/* ============================================================
   Steph Ferrera — Layer 0
   Design system: three forces (intelligence / value / life)
   ============================================================ */

:root{
  --bg:#06070A;
  --bg-2:#0A0C12;
  --surface:#0E1118;
  --line:rgba(255,255,255,.09);
  --line-2:rgba(255,255,255,.16);

  --ink:#ECEBF2;
  --ink-soft:#9C9CB0;
  --ink-dim:#6C6C80;

  --violet:#8B7CF8;   /* intelligence */
  --gold:#E3B778;     /* value        */
  --teal:#45D6C0;     /* life         */

  --display: ui-serif, "New York", "Iowan Old Style", Palatino, Georgia, serif;
  --sans: ui-sans-serif, -apple-system, "SF Pro Text", Inter, system-ui, "Segoe UI", sans-serif;
  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;

  --pad: clamp(1.25rem, 5vw, 6rem);
  --maxw: 1240px;
  --ease: cubic-bezier(.22,.68,0,1);
  --slow: 1.05s var(--ease);
}

*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
@media (prefers-reduced-motion:reduce){ html{ scroll-behavior:auto; } }

body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font-family:var(--sans);
  font-size:clamp(1rem,.96rem + .2vw,1.075rem);
  line-height:1.62;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

img{ max-width:100%; height:auto; display:block; }
a{ color:inherit; }

h1,h2,h3{ font-family:var(--display); font-weight:500; line-height:1.05; letter-spacing:-.02em; margin:0; }
h1{ font-size:clamp(3rem,10.5vw,7.5rem); letter-spacing:-.035em; }
h2{ font-size:clamp(2rem,5.2vw,3.9rem); }
h3{ font-size:clamp(1.25rem,2.2vw,1.6rem); letter-spacing:-.015em; }

p{ margin:0 0 1.1em; }
p:last-child{ margin-bottom:0; }

.eyebrow{
  font-family:var(--mono);
  font-size:.685rem;
  letter-spacing:.19em;
  text-transform:uppercase;
  color:var(--ink-dim);
  margin:0 0 1.1rem;
}
.sr,.skip{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
.skip:focus{ position:fixed; top:.75rem; left:.75rem; width:auto; height:auto; clip:auto; z-index:200;
  background:var(--ink); color:var(--bg); padding:.6rem 1rem; border-radius:.5rem; }

/* ── reveals ─────────────────────────────────────────────── */
.reveal{ opacity:0; transform:translateY(22px); transition:opacity var(--slow), transform var(--slow); }
.reveal.in{ opacity:1; transform:none; }
.d1{ transition-delay:.09s } .d2{ transition-delay:.18s } .d3{ transition-delay:.27s }
.d4{ transition-delay:.36s } .d5{ transition-delay:.45s }
@media (prefers-reduced-motion:reduce){
  .reveal{ opacity:1; transform:none; transition:none; }
}

/* ── buttons ─────────────────────────────────────────────── */
.btn{
  --b:var(--ink);
  display:inline-flex; align-items:center; justify-content:center;
  min-height:48px; padding:.85rem 1.6rem;
  border-radius:100px; border:1px solid var(--line-2);
  font-size:.925rem; font-weight:500; letter-spacing:.005em;
  text-decoration:none; cursor:pointer; background:transparent; color:var(--ink);
  font-family:var(--sans);
  transition:transform .45s var(--ease), background .45s var(--ease), border-color .45s var(--ease), color .45s var(--ease);
}
.btn.primary{ background:var(--ink); color:#08080C; border-color:var(--ink); }
.btn:hover{ transform:translateY(-2px); }
.btn.primary:hover{ background:#fff; border-color:#fff; }
.btn.ghost:hover{ border-color:var(--ink); background:rgba(255,255,255,.05); }
.btn:focus-visible,a:focus-visible,button:focus-visible,input:focus-visible{
  outline:2px solid var(--teal); outline-offset:3px;
}

/* ── nav ─────────────────────────────────────────────────── */
.nav{
  position:fixed; inset:0 0 auto 0; z-index:100;
  display:flex; align-items:center; gap:1.5rem;
  padding:.85rem var(--pad);
  padding-top:max(.85rem, env(safe-area-inset-top));
  background:rgba(6,7,10,.66);
  backdrop-filter:blur(18px) saturate(150%);
  -webkit-backdrop-filter:blur(18px) saturate(150%);
  border-bottom:1px solid transparent;
  transform:translateY(-100%);
  transition:transform .7s var(--ease), border-color .7s var(--ease);
}
.nav.show{ transform:none; border-bottom-color:var(--line); }
.mark{ display:flex; align-items:center; gap:.6rem; text-decoration:none; font-size:.9rem; font-weight:500; letter-spacing:-.01em; margin-right:auto; }
.mark svg{ width:26px; height:26px; fill:none; stroke:var(--gold); stroke-width:1.5; opacity:.95; }
.nav-links{ display:none; gap:1.75rem; font-size:.85rem; color:var(--ink-soft); }
.nav-links a{ text-decoration:none; transition:color .3s var(--ease); }
.nav-links a:hover{ color:var(--ink); }
.nav-right{ display:flex; align-items:center; gap:.6rem; }
.lang{
  font-family:var(--mono); font-size:.7rem; letter-spacing:.1em;
  background:transparent; border:1px solid var(--line-2); color:var(--ink-soft);
  border-radius:100px; padding:.4rem .6rem; cursor:pointer; min-height:34px;
  display:flex; gap:.35rem; transition:border-color .3s var(--ease);
}
.lang .on{ color:var(--ink); } .lang .off{ color:var(--ink-dim); }
.lang:hover{ border-color:var(--ink-soft); }
.pill{
  display:none; text-decoration:none; font-size:.85rem;
  border:1px solid var(--line-2); border-radius:100px; padding:.5rem 1.1rem; min-height:36px;
  align-items:center; transition:border-color .3s var(--ease), background .3s var(--ease);
}
.pill:hover{ border-color:var(--ink); background:rgba(255,255,255,.05); }
@media (min-width:900px){ .nav-links{ display:flex; } .pill{ display:inline-flex; } }

/* ── the menu a phone actually gets ──────────────────────────
   Hidden with visibility, not just opacity, so its links stay out of the tab
   order while it is closed. */
.nav-toggle{
  display:grid; place-content:center; gap:5px;
  width:40px; height:40px; padding:0; cursor:pointer;
  background:transparent; border:1px solid var(--line-2); border-radius:12px;
}
.nt-bar{
  display:block; width:16px; height:1.5px; background:var(--ink); border-radius:2px;
  transition:transform .32s var(--ease), opacity .2s var(--ease);
}
.nav-toggle[aria-expanded="true"] .nt-bar:first-child{ transform:translateY(3.25px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nt-bar:last-child{ transform:translateY(-3.25px) rotate(-45deg); }
@media (min-width:900px){ .nav-toggle{ display:none; } }

.nav-panel{
  position:absolute; top:100%; left:0; right:0;
  /* opaque, and blurred like the bar above it: at .97 the big serif behind
     still read through the panel. */
  background:#090B11; border-bottom:1px solid var(--line);
  backdrop-filter:blur(18px) saturate(150%);
  -webkit-backdrop-filter:blur(18px) saturate(150%);
  box-shadow:0 18px 40px rgba(0,0,0,.5);
  padding:1rem var(--pad) 1.4rem;
  display:flex; flex-direction:column; gap:.2rem;
  opacity:0; visibility:hidden; transform:translateY(-8px);
  transition:opacity .3s var(--ease), transform .3s var(--ease), visibility .3s;
}
.nav-panel.open{ opacity:1; visibility:visible; transform:translateY(0); }
.nav-panel nav{ display:flex; flex-direction:column; }
.nav-panel a{
  color:var(--ink-soft); text-decoration:none; font-size:1rem;
  padding:.8rem 0; border-bottom:1px solid var(--line);
}
.nav-panel a:last-of-type{ border-bottom:0; }
.nav-panel .np-cta{ margin-top:1rem; width:100%; color:#08080C; border-bottom:0; }
@media (min-width:900px){ .nav-panel{ display:none; } }

/* ── hero ────────────────────────────────────────────────── */
/* ── hero: one square millimetre ──────────────────────────────
   Her work occupies about a square millimetre of the lunar surface. So the
   page opens at that scale — a speck in the middle of the black — and pulls
   back until you can see what the speck is: the picture that is up there.

   Mechanically it is a clip window opening while the image itself un-zooms,
   which reads as backing away from a microscope rather than as a fade. Both
   properties are composited, so it stays at 60fps on a phone. */
.hero{
  position:relative; min-height:100svh;
  display:flex; align-items:flex-end;
  padding:7rem var(--pad) 5rem;
  padding-bottom:max(5rem, env(safe-area-inset-bottom));
  overflow:hidden;
}
.hero-frame{
  position:absolute; inset:0; z-index:0; overflow:hidden;
  clip-path:inset(calc(50% - 5px) calc(50% - 5px) round 1px);
  animation:speck-open 5.4s var(--ease) .35s forwards;
}
.hero-frame img{
  width:100%; height:100%; object-fit:cover; object-position:52% 44%;
  transform:scale(2.6); transform-origin:52% 44%;
  animation:speck-pull 5.4s var(--ease) .35s forwards;
}
@keyframes speck-open{
  0%{ clip-path:inset(calc(50% - 5px) calc(50% - 5px) round 1px); }
  100%{ clip-path:inset(0% 0% round 0px); }
}
@keyframes speck-pull{
  0%{ transform:scale(2.6); } 100%{ transform:scale(1); }
}

/* The measure counts up alongside the opening. It is the same argument the
   site closes on — a millimetre up there, a metre down here. */
.hero-measure{
  position:absolute; z-index:3; top:calc(50% - .7rem); left:0; right:0; margin:0;
  text-align:center; pointer-events:none;
  font-family:var(--mono); font-size:.68rem; letter-spacing:.3em; text-transform:uppercase;
  color:var(--gold); text-shadow:0 2px 20px rgba(0,0,0,.9);
  animation:measure-out 6.6s var(--ease) forwards;
}
@keyframes measure-out{
  0%{ opacity:0 } 8%{ opacity:1 } 74%{ opacity:1 }
  100%{ opacity:0; transform:translateY(-8px) }
}

.hero::after{
  content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:
    radial-gradient(105% 80% at 50% 42%, transparent 22%, rgba(6,7,10,.62) 72%),
    linear-gradient(to bottom, rgba(6,7,10,.86) 0%, rgba(6,7,10,.30) 26%, rgba(6,7,10,.62) 62%, var(--bg) 100%);
}
.hero-in{ position:relative; z-index:2; max-width:var(--maxw); margin-inline:auto; width:100%; }
.hero .lede{
  font-family:var(--display); font-size:clamp(1.45rem,4.2vw,2.6rem);
  line-height:1.18; letter-spacing:-.02em; max-width:18ch; margin:1.4rem 0 0;
  background:linear-gradient(96deg,var(--ink) 25%,var(--gold) 62%,var(--teal) 96%);
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
.hero .sub{ color:var(--ink-soft); max-width:46ch; margin-top:1.5rem; font-size:1.03rem; text-shadow:0 1px 18px rgba(0,0,0,.7); }
.hero h1{ text-shadow:0 4px 40px rgba(0,0,0,.55); }
.doors{ display:flex; flex-wrap:wrap; gap:.75rem; margin-top:2.4rem; }
.scroll-cue{ position:absolute; left:50%; bottom:2rem; z-index:2; translate:-50% 0; width:1px; height:56px; background:linear-gradient(var(--line-2),transparent); overflow:hidden; }
.scroll-cue span{ position:absolute; inset:0 auto auto 0; width:1px; height:18px; background:var(--gold); animation:cue 2.6s var(--ease) infinite; }
@keyframes cue{ 0%{ transform:translateY(-20px); opacity:0 } 35%{ opacity:1 } 100%{ transform:translateY(56px); opacity:0 } }

/* Reduced motion gets the destination, not the journey — the picture, open. */
@media (prefers-reduced-motion:reduce){
  .hero-frame{ animation:none; clip-path:inset(0); }
  .hero-frame img{ animation:none; transform:none; }
  .hero-measure{ animation:none; opacity:0; }
  .scroll-cue span{ animation:none; }
}

/* ── thesis ──────────────────────────────────────────────── */
.thesis{ position:relative; min-height:88svh; display:grid; place-items:center; padding:6rem var(--pad); overflow:hidden; }
.thesis .bleed{ position:absolute; inset:0; z-index:0; }
/* The film sits BEHIND the sentence, never beside it. Held at .46 and slightly
   desaturated it reads as the room the words are spoken in — which is also why
   the source resolution stops mattering: nothing here is asked to be a photo. */
.thesis .bleed-film,
.thesis .bleed-still{
  width:100%; height:100%; object-fit:cover; object-position:50% 42%;
  opacity:.46; filter:saturate(.86) contrast(1.04);
}
.thesis .bleed-still{ display:none; }
.thesis::after{
  content:""; position:absolute; inset:0; z-index:1;
  background:
    radial-gradient(120% 78% at 50% 46%, rgba(6,7,10,.30), rgba(6,7,10,.86) 78%),
    linear-gradient(to bottom, var(--bg), rgba(6,7,10,.52) 26%, rgba(6,7,10,.62) 72%, var(--bg));
}
@media (prefers-reduced-motion: reduce){
  .thesis .bleed-film{ display:none; }
  .thesis .bleed-still{ display:block; }
}
/* The measure and the size are a pair: 19ch at 5rem only survives a very short
   sentence, and a longer one sets a word per line and walks off the screen.
   A wider measure and a gentler cap make the block tolerate the copy changing
   without anyone having to re-tune it. */
/* ⚠️ The measure belongs on the <p>, not on the <blockquote>.
   `ch` resolves against the element's OWN font, and the blockquote inherits
   the 17px body sans while the quote is drawn at up to 4.2rem in the serif.
   A `max-width` in ch on the blockquote is therefore about 190px wide, which
   is what set the sentence one word per line and broke words in half. */
.thesis blockquote{
  position:relative; z-index:2; margin:0; text-align:center;
  max-width:min(1040px, 92vw);
}
.thesis blockquote p{
  font-family:var(--display); font-size:clamp(1.85rem,5.2vw,3.9rem);
  line-height:1.07; letter-spacing:-.032em; margin:0 auto;
  max-width:17ch;                 /* in the serif, at its own size: correct */
  text-wrap:balance; hyphens:none;
}
.thesis footer{ margin-top:1.8rem; color:var(--ink-soft); font-size:.98rem; max-width:42ch; margin-inline:auto; text-wrap:pretty; }

/* ── proof ───────────────────────────────────────────────── */
.proof{ padding:4.5rem var(--pad); border-block:1px solid var(--line); background:var(--bg-2); }
.proof ul{ list-style:none; margin:0 auto; padding:0; max-width:var(--maxw);
  display:grid; gap:2rem 2.5rem; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); }
.proof li{ display:flex; flex-direction:column; gap:.35rem; }
.proof b{ font-family:var(--display); font-size:1.28rem; font-weight:500; letter-spacing:-.015em; }
.proof span{ font-family:var(--mono); font-size:.7rem; letter-spacing:.11em; text-transform:uppercase; color:var(--ink-dim); line-height:1.5; }

/* ── shared section head ─────────────────────────────────── */
.head{ max-width:var(--maxw); margin:0 auto 3.5rem; }
.head h2{ max-width:16ch; text-wrap:balance; }
.head .intro{ color:var(--ink-soft); max-width:52ch; margin-top:1.3rem; }

/* ── the arc ─────────────────────────────────────────────── */
.arc{ padding:7rem var(--pad); }
/* ── the arc: six magnitudes ──────────────────────────────────
   The whole section is one idea — a life that scales outward from a body to a
   layer under everything — so the design has to be that idea, not a decoration
   next to it. Hence the rail: a measure you climb, not a list you read.

   The films sit far back on purpose. The archive footage is 960 px, twice
   re-encoded; shown large it looks like a bad photograph, held at .28 behind a
   scrim and a headline it reads as the room the sentence is spoken in.
   The one true 1080 shot (the Red Tent) is allowed to come forward. */
.arc{ padding:7rem var(--pad) 0; position:relative; }
.rail{ list-style:none; margin:0; padding:0; }

/* ── the scale rail ── */
.scale-rail{ display:none; }
@media (min-width:1080px){
  .scale-rail{
    display:block; position:sticky; top:50vh; z-index:5;
    height:0; max-width:var(--maxw); margin:0 auto;
    pointer-events:none;
  }
  .scale-rail ol{
    list-style:none; margin:0; padding:0;
    position:absolute; left:0; translate:0 -50%;
    display:grid; gap:.95rem;
  }
  .scale-rail li{
    display:flex; align-items:center; gap:.7rem;
    font-family:var(--mono); font-size:.66rem; letter-spacing:.15em; text-transform:uppercase;
    color:var(--ink-dim); opacity:.42;
    transition:opacity .6s var(--ease), color .6s var(--ease), transform .6s var(--ease);
  }
  .scale-rail .dot{
    width:7px; height:7px; border-radius:50%; flex:none;
    border:1px solid currentColor; background:transparent;
    transition:background .6s var(--ease), box-shadow .6s var(--ease), scale .6s var(--ease);
  }
  .scale-rail li.on{ opacity:1; color:var(--gold); transform:translateX(4px); }
  .scale-rail li.on .dot{ background:var(--gold); scale:1.35; box-shadow:0 0 0 5px rgba(227,183,120,.14); }
  .scale-rail li.past{ opacity:.7; color:var(--ink-soft); }
  .scale-rail li.past .dot{ background:var(--ink-dim); }
}

/* ── a chapter ── */
.chapter{
  position:relative; isolation:isolate;
  display:grid; align-items:end;
  min-height:82svh;
  padding:clamp(3.5rem,11vh,8rem) var(--pad);
  margin-inline:calc(var(--pad) * -1);
  border-top:1px solid var(--line);
}
.chapter:last-child{ border-bottom:1px solid var(--line); }

.chapter-bg{ position:absolute; inset:0; z-index:-2; overflow:hidden; background:var(--bg-2); }
.chapter-bg .film,
.chapter-bg .film-still{
  width:100%; height:100%; object-fit:cover; object-position:50% 42%;
  opacity:.28; filter:saturate(.78) contrast(1.06);
  transition:opacity 1.2s var(--ease), transform 1.8s var(--ease);
  transform:scale(1.05);
}
.chapter-bg .film-still{ display:none; }
.chapter-bg .film.playing{ opacity:.40; transform:scale(1); }
.chapter-bg .film[data-failed]{ opacity:.28; }

/* The Red Tent is a real 1080 photograph and the only image on the page that
   has earned the right to be looked at directly. */
.chapter.has-shot .chapter-bg .film-still{ display:block; opacity:.50; transform:scale(1.02); }
.chapter.has-shot.in .chapter-bg .film-still{ opacity:.62; transform:scale(1); }

.chapter::after{
  content:""; position:absolute; inset:0; z-index:-1;
  background:linear-gradient(to top, rgba(6,7,10,.95) 0%, rgba(6,7,10,.74) 40%, rgba(6,7,10,.42) 74%, rgba(6,7,10,.58) 100%);
}
/* No footage is not a hole — it is a page of type. */
.chapter:not(.has-film):not(.has-shot)::after{
  background:
    radial-gradient(85% 65% at 8% 100%, rgba(227,183,120,.09), transparent 62%),
    radial-gradient(70% 60% at 92% 0%, rgba(139,124,248,.08), transparent 60%),
    linear-gradient(to top, rgba(6,7,10,.93), rgba(6,7,10,.88));
}

.chapter-type{ position:relative; max-width:46ch; }
.chapter .scale{
  display:flex; align-items:baseline; gap:.7rem; margin:0 0 1.5rem;
  font-family:var(--mono); font-size:.67rem; letter-spacing:.2em; text-transform:uppercase;
  color:var(--ink-dim);
}
.chapter .scale .n{
  font-size:.9rem; letter-spacing:.06em; color:var(--gold);
  border-bottom:1px solid rgba(227,183,120,.42); padding-bottom:.15rem;
}
.chapter .yr{
  display:block; font-family:var(--mono); font-size:.72rem; letter-spacing:.17em;
  text-transform:uppercase; color:var(--ink-soft); margin-bottom:.9rem;
}
.chapter h3{
  font-size:clamp(2.15rem,6.6vw,4rem); line-height:1.02; letter-spacing:-.033em;
  margin-bottom:1.3rem; text-wrap:balance;
}
.chapter p{ color:var(--ink-soft); font-size:clamp(1.02rem,1.9vw,1.14rem); line-height:1.66; text-wrap:pretty; }
.chapter p i{ color:var(--ink); font-style:italic; }
.chapter p b{ color:var(--ink); font-weight:500; }

/* The line that lands a chapter. It gets to be a voice, not a caption. */
.chapter .turn{
  margin-top:1.9rem; padding-top:1.5rem; border-top:1px solid rgba(227,183,120,.28);
  font-family:var(--display); font-size:clamp(1.3rem,3vw,1.85rem); line-height:1.24;
  letter-spacing:-.02em; color:var(--ink); max-width:28ch; text-wrap:balance;
}
/* 2035 is the only promise on the page. It is allowed to be the largest thing
   in its chapter — a vision stated small reads as a hedge. */
.chapter .turn.big{
  font-size:clamp(1.8rem,4.6vw,3rem); line-height:1.12; max-width:20ch;
  color:var(--gold); border-top-color:rgba(227,183,120,.5);
}
.chapter.is-vision::after{
  background:
    radial-gradient(70% 60% at 78% 22%, rgba(227,183,120,.16), transparent 62%),
    radial-gradient(90% 70% at 8% 100%, rgba(139,124,248,.12), transparent 60%),
    linear-gradient(to top, rgba(6,7,10,.93), rgba(6,7,10,.87)) !important;
}
/* Second and third paragraphs sit quieter than the first — a chapter should
   read as one voice getting more specific, not three equal blocks. */
.chapter-type > p + p:not(.turn){ margin-top:1.15rem; color:var(--ink-dim); }

@media (min-width:900px){
  .chapter{ min-height:90svh; align-items:center; }
  .chapter-type{ max-width:50ch; }
  .chapter:nth-child(even) .chapter-type{ margin-left:auto; }
  .chapter::after{
    background:linear-gradient(to right, rgba(6,7,10,.94) 0%, rgba(6,7,10,.76) 48%, rgba(6,7,10,.42) 100%);
  }
  .chapter:nth-child(even)::after{
    background:linear-gradient(to left, rgba(6,7,10,.94) 0%, rgba(6,7,10,.76) 48%, rgba(6,7,10,.42) 100%);
  }
}
@media (min-width:1080px){
  /* leave the rail its gutter */
  .chapter-type{ margin-left:13.5rem; }
  .chapter:nth-child(even) .chapter-type{ margin-left:auto; margin-right:0; }
}

@media (prefers-reduced-motion: reduce){
  .chapter-bg .film{ display:none; }
  .chapter-bg .film-still{ display:block; }
}

/* ── the moon ────────────────────────────────────────────── */
.moon{
  padding:7rem var(--pad); background:
    radial-gradient(90% 60% at 82% 6%, rgba(139,124,248,.13), transparent 62%), var(--bg-2);
  border-block:1px solid var(--line);
  display:grid; gap:3.5rem; max-width:100%;
}
.moon-copy{ max-width:56ch; }
.moon-copy h2{ max-width:14ch; margin-bottom:1.6rem; text-wrap:balance; }
.moon-copy p{ color:var(--ink-soft); }
.moon-copy i{ color:var(--ink); font-style:italic; }
/* Portrait source (960×1460). Framed to 4/5 and biased upward so Steph —
   centre of frame, above the man holding the dog — is never the part that
   gets cropped away. */
.moon-shot img{
  width:100%; border-radius:14px; border:1px solid var(--line);
  aspect-ratio:4/5; object-fit:cover; object-position:48% 32%;
}
.moon-shot figcaption{ font-family:var(--mono); font-size:.68rem; letter-spacing:.13em; text-transform:uppercase; color:var(--ink-dim); margin-top:.9rem; }
.moon-shot{ margin:0; }
@media (min-width:940px){
  .moon{ grid-template-columns:1fr 1fr; align-items:center; gap:5rem;
         padding-inline:var(--pad); }
  .moon-copy,.moon-shot{ max-width:none; }
  .moon > *{ min-width:0; }
}

/* ── the system ──────────────────────────────────────────── */
.system{ padding:7rem var(--pad); }
.forces{ max-width:var(--maxw); margin-inline:auto; display:grid; gap:1.25rem; }
.force{
  position:relative; padding:2.4rem 2rem 2.2rem;
  border:1px solid var(--line); border-radius:16px; background:var(--surface);
  overflow:hidden; transition:border-color .55s var(--ease), transform .55s var(--ease);
}
.force::before{
  content:""; position:absolute; inset:0 0 auto 0; height:2px;
  background:linear-gradient(90deg, var(--c), transparent 78%);
  opacity:.85;
}
.force::after{
  content:""; position:absolute; z-index:0; width:220px; height:220px; right:-90px; top:-90px;
  border-radius:50%; background:var(--c); filter:blur(70px); opacity:.14;
  transition:opacity .6s var(--ease);
}
.force:hover{ border-color:var(--line-2); transform:translateY(-3px); }
.force:hover::after{ opacity:.24; }
.force > *{ position:relative; z-index:1; }
.f-int{ --c:var(--violet) } .f-val{ --c:var(--gold) } .f-life{ --c:var(--teal) }
.force .n{ font-family:var(--mono); font-size:.7rem; letter-spacing:.16em; color:var(--c); }
.force h3{ margin:.9rem 0 .3rem; }
.force .k{ font-family:var(--mono); font-size:.7rem; letter-spacing:.11em; text-transform:uppercase; color:var(--ink-dim); margin-bottom:1.1rem; }
.force p:last-child{ color:var(--ink-soft); font-size:.95rem; }
@media (min-width:860px){ .forces{ grid-template-columns:repeat(3,1fr); gap:1.5rem; } }
.system .closing{
  max-width:var(--maxw); margin:3.5rem auto 0; font-family:var(--display);
  font-size:clamp(1.2rem,2.6vw,1.75rem); line-height:1.35; letter-spacing:-.018em;
  color:var(--ink); max-width:30ch; text-wrap:balance;
}

/* ── the work ────────────────────────────────────────────── */
.work{ padding:7rem var(--pad); background:var(--bg-2); border-block:1px solid var(--line); }
.grid{ list-style:none; margin:0 auto; padding:0; max-width:var(--maxw);
  display:grid; gap:1px; background:var(--line); border:1px solid var(--line); border-radius:14px; overflow:hidden;
  grid-template-columns:repeat(auto-fill,minmax(min(100%,255px),1fr)); }
.tile{ background:var(--bg-2); padding:1.6rem 1.4rem; display:flex; flex-direction:column; gap:.5rem;
  text-decoration:none; min-height:150px; position:relative;
  transition:background .45s var(--ease); }
.tile:hover{ background:var(--surface); }
.tile .t{ font-family:var(--display); font-size:1.18rem; letter-spacing:-.015em; }
.tile .d{ color:var(--ink-soft); font-size:.875rem; line-height:1.5; }
.tile .s{ margin-top:auto; font-family:var(--mono); font-size:.63rem; letter-spacing:.14em; text-transform:uppercase;
  display:inline-flex; align-items:center; gap:.45rem; color:var(--ink-dim); }
.tile .s::before{ content:""; width:5px; height:5px; border-radius:50%; background:var(--teal); box-shadow:0 0 0 3px rgba(69,214,192,.16); }
.tile.soon .s::before{ background:var(--gold); box-shadow:0 0 0 3px rgba(227,183,120,.14); }
.tile[href]::after{ content:"↗"; position:absolute; top:1.4rem; right:1.3rem; color:var(--ink-dim); font-size:.85rem;
  opacity:0; transform:translate(-3px,3px); transition:all .45s var(--ease); }
.tile[href]:hover::after{ opacity:1; transform:none; }
.grid-note{ max-width:var(--maxw); margin:1.6rem auto 0; color:var(--ink-dim); font-size:.85rem; }

/* ── doors ───────────────────────────────────────────────── */
.doors-sec{ padding:7rem var(--pad); max-width:var(--maxw); margin-inline:auto; display:grid; gap:1.5rem; }
.door{ padding:2.8rem 2.2rem; border:1px solid var(--line); border-radius:18px; background:var(--surface); }
.door h2{ font-size:clamp(1.7rem,3.4vw,2.5rem); margin-bottom:1.1rem; }
.door p{ color:var(--ink-soft); margin-bottom:1.9rem; }
@media (min-width:860px){ .doors-sec{ grid-template-columns:1fr 1fr; gap:1.75rem; } }

/* ── vault ───────────────────────────────────────────────── */
.vault{ position:fixed; inset:0; z-index:150; display:grid; place-items:center; padding:1.25rem;
  background:rgba(4,5,8,.82); backdrop-filter:blur(12px); -webkit-backdrop-filter:blur(12px); }
.vault[hidden]{ display:none; }
.vault-panel{ position:relative; width:min(560px,100%); max-height:88svh; overflow-y:auto;
  background:var(--surface); border:1px solid var(--line-2); border-radius:18px; padding:2.6rem 2rem 2.2rem; }
.vault-x{ position:absolute; top:.9rem; right:1rem; background:transparent; border:0; color:var(--ink-soft);
  font-size:1.7rem; line-height:1; cursor:pointer; width:44px; height:44px; }
.vault-lede{ color:var(--ink-soft); font-size:.95rem; margin-bottom:1.6rem; }
#vault-form{ display:flex; gap:.6rem; flex-wrap:wrap; }
#vault-code{ flex:1 1 210px; min-height:48px; padding:.8rem 1.1rem; border-radius:100px;
  background:var(--bg); border:1px solid var(--line-2); color:var(--ink);
  font-family:var(--mono); font-size:.9rem; letter-spacing:.12em; }
#vault-code::placeholder{ color:var(--ink-dim); }
.vault-msg{ margin:1rem 0 0; font-size:.88rem; color:var(--gold); min-height:1.2em; }
.vault-out{ margin-top:1.8rem; border-top:1px solid var(--line); padding-top:1.4rem; }
.vault-out table{ width:100%; border-collapse:collapse; font-size:.9rem; }
.vault-out th{ text-align:left; font-family:var(--mono); font-size:.63rem; letter-spacing:.13em;
  text-transform:uppercase; color:var(--ink-dim); font-weight:400; padding-bottom:.7rem; }
.vault-out td{ padding:.6rem 0; border-top:1px solid var(--line); vertical-align:top; }
.vault-out td.r{ text-align:right; font-family:var(--mono); font-size:.85rem; }
.vault-out .sub{ display:block; color:var(--ink-dim); font-size:.78rem; }
.vault-out .vault-note{ margin-top:1rem; color:var(--ink-dim); font-size:.78rem; line-height:1.5; }
.vault-out .badge{ font-family:var(--mono); font-size:.55rem; letter-spacing:.1em; text-transform:uppercase;
  border:1px solid var(--line-2); border-radius:100px; padding:.12rem .45rem; color:var(--ink-dim); margin-left:.5rem; }

/* ── contact ─────────────────────────────────────────────── */
.contact{ padding:7rem var(--pad); display:grid; gap:3rem; max-width:var(--maxw); margin-inline:auto; align-items:center; }
.portrait{ margin:0; }
.portrait img{ width:100%; max-width:380px; border-radius:16px; border:1px solid var(--line); filter:grayscale(1) contrast(1.06); }
.contact-copy h2{ max-width:14ch; margin-bottom:1.3rem; text-wrap:balance; }
.contact-copy > p{ color:var(--ink-soft); max-width:44ch; }
.contact-links{ display:flex; flex-wrap:wrap; gap:.7rem; margin-top:2.2rem; }
@media (min-width:860px){ .contact{ grid-template-columns:380px 1fr; gap:4.5rem; } }

/* ── footer ──────────────────────────────────────────────── */
.foot{ padding:3rem var(--pad); padding-bottom:max(3rem, env(safe-area-inset-bottom));
  border-top:1px solid var(--line); display:flex; flex-wrap:wrap; gap:.6rem 2rem; justify-content:space-between;
  color:var(--ink-dim); font-size:.83rem; }
.foot p{ margin:0; }
.foot .credo{ font-family:var(--display); font-style:italic; color:var(--ink-soft); }


/* ── the vision ──────────────────────────────────────────────
   The only promise on the site. It gets a section to itself and the largest
   type on the page after the name — a vision stated small reads as a hedge. */
.vision{
  padding:8rem var(--pad); border-block:1px solid var(--line);
  background:
    radial-gradient(80% 60% at 74% 12%, rgba(227,183,120,.13), transparent 62%),
    radial-gradient(70% 60% at 10% 96%, rgba(139,124,248,.10), transparent 60%),
    var(--bg-2);
}
.vision-in{ max-width:var(--maxw); margin-inline:auto; }
.vision h2{
  font-size:clamp(2.4rem,7.6vw,5.4rem); line-height:1.0; letter-spacing:-.038em;
  max-width:13ch; margin-bottom:2.2rem; text-wrap:balance;
}
.vision p{ color:var(--ink-soft); max-width:56ch; font-size:clamp(1.02rem,1.9vw,1.14rem); line-height:1.66; }
.vision p b{ color:var(--gold); font-weight:500; }
.vision .vision-close{
  margin-top:2.4rem; padding-top:1.8rem; border-top:1px solid rgba(227,183,120,.3);
  font-family:var(--display); font-size:clamp(1.35rem,3.2vw,2.1rem); line-height:1.26;
  letter-spacing:-.022em; color:var(--ink); max-width:30ch; text-wrap:balance;
}

/* ── the story, in one breath ─────────────────────────────────
   Ten lines is the whole life. If someone reads only this, they still get the
   shape — and the shape is the argument. */
.story-teaser{ padding:7rem var(--pad); }
.story-teaser .head{ margin-bottom:2.6rem; }
.beats{
  list-style:none; margin:0 auto; padding:0; max-width:var(--maxw);
  counter-reset:beat; display:grid; gap:0;
}
.beats li{
  counter-increment:beat;
  display:grid; grid-template-columns:3.2rem 1fr; align-items:baseline; gap:1rem;
  padding:1.05rem 0; border-top:1px solid var(--line);
}
.beats li:last-child{ border-bottom:1px solid var(--line); }
.beats li::before{
  content:counter(beat,decimal-leading-zero);
  font-family:var(--mono); font-size:.72rem; letter-spacing:.12em; color:var(--gold);
}
.beats li span{ font-family:var(--display); font-size:clamp(1.15rem,2.6vw,1.6rem); letter-spacing:-.018em; }
.beats li:last-child span{ color:var(--gold); }
.story-cta{ max-width:var(--maxw); margin:2.6rem auto 0; }

/* ── the story page ── */
.story-head{ padding:9rem var(--pad) 4rem; max-width:var(--maxw); margin-inline:auto; }
.story-head h1{ font-size:clamp(2.4rem,7vw,4.6rem); letter-spacing:-.035em; max-width:16ch; margin-bottom:1.6rem; text-wrap:balance; }
.story-head .lede-sm{ color:var(--ink-soft); max-width:54ch; font-size:clamp(1.02rem,1.9vw,1.14rem); }
.story-head .back{ margin-top:2.2rem; font-family:var(--mono); font-size:.72rem; letter-spacing:.13em; text-transform:uppercase; }
.story-head .back a{ color:var(--ink-dim); text-decoration:none; transition:color .3s var(--ease); }
.story-head .back a:hover{ color:var(--ink); }


/* ── 404 ─────────────────────────────────────────────────────
   Small on purpose. Its job is to return the right status code; looking
   composed while doing it is a bonus. */
.nf{ min-height:100svh; display:grid; align-content:center; gap:1.1rem; padding:6rem var(--pad); max-width:var(--maxw); margin-inline:auto; }
.nf h1{ font-size:clamp(2.2rem,7vw,4.4rem); letter-spacing:-.035em; max-width:14ch; }
.nf-sub{ color:var(--ink-soft); max-width:42ch; }
.nf-links{ display:flex; flex-wrap:wrap; gap:.75rem; margin-top:1.4rem; }

/* ── the profile ─────────────────────────────────────────────
   Sits between the projects and the story: by now you know what she builds,
   so this answers "who" — and hands you off to the long version. */
.profile{ padding:7rem var(--pad); border-block:1px solid var(--line); background:var(--bg-2); }
.profile-in{ max-width:var(--maxw); margin-inline:auto; display:grid; gap:2.6rem; }
.profile-shot{ margin:0; max-width:320px; }
.profile-shot img{ width:100%; border-radius:14px; border:1px solid var(--line); filter:grayscale(1) contrast(1.05); }
.profile-copy h2{ font-size:clamp(2rem,5vw,3.2rem); letter-spacing:-.03em; margin-bottom:1.4rem; }
.profile-copy p{ color:var(--ink-soft); max-width:56ch; }
.profile-copy p b{ color:var(--ink); font-weight:500; }
.profile-copy p + p{ margin-top:1.1rem; }
.profile-cta{ margin-top:1.9rem; }
@media (min-width:860px){
  .profile-in{ grid-template-columns:320px 1fr; gap:4rem; align-items:start; }
}

/* ── how it travels ──────────────────────────────────────────
   The technical section. It earns its place by being specific: engraved
   nickel, not "blockchain-enabled". Four cards so nothing has to be a wall. */
.soon{ padding:7rem var(--pad); border-block:1px solid var(--line); }
.soon-in{ max-width:var(--maxw); margin-inline:auto; }
.soon h2{ font-size:clamp(1.9rem,4.6vw,3rem); letter-spacing:-.032em; max-width:20ch; margin-bottom:3rem; text-wrap:balance; }
.soon-grid{ display:grid; gap:1.1rem; }
.soon article{
  padding:2rem 1.8rem; border:1px solid var(--line); border-radius:16px;
  background:var(--surface); position:relative; overflow:hidden;
}
.soon article h3{ font-size:1.22rem; margin-bottom:.85rem; letter-spacing:-.018em; }
.soon article p{ color:var(--ink-soft); font-size:.965rem; }
.soon article p b{ color:var(--ink); font-weight:500; }
.soon .soon-open{ border-color:rgba(227,183,120,.34); }
.soon .soon-open h3{ color:var(--gold); }
.soon .soon-open::after{
  content:""; position:absolute; right:-70px; top:-70px; width:190px; height:190px;
  border-radius:50%; background:var(--gold); filter:blur(66px); opacity:.15;
}
.soon .soon-note{
  margin-top:1rem; font-family:var(--mono); font-size:.68rem; letter-spacing:.06em;
  color:var(--ink-dim); line-height:1.6;
}
@media (min-width:820px){ .soon-grid{ grid-template-columns:repeat(2,1fr); gap:1.25rem; } }

/* ── missions ────────────────────────────────────────────────
   Three states, and the state is the point: one landed, one manifested, one
   still being booked. A reader who invests should be able to tell them apart
   at a glance — which is why the status line comes before the title. */
.soon-lede{ color:var(--ink-soft); max-width:52ch; margin:-1.6rem 0 3rem; font-size:clamp(1.02rem,1.9vw,1.14rem); }
.missions{ list-style:none; margin:0 0 3.2rem; padding:0; display:grid; gap:0; counter-reset:m; }
.missions li{ padding:1.9rem 0 1.9rem 1.6rem; border-top:1px solid var(--line); position:relative; }
.missions li:last-child{ border-bottom:1px solid var(--line); }
.missions li::before{
  content:""; position:absolute; left:0; top:2.45rem;
  width:8px; height:8px; border-radius:50%; border:1px solid var(--ink-dim);
}
.missions .m-done::before{ background:var(--teal); border-color:var(--teal); box-shadow:0 0 0 5px rgba(69,214,192,.14); }
.missions .m-next::before{ background:var(--gold); border-color:var(--gold); box-shadow:0 0 0 5px rgba(227,183,120,.14); }
.missions .m-open::before{ background:transparent; border-style:dashed; }
.m-status{
  font-family:var(--mono); font-size:.66rem; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-dim); margin-bottom:.6rem;
}
.m-done .m-status{ color:var(--teal); }
.m-next .m-status{ color:var(--gold); }
.missions h3{ font-size:clamp(1.2rem,2.6vw,1.6rem); margin-bottom:.7rem; letter-spacing:-.018em; }
.missions p{ color:var(--ink-soft); max-width:56ch; font-size:.985rem; }
.missions p b{ color:var(--ink); font-weight:500; }
.m-note{
  margin-top:.8rem; font-family:var(--mono); font-size:.7rem; letter-spacing:.06em;
  color:var(--ink-dim); line-height:1.6;
}
.m-next .m-note b{ color:var(--gold); font-weight:400; }

/* ── a chapter with a portrait ────────────────────────────────
   When the subject IS the picture, a full-bleed wash is the wrong instrument:
   the Red Tent close-up is 340 px of real pixels and stretching it across a
   viewport would turn Steph into mush. Framed at native size beside the type,
   it stays sharp and she stays the subject. */
.chapter.has-portrait{ align-items:center; }
.chapter.has-portrait::after{
  background:linear-gradient(to top, rgba(6,7,10,.55), rgba(6,7,10,.30)) !important;
}
.chapter-portrait{ margin:2.6rem 0 0; max-width:340px; }
.chapter-portrait img{
  width:100%; height:auto; border-radius:12px; border:1px solid var(--line-2);
  box-shadow:0 24px 60px rgba(0,0,0,.45);
}
.chapter-portrait figcaption{
  margin-top:.85rem; font-family:var(--mono); font-size:.66rem; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-dim);
}
@media (min-width:900px){
  .chapter.has-portrait{ grid-template-columns:1fr auto; gap:4.5rem; align-items:center; }
  .chapter.has-portrait .chapter-type{ margin-left:13.5rem; }
  .chapter-portrait{ margin:0; }
}

/* ── a chapter that carries both ─────────────────────────────
   The rabbit hole has an atmosphere and an artifact: the backing behind it,
   heavily blurred and far back, and the one photograph that proves the room.
   The blurred layer is decorative — empty alt, aria-hidden — because it is a
   feeling, not information, and a screen reader should not be told to imagine
   a face that was deliberately taken out of focus. */
/* The backing layer is meant to be SEEN — at .20 it read as an empty dark
   panel, which is worse than not having it. It is already blurred at source,
   so opacity is free to carry it: the gold and the wings land, the face never
   resolves. */
.chapter.is-backing .chapter-bg .film,
.chapter.is-backing .chapter-bg .film-still{
  opacity:.62; filter:saturate(1.04) contrast(1.03); object-position:62% 22%;
}
.chapter.is-backing .chapter-bg .film.playing{ opacity:.76; }

/* A chapter whose picture has a subject that must stay legible — Austin is
   Steph mid-sentence, and at the opacity the other chapters use she was a
   smudge. The image is mirrored in the file so she lands on the open side and
   the person beside her falls behind the type, not the other way round. */
.chapter.is-subject .chapter-bg .film,
.chapter.is-subject .chapter-bg .film-still{
  opacity:.68; filter:saturate(1.02) contrast(1.02); object-position:28% 40%;
}
.chapter.is-subject .chapter-bg .film.playing{ opacity:.82; }
.chapter.is-subject::after{
  background:linear-gradient(to left, rgba(6,7,10,.96) 0%, rgba(6,7,10,.84) 44%, rgba(6,7,10,.24) 100%) !important;
}
/* The scrim has to darken the side the TEXT is on, not a fixed side. Chapters
   alternate which side they type on, so a hard-coded direction guarantees that
   half of them put the paragraph over the brightest part of the picture —
   which is exactly what happened here. */
.chapter.is-backing::after{
  background:linear-gradient(to right, rgba(6,7,10,.97) 0%, rgba(6,7,10,.88) 46%, rgba(6,7,10,.30) 100%) !important;
}
.chapter.is-backing:nth-child(even)::after{
  background:linear-gradient(to left, rgba(6,7,10,.97) 0%, rgba(6,7,10,.88) 46%, rgba(6,7,10,.30) 100%) !important;
}
.chapter.is-subject:nth-child(odd)::after{
  background:linear-gradient(to right, rgba(6,7,10,.96) 0%, rgba(6,7,10,.84) 44%, rgba(6,7,10,.24) 100%) !important;
}
/* A landscape artifact needs more room than a portrait one. */
.chapter.wide-portrait .chapter-portrait{ max-width:520px; }
@media (min-width:900px){
  .chapter.wide-portrait{ grid-template-columns:1fr 400px; }
}

/* ── gallery ─────────────────────────────────────────────────
   A home for pictures that are good but do not belong to a chapter. Before
   this existed, every strong photo had to be forced into a paragraph it did
   not illustrate — which is exactly how the wrong image ends up next to the
   wrong sentence. */
.gallery{ padding:2rem var(--pad) 7rem; }
.g-grid{ max-width:var(--maxw); margin-inline:auto; display:grid; gap:2.4rem; }
.g-item{ margin:0; }
/* Uniform cards, because eleven different aspect ratios read as a pile rather
   than a curation. The crop is anchored on the subject, not the centre — see
   feedback_frame_on_the_face: a centre crop takes people's chins off. */
.g-item img{
  width:100%; aspect-ratio:4/5; object-fit:cover; object-position:50% 34%;
  border-radius:14px; border:1px solid var(--line); background:var(--bg-2);
  display:block;
}
.g-item.fp-left img{ object-position:38% 26%; }
.g-item.fp-high img{ object-position:50% 24%; }
.g-item.fp-mid  img{ object-position:45% 38%; }
/* wide plates get a landscape card and span the row */
.g-item.g-wide img{ aspect-ratio:16/9; object-position:50% 42%; }
/* the painting is the work itself: never crop it */
.g-item.g-art img{ aspect-ratio:auto; object-fit:contain; height:auto; }
.g-item figcaption{
  margin-top:.9rem; font-family:var(--mono); font-size:.68rem; letter-spacing:.13em;
  text-transform:uppercase; color:var(--ink-dim); line-height:1.6;
}
@media (min-width:900px){ .g-grid{ grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr)); gap:2.6rem 2rem; } }
/* A three-chapter archive rather than one long wall: the tent and the town,
   the stages, the Moon. Chapters give the eye somewhere to rest and let the
   captions mean something. */
.g-chapter{
  max-width:var(--maxw); margin:4.5rem auto 1.6rem;
  display:flex; align-items:center; gap:1rem;
  font-family:var(--mono); font-size:.68rem; letter-spacing:.19em;
  text-transform:uppercase; color:var(--gold);
}
.g-chapter::after{ content:""; flex:1; height:1px; background:var(--line); }
.g-chapter:first-of-type{ margin-top:1rem; }
.g-item img{ transition:transform .8s var(--ease), border-color .8s var(--ease); }
.g-item:hover img{ transform:scale(1.012); border-color:var(--line-2); }
@media (min-width:900px){ .g-item.g-wide{ grid-column:span 2; } }
.g-tail{
  max-width:var(--maxw); margin:4.5rem auto 0; color:var(--ink-dim); font-size:.9rem;
}
.g-tail a{ color:var(--gold); text-decoration:none; }
.g-tail a:hover{ color:var(--ink); }
@media (prefers-reduced-motion:reduce){ .g-item img{ transition:none; } .g-item:hover img{ transform:none; } }

/* ── the Moon, in sequence ───────────────────────────────────
   Not one picture — the whole thing, in the order it happened: the climb, the
   plaque, the room when it lands, the flag, the crowd, the carpet. It sits
   between the Moon chapter and what comes after, because a single still could
   never carry six years ending in one night.

   Full-bleed and vertical: you keep scrolling and it keeps going. */
.moon-strip{ list-style:none; margin-inline:calc(var(--pad) * -1); padding:0; border-top:1px solid var(--line); }
.moon-strip > ol{ list-style:none; margin:0; padding:0; }
.moon-strip > ol > li{ position:relative; isolation:isolate; min-height:64svh; display:grid; align-items:end; padding:2.5rem var(--pad); }
.moon-strip > ol > li + li{ border-top:1px solid rgba(255,255,255,.06); }
.moon-strip .film, .moon-strip .film-still{
  position:absolute; inset:0; z-index:-2; width:100%; height:100%;
  object-fit:cover; opacity:.62; filter:saturate(.95) contrast(1.04);
  transition:opacity 1.1s var(--ease), transform 2s var(--ease); transform:scale(1.03);
}
.moon-strip .film-still{ display:none; }
.moon-strip .film.playing{ opacity:.82; transform:scale(1); }
.moon-strip > ol > li::after{
  content:""; position:absolute; inset:0; z-index:-1;
  background:linear-gradient(to top, rgba(6,7,10,.92) 0%, rgba(6,7,10,.42) 42%, rgba(6,7,10,.18) 100%);
}
.moon-strip p{
  position:relative; margin:0; max-width:var(--maxw); margin-inline:auto; width:100%;
  font-family:var(--mono); font-size:.72rem; letter-spacing:.2em; text-transform:uppercase;
  color:var(--ink); text-shadow:0 2px 22px rgba(0,0,0,.8);
}
@media (min-width:900px){ .moon-strip > ol > li{ min-height:78svh; } .moon-strip p{ font-size:.78rem; } }
@media (prefers-reduced-motion: reduce){
  .moon-strip .film{ display:none; } .moon-strip .film-still{ display:block; }
}

/* ── reading over a picture, on a phone ──────────────────────
   The chapters put body copy on top of imagery. On a narrow screen that
   collides: full-width measure, 1.14rem type and a scrim tuned for a wide
   viewport turn a paragraph into a wall you have to fight. Below 900px the
   type steps down, the measure tightens, and the scrim goes bottom-heavy so
   the words always sit on the darkest part of the frame. */
@media (max-width:899px){
  .chapter{ padding:clamp(2.6rem,8vh,4.5rem) var(--pad); min-height:auto; }
  .chapter h3{ font-size:clamp(1.75rem,7.4vw,2.4rem); margin-bottom:.9rem; }
  .chapter p{ font-size:.95rem; line-height:1.58; max-width:38ch; }
  .chapter-type{ max-width:none; }
  .chapter .turn{ font-size:clamp(1.12rem,4.4vw,1.4rem); margin-top:1.4rem; padding-top:1.1rem; }
  .chapter .turn.big{ font-size:clamp(1.4rem,6vw,1.9rem); }
  .chapter::after{
    background:linear-gradient(to top, rgba(6,7,10,.97) 0%, rgba(6,7,10,.92) 46%, rgba(6,7,10,.62) 78%, rgba(6,7,10,.5) 100%) !important;
  }
  .chapter-bg .film, .chapter-bg .film-still{ opacity:.22; }
  .chapter.is-backing .chapter-bg .film,
  .chapter.is-subject .chapter-bg .film{ opacity:.34; }
  .chapter.has-shot .chapter-bg .film-still{ opacity:.40; }
  .moon-strip > ol > li{ min-height:48svh; }
}

/* ── the map ─────────────────────────────────────────────────
   A credentials list is a list of logos and reads like a CV. Plotted by real
   latitude and longitude, the same information becomes a shape — and the shape
   is the argument: a cluster in Mexico, a line running north from Argentina,
   two points in Asia, and one that leaves the frame entirely.

   Inline SVG, no map library, no tiles: the CSP forbids external hosts and a
   basemap would have been 300 KB to say less than eleven dots do. */
.mapsec{ padding:7rem var(--pad); border-block:1px solid var(--line); background:var(--bg-2); overflow:hidden; }
.mapsec-in{ max-width:var(--maxw); margin-inline:auto; }
.mapsec h2{ font-size:clamp(1.7rem,4vw,2.7rem); letter-spacing:-.03em; max-width:24ch; margin-bottom:3rem; text-wrap:balance; }
.map-wrap{ position:relative; }
.mapsvg{ width:100%; height:auto; overflow:visible; display:block; }

.mp-grid line{ stroke:rgba(255,255,255,.07); stroke-width:1; stroke-dasharray:2 7; }
.mp-arc path{
  fill:none; stroke:rgba(227,183,120,.34); stroke-width:1.1;
  stroke-dasharray:1400; stroke-dashoffset:1400;
  animation:arc-draw 2.6s var(--ease) .5s forwards;
}
.mp-arc .mp-arc-moon{ stroke:rgba(139,124,248,.55); stroke-width:1.4; animation-delay:1.6s; }
@keyframes arc-draw{ to{ stroke-dashoffset:0 } }

.mp-dot{
  fill:var(--gold); opacity:0;
  animation:dot-in .8s var(--ease) forwards;
  animation-delay:calc(.35s + var(--i) * .11s);
}
.mp-dot.big{ fill:var(--teal); }
.mp-dot.prod{ fill:#fff; }
@keyframes dot-in{ from{ opacity:0; transform:scale(.2) } to{ opacity:1; transform:scale(1) } }

.mp-name, .mp-sub{
  opacity:0; animation:dot-in .9s var(--ease) forwards;
  animation-delay:calc(.55s + var(--i) * .11s);
  font-family:var(--mono);
}
.mp-name{ fill:var(--ink); font-size:14px; letter-spacing:.06em; }
.mp-sub{ fill:var(--ink-dim); font-size:11px; letter-spacing:.1em; text-transform:uppercase; }

.mp-moon{ fill:none; stroke:var(--violet); stroke-width:1.4; opacity:0;
  animation:dot-in 1.2s var(--ease) 2.4s forwards; }
.mp-moon-name{ fill:var(--violet); font-family:var(--mono); font-size:15px; letter-spacing:.28em;
  opacity:0; animation:dot-in 1.2s var(--ease) 2.6s forwards; }
.mp-moon-sub{ fill:var(--ink-dim); font-family:var(--mono); font-size:11px; letter-spacing:.14em;
  opacity:0; animation:dot-in 1.2s var(--ease) 2.8s forwards; }

@media (max-width:760px){
  .mp-name{ font-size:19px; } .mp-sub{ font-size:15px; }
  .mp-moon-name{ font-size:20px; } .mp-moon-sub{ font-size:15px; }
  .mp-dot{ r:6; }
}
@media (prefers-reduced-motion:reduce){
  .mp-arc path{ animation:none; stroke-dashoffset:0; }
  .mp-dot,.mp-name,.mp-sub,.mp-moon,.mp-moon-name,.mp-moon-sub{ animation:none; opacity:1; }
}

/* ── the globe ───────────────────────────────────────────────
   Sticky inside a tall section, so scrolling turns the planet at the reader's
   own pace. The label sits under the sphere rather than beside each dot: at
   this scale Tulum, Cancún and Mexico City are a few pixels apart, and one
   name at a time is the only version that can be read at all. */
.globe-sec{ padding:7rem 0 0; border-top:1px solid var(--line); }
.globe-scroll{ height:1500svh; position:relative; }
/* A column with real gaps, not a grid plus a negative margin. The old version
   pulled the HUD up by a fixed 1.5rem and pinned the legend to the bottom in
   absolute position, so on a short window the place name sat ON the globe and
   the subtitle ran into "keep scrolling". Here the globe is the only thing
   allowed to shrink, and the bottom padding reserves the legend's room, so
   nothing can collide at any height. */
.globe-sticky{
  position:sticky; top:0; height:100svh;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:clamp(.35rem, 1.6svh, 1.1rem);
  padding:clamp(1rem,3svh,2rem) var(--pad) clamp(5rem, 13svh, 7.5rem);
  background:
    radial-gradient(70% 55% at 50% 42%, rgba(40,70,130,.16), transparent 70%),
    var(--bg);
  overflow:hidden;
}
.globe{
  width:min(92vw, 720px); height:min(58svh, 660px); display:block;
  flex:0 1 auto; min-height:0;                 /* the globe yields, the words never do */
}
.globe-hud{ text-align:center; flex:none; max-width:min(38ch, 92vw); }
.globe-name{
  margin:0; font-family:var(--display); font-size:clamp(1.5rem,4.4vw,2.6rem);
  letter-spacing:-.028em; line-height:1.1; text-wrap:balance;
}
.globe-sub{
  margin:.45rem 0 0; font-family:var(--mono); font-size:clamp(.6rem,1.5vw,.7rem);
  letter-spacing:.18em; text-transform:uppercase; color:var(--gold);
  text-wrap:balance; line-height:1.5;
}
@media (prefers-reduced-motion:reduce){
  .globe-scroll{ height:auto; }
  .globe-sticky{ position:static; height:auto; padding:3rem 0 4rem; }
}

/* ── the doors, and the five questions ───────────────────────
   No deck, no calendar link, no inbox. The quiz is a modal so the page keeps
   its place underneath — answering it should feel like being asked something,
   not like being routed to a form. */
.doors-head{ max-width:var(--maxw); margin:0 auto 3rem; grid-column:1/-1; }
.doors-head h2{ font-size:clamp(1.9rem,5vw,3.2rem); letter-spacing:-.032em; max-width:18ch; margin-bottom:1.2rem; text-wrap:balance; }
.doors-lede{ color:var(--ink-soft); max-width:56ch; }
.door h2{ font-size:clamp(1.5rem,3.4vw,2.1rem); letter-spacing:-.024em; margin-bottom:.9rem; }

.quiz{ position:fixed; inset:0; z-index:200; display:grid; place-items:center;
  background:rgba(4,5,8,.86); backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px); padding:1.25rem; }
.quiz[hidden]{ display:none; }
.quiz-panel{
  position:relative; width:min(560px,100%); background:var(--surface);
  border:1px solid var(--line-2); border-radius:20px; padding:2.6rem 2.2rem 1.8rem;
  box-shadow:0 40px 120px rgba(0,0,0,.6);
}
.quiz-x{ position:absolute; top:1rem; right:1.1rem; background:none; border:0; color:var(--ink-dim);
  font-size:1.6rem; line-height:1; cursor:pointer; padding:.2rem .4rem; }
.quiz-x:hover{ color:var(--ink); }
.quiz-panel h2{ font-size:clamp(1.7rem,4.4vw,2.3rem); letter-spacing:-.026em; margin-bottom:1.9rem; }
.quiz-q{ font-family:var(--display); font-size:clamp(1.15rem,3vw,1.42rem); line-height:1.28;
  letter-spacing:-.018em; margin-bottom:1.4rem; text-wrap:balance; }
.quiz-opts{ display:grid; gap:.55rem; }
.quiz-opt{
  text-align:left; padding:.9rem 1.1rem; border-radius:12px; cursor:pointer;
  border:1px solid var(--line); background:rgba(255,255,255,.02); color:var(--ink);
  font-family:var(--sans); font-size:.97rem;
  transition:border-color .3s var(--ease), background .3s var(--ease), transform .3s var(--ease);
}
.quiz-opt:hover{ border-color:var(--gold); background:rgba(227,183,120,.07); transform:translateX(3px); }
.quiz-form{ display:grid; gap:.6rem; }
.quiz-form input{
  width:100%; padding:.9rem 1.1rem; border-radius:12px; background:rgba(255,255,255,.03);
  border:1px solid var(--line); color:var(--ink); font-family:var(--mono); font-size:.9rem;
}
.quiz-form input:focus{ outline:none; border-color:var(--teal); }
.quiz-note{ font-family:var(--mono); font-size:.66rem; letter-spacing:.08em; color:var(--ink-dim); margin:.3rem 0 .5rem; }
.quiz-err{ font-family:var(--mono); font-size:.7rem; color:var(--gold); margin-top:.7rem; }
.quiz-done{ color:var(--ink-soft); font-size:.97rem; max-width:44ch; }
.quiz-foot{ display:flex; align-items:center; justify-content:space-between; margin-top:1.9rem;
  padding-top:1.1rem; border-top:1px solid var(--line); }
.quiz-step{ font-family:var(--mono); font-size:.68rem; letter-spacing:.18em; color:var(--ink-dim); margin:0; }
.quiz-foot .btn{ min-height:38px; padding:.45rem 1rem; font-size:.82rem; }

/* Every gate offers a second path. */
.vault-nocode{ margin-top:1.1rem; font-size:.86rem; color:var(--ink-dim); }
.vault-nocode button{
  background:none; border:0; padding:0; cursor:pointer; color:var(--gold);
  font:inherit; text-decoration:underline; text-underline-offset:3px;
}
.vault-nocode button:hover{ color:var(--ink); }
.contact-note{ margin-top:1.6rem; font-family:var(--mono); font-size:.68rem; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-dim); }

/* Subtle outbound: a chapter can hand you the living version of what it just
   described, without turning the paragraph into a banner. Small, mono, gold,
   and always at the end of the thought — never in the middle of a sentence. */
.chapter-live{
  display:inline-block; margin-top:.6rem; font-family:var(--mono); font-size:.68rem;
  letter-spacing:.12em; text-transform:uppercase; color:var(--gold);
  text-decoration:none; border-bottom:1px solid rgba(227,183,120,.32); padding-bottom:2px;
  transition:color .3s var(--ease), border-color .3s var(--ease);
}
.chapter-live:hover{ color:var(--ink); border-color:var(--ink); }
.chapter-live-p{ margin-top:.4rem; }

/* ── ventures & partners ─────────────────────────────────────
   The shortest path for someone who already knows what they want. A table of
   rows rather than cards on purpose: this is a price list, and a price list
   that pretends to be a gallery is harder to scan, not easier.

   Everything here is live today. Nothing on this list is a waitlist. */
.offer{ padding:7rem var(--pad); border-block:1px solid var(--line); background:var(--bg-2); }
.offer-in{ max-width:var(--maxw); margin-inline:auto; }
.offer h2{ font-size:clamp(1.9rem,5vw,3rem); letter-spacing:-.032em; max-width:18ch; margin-bottom:1.1rem; text-wrap:balance; }
.offer-lede{ color:var(--ink-soft); max-width:54ch; margin-bottom:2.8rem; }
.offer-list{ list-style:none; margin:0; padding:0; }
.offer-list li{ border-top:1px solid var(--line); }
.offer-list li:last-child{ border-bottom:1px solid var(--line); }
.offer-list a{
  display:grid; gap:.15rem 1.5rem; padding:1.35rem 0; text-decoration:none; color:inherit;
  transition:padding-left .4s var(--ease), color .4s var(--ease);
}
.offer-list a:hover{ padding-left:.9rem; }
.of-what{ font-family:var(--display); font-size:clamp(1.05rem,2.4vw,1.42rem); letter-spacing:-.018em; }
.of-who{ font-family:var(--mono); font-size:.67rem; letter-spacing:.15em; text-transform:uppercase; color:var(--ink-dim); }
.of-price{ font-family:var(--mono); font-size:.72rem; letter-spacing:.11em; color:var(--gold); }
.offer-list a:hover .of-price{ color:var(--ink); }
.offer-note{ margin-top:2.2rem; font-size:.92rem; color:var(--ink-dim); }
@media (min-width:820px){
  .offer-list a{ grid-template-columns:1fr 230px 170px; align-items:baseline; gap:1.5rem; }
  .of-price{ text-align:right; }
}

/* The vault reads as a gate, not a dialog: a hairline gold frame, mono
   everything, and a code field wide enough to look like it expects something
   specific. It is the one place on the site that says no. */
.vault-panel{ border-color:rgba(227,183,120,.30); }
.vault-panel::before{
  content:""; position:absolute; inset:10px; border-radius:14px; pointer-events:none;
  border:1px solid rgba(227,183,120,.14);
}
.vault-panel .eyebrow{ color:var(--gold); letter-spacing:.3em; }
.vault-lede{ color:var(--ink-soft); max-width:40ch; }
#vault-code{ font-family:var(--mono); letter-spacing:.22em; text-transform:uppercase; }

/* The room behind the code. It is per-person, so it opens with a name and a
   line ClaudIA wrote for them — the numbers come after, not first. */
.vault-head{ margin-bottom:1.4rem; }
.vault-who{
  margin:0 0 .35rem; font-family:var(--mono); font-size:.68rem; letter-spacing:.24em;
  text-transform:uppercase; color:var(--gold);
}
.vault-line{
  margin:0; font-family:var(--display); font-size:clamp(1.15rem,3vw,1.5rem);
  line-height:1.28; letter-spacing:-.018em; color:var(--ink); max-width:34ch;
}
.vault-notes{ list-style:none; margin:0 0 1.6rem; padding:0; display:grid; gap:.5rem; }
.vault-notes li{
  padding-left:1.1rem; position:relative; color:var(--ink-soft); font-size:.94rem;
}
.vault-notes li::before{
  content:""; position:absolute; left:0; top:.62em; width:5px; height:5px;
  border-radius:50%; background:var(--gold);
}
.vault-next{ margin-top:1.4rem; }

/* The form asks for more than a name now, but only two fields are required.
   Everything optional is labelled optional in the placeholder itself, so
   nobody has to guess what they are obliged to hand over. */
.quiz-sub{ margin:-.8rem 0 1.2rem; color:var(--ink-dim); font-size:.88rem; max-width:42ch; }
.quiz-form textarea{
  width:100%; padding:.9rem 1.1rem; border-radius:12px; background:rgba(255,255,255,.03);
  border:1px solid var(--line); color:var(--ink); font-family:var(--sans); font-size:.94rem;
  line-height:1.5; resize:vertical; min-height:5.2rem;
}
.quiz-form textarea:focus{ outline:none; border-color:var(--teal); }
.quiz-count{
  margin:-.2rem 0 0; text-align:right; font-family:var(--mono); font-size:.64rem;
  letter-spacing:.08em; color:var(--ink-dim);
}
.quiz-alt{ margin:1.1rem 0 0; font-size:.88rem; color:var(--ink-dim); }
.quiz-alt a{ color:var(--gold); text-decoration:underline; text-underline-offset:3px; }
.quiz-alt a:hover{ color:var(--ink); }

/* ── the gate ────────────────────────────────────────────────
   Full screen, dark, a field of drifting keys and one lock. Everything that
   moves here is transform and opacity, so a phone can run it without the
   scroll it just fell down going to pieces. */
.gate{
  position:fixed; inset:0; z-index:300; overflow-y:auto;
  background:
    radial-gradient(60% 45% at 50% 38%, rgba(227,183,120,.10), transparent 70%),
    radial-gradient(120% 90% at 50% 50%, rgba(8,9,14,.94), #04050a 78%);
  opacity:0; transition:opacity .34s var(--ease);
  display:grid; place-items:center; padding:4rem 1.25rem;
}
.gate[hidden]{ display:none; }
.gate.in{ opacity:1; }

.gate-keys{ position:fixed; inset:0; width:100%; height:100%; z-index:0; pointer-events:none; }
.gk{
  opacity:0; animation:key-in 1.1s var(--ease) forwards, key-drift 13s ease-in-out infinite;
  animation-delay:var(--d), calc(var(--d) + 1.1s);
  transform-box:fill-box; transform-origin:center;
}
@keyframes key-in{ from{ opacity:0 } to{ opacity:var(--o) } }
@keyframes key-drift{
  0%,100%{ translate:0 0 } 50%{ translate:0 -14px }
}
/* When a key turns, the rest stand back. */
.gate.is-open .gk, .gate.is-trying .gk{ opacity:.10; transition:opacity .8s var(--ease); }

.gate-inner{ position:relative; z-index:2; width:min(620px,100%); text-align:center; }
.gate-x{ position:absolute; top:-2.4rem; right:0; background:none; border:0; color:var(--ink-dim);
  font-size:1.8rem; line-height:1; cursor:pointer; }
.gate-x:hover{ color:var(--ink); }

.gate-lock{ position:relative; width:132px; height:132px; margin:0 auto 2rem; }
.lock-svg{ width:100%; height:100%; }
.lock-ring{ fill:none; stroke:rgba(227,183,120,.35); stroke-width:1.5; }
.lock-ring2{ fill:none; stroke:rgba(227,183,120,.18); stroke-width:1; stroke-dasharray:3 7; }
.lock-hole{ fill:rgba(227,183,120,.55); }
.gate.is-open .lock-ring{ stroke:var(--teal); transition:stroke .6s var(--ease); }

/* The key that answers: it flies in, meets the lock, and either turns or does not. */
.lock-key{
  position:absolute; left:50%; top:50%; width:52px; height:112px;
  translate:-50% -50%; opacity:0; transform-origin:50% 22%;
}
.gate.is-trying .lock-key{ opacity:1; animation:key-approach .62s var(--ease) forwards; }
.gate.is-open .lock-key{ opacity:1; animation:key-turn .9s var(--ease) forwards; }
.gate.is-wrong .lock-key{ opacity:1; animation:key-refuse .9s var(--ease) forwards; }
@keyframes key-approach{ from{ opacity:0; translate:-50% 40%; scale:.7 } to{ opacity:1; translate:-50% -50%; scale:1 } }
@keyframes key-turn{
  0%{ rotate:0deg } 55%{ rotate:96deg } 70%{ rotate:88deg }
  100%{ rotate:92deg; opacity:0; scale:1.25 }
}
@keyframes key-refuse{
  0%{ rotate:0deg } 18%{ rotate:22deg } 32%{ rotate:6deg } 46%{ rotate:20deg }
  60%{ rotate:0deg } 100%{ rotate:0deg; opacity:0; translate:-50% 26% }
}

.gate-inner h2{ font-size:clamp(2rem,6vw,3.2rem); letter-spacing:-.034em; margin-bottom:1rem; }
.gate-lede{ color:var(--ink-soft); max-width:44ch; margin:0 auto 2.2rem; }
#gate-form{ display:flex; gap:.6rem; justify-content:center; flex-wrap:wrap; }
#gate-code{
  flex:1 1 300px; max-width:360px; padding:1rem 1.3rem; border-radius:100px;
  background:rgba(255,255,255,.03); border:1px solid rgba(227,183,120,.4); color:var(--ink);
  font-family:var(--mono); font-size:.95rem; letter-spacing:.26em; text-transform:uppercase;
  text-align:center;
}
#gate-code:focus{ outline:none; border-color:var(--teal); box-shadow:0 0 0 4px rgba(69,214,192,.12); }
.gate.is-wrong #gate-code{ border-color:#e0705f; animation:shake .5s var(--ease); }
@keyframes shake{ 0%,100%{ translate:0 } 20%{ translate:-7px } 40%{ translate:6px } 60%{ translate:-4px } 80%{ translate:2px } }
.gate-msg{ margin-top:1rem; min-height:1.3em; font-family:var(--mono); font-size:.74rem;
  letter-spacing:.12em; color:var(--gold); }
.gate-nocode{ margin-top:1.6rem; font-size:.88rem; color:var(--ink-dim); }
.gate-nocode button{
  background:none; border:0; padding:0; cursor:pointer; color:var(--gold); font:inherit;
  text-decoration:underline; text-underline-offset:3px;
}
.gate-nocode button:hover{ color:var(--ink); }
.gate-out{ margin-top:2.6rem; text-align:left; }
.gate.is-open .gate-lede, .gate.is-open #gate-form, .gate.is-open .gate-nocode{ display:none; }

@media (prefers-reduced-motion:reduce){
  .gk{ animation:none; opacity:var(--o); }
  .lock-key{ display:none; }
  .gate{ transition:none; }
}

/* ── glocal: three places ────────────────────────────────────
   Local initiatives, global effect. Each card is a place she actually works
   from, and its links are only the things that are genuinely live there.
*/
.glocal{ padding:7rem var(--pad); }
.glocal-in{ max-width:var(--maxw); margin-inline:auto; }
.places{ list-style:none; margin:2.8rem 0 0; padding:0; display:grid; gap:1.2rem; }
@media (min-width:900px){ .places{ grid-template-columns:repeat(3,1fr); } }
.place{
  padding:2.1rem 1.8rem; border:1px solid var(--line); border-radius:18px;
  background:var(--surface); display:flex; flex-direction:column;
}
.place-co{ font-family:var(--mono); font-size:.64rem; letter-spacing:.15em; color:var(--ink-dim); }
.place h3{ font-size:1.45rem; margin:.5rem 0 .8rem; letter-spacing:-.02em; }
.place > p{ color:var(--ink-soft); font-size:.93rem; margin:0 0 1.4rem; }
.place-links{ list-style:none; margin:auto 0 0; padding:0; display:flex; flex-wrap:wrap; gap:.45rem; }
.place-links a{
  font-family:var(--mono); font-size:.64rem; letter-spacing:.1em; text-transform:uppercase;
  text-decoration:none; color:var(--ink-soft);
  border:1px solid var(--line-2); border-radius:999px; padding:.42rem .75rem;
  transition:color .35s var(--ease), border-color .35s var(--ease), background .35s var(--ease);
}
.place-links a:hover{ color:var(--ink); border-color:var(--ink-soft); background:rgba(255,255,255,.05); }

/* ── savia ───────────────────────────────────────────────────
   The one live research strand, and the only place on the site that asks for
   money rather than attention. The film sits behind the copy at low opacity:
   it is a generated data film, so it reads as texture, and the argument
   survives with it turned off.
*/
.savia{ position:relative; padding:7.5rem var(--pad); overflow:hidden; border-block:1px solid var(--line); }
.savia-bg{ position:absolute; inset:0; z-index:-2; background:#040603; overflow:hidden; }
/* The film is itself typographic, so at full sharpness its burned-in words
   ("ION CHANNELS OPEN") sat behind the section's own headline and the two
   sets of type fought. Blurred and scaled past the frame edge it becomes
   what it should be here: a field of moving light. */
.savia-bg video, .savia-bg img{
  width:100%; height:100%; object-fit:cover; opacity:.22;
  filter:blur(5px) saturate(1.15);
  transform:scale(1.08);
}
/* the still is the reduced-motion path only — never both at once */
.savia-bg img{ display:none; }
.savia-bg::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(180deg, var(--bg) 0%, rgba(6,7,10,.58) 30%, rgba(6,7,10,.70) 70%, var(--bg) 100%);
}
.savia-in{ max-width:var(--maxw); margin-inline:auto; position:relative; }
.savia h2{ font-size:clamp(1.9rem,4.8vw,3rem); letter-spacing:-.032em; max-width:17ch; margin-bottom:1.2rem; text-wrap:balance; }
.savia-lede{ color:var(--ink); max-width:54ch; font-size:clamp(1.04rem,2vw,1.16rem); }
.savia-body{ color:var(--ink-soft); max-width:54ch; margin-top:1.1rem; }
.savia-q{
  margin:2.6rem 0; padding:1.5rem 1.7rem; max-width:54ch;
  border-left:2px solid var(--teal); background:rgba(69,214,192,.055); border-radius:0 12px 12px 0;
}
.savia-q p{ margin:0; font-family:var(--display); font-style:italic; font-size:1.12rem; color:var(--ink); }
.savia-q .untested{
  display:block; margin-top:.7rem; font-family:var(--mono); font-size:.63rem;
  letter-spacing:.16em; text-transform:uppercase; font-style:normal; color:var(--teal);
}
.savia-open{ list-style:none; margin:2.4rem 0 0; padding:0; display:grid; gap:1px;
  background:var(--line); border:1px solid var(--line); border-radius:14px; overflow:hidden;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,190px),1fr)); }
.savia-open li{ background:rgba(10,12,18,.82); padding:1.25rem 1.2rem; }
.savia-open b{ display:block; font-family:var(--mono); font-size:.63rem; letter-spacing:.14em;
  text-transform:uppercase; color:var(--gold); margin-bottom:.45rem; }
.savia-open span{ color:var(--ink-soft); font-size:.87rem; }
.savia-cta{ display:flex; flex-wrap:wrap; gap:.75rem; margin-top:2.8rem; }
.savia-note{ margin-top:1.5rem; color:var(--ink-dim); font-size:.83rem; max-width:52ch; }

@media (prefers-reduced-motion:reduce){
  .savia-bg video{ display:none; }
  .savia-bg img{ display:block; }
}

/* ── socials ─────────────────────────────────────────────────
   Wired from one config object in app.js. An entry with no handle is never
   rendered — an empty row is honest, a link to a profile that does not exist
   is not.
*/
.socials{ list-style:none; margin:2.2rem 0 0; padding:0; display:flex; flex-wrap:wrap; gap:.6rem; }
.socials a{
  display:inline-flex; align-items:center; gap:.55rem;
  min-height:44px; padding:.6rem 1rem;
  border:1px solid var(--line-2); border-radius:999px;
  text-decoration:none; color:var(--ink-soft);
  font-family:var(--mono); font-size:.68rem; letter-spacing:.11em; text-transform:uppercase;
  transition:color .35s var(--ease), border-color .35s var(--ease), background .35s var(--ease);
}
.socials a:hover{ color:var(--ink); border-color:var(--ink-soft); background:rgba(255,255,255,.05); }
.socials svg{ width:15px; height:15px; fill:currentColor; flex:none; }
.foot-socials{ display:flex; flex-wrap:wrap; gap:1.1rem; }
.foot-socials a{ color:var(--ink-dim); text-decoration:none; transition:color .3s var(--ease); }
.foot-socials a:hover{ color:var(--ink); }

/* the nav is fixed, so an anchor jump lands with the heading underneath it */
#ecosystem, #glocal, #savia, #doors, #vision, #contact{ scroll-margin-top:84px; }

/* ── the map: legend and the way out ─────────────────────────
   The globe scroller is 1500svh. Fifteen screens is a long time to trust a
   page, so it says what is happening and offers an exit that is deliberately
   quiet: findable when you want it, never competing with the globe.
*/
.globe-legend{
  position:absolute; left:0; right:0; bottom:clamp(1.2rem,4svh,2.6rem);
  display:flex; flex-direction:column; align-items:center; gap:.9rem;
  pointer-events:none;
}
.globe-keep{
  margin:0; display:inline-flex; align-items:center; gap:.6rem;
  font-family:var(--mono); font-size:.64rem; letter-spacing:.2em; text-transform:uppercase;
  color:var(--ink-dim);
}
/* Its own short travel. The hero's `cue` runs -20px to +56px, which is right
   for a tall hero and sends this one clean out of its label. */
.globe-keep .kb{
  position:relative; width:1px; height:14px; flex:none; display:block;
  background:linear-gradient(to bottom, transparent, var(--gold));
  animation:keep-cue 2.4s var(--ease) infinite;
}
@keyframes keep-cue{
  0%{ transform:translateY(-6px); opacity:0 }
  40%{ opacity:1 }
  100%{ transform:translateY(6px); opacity:0 }
}
.globe-skip{
  pointer-events:auto;
  font-family:var(--mono); font-size:.6rem; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-dim); text-decoration:none;
  border:1px solid var(--line); border-radius:999px; padding:.45rem .9rem;
  transition:color .35s var(--ease), border-color .35s var(--ease), background .35s var(--ease);
}
.globe-skip:hover, .globe-skip:focus-visible{ color:var(--ink); border-color:var(--ink-soft); background:rgba(255,255,255,.05); }

/* The road behind the globe. One clip at a time, each one drifting slowly so
   the frame is never still, cross-faded over two and a half seconds.
   Less blur and more of the real colour than before, because these are the
   clips she is actually in and they should read as a life rather than as
   wallpaper. The globe stays the subject: the scrim darkens the CENTRE, which
   is the one place the route has to stay legible. */
.globe-film{ position:absolute; inset:0; z-index:-1; overflow:hidden; }
.globe-film .gf{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  opacity:0; transition:opacity 2.5s var(--ease);
  filter:blur(2.5px) saturate(1.12) contrast(1.05);
  transform:scale(1.14);
  will-change:opacity, transform;
}
.globe-film .gf.on{ opacity:.32; }
/* four drifts, so two clips in a row never move the same way */
.globe-film .gf.on.k1{ animation:drift1 17s var(--ease) forwards; }
.globe-film .gf.on.k2{ animation:drift2 17s var(--ease) forwards; }
.globe-film .gf.on.k3{ animation:drift3 17s var(--ease) forwards; }
.globe-film .gf.on.k4{ animation:drift4 17s var(--ease) forwards; }
@keyframes drift1{ from{ transform:scale(1.13) translate(0,0) }      to{ transform:scale(1.26) translate(-2.2%, -1.6%) } }
@keyframes drift2{ from{ transform:scale(1.26) translate(1.8%,1.2%) } to{ transform:scale(1.13) translate(0,0) } }
@keyframes drift3{ from{ transform:scale(1.14) translate(1.6%,-1%) }  to{ transform:scale(1.27) translate(-1.4%, 1.4%) } }
@keyframes drift4{ from{ transform:scale(1.25) translate(-1.6%,1%) }  to{ transform:scale(1.13) translate(1.6%,-1.2%) } }
.globe-film::after{
  content:""; position:absolute; inset:0;
  background:
    radial-gradient(54% 48% at 50% 44%, rgba(6,7,10,.90) 0%, rgba(6,7,10,.60) 52%, rgba(6,7,10,.30) 78%, transparent 100%),
    linear-gradient(to bottom, var(--bg) 0%, rgba(6,7,10,.34) 22%, rgba(6,7,10,.34) 74%, var(--bg) 100%);
}
@media (prefers-reduced-motion:reduce){
  .globe-film .gf{ display:none; }
  .globe-keep .kb{ animation:none; }
}

/* ── the products, as holons ─────────────────────────────────
   A holon is a whole that is also a part, so a cell is a complete thing with
   its own membrane and the group around it is the same shape one size up.
   Nothing here is a rectangle grid pretending the items are interchangeable.
*/
.holons{ padding:7rem var(--pad); background:var(--bg-2); border-block:1px solid var(--line); }
.holons-in{ max-width:var(--maxw); margin-inline:auto; }
.holon-wrap{ display:grid; gap:2.5rem; margin-top:1rem; }
@media (min-width:1000px){
  .holon-wrap{ grid-template-columns:minmax(0,1fr) minmax(0,1.02fr); gap:3.5rem; align-items:start; }
}
.holon{ margin-bottom:2.6rem; }
.holon:last-child{ margin-bottom:0; }
.holon-label{
  display:flex; align-items:center; gap:.8rem; margin:0 0 1.1rem;
  font-family:var(--mono); font-size:.68rem; letter-spacing:.17em; text-transform:uppercase;
  color:var(--ink-soft);
}
.holon-label .hn{ color:var(--gold); }
.holon-label::after{ content:""; flex:1; height:1px; background:var(--line); }

.cells{ list-style:none; margin:0; padding:0; display:grid; gap:.6rem;
  grid-template-columns:repeat(auto-fill,minmax(min(100%,168px),1fr)); }
.cell{
  --ring:var(--line-2);
  position:relative; width:100%; min-height:104px;
  display:flex; flex-direction:column; align-items:flex-start; gap:.3rem;
  padding:1.05rem 1rem 1rem;
  background:var(--surface); color:inherit; text-align:left; cursor:pointer;
  border:1px solid var(--ring); border-radius:16px;
  font:inherit;
  transition:border-color .45s var(--ease), background .45s var(--ease), transform .45s var(--ease);
}
.cell::before{ /* the nucleus */
  content:""; position:absolute; top:1.05rem; right:1rem;
  width:7px; height:7px; border-radius:50%;
  background:var(--teal); box-shadow:0 0 0 4px rgba(69,214,192,.14);
  transition:background .45s var(--ease), box-shadow .45s var(--ease);
}
.cell.building::before{ background:var(--gold); box-shadow:0 0 0 4px rgba(227,183,120,.14); }
.cell:hover, .cell:focus-visible, .cell.on{
  --ring:var(--ink-soft); background:#141924; transform:translateY(-2px);
}
.cell:focus-visible{ outline:2px solid var(--teal); outline-offset:3px; }
.cell .cn{ font-family:var(--mono); font-size:.6rem; letter-spacing:.14em; color:var(--ink-dim); }
.cell .ct{ font-family:var(--display); font-size:1.08rem; letter-spacing:-.015em; line-height:1.2; }
.cell .ck{
  margin-top:auto; font-family:var(--mono); font-size:.58rem; letter-spacing:.13em;
  text-transform:uppercase; color:var(--ink-dim);
}

/* ── the stage ───────────────────────────────────────────────
   Sticky beside the cells on a pointer device. On touch it becomes a sheet.
*/
.stage{ display:none; }
@media (min-width:1000px){
  .stage{ display:block; position:sticky; top:96px; }
}
.stage-in{
  border:1px solid var(--line); border-radius:20px; overflow:hidden;
  background:var(--surface);
}
.stage-x{ display:none; }
.stage-frame{
  position:relative; aspect-ratio:4/3; background:#05070c;
  border-bottom:1px solid var(--line); overflow:hidden;
}
.stage-chrome{
  position:absolute; inset:0 0 auto 0; height:30px; z-index:2;
  display:flex; align-items:center; gap:.35rem; padding:0 .8rem;
  background:rgba(8,10,16,.92); border-bottom:1px solid var(--line);
}
.stage-chrome span{ width:7px; height:7px; border-radius:50%; background:var(--line-2); }
.stage-chrome b{
  margin-left:.7rem; font-family:var(--mono); font-weight:400; font-size:.6rem;
  letter-spacing:.09em; color:var(--ink-dim); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* The frame scrolls. The capture is the whole page, so a visitor can look
   around a site before deciding to open it, which is the point of a preview. */
.stage-scroll{
  position:absolute; inset:30px 0 0 0; overflow-y:auto; overflow-x:hidden;
  overscroll-behavior:contain;              /* never hand the scroll to the page */
  scrollbar-width:thin; scrollbar-color:var(--line-2) transparent;
  -webkit-overflow-scrolling:touch;
}
.stage-scroll::-webkit-scrollbar{ width:6px; }
.stage-scroll::-webkit-scrollbar-thumb{ background:var(--line-2); border-radius:3px; }
.stage-scroll::-webkit-scrollbar-track{ background:transparent; }
#stageShot{
  display:block; width:100%; height:auto;
  opacity:0; transition:opacity .5s var(--ease);
}
#stageShot.on{ opacity:1; }
/* the nudge that says the box is not a picture */
.stage-hint{
  position:absolute; left:50%; bottom:.7rem; transform:translateX(-50%); z-index:3;
  margin:0; padding:.35rem .75rem; border-radius:999px; pointer-events:none;
  background:rgba(8,10,16,.82); border:1px solid var(--line-2);
  font-family:var(--mono); font-size:.57rem; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-soft); opacity:0; transition:opacity .45s var(--ease);
}
.stage.has .stage-hint{ opacity:1; }
.stage.has.explored .stage-hint{ opacity:0; }
.stage-empty{
  position:absolute; inset:30px 0 0 0; margin:0; display:grid; place-items:center;
  font-family:var(--mono); font-size:.64rem; letter-spacing:.15em; text-transform:uppercase;
  color:var(--ink-dim); transition:opacity .4s var(--ease); z-index:2;
}
.stage.has .stage-empty{ opacity:0; }
.stage-copy{ padding:1.6rem 1.5rem 1.7rem; }
.stage-kicker{
  margin:0 0 .5rem; font-family:var(--mono); font-size:.62rem; letter-spacing:.15em;
  text-transform:uppercase; color:var(--gold); min-height:1em;
}
.stage-name{ margin:0 0 .7rem; font-size:1.5rem; letter-spacing:-.022em; }
.stage-desc{ margin:0 0 1.5rem; color:var(--ink-soft); font-size:.92rem; min-height:3.6em; }
.stage-go{ min-height:44px; padding:.7rem 1.3rem; }
.stage-go[hidden]{ display:none !important; }

.holons-note{ margin:2.6rem 0 0; color:var(--ink-dim); font-size:.82rem; max-width:56ch; }

/* ── the stage as a sheet, on touch ──────────────────────────
   Below 1000px the sticky column has nowhere to sit, so a tap opens the
   preview over the page instead. One DOM, one code path.
*/
@media (max-width:999.98px){
  .stage{
    display:block; position:fixed; inset:auto 0 0 0; z-index:60;
    transform:translateY(101%); transition:transform .5s var(--ease);
    padding:0 .75rem calc(.75rem + env(safe-area-inset-bottom));
    pointer-events:none;
  }
  .stage.open{ transform:translateY(0); pointer-events:auto; }
  .stage-in{ box-shadow:0 -24px 60px rgba(0,0,0,.6); position:relative; }
  .stage-frame{ aspect-ratio:1/1; }
  .stage-x{
    display:grid; place-items:center; position:absolute; top:.5rem; right:.5rem; z-index:3;
    width:34px; height:34px; border-radius:50%;
    background:rgba(8,10,16,.82); border:1px solid var(--line-2); color:var(--ink);
    font-size:1.3rem; line-height:1; cursor:pointer;
  }
  .stage-copy{ padding:1.2rem 1.2rem 1.4rem; }
  .stage-desc{ min-height:0; font-size:.88rem; }
  .stage-empty{ display:none; }
}
@media (prefers-reduced-motion:reduce){
  .stage{ transition:none; }
  #stageShot{ transition:none; }
  .cell{ transition:none; }
}

/* ── 2035, the close of the story ────────────────────────────
   The page used to end on the 2024 landing, which read as a finish line. This
   is the horizon it actually points at, so it gets the last word and the
   largest type on the page after the chapter headings. */
.dance{
  position:relative; padding:9rem var(--pad) 10rem;
  border-top:1px solid var(--line);
  background:
    radial-gradient(90% 60% at 50% 0%, rgba(139,124,248,.10), transparent 62%),
    radial-gradient(70% 50% at 50% 100%, rgba(69,214,192,.07), transparent 66%),
    var(--bg);
  text-align:center;
}
.dance-in{ max-width:60ch; margin-inline:auto; }
.dance h2{
  font-size:clamp(2.1rem,6vw,4.2rem); letter-spacing:-.035em; line-height:1.04;
  max-width:16ch; margin:0 auto 2rem; text-wrap:balance;
  background:linear-gradient(96deg,var(--ink) 22%,var(--gold) 64%,var(--teal) 98%);
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
.dance p{ color:var(--ink-soft); margin:0 auto 1.3rem; max-width:54ch; text-wrap:pretty; }
.dance p b{ color:var(--ink); font-weight:500; }
.dance-close{
  margin-top:2.6rem !important; font-family:var(--display); font-style:italic;
  font-size:clamp(1.1rem,2.4vw,1.45rem); color:var(--ink) !important; max-width:46ch !important;
}
.dance-cta{ margin-top:2.8rem !important; }
