/* ═══════════════════════════════════════════════════════════
   Vordero Marketing — Shared Design Tokens & Base Styles
   Canonical source: docs/vordero/design/tokens.css
   Updated: 2026-05-29
   ═══════════════════════════════════════════════════════════ */

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

/* ── TOKENS (light mode = default) — Petrol + Slate (design system v2) ── */
:root {
  /* Brand — teal. #0d9488 is de MERK-mark (logo, accenten, labels).
     Interactieve vullingen gebruiken --btn-* hieronder: wit op #0d9488 haalt
     maar ~3.7:1 en zakt onder WCAG AA, wit op teal-700 haalt het wel. */
  --brand:    #0d9488;
  --brand-h:  #0f766e;
  --brand-p:  #134e4a;
  --brand-ll: rgba(13,148,136,.08);
  --brand-md: rgba(13,148,136,.18);

  /* Interactieve vulling (knoppen) — gelijk aan de app z'n --primary */
  --btn-bg:   #0f766e;
  --btn-bg-h: #115e59;
  --btn-fg:   #ffffff;

  /* Light surface (default) — slate */
  --bg:    #f8fafc;
  --bg-2:  #f1f5f9;
  --bg-3:  #e2e8f0;
  --bg-4:  #cbd5e1;

  /* Text — slate. Contrast tegen --bg (#f8fafc):
     text 17.9:1 · text-2 7.2:1 · text-3 5.3:1 · text-4 3.3:1.
     --text-4 haalt AA voor bodytekst NIET en is dus decoratief:
     alleen voor randen, iconen en losse micro-labels, nooit voor zinnen. */
  --text:   #0f172a;
  --text-2: #475569;
  --text-3: #5a6b80;
  --text-4: #7d8b9e;
  /* Tekst op een vlak dat in beide modi donker is: een foto, de nachtband, een
     gevulde merkknop. Bewust géén thema-afhankelijk token, en bewust wél een
     token: DESIGN.md (Tekstveilig, v9) verbiedt een rauwe hex in `color:`,
     ook waar het vlak nooit van kleur verandert, en de poort in
     scripts/ci/checks/productbeeld.mjs leest dat letterlijk. */
  --wit:    #ffffff;
  /* De slagschaduw op een kaart in de nachtband, die in beide modi donker is.
     Dieper dan --shadow-strong, want op nacht is een schaduw van 28% niet te
     zien. Zelfde redenering als --wit: invariant vlak, dus invariant token. */
  --nacht-schaduw: rgba(0, 0, 0, 0.85);

  /* Border */
  --border:   rgba(15,23,42,.08);
  --border-2: rgba(15,23,42,.14);

  /* Status */
  --green: #16A34A;
  --red:   #DC2626;
  --amber: #d97706;

  /* Theme-adaptive tokens */
  --nav-bg: rgba(248,250,252,.90);
  --deco-stroke: rgba(15,23,42,.05);
  --deco-hover: rgba(15,23,42,.035);
  --dot-1px: rgba(15,23,42,.05);
  --incasso-mid-1: #ecfdf5;
  --incasso-mid-2: #f0fdfa;
  --cta-start: #ecfdf5;
  --cta-mid: #f0fdfa;
  --pricing-feat-start: #ecfdf5;
  --pricing-feat-end: #d1fae5;
  /* Schaduw — vlak gehouden, gelijk aan de app. Zware drop-shadows lezen
     als landingspagina-sjabloon, vlakke vlakken lezen als software. */
  --shadow-strong: rgba(15,23,42,.07);
  --shadow-card: rgba(15,23,42,.06);
  /* Amber UI elements (decorative) */
  --amber-ui-bg: rgba(217,119,6,.10);
  --amber-ui-color: #b45309;
  --amber-ui-border: rgba(217,119,6,.22);

  /* Radius — de trap van de SITE. Hier stond "zelfde trap als de app
     (8/10/14/18)", en dat was onwaar: de app leidt zijn trap af van
     `--radius: 0.625rem` en komt uit op 6/8/10/12/14/22/26, waarin 18 niet
     bestaat. Gecorrigeerd 06-09 (golf 9 fase 4). */
  --r:    8px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-xl: 18px;
  /* 24 is de kaartradius van de SITE (DESIGN.md, De marketingsite: "24 is een
     kaart die de site tekent, 18 een voorwerp dat hij toont"). In de app is de
     kaart sinds v7 (24-08) 12 en niet 18; die 18 stond hier nog als verouderd
     citaat en is 06-09 rechtgezet. Hij ontbrak in deze
     trap, waardoor `border-radius: 24px` als rauw getal op twintig plekken in
     acht bestanden stond, met op `functies.astro:350` zelfs een commentaar dat
     naar DESIGN.md verwees. Een maat die je twintig keer overtypt hoort een
     token te zijn. Toegevoegd 01-09. */
  --r-2xl: 24px;

  /* Motion — zelfde vocabulaire als de app (globals.css). Elke pagina
     hardcodeerde tot nu toe zijn eigen cubic-beziers; nieuw werk gebruikt
     deze drie en niets anders. */
  --ease-out-soft: cubic-bezier(.22, 1, .36, 1);
  /* --ease-spring verwijderd (B13, golf 0): nul gebruikers; in de app is diezelfde token in v5 al weg. */
  --ease-standard: cubic-bezier(.4, 0, .2, 1);
  --dur-fast: .18s;
  --dur-base: .3s;
  --dur-slow: .55s;

  /* Grain — statische SVG-ruis als data-URI. Eén frame, dus geen
     rendering-kosten; alleen textuur. Gebruikt door .has-grain. */
  --grain-url: 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='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");

  /* Font. Inter sinds 06-09-2026, op Vincents keuze in golf 9: de homepage
     neemt fora's maatsysteem letterlijk over, en dan hoort de letter erbij.
     Geist blijft de letter van de app. De impeccable-detector noemt Inter
     "overused"; dat is hier een merkbesluit en geen bevinding. */
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; /* impeccable-disable-line overused-font -- merkbesluit */
  font-feature-settings: "ss01" on, "ss02" on, "cv01" on;
}

/* ── DARK MODE ──────────────────────────────────────────────── */
html[data-mode="dark"] {
  /* Brand — teal-400 op donker (zelfde als app dark) */
  --brand:    #2dd4bf;
  --brand-h:  #5eead4;
  --brand-p:  #99f6e4;
  --brand-ll: rgba(45,212,191,.10);
  --brand-md: rgba(45,212,191,.20);
  /* Op donker draagt de aanvoerder petrol met WITTE tekst (28-08, K-2).
     Hier stond merkpetrol #2dd4bf met donkere tekst; die leest als een
     tweede merkkleur en niet als dezelfde knop die op licht staat. Wit op
     #0f766e haalt 5,0:1, ruim boven de 4,5. Merkpetrol blijft wat hij is,
     een tekst- en accentkleur op donker, en gaat van --btn-bg af. */
  --btn-bg:   #0f766e;
  --btn-bg-h: #13867d;
  --btn-fg:   #ffffff;
  /* Slate-donker (zelfde familie als app dark) */
  --bg:    #0b1120;
  --bg-2:  #131c2b;
  --bg-3:  #1e293b;
  --bg-4:  #283548;
  /* Contrast tegen --bg (#0b1120): text 15.8:1 · text-2 9.1:1 · text-3 6.8:1 ·
     text-4 5.0:1. De oude waarden (#64748b/#475569) haalden 3.96:1 en 2.49:1
     en zakten dus onder AA op precies de plekken met fijne tekst. */
  --text:   #e2e8f0;
  --text-2: #a8b6c8;
  --text-3: #8b9cb3;
  --text-4: #74869d;
  --border:   rgba(226,232,240,.08);
  --border-2: rgba(226,232,240,.14);
  --green: #4ade80;
  --red:   #f87171;
  --amber: #fbbf24;
  --nav-bg: rgba(11,17,32,.88);
  --deco-stroke: rgba(226,232,240,.05);
  --deco-hover: rgba(226,232,240,.03);
  --dot-1px: rgba(226,232,240,.03);
  --incasso-mid-1: #0c1f1c;
  --incasso-mid-2: #0a1715;
  --cta-start: #0c1f1c;
  --cta-mid: #0a1715;
  --pricing-feat-start: #0c1f1c;
  --pricing-feat-end: #0a1715;
  --shadow-strong: rgba(0,0,0,.28);
  --shadow-card: rgba(0,0,0,.3);
  --amber-ui-bg: rgba(251,191,36,.12);
  --amber-ui-color: #FBBF24;
  --amber-ui-border: rgba(251,191,36,.25);
}

/* ── BASE ───────────────────────────────────────────────── */
/* clip in plaats van hidden: overflow-x:hidden maakt html/body zelf
   scrollcontainers, en dan hechten view()-timelines zich dáár aan in
   plaats van aan de viewport (waardoor scroll-reveals als "finished"
   starten). clip knipt hetzelfde af zonder scrollcontainer te worden. */
html { scroll-behavior: smooth; overflow-x: clip; }
body {
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}
a { color: inherit; text-decoration: none; }

/* ── LAYOUT ─────────────────────────────────────────────── */
.container {
  max-width: 1320px;
  margin: 0 auto;
  padding: 0 24px;
}
.container-narrow {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 24px;
}

/* ── BUTTONS ────────────────────────────────────────────── */
.btn {
  /* v6-dialect: 44px vaste hoogte (was ~40px via padding, en var(--r) = 8px
     radius die nergens anders in het systeem voorkomt). Een marketingknop is
     een doel en geen gereedschap — groter dan de 36px van de app-knop, maar
     dezelfde radius (10px = --r-md, gelijk aan DESIGN.md's inset-radius). */
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; padding: 0 22px;
  border-radius: var(--r-md);
  font-size: 15px; font-weight: 600;
  border: none; cursor: pointer;
  font-family: inherit;
  transition: background-color .15s, box-shadow .15s, border-color .15s;
  text-decoration: none;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
.btn-primary {
  background: var(--btn-bg);
  color: var(--btn-fg);
  box-shadow: 0 1px 2px rgba(15,23,42,.06);
}
.btn-primary:hover {
  background: var(--btn-bg-h);
  box-shadow: 0 2px 6px rgba(15,23,42,.10);
}

/* HET GENESTELDE PIJLTJE (01-09, V-C uit de kritiekronde).
   De pijl zit in zijn eigen cirkel tegen de binnenrand, en niet naakt naast de
   tekst. Hij is een `::after` en dus een flex-item, zodat de `gap: 8px` van
   `.btn` de afstand al regelt; `margin-right` trekt hem tegen de padding aan.

   BEWEGING. Alleen `transform` en `opacity`, 150ms (de duur voor een tint) op
   `--ease-out-soft`. Geen veer en geen stuiter: de skill die dit voorstelde
   vraagt om spring physics, en die staan sinds v5 niet meer in de tokens.

   OP ELKE PAGINA-CTA EN NIET ALLEEN OP `.btn-primary`. De uitgelichte
   prijskaart gebruikt `.plan-knop--vol` en het slot `.slot-knop`; zonder die
   twee zou de ene CTA een pijl dragen en de andere niet, en dat is slechter
   dan geen pijl. De kopknop krijgt hem niet: die is klein en herhaalt alleen.

   NIET OP DE DUIMBALK. Die knop is volle breedte en gecentreerd; een pijl in
   de hoek van een balk van 358px leest als een tweede handeling in plaats van
   als versiering van dezelfde. */
.btn-primary::after,
.plan-knop--vol::after,
.slot-knop::after {
  content: "";
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  margin-right: -10px;
  border-radius: 999px;
  background-color: rgba(255, 255, 255, 0.18);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5 8.5 3.5M4.2 3.5h4.3v4.3'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  transition:
    transform 150ms var(--ease-out-soft),
    background-color 150ms var(--ease-out-soft);
}
.btn-primary:hover::after,
.plan-knop--vol:hover::after,
.slot-knop:hover::after {
  transform: translate(2px, -1px);
  background-color: rgba(255, 255, 255, 0.28);
}
.duimbalk .btn-primary::after { content: none; }
/* Alleen onder html[data-rust], de schakelaar in Basis.astro (05-09). */
html[data-rust] .btn-primary::after,
html[data-rust] .plan-knop--vol::after,
html[data-rust] .slot-knop::after { transition-duration: 1ms; }
.btn-ghost {
  background: transparent;
  color: var(--text-2);
  border: 1px solid var(--border-2);
}
.btn-ghost:hover { border-color: var(--border-2); color: var(--text); background: var(--bg-3); }
/* Eigen expliciete hoogte, niet alleen padding: .btn zet nu height:44px met
   box-sizing:border-box (globale reset), dus een grotere padding zonder een
   grotere hoogte duwt de tekst plat. */
.btn-lg { height: 52px; padding: 0 28px; font-size: 16px; border-radius: var(--r-lg); }

/* ── VIEW TRANSITIONS ───────────────────────────────────────
   Cross-document paginaovergangen, native. Gemaakt voor precies deze
   architectuur (statische MPA, clean URLs op Vercel). Browsers zonder
   ondersteuning (vooral Firefox) doen een gewone navigatie; niemand
   merkt iets. De nav krijgt een eigen naam zodat hij blijft staan
   terwijl de rest van de pagina cross-fadet: dat is wat het als een
   app laat voelen in plaats van als losse documenten. */
@view-transition { navigation: auto; }
/* Altijd (05-09, Vincent): de site negeert prefers-reduced-motion; zie Basis.astro. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: .22s;
  animation-timing-function: var(--ease-standard);
}
/* Alleen onder html[data-rust], de schakelaar in Basis.astro (05-09). */
html[data-rust]::view-transition-group(*),
html[data-rust]::view-transition-old(*),
html[data-rust]::view-transition-new(*) { animation: none !important; }

/* ── NAV ────────────────────────────────────────────────── */
.nav {
  position: sticky; top: 0; z-index: 100;
  background: var(--nav-bg);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--border);
  view-transition-name: site-nav;
}
.nav-inner {
  display: flex; align-items: center;
  height: 62px;
}
.nav-logo {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none;
}
.nav-wordmark {
  font-size: 17px; font-weight: 700;
  color: var(--text);
  letter-spacing: -.03em;
}
.nav-right {
  margin-left: auto;
  display: flex; align-items: center; gap: 20px;
}
.nav-url {
  /* Geen monospace: de app gebruikt die bewust niet, dus de site ook niet.
     tabular-nums houdt cijferkolommen wel uitgelijnd. */
  font-variant-numeric: tabular-nums;
  font-size: 12px; font-weight: 500;
  color: var(--text-3);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.nav-right .nav-links {
  display: flex; align-items: center; gap: 4px;
  margin-left: 0;
}
.nav-links > a:not(.btn) {
  font-size: 14px; font-weight: 500;
  color: var(--text-2);
  padding: 6px 12px;
  border-radius: var(--r);
  transition: color .12s, background .12s;
}
.nav-links > a.active { color: var(--text); }
.nav-links > a:not(.btn):hover { color: var(--text); background: var(--bg-3); }

/* ── Nav-dropdowns ──────────────────────────────────────────
   Drie groepen (Product, Diensten, Juridisch) in plaats van zes losse links.

   Openen kan op drie manieren, en de eerste twee hebben géén JavaScript nodig:
   hover voor de muis, :focus-within voor het toetsenbord, en aria-expanded voor
   de klik. Valt het script uit, dan is het menu dus nog steeds bereikbaar. */
.nav-group { position: relative; }
.nav-group-btn {
  display: inline-flex; align-items: center; gap: 5px;
  font: inherit;
  font-size: 14px; font-weight: 500;
  color: var(--text-2);
  background: none; border: none; cursor: pointer;
  padding: 6px 10px;
  border-radius: var(--r);
  transition: color .12s, background .12s;
}
.nav-group-btn:hover { color: var(--text); background: var(--bg-3); }
.nav-chev { transition: transform .15s; flex-shrink: 0; opacity: .7; }

/* De groep van de huidige pagina blijft opgelicht. :has() bespaart stitch.mjs
   een tweede markering: de actieve klasse staat al op de link eronder. */
.nav-group:has(a.active) > .nav-group-btn { color: var(--text); }

.nav-menu {
  position: absolute; top: calc(100% + 6px); left: 0;
  min-width: 210px;
  display: flex; flex-direction: column; gap: 2px;
  padding: 6px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: 0 8px 28px var(--shadow-strong), 0 1px 2px var(--shadow-card);
  opacity: 0; visibility: hidden;
  transform: translateY(-4px);
  transition: opacity .14s, transform .14s, visibility .14s;
  z-index: 10;
}
.nav-group:hover > .nav-menu,
.nav-group:focus-within > .nav-menu,
.nav-group-btn[aria-expanded="true"] + .nav-menu {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.nav-group:hover > .nav-group-btn .nav-chev,
.nav-group:focus-within > .nav-group-btn .nav-chev,
.nav-group-btn[aria-expanded="true"] .nav-chev { transform: rotate(180deg); }

/* Een onzichtbare brug over de 6px tussen knop en paneel. Zonder deze valt de
   hover weg zodra de muis het gat oversteekt en klapt het menu dicht. */
.nav-menu::before {
  content: ""; position: absolute; top: -8px; left: 0; right: 0; height: 8px;
}
.nav-menu > a {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: 14px; font-weight: 500;
  color: var(--text-2);
  padding: 8px 10px;
  border-radius: var(--r-md);
  white-space: nowrap;
  transition: color .12s, background .12s;
}
.nav-menu > a:hover { color: var(--text); background: var(--bg-3); }
.nav-menu > a.active { color: var(--text); background: var(--bg-3); }
.nav-badge {
  background: var(--btn-bg); color: var(--btn-fg);
  font-size: 12.5px; font-weight: 700;
  padding: 1px 6px; border-radius: 999px;
  line-height: 1.5; letter-spacing: .03em;
  flex-shrink: 0;
}
/* Alleen onder html[data-rust], de schakelaar in Basis.astro (05-09). */
html[data-rust] .nav-menu,
html[data-rust] .nav-chev { transition: none; }
.nav-mobile-btn {
  display: none; background: none; border: none;
  cursor: pointer; color: var(--text); margin-left: 12px; padding: 6px;
}
.nav-mobile {
  display: none; flex-direction: column; gap: 2px;
  padding: 10px 16px 16px;
  border-top: 1px solid var(--border);
}
.nav-mobile.open { display: flex; }
.nav-mobile a {
  padding: 10px 12px; font-size: 15px; font-weight: 500;
  color: var(--text-2); border-radius: var(--r);
}
.nav-mobile a { display: flex; align-items: center; gap: 8px; }
.nav-mobile a:hover { background: var(--bg-3); color: var(--text); }
.nav-mobile-kop {
  padding: 12px 12px 4px;
  font-size: 12.5px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-3);
}
.nav-mobile-kop:first-child { padding-top: 4px; }
/* ── Nav actions (Inloggen + Start gratis) ──────────── */
.nav-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.nav-login-link { font-size: 13px; font-weight: 500; color: var(--text-2); text-decoration: none; transition: color .12s; white-space: nowrap; padding: 6px 8px; border-radius: var(--r); }
.nav-login-link:hover { color: var(--text); }
.nav-start-btn { display: inline-flex; align-items: center; background: var(--btn-bg); color: var(--btn-fg); font-size: 13px; font-weight: 600; padding: 7px 14px; border-radius: var(--r); text-decoration: none; white-space: nowrap; transition: background .15s; }
.nav-start-btn:hover { background: var(--btn-bg-h); }

/* ── FOCUS ──────────────────────────────────────────────────
   Toetsenbordgebruikers hadden site-breed geen enkele zichtbare
   focus-indicator. Eén gedeelde ring voor alles wat focusbaar is.

   `--focus-halo` is de tweede toon, en hij bestaat voor precies één situatie:
   een ring die op fotografie ligt. Op een egale grond haalt één kleur de 3:1
   van WCAG 2.2 SC 1.4.11 gewoon; op een foto niet, want die heeft donkere
   hoeken én een lichte highlight. Gemeten 29-08 over de 98.049 pixels onder
   de navbalk in de hero: merkpetrol haalt daar in het slechtste geval 1,02:1
   en wit 1,81:1. Een witte ring mét deze halo eromheen haalt 3,87:1, omdat per
   pixel de een of de ander draagt.

   Alleen gebruiken waar een ring op een beeld of een verloop ligt. Op een
   egaal vlak is hij overbodig en tekent hij een tweede rand die er niet hoort. */
:root {
  /* De plaat uit ons eigen app-icoon: het vlak waar het merkteken op staat.
     Bewust geen `--nacht` (#0b1120): die is blauwig en deze is neutraal, en het
     verschil is precies wat het icoon zijn eigen materiaal geeft. Hij stond tot
     29-08 als letterlijke waarde in Orbit.astro, en toen de mobiele merkenrij
     zijn anker terugkreeg werd dat een tweede kopie. Twee gebruikers is het
     moment waarop een waarde een naam hoort te krijgen. */
  --merkplaat: #0b0d0e;
  --focus-halo: rgba(0, 0, 0, 0.7);
  /* Dezelfde gedachte, voor type op fotografie (29-08, K-5). Een tekstgloed en
     geen sluier over de foto: hij zit tegen de letter aan, dus op de donkere
     delen van een opname is hij onzichtbaar en op de lichte plekken geeft hij
     de letter zijn eigen grond mee. Gemeten op de hero: de onderregel stond
     over het grootste deel van zijn lengte op 15,3:1, maar zakte op de lichtste
     twee procent van de foto naar 1,32:1 (mobiel) en 1,21:1 (desktop). Een
     sluier over de hele foto lost dat ook op, en dat is precies het trucje dat
     Hero.astro zelf afwijst. */
  --foto-tekstgloed: 0 1px 2px rgba(0, 0, 0, 0.6), 0 0 5px rgba(0, 0, 0, 0.85);
}

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: var(--r);
}
.btn:focus-visible,
.nav-start-btn:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 3px;
}

/* ── KAART-BASIS ────────────────────────────────────────────
   Eén bron voor het kaart-uiterlijk. Elke pagina definieerde tot nu toe
   zijn eigen kaartklassen (feature-card, pricing-card, pain-card, say-card,
   door, proof-tile, included-item, plan-card, ...) met net andere radius,
   padding en schaduw. De look staat nu hier; per-pagina blijft alleen wat
   echt uniek is (grid-plaatsing, afwijkende padding, accenten). */
.card-base {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 24px 22px;
}
.card-base--raised {
  background: var(--bg-3);
  border-radius: var(--r-xl);
  padding: 32px 28px;
}
.card-base--accent {
  background: var(--brand-ll);
  border-color: var(--brand-md);
}
/* Standaard-breekpunten: 600 (mobiel), 960 (tablet), 1280 (breed).
   Per-pagina media queries horen op deze drie te collapsen. */

/* ── SECTIONS ───────────────────────────────────────────── */
.section { padding: 96px 0; }
.section-alt { background: var(--bg-2); }
.section-header {
  text-align: center;
  margin: 0 auto 56px;
  /* Zonder deze cap loopt een sectiekop over de volle 1320px, wat neerkomt
     op ~150 tekens per regel. Onleesbaar lang voor een kop of introzin. */
  max-width: 780px;
}
.section-header h2 {
  font-size: clamp(28px, 4vw, 40px);
  font-weight: 700;
  letter-spacing: -.03em;
  line-height: 1.15;
  margin-bottom: 16px;
}
.section-header p {
  font-size: 17px;
  color: var(--text-2);
  line-height: 1.65;
}

/* ── FOOTER ─────────────────────────────────────────────── */
.footer {
  border-top: 1px solid var(--border);
  padding: 48px 0 32px;
}
.footer-inner {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: 40px;
  margin-bottom: 40px;
}
.footer-brand p {
  font-size: 14px;
  color: var(--text-3);
  line-height: 1.6;
  margin-top: 12px;
  max-width: 240px;
}
/* De footer komt uit partials/footer.html (tools/stitch.mjs) en moet er op
   elke pagina hetzelfde uitzien, ook op pagina's zonder eigen ul-reset. */
.footer-brand-logo { display: flex; align-items: center; gap: 8px; }
.footer-brand-name { font-weight: 700; color: var(--text); }
.footer-by { margin-top: 14px; font-size: 13px; color: var(--text-3); }
.footer-col ul { list-style: none; margin: 0; padding: 0; }
.footer-col h4 {
  font-size: 12px; font-weight: 600;
  color: var(--text-3);
  text-transform: uppercase;
  letter-spacing: .08em;
  margin-bottom: 14px;
}
.footer-col a {
  display: block;
  font-size: 14px;
  color: var(--text-2);
  margin-bottom: 8px;
  transition: color .12s;
}
.footer-col a:hover { color: var(--text); }
.footer-bottom {
  display: flex; align-items: center; justify-content: space-between;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  font-size: 13px;
  color: var(--text-3);
}
.footer-bottom a { color: var(--text-3); transition: color .12s; }
.footer-bottom a:hover { color: var(--text-2); }

/* ── TRUST ITEMS ────────────────────────────────────────── */
.trust-item {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; font-weight: 500;
  color: var(--text-2);
}
.trust-item svg {
  width: 14px; height: 14px;
  stroke: var(--brand);
}

/* ── RESPONSIVE ─────────────────────────────────────────── */
@media (max-width: 960px) {
  .footer-inner  { grid-template-columns: 1fr; gap: 32px; }
  .nav-right .nav-links,
  .nav-inner > .nav-links  { display: none; }
  .nav-url                 { display: none; }
  .nav-mobile-btn          { display: block; }
  .nav-actions             { display: none; }
}
@media (max-width: 600px) {
  .section { padding: 64px 0; }
}

/* ═══════════════════════════════════════════════════════════
   DESIGN-FUNDAMENT v2 (register: zelfverzekerd en rustig)
   Typografie draagt de pagina; teal is het enige accent; motion is
   kort en bevestigend. Alles hieronder is de gedeelde vocabulaire
   waar de herontwerpronde op bouwt.
   ═══════════════════════════════════════════════════════════ */

/* ── TYPESCHAAL ─────────────────────────────────────────────
   Vaste trap in plaats van per-element font-sizes. De display-maat
   is bewust groot (tot 72px): in dit register is de kop het beeld. */
.t-display {
  font-size: clamp(44px, 6.5vw, 72px);
  font-weight: 800; line-height: 1.04;
  letter-spacing: -.035em;
  text-wrap: balance;
}
.t-h1 {
  font-size: clamp(36px, 5vw, 56px);
  font-weight: 800; line-height: 1.08;
  letter-spacing: -.03em;
  text-wrap: balance;
}
.t-h2 {
  font-size: clamp(28px, 4vw, 40px);
  font-weight: 700; line-height: 1.15;
  letter-spacing: -.03em;
  text-wrap: balance;
}
.t-h3 { font-size: 22px; font-weight: 700; line-height: 1.25; letter-spacing: -.02em; }
.t-lead  { font-size: clamp(17px, 2vw, 20px); line-height: 1.6; color: var(--text-2); text-wrap: pretty; }
.t-body  { font-size: 15px; line-height: 1.65; color: var(--text-2); }
.t-small { font-size: 13.5px; line-height: 1.55; color: var(--text-3); }
.t-label {
  font-size: 12.5px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-3);
}
.t-stat {
  font-size: clamp(28px, 3.4vw, 40px);
  font-weight: 800; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* ── BALKENMOTIEF (.vbars) ──────────────────────────────────
   Het merkteken (drie aflopende balken) als herbruikbaar element:
   Payt heeft de markeerstift, Moneybird de chevron, wij de balken.
   Markup: <span class="vbars"><i></i><i></i><i></i></span>

   Breedtes en kleuren komen exact uit het logo (32/22/12 in het
   32-stelsel, dus 100/68,75/37,5 procent), zodat dit motief en het
   merkteken dezelfde vorm hebben en niet twee varianten worden.

   Drie volle tinten in plaats van één kleur op aflopende
   doorzichtigheid: dat is dezelfde keuze als bij het logo, zodat het
   ook op een gekleurd vlak leesbaar blijft. De golf animeert daarom
   op vorm en niet meer op opacity.

   Varianten:
     .vbars            statisch merkteken
     .vbars--wave      golvende laadstaat / levend accent
     .vbars--progress  voortgang: data-step="0..3" bepaalt hoeveel vol
     .vbars-divider    sectiescheiding met het teken in het midden   */
/* De maatvoering komt uit het echte merkteken (components/ui/VBars.tsx en de
   mails): drie balken in een vak van 32, hoogte 5, op y 4, 12 en 20, breed
   32, 22 en 12. Hier stond een benadering met flex en een gelijke tussenruimte
   van 18%: dat klopt op 18 pixels en loopt zichtbaar uit de pas zodra het teken
   groot wordt, en juist in de hero is hij groot. Nu staat elke balk op zijn
   exacte plek, uitgedrukt als breukdeel van datzelfde vak van 32, zodat het
   teken op elk formaat dezelfde verhoudingen houdt als in de app. */
.vbars {
  --vb-size: 18px;
  position: relative;
  display: inline-block;
  width: var(--vb-size); height: var(--vb-size);
  flex-shrink: 0;
}
.vbars i {
  position: absolute; left: 0;
  display: block;
  height: 15.625%;            /* 5 / 32 */
  border-radius: 999px;
  background: var(--vb-tint, var(--brand));
  transform-origin: left center;
}
.vbars i:nth-child(1) { top: 12.5%;  width: 100%;    --vb-tint: #2DD4BF; }
.vbars i:nth-child(2) { top: 37.5%;  width: 68.75%;  --vb-tint: #14B8A6; }
.vbars i:nth-child(3) { top: 62.5%;  width: 37.5%;   --vb-tint: #0D9488; }

.vbars--wave i { animation: vbar-wave 1.4s ease-in-out infinite; }
.vbars--wave i:nth-child(2) { animation-delay: .35s; }
.vbars--wave i:nth-child(3) { animation-delay: .7s; }
@keyframes vbar-wave {
  0%, 100% { transform: scaleX(1); }
  50%      { transform: scaleX(1.12); }
}

.vbars--progress i { opacity: .18; transition: opacity var(--dur-base) var(--ease-out-soft); }
.vbars--progress[data-step="1"] i:nth-child(-n+1),
.vbars--progress[data-step="2"] i:nth-child(-n+2),
.vbars--progress[data-step="3"] i:nth-child(-n+3) { opacity: 1; }

/* Minder beweging betekent minder beweging, niet minder informatie: de
   balken blijven staan, alleen de golf stopt. */
/* Alleen onder html[data-rust], de schakelaar in Basis.astro (05-09). */
html[data-rust] .vbars--wave i { animation: none; }

.vbars-divider {
  display: flex; align-items: center; gap: 18px;
  margin: 0 auto; max-width: 1320px; padding: 0 24px;
}
.vbars-divider::before,
.vbars-divider::after {
  content: ''; flex: 1; height: 1px; background: var(--border-2);
}

/* ── AMBIENT ACHTERGROND ───────────────────────────────────
   Gelaagde radial-gradients, geport uit de app. Vervangt elke
   behoefte aan WebGL: dit is de "dure" hero-achtergrond. */
.bg-ambient {
  background:
    radial-gradient(60rem 40rem at 85% -10%, color-mix(in srgb, var(--brand) 7%, transparent), transparent 60%),
    radial-gradient(50rem 36rem at -5% 110%, color-mix(in srgb, var(--text) 4%, transparent), transparent 55%),
    var(--bg);
}

/* ── GRAIN ──────────────────────────────────────────────────
   Statische ruis-overlay. Het detail dat "duur" leest op alle
   referentiesites, voor nul runtime-kosten. Opt-in per sectie:
   class="has-grain" op een element met position:relative context. */
.has-grain { position: relative; }
.has-grain::after {
  content: ''; position: absolute; inset: 0;
  background-image: var(--grain-url);
  opacity: .05; pointer-events: none;
  z-index: 1;
}
html[data-mode="dark"] .has-grain::after { opacity: .07; }

/* ── SCROLL-REVEAL (CSS scroll-driven, vervangt JS-observers) ──
   De reveal verplaatst, hij onthult niet. Dat is een correctie van 18-08.

   Hier stond dat zichtbaar de default was, met een @supports-guard eromheen.
   Die guard beschermt alleen browsers die `animation-timeline` NIET kennen.
   In elke browser die hem wél kent staat een view()-tijdlijn op progress 0
   zolang het element onder de viewport hangt, en progress 0 is de
   from-keyframe. Met `opacity: 0` daarin bestaat de inhoud dus echt niet:
   niet in print, niet in een screenshot, niet in een PDF, en niet voor wie
   landt zonder te scrollen. Gemeten op 18-08: 34 van de 39 reveal-elementen
   op de site stonden bij het laden op opacity 0, waaronder de drie
   prijskaarten en de slot-CTA van de homepage.

   Daarom animeert de from-keyframe alleen nog de translatie. De beweging
   blijft voor wie scrolt; de inhoud bestaat voor iedereen. De bredere vraag
   of deze site überhaupt een reveal hoort te hebben (Helder zegt: beweging
   bevestigt een toestandswisseling, en langsscrollen is er geen) staat in
   het kritiekregister van 18-08. */
@supports (animation-timeline: view()) {
  /* Altijd (05-09, Vincent): de site negeert prefers-reduced-motion; zie Basis.astro. */
  .sr, .reveal, .rv {
    animation: sr-in linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 55%;
  }
  .sr-d1, .reveal-d1 { animation-range: entry 8%  entry 63%; }
  .sr-d2, .reveal-d2 { animation-range: entry 16% entry 71%; }
  .sr-d3, .reveal-d3 { animation-range: entry 24% entry 79%; }
}
@keyframes sr-in {
  from { transform: translateY(22px); }
  to   { transform: none; }
}
/* Papier scrolt niet, dus een scroll-tijdlijn komt er nooit vooruit. Zonder
   dit blok drukt de browser elk reveal-element 22px verschoven af. */
@media print {
  .sr, .reveal, .rv { animation: none !important; transform: none !important; }
}
/* De oude klassen .reveal en .rv zijn hierboven op het nieuwe systeem gemapt
   zodat de honderden bestaande class-attributen niet hoefden te veranderen.
   De per-pagina definities (opacity:0 + IntersectionObserver + .visible/.in)
   zijn uit de pagina's verwijderd; dit is nu de enige bron. */

/* ── REDUCED MOTION ─────────────────────────────────────────
   Eén vangnet voor de hele site, overgenomen uit de app
   (app-next/app/globals.css). Elke pagina had hiervoor zijn eigen
   opt-in-guards per selector, waardoor er gaten vielen: pricing en
   starten draaiden GSAP ongeacht de voorkeur, en de chat-demo in de
   hero animeerde altijd. Een blanket-regel dekt ook alles wat we
   hierna nog bouwen, in plaats van dat elke nieuwe animatie er weer
   handmatig aan gedacht moet worden.

   Niet op 0 maar op 0.01ms: animaties moeten hun eindstaat wél
   bereiken (een `forwards`-animatie die nooit draait laat het element
   op opacity 0 staan), ze mogen alleen geen waarneembare beweging
   maken. */
/* Alleen onder html[data-rust], de schakelaar in Basis.astro (05-09). */
html[data-rust] *,
html[data-rust] *::before,
html[data-rust] *::after {
  animation-duration: .01ms !important;
  animation-iteration-count: 1 !important;
  scroll-behavior: auto !important;
  transition-property: color, background-color, border-color,
    text-decoration-color, fill, stroke, opacity, box-shadow,
    outline-color !important;
}

/* ═══════════════════════════════════════════════════════════
   ELEVATED v3 — premiumlaag voor de herontwerpronde
   Register: rustig, licht, product-first. Eén teal-signatuur
   (aurora), één kinetische kop-toets, subtiele diepte. Alles
   theme-aware via de tokens hierboven en gated op reduced-motion.
   Dit is de gedeelde vocabulaire die over alle pagina's uitrolt.
   ═══════════════════════════════════════════════════════════ */

/* Aurora — de "dure" hero-achtergrond, iets rijker dan .bg-ambient,
   met de teal-gloed naar de hoek waar het productvenster staat.
   Gelaagde radial-gradients, nul runtime-kosten, vervangt WebGL. */
.bg-aurora {
  position: relative;
  background:
    radial-gradient(46rem 32rem at 82% 2%,  color-mix(in srgb, var(--brand) 13%, transparent), transparent 60%),
    radial-gradient(38rem 30rem at 4% 104%, color-mix(in srgb, var(--brand) 7%, transparent),  transparent 56%),
    var(--bg);
}

/* Kinetische kop-toets — een lijn die zichzelf onder een sleutelwoord
   trekt bij het laden. Eén accent, niet meer (Chanel: doe er één af).
   box-decoration-break houdt de lijn heel over een regelafbreking heen.
   Reduced-motion: de lijn staat meteen vol (blanket-regel + expliciet). */
.hl-underline {
  background-image: linear-gradient(var(--brand), var(--brand));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 3px;
  padding-bottom: .12em;
  animation: hl-draw .9s var(--ease-out-soft) .8s forwards;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
@keyframes hl-draw { to { background-size: 100% 3px; } }
/* Alleen onder html[data-rust], de schakelaar in Basis.astro (05-09). */
html[data-rust] .hl-underline { animation: none; background-size: 100% 3px; }

/* `.floaty` verwijderd (v10). Nul gebruikers, en de reden erboven was letterlijk
   "de indruk van een levend systeem": dat is versiering, en DESIGN.md zegt sinds
   v9 dat doorlopende beweging moet laten zien dat het product iets doet dat in
   werkelijkheid ook beweegt. Gevonden door de nieuwe bewegingspoort. */

/* ═══════════════════════════════════════════════════════════
   COMPOSITIE-TOOLKIT v4 — ritme-varianten, bento, frame, donker moment
   Breekt de "verticale stapel gecentreerde secties". Elke pagina componeert
   hieruit i.p.v. overal de centered .section + gecentreerde .section-header.
   Puur additief: bestaande selectors ongewijzigd, dus geen pagina verandert
   tot een pagina deze klassen daadwerkelijk gebruikt.
   ═══════════════════════════════════════════════════════════ */

/* ── Section-header varianten: doorbreek de gecentreerde mold ─────
   .section-header is default centered (max-width 780, text-align center);
   dit is de #1 reden dat elke sectie dezelfde vorm heeft. Deze varianten
   staan links-uitgelijnd + genummerd toe. */
.section-header--left { text-align: left; margin-left: 0; margin-right: 0; max-width: 46rem; }
.section-header--left h2 { margin-left: 0; margin-right: 0; }
.section-eyebrow {
  display: inline-flex; align-items: baseline; gap: 12px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--brand); margin-bottom: 14px;
}
.section-eyebrow .num { font-variant-numeric: tabular-nums; color: var(--text-4); }

/* De losse eyebrow boven een kop. Stond tot 28-08 als hetzelfde blok van
   zeven regels in vijf paginabestanden, en op vier andere pagina's
   (/contact, /tools, /vergelijk, elke rekentool) helemaal niet: daar was
   `class="eyebrow"` een gewoon woord van 16px in inkt, boven een h1. Eén
   definitie, hier. Onderscheid met `.section-eyebrow`: die hoort bij een
   `.section-header--left`, draagt petrol en kan een nummer bevatten; deze
   is de stille variant in `--text-3`. */
.eyebrow {
  display: block;
  margin-bottom: 12px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-3);
}

/* ── Hero, tweede vorm (kritiekregister 2026-08-18, voorstel 4) ──────
   .hero blijft lokaal de gecentreerde eerste vorm (home, pricing,
   onboarding, verliescheck). .hero--left is de tweede: linksuitgelijnd,
   met .section-eyebrow + t-display + t-lead, zonder hl-underline en
   zonder vinkjesrij — het patroon van /wetgeving. Voor /features,
   /hoe-het-werkt, /integraties en /over. */
.hero--left { padding: 92px 0 56px; text-align: left; }
.hero--left .t-lead { max-width: 62ch; margin: 0; }

/* ── Ritme: asymmetrische split-sectie (tekst + beeld naast elkaar) ──
   Standaard tekst links / beeld rechts; .is-visual-left draait om (om-en-om
   ritme over een pagina). Stapelt op mobiel. */
.section--split .split-inner {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 40px 64px; align-items: center;
}
.section--split.is-visual-left .split-inner { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); }
.section--split.is-visual-left .split-copy { order: 2; }
.split-copy { max-width: 40rem; }
.split-copy h2 { font-size: clamp(28px, 4vw, 40px); font-weight: 800; letter-spacing: -.03em; line-height: 1.12; margin-bottom: 16px; text-wrap: balance; }
.split-copy > p { font-size: clamp(17px, 2vw, 20px); color: var(--text-2); line-height: 1.6; }

/* ── Wide / tight ritme ── */
.section--tight { padding: 64px 0; }
.section--wide > .container { max-width: 1480px; }

/* ── BENTO — bewuste celratio's, heterogene inhoud, één anker ──
   HARDE REGEL: alleen bij >=3 verschillende inhoudstypes met één 2x-anker-cel.
   Homogene gelijk-gewicht lijsten NOOIT als bento (dan een compacte lijst). */
.bento { display: grid; grid-template-columns: repeat(6, 1fr); gap: 16px; }
.bento > .b-cell {
  background: var(--bg-2); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: 24px; grid-column: span 2;
}
.bento .b-anchor { grid-column: span 4; grid-row: span 2; }
.bento .b-wide   { grid-column: span 4; }
.bento .b-half   { grid-column: span 3; }
.bento .b-tall   { grid-row: span 2; }
.bento .b-full   { grid-column: 1 / -1; }

/* ═══════════════════════════════════════════════════════════
   PRODUCTBEELD (.pv) — het enige frame voor een beeld van het product

   Vervangt vier verschillende nagebouwde browserbalken (.vdemo-chrome,
   .frame-chrome, .sv-bar, .mockup-topbar) door één vorm zonder balk. Dat
   was al de MOCK-regel uit het kritiekregister van 18-08 ("18px radius,
   paneelschaduw, GEEN nagebouwde browserbalk met stoplichtjes") en die is
   nooit uitgevoerd.

   Een productbeeld is bewust géén schermafdruk en géén nagebouwd scherm,
   maar een BEWERKT FRAGMENT: één idee, geen zijbalk, geen zoekbalk, geen
   paginakop. De bronnen die Vincent aandroeg zijn daar eensluidend over
   ("a cluster of edited interface elements"; "showing people everything
   wouldn't be as powerful as showing a marketer a fragment"). Het
   vocabulaire — kolomnamen, statuspillen, bedragopmaak — komt wél uit de
   echte app, anders wordt het vaag. Zie DESIGN.md, "De marketingsite".

   Alles op tokens, dus licht en donker uit één bron. Een rauwe hex hier is
   een fout die de donkere modus breekt; de poort in
   scripts/ci/checks/productbeeld.mjs bewaakt dat.
   ═══════════════════════════════════════════════════════════ */
.pv { margin: 0; position: relative; }
.pv-vlak {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: 0 2px 4px var(--shadow-card), 0 24px 48px -24px var(--shadow-strong);
  overflow: hidden;
}
.pv-body { padding: 22px 24px; }
.pv-bijschrift {
  margin: 10px 0 0;
  font-size: 12.5px;
  letter-spacing: .03em;
  color: var(--text-4);
}

/* Kolomkop en rij — spiegelen de tabel in de app: kop op eyebrow, rij op
   body, één haarlijn per rij, bedragen rechts. */
.pv-kop {
  display: flex; align-items: center; gap: 12px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--text-4);
  padding-bottom: 9px; border-bottom: 1px solid var(--border);
}
.pv-rij {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 0; border-bottom: 1px solid var(--border);
  font-size: 14px; color: var(--text-2);
}
.pv-rij:last-child { border-bottom: none; padding-bottom: 0; }
.pv-groei { flex: 1 1 auto; min-width: 0; }
.pv-naam { color: var(--text); font-weight: 600; }
.pv-sub { display: block; font-size: 12.5px; color: var(--text-3); margin-top: 2px; }

/* De Ledger-regel: tabulair, rechts, centen gedempt. */
.pv-bedrag {
  font-variant-numeric: tabular-nums;
  margin-left: auto; text-align: right; white-space: nowrap;
  color: var(--text); font-weight: 600;
}
.pv-bedrag i { font-style: normal; font-size: .82em; color: var(--text-3); }

/* Een aantal, percentage of duur — nooit de bedragrol (de kental-regel). */
.pv-kental {
  font-size: 26px; font-weight: 700; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; color: var(--text);
}
.pv-label {
  font-size: 12.5px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--text-4);
}

/* De Semantiek-regel: tint met de kleur als tekst, nooit een gevuld vlak.
   Verwerkingsstanden (concept, verzonden) zijn neutraal — de
   Proces-familie: een mail die aankomt is geen goed nieuws over geld. */
.pv-pil {
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: 999px; padding: 3px 10px;
  font-size: 12.5px; font-weight: 600; white-space: nowrap;
}
.pv-pil--ok       { background: color-mix(in srgb, var(--green) 12%, transparent); color: var(--green); }
.pv-pil--warn     { background: color-mix(in srgb, var(--amber) 14%, transparent); color: var(--amber); }
.pv-pil--danger   { background: color-mix(in srgb, var(--red)   12%, transparent); color: var(--red); }
.pv-pil--neutraal { background: var(--bg-3); color: var(--text-3); }

/* Annotatie. Max drie per beeld en nul op de hero (screenhance). Zit
   bewust niet absoluut gepositioneerd maar als chip schrijlings op de
   onderrand: dat overleeft elke kolombreedte zonder te clippen. */
.pv-callout {
  position: relative; z-index: 2;
  margin: -15px 0 0 22px;
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--bg);
  border: 1px solid var(--border-2);
  border-radius: 999px;
  padding: 7px 14px 7px 11px;
  font-size: 12.5px; font-weight: 500; color: var(--text);
  box-shadow: 0 8px 20px -10px var(--shadow-strong);
}
/* Het stipje dat hier stond is weg (golf 7). Een gekleurde punt voor een
   toelichting toont geen toestand, hij toont dat er iemand een punt wilde
   tekenen. De detector noemt dit patroon met zoveel woorden: decoratieve
   statusstippen zijn standaard nul. */

/* Twee kolommen naast elkaar (NL naast BE). Stapelt op smal. */
.pv-duo { display: grid; grid-template-columns: 1fr 1fr; gap: 0; }
.pv-duo > * + * { border-left: 1px solid var(--border); padding-left: 20px; }
.pv-duo > * { min-width: 0; }
.pv-duo > :first-child { padding-right: 20px; }
@media (max-width: 560px) {
  .pv-duo { grid-template-columns: 1fr; }
  .pv-duo > * + * { border-left: none; border-top: 1px solid var(--border); padding-left: 0; padding-top: 18px; margin-top: 18px; }
  .pv-duo > :first-child { padding-right: 0; }
}

/* Optelblok: hairline erboven, het totaal zwaarder dan de regels erboven. */
.pv-som { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border-2); }
.pv-som .pv-rij { border-bottom: none; padding: 5px 0; font-size: 14px; }
.pv-som .pv-rij--totaal { padding-top: 9px; font-size: 15px; color: var(--text); font-weight: 700; }
.pv-som .pv-rij--totaal .pv-bedrag { font-size: 17px; }

/* Stap op een opvolgpad. De rail links is het merkteken van dit product. */
.pv-stap { position: relative; padding: 0 0 18px 26px; }
.pv-stap:last-child { padding-bottom: 0; }
.pv-stap::before {
  content: ''; position: absolute; left: 4px; top: 4px;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--bg-4);
}
.pv-stap::after {
  content: ''; position: absolute; left: 8px; top: 15px; bottom: 0;
  width: 1px; background: var(--border-2);
}
.pv-stap:last-child::after { display: none; }
.pv-stap--nu::before { background: var(--brand); box-shadow: 0 0 0 4px var(--brand-ll); }
.pv-stap-kop { font-size: 14px; font-weight: 600; color: var(--text); }
.pv-stap-uit { font-size: 12.5px; color: var(--text-3); margin-top: 2px; }

/* Chip: betaalmethode, label, klein feit. Neutraal, nooit een statuskleur. */
.pv-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--bg-3); color: var(--text-2);
  border-radius: var(--r); padding: 5px 10px;
  font-size: 12.5px; font-weight: 600; white-space: nowrap;
}

/* Een afbeelding van een knop. Niet klikbaar: dit is een beeld, geen UI. */
.pv-knop {
  display: block; text-align: center;
  background: var(--btn-bg); color: var(--btn-fg);
  border-radius: var(--r-md); padding: 11px 18px;
  font-size: 14px; font-weight: 600;
}
.pv-groot {
  font-size: clamp(26px, 4vw, 34px); font-weight: 700;
  letter-spacing: -.02em; font-variant-numeric: tabular-nums;
  color: var(--text); line-height: 1.1;
}

/* ── BIGNUM — groot cijfer als moment. Count-up (waar toegestaan) is een
   klein inline-scriptje per pagina; het echte getal staat ALTIJD in de HTML.
   NOOIT count-up op geld-/verliescijfers. Selector exact .bignum. ── */
.bignum { font-size: clamp(64px, 12vw, 152px); font-weight: 800; line-height: .92; letter-spacing: -.045em; color: var(--brand); font-variant-numeric: tabular-nums; }

/* ── SECTION--DARK — full-bleed donker moment ─────────────────
   Scope't de dark-tokens lokaal → elke mockup-class die var(--…) leest,
   rendert donker binnen deze sectie (light-default blijft site-breed).
   overflow-x:clip ONLY (nooit hidden/transform op ancestors → breekt sticky).
   De drie --btn-tokens MOETEN mee en staan op petrol met wit, gelijk aan de
   donkere modus (28-08, K-2): dezelfde knop op elke grond, 5,0:1. */
.section--dark {
  --brand:#2dd4bf; --brand-h:#5eead4; --brand-p:#99f6e4;
  --brand-ll:rgba(45,212,191,.10); --brand-md:rgba(45,212,191,.22);
  --btn-bg:#0f766e; --btn-bg-h:#13867d; --btn-fg:#ffffff;
  --bg:#0b1120; --bg-2:#131c2b; --bg-3:#1e293b; --bg-4:#283548;
  --text:#e2e8f0; --text-2:#a8b6c8; --text-3:#8b9cb3; --text-4:#74869d;
  --border:rgba(226,232,240,.08); --border-2:rgba(226,232,240,.14);
  --green:#4ade80; --red:#f87171; --amber:#fbbf24;
  --shadow-strong:rgba(0,0,0,.28); --shadow-card:rgba(0,0,0,.3);
  background: var(--bg); color: var(--text);
  position: relative; overflow-x: clip;
}
.section--dark .has-grain::after { opacity: .07; }

/* ── Toolkit responsive ── */
@media (max-width: 860px) {
  .section--split .split-inner,
  .section--split.is-visual-left .split-inner { grid-template-columns: 1fr; gap: 32px; }
  .section--split.is-visual-left .split-copy { order: 0; }
  .split-copy { max-width: none; }
  .bento { grid-template-columns: 1fr; }
  .bento > .b-cell,
  .bento .b-anchor, .bento .b-wide, .bento .b-half, .bento .b-tall, .bento .b-full {
    grid-column: auto; grid-row: auto;
  }
}




/* ═══════════════════════════════════════════════════════════════════════════
   GOLF 7 — de laag die de designronde van 19-08-2026 afdwingt.

   Vier dingen, allemaal terug te voeren op een meting en niet op smaak. De
   volledige onderbouwing staat in docs/vordero/homepage-2026-08-19/SPEC.md.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. De letters staan hier, niet bij Google ──────────────────────────────
   Bevinding P-050. Elke pagina laadde Geist via fonts.googleapis.com met twee
   preconnects, dus het IP-adres van elke bezoeker ging naar een derde partij
   vóór er iets in beeld stond, terwijl /pricing en de privacypagina beloven dat
   alles in Frankfurt staat. De bevinding stond in het register als AFGEROND
   (commit 9d698bb6) en was dat aantoonbaar niet: de link stond er nog op alle
   elf pagina's. Vandaar dat dit hier staat en niet in een takenlijst.
   Inter is SIL OFL 1.1, opgehaald met tools/haal-assets.mjs.

   Het latijnse subset met de gewichtsas (48 kB, kleiner dan de 70 kB van
   Geist). Fora zet voor zijn H3 "Inter Display", de optische variant voor
   grote maten; het zichtbare verschil daarvan is de strakkere letterafstand,
   en die dragen wij al per rol uit `fora.generated.css` (-0,03em op H3). Een
   tweede bestand voor die ene rol is die 25 kB niet waard. */
@font-face {
  font-family: "Inter"; /* impeccable-disable-line overused-font -- merkbesluit */
  src: url("/fonts/Inter-Variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ── 2. Contrast per oppervlak ─────────────────────────────────────────────
   De tabel bovenaan dit bestand documenteert contrast tegen ÉÉN achtergrond
   (--bg). Er zijn er vijf. De detector vond 111 contrastfouten waarvan het
   grootste deel uit precies dat gat kwam:

     --text-3 op --bg    5.3:1  haalt AA
     --text-3 op --bg-3  4.4:1  haalt AA NIET   ← 35 treffers
     --brand  op --bg    3.6:1  haalt AA NIET   ← 14 treffers, als tekstkleur
     --text-4 op --bg    3.3:1  decoratief, en toch in zinnen gebruikt

   Twee nieuwe tokens sluiten dat gat. Ze zijn donkerder dan hun voorganger en
   verder niets; wie tekst op een doek- of randvlak zet, gebruikt deze.

   EN DE HARDE REGEL DIE ERBIJ HOORT: --brand is een merkkleur, geen tekstkleur.
   Wit op #0d9488 haalt 3.7:1, en de omgekeerde richting haalt hetzelfde. Er
   stonden negen labels en kickers in --brand op de homepage, allemaal onder AA,
   allemaal in de kleinste letter van de site. Gebruik --brand-tekst. */
:root {
  --text-3-op-vlak: #465468;   /* 7.0:1 op --bg-3 (#e2e8f0) */
  --brand-tekst:    #0b6d64;   /* 4.8:1 op --bg, 4.5:1 op --bg-2 */
}
html[data-mode="dark"] {
  --text-3-op-vlak: #a9b6c7;
  --brand-tekst:    #5eead4;
}

/* ── 3. Elevatie krijgt een lichtbron ──────────────────────────────────────
   Er was één schaduwwaarde en één randwaarde, aan alle vier de kanten gelijk,
   op alles. Een demovenster van 570px en een logopil van 80px droegen dezelfde
   rand. Daarom leest elk vlak als een sticker in plaats van een oppervlak.

   De redenering die hier stond ("zware drop-shadows lezen als sjabloon, vlakke
   vlakken lezen als software") klopt half en blijft staan. Wat eraan ontbrak:
   Linear is óók vlak, en elk vlak daar heeft een lichtere bovenrand dan
   onderrand. Vlak mét lichtbron leest als software; vlak zonder leest als
   ongerenderd.

   Drie tiers. Tier 3 staat op precies één object per venster: het onderwerp.

   DE DONKERE VARIANT IS GEEN NAKOMERTJE. Een witte binnenrand wordt op #0B1120
   een grijze kras. Dit repo is daar al een keer op stukgelopen met
   --shadow-card, en daarom staan de gepaarde waarden hier in dezelfde regel
   en niet in een latere commit. */
:root {
  --licht-boven:  inset 0 1px 0 rgba(255,255,255,.70);
  --rand-boven:   rgba(255,255,255,.90);
  --vlak-1: 0 1px 2px var(--shadow-card);
  --vlak-2: 0 2px 4px var(--shadow-card), 0 12px 24px -12px var(--shadow-strong);
  --vlak-3: 0 2px 6px var(--shadow-card), 0 32px 64px -28px var(--shadow-strong);
}
html[data-mode="dark"] {
  --licht-boven: inset 0 1px 0 rgba(255,255,255,.08);
  --rand-boven:  rgba(255,255,255,.12);
}

.vlak-1 { box-shadow: var(--vlak-1), var(--licht-boven); border-top-color: var(--rand-boven); }
.vlak-2 { box-shadow: var(--vlak-2), var(--licht-boven); border-top-color: var(--rand-boven); }
.vlak-3 { box-shadow: var(--vlak-3), var(--licht-boven); border-top-color: var(--rand-boven); }

/* ── 4. Eén warme kleur, en hij komt één keer voor ─────────────────────────
   De pagina was monochroom teal van de eerste tot de laatste pixel, en dat is
   de reden dat alle banden hetzelfde lazen. Eén tweede tint die één keer
   verschijnt is een sterker signaal dan een vijfde tint van de eerste.

   DE BEPERKING IS DE REGEL, NIET DE KLEUR. Deze tint hoort uitsluitend bij de
   founding-sectie: het enige menselijke moment op de site. Verschijnt hij
   ergens anders, dan is hij geen accent meer maar een tweede merkkleur, en dan
   is het merk goedkoper geworden. Er is precies één gebruiker toegestaan. */
:root {
  /* #9a5a36 en niet #a8623c: die haalde 4,38:1 op papier en dat is net onder
     AA voor de ene warme regel op de site, het adres van het founding-aanbod
     (audit 27-08, S-008). Eén stap donkerder haalt 5,0:1. */
  --warm:      #9a5a36;
  --warm-vlak: #fdf6f1;
  --warm-rand: rgba(168,98,60,.18);
}
html[data-mode="dark"] {
  --warm:      #e09b76;
  --warm-vlak: #1b1512;
  --warm-rand: rgba(224,155,118,.22);
}

/* ── 5. Een druk moet voelbaar zijn ────────────────────────────────────────
   DESIGN.md schrijft scale(0.98) voor bij een druk. De app deed dat, de site
   niet: hier stond translateY(1px). Op mobiel, waar geen hover bestaat, was er
   dus geen enkele terugkoppeling tussen de tik en de navigatie, op precies de
   knop waarvoor de hele pagina bestaat. */
.btn:active { transform: scale(.98); }

/* Hover is een muisding. Zonder deze poort blijft een knop op een aanraakscherm
   in zijn hover-toestand hangen tot je ergens anders tikt. */
@media (hover: none) {
  .btn:hover { transform: none; }
}

/* ── 6. De donkere band herschaalt ook de golf 7-tokens ────────────────────
   `.section--dark` zet elk oorspronkelijk token lokaal op zijn donkere waarde,
   zodat een component daarbinnen donker rendert op een lichte pagina. De vier
   tokens die deze golf toevoegde stonden daar niet in, en dan krijgt een
   donkere band de LICHTE waarden: een binnenrand van 70% wit is op #0B1120 geen
   subtiele lichtvang maar een streep. Precies de fout waar dit repo al eens op
   is stukgelopen met --shadow-card, en de reden dat het gepaarde donkere token
   in dezelfde commit hoort als het lichte. */
.section--dark {
  --licht-boven: inset 0 1px 0 rgba(255,255,255,.08);
  --rand-boven: rgba(255,255,255,.12);
  --text-3-op-vlak: #a9b6c7;
  --brand-tekst: #5eead4;
}

/* ── 7. Het merkvlak draait niet mee met het thema ─────────────────────────
   Een betaalmerk is andermans huisstijl. Visa is #1434CB, PayPal #002991,
   Apple Pay zwart: op een donkere chip verdwijnen die alle drie. In de donkere
   modus stonden er zo drie lege cirkels in de koppeling-orbit.

   Dit token blijft daarom in beide modi wit. Dat is geen vergeten donkere
   variant maar het punt: een logo hoort op het vlak waarvoor zijn eigenaar hem
   getekend heeft, en dat is bij al deze merken wit. Qonto en Puzzle zetten hun
   orbit-logo's om dezelfde reden op een dekkende plaat. */
:root, html[data-mode="dark"], .section--dark {
  --merkvlak: #ffffff;
  --merkvlak-rand: rgba(15,23,42,.10);
  --merkvlak-inkt: #0f172a;
}

/* ── 8. Twee secties in hetzelfde hoofdstuk staan dichter op elkaar ─────────
   Elke sectie had dezelfde padding boven en onder, dus tussen twee secties van
   hetzelfde hoofdstuk stond evenveel lucht als tussen twee hoofdstukken. Op de
   homepage werd dat bij drie doek-secties achter elkaar een gat van honderd-
   achtentwintig pixels dat niets markeert.

   De band zegt al dat twee secties bij elkaar horen; de ruimte moet dat dan
   niet tegenspreken. Alleen padding-top halveren, niet allebei: de eerste
   sectie van een hoofdstuk houdt zijn volle aanloop. */
.section-alt + .section-alt,
.section--dark + .section--dark,
.section:not(.section-alt):not(.section--dark) + .section:not(.section-alt):not(.section--dark) {
  padding-top: 24px;
}

/* ── 9. De fotohero, golf 7b ───────────────────────────────────────────────
   Twee maten die er nog niet waren, en die er moeten zijn omdat een
   volle-breedte fotohero andere natuurkunde heeft dan een kop in een kolom.

   `--maat-hero` gaat boven de displaytrap uit (die stopt op 72px). Op een foto
   van rand tot rand moet de kop het beeld aankunnen; op 72px leest hij als een
   onderschrift. Qonto zit op dezelfde hoogte. Dit is de enige plek waar deze
   maat mag staan. Het plafond stond op 64 en staat sinds 28-08 op 56: de kop
   is met K-1 drie regels geworden en de langste ("Herinneren, aanmanen,
   innen.") moet binnen de donkere linkerzone van de foto blijven staan.

   `--foto-grond` is de kleur onder de foto: de tint van de opname zelf, zodat
   er tijdens het laden geen wit vlak staat waar een donkere foto komt, en zodat
   de knoptekst op wit dezelfde inkt heeft als het beeld. Bewust géén
   slate-token: die is blauwig en de foto is warm. Sinds 28-08 een tint lichter
   (K-6): op #14100c leest de flits vóór het lazy laden als een zwart gat, en
   het is de grond van een werkplaats, geen leegte. */
:root {
  --maat-hero: clamp(36px, 3.9vw, 56px);
  --maat-hero-smal: clamp(28px, 8vw, 40px);
  --foto-grond: #1f1a14;
  /* De hoogte van de navigatiebalk, zodat een sectie die eronder door moet
     lopen niet met een los getal hoeft te raden. */
  --nav-hoogte: 68px;
}

/* ── 10. De gedeelde in-beeld-onthulling ───────────────────────────────────
   Overgenomen uit de Copilot-ronde van 27-08, en bewust maar voor de helft.
   Die ronde zette er ook een `--ease-onthul: cubic-bezier(.16,1,.3,1)`, een
   `--dur-onthul: .62s` en een `--dur-focaal: 1.05s` bij. De eerste twee zijn
   `--ease-out-soft` en `--dur-slow` met een andere naam, en twee namen voor
   dezelfde curve is hoe een designsysteem in tweeen valt. De derde beschreef
   de lengte van een geregisseerd moment in een hero die niet meer bestaat, en
   een token zonder gebruikers is precies de stille rot waar dit repo al eerder
   op is stukgelopen. Geen van drieen staat er dus; gebruik de bestaande.

   HET CONTRACT, en dat is waarom er `html[data-js]` voor staat. Zonder
   JavaScript staat elk productbeeld in zijn eindstand. De begintoestand wordt
   pas geschreven als het inline-script in Basis.astro `data-js` heeft gezet, en
   dat gebeurt voor de eerste verf. Faalt dat script, dan is er geen
   begintoestand en verbergt de onthulling dus niets.

   Basis.astro zet `data-in` op elk `[data-inbeeld]` zodra het in beeld komt,
   een keer en niet meer terug. De component beschrijft zelf wat er dan
   beweegt; dit blok zorgt alleen dat het tot dat moment niet te zien is. */
html[data-js] [data-inbeeld]:not([data-in]) [data-onthul] {
  opacity: 0;
}
/* Beweging is een dimmer en geen noodstop: onder reduced-motion staat alles
   meteen in de eindstand, ook wat nog niet in beeld is geweest. */
/* Alleen onder html[data-rust], de schakelaar in Basis.astro (05-09). */
html[data-rust][data-js] [data-inbeeld]:not([data-in]) [data-onthul] { opacity: 1; }
