/* Drift hero — the nine-facet 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);
}

/* The scroll distance of the nine chapters. behaviours.js starts the card
   shrink and the manifesto scrub only once this much has been scrolled. */
#drift-spacer { height: 0; }
.drift-on #drift-spacer { height: 1480svh; }

/* 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;
}
#hero-canvas.hx-done .drift-hero { visibility: hidden; }
.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 the nine 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). drift.js builds
   them from the guide copy and 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 nine 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-on #drift-spacer { height: 1630svh; }
  .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; }
}
