/* Drift hero — the three-piece logo assembly that opens the page, ahead of the
   manifesto scroll. Everything is scroll-driven from assets/js/drift.js; there
   are no CSS animations here. Colours come from the site tokens and the Flech
   accent in 02-accent.css. */
.drift-hero,
.drift-guide {
  --drift-ink: var(--flech-accent-ink);
  --drift-accent: var(--flech-accent);
  --drift-accent-deep: var(--flech-accent-deep);
  --drift-muted: var(--site-muted);
  --drift-line: var(--site-hairline);
  --drift-serif: var(--font-family-editorial);
}

/* Stepped (sequence.js), the hero is one screen in normal flow and native
   scrolling is locked while the sequence plays. The spacer only exists for
   the reduced-motion scroll scrub, where it gives the chapters their length. */
#drift-spacer { height: 0; }
.drift-on #drift-spacer { height: 613svh; }
html.seq-stepper #drift-spacer { height: 0; }
html.seq-locked { overflow: hidden; scrollbar-gutter: stable; overscroll-behavior: none; }
html.seq-locked body { overflow: hidden; }
html.seq-locked #hero-canvas { touch-action: none; }

/* Fixed to the viewport box rather than the card, so the composition does not
   reflow (and the measured letters stay put) while the card shrinks around it. */
.drift-hero {
  position: absolute;
  z-index: 10;
  left: 50%;
  top: 50%;
  width: 100vw;
  height: 100svh;
  transform: translate(-50%, calc(-50% - var(--hx) * 72px));
  opacity: calc(1 - var(--hx) * 1.7);
  color: var(--drift-ink);
  font-family: var(--font-family-text);
  text-align: center;
}
/* the finished mark is set visible inline, so the descendants need forcing too
   (without --hx, as in reduced motion, the hero does not fade out) */
#hero-canvas.hx-done .drift-hero,
#hero-canvas.hx-done .drift-hero * { visibility: hidden !important; }
.drift-hero button:focus-visible { outline: 2px solid var(--drift-accent-deep); outline-offset: 5px; }
.drift-hero ::selection { background: var(--drift-accent); }

/* Until drift.js takes over, the markup holds the finished state for readers
   without scripting. Keep that from flashing before the first frame — but only
   briefly, so it still appears if the script never arrives. */
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  html:not(.drift-on) .drift-whole,
  html:not(.drift-on) .drift-text { animation: drift-await 2.5s steps(1); }
}
@keyframes drift-await { from, to { visibility: hidden; } }

/* Faint echoes of nine drift quotes around the opening headline, so it is not
   alone on the first screen. On load they drift apart from behind it and hang
   there, small and distant, slowly adrift. Scrolling brings them at you: each
   one grows and flies outward past the edge of the screen, the near ones
   fastest, as the stage comes up behind (--drift-stage, 0 → 1). The words are
   written into the page; only three of them become chapters. drift.js sets
   .is-opening only while they can be seen, so nothing animates once the
   chapters are under way. */
.drift-murmur {
  position: absolute;
  inset: 0;
  pointer-events: none;
  visibility: hidden;
  /* holds through most of the approach, gone as the last ones pass */
  opacity: calc(1 - var(--drift-stage, 1) * var(--drift-stage, 1));
}
.drift-hero.is-opening .drift-murmur { visibility: visible; }
/* --x/--y: resting offset from the centre of the screen, in vw and svh.
   --z: nearness, 0–1. The size and the offset are both multiplied by
        1 / (1 - stage × z), the way a thing looms as it closes on the eye.
   --k size, --o opacity, --b blur; --wx/--wy/--r/--d: the idle sway. */
.drift-murmur span {
  --s: calc(1 / (1 - var(--drift-stage, 0) * var(--z, .7)));
  position: absolute;
  left: calc(50% + var(--x) * var(--s) * 1vw);
  top: calc(50% + var(--y) * var(--s) * 1svh);
  color: var(--drift-ink);
  font-family: var(--drift-serif);
  font-size: calc(clamp(12px, .95vw, 15px) * var(--k, 1));
  letter-spacing: -.01em;
  white-space: nowrap;
  opacity: calc(var(--o) * (1 + var(--drift-stage, 0) * 1.4));
  filter: blur(var(--b, 0px));
  /* anchored on its own centre, so growing does not slide it sideways */
  transform-origin: 0 0;
  transform: translate(-50%, -50%);
  scale: var(--s);
  animation:
    drift-apart 4.4s cubic-bezier(.16, 1, .3, 1) var(--delay, 0s) both,
    drift-adrift var(--d, 18s) ease-in-out var(--delay, 0s) infinite alternate;
  animation-play-state: paused;
}
.drift-hero.is-opening .drift-murmur span { animation-play-state: running; }
/* each starts most of the way back toward the headline and lets go of it */
@keyframes drift-apart {
  from { translate: calc(var(--x) * -.72vw) calc(var(--y) * -.72svh); opacity: 0; filter: blur(7px); }
}
@keyframes drift-adrift {
  from { transform: rotate(calc(var(--r) * -1)) translate(-50%, -50%); }
  to { transform: translate(var(--wx), var(--wy)) rotate(var(--r)) translate(-50%, -50%); }
}
.drift-murmur span:nth-child(1) { --x: -21; --y: -24; --z: .8; --k: 1.1; --o: .16; --wx: 12px; --wy: -8px; --r: .7deg; --d: 19s; --delay: .1s; }
.drift-murmur span:nth-child(2) { --x: 20; --y: -27; --z: .62; --k: .9; --o: .11; --b: .5px; --wx: -9px; --wy: 9px; --r: -.9deg; --d: 23s; --delay: .45s; }
.drift-murmur span:nth-child(3) { --x: -27; --y: -7; --z: .58; --k: .85; --o: .1; --b: .8px; --wx: 8px; --wy: 10px; --r: 1.1deg; --d: 17s; --delay: .7s; }
.drift-murmur span:nth-child(4) { --x: 26; --y: -11; --z: .86; --k: 1.2; --o: .2; --wx: -13px; --wy: -6px; --r: -.6deg; --d: 21s; --delay: .25s; color: var(--drift-accent-deep); }
.drift-murmur span:nth-child(5) { --x: -24; --y: 12; --z: .78; --k: 1.1; --o: .14; --wx: 10px; --wy: 8px; --r: -.8deg; --d: 25s; --delay: .55s; }
.drift-murmur span:nth-child(6) { --x: 25; --y: 11; --z: .6; --k: .88; --o: .1; --b: .6px; --wx: -8px; --wy: -10px; --r: 1deg; --d: 18s; --delay: .85s; }
.drift-murmur span:nth-child(7) { --x: -13; --y: 26; --z: .7; --k: .95; --o: .18; --wx: 13px; --wy: -7px; --r: .6deg; --d: 22s; --delay: .35s; color: var(--drift-accent-deep); }
.drift-murmur span:nth-child(8) { --x: 16; --y: 27; --z: .72; --k: 1; --o: .13; --b: .4px; --wx: -11px; --wy: 7px; --r: -1deg; --d: 20s; --delay: .65s; }
.drift-murmur span:nth-child(9) { --x: -3; --y: -17; --z: .55; --k: .85; --o: .09; --b: .9px; --wx: 9px; --wy: 6px; --r: .9deg; --d: 16s; --delay: .95s; }

/* One fixed composition: the logo and story share a centre line and never
   reflow between chapters. The stage and the story slot sit together in the
   middle of the screen; the island nav stays away until the manifesto.
   --drift-stage runs 0 → 1 as the opening headline leaves the centre of the
   screen for the story slot, bringing the empty stage up behind it. */
.drift-composition {
  position: absolute;
  inset: 56px 6%;
  display: grid;
  grid-template-rows: minmax(0, 390px) 26px 216px;
  align-content: center;
  justify-items: center;
}
.drift-art { position: relative; width: min(850px, 100%); height: 100%; }
/* The faint grid the facets fly across. Centred on the mark and far larger
   than the stage, so it runs out to the edges of the screen and fades there
   rather than stopping at a box. */
.drift-art::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 130vw;
  height: 150svh;
  translate: -50% -50%;
  background-image: linear-gradient(#17121f0a 1px, transparent 1px), linear-gradient(90deg, #17121f0a 1px, transparent 1px);
  background-size: 44px 44px;
  background-position: center;
  mask-image: radial-gradient(ellipse closest-side, #000 25%, transparent 100%);
  -webkit-mask-image: radial-gradient(ellipse closest-side, #000 25%, transparent 100%);
  opacity: var(--drift-stage, 1);
  pointer-events: none;
}
/* overflow stays visible: the facets and their wake fly in from well outside
   the stage, and only the hero card itself should clip them */
.drift-art svg { display: block; position: relative; width: 100%; height: 100%; overflow: visible; }
.drift-whole { fill: var(--drift-ink); }
.drift-pieces { visibility: hidden; fill: var(--drift-ink); }
.drift-piece { opacity: 0; }
.drift-wind { visibility: hidden; pointer-events: none; }
.drift-wind-stream { fill: none; stroke: var(--drift-accent-deep); stroke-linecap: round; }
.drift-wind-mote { fill: var(--drift-accent-deep); }
.drift-wind-mote.is-ink { fill: var(--drift-ink); }
.drift-on .drift-pieces { visibility: visible; }
.drift-on .drift-whole { visibility: hidden; }

.drift-link { width: 1px; height: 17px; align-self: center; background: linear-gradient(var(--drift-line), var(--drift-accent-deep)); }

/* above the stage: facets arriving from below pass behind the words */
.drift-text { position: relative; z-index: 1; width: min(680px, 100%); }
.drift-intro { will-change: transform; }
.drift-intro[hidden], .drift-story[hidden], .drift-cta[hidden] { display: none; }
.drift-headline {
  margin: 0;
  font-family: var(--drift-serif);
  font-size: clamp(36px, 4.2vw, 58px);
  font-weight: 400;
  line-height: 1.07;
  letter-spacing: -.015em;
  text-wrap: balance;
}
.drift-headline .drift-last-word { color: var(--drift-accent-deep); }
.drift-cta { margin-top: 22px; }

.drift-story { --story-gap: 12px; }
.drift-story blockquote {
  margin: 0 0 var(--story-gap);
  font-family: var(--drift-serif);
  font-size: clamp(32px, 3.6vw, 46px);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -.015em;
  text-wrap: balance;
}
.drift-story h2 {
  margin: 0 0 var(--story-gap);
  color: var(--drift-accent-deep);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: .01em;
  text-wrap: balance;
}
.drift-story p { max-width: 550px; margin: 0 auto; color: var(--drift-muted); font-size: 14px; line-height: 1.6; text-wrap: pretty; }

/* Letter overlays for the flying text; drift.js measures and positions them. */
.drift-fly { position: relative; }
.drift-fly-placeholder { visibility: hidden; }
.drift-fly-overlay { position: absolute; inset: 0; pointer-events: none; overflow: visible; }
.drift-fly-char { position: absolute; display: block; white-space: pre; text-align: left; transform-origin: 50% 50%; backface-visibility: hidden; }

/* The chapters as plain reading. Shown when the scroll sequence is off
   (reduced motion, or no scripting); drift.js also reads its copy from here. */
.drift-guide { max-width: 1048px; margin: 0 auto; padding: 96px 16px 0; color: var(--drift-ink); }
.drift-on .drift-guide { display: none; }
/* the next section's pull-up closes the gap a shrunken hero card leaves; with
   the guide in between there is no such gap to close */
html:not(.drift-on) .drift-guide + section { margin-top: 0 !important; }
.drift-guide > h2 {
  margin: 0 0 48px;
  font-family: var(--drift-serif);
  font-size: 48px;
  font-weight: 400;
  line-height: 56px;
  letter-spacing: -.015em;
  text-align: center;
  text-wrap: balance;
}
.drift-guide-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr)); gap: 16px; }
.drift-entry { border-radius: 24px; padding: 32px; background: #f4f5f7; }
.drift-entry > span { color: var(--drift-accent-deep); font: 400 10.5px/1 var(--font-family-code); letter-spacing: .12em; }
.drift-entry blockquote { margin: 18px 0 10px; font-family: var(--drift-serif); font-size: 28px; font-weight: 400; line-height: 1.15; letter-spacing: -.015em; text-wrap: balance; }
.drift-entry h3 { margin: 0 0 12px; color: var(--drift-accent-deep); font-family: var(--font-family-text); font-size: 15px; font-weight: 500; }
.drift-entry p { margin: 0; color: var(--drift-muted); font-family: var(--font-family-text); font-size: 15px; line-height: 1.6; }

@media (min-width: 768px) {
  .drift-guide { padding-left: 32px; padding-right: 32px; }
}
@media (max-width: 760px) {
  .drift-murmur span { font-size: calc(12px * var(--k, 1)); }
  .drift-murmur span:nth-child(1) { --x: -9; --y: -34; }
  .drift-murmur span:nth-child(2) { --x: 10; --y: -27; }
  .drift-murmur span:nth-child(3) { --x: -5; --y: -20; }
  .drift-murmur span:nth-child(4) { --x: 9; --y: -13; }
  .drift-murmur span:nth-child(5) { --x: -8; --y: 11; }
  .drift-murmur span:nth-child(6) { --x: 11; --y: 18; }
  .drift-murmur span:nth-child(7) { --x: -6; --y: 25; }
  .drift-murmur span:nth-child(8) { --x: 7; --y: 32; }
  .drift-murmur span:nth-child(9) { --x: -10; --y: 39; }
  .drift-composition { inset: 36px 7%; grid-template-rows: minmax(0, 380px) 22px 228px; }
  .drift-art { width: 116%; justify-self: center; }
  .drift-headline { font-size: clamp(32px, 8.5vw, 47px); }
  .drift-cta { margin-top: 18px; }
  .drift-story { --story-gap: 10px; }
  .drift-story blockquote { font-size: clamp(27px, 7.5vw, 32px); }
  .drift-story h2 { font-size: 15px; }
  .drift-story p { font-size: 13px; line-height: 1.55; }
  .drift-guide > h2 { font-size: 36px; line-height: 1.15; }
}
@media (max-height: 600px) {
  .drift-composition { top: 24px; bottom: 24px; grid-template-rows: minmax(0, 390px) 16px 208px; }
  .drift-headline { font-size: 34px; }
  .drift-story { --story-gap: 9px; }
  .drift-story blockquote { font-size: 26px; }
  .drift-story h2 { font-size: 14px; }
  .drift-story p { font-size: 13px; }
}
@media (max-height: 500px) {
  .drift-composition { top: 16px; bottom: 16px; grid-template-rows: minmax(0, 390px) 12px 174px; }
  .drift-headline { font-size: 28px; }
  .drift-cta { margin-top: 12px; }
  .drift-story { --story-gap: 7px; }
  .drift-story blockquote { font-size: 24px; }
  .drift-story h2 { font-size: 13px; }
  .drift-story p { font-size: 11px; line-height: 1.4; }
}
@media (prefers-reduced-motion: reduce) {
  .drift-wind { display: none; }
}
