/* ═══════════════════════════════════════════════════════════
   Ajeto — landing
   Type:  Funnel Display (headlines) · Figtree (body / notes)

   The hero video is anchored to the bottom and dissolves upward —
   sharp at the horizon, blurred through the middle, gone by the
   time it reaches the copy. Its own top edge is #163054, which is
   exactly the stage background there, so the blend has no seam.
   ═══════════════════════════════════════════════════════════ */

/* The palette comes from tokens.css, which mirrors the product's. The
   short names below are this page's own vocabulary; each one says
   where its value comes from.

   Two groups do NOT take the app's value:

   · The sky. Those three are eyedropped from the top edge of the
     artwork so the illustration can dissolve into the page without a
     seam. They answer to the picture, not to the brand — the app has
     no equivalent and shouldn't get one.

   · The four accents marked "artwork". They were sampled off the
     illustration too, and each sits a little warmer and lighter than
     the app's version of the same colour, so the buttons agree with
     the sunset behind them. Flipping them to the app values is a one
     line change per token and a visible one; the deltas are in the
     comments. See the palette note in the README.

   The var() fallbacks are the app's own convention (it writes
   var(--brand-primary, #F57C00) throughout) and they mean this
   stylesheet still renders on its own if tokens.css is missing. */

:root {
  --navy:      var(--ajeto-navy-700, #2B364F);
  --cream:     var(--ajeto-off-white, #FFFDF8);   /* app --background */

  --orange:    #FC911D;   /* artwork · app --ajeto-orange       #F57C00 */
  --amber:     #FFB052;   /* artwork · app --ajeto-orange-light #F9A547 */
  --gold:      #FFD664;   /* artwork · app --ajeto-sunshine     #FFCD57 */
  --teal:      #62BCB8;   /* artwork · app --ajeto-teal         #2EC4B6 */
  --mint:      var(--ajeto-teal-light, #A5F0E0);

  --sky-deep:  #2F4A6C;   /* sampled from the artwork's top edge */
  --sky-night: #21375A;

  --ease:      cubic-bezier(.22, 1, .36, 1);
  --ease-soft: cubic-bezier(.33, 1, .68, 1);

  --font-display: var(--ajeto-font-display, "Funnel Display", "Figtree", sans-serif);
  --font-body:    var(--ajeto-font-body, "Figtree", ui-sans-serif, system-ui, sans-serif);
  --radius-pill:  var(--ajeto-r-pill, 999px);

  --bar-h: 84px;
}

/* The live page uses .theme-flat. The other three are kept only so the
   archived style variants in /archive/pages still render if restored;
   each one's sky tokens are sampled from the top edge of its own
   artwork, so the dissolve never shows a seam. */

body.theme-paint {
  --sky-deep:  #2F4A6C;
  --sky-night: #21375A;
  --sky-mid:   #294364;
}

body.theme-flat {
  --sky-deep:  #163054;
  --sky-night: #10233F;
  --sky-mid:   #132B4B;
}

body.theme-minimal {
  --sky-deep:  #1E3356;
  --sky-night: #16294A;
  --sky-mid:   #1A2E50;
}

/* the vector scene carries its own sky, so the page background only has
   to match its top stop exactly — no gradient of its own */
body.theme-vector {
  --sky-deep:  #21375A;
  --sky-night: #21375A;
  --sky-mid:   #21375A;
}

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; margin: 0; }

/* anchor jumps have to clear the fixed bar */
html { scroll-padding-top: var(--bar-h); }

body {
  background: linear-gradient(
    180deg,
    var(--sky-night) 0%,
    var(--sky-mid) 40%,
    var(--sky-deep) 72%,
    var(--sky-deep) 100%
  );
  color: var(--cream);
  font-family: var(--font-body);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow: hidden;
}

a { text-decoration: none; color: inherit; }


/* ── Stage ──────────────────────────────────────────────── */

.stage {
  position: relative;
  min-height: 100svh;
  height: 100svh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}


/* ── Scene ──────────────────────────────────────────────── */

.scene {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

/* De onderrand van het beeld was een rechte snede: teal die pal op het
   creme van de pagina stuit. Onder de witte plaat viel dat niet op; nu
   de plaat weg is, dooft het beeld uit naar precies die grondkleur. De
   laag ligt in .scene, dus onder de kop en de knoppen. */
.scene::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: clamp(70px, 12vh, 130px);
  background: linear-gradient(180deg, rgba(255, 253, 248, 0), var(--cream));
  pointer-events: none;
}

.scene__art {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  /* a hair of extra height so the parallax drift never bares the edge */
  padding-bottom: 0;
  will-change: translate;
}

.scene__art picture { display: block; }

/* ── De bus in de hero niet in de waas ────────────────────
   Bij binnenkomst staat de bus linksonder, met zijn wielen op 95% van de
   hoogte van het beeld. De uitvloeiing onderaan de hero (12vh naar het
   creme) liep over hem heen: een witte waas over de bus (Nathan, 5 en
   6 oktober). Het beeld gaat daarom een stuk omhoog (--til), de
   uitvloeiing begint pas onder de wielen en loopt alleen over de strook
   weg eronder (2,5vw: 4,5% van een beeld dat 100vw breed is), en daaronder
   is het effen creme. Uit ronde 8 en 9. Die effen strook was tot
   16 oktober 10svh; Nathan wilde minder wit onderaan, dus nu ruwweg een
   derde. De uitvloeiing hangt aan de onderrand van het beeld, dus de bus
   blijft vrij. */
@media (min-width: 1025px) {
  body { --til: clamp(20px, 3.5svh, 40px); }
  .scene__art { bottom: var(--til); }
  .scene::after {
    height: calc(var(--til) + 2.5vw);
    background: linear-gradient(
      180deg,
      rgba(255, 253, 248, 0) 0,
      rgba(255, 253, 248, .14) .6vw,
      rgba(255, 253, 248, .5) 1.25vw,
      rgba(255, 253, 248, .86) 1.9vw,
      var(--cream) 2.5vw
    );
  }
}

.art {
  display: block;
  width: 100%;
  height: auto;
  /* pushed a touch wider than the stage so the drift has room */
  min-height: 46svh;
  object-fit: cover;
  object-position: 50% 100%;
}

/* sharp layer — fully opaque only from the horizon down */
.art--sharp {
  position: relative;
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    rgba(0, 0, 0, .05) 26%,
    rgba(0, 0, 0, .20) 44%,
    rgba(0, 0, 0, .48) 58%,
    rgba(0, 0, 0, .82) 70%,
    #000 79%,
    #000 100%
  );
  mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    rgba(0, 0, 0, .05) 26%,
    rgba(0, 0, 0, .20) 44%,
    rgba(0, 0, 0, .48) 58%,
    rgba(0, 0, 0, .82) 70%,
    #000 79%,
    #000 100%
  );
}

/* blurred twin — only lives in the dissolve band, so the artwork
   doesn't just fade, it softens as it melts into the sky */
.art--blur {
  position: absolute;
  inset: 0;
  height: 100%;
  filter: blur(30px) saturate(1.14);
  transform: scale(1.04);
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 10%,
    rgba(0, 0, 0, .38) 34%,
    rgba(0, 0, 0, .62) 52%,
    rgba(0, 0, 0, .34) 68%,
    transparent 80%
  );
  mask-image: linear-gradient(
    to bottom,
    transparent 10%,
    rgba(0, 0, 0, .38) 34%,
    rgba(0, 0, 0, .62) 52%,
    rgba(0, 0, 0, .34) 68%,
    transparent 80%
  );
}

/* keeps the sky dusky where the copy sits, without touching the
   glow at the horizon */
.scene__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(35, 58, 92, .00) 0%,
    rgba(35, 58, 92, .40) 34%,
    rgba(35, 58, 92, .34) 52%,
    rgba(35, 58, 92, .12) 68%,
    rgba(35, 58, 92, 0)   80%
  );
}

/* warm bloom lifting off the horizon into the night sky */
.scene__glow {
  position: absolute;
  left: 50%;
  bottom: 6%;
  width: 130%;
  height: 78%;
  transform: translateX(-50%);
  background: radial-gradient(
    50% 52% at 56% 88%,
    rgba(255, 190, 96, .32) 0%,
    rgba(255, 170, 80, .16) 34%,
    rgba(98, 188, 184, .07) 58%,
    rgba(40, 63, 94, 0) 76%
  );
  mix-blend-mode: screen;
}

/* barely-there film grain — kills gradient banding */
/* the flat treatments read as clean vector, so they get only enough
   grain to stop the sky banding */
.theme-flat .scene__grain    { opacity: .10; }
.theme-minimal .scene__grain { opacity: .08; }
.theme-vector .scene__grain  { opacity: .06; }

/* The vector scene is a complete illustration with its own sky, so it
   needs no dissolve mask — masking would only wash out the flat colour
   it is built on. */
.theme-vector .art--sharp {
  -webkit-mask-image: none;
  mask-image: none;
}

/* a warm bloom reads as light on a painting, but as dirt on flat colour */
.theme-minimal .scene__glow,
.theme-vector .scene__glow { display: none; }

.scene__grain {
  position: absolute;
  inset: -50%;
  opacity: .13;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}


/* ── Top bar ────────────────────────────────────────────── */

/* Fixed to the window, not to the stage: the stage is clipped and gets
   transformed during the handover, either of which would take the bar
   with it. It sits above .after (z-index 1) so the light section slides
   underneath the glass rather than over it. */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  height: var(--bar-h);
  padding: 0 clamp(20px, 4vw, 52px);
  display: flex;
  align-items: center;
  gap: 24px;
}

/* The glass is a layer of its own, so fading it in never touches the
   opacity of the bar's contents. Over the hero it is absent — the sky
   is already dark enough — and it fades in the moment you leave the
   top, staying smoked navy so the cream text and the light lockup
   read against the cream section below just as well. */
.topbar::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    180deg,
    rgba(22, 48, 84, .24),
    rgba(22, 48, 84, .16)
  );
  /* barely a tint — the blur does the work, and the small brightness
     cut only keeps the sky from washing out the cream type */
  -webkit-backdrop-filter: blur(16px) saturate(150%) brightness(.84);
  backdrop-filter: blur(16px) saturate(150%) brightness(.84);
  border-bottom: 1px solid rgba(255, 253, 248, .10);
  opacity: 0;
  transition: opacity .45s var(--ease-soft);
}

/* no backdrop-filter: there is no blur to lean on, so the tint has to
   carry the separation on its own — still light, just less see-through */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .topbar::before {
    background: linear-gradient(
      180deg,
      rgba(19, 41, 72, .46),
      rgba(19, 41, 72, .36)
    );
  }
}

body.is-pinned .topbar::before { opacity: 1; }

/* Over the night section the bar and the page behind it are the same
   navy, so the pane adds nothing and its hairline reads as a frame
   drawn around nothing. Take the glass off entirely there and let the
   bar sit straight on the dark. */
body.bar-dark .topbar::before { opacity: 0; }

.brand { flex: 0 0 auto; display: block; line-height: 0; }

.brand img {
  height: 30px;
  width: auto;
  display: block;
}

.nav {
  flex: 1 1 auto;
  display: flex;
  justify-content: center;
  gap: clamp(6px, 1.6vw, 18px);
}

.nav a {
  position: relative;
  padding: 9px 14px;
  border-radius: var(--radius-pill);
  font-size: 15px;
  font-weight: 500;
  color: rgba(255, 253, 248, .80);
  transition: color .28s var(--ease-soft), background-color .28s var(--ease-soft);
}

.nav a::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 3px;
  width: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--gold);
  transform: translateX(-50%);
  transition: width .34s var(--ease);
}

.nav a:hover { color: var(--cream); background: rgba(255, 253, 248, .08); }
.nav a:hover::after { width: 18px; }

/* Vijf links (sinds Product erbij kwam): net boven de telefoonbreedte is
   het krap, dus daar iets kleiner in plaats van over twee regels. */
.nav a { white-space: nowrap; }
@media (min-width: 901px) and (max-width: 1180px) {
  .nav { gap: 2px; }
  .nav a { padding: 9px 9px; font-size: 14px; }
}

.topbar__actions {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
}


/* Een sprong naar een anker binnen dezelfde pagina glijdt, zodat je ziet
   waar je terechtkomt. Het scrollmodel van de hero staat dit toe: alleen
   de hero is vastgezet, de pagina zelf scrolt gewoon. De demo plaatst zijn
   scherm bewust wél in één keer (window.scrollTo met behavior "auto"),
   want daar mag geen seconde van de scene af. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* zodat een anker niet onder de vastgezette topbalk landt */
[id] { scroll-margin-top: calc(var(--bar-h, 84px) + 16px); }


/* ── Buttons ────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  border-radius: var(--radius-pill);
  font-family: var(--font-body);
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  transition:
    transform .3s var(--ease),
    box-shadow .3s var(--ease),
    background-color .3s var(--ease-soft),
    color .3s var(--ease-soft),
    border-color .3s var(--ease-soft);
}

.btn:active { transform: translateY(1px) scale(.99); }

.btn--ghost {
  padding: 10px 18px;
  font-size: 15px;
  color: rgba(255, 253, 248, .90);
  border: 1px solid rgba(255, 253, 248, .22);
}
.btn--ghost:hover {
  background: rgba(255, 253, 248, .10);
  border-color: rgba(255, 253, 248, .48);
  color: var(--cream);
}

.btn--solid {
  padding: 11px 20px;
  font-size: 15px;
  color: var(--cream);
  background: linear-gradient(135deg, var(--orange) 0%, #F7830C 100%);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, .28) inset,
    0 6px 18px -6px rgba(180, 92, 4, .75);
}
.btn--solid:hover {
  transform: translateY(-1px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, .34) inset,
    0 12px 26px -8px rgba(180, 92, 4, .9);
}

.btn--primary {
  padding: 17px 30px;
  font-size: 17px;
  letter-spacing: -.01em;
  color: var(--cream);
  background: linear-gradient(135deg, #FFA43A 0%, var(--orange) 52%, #F07E08 100%);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, .32) inset,
    0 10px 26px -8px rgba(180, 92, 4, .75),
    0 26px 60px -22px rgba(0, 0, 0, .6);
}
/* de demoknop op de lichte secties: dezelfde oranje pil als in de hero,
   zodat er maar één demoknop bestaat. Alleen de slagschaduw is lichter,
   want hier ligt geen donkere lucht achter waar hij tegenaan moet duwen. */
.btn--secondary {
  padding: 17px 28px;
  font-size: 17px;
  letter-spacing: -.01em;
  color: var(--cream);
  background: linear-gradient(135deg, #FFA43A 0%, var(--orange) 52%, #F07E08 100%);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, .32) inset,
    0 10px 26px -10px rgba(180, 92, 4, .7);
}
.btn--secondary:hover {
  transform: translateY(-2px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, .38) inset,
    0 18px 36px -12px rgba(180, 92, 4, .85);
}

.btn--primary svg,
.btn--secondary svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform .34s var(--ease);
}
.btn--primary:hover {
  transform: translateY(-2px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, .38) inset,
    0 18px 36px -10px rgba(180, 92, 4, .85),
    0 34px 70px -24px rgba(0, 0, 0, .65);
}
.btn--primary:hover svg,
.btn--secondary:hover svg { transform: translateX(4px); }

/* de stille knop op de lichte grond: een tekstlink met knopmaat, zodat
   hij naast de oranje pil kan staan zonder ermee te concurreren */
.btn--link {
  padding: 17px 10px;
  font-size: 17px;
  font-weight: 600;
  color: rgba(43, 54, 79, .86);
  text-decoration: underline;
  text-decoration-color: rgba(43, 54, 79, .32);
  text-underline-offset: 5px;
}
.btn--link:hover {
  color: var(--navy);
  text-decoration-color: rgba(43, 54, 79, .7);
}
.btn--link svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform .34s var(--ease);
}
.btn--link:hover svg { transform: translateY(3px); }

.btn--quiet {
  padding: 17px 26px;
  font-size: 17px;
  color: rgba(255, 253, 248, .94);
  background: rgba(255, 253, 248, .07);
  border: 1px solid rgba(255, 253, 248, .20);
  backdrop-filter: blur(8px);
}
.btn--quiet:hover {
  transform: translateY(-2px);
  background: rgba(255, 253, 248, .13);
  border-color: rgba(255, 253, 248, .42);
}

/* de pijl in "Wat doet Ajeto?" in de hero. Zonder deze regel had hij geen
   maat en geen lijn: op een telefoon werd hij 149 px groot en zwart (de knop
   185 px hoog), op desktop 0 px en dus onzichtbaar. */
.btn--quiet svg {
  flex: none;
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform .34s var(--ease);
}
.btn--quiet:hover svg { transform: translateY(3px); }


/* ── Hero copy ──────────────────────────────────────────── */

.hero {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  /* the bar no longer sits in this column, so its height is held open
     here instead — the copy stays centred exactly where it was */
  padding: var(--bar-h) 24px clamp(110px, 30vh, 330px);
}

.headline {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(38px, 5.4vw, 76px);
  line-height: 1.16;
  letter-spacing: -.035em;
  color: var(--cream);
  max-width: 24ch;
  text-wrap: balance;
}

.headline__line { display: block; }

.headline__line--accent {
  background: linear-gradient(100deg, var(--gold) 0%, var(--amber) 45%, var(--orange) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* background-clip: text paints only the line box, so the descenders
     of "j" and "g" get sheared off. Grow the box, then pull the extra
     space back out of the layout. */
  padding-block: .08em .18em;
  margin-block: -.08em -.18em;
}

.sub {
  margin: 22px 0 0;
  max-width: 52ch;
  font-size: clamp(16px, 1.35vw, 19px);
  line-height: 1.62;
  font-weight: 400;
  color: rgba(255, 253, 248, .78);
  text-shadow: 0 1px 14px rgba(24, 38, 62, .38);
}

/* break on the sentence, never mid-clause */
@media (min-width: 700px) {
  .sub span { display: block; }
}

.cta {
  margin-top: 34px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 13px;
}

.micro {
  margin: 24px 0 0;
  display: flex;
  align-items: center;
  gap: 11px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 11.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(255, 253, 248, .70);
  text-shadow: 0 1px 12px rgba(24, 38, 62, .55);
}

.micro .dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--teal);
}


/* ═══ Scroll-scrubbed hero ══════════════════════════════════
   Desktop only. The stage is pinned while a tall spacer scrolls
   past it; that scroll distance drives the video's currentTime.
   The scrub finishes before the spacer does: the last stretch is a
   handover, in which the section below rides up over the pinned hero
   while the van settles. So the reader never sits at a finished
   animation waiting to be let go.

   Phones and tablets never load the video at all — they get the
   still, and an ordinary page that scrolls straight through.     */

body.is-scrolly {
  overflow: visible;
  height: auto;
  background: var(--cream);
}

.scrolly {
  position: relative;
}

/* The still is the base layer on every screen: it sets the height of
   .scene__art and doubles as the video's poster, so desktop paints
   instantly too. The video is laid over it and only exists above the
   tablet breakpoint — below that it is never given a src at all. */
.art--motion { display: none; }

@media (min-width: 1025px) {
  .art--motion {
    display: block;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  /* ~2 viewports past the first screenful: 1.6 of scrubbing, then
     0.6 of handover. Keep in sync with SCRUB_END in main.js and with
     the negative margin on .after below. */
  .scrolly { height: 300svh; }
}

.is-scrolly .stage {
  /* the page behind is cream for the section below, so the sky the
     artwork dissolves into has to live on the stage itself */
  background: linear-gradient(
    180deg,
    var(--sky-night) 0%,
    var(--sky-mid) 40%,
    var(--sky-deep) 72%,
    var(--sky-deep) 100%
  );
}

@media (min-width: 1025px) {
  .is-scrolly .stage {
    position: sticky;
    top: 0;
    height: 100svh;
  }

  /* the copy steps aside as the van leaves */
  .is-scrolly .hero {
    opacity: var(--copy-fade, 1);
    transform: translateY(calc((1 - var(--copy-fade, 1)) * -26px));
    will-change: opacity, transform;
  }

  /* Handover: the section below is pulled up over the tail of the
     spacer, so it starts rising while the van is still settling.
     -60svh against a 300svh spacer means its top edge reaches the
     fold at 140svh — a touch before the scrub ends at 160svh.

     Dit hangt aan de sectie die direct onder de hero staat. Sinds de
     volgorde van Sam is dat weer .pageflow; het uitlegblok staat nu na
     de dag. Staat er ooit weer iets anders direct onder de hero, dan
     verhuist deze regel mee, anders schuift .pageflow over dat blok. */
  body.is-scrolly .pageflow {
    margin-top: -60svh;
  }

  /* and the hero drifts up a little to meet it, so the two layers
     move at different speeds instead of one sliding over a still */
  .is-scrolly .stage {
    transform: translate3d(0, calc(var(--release, 0) * -7svh), 0);
  }
}

video.art {
  background: transparent;
  pointer-events: none;
}


/* ── Everything past the hero ───────────────────────────── *
   One cream ground for all the sections below the hero, so the route
   can be painted on it and still sit underneath their content. The
   sections themselves are transparent; this is also the layer that
   rides up over the pinned hero during the handover, which is why the
   negative margin lives here and not on .after any more.           */

.pageflow {
  position: relative;
  z-index: 1;
  /* De grond vertelt de dag één keer: probleem in het ochtendgloren,
     aanvraag om 07:00, klantuitvraag om 09:15 en schouw om 10:45.
     Daarna neemt de schemerband het over en volgt de enige nacht.

     Elke stop staat als "sectie plus fractie van haar hoogte", met de
     variabelen die main.js per sectie zet (--y-<id>-top, -h). De
     fallbacks zijn de gemeten waarden, dus zonder JavaScript ziet de
     pagina er hetzelfde uit. De onderste kleur is de gemeten bovenrand
     van dusk-thuis, niet een gok. */
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='.22'/%3E%3C/svg%3E"),
    linear-gradient(
      180deg,
      /* doorzichtig aan de bovenrand: deze laag schuift tijdens de
         handover over de staart van de hero, en een harde creme rand
         zou daar als een lijn over de video lopen */
      rgba(255, 241, 216, 0) 0,
      #FFF1D8 150px,
      #FFE8C4 calc(var(--y-probleem-top, 5.02%) + var(--y-probleem-h, 21.09%) * .15),
      #FFDCA8 calc(var(--y-probleem-top, 5.02%) + var(--y-probleem-h, 21.09%) * .78),
      #F0A868 calc(var(--y-dag-top, 26.11%) + var(--y-dag-h, 24.63%) * .38),
      #FFE2B4 calc(var(--y-dag-top, 26.11%) + var(--y-dag-h, 24.63%) * .95),
      #FFF9EE calc(var(--y-klant-top, 50.74%) + var(--y-klant-h, 24.63%) * .30),
      #FFFDF8 calc(var(--y-klant-top, 50.74%) + var(--y-klant-h, 24.63%) * .96),
      #FFFDF8 calc(var(--y-schouw-top, 75.37%) + var(--y-schouw-h, 24.63%) * .60),
      #FFF4DA 100%
    );
  background-size: 200px 200px, 100% 100%;
  background-blend-mode: soft-light, normal;


}


/* ── The route ──────────────────────────────────────────── *
   A road threading the length of the page. The faint line is the
   whole way ahead — the plan — and the warm one is how far you have
   travelled; main.js drives its dash offset straight off scroll
   position, so it draws on the way down and retracts on the way up
   with no animation of its own. The stops light as it passes them.

   preserveAspectRatio is none on purpose: the path is meant to
   stretch to whatever height the page turns out to be, and
   non-scaling-stroke keeps the line an even weight while it does.  */

.route {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

.route__svg {
  width: 100%;
  height: 100%;
  display: block;
  /* De weg begint zacht onder de bovenrand en vloeit uit achter de
     laatste kaart van de dag (--tail-*, gezet door markNight in main.js).
     Hier stonden ook de stops voor de slapende weg (--sleep-*, --wake-*).
     Die worden sinds september niet meer gezet en vielen dan terug op
     100%, en CSS schuift elke latere stop mee naar minstens die waarde:
     daardoor deed ook het uitvloeien niets en stak de weg onder de laatste
     kaart uit tot de onderrand van de dag. */
  -webkit-mask-image: linear-gradient(
    180deg,
    transparent 0, #000 260px,
    #000 var(--tail-from, 100%),
    transparent var(--tail-to, 100%),
    transparent 100%
  );
  mask-image: linear-gradient(
    180deg,
    transparent 0, #000 260px,
    #000 var(--tail-from, 100%),
    transparent var(--tail-to, 100%),
    transparent 100%
  );
}

.route__edge,
.route__plan,
.route__dash {
  fill: none;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

/* The road is drawn in three layers: a darker outline underneath, the
   asphalt bed on top of it (leaving a crisp edge line either side),
   and the cream centre line. Wide enough to read as a road, and it
   ducks under the art panels the way a road passes behind buildings. */
.route__edge {
  stroke: rgba(43, 54, 79, .30);
  stroke-width: 41;
}

.route__plan {
  stroke: #E7E4DB;
  stroke-width: 35;
}

/* the centre line, painted on the bed */
.route__dash {
  stroke: rgba(255, 253, 248, .95);
  stroke-width: 2.8;
  stroke-dasharray: 10.5 14;
}

/* ── Section released after the pinned hero ─────────────── */

.after {
  position: relative;
  z-index: 1;
  color: var(--navy);
  padding: clamp(72px, 12vh, 140px) clamp(20px, 5vw, 64px) clamp(90px, 14vh, 170px);
}

/* Square art left, copy right. The art column is capped so the picture
   never outgrows the text beside it; below the tablet break the two
   simply stack, art first — it carries the idea faster than the
   heading does. */
.after__inner {
  max-width: 1140px;
  margin: 0 auto;
  display: grid;
  gap: clamp(34px, 5vw, 72px);
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  align-items: center;
}

.after__art {
  margin: 0;
  /* square corners — the sky in the art already matches the hero's
     navy, so no border or plate is needed to hold the edge either */
  overflow: hidden;
  box-shadow: var(--ajeto-shadow-lg, 0 8px 32px rgba(15, 23, 42, .08));
}

.after__art {
  position: relative;
}

.after__art picture { display: block; }

.after__art img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

/* Ground for the cards, and the only thing that softens the picture.
   Its own mask keeps both the wash and the blur in the lower half, so
   the sunrise above stays sharp and visible the whole way through —
   blurring the whole plate left nothing to look at.

   None of this section is tied to scroll position. Crossing a threshold
   flips .chores-in on and the whole thing plays itself out at its own
   pace; scrolling on does not push it along and stopping does not hold
   it half-done. Crossing back up flips it off, so it can play again. */
.after__art::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(16, 35, 63, 0) 0%,
    rgba(16, 35, 63, .52) 46%,
    rgba(16, 35, 63, .72) 100%
  );
  -webkit-mask-image: linear-gradient(180deg, transparent 12%, #000 44%, #000 100%);
  mask-image: linear-gradient(180deg, transparent 12%, #000 44%, #000 100%);
  opacity: 0;
  -webkit-backdrop-filter: blur(0px);
  backdrop-filter: blur(0px);
  transition:
    opacity .62s var(--ease-soft),
    -webkit-backdrop-filter .62s var(--ease-soft),
    backdrop-filter .62s var(--ease-soft);
}

.after__art.chores-in::after {
  opacity: 1;
  -webkit-backdrop-filter: blur(7px);
  backdrop-filter: blur(7px);
}

/* Clear the last one and the wash goes with it: the morning comes back
   into focus. That is the whole argument of the section in one move, so
   it is given a slower, later curve than the one that put it there. */
.after__art.chores-in.chores-clear::after {
  opacity: 0;
  -webkit-backdrop-filter: blur(0px);
  backdrop-filter: blur(0px);
  transition:
    opacity .9s var(--ease-soft) .18s,
    -webkit-backdrop-filter .9s var(--ease-soft) .18s,
    backdrop-filter .9s var(--ease-soft) .18s;
}

.chores {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  /* Een kolom, niet een rij: de slotregel hoort onder de stapel te
     staan. Als rij zou hij naast de lijst komen en die smaller maken. */
  flex-direction: column;
  justify-content: flex-end;
  padding: clamp(14px, 3.4%, 26px);
  pointer-events: none;
}

.chores ul {
  --chore-gap: clamp(6px, 1.4%, 10px);

  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  width: 100%;
}

/* The rows are collapsed to nothing until the list arrives, then all
   open together. The 0fr → 1fr track is what lets them animate to their
   own height without anyone measuring it, and because the list is
   anchored to the bottom of the plate, opening pushes it up into the
   picture rather than down away from it. */
.chores li {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .5s var(--ease);
}

.after__art.chores-in .chores li:not(.is-gone) { grid-template-rows: 1fr; }

/* The padding is the gap, so it has to go with the row. A collapsed
   track alone leaves it behind, and seven cleared rows then add up to a
   band of nothing at the bottom of the pile. */
.chore-slot {
  overflow: hidden;
  min-height: 0;
  padding-top: 0;
  transition: padding-top .5s var(--ease);
}

.after__art.chores-in .chores li:not(.is-gone) .chore-slot {
  padding-top: var(--chore-gap);
}

/* the last two sit slightly askew, so the pile reads as growing rather
   than as a tidy list someone is working through */
.chores li:nth-child(6) .chore { rotate: -.6deg; }
.chores li:nth-child(7) .chore { rotate: .7deg; }

.chore {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  margin: 0;
  padding: clamp(9px, 1.9%, 13px) clamp(12px, 2.7%, 17px);
  border: 0;
  /* zelfde taal als de kaarten verderop: rechte hoeken, een rand links
     die de status draagt en een verschoven harde schaduw */
  border-radius: 0;
  border-left: 5px solid rgba(30, 42, 69, .32);
  box-shadow: 4px 4px 0 rgba(30, 42, 69, .17);
  background: #FBF9F4;
  color: var(--ajeto-navy, #1E2A45);
  font-family: var(--font-body);
  font-size: clamp(13px, 3.1%, 16px);
  font-weight: 600;
  letter-spacing: -.01em;
  line-height: 1.25;
  text-align: left;
  box-shadow: 0 6px 18px -8px rgba(9, 20, 38, .55);
  cursor: pointer;
  /* the wrapper is inert so it never eats a scroll; the cards are not */
  pointer-events: auto;

  opacity: 0;
  translate: 0 12px;
  transition:
    opacity .34s var(--ease-soft),
    translate .34s var(--ease),
    scale .3s var(--ease),
    background-color .3s var(--ease-soft),
    box-shadow .3s var(--ease-soft);
}

/* a beat behind the rows, so the cards land into space already made */
.after__art.chores-in .chores li:not(.is-gone) .chore {
  opacity: 1;
  translate: 0 0;
  transition:
    opacity .46s var(--ease-soft) .16s,
    translate .52s var(--ease) .16s,
    scale .3s var(--ease),
    background-color .3s var(--ease-soft),
    box-shadow .3s var(--ease-soft);
}

.chore:hover { translate: 2px 0; background: var(--cream); }
.chore:focus-visible {
  outline: 2px solid rgba(252, 145, 29, .8);
  outline-offset: 2px;
}

/* every box empty — none of it is done */
.chore__box {
  position: relative;
  flex: 0 0 auto;
  width: 13px;
  height: 13px;
  border-radius: 0;
  border: 1.5px solid rgba(252, 145, 29, .8);
  transition:
    background-color .25s var(--ease-soft),
    border-color .25s var(--ease-soft);
}

/* the tick is drawn, not typed: two borders on a rotated box, scaled in */
.chore__box::after {
  content: "";
  position: absolute;
  left: 3.5px;
  top: .5px;
  width: 4px;
  height: 8px;
  border: solid var(--cream);
  border-width: 0 1.8px 1.8px 0;
  rotate: 45deg;
  scale: 0;
  transition: scale .28s var(--ease);
}

.chore__t {
  position: relative;
  transition: color .3s var(--ease-soft);
}

/* the strike is a line that draws across rather than a text-decoration
   that simply switches on */
.chore__t::after {
  content: "";
  position: absolute;
  left: 0;
  top: 52%;
  width: 100%;
  height: 1.5px;
  background: currentColor;
  border-radius: 2px;
  transform-origin: 0 50%;
  scale: 0 1;
  transition: scale .32s var(--ease);
}

/* ── resolved ── */

.chore.is-done { background: rgba(255, 253, 248, .72); }
.chore.is-done .chore__box {
  background: var(--orange);
  border-color: var(--orange);
}
.chore.is-done .chore__box::after { scale: 1; }
.chore.is-done .chore__t {
  color: rgba(30, 42, 69, .5);
}
.chore.is-done .chore__t::after { scale: 1 1; }

/* Then it clears, closing the same track it opened — the pile settles
   back down and the rows below it come up to meet the gap. */
.chores li.is-gone {
  grid-template-rows: 0fr;
  transition: grid-template-rows .46s var(--ease) .06s;
}

.chores li.is-gone .chore {
  opacity: 0;
  translate: 26px 0;
  scale: .97;
  transition:
    opacity .3s var(--ease-soft),
    translate .4s var(--ease),
    scale .4s var(--ease);
}

.after__title {
  margin: 0 0 clamp(18px, 2.6vh, 28px);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(28px, 3.4vw, 44px);
  line-height: 1.14;
  letter-spacing: -.03em;
  /* was 18ch: dan brak de kop op drie regels terwijl er ruimte voor twee
     is, en drie regels kop naast één alinea leest als twee blokken */
  max-width: 24ch;
}

/* ── De probleemstelling ────────────────────────────────── *
   Geen dagmoment maar de aanleiding, dus zonder beeld eronder: de
   stapel werk is hier zelf het onderwerp. De kaartjes staan los op de
   ochtendgrond, licht scheef, alsof ze op je bureau zijn gelegd.    */

/* De slotregel van de stapel: is alles afgevinkt, dan komt de ochtend
   weer in beeld en staat hier waarom dat kan. */
.chores__done {
  margin: 12px 0 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(15px, 1.3vw, 18px);
  letter-spacing: -.015em;
  color: var(--gold);
  text-shadow: 0 1px 12px rgba(9, 20, 38, .7);
  opacity: 0;
  translate: 0 8px;
  transition: opacity .7s var(--ease-soft) .3s, translate .7s var(--ease) .3s;
}

.after__art.chores-clear .chores__done { opacity: 1; translate: 0 0; }


.after__lead {
  margin: 0 0 clamp(18px, 2.6vh, 26px);
  font-size: clamp(16px, 1.3vw, 18.5px);
  line-height: 1.6;
  color: rgba(43, 54, 79, .84);
  max-width: 46ch;
}

@media (max-width: 900px) {
  .after__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(28px, 6vw, 44px);
  }

  .after__art { max-width: 520px; }
  .after__title { max-width: 22ch; }
}


/* De knop onder het probleemblok wijst naar beneden, dus zijn pijl ook. */
#probleem .btn--secondary { margin-top: clamp(8px, 1.6vh, 16px); }
#probleem .btn--secondary:hover svg { transform: translateY(3px); }

/* ── Sections arriving ──────────────────────────────────── *
   Every [data-reveal] section works the same way: its marked items
   come up in order, the first one leading. It runs in both directions
   — scroll back up past the trigger and .is-in comes off again, so a
   section is never just "already there" the second time you reach it.

   The resting state carries its own transition, and that is the one
   used on the way out: shorter, and without the stagger, so leaving
   reads as the section packing itself away in one piece rather than
   playing the arrival backwards.                                   */

/* Only hidden once JS has said it will reveal them — if the script
   never runs, nothing is ever hidden in the first place. */
.reveal-ready [data-reveal-item] {
  opacity: 0;
  translate: 0 34px;
  transition:
    translate 480ms var(--ease-soft),
    opacity   340ms var(--ease-soft);
}

.reveal-ready [data-reveal].is-in [data-reveal-item] {
  transition:
    translate 980ms var(--ease)      calc(var(--i, 0) * 110ms),
    opacity   680ms var(--ease-soft) calc(var(--i, 0) * 110ms);
  translate: 0 0;
  opacity: 1;
}


/* ── De bus op de route ─────────────────────────────────── *
   The van rides the tip of the drawn road; main.js positions it in
   pixels and rotates it along the path's own tangent, same as the
   head. It is the protagonist of the journey, so it gets the glow
   the head used to carry alone.                                   */

.route__van {
  position: absolute;
  top: 0;
  left: 0;
  width: 76px;
  margin: -26px 0 0 -38px;
  color: var(--orange);
  filter: drop-shadow(0 6px 12px rgba(15, 26, 45, .3));
  opacity: 0;
  transition: opacity .5s var(--ease-soft);
  will-change: translate;
}

.route.is-live .route__van { opacity: 1; }

.route__van svg { display: block; width: 100%; height: auto; }

/* Het 3D-model staat over de tekening heen zodra WebGL het aankan;
   de tekening blijft eronder als terugval en verdwijnt pas als het
   model er echt is. Het doek is ruimer dan de bus zelf, zodat de
   perspectiefblik en de schaduw er niet tegenaan lopen. */
.route__3d {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 190px;
  height: 190px;
  margin: -95px 0 0 -95px;
  display: none;
}

.route.has-3d .route__3d { display: block; }
.route.has-3d .route__van > svg { display: none; }

/* ── Uitlaatgas ─────────────────────────────────────────── *
   Vijf pluimen die uit de uitlaat komen, opzwellen en oplossen. Ze
   zijn zacht aan de rand en verschillen in maat, snelheid en drift,
   want een echte pluim komt er niet in nette rondjes uit. De bak
   staat op de staart van de bus en spiegelt met hem mee, zodat het
   gas altijd achter blijft.                                        */

/* De bak hangt in het midden van de bus en draait mee met de
   rijrichting, zodat de pluim altijd achter de uitlaat vandaan komt,
   welke kant de bus ook op stuurt. */
.route__smoke {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0;
  height: 0;
  rotate: var(--smoke-rot, 0deg);
  pointer-events: none;
}

.route__smoke i {
  position: absolute;
  left: -40px;
  top: 4px;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: radial-gradient(
    circle at 50% 50%,
    rgba(96, 108, 128, .78) 0%,
    rgba(118, 130, 150, .5) 42%,
    rgba(140, 152, 170, 0) 74%
  );
  filter: blur(3px);
  opacity: 0;
  transform-origin: 60% 50%;
}

.route.is-live .route__smoke i {
  animation: puff 2.6s cubic-bezier(.18, .58, .3, 1) infinite;
  animation-delay: calc(var(--d) * -.37s);
}

/* elke pluim iets anders van maat, hoogte en levensduur, want een
   echte pluim komt er niet in nette rondjes uit */
.route__smoke i:nth-child(2) { animation-duration: 3s; }
.route__smoke i:nth-child(3) { animation-duration: 2.3s; }
.route__smoke i:nth-child(4) { animation-duration: 3.2s; }
.route__smoke i:nth-child(5) { animation-duration: 2.8s; }
.route__smoke i:nth-child(6) { animation-duration: 2.5s; }
.route__smoke i:nth-child(7) { animation-duration: 3.4s; }

@keyframes puff {
  0% {
    opacity: 0;
    transform: translate(4px, 0) scale(.28);
  }
  9% {
    opacity: .9;
    transform: translate(-2px, -1px) scale(.6);
  }
  45% {
    opacity: .6;
    transform: translate(-26px, -7px) scale(1.5);
  }
  78% {
    opacity: .3;
    transform: translate(-52px, -14px) scale(2.4);
  }
  100% {
    opacity: 0;
    transform: translate(-74px, -21px) scale(3.2);
  }
}


/* ── Wat Ajeto is ───────────────────────────────────────── *
   Het antwoord, na de dag en buiten .pageflow. Gecentreerd,
   want er staat geen illustratie naast: het productvenster eronder is
   het beeld. De tabbalk en het venster komen uit product.css; die
   stylesheet wordt sinds dit blok ook op de homepage geladen.      */

.uitleg {
  position: relative;
  z-index: 1;
  /* Het goud waar de dag eindigt (de onderste kleur van .pageflow) en
     waar de schemerband begint: het blok ligt daartussen, dus aan geen
     van beide kanten een naad. */
  background: #FFF4DA;
  padding: clamp(64px, 9vh, 104px) 0 clamp(40px, 6vh, 64px);
  text-align: center;
}

.uitleg__inner {
  width: min(1180px, 100% - clamp(40px, 10vw, 128px));
  margin: 0 auto;
}

.uitleg__title {
  margin: 0 auto;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(34px, 4.4vw, 60px);
  line-height: 1.06;
  letter-spacing: -.03em;
  text-wrap: balance;
  color: var(--navy);
}

/* de tabbalk en het venster dragen hun eigen ruimte al in product.css */
.uitleg__demo { margin-top: clamp(30px, 5vh, 52px); }
.uitleg .pstage { padding-bottom: clamp(26px, 4vh, 44px); }

@media (max-width: 900px) {
  .uitleg { padding-top: clamp(48px, 7vh, 72px); text-align: left; }
  .uitleg .pstage { padding-bottom: clamp(20px, 4vh, 36px); }
}

/* ── Vertrouwen ─────────────────────────────────────────── *
   De namen die je onderweg tegenkomt. Geen vlak eronder: een witte
   plaat tussen de teal van de hemel en het warme creme eronder botste
   met allebei. Nu liggen de namen op de grond van de pagina zelf, in
   een tint, en schuiven ze traag langs.                              */

.trust {
  position: relative;
  z-index: 1;
  color: var(--navy);
  padding: clamp(30px, 5vh, 54px) 0 clamp(34px, 5.5vh, 60px);
  text-align: center;
}

.trust__note {
  margin: 0 0 clamp(22px, 3.2vh, 32px);
  padding: 0 clamp(20px, 5vw, 64px);
  font-family: var(--font-display);
  font-size: clamp(16px, 1.3vw, 19px);
  font-weight: 600;
  letter-spacing: -.015em;
  color: var(--navy);
}

/* De baan: de rij loopt door tot buiten beeld en vervaagt aan beide
   kanten naar de grond, zodat er nergens een rand ontstaat. */
.trust__baan {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 clamp(40px, 8vw, 130px), #000 calc(100% - clamp(40px, 8vw, 130px)), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 clamp(40px, 8vw, 130px), #000 calc(100% - clamp(40px, 8vw, 130px)), transparent);
}

.trust__rij {
  display: flex;
  width: max-content;
  will-change: transform;
  animation: trust-schuif 38s linear infinite;
}

.trust__baan:hover .trust__rij,
.trust__baan:focus-within .trust__rij { animation-play-state: paused; }

@keyframes trust-schuif { to { transform: translateX(-33.3333%); } }

/* Een set is minstens een halve pagina breed. Met drie namen is de rij
   anders smaller dan twee schermen en valt er na het opschuiven een gat
   aan de rechterkant. De namen verdelen zich binnen die breedte; de lucht
   aan de rand van een set is precies de helft van de lucht ertussen, dus
   de ene set sluit naadloos op de volgende aan. */
.trust__set {
  display: flex;
  align-items: center;
  justify-content: space-around;
  min-width: 56vw;
}

/* Elk merk in dezelfde tint: het logobestand is een masker en de kleur
   komt van de strook. Een handvol huisstijlkleuren naast elkaar was de
   tweede bron van onrust, naast de witte plaat. */
.mark {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  flex: 0 0 auto;
  /* de helft van de kleinste tussenruimte aan weerskanten, zodat de
     verdeling klopt tot aan de naad tussen twee sets */
  padding: 0 clamp(19px, 2.5vw, 36px);
  color: var(--ajeto-navy, #1E2A45);
  opacity: .78;
}

.mark i {
  display: block;
  background: currentColor;
  -webkit-mask-image: var(--l);
  mask-image: var(--l);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

.mark b {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(16px, 1.3vw, 19px);
  letter-spacing: -.01em;
}

@media (prefers-reduced-motion: reduce) {
  .trust__rij { animation: none; }
  .trust__baan { overflow-x: auto; scrollbar-width: none; }
  .trust__baan::-webkit-scrollbar { display: none; }
}

/* ── The hour of the stop ───────────────────────────────── *
   Every stop carries its time, large and light: the clock is the
   storyline, not decoration — the four hours are what turn features
   into one day.                                                    */

.stoptime {
  margin: 0 0 12px;
}

.stoptime__big {
  display: block;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(54px, 6vw, 92px);
  line-height: 1;
  letter-spacing: -.03em;
  /* Het uur is de ankerpunt van elk blok, dus het moet te lezen zijn op
     elke grond die de dag onderweg aanneemt: crème, avondgoud en nacht. */
  color: rgba(30, 42, 69, .7);
}

.stoptime__at {
  font-family: var(--font-body);
  font-style: normal;
  font-size: clamp(15px, 1.15vw, 17px);
  font-weight: 800;
  letter-spacing: .01em;
  color: #B26A12;
  margin-left: 16px;
}


/* ── De haltes ──────────────────────────────────────────── *
   One scene per stop: the illustration panel on one side, the hour
   and the copy on the other, sides alternating so the road can weave
   between them. The panel carries a small UI card that mirrors the
   real product's answer at that hour.                              */

.stop {
  position: relative;
  z-index: 1;
  color: var(--navy);
  padding: clamp(56px, 10vh, 120px) clamp(20px, 5vw, 64px);
}

.stop__inner {
  max-width: 1140px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: clamp(34px, 6vw, 84px);
  align-items: center;
}

.stop--flip .stop__inner { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }
.stop--flip .stop__art { order: 2; }

.stop__art {
  position: relative;
  margin: 0;
  width: 100%;
  max-width: 440px;
  justify-self: center;
  border-radius: var(--ajeto-r-xl, 20px);
  overflow: hidden;
  box-shadow: 0 34px 80px -32px rgba(15, 26, 45, .38);
}

.stop__art picture { display: block; }

.stop__art img {
  display: block;
  width: 100%;
  height: auto;
}

.stop__title {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(26px, 3vw, 40px);
  line-height: 1.12;
  letter-spacing: -.03em;
  max-width: 18ch;
  /* geen los woord op de laatste regel ("De bewoner vult thuis / aan.") */
  text-wrap: balance;
}

.stop__body {
  margin: 0;
  font-size: clamp(16px, 1.35vw, 19px);
  line-height: 1.6;
  color: rgba(43, 54, 79, .84);
  max-width: 44ch;
}

/* Op het avondgoud van gisteravond heeft de tekst zijn volle inkt
   nodig; met de gebruikelijke verzachting valt hij weg. */
.stop--dusk .stop__body { color: var(--ajeto-navy, #1E2A45); }
.stop__body + .stop__body { margin-top: 12px; }

/* Om 21:15 is het buiten donker, dus staat dit blok op een nachtgrond
   en draait de tekst mee naar licht. */

.stop--evening .stop__title { color: var(--cream); }
.stop--evening .stop__body { color: rgba(255, 253, 248, .84); }
.stop--evening .stoptime__big { color: rgba(255, 253, 248, .62); }
.stop--evening .stoptime__at { color: var(--gold); }


/* ── The card on the panel ──────────────────────────────── *
   A light card at the foot of each illustration: the product's own
   answer at that hour, in its own vocabulary. Its pieces play in when
   the section arrives — the reveal observer's .is-in is the trigger,
   so scrolling back up resets it and it plays again.               */

.ui {
  position: absolute;
  left: clamp(10px, 4.5%, 20px);
  right: clamp(10px, 4.5%, 20px);
  bottom: clamp(10px, 4.5%, 20px);
  /* De strook, gekozen uit drie richtingen (formulier, strook,
     register). Weg van de afgeronde pil met de zachte waas: de kaart
     zelf is geen doos meer, elke regel draagt zijn eigen vlak met
     rechte hoeken, een harde kleurrand links die de status draagt en
     een verschoven harde schaduw. Kleur doet daarmee werk in plaats
     van decoratie: teal is binnen, oranje staat open. */
  background: none;
  border-radius: 0;
  padding: 0;
  box-shadow: none;
}

.ui__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 0;
  padding: 9px 13px 8px;
  background: var(--ajeto-navy, #1E2A45);
  box-shadow: 4px 4px 0 rgba(30, 42, 69, .26);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--sunshine, #FFCD57);
}

.ui__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  /* de bronnen boven, het dossier eronder: die twee moeten niet in
     elkaar overlopen */
  margin-bottom: 13px;
}

.ui__chips span {
  padding: 4px 9px;
  border-radius: 0;
  background: var(--ajeto-navy, #1E2A45);
  border: 0;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--cream);
  opacity: 0;
  translate: 0 8px;
}

/* De voortgangsbalk plakte tegen de eerste regel: de balk en het
   vinkje eronder liepen optisch in elkaar over. */
.ui__meter + .ui__rows { margin-top: 15px; }

.ui__rows {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 7px;
}

.ui__rows li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 11px 8px 10px;
  border-radius: 0;
  background: #FBF9F4;
  border: 0;
  border-left: 5px solid var(--teal);
  box-shadow: 4px 4px 0 rgba(30, 42, 69, .17);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--navy);
  opacity: 0;
  translate: 0 8px;
}

/* wat nog open staat draagt oranje in plaats van teal; dat is het enige
   verschil dat de lezer hoeft te zien */
.ui__rows .flag,
.ui__rows li:has(.warn) {
  border-left-color: var(--orange);
  background: #FFF6EA;
}

.ui__rows b {
  margin-left: auto;
  padding-left: 10px;
  font-weight: 700;
  /* was .55, dat gaf 3,4:1 op de strook — onder de norm van 4,5 */
  color: rgba(43, 54, 79, .74);
  white-space: nowrap;
}

/* De bolletjes zijn weg: de kleurrand links van de strook zegt
   hetzelfde, en twee keer dezelfde melding is er een te veel. Ze
   blijven wel in de opmaak staan, want de klantuitvraag animeert ze. */
.ui .ok,
.ui .warn { display: none; }

/* waar een gegeven vandaan komt, achter de waarde: controleerbaar */
.ui__rows b em {
  margin-left: 7px;
  font-style: normal;
  font-weight: 600;
  font-size: 11px;
  color: rgba(43, 54, 79, .66);
}

.ui__rows .flag {
  border-color: rgba(252, 145, 29, .5);
  background: rgba(252, 145, 29, .10);
}
.ui__rows .flag b { color: #B26A12; }

/* Deze twee leunden op het witte vlak van de kaart. Dat is er niet
   meer, dus stonden ze rechtstreeks op de illustratie en waren ze niet
   te lezen. Ze krijgen hun eigen strook, in dezelfde taal. */
.ui__meter {
  margin-top: 9px;
  padding: 9px 11px 10px;
  background: #FBF9F4;
  border-top: 0;
  border-left: 5px solid rgba(30, 42, 69, .32);
  box-shadow: 4px 4px 0 rgba(30, 42, 69, .17);
  opacity: 0;
  translate: 0 8px;
}

.ui__meter p {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin: 0 0 6px;
  font-size: 12.5px;
}

.ui__meter em {
  font-style: normal;
  font-weight: 600;
  color: rgba(43, 54, 79, .65);
}

.ui__meter b {
  font-weight: 800;
  color: #B26A12;
}

.ui__meter i {
  display: block;
  height: 6px;
  border-radius: 3px;
  background: rgba(43, 54, 79, .12);
  overflow: hidden;
}

.ui__meter i::after {
  content: "";
  display: block;
  height: 100%;
  width: 0;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--amber), var(--orange));
}

/* the entrance, shared by every piece and spaced by its own --d */
[data-reveal].is-in .ui__chips span,
[data-reveal].is-in .ui__rows li,
[data-reveal].is-in .ui__meter {
  animation: ui-in .5s var(--ease) forwards;
  animation-delay: calc(.45s + var(--d, 0) * .12s);
}

@keyframes ui-in {
  to { opacity: 1; translate: 0 0; }
}

[data-reveal].is-in .ui__meter i::after {
  animation: meter-fill .9s var(--ease) forwards;
  animation-delay: calc(.9s + var(--d, 0) * .12s);
}

@keyframes meter-fill {
  to { width: var(--fill, 100%); }
}

/* the one that does not match keeps drawing the eye */
[data-reveal].is-in .ui__rows .flag .warn {
  animation: warn-pulse 1.8s var(--ease-soft) infinite;
  animation-delay: 1.5s;
}

@keyframes warn-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(252, 145, 29, .55); }
  50%      { box-shadow: 0 0 0 5px rgba(252, 145, 29, 0); }
}

/* ── The questionnaire that shrinks itself ──────────────── *
   The evening card's rows are questions. The ones the enrichment
   already answered get struck through, then fold away entirely —
   the list physically gets shorter, which is the product's cleverest
   mechanism playing out in three seconds.                          */

.ui__rows--shrink {
  display: block;
}

.ui__rows--shrink li {
  max-height: 44px;
  overflow: hidden;
}

.ui__rows--shrink li + li { margin-top: 5px; }

.ui__rows--shrink .q { position: relative; white-space: nowrap; }

.ui__rows--shrink .q::after {
  content: "";
  position: absolute;
  left: 0;
  top: 52%;
  width: 100%;
  height: 1.5px;
  border-radius: 2px;
  background: currentColor;
  transform-origin: 0 50%;
  scale: 0 1;
}

[data-reveal].is-in .ui__rows--shrink .known .q::after {
  animation: strike-in .38s var(--ease) forwards;
  animation-delay: calc(1.6s + var(--d, 0) * .5s);
}

@keyframes strike-in {
  to { scale: 1 1; }
}

[data-reveal].is-in .ui__rows--shrink .known {
  animation:
    ui-in .5s var(--ease) forwards,
    row-fold .55s var(--ease) forwards;
  animation-delay:
    calc(.45s + var(--d, 0) * .12s),
    calc(1.95s + var(--d, 0) * .5s);
}

@keyframes row-fold {
  to {
    max-height: 0;
    margin-top: 0;
    padding-top: 0;
    padding-bottom: 0;
    border-top-width: 0;
    border-bottom-width: 0;
    opacity: 0;
  }
}


/* ── De vier scènes, geregisseerd ───────────────────────── *
   Elke kaart speelt een korte scène zodra zijn sectie in beeld komt
   (.is-in van de reveal-observer) en re-armt op de weg terug. De
   demodata is verzonnen en consistent met het bord-schermbeeld.    */

/* 09:30 · het dossier vult zichzelf: per bron licht de chip op en
   landt zijn regel in de lead, van boven naar beneden */

.ui__addr {
  margin: 0 0 9px;
  padding: 0 13px 10px;
  background: var(--ajeto-navy, #1E2A45);
  box-shadow: 4px 4px 0 rgba(30, 42, 69, .26);
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.015em;
  color: var(--cream);
  opacity: 0;
  translate: 0 6px;
}

[data-reveal].is-in .ui__addr {
  animation: ui-in .45s var(--ease) forwards .35s;
}

[data-reveal].is-in .ui--leads .ui__chips span {
  animation:
    ui-in .5s var(--ease) forwards,
    chip-flare .55s var(--ease);
  animation-delay:
    calc(.55s + var(--d, 0) * .1s),
    calc(1.25s + var(--d, 0) * .55s);
}

@keyframes chip-flare {
  35% { background: rgba(98, 188, 184, .3); border-color: var(--teal); translate: 0 -2px; }
}

.ui__rows--fill li { translate: 0 -10px; }

[data-reveal].is-in .ui__rows--fill li {
  animation: ui-in .5s var(--ease) forwards;
  animation-delay: calc(1.3s + var(--d, 0) * .55s);
}

.ui__meter p b { display: inline-block; }

[data-reveal].is-in .ui--leads .ui__meter { animation-delay: 3.5s; }
[data-reveal].is-in .ui--leads .ui__meter i::after { animation-delay: 3.7s; }
[data-reveal].is-in .ui--leads .ui__meter p b { animation: val-pop .5s var(--ease) 4.1s backwards; }

@keyframes val-pop {
  0%  { scale: .6; opacity: 0; }
  60% { scale: 1.15; }
  100% { scale: 1; opacity: 1; }
}

/* 13:30 · live meten: de gouden meetlijnen tekenen zich over het huis
   terwijl de controles een voor een op hun plek vallen */

.trace {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Teal, niet goud: in het product is teal de kleur van Ajeto dat bezig
   is (project-progress.tsx, state running). Goud hoort bij de zon in de
   illustraties en zei hier het verkeerde. */
.trace path {
  fill: none;
  stroke: var(--teal);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  filter: drop-shadow(0 0 6px rgba(46, 196, 182, .6));
}

[data-reveal].is-in .trace path {
  animation: trace-draw .65s var(--ease) forwards;
  animation-delay: calc(.9s + var(--d, 0) * .55s);
}

@keyframes trace-draw { to { stroke-dashoffset: 0; } }

/* de oordelen stempelen pas als er gemeten is */
.ui--schouw .ui__rows b { opacity: 0; translate: 6px 0; }
.ui--schouw .ok,
.ui--schouw .warn { background: #C6C9D2; }
/* Was een doorschijnend navy vlak; op de illustratie werd dat een
   zwarte balk met onleesbare tekst. Nu een gewone strook die pas
   omslaat naar oranje zodra Ajeto de afwijking vindt. */
.ui--schouw .flag { background: #FBF9F4; border-left-color: rgba(30, 42, 69, .32); }
.ui--schouw .flag b { color: #B26A12; }

[data-reveal].is-in .ui--schouw .ui__rows b {
  animation: stamp-in .38s var(--ease) forwards;
  animation-delay: calc(1.7s + var(--d, 0) * .65s);
}

@keyframes stamp-in { to { opacity: 1; translate: 0 0; } }

[data-reveal].is-in .ui--schouw .ui__rows .ok {
  animation: dot-teal .3s var(--ease-soft) forwards;
  animation-delay: calc(1.7s + var(--d, 0) * .65s);
}

@keyframes dot-teal { to { background: var(--teal); } }

/* the flag needs its entrance AND its turn: a lone override here would
   replace the ui-in animation and leave the row invisible */
[data-reveal].is-in .ui--schouw .ui__rows .flag {
  animation:
    ui-in .5s var(--ease) forwards,
    flag-on .5s var(--ease) forwards;
  animation-delay:
    calc(.45s + var(--d, 0) * .12s),
    calc(1.7s + var(--d, 0) * .65s);
}

@keyframes flag-on {
  30% { translate: 0 -3px; }
  to  { border-left-color: var(--orange); background: #FFF6EA; }
}

[data-reveal].is-in .ui--schouw .ui__rows .flag .warn {
  animation:
    dot-warn .3s var(--ease-soft) forwards,
    warn-pulse 1.8s var(--ease-soft) infinite;
  animation-delay:
    calc(1.7s + var(--d, 0) * .65s),
    3.4s;
}

@keyframes dot-warn { to { background: var(--orange); } }

/* het gedeelde bus-glyph */
.defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* goed voorbereid op pad: de meegenomen spullen, afgevinkt in mint */
/* Stond doorzichtig op de illustratie en was daar niet te lezen. Nu
   een strook in dezelfde taal als de kop erboven. */
.ui__sub {
  margin: 0 0 8px;
  padding: 7px 13px 8px;
  background: var(--ajeto-navy, #1E2A45);
  box-shadow: 4px 4px 0 rgba(30, 42, 69, .26);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: rgba(255, 253, 248, .72);
}

/* De letters zijn crème; op een doorschijnend teal vlak verdwenen ze.
   Massief navy, net als de andere bronblokjes, met het icoon in teal. */
.ui__chips--pack span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: var(--ajeto-navy, #1E2A45);
  border-color: transparent;
}

.ui__chips--pack svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: #6FDCCF;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* de conclusie: dezelfde geschiktheid-badge als het product geeft */
.ui__verdict {
  margin-top: 9px;
  padding: 10px 11px;
  background: #FBF9F4;
  border-top: 0;
  border-left: 5px solid rgba(30, 42, 69, .32);
  box-shadow: 4px 4px 0 rgba(30, 42, 69, .17);
  display: flex;
  align-items: center;
  gap: 11px;
  flex-wrap: wrap;
  opacity: 0;
  translate: 0 8px;
}

[data-reveal].is-in .ui__verdict {
  animation: ui-in .55s var(--ease) forwards 3.9s;
}

.ui__badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 11px;
  border-radius: 0;
  background: #DFF4F1;
  border: 0;
  border-left: 4px solid var(--teal);
  color: #0B5E56;
  font-size: 12.5px;
  font-weight: 800;
}

.ui__badge::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--teal);
}

.ui__vnote {
  font-size: 12.5px;
  font-weight: 700;
  color: #B26A12;
}

@keyframes pline-fill { to { scale: .52 1; } }

@keyframes phv-in {
  0%   { opacity: 0; translate: -120px 0; }
  100% { opacity: 1; translate: 0 0; }
}

/* ── 07:40 · Is het dossier compleet? ─────────────────────── *
   Het scherm zelf als beeld: het projectenbord onscherp op de
   achtergrond, het dossier ervoor geopend. De twee open regels zijn
   knoppen; tik ze dicht en de meter loopt op, de conclusie klapt om en
   op de fasebalk schuift de bus van Dossier naar Offerte.            */


.ui--dossier .ui__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
}

/* de meter is hier live: geen animatie naar een vaste waarde maar een
   overgang naar wat de lezer ervan maakt */
.ui__meter--live i::after { display: none; }

.ui__meter--live i span {
  display: block;
  height: 100%;
  width: var(--fill, 0%);
  border-radius: 3px;
  background: linear-gradient(90deg, var(--amber), var(--orange));
  transition: width .8s var(--ease);
}

.ui--dossier .tick {
  all: unset;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.ui--dossier .tick b {
  margin-left: auto;
  padding-left: 10px;
  font-weight: 700;
  color: #B26A12;
  white-space: nowrap;
}

.ui--dossier .tick:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 5px;
  border-radius: 6px;
}

.ui--dossier li.is-ok {
  border-color: rgba(43, 54, 79, .10);
  background: rgba(43, 54, 79, .05);
}

.ui--dossier li.is-ok .warn {
  background: var(--teal);
  animation: none !important;
}

.ui--dossier li.is-ok .tick { cursor: default; }
.ui--dossier li.is-ok .tick b { color: #157A70; }

.ui__badge--open {
  background: rgba(252, 145, 29, .14);
  color: #8F5510;
}

.ui__badge--open::before { background: var(--orange); }

/* de conclusie hoort hier bij de openstand, dus niet de lange
   vertraging van de schouwscène afwachten */
[data-reveal].is-in .ui--dossier .ui__verdict { animation-delay: 1.7s; }

@media (max-width: 900px) {
  /* de open regels zijn knoppen, dus een tapdoel van 44px */
  .ui--dossier .ui__rows li { min-height: 44px; }
}

/* 16:15 · alles valt samen: snippers uit de dag dwarrelen binnen en
   worden regels van het overdrachtspakket */

.snip {
  position: absolute;
  z-index: 1;
  padding: 7px 13px;
  border-radius: 10px;
  background: rgba(255, 253, 248, .95);
  border: 1px solid rgba(43, 54, 79, .14);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: -.01em;
  color: var(--navy);
  box-shadow: 0 10px 24px -10px rgba(15, 26, 45, .45);
  opacity: 0;
}

[data-reveal].is-in .snip {
  animation: snip-pass 1.15s var(--ease) forwards;
  animation-delay: calc(1s + var(--d, 0) * .7s);
}

@keyframes snip-pass {
  0%   { opacity: 0; translate: var(--fx) var(--fy); rotate: var(--fr); }
  28%  { opacity: 1; translate: 0 0; rotate: 0deg; }
  62%  { opacity: 1; translate: 0 22px; }
  100% { opacity: 0; translate: 0 52px; scale: .92; }
}

[data-reveal].is-in .ui--wvb .ui__rows--fill li {
  animation-delay: calc(1.6s + var(--d, 0) * .7s);
}

[data-reveal].is-in .ui--wvb .ui__meter { animation-delay: 3.6s; }
[data-reveal].is-in .ui--wvb .ui__meter i::after { animation-delay: 3.8s; }

/* 20:30 · de teller: de kop telt af terwijl de lijst korter wordt */

.ui--klant .ui__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}

.ui__count {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(255, 253, 248, .68);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ui__rows--shrink .known b { opacity: 0; translate: 8px 0; color: #157A70; }

[data-reveal].is-in .ui__rows--shrink .known b {
  animation: stamp-in .35s var(--ease) forwards;
  animation-delay: calc(1.4s + var(--d, 0) * .5s);
}

[data-reveal].is-in .ui__rows--shrink li:not(.known) .warn {
  animation: warn-pulse 1.8s var(--ease-soft) infinite 4.8s;
}


/* ── Ondergaande zon ────────────────────────────────────── *
   The hero's landscape returns, mirrored: the van drives home into
   the sunset. Full-bleed art with a dusk grade over it, the day's
   yield in three short lines, and the one human voice of the page.
   The art's own top edge is masked away so the warming pageflow
   ground hands over without a seam.                                */

.dusk {
  position: relative;
  z-index: 1;
  overflow: hidden;
  padding: clamp(96px, 17vh, 190px) clamp(20px, 5vw, 64px) clamp(120px, 22vh, 250px);
  text-align: center;
  color: var(--cream);
}


/* De schemer is nu bijna helemaal beeld: de kop en de opbrengst staan
   hoog, zodat het landschap met de thuisrijdende bus eronder de ruimte
   krijgt die het verdient. */
.dusk__copy {
  position: relative;
  z-index: 1;
  max-width: 1140px;
  margin: 0 auto;
}

.dusk__title {
  margin: 0 auto;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(30px, 4vw, 54px);
  line-height: 1.1;
  letter-spacing: -.03em;
  max-width: 18ch;
  text-wrap: balance;
  text-shadow: 0 2px 26px rgba(15, 26, 45, .55);
}

/* 07:00: hetzelfde landschap, maar nu de zon die opkomt in plaats van
   ondergaat, en onderaan overlopend in de crème dag eronder. */
/* Geen doorschijnende bovenkant hier: de lucht van de illustratie sluit
   zelf aan op de grond erboven, en zo verdwijnt de weg netjes achter
   het beeld in plaats van erdoorheen te lopen. */


/* het spookgetal leest hier tegen een lichte lucht, dus donker */
.dusk--dawn .stoptime__big { color: rgba(255, 253, 248, .68); }

/* De opkomst heeft ruimte nodig: de sectie is hoger dan het scherm,
   met de tekst bovenin en de horizon onderin, zodat de zon een echte
   afstand aflegt terwijl je erdoorheen scrollt. */
.dusk--dawn {
  min-height: 122svh;
  padding-top: clamp(72px, 11vh, 140px);
  padding-bottom: clamp(240px, 44vh, 540px);
}

/* ── De avondband ────────────────────────────────────────── *
   Tussen de dagflow en de laatste schroef. De plaat loopt zelf van het
   creme waar de dag eindigt naar het navy waarmee de nacht begint, dus
   er is aan geen van beide kanten iets te overbruggen.              */

.duskband {
  display: block;
  position: relative;
  z-index: 1;
  margin-top: -1px;
}

.duskband img {
  display: block;
  width: 100%;
  height: auto;
}

/* ── De zonsopkomst ──────────────────────────────────────── *
   De luchtgang hierboven doet de kleur; deze laag zet er het licht in.
   Een zon die uit de horizon omhoog komt terwijl je scrollt, met een
   gloed die meegroeit, stralen die openvouwen en sterren die doven.
   Zonder die lichtbron blijft het een kleurverloop; mét is het een
   ochtend die aanbreekt.                                            */

.dawn {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  --dawn: 0;
  /* De gloed reikt tot boven de sectie en werd daar hard afgeknipt op
     de rand, wat als een streep las. Deze maskering laat de hele laag
     invloeien, zodat er geen kant is om af te knippen. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 160px);
  mask-image: linear-gradient(180deg, transparent 0, #000 160px);
}

/* De plaat ligt als band op de onderrand: de daklijn valt samen met de
   overgang van nacht naar dag. De bovenkant vloeit weg in de grond
   erboven, zodat er geen rand van het beeld te zien is. */
/* Het beeld vult de hele sectie. Het loopt zelf van nachtblauw naar het
   creme van de pagina, dus er is geen vervaging nodig om het aan te
   sluiten: geen waas onder de huizen en geen weg die er doorheen
   schijnt. De bovenrand van het beeld en de grond erboven hebben
   dezelfde kleur, dus daar valt niets te zien. */
.dawn__scene {
  position: absolute;
  inset: 0;
  display: block;
}

.dawn__scene img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  /* een lichte inzoom die uitloopt terwijl je scrollt; de rand blijft
     altijd buiten beeld doordat de sectie afknipt */
  scale: calc(1.05 - var(--dawn) * .05);
}

.dusk__copy { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  /* geen opkomst, wel de ochtend: de eindstand staat er meteen */
  .dawn { --dawn: 1 !important; }
  .dawn__scene img { scale: 1 !important; }
}

.dusk__body {
  margin: 18px auto 0;
  max-width: 46ch;
  font-size: clamp(16px, 1.35vw, 19px);
  line-height: 1.6;
  color: var(--cream);
  text-shadow: 0 1px 16px rgba(15, 26, 45, .5);
}


/* ── De nacht: Ajeto werkt door ─────────────────────────── *
   Een eigen donkere grond met maan en sterren, waar het projectenbord
   als enige licht geeft. Dit blok stond eerst helemaal aan het eind;
   in de omgekeerde dag is het juist het beginpunt van het werk.     */

/* De avond en de nacht liggen ná de schemerband en dus buiten .pageflow.
   Ze dragen daarom zelf hun grond. De bovenkant is de gemeten onderrand
   van dusk-thuis (#1B2942).

   Sinds ronde 6 is de nacht kort, en sinds 9 oktober is het slot er geen
   eigen sectie meer onder: links de zin, rechts de vraag als kaart, één
   blok (Nathan: "twee tekstbalken onder elkaar"). De grond loopt daarom
   door tot de kleur van de voettekst (#070E19), die meet check:naden.
   Het bord en de schroefscène zijn eruit; hun regels hieronder (.board,
   .night) slapen, zie CLAUDE.md. */
.stop--evening {
  background: linear-gradient(180deg, #1B2942 0%, #1A2740 100%);
}

.nightwork {
  position: relative;
  z-index: 1;
  overflow: hidden;
  background: linear-gradient(180deg, #1A2740 0%, #16233C 42%, #0E1729 78%, #070E19 100%);
  padding: clamp(84px, 14vh, 156px) clamp(20px, 5vw, 64px) clamp(72px, 12vh, 128px);
  color: var(--cream);
}

.nightwork__sky { position: absolute; inset: 0; }

.nightwork__inner {
  position: relative;
  z-index: 1;
  max-width: 1140px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(40px, 5vw, 80px);
  align-items: center;
}

.nightwork__copy { min-width: 0; }

.nightwork__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(34px, 4.6vw, 64px);
  line-height: 1.05;
  letter-spacing: -.03em;
  color: var(--cream);
  text-wrap: balance;
}

@media (max-width: 900px) {
  .nightwork__inner { grid-template-columns: minmax(0, 1fr); text-align: center; }
}

.asleep__star {
  position: absolute;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: rgba(255, 253, 248, .8);
}

.asleep__moon {
  position: absolute;
  /* hing eerst naast het bord, daarna boven de zin; nu de vraag rechts
     als kaart staat, hangt hij er net boven in de hoek */
  right: 7%;
  top: 11%;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: radial-gradient(circle at 38% 34%, #FFFDF8 0%, #E8E2D2 70%, #D5CFC0 100%);
  opacity: .9;
  box-shadow: 0 0 60px 12px rgba(255, 253, 248, .14);
}

@media (max-width: 900px) {
  /* op een telefoon staat 03:20 bovenaan; de maan gaat de hoek in */
  .asleep__moon { top: 3%; right: 7%; width: 40px; height: 40px; }
}

/* het tijdstip op een donkere grond */
.stoptime--dark .stoptime__big { color: rgba(255, 253, 248, .62); }
.stoptime--dark .stoptime__at { color: var(--gold); }

.board {
  position: relative;
  margin: 0 auto;
  max-width: 1120px;
}

/* thuis: de bus geparkeerd naast het scherm */
.board__van {
  position: absolute;
  /* lager dan voorheen: sinds het bord een echte zijbalk heeft, stond
     hij pal op de regel Feedback */
  left: -22px;
  bottom: -6px;
  z-index: 1;
  width: 46px;
  color: var(--orange);
  filter: drop-shadow(0 6px 12px rgba(0, 0, 0, .55));
}

.board__van svg { display: block; width: 100%; height: auto; }

/* nog één lamp aan: Ajeto is bezig */
.board__live {
  position: absolute;
  top: -16px;
  right: 5%;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 10px 16px;
  border-radius: var(--radius-pill);
  background: rgba(255, 253, 248, .96);
  color: var(--navy);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -.01em;
  rotate: -1.5deg;
  box-shadow: 0 14px 34px -12px rgba(0, 0, 0, .6);
}

.board__live i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--teal);
  animation: live-breathe 2.2s var(--ease-soft) infinite;
}

@keyframes live-breathe {
  0%, 100% { box-shadow: 0 0 0 0 rgba(98, 188, 184, .5); }
  50%      { box-shadow: 0 0 0 6px rgba(98, 188, 184, 0); }
}

.board img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 14px;
  border: 1px solid rgba(255, 253, 248, .14);
  rotate: -1.5deg;
  box-shadow:
    0 0 120px -8px rgba(255, 176, 82, .35),
    0 50px 100px -40px rgba(0, 0, 0, .8);
}

.board figcaption {
  margin-top: 22px;
  text-align: center;
  font-size: 14.5px;
  font-weight: 500;
  color: rgba(255, 253, 248, .62);
}


/* keyboard travellers get the brand focus, not the UA default */
.btn:focus-visible,
.nav a:focus-visible,
.footer__col a:focus-visible {
  outline: 2px solid rgba(252, 145, 29, .85);
  outline-offset: 3px;
}



/* ── Footer ─────────────────────────────────────────────── */

/* De voettekst had exact dezelfde grond als het slot erboven, dus liep
   het over in één donkere massa. Een slag dieper plus een haarlijn maakt
   er twee blokken van: hier eindigt het verhaal, hier begint de
   huishouding. */
.footer {
  position: relative;
  z-index: 2;
  background: #070E19;
  /* geen lijn meer bovenaan: die scheidde de voettekst van het creme
     blogblok dat er niet meer is. Nu sluit het slot er in dezelfde kleur
     op aan en zou een lijn de naad juist zichtbaar maken. */
  color: rgba(255, 253, 248, .74);
  padding: clamp(70px, 11vh, 104px) clamp(20px, 5vw, 64px) 42px;
}

.footer__inner {
  max-width: 1140px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) auto auto;
  gap: clamp(40px, 7vw, 110px);
  align-items: start;
}

.footer__brand img {
  height: 30px;
  width: auto;
  display: block;
  margin-bottom: 16px;
}

.footer__brand p {
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  max-width: 30ch;
}

.footer__col {
  display: grid;
  gap: 9px;
  align-content: start;
  justify-items: start;
}

.footer__col h3 {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: var(--ajeto-tracking-caps, .14em);
  text-transform: uppercase;
  color: rgba(255, 253, 248, .45);
}

.footer__col a,
.footer__col span {
  font-size: 15px;
  font-weight: 500;
  color: rgba(255, 253, 248, .78);
  transition: color .28s var(--ease-soft);
}

.footer__col a:hover { color: var(--cream); }

.footer__eu {
  max-width: 1140px;
  margin: clamp(48px, 8vh, 72px) auto 0;
  padding-top: 28px;
  border-top: 1px solid rgba(255, 253, 248, .12);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}

.footer__eu p {
  margin: 0;
  font-size: 13.5px;
  color: rgba(255, 253, 248, .55);
  max-width: 62ch;
}

.footer__eu img {
  height: 56px;
  width: auto;
  border-radius: 6px;
  background: #FFFFFF;
  padding: 5px 10px;
}

.footer__legal {
  max-width: 1140px;
  margin: 26px auto 0;
  font-size: 13px;
  color: rgba(255, 253, 248, .4);
}


/* ── Uit de praktijk: de artikelen ──────────────────────── *
   Na het donkere slot breekt een crèmevlak de nacht open. Dat is een
   sein: het verhaal is klaar, hier is nog een laag. Daarna sluit de
   demo weer donker af, zoals besloten.                             */

/* ── Het slot ───────────────────────────────────────────── *
   Eén kop, één knop en een stille bel-link, het laatste blok voor de
   voettekst. Sinds 9 oktober een kaart rechts naast de zin van de nacht,
   binnen .nightwork: de nacht zegt wat Ajeto doet, de kaart vraagt iets.
   Licht doorschijnend, zodat de lucht erachter doorloopt en het één
   beeld blijft. Geen vraagzin erboven en geen drieluik: die zijn er eerder
   bewust uitgehaald.                                                   */

.slot {
  position: relative;
  min-width: 0;
  padding: clamp(28px, 3vw, 44px);
  border: 1px solid rgba(255, 253, 248, .12);
  border-radius: 24px;
  background: linear-gradient(180deg, rgba(255, 253, 248, .075), rgba(255, 253, 248, .03));
  box-shadow: 0 34px 70px -34px rgba(0, 0, 0, .7);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: var(--cream);
}

.slot__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(24px, 2.3vw, 32px);
  line-height: 1.1;
  letter-spacing: -.025em;
  text-wrap: balance;
  color: var(--cream);
}

.slot__body {
  margin: 12px 0 0;
  max-width: 36ch;
  font-size: clamp(16px, 1.2vw, 18px);
  line-height: 1.6;
  color: rgba(255, 253, 248, .82);
}

.slot__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: clamp(22px, 3vh, 30px);
}

@media (max-width: 900px) {
  .slot { max-width: 520px; margin: 0 auto; width: 100%; }
  .slot__body { margin-inline: auto; }
  .slot__cta { justify-content: center; }
  .slot__cta .btn--primary { width: 100%; max-width: 340px; }
}

.journal {
  position: relative;
  z-index: 2;
  /* De sprong van nacht naar creme was een rechte snede dwars over de
     pagina. Nu loopt het navy van het slot nog even door en vervaagt
     het naar de cremekleurige grond, zodat de nacht uitdooft in plaats
     van te worden afgekapt. */
  background:
    linear-gradient(180deg, #142137 0%, rgba(20, 33, 55, 0) 190px),
    var(--cream);
  color: var(--ajeto-navy, #1E2A45);
  padding: calc(clamp(64px, 10vh, 118px) + 150px) clamp(20px, 5vw, 64px) clamp(64px, 10vh, 118px);
}

.journal__inner { max-width: 1140px; margin: 0 auto; }

.journal__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: clamp(26px, 4vh, 40px);
}

.journal__eyebrow {
  margin: 0 0 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: #B26A12;
}

.journal__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(24px, 3vw, 38px);
  line-height: 1.12;
  letter-spacing: -.028em;
}

.journal__all {
  font-size: 15px;
  font-weight: 600;
  color: var(--orange);
  white-space: nowrap;
}

.journal__all:hover { color: #E57100; }

/* Met één artikel staat er één kaart van 380px links; komen er meer,
   dan vult de rij zich vanzelf tot drie. Zo hoeft de opmaak niet mee
   te veranderen als jij gaat schrijven. */
.journal__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 380px));
  gap: 18px;
}

.post {
  display: flex;
  flex-direction: column;
  padding: 24px;
  border-radius: 16px;
  background: #FFFFFF;
  border: 1px solid var(--ajeto-line, #EAE8E2);
  transition: transform .2s var(--ease-soft), box-shadow .2s var(--ease-soft);
}

.post:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 30px rgba(20, 24, 34, .09);
}

.post__meta {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 12px;
  margin-bottom: 15px;
  border-bottom: 1px dashed var(--ajeto-line-2, #D9D6CE);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ajeto-muted, #6B7280);
}

.post__title {
  margin: 0 0 10px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 19px;
  line-height: 1.2;
  letter-spacing: -.015em;
}

.post:hover .post__title { color: var(--orange); }

.post__desc {
  margin: 0 0 18px;
  flex: 1;
  font-size: 14.5px;
  line-height: 1.55;
  color: rgba(43, 54, 79, .78);
}

.post__tags { display: flex; flex-wrap: wrap; gap: 6px; }

.post__tags span {
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(46, 196, 182, .45);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #17857A;
}

/* ── Aanmelden in de voettekst ──────────────────────────── *
   De V1-site had dit en deze niet. Voor iemand die nog niet wil
   boeken is een e-mailadres het enige wat je overhoudt.           */

.footer__signup { margin-top: 22px; }

.footer__signup h4 {
  margin: 0 0 9px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(255, 253, 248, .55);
}

.footer__form { display: flex; gap: 8px; max-width: 340px; }

.footer__form input {
  flex: 1;
  min-width: 0;
  padding: 11px 14px;
  border-radius: 9px;
  border: 1px solid rgba(255, 253, 248, .22);
  background: rgba(255, 253, 248, .06);
  color: var(--cream);
  font-family: var(--font-body);
  /* 16 px: kleiner, en een iPhone zoomt in zodra je erop tikt */
  font-size: 16px;
}

.footer__form input::placeholder { color: rgba(255, 253, 248, .42); }

.footer__form input:focus-visible {
  outline: 2px solid rgba(252, 145, 29, .85);
  outline-offset: 2px;
}

.footer__form button {
  padding: 11px 18px;
  border-radius: 9px;
  border: 0;
  background: var(--orange);
  color: #fff;
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
}

.footer__form button:hover { background: #E57100; }

.footer__note {
  margin: 9px 0 0;
  font-size: 12.5px;
  color: rgba(255, 253, 248, .5);
}

/* de uitkomst van het aanmelden komt in hetzelfde regeltje (aanmelden.js) */
.footer__note[data-soort="goed"] { color: #9FE3C9; }
.footer__note[data-soort="fout"] { color: #FFC08A; }

/* Het veld voor bots (aanmelden.js, api/_lib/validate.js). Buiten beeld
   geschoven en niet op display:none, want sommige bots slaan onzichtbare
   velden over. Met tabindex -1 en aria-hidden komt geen mens erin. */
.honing {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}

@media (max-width: 700px) {
  .journal__grid { grid-template-columns: 1fr; }
}


/* ── Het projectenbord ───────────────────────────────────── *
   Was een schermafdruk. Een plaatje kan niet laten zien dat Ajeto
   bezig is, en dat is juist het punt van dit blok: iemand slaapt
   en er wordt doorgewerkt. Nu is het echte HTML, dus de spinners
   draaien, de balken van lopende taken schuiven en de bezig-melding
   wisselt.

   De bewegingen zijn niet verzonnen: progress-slide (1,8s lineair),
   pulse (1,4s) en de draaiende LoaderCircle staan zo in
   apps/web/tailwind.config.ts van het product. De statussen ook:
   running is teal met een onbepaalde balk, action is oranje.

   Alles schaalt mee met de breedte van het bord via container
   queries, zodat één maatvoering klopt op elk scherm.          */

.board { container-type: inline-size; }

.brd {
  display: flex;
  /* De verhouding van een 16-inch MacBook (3456 bij 2234). Het bord is
     daarmee een venster, geen lap: wat er onderaan niet in past valt
     buiten beeld, precies zoals bij een echt scherm dat verder scrollt. */
  aspect-ratio: 3456 / 2234;
  border-radius: 1.1em;
  overflow: hidden;
  background: var(--cream);
  box-shadow: 0 2.4em 5em -1.6em rgba(0, 0, 0, .6);
  font-size: 11px;
  font-size: clamp(7.5px, 1.06cqw, 13px);
  line-height: 1.35;
  color: var(--ajeto-navy, #1E2A45);
  text-align: left;
}

/* De zijbalk zoals in het product: logo met inklapknop, Home,
   Projectoverzicht als actief item met zijn drie fases eronder,
   en onderaan Logboek en Feedback. */
.brd__rail {
  flex: 0 0 auto;
  /* Exact de maat uit het product: sidebar.tsx zet de uitgeklapte balk
     op w-[220px] met px-3. Het bord beeldt een venster van 1280 breed
     af, dus 220/1280 = 17,19 procent van de bordbreedte. Als percentage
     en niet in em, want dan blijft hij kloppen los van de lettergrootte. */
  width: 17.19%;
  padding: 1.3em 1.15em 1.1em;
  background: #1B2A44;
  display: flex;
  flex-direction: column;
  gap: .3em;
  color: rgba(255, 253, 248, .74);
}

.brd__brand {
  display: flex; align-items: center; gap: .6em;
  padding: 0 .4em .2em;
  margin-bottom: 1.4em;
}

.brd__brand b {
  flex: 1;
  font-family: var(--font-display);
  font-weight: 600; font-size: 1.9em; letter-spacing: -.03em;
  color: var(--cream);
}

.brd__brand i { font-style: normal; font-size: 1.1em; opacity: .55; }

.brd__nav {
  display: flex; align-items: center; gap: .7em;
  padding: .62em .7em;
  border-radius: .55em;
  font-size: 1.08em; font-weight: 500;
}

.brd__nav svg { width: 1.25em; height: 1.25em; flex: 0 0 auto; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

.brd__nav.is-now { background: rgba(46, 196, 182, .13); color: var(--teal); font-weight: 600; }
.brd__nav--sub { margin-left: 1.5em; font-size: 1.02em; }
.brd__spacer { flex: 1 1 auto; min-height: 1.5em; }

/* het merkteken: een ring van de vier merkkleuren, zoals in de
   zijbalk van het product */
/* De ring van vier merkkleuren. Als één achtergrond met een
   radial-gradient erboven bleef hij onzichtbaar; met een echt gat via
   mask werkt hij wel, en de kleuren blijven de vier uit tokens.css. */
.brd__mark {
  flex: 0 0 auto;
  width: 1.9em;
  height: 1.9em;
  border-radius: 50%;
  background: conic-gradient(
    from -20deg,
    var(--orange) 0 22%,
    var(--sunshine) 22% 44%,
    var(--teal) 44% 62%,
    #FFFDF8 62% 100%
  );
  -webkit-mask: radial-gradient(circle at 50% 50%, transparent 0 42%, #000 44%);
  mask: radial-gradient(circle at 50% 50%, transparent 0 42%, #000 44%);
}

.brd__main { flex: 1 1 auto; min-width: 0; background: var(--cream); }

.brd__bar {
  display: flex; align-items: center; justify-content: flex-end; gap: .8em;
  padding: .9em 1.4em; border-bottom: 1px solid rgba(43, 54, 79, .07);
}

.brd__dot { width: 1.1em; height: 1.1em; border-radius: 50%; background: rgba(43, 54, 79, .16); }

.brd__you {
  width: 1.6em; height: 1.6em; border-radius: 50%;
  background: #FFE0B8; color: #A05A08;
  display: grid; place-items: center;
  font-size: .82em; font-weight: 700;
}

.brd__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1em; padding: 1.1em 1.6em .9em;
}

.brd__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600; font-size: 2.1em; letter-spacing: -.03em;
}

.brd__tools { display: flex; align-items: center; gap: .55em; }

.brd__seg, .brd__btn {
  padding: .45em .85em; border-radius: .6em;
  border: 1px solid rgba(43, 54, 79, .13);
  font-size: .95em; font-weight: 600; color: rgba(43, 54, 79, .72);
  white-space: nowrap;
}

.brd__seg { display: inline-flex; gap: .7em; }
.brd__seg b { color: var(--ajeto-navy, #1E2A45); }
.brd__btn--new { background: var(--orange); border-color: var(--orange); color: #fff; }

.brd__cols {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 1.1em; padding: 0 1.6em 1.6em;
  align-items: start;
}

.brd__colhd {
  display: flex; align-items: center; justify-content: space-between;
  margin: 0 0 .8em; padding-bottom: .6em;
  border-bottom: 1px solid rgba(43, 54, 79, .10);
  font-family: var(--font-body);
  font-size: 1.05em; font-weight: 600; color: rgba(43, 54, 79, .8);
}

.brd__colhd span { font-weight: 600; color: rgba(43, 54, 79, .6); }

/* ── Een projectkaart ───────────────────────────────────── */

.pc {
  padding: .85em .95em;
  margin-bottom: .8em;
  border-radius: .75em;
  background: #fff;
  border: 1px solid rgba(43, 54, 79, .10);
  box-shadow: 0 .2em .5em rgba(15, 23, 42, .04);
}

.pc--running { border-color: rgba(46, 196, 182, .45); }
.pc--action  { border-color: rgba(245, 124, 0, .38); }

.pc__top { display: flex; align-items: flex-start; justify-content: space-between; gap: .6em; }
.pc__name { display: block; font-size: 1.25em; font-weight: 700; letter-spacing: -.01em; }
.pc__addr { display: block; margin-top: .1em; font-size: .95em; color: rgba(43, 54, 79, .74); }

.pc__who {
  flex: 0 0 auto;
  width: 1.7em; height: 1.7em; border-radius: 50%;
  background: #FFE0B8; color: #A05A08;
  display: grid; place-items: center;
  font-size: .8em; font-weight: 700;
}

.pc__tags { display: flex; align-items: center; flex-wrap: wrap; gap: .5em; margin: .7em 0 0; }

.pot {
  display: inline-flex; align-items: center; gap: .35em;
  padding: .25em .6em; border-radius: 999px;
  font-size: .92em; font-weight: 600;
}

.pot i { width: .4em; height: .4em; border-radius: 50%; background: currentColor; }
.pot--extreem { background: rgba(245, 124, 0, .12); color: #A85800; }
.pot--hoog    { background: rgba(46, 196, 182, .15); color: #12756B; }
.pot--middel  { background: rgba(245, 124, 0, .10); color: #A85800; }

.pc__prod { font-size: 1em; font-weight: 500; color: rgba(43, 54, 79, .82); }

.pc__marks { display: flex; flex-wrap: wrap; align-items: center; gap: .55em; margin: .5em 0 0; font-size: .9em; color: rgba(43, 54, 79, .64); }
.pc__chip { padding: .18em .5em; border-radius: .35em; background: rgba(43, 54, 79, .07); color: rgba(43, 54, 79, .68); font-weight: 600; }
.pc__open { color: #12756B; font-weight: 600; }

.pc__meta { display: flex; justify-content: space-between; margin: .8em 0 .35em; font-size: .95em; color: rgba(43, 54, 79, .72); }
.pc__meta b { font-weight: 700; font-variant-numeric: tabular-nums; }
.pc--running .pc__meta b { color: #12756B; }
.pc--action  .pc__meta b { color: #A85800; }
.pc--default .pc__meta b { color: rgba(43, 54, 79, .45); }

.pc__bar { position: relative; height: .35em; border-radius: .2em; background: rgba(43, 54, 79, .10); overflow: hidden; }

.pc__bar i {
  display: block; height: 100%; width: var(--pct, 0%);
  border-radius: .2em;
  background: var(--orange);
}

.pc--running .pc__bar i { background: var(--teal); }

/* Geen bewegende balk. In het product krijgt de kaartbalk alleen
   value={pct} mee; de indeterminate-vlag uit STATE_STYLE wordt daar
   niet doorgegeven. Alleen het icoon draait. */

.pc__next { display: flex; align-items: center; gap: .45em; margin: .7em 0 0; font-size: .98em; font-weight: 600; }
.pc--running .pc__next { color: #12756B; }
.pc--action  .pc__next { color: #A85800; }
.pc--default .pc__next { color: rgba(43, 54, 79, .5); }

.pc__spin, .pc__ico { flex: 0 0 auto; width: 1.15em; height: 1.15em; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }

@keyframes brd-spin { to { rotate: 360deg; } }

.pc__foot { margin: .6em 0 0; font-size: .88em; color: rgba(43, 54, 79, .58); }

/* De installatietypes als icoon in plaats van als woord, met de datum
   erachter — zo staat het op de projectkaart in het product. De iconen
   komen uit lib/products.ts: warmtepomp is Fan, zonnepanelen is Sun, de
   datum krijgt CalendarDays. */
.pc__icons {
  display: flex;
  align-items: center;
  gap: .5em;
  margin: .7em 0 0;
  font-size: 1.02em;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: rgba(43, 54, 79, .74);
}

.pc__icons .pi {
  width: 1.35em;
  height: 1.35em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: rgba(43, 54, 79, .62);
}

.pc__icons span { margin-left: .1em; }

.pc__act { display: flex; align-items: center; gap: .4em; flex: 0 0 auto; }

.pc__send {
  width: 1.9em; height: 1.9em; border-radius: 50%;
  background: var(--orange);
  display: grid; place-items: center;
}

.pc__send svg { width: 1em; height: 1em; fill: none; stroke: #fff; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }

.pc__menu svg { width: 1.2em; height: 1.2em; fill: rgba(43, 54, 79, .45); }

/* ── De bewegingen ──────────────────────────────────────── *
   Pas aan zodra het blok in beeld is, zodat er niets staat te
   draaien in een sectie die niemand ziet.                     */

[data-reveal].is-in .pc__spin { animation: brd-spin 1s linear infinite; }
[data-reveal].is-in .board__live i { animation: brd-pulse 1.4s ease-in-out infinite; }

@keyframes brd-pulse { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }

/* de vaste balken groeien één keer naar hun stand */
@keyframes brd-fill { from { width: 0; } }

[data-reveal].is-in .pc:not(.pc--running) .pc__bar i {
  animation: brd-fill 1.1s var(--ease) both;
  animation-delay: calc(.5s + var(--d, 0) * .18s);
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal].is-in .pc__spin,
  [data-reveal].is-in .board__live i,
  [data-reveal].is-in .pc:not(.pc--running) .pc__bar i { animation: none !important; }
}

@media (max-width: 700px) {
  .brd__cols { grid-template-columns: 1fr; }
  .brd__col:nth-child(n+2) { display: none; }
}


/* ── Small screens: the journey stacks ──────────────────── */

@media (max-width: 900px) {
  /* Gestapeld is er geen ruimte om te slingeren: de weg liep als draad
     langs de rand, onder de tekst door (Nathan, 27 oktober: weg ermee).
     Alleen het getekende verdwijnt. .route zelf blijft staan, want
     main.js meet daaraan ook het kleurverloop van de grond (measure →
     paintGround); met display: none krijgt die geen maten meer. */
  .route__svg { visibility: hidden; }
  .route__van { display: none; }

  /* op een telefoon schuift de rij wat trager en staan de merken dichter
     op elkaar, zodat er meer dan een tegelijk in beeld past */
  .trust__rij { animation-duration: 26s; }
  .mark { padding: 0 15px; }

  .stop__inner,
  .stop--flip .stop__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(24px, 6vw, 40px);
  }

  /* the panel leads on a phone — it carries the idea faster */
  .stop--flip .stop__art { order: 0; }
  .stop__art { max-width: 460px; }

  .stoptime__big { font-size: clamp(44px, 13vw, 64px); }

  .footer__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 36px;
  }

  .footer__eu {
    flex-direction: column;
    align-items: flex-start;
  }

  /* links van 18 px hoog, 9 px uit elkaar, waren met een duim makkelijk
     mis te tikken; nu is elke regel zelf het tikvlak */
  .footer__col { gap: 0; }
  .footer__col a,
  .footer__col span { padding-block: 8px; }
}


/* ── Reduced motion: every scene simply stands there ────── */

@media (prefers-reduced-motion: reduce) {
  .ui__chips span,
  .ui__rows li,
  .ui__meter {
    animation: none !important;
    opacity: 1 !important;
    translate: 0 0 !important;
  }

  .ui__meter i::after {
    animation: none !important;
    width: var(--fill, 100%);
  }

  .ui__rows .flag .warn { animation: none !important; }

  /* the struck questions stay visible instead of folding away */
  .ui__rows--shrink .known { animation: none !important; }
  .ui__rows--shrink .known .q::after {
    animation: none !important;
    scale: 1 1;
  }
  .ui__rows--shrink .known { opacity: .55; }

  /* the scenes stand in their end state */
  .ui__addr { animation: none !important; opacity: 1 !important; translate: 0 0 !important; }
  .snip { display: none !important; }
  .trace path { animation: none !important; stroke-dashoffset: 0; }
  .ui--schouw .ui__rows b,
  .ui__rows--shrink .known b {
    animation: none !important;
    opacity: 1 !important;
    translate: 0 0 !important;
  }
  .ui--schouw .ok { background: var(--teal) !important; }
  .ui--schouw .warn { background: var(--orange) !important; }
  .ui__verdict { animation: none !important; opacity: 1 !important; translate: 0 0 !important; }
  .ui--schouw .flag {
    animation: none !important;
    border-left-color: var(--orange) !important;
    background: #FFF6EA !important;
  }
  .ui__meter p b { animation: none !important; }

  .ui__meter--live i span { transition: none !important; }
  .route__van { transition: none !important; }
  .route__smoke { display: none !important; }
  .board__live i { animation: none !important; }

  /* the night is static there, so --fall never rises: beide zinnen staan
     er gewoon, onder elkaar, zonder scherpstellen */
  .night__woorden {
    position: static;
    padding: 0 24px 40px;
    gap: .5em;
  }
  .night__line {
    grid-area: auto;
    opacity: 1 !important;
    filter: none !important;
    letter-spacing: -.022em;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .night__art { opacity: 1 !important; filter: none !important; }
}


/* ── Nightfall ──────────────────────────────────────────── *
   The closing beat, and the only pinned thing on the page besides the
   hero. A tall section holds a sticky stage the size of the window;
   --fall runs 0 → 1 across the whole section and drives two phases of
   one movement:

     0 → .5   the Ajeto navy sweeps in on a diagonal until it owns the
              screen, with the last of the day's warmth on its edge
     .45 → 1  the picture comes up out of the dark it just made

   The sweep is pinned to the window rather than to the section — a
   gradient stop tied to the section's own height races off the bottom
   of the screen before you ever see it move. That is what the sticky
   stage buys: the gradient's 100% is the viewport, so the diagonal
   crosses the reader.

   Everything is read off scroll position rather than animated, so it
   all runs backwards on the way up with no state to unwind.        */

.night {
  /* Sits a hair above the darkest navy in the footage. That matters
     because the art is composited with mix-blend-mode: lighten — every
     pixel darker than this one resolves to exactly this one, so the
     video's own background disappears into the page instead of sitting
     on it as a rectangle. Deeper than the app's navy-800, same family. */
  --night-floor: #1A2A40;

  position: relative;
  z-index: 2;
  /* Was 175svh. De schroefanimatie is klaar ruim voordat het blok
     op is, en die staart las als vierhonderd pixel donker niets.
     --fall rekent zelf met de hoogte, dus de val blijft kloppen. */
  height: 400svh;
  background: var(--night-floor);
}

.night__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;

  /* De scène speelt op zijn eigen klok, niet op de scrollpositie: wie
     snel doorscrolde joeg er anders in een flits doorheen. main.js zet
     .speelt zodra het toneel goed in beeld staat; de tijden hieronder
     doen de rest. De schroef draait 2,6 seconden, dan lost de hand op
     en nemen de twee zinnen om de beurt zijn plek in. */
}

/* No sweep any more: the dusk above already did the darkening, so the
   night simply continues the same navy and deepens a little on the way
   down. The drama is the picture coming up out of it, driven by --fall
   as before. */
.night__sky {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(
    180deg,
    var(--night-floor) 0%,
    #17253B 55%,
    #142137 100%
  );
}

/* The picture is generated on the same navy the sweep ends on, so a
   soft radial mask is all it takes for it to have no edge at all — it
   stops being a picture and becomes part of the dark. */
.night__art {
  position: absolute;
  inset: 0;
  z-index: 1;
  margin: 0;
  display: grid;
  place-items: center;

  /* a touch above centre — dead centre reads low under the fixed bar */
  padding-bottom: 12svh;

  /* The art is lightened onto the sky rather than laid over it: the
     footage's flat navy is darker than --night-floor everywhere, so it
     resolves away and only the hand, the tool and the glow survive.
     There is no edge to hide because there is no rectangle. It goes on
     the wrapper, not the video — the opacity ramp below makes this a
     stacking context, and a blend mode on a child would be trapped
     inside it and never reach the sky. */
  mix-blend-mode: lighten;

  /* Komt op uit de nacht en lost er aan het eind weer in op. In rust
     staat hij er niet; .speelt zet de tijdlijn in gang. */
  opacity: 0;
  scale: .99;

  /* The picture's own corners are --night-floor, so the rectangle is
     already invisible against the section and the mask does not have to
     hide it — cropping hard enough to bury four straight edges would
     take the screwdriver with them. All it does is feather the last of
     the glow away, right out to the edge. */
  /* Two masks, intersected. The radial takes the sides and the top;
     the linear does the bottom much harder, so the shaft runs out of
     light halfway down and the screw it is driving is never actually
     shown — you see the turning, not the fastener. */
  -webkit-mask-image:
    radial-gradient(
      80% 88% at 50% 44%,
      #000 50%,
      rgba(0, 0, 0, .72) 74%,
      transparent 99%
    ),
    linear-gradient(
      180deg,
      #000 0%,
      #000 46%,
      rgba(0, 0, 0, .58) 59%,
      rgba(0, 0, 0, .16) 70%,
      transparent 80%
    );
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(
      80% 88% at 50% 44%,
      #000 50%,
      rgba(0, 0, 0, .72) 74%,
      transparent 99%
    ),
    linear-gradient(
      180deg,
      #000 0%,
      #000 46%,
      rgba(0, 0, 0, .58) 59%,
      rgba(0, 0, 0, .16) 70%,
      transparent 80%
    );
  mask-composite: intersect;
}

.night__art picture { display: block; }

.night__art img {
  display: block;
  width: min(76vw, 960px);
  max-width: none;
  height: auto;
}

/* The video is laid over the still and only exists on desktop — below
   that it never gets a src, so not a byte of it is fetched. */
.night__still { display: block; position: relative; }

.night__motion {
  display: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: transparent;
  pointer-events: none;
}

@media (min-width: 1025px) {
  .night__motion { display: block; }
}

/* The one line the dark gets: it resolves the beat above it — the work
   that remains at night is the craft, not the paperwork. It rises with
   the same --fall that turns the screw, so it is never there before
   the dark is. */
/* De woorden staan waar de hand stond, niet eronder: de twee zinnen
   liggen in hetzelfde vak en nemen om de beurt die plek in. */
.night__woorden {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-items: center;
  padding: 0 24px 12svh;
  pointer-events: none;
}

.night__line {
  grid-area: 1 / 1;
  margin: 0;
  max-width: 22ch;
  text-align: center;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(28px, 4vw, 54px);
  line-height: 1.18;
  letter-spacing: calc(-.022em + (1 - var(--scherp, 0)) * .13em);
  text-wrap: balance;
  color: rgba(255, 253, 248, .92);

  /* Scherpstellen vanuit het midden: het masker groeit van een streepje
     in het midden naar volle breedte, terwijl de waas eruit loopt en de
     letters naar hun eigen spatiëring kruipen. */
  opacity: calc(var(--scherp, 0) * (1 - var(--uit, 0)));
  filter: blur(calc((1 - var(--scherp, 0)) * 15px + var(--uit, 0) * 13px));
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 16%, #000 84%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 16%, #000 84%, transparent 100%);
  -webkit-mask-size: calc(12% + var(--scherp, 0) * 180%) 100%;
  mask-size: calc(12% + var(--scherp, 0) * 180%) 100%;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

/* De tweede zin is kleiner en rustiger dan de eerste. */
.night__line--twee {
  font-weight: 400;
  font-size: clamp(21px, 2.8vw, 38px);
  max-width: 26ch;
  color: rgba(255, 253, 248, .84);
}

/* ── De tijdlijn ────────────────────────────────────────────
   Alles hangt aan --toon, dat main.js afleidt uit de scrollpositie van
   de sectie. Geen klok en geen terugslag, dus de scene is heen en terug
   precies hetzelfde; alle getallen hieronder zijn fracties van het stuk
   dat het toneel vastgeplakt staat.

   De schroef gaat voor, de woorden komen erna: je ziet het gebeuren en
   leest daarna wat het betekent. De draai krijgt daarbij ruim een derde
   van de scene; hij stond ooit op de eerste zes procent en was dan in
   anderhalve tel voorbij.

   .01–.08  de hand komt op
   .04–.30  de schroef draait (main.js stuurt de film)
   .08–.26  de hand staat stil, de draai is te volgen
   .26–.34  de hand lost op
   .30–.38  de eerste zin komt scherp vanuit het midden
   .38–.54  staat stil en leesbaar
   .54–.60  maakt plaats
   .58–.66  de tweede zin neemt dezelfde plek in
   .66–1    blijft staan, en loopt over in "Zie Ajeto aan het werk"  */

/* De hand komt op, draait de schroef, en maakt daarna plaats voor de
   woorden. */
.night__art {
  --op: clamp(0, calc((var(--toon, 0) - .01) * 14), 1);
  --weg: clamp(0, calc((var(--toon, 0) - .26) * 12.5), 1);
  opacity: calc(var(--op) * (1 - var(--weg)));
  scale: calc(1.03 - var(--op) * .03 + var(--weg) * .05);
  filter: blur(calc((1 - var(--op)) * 10px + var(--weg) * 8px));
}

/* Allebei de zinnen krijgen een brede rustplek, want daar ging het mis.
   De tweede stond ooit op 76 procent van het plakstuk, precies waar het
   toneel wegschuift: naar beneden zag je hem niet, op de terugweg wel.
   Het overgaan zelf gaat kort, zodat er van beide zinnen zo veel
   mogelijk tijd overblijft waarin ze gewoon stilstaan. */
.night__line--een {
  --scherp: clamp(0, calc((var(--toon, 0) - .30) * 12.5), 1);
  --uit: clamp(0, calc((var(--toon, 0) - .54) * 16), 1);
}

/* De tweede neemt dezelfde plek in en blijft tot het eind. */
.night__line--twee {
  --scherp: clamp(0, calc((var(--toon, 0) - .58) * 12.5), 1);
}

/* zonder waarnemer zet main.js dit erbij: alles staat er gewoon */
.night__stage.staat-stil .night__art,
.night__stage.staat-stil .night__line { animation: none !important; opacity: 1; }

@media (max-width: 900px) {
  /* no scrub on a phone, so the section only needs room for the sweep */
  .night { height: 108svh; }
  .night__art img,
  .night__art video { width: 104vw; }
}


/* ── Mobile menu toggle ─────────────────────────────────── */

.menu-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 42px;
  height: 42px;
  padding: 0 10px;
  border: 1px solid rgba(255, 253, 248, .22);
  border-radius: 12px;
  background: rgba(255, 253, 248, .07);
  cursor: pointer;
}

.menu-toggle span {
  display: block;
  height: 1.5px;
  width: 100%;
  border-radius: 2px;
  background: var(--cream);
  transition: transform .3s var(--ease), opacity .3s var(--ease);
}

.menu-toggle[aria-expanded="true"] span:first-child { transform: translateY(3.25px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:last-child  { transform: translateY(-3.25px) rotate(-45deg); }


/* ═══ Entrance choreography ═════════════════════════════════
   Artwork rises and resolves, bar drops in, copy lands
   line by line from the top down.                            */

.scene__art {
  translate: 0 44px;
  opacity: 0;
}

.scene__glow { opacity: 0; }

.topbar {
  translate: 0 -102%;
  opacity: 0;
}

[data-anim="line"] {
  opacity: 0;
  translate: 0 26px;
  will-change: translate, opacity;
}

.is-ready .scene__art {
  transition:
    translate 2000ms var(--ease),
    opacity   1300ms var(--ease-soft);
  translate: 0 0;
  opacity: 1;
}

.is-ready .scene__glow {
  transition: opacity 2200ms var(--ease-soft) 300ms;
  opacity: 1;
}

.is-ready .topbar {
  transition:
    translate 1000ms var(--ease) 300ms,
    opacity    700ms var(--ease-soft) 300ms;
  translate: 0 0;
  opacity: 1;
}

.is-ready [data-anim="line"] {
  transition:
    translate 1000ms var(--ease) calc(600ms + var(--i) * 115ms),
    opacity    780ms var(--ease-soft) calc(600ms + var(--i) * 115ms);
  translate: 0 0;
  opacity: 1;
}


/* ── Short / wide viewports: keep the horizon off the copy ─ */

@media (max-height: 760px) {
  .hero { padding-bottom: clamp(70px, 16vh, 150px); }
  .cta { margin-top: 26px; }
  .micro { margin-top: 18px; }
}


/* ── Small screens ──────────────────────────────────────── */

@media (max-width: 900px) {
  :root { --bar-h: 74px; }

  .nav,
  .topbar__actions { display: none; }

  .menu-toggle { display: flex; }

  .topbar { justify-content: space-between; }

  .brand img { height: 26px; }

  /* the landscape artwork would be a thin ribbon at phone widths,
     so scale it up and hold the van in frame */
  .art {
    width: 175%;
    margin-left: -30%;
  }

}

@media (max-width: 560px) {
  .headline { font-size: clamp(34px, 10vw, 46px); max-width: 14ch; }
  .sub { font-size: 16px; max-width: 34ch; }
  .cta { width: 100%; flex-direction: column; gap: 10px; }
  .cta .btn { width: 100%; max-width: 340px; }
  .hero { padding-bottom: clamp(120px, 26vh, 240px); }
  .art { width: 215%; margin-left: -36%; }
}


/* ── Het menu op een smal scherm ────────────────────────────
   Tot 22 oktober deed de hamburger niets: de knop zette menu-open op
   body, maar geen regel keek ernaar. Open wordt de topbalk zelf het
   menu, over het hele scherm: dezelfde links groot onder elkaar, en de
   twee knoppen onderaan, waar je duim al is. De pagina eronder scrolt
   zolang niet mee. Op de losse pagina's is de grond crème (pages.css). */

@media (max-width: 900px) {
  body.menu-open { overflow: hidden; }

  body.menu-open .topbar {
    height: 100svh;
    height: 100dvh;
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-rows: var(--bar-h) 1fr auto;
    align-items: center;
    padding-bottom: calc(22px + env(safe-area-inset-bottom, 0px));
    overflow-y: auto;
    overscroll-behavior: contain;
    background: #0B1526;
  }

  body.menu-open .topbar::before { opacity: 0; }
  body.menu-open .brand { grid-area: 1 / 1; }
  body.menu-open .menu-toggle { grid-area: 1 / 2; }

  body.menu-open .nav,
  body.menu-open .topbar__actions {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    animation: menu-in .42s var(--ease) both;
  }

  body.menu-open .nav {
    align-self: start;
    gap: 0;
    padding-top: 10px;
  }

  body.menu-open .nav a {
    padding: 15px 2px;
    border-radius: 0;
    border-bottom: 1px solid rgba(255, 253, 248, .1);
    font-family: var(--font-display);
    font-size: 25px;
    font-weight: 600;
    letter-spacing: -.02em;
    color: var(--cream);
  }

  body.menu-open .nav a::after { display: none; }
  body.menu-open .nav a:hover { background: none; }
  body.menu-open .nav a[aria-current="page"] { color: var(--amber); }

  body.menu-open .topbar__actions {
    align-items: stretch;
    gap: 10px;
    padding-top: 24px;
    animation-delay: .06s;
  }

  body.menu-open .topbar__actions .btn {
    padding: 15px 20px;
    font-size: 16px;
  }

  @keyframes menu-in {
    from { opacity: 0; translate: 0 10px; }
  }
}

@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  body.menu-open .nav,
  body.menu-open .topbar__actions { animation: none; }
}


/* ── Reduced motion ─────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  /* no scrubbing: the hero becomes an ordinary static screen */
  .scrolly { height: auto; }
  .is-scrolly .stage { position: relative; transform: none; }
  .is-scrolly .hero { opacity: 1; transform: none; }
  body.is-scrolly .pageflow { margin-top: 0; }

  .scene__art,
  .scene__glow,
  .topbar,
  [data-anim="line"] {
    transition: none !important;
    translate: 0 0 !important;
    opacity: 1 !important;
  }
  .topbar::before { transition: none !important; }

  .reveal-ready [data-reveal-item] {
    transition: none !important;
    translate: 0 0 !important;
    opacity: 1 !important;
  }


  /* no sweep and nothing pinned: the night is simply already there */
  .night { height: auto !important; }
  .night__stage { position: static !important; height: auto !important; }
  .night__sky { background: var(--night-floor) !important; }
  .night__art {
    position: static !important;
    opacity: 1 !important;
    scale: 1 !important;
    filter: none !important;
    padding: clamp(60px, 12vh, 120px) 0;
  }
  .btn { transition: none; }
}
