/* =========================================================
   [PRODUCTNAAM] — marketing site
   Structuur overgenomen uit het Sjabloon-project.
   Aanpassingen: dieper navy, zakelijker contrast, witte CTA's.
   ========================================================= */

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

html, body, div, span,
h1, h2, h3, h4, h5, h6,
p, a, img, ul, ol, li, table, thead, tbody, tr, th, td,
section, header, footer, nav, details, summary, figure, blockquote {
  margin: 0; padding: 0; border: 0; font: inherit; vertical-align: baseline;
}
img { display: block; max-width: 100%; height: auto; }
summary::-webkit-details-marker { display: none; }

/* ---------- Tokens ----------
   Eén variabele om de achtergrond te dialen: --bg.
   Zwart-wit. Geen enkele grijstint bevat kleur: overal R = G = B.
------------------------------ */
:root {
  /* **`color-scheme: dark` staat hier omdat Android de gevulde knop anders
     omkeert.** Chrome en Samsung Internet hebben een stand die een pagina
     zelf donker maakt ("automatisch donker thema"). Die kijkt of de pagina
     zegt welk schema zij voert; staat dat er niet, dan gaat hij het zelf doen.
     Deze site ís al donker, dus aan het meeste verandert er niets — behalve
     aan wat licht is, en dat is precies de belangrijkste knop. Gemeten op een
     Samsung: de knop die `#E8E8E8` met donkere letters hoort te zijn, kwam als
     een donker vlak met een fijne rand in beeld, niet te onderscheiden van een
     secundaire knop. Op iOS speelt het niet; daar bestaat die stand niet.

     Eén regel, en hij zegt tegen de browser: laat maar, dit is al donker. */
  color-scheme: dark;

  /* Diep antraciet, niet zwart. Puur zwart versterkt de halatie rond lichte
     koppen en sleept na op OLED; een achtergrond die een paar punten omhoog
     staat dempt dat aan de bron in plaats van bij de tekst. Eerder stond hier
     #070707 — zeven punten van zwart, wat het bezwaar niet wegnam. */
  --bg:        #121212;   /* Obsidian         canvas */
  --bg-deep:   #050505;   /* niet in gebruik: de hero stond hierop en gaf halatie */
  --surface:   #121212;   /* gelijk aan canvas, scheiding via 1px rand */
  --surface-2: #121212;   /* idem, kaarten leunen op hun rand */
  /* De scheidingslijnen zijn meeverhoogd. Op #070707 stond --line op 1,48:1 en
     --line-soft op 1,18:1 ten opzichte van het vlak. Ongewijzigd zouden ze op
     #121212 naar 1,38:1 en 1,10:1 zakken en zou de zachte lijn vrijwel
     verdwijnen. Deze waarden houden beide op hun oude zichtbaarheid. */
  --line:      #333333;   /* Graphite         1px scheidingen */
  /* De rand van een bedieningselement is geen scheidingslijn. WCAG 1.4.11 vraagt
     daar 3:1 en --line haalt 1,48:1 — bewust, want als scheiding hoort die dof te
     zijn. Bij een invoerveld is de rand echter het enige wat het veld markeert:
     de veldachtergrond is exact de paginakleur. Vandaar een eigen waarde, alleen
     voor velden en omlijnde knoppen. 3,26:1 op #121212. Verplaats je --bg, meet
     deze dan opnieuw mee. */
  --line-veld: #666666;   /* rand van velden en omlijnde knoppen, 3,26:1 */

  /* ---------------------------------------------------------------------
     DE TRAP. Eén schaalfactor van 1,125 vanaf 16 px. Waarom die verhouding:
     het is de kleinste waarbij zowel 16 als 18 op de trap valt, en dat zijn
     de twee maten die al vastlagen (lopende tekst, en h4 op mobiel). Stonden
     er zeventien losse maten met verhoudingen van 1,029 tot 1,7 — dat is een
     glijschaal en geen trap, en een volgende maker kiest daar zijn eigen
     tussenstap in.

     Dit register is voor tekst in de interface. De koppen staan bewust in een
     ander register: h1 tot en met h3 lopen vloeiend mee met de vensterbreedte
     via clamp(), en de mobiele koppen staan op vaste pixels (21 · 18 · 16)
     omdat die op regelval zijn uitgemeten. Zie CLAUDE.md; verhoog daar niet
     één maat los.
     --------------------------------------------------------------------- */
  --maat-min3: 1.1240rem;   /*  11.24 px */
  --maat-min2: 1.2640rem;   /*  12.64 px */
  --maat-min1: 1.4220rem;   /*  14.22 px */
  --maat-0: 1.6000rem;   /*  16.00 px */
  --maat-1: 1.8000rem;   /*  18.00 px */
  --maat-2: 2.0250rem;   /*  20.25 px */
  --maat-6: 3.2440rem;   /*  32.44 px */

  --line-soft: #222222;
  --white:     #FAFAFA;   /* Platinum White   titels */
  /* De hero-tekst staat bewust onder --white. Op groot formaat en zwaar gewicht
     waaiert bijna-wit op bijna-zwart zichtbaar uit; een paar punten eraf haalt
     dat weg zonder dat het grijs wordt. Geldt voor de hele display-schaal:
     h1, h2 en de claimregel in de hero. Alles daaronder (h3, h4, lopende
     tekst) blijft op --white, want daar treedt het effect niet op. */
  --display:   #EDEDED;
  --text:      #A3A3A3;   /* Ash              lopende tekst */
  --text-dim:  #8A8A8A;   /* Ash dim          labels, micro-copy */
  --accent:    #E8E8E8;   /* Brushed Steel    actieve status, focusrand */
  /* De knop is wit, net als de rest van de site. Een merkkleur is geprobeerd
     en weer losgelaten: op een pagina waar nog maar een knop staat voegt kleur
     geen zichtbaarheid toe, en zwart-wit past bij de ingehouden toon.
     Wil je hem ooit terug, zet --merk op een van deze en de tekstkleur op #fff:
       #B03A47 wijnrood     wit 5,93:1  op de pagina 3,42:1
       #C3135F karmijn      wit 5,87:1  op de pagina 3,45:1
       #0F86B0 tekencyaan   zwart 4,77:1, dan tekstkleur op var(--bg)
     Rood heeft een bezwaar: het product markeert afwijkingen, en dan kan
     dezelfde kleur niet ook de knop zijn. */
  --merk:      #E8E8E8;
  /* Signaalkleuren blijven gedefinieerd maar worden nergens gebruikt.
     De site is monochroom. Wil je één signaalkleur terug voor dreiging,
     zet dan .meter__seg--was op var(--danger-bg). */
  --ok:        #10B981;
  --ok-bg:     #064E3B;
  --danger:    #EF4444;
  --danger-bg: #451A1A;
  --text-micro: #8A8A8A;  /* lopende micro-tekst: bronregels */
  --container: 1440px;
  --gutter:    32px;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
}
/* Op mobiel 24px in plaats van 32px. Eén custom property, dus dit werkt door
   in alles wat `var(--gutter)` gebruikt: navbalk, secties, hero, footer —
   zonder die stuk voor stuk te hoeven aanpassen. Alleen onder 768px; vanaf
   daar blijft 32px (en vanaf 1024px 80px voor de navbalk, zie de nav-regels
   verderop) ongewijzigd staan. */
@media (max-width: 767px) {
  :root { --gutter: 24px; }

}

html {
  font-size: 62.5%;
  scroll-behavior: smooth;
  background-color: var(--bg);
  scroll-padding-top: 88px;
}

/* Zelf gehost, twee bestanden voor het Latijnse en het Latijns-Uitgebreide
   bereik (accenttekens: é, ë, ñ). Geen local()-bron: dat zou het lettertype op
   een bezoeker met een andere, eerder geïnstalleerde versie van Inter laten
   terugvallen op diens eigen kopie, met net andere metrics. Nu ziet iedereen
   exact hetzelfde bestand. Variabele font, dus één @font-face per bereik
   dekt het hele gewicht van 100 tot 900 — geen apart bestand per snit. */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 100 900;
  font-display: swap; src: url("../fonts/inter/inter-latin-variable.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 100 900;
  font-display: swap; src: url("../fonts/inter/inter-latin-ext-variable.woff2") format("woff2-variations");
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

body {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
               system-ui, "Helvetica Neue", Arial, sans-serif;
  font-size: clamp(1.6rem, calc(1.5rem + 0.3vw), 1.8rem);
  font-weight: 400;
  line-height: 1.55;
  color: var(--text);
  background-color: var(--bg);
  -webkit-font-smoothing: antialiased;
}

/* ---------- Typografie ---------- */
h1, h2, h3, h4, h5, h6 { font-family: inherit; color: var(--white); }

/* Display: uitsluitend de landingstitel */
h1 {
  font-size: clamp(4.0rem, 4.4vw, 7.2rem);
  line-height: 1.05; font-weight: 700; letter-spacing: -.03em; margin-bottom: 24px;
}
/* H1 Header: sectietitels en subpaginatitels */
h2, .page-hero h1 {
  font-size: clamp(3.2rem, calc(2.8rem + 1.2vw), 4.0rem);
  line-height: 1.15; font-weight: 600; letter-spacing: -.02em; margin-bottom: 24px;
  color: var(--display);
}
/* H2 Header: sub-secties en kaarttitels */
h3 {
  font-size: clamp(2.0rem, calc(1.8rem + 0.6vw), 2.4rem);
  line-height: 1.25; font-weight: 500; letter-spacing: -.01em; margin-bottom: 16px;
}
h4 { font-size: var(--maat-1); font-weight: 600; line-height: 1.25; letter-spacing: -.01em; margin-bottom: 8px; }

p { margin-bottom: 24px; }
p:last-child { margin-bottom: 0; }

a { color: var(--white); font-weight: 600; text-decoration: none; transition: 200ms; }
a:hover { color: var(--white); opacity: .75; }

strong { color: var(--white); font-weight: 600; }

ul, ol { display: block; padding-inline-start: 24px; margin-bottom: 24px; }
ul { list-style-type: none; }
ol { list-style-type: decimal; }
ul li { position: relative; padding-bottom: 8px; }
ul li::before {
  content: ""; position: absolute; left: -24px; top: 12px;
  width: 5px; height: 1px; background: var(--text-dim);
}
ol li { padding-bottom: 8px; padding-left: 8px; }
li::marker { color: var(--text-dim); }
li:last-child { padding-bottom: 0; }

.color-white { color: var(--white); }
.dim { color: var(--text-dim); }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.t-margin { margin-bottom: 8px; }
.s-margin { margin-bottom: 24px; }
.no-margin { margin-bottom: 0; }

.eyebrow {
  font-size: var(--maat-min2); font-weight: 600; letter-spacing: .18em; text-transform: uppercase;
  line-height: 1.2; color: var(--text-dim); margin-bottom: 16px; display: block;
}

.lede { font-size: var(--maat-1); line-height: 1.55; color: var(--text); }

/* Zonder maximum pakken deze twee de volle 1376px als ze rechtstreeks in
   .inner staan; gemeten liep dat op tot 206 tekens per regel. */
.source, .verwijzing { max-width: 52ch; }
.source {
  font-size: var(--maat-min2); line-height: 1.5; color: var(--text-micro); font-weight: 400;
  margin-top: 16px; margin-bottom: 0;
}
/* De bronregel is bedoeld als sluitregel en heeft daarom geen ondermarge. Staat
   er wel iets achter, dan plakken de twee tegen elkaar. Dat gebeurde op veertien
   plekken. 24px is dezelfde afstand die een gewone alinea eronder heeft, zodat
   een bronregel middenin een blok net zo ademt als de rest. */
.source:not(:last-child) { margin-bottom: 24px; }

/* Een bronregel direct onder een alinea staat overal op 24px.

   Zonder deze regel hangt dat af van waar hij staat, en dat is niet te zien
   aan de opmaak. `.section > .inner` is een flexbox en daar klappen marges
   niet samen: de ondermarge van de alinea (24px) en de bovenmarge van .source
   (16px) tellen dan op tot 40px. In een `.split__body` — een gewoon blok —
   klappen ze wel samen en is het 24px. Zelfde markup, ander resultaat.

   Twee bronregels hadden daar een inline marge overheen gekregen. Die van
   20px deed niets (24 is groter en wint bij het samenklappen); die van 32px
   maakte er 56px van. Allebei weggehaald; de norm staat nu hier.

   Alleen na een alinea. Na een .stats of een .figure houdt .source zijn eigen
   grotere marge — dat is een andere relatie. */
p + p.source { margin-top: 0; }

/* Een doorverwijzing is geen bronregel. Vijf regels op de site zeggen "meer
   daarover staat bij X". Die stonden in .source, het kleinste register dat er
   is, en het linkidioom van deze site is gewicht 600 en bijna wit. Op 16px
   leest dat als nadruk binnen een zin; op 12px is de link het helderste en
   zwaarste van de regel terwijl de regel zelf het kleinste en dofste is. Op de
   homepage vulden twee links tweederde van de regel - klein en zwaar tegelijk,
   en dus geen hierarchie. De doorverwijzing heeft nu een eigen trede tussen de
   lopende tekst en de bronregel in: 16 - 14 - 12. */
/* Let op dezelfde val als bij .source: binnen een .item wint `.item p`
   (0,1,1) van `.verwijzing` (0,1,0) en staat er 15px. Dat scheelt een pixel
   en is daar ook de bedoeling, dus er staat geen tegenregel tegenover. */
.verwijzing {
  font-size: var(--maat-min1); line-height: 1.5; color: var(--text-dim); font-weight: 400;
  margin-top: 16px; margin-bottom: 0;
}
.verwijzing:not(:last-child) { margin-bottom: 24px; }
p + p.verwijzing { margin-top: 0; }

/* In dit kleine register draagt de onderstreping de link en niet het gewicht.
   Ook op .source, zodat het daar niet opnieuw ontstaat. */
.source a, .verwijzing a {
  font-weight: 400; color: var(--text);
  text-decoration: underline; text-underline-offset: 3px;
}
.source a:hover, .verwijzing a:hover { color: var(--white); opacity: 1; }

/* ---------- Layout ---------- */
.section > .inner {
  max-width: var(--container); margin: 0 auto;
  padding: 96px var(--gutter);
  display: flex; flex-direction: column; align-items: stretch;
}
/* align-items stond op flex-start. Tekst-align is toch al links, dus dat
   veranderde niets aan hoe tekst staat — maar flex-start laat elk kind
   krimpen naar zijn eigen inhoud (fit-content) in plaats van de kolom te
   vullen. Bij een lang lopende alinea viel dat niet op, want die heeft de
   volle breedte toch al nodig om te passen. Bij een kop of eyebrow-label wél:
   die bleef tientallen tot bijna 200px smaller staan dan de kolom toestond.
   stretch lost dat op zonder iets aan de tekstuitlijning te veranderen; een
   knop blijft vanzelf compact, want .s-button zet zijn eigen align-self. */
.section--tight > .inner { padding-top: 56px; padding-bottom: 56px; }
/* Het eerste element in een sectie krijgt zijn ruimte van de padding van die
   sectie. Heeft het daarnaast een eigen bovenmarge, dan telt die er in een
   flexbox bovenop — .inner is flex. Op nameting.html begon een sectie met een
   bronregel (eigen marge 16px) en stond de scheidingslijn daardoor op 64px
   boven en 80px onder. Zelfde verhaal aan de onderkant. */
.section > .inner > *:first-child { margin-top: 0; }
.section > .inner > *:last-child { margin-bottom: 0; }
/* Let op: --surface is gelijk aan --bg, dus deze klasse zet geen band aan.
   Hij staat er wel op zeventien secties in de opmaak. Wil je die secties toch
   laten afsteken, geef --surface dan een eigen waarde, bijvoorbeeld #0E0E0E.
   Zolang dat niet gebeurt is de site vlak en scheidt hij op lijn en witruimte. */
.section--deep { background: var(--surface); }

.divider { width: 100%; height: 1px; background-color: var(--line); }
.w-100 { width: 100%; }
/* Leesbreedte. Stond op 68ch, maar dat leverde 92 tekens per regel op — ruim
   boven de richtlijn van 45 tot 75. Dat komt doordat `ch` de breedte van het
   cijfer nul meet, en dat teken is in deze letter een stuk breder dan een
   gemiddelde kleine letter. De regel deed dus niet wat er stond.

   52ch is gemeten, niet uitgerekend: over zeven alinea's op drie pagina's
   geeft het gemiddeld 69 tekens (spreiding 63 tot 74). ch blijft de eenheid,
   zodat de maat meeschaalt als de tekstgrootte verandert.

   Gevolg op desktop: de tekstkolom stopt verder van de rechterkantlijn dan
   voorheen. Dat is de bedoeling — het leest als een smalle tekstkolom in een
   breed raster in plaats van als een regel die net te kort is. Onder 768px
   raakt deze regel niets: de kolom is daar smaller dan de leesmaat. */
.measure { max-width: 52ch; }

.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 24px 48px; width: 100%; }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 48px 24px; width: 100%; }
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 32px 24px; width: 100%; }

/* split: smalle introkolom links, inhoud rechts (zoals het sjabloon) */
.split { display: grid; grid-template-columns: repeat(6, minmax(0,1fr)); gap: 24px; width: 100%; }
.split__intro { grid-column: span 2; display: flex; flex-direction: column; }
.split__body  { grid-column: span 4; display: flex; flex-direction: column; }
/* Waarom flex en niet gewoon een blok: in een blok klappen marges samen (het
   grootste van de twee wint), in flex tellen ze op. `.section > .inner` is
   flex, `.split__body` was een blok — en daardoor gaf exact dezelfde opmaak
   een ander resultaat, afhankelijk van waar hij stond. Een knop onder een
   alinea werd 32px in een split en 56px daarbuiten; een bronregel 24 tegen 40.
   Dat verschil was nergens aan de opmaak te zien en heeft meerdere keren tot
   verkeerde afstanden geleid. Nu gedragen beide containers zich hetzelfde. */
/* Een rasterkolom krimpt standaard niet onder de minimale breedte van zijn inhoud.
   Staat er een tabel in — die heeft min-width: 640px — dan duwt hij de kolom open
   en scrolt de hele pagina horizontaal in plaats van alleen de tabel. min-width: 0
   geeft de overflow-x op .table-scroll zijn werk terug. */
.split__intro, .split__body { min-width: 0; }

/* Portret op over.html: het kader (rand, breedte) staat op de omtrek, zodat
   de foto erbinnen vrij kan schalen zonder de rand mee te vergroten. */
.portrait { width: 100%; overflow: hidden; border: 1px solid var(--line); }
.portrait img { display: block; width: 100%; height: auto; animation: portrait-zoom 9s ease-in-out infinite; }
@keyframes portrait-zoom {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}

/* Titel en portret op over.html schuiven tegengesteld mee met de scroll —
   titel omhoog, foto omlaag — zodat ze bij het scrollen zichtbaar loskomen
   van elkaar. main.js zet de transform; hier alleen de renderhint. */
[data-parallax] { will-change: transform; }

/* ---------- Knop ---------- */
.s-button {
  display: inline-flex; align-items: center; justify-content: center; align-self: flex-start;
  border-radius: 4px; color: var(--white);
  font-size: 15px; font-weight: 600; padding: 16px 24px;
  text-decoration: none; border: 1px solid var(--line-veld);
  position: relative; z-index: 1; white-space: nowrap; overflow: hidden;
  transition: color 140ms ease-in-out, border-color 140ms ease-in-out,
              background-color 140ms ease-in-out;
}
.s-button span, .s-button svg { position: relative; z-index: 2; }
.s-button::before {
  content: ''; position: absolute; inset: 0 auto 0 0;
  width: 0%; height: 100%; background: var(--accent); border-radius: 4px;
  transition: width 160ms cubic-bezier(.2,.6,.2,1);
}
.s-button:hover { color: var(--bg); border-color: var(--accent); opacity: 1; }
.s-button:hover::before { width: 100%; }
.s-button:focus-visible { outline: 2px solid rgba(255,255,255,.75); outline-offset: 5px; border-radius: 4px; }
.nav__menu a:focus-visible, .nav__menu button:focus-visible,
.footer__menu a:focus-visible, .wordmark:focus-visible, .footer__logo:focus-visible,
.faq__body a:focus-visible, .split__body a:focus-visible {
  outline: 2px solid rgba(255,255,255,.75); outline-offset: 4px; border-radius: 3px;
}

/* Een <button> krijgt van de browser een eigen achtergrond. Bij een anker valt
   dat niet op, bij een verzendknop wel: die kleurde lichtgrijs op. Solid houdt
   zijn eigen vulling, vandaar de uitzondering. */
button.s-button:not(.s-button--solid) { background: none; }
.s-button--solid { background: var(--merk); color: var(--bg); border-color: var(--merk); }
.s-button--solid::before { background: transparent; }
/* De gevulde knop is op elke pagina de belangrijkste, en had de zwakste
   terugkoppeling: hij werd alleen twaalf procent doorzichtiger. Nu keert hij
   om naar een donker vlak met een fijne rand. Dezelfde beweging als bij de
   omlijnde knop, maar andersom, zodat beide soorten even sterk reageren. */
.s-button--solid:hover {
  background: transparent; color: var(--merk); border-color: var(--merk); opacity: 1;
}

.s-button--ghost { border-color: transparent; padding-left: 0; padding-right: 0; overflow: visible; }
/* De ghost-knop heeft bewust geen horizontale padding, zodat hij als tekst uitlijnt.
   Daardoor zou de focusring links en rechts tegen de letters plakken. Vandaar een
   eigen ring die aan alle vier de zijden 12px van de tekst blijft. */
.s-button--ghost:focus-visible { outline: none; }
.s-button--ghost:focus-visible::after {
  content: ''; position: absolute; inset: 4px -12px; border-radius: 4px;
  border: 2px solid rgba(255,255,255,.75); pointer-events: none;
}
.s-button--ghost::before { display: none; }
/* .s-button:hover zet border-color op --accent; voor de ghost-knop moet dat
   terug naar transparant, anders verschijnt er een kader dat links en rechts
   tegen de letters plakt omdat deze variant geen horizontale padding heeft. */
.s-button--ghost:hover { color: var(--white); opacity: .7; border-color: transparent; }

.arrow-icon { overflow: visible; margin-left: 8px; width: 10px; flex: none; }
.arrow-icon path { stroke: currentColor; }
.arrow-head { transform: translateX(0); transition: transform 120ms ease-in-out; }
.arrow-body { opacity: 0; transform: scaleX(1); transition: transform 120ms ease-in-out, opacity 120ms ease-in-out; }
.button-arrow:hover .arrow-head { transform: translateX(3px); }
.button-arrow:hover .arrow-body { opacity: 1; transform: scaleX(2); }

.button-row { display: flex; flex-direction: row; align-items: center; gap: 24px; flex-wrap: wrap; }

/* ---------- Header ---------- */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  background-color: transparent;
  border-bottom: 1px solid transparent;
  transition: transform 340ms cubic-bezier(.4,0,.2,1),
              background-color 260ms ease, border-color 260ms ease;
}
.nav__row { padding-top: 16px; padding-bottom: 16px; }
.nav__container {
  max-width: var(--container); margin: 0 auto; padding: 0 var(--gutter);
  display: flex; flex-direction: row; align-items: center;
}
.nav__left { display: flex; align-items: center; }
.nav__center { flex: 1; }
.nav__right { display: flex; flex-direction: row; align-items: center; }

.wordmark { display: inline-flex; align-items: center; }
/* Aanraakvlak. Het beeldmerk in de balk is 12px hoog en dat in de voettekst
   17px. Als link zijn dat doelen van 46x12 en 65x17 — ruim onder de 24px die
   WCAG 2.2 AA vraagt, en ver onder de 44px die op een telefoon prettig is.
   Een onzichtbaar vlak eroverheen maakt het doel groot genoeg zonder dat er
   iets verschuift: het beeldmerk zelf blijft precies waar het stond. */
.wordmark, .footer__logo { position: relative; }
.wordmark::after, .footer__logo::after {
  content: ''; position: absolute;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 100%; min-width: 44px; height: 44px;
}
.wordmark__logo { height: 16px; width: auto; display: block; }
.wordmark:hover { opacity: 1; }
.wordmark__mark {
  height: 22.5px; width: auto; flex: none; display: block;
}
.footer__logo { display: inline-block; }
.footer__logo img { height: 17px; width: auto; display: block; }

.nav__menu {
  display: flex; flex-direction: row; align-items: center;
  list-style: none; padding: 0 16px; margin: 0 8px 0 0;
}
.nav__menu > li { white-space: nowrap; position: relative; }
.nav__menu > li > a, .nav__menu > li > button {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 16px; font-size: 15px; font-weight: 600;
  color: var(--text); background: none; border: 0; cursor: pointer;
  font-family: inherit; transition: color 200ms;
}
.nav__menu > li > a:hover,
.nav__menu > li > button:hover,
.nav__menu > li > a[aria-current="page"] { color: var(--white); opacity: 1; }
.nav__menu li::before { display: none; }
.nav__menu li { padding-bottom: 0; }
/* De zelftestknop staat twee keer in de opmaak (los in .nav__right, en als
   laatste regel in .nav__menu). Boven 768px telt alleen de losse knop; deze
   kopie in het menu blijft dicht. Onder 768px draait het om, zie de mobiele
   media query. */
.nav__menu__cta { display: none; }

/* Tussen de hamburgergrens (768px) en 812px passen de vier Nederlandse labels
   plus de zelftestknop net niet. In die band krimpt alleen de tussenruimte in
   het menu. Boven 812px verandert er niets. */
@media (min-width: 768px) and (max-width: 812px) {
  .nav__menu { padding: 0 4px; }
  .nav__menu > li > a, .nav__menu > li > button { padding: 16px 8px; }
}

.caret { width: 9px; height: 9px; fill: none; stroke: currentColor; stroke-width: 1.4; transition: transform 200ms; }
.has-dropdown[aria-expanded="true"] .caret { transform: rotate(180deg); }

.dropdown {
  position: absolute; top: calc(100% + 6px); left: 0; min-width: 268px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px;
  padding: 8px; list-style: none; margin: 0;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity 160ms ease, transform 160ms ease, visibility 160ms;
}
.nav__menu li:hover > .dropdown,
.dropdown.is-open { opacity: 1; visibility: visible; transform: none; }
.dropdown li { padding: 0; }
.dropdown a {
  display: block; padding: 8px 16px;
  font-size: 14px; font-weight: 600; color: var(--white);
  transition: color 200ms;
}
/* Geen vak op hover. De titel wordt wit, verder gebeurt er niets. Een vlak
   dat onder de muis verschijnt is het enige gevulde oppervlak dat de site
   nog had, en het lag over een paneel dat zelf al een vlak is. */
.dropdown a:hover { background: none; color: var(--white); opacity: 1; }
.dropdown .dd-desc { display: block; font-size: 12.5px; font-weight: 400; color: var(--text-dim); margin-top: 2px; }

.nav__toggle {
  display: none; background: none; border: 0; color: var(--white);
  padding: 8px; cursor: pointer;
  /* 8px padding om een pictogram van 22px gaf een doel van 38px hoog. 44px is
     de maat waarop een duim betrouwbaar raakt. De balk groeit er niet van:
     .nav__container staat al op min-height 50px. */
  min-height: 44px; min-width: 44px;
}
.nav__toggle svg { width: 22px; height: 22px; fill: currentColor; }

.page { padding-top: 72px; }

/* ---------- Hero ---------- */
.hero__grid {
  display: grid; grid-template-columns: repeat(5, minmax(0,1fr));
  column-gap: 48px; row-gap: 24px; align-items: center; width: 100%;
}
.hero__headline { grid-column: span 3; }
.hero__intro { grid-column: span 2; display: flex; flex-direction: column; align-items: flex-start; }
.hero__art { grid-column: span 5; }
.hero__headline h1 { margin-bottom: 0; }
.hero__headline h1 .color-white { color: var(--white); }
.hero__headline h1 .muted { color: var(--text-dim); }

/* pagina-hero (subpagina's) */
.page-hero > .inner { padding-top: 88px; padding-bottom: 56px; }
.page-hero h1 { max-width: 26ch; }   /* 26ch = 664px bij 40px: de langste titelhelft meet 638px */
.page-hero .lede { max-width: 62ch; }
/* De 26ch-afspraak hierboven is getoetst op breedtes waar de kolom zelf breder
   is dan 26ch; onder 768px is de kolom (met --gutter eraf) altijd smaller dan
   dat, dus de titel breekt daar op de kolombreedte, niet op 26ch. Bij het
   basisformaat (clamp-vloer 32px) brak dat bij een aantal koppen door naar drie
   of vier regels in plaats van twee. 24px is gemeten: op de meeste pagina's
   terug naar twee regels. Drie koppen pasten ook bij 24px niet — daar wint niet
   het lettertype maar de tekst, dus die drie hebben via h1_mobiel() een tweede,
   ingekorte versie die er onder 768px voor in de plaats komt (h1-vol/h1-kort
   hieronder).
   Belangrijk: page-hero h1 deelt zijn grootte bewust met h2 (zie de regel
   `h2, .page-hero h1` verderop) — dezelfde subpagina-titel als een gewone
   sectiekop. Hier eerder alleen .page-hero h1 naar 24px gezet zonder h2 mee te
   nemen zette die twee uit elkaar: de h1 werd kleiner dan de h2's eronder op
   dezelfde pagina, dus zet dit op de gedeelde regel, niet op de helft ervan. */
.page-hero h1 .h1-kort { display: none; }
/* De hele koppenschaal op mobiel, in één blok, zodat de stappen ertussen
   zichtbaar bij elkaar staan en niet per ongeluk uit elkaar lopen:

     hero h1   ~24,5px (schaalt mee, zie .hero__copy h1 verderop)
     h1 / h2    21px
     h3         18px
     h4         16px
     tekst      15-16px

   Deze stond eerder op h2 24px / h3 20,2px. Dat gaf twee problemen tegelijk:
   de h2 zat vrijwel gelijk aan de hero-kop (24 tegen 24,5), en de h3 zat er
   met 20,2 nauwelijks onder. De hero kan niet groter — die zit vast aan de
   breedte van "Uw merk wordt toegepast" op één regel — dus de schaal eronder
   moest zakken. h3 en h4 gaan mee omlaag; alleen h2 verlagen zou het probleem
   een niveau opschuiven in plaats van oplossen.

   Let op: de footer-koppen zijn h4 maar hebben een eigen regel
   (`.footer__col h4`, 13px hoofdletters) en zijn labels, geen koppen. Die
   vallen hier bewust buiten. */
/* Twee secties zetten de kop bóven de split in plaats van in de linkerkolom.
   Die kolom blijft dan leeg, puur om de tekst op desktop in de rechterkolom te
   houden. Ze hadden allebei een inline `margin-top:32px`, en dat gaf op mobiel
   een gat van 56px tussen kop en tekst — terwijl de vijftig secties die via de
   split()-bouwsteen lopen daar allemaal op 48px staan. Inline marges zijn niet
   per schermbreedte te zetten, vandaar deze klasse. */
.split--koploos { margin-top: 32px; }

/* Een raster dat rechtstreeks onder een sectielabel staat, zonder kop ertussen.
   Stond als inline `margin-top:32px`, en dat gaf op mobiel een gat van 48px
   tussen het label en de eerste kop van het raster — terwijl de andere
   tweeëntachtig labels op de site 16px van hun kop af staan. Op desktop klopt
   die 32px wel: daar is het raster een blok onder een label, geen kop. */
.grid--onder-label { margin-top: 32px; }

/* Tussenkop die een lijst in groepen verdeelt (de vier lagen boven de
   eenentwintig meetpunten). Stond op een inline margin-top van 56px, terwijl
   de afstand tussen twee punten in zo'n lijst 48px is — acht pixels verschil.
   De groepen vielen daardoor niet op als groep en de eenentwintig blokken
   liepen in elkaar over. 80px zet de groepsgrens duidelijk boven de
   puntgrens. */
.groepskop { margin-top: 80px; }

/* Een blok — raster, tijdlijn, statistieken — direct onder een kop.

   Stond als inline `margin-top:40px`. In `.section > .inner`, een flexbox waar
   marges optellen, gaf dat 24 + 40 = 64px. Staat er tekst onder een kop, dan
   is het 24px. Site-breed: 55 koppen op 24px, 5 op 64px, en dat verschil zit
   alleen in wát eronder staat, niet in de relatie zelf.

   Op desktop blijft die 40px staan: daar is de kolom breed en mag een blok
   meer lucht boven zich hebben dan een alinea. Op mobiel gaat hij eraf. */
.blok--onder-kop { margin-top: 40px; }



@media (max-width: 767px) {
  h2, .page-hero h1 { font-size: 21px; }
  h3 { font-size: 18px; }
  h4 { font-size: 16px; }
  .page-hero h1 .h1-vol { display: none; }
  .page-hero h1 .h1-kort { display: inline; }
}

/* dot grid */
.hero__art { display: flex; justify-content: center; }

/* ---------- Statistiekenstrip ---------- */
.stats {
  display: grid; grid-template-columns: repeat(3, minmax(0,1fr));
  gap: 0 48px; width: 100%;
  padding-top: 8px;   /* geen scheidingslijn: de cijfers staan op zichzelf */
}
.stat { display: flex; flex-direction: column; gap: 8px; }
.stat__value { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--white); font-size: clamp(2.8rem, 3.4vw, 4.0rem); font-weight: 600; line-height: 1.05; letter-spacing: -.02em; }
.stat__label { font-size: var(--maat-min1); color: var(--text); }

/* ---------- Kaarten ---------- */
.card {
  display: flex; flex-direction: column; align-items: stretch;
  padding: 24px; border-radius: 6px; border: 1px solid var(--line); background: var(--surface-2);
  height: 100%;
}
.card--flat { background: transparent; }
.card__num { color: var(--text-dim); font-size: var(--maat-min2); font-weight: 600; margin-bottom: 16px; }
.card .s-button { margin-top: auto; }
.card h3 { margin-bottom: 16px; }
/* Een kleinere letter in een bredere kolom betekent meer tekens: in de
   tweekolomsrasters liep dat op tot 95 per regel. */
.card p, .item p { max-width: 52ch; }
.card p { font-size: var(--maat-min1); }

/* Zelfde reden als .section > .inner hierboven: stretch in plaats van
   flex-start, anders krimpt een korte h3 naar zijn eigen tekstbreedte
   terwijl de alinea eronder wél de volle kolom gebruikt. */
.item { display: flex; flex-direction: column; align-items: stretch; }
.item h3, .item h4 { margin-bottom: 8px; }
.item p { font-size: var(--maat-min1); margin-bottom: 0; }
/* margin-bottom: 0 hierboven houdt de laatste alinea van een item strak tegen
   de onderkant. Staan er twee alinea's in een item, dan plakten ze daardoor
   aan elkaar: nul pixels ertussen, terwijl twee alinea's elders overal 24px
   uit elkaar staan. Op de homepage liep "Volledig verrekend als het een
   traject wordt." zo vast aan de alinea erboven. */
/* Alleen tussen twee gewone alinea's. Niet na een bronregel: die heeft een
   eigen ondermarge, en op merkmeting.html staat onder elk van de eenentwintig
   meetpunten een vraag (.source) met daaronder de betekenis. Deze regel telde
   daar bovenop en maakte er 38px van, terwijl de afstand tússen twee
   meetpunten 48px is. Binnen en tussen werden daardoor bijna even groot en
   liepen de eenentwintig blokken in elkaar over. */
.item p:not(.source) + p { margin-top: 24px; }

/* ---------- Trust-strip ---------- */
.trust { display: grid; grid-template-columns: repeat(5, minmax(0,1fr)); gap: 24px; width: 100%; }
.trust__item { border-top: 1px solid var(--line); padding-top: 24px; }
.trust__item h4 { color: var(--white); margin-bottom: 8px; font-size: var(--maat-0); }
.trust__item p { font-size: var(--maat-min1); margin-bottom: 0; }

/* ---------- Figuur ---------- */
.figure-wrap { position: relative; width: 100%; }
.figure { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.figure img, .figure svg { min-width: 1100px; width: 100%; height: auto; display: block; }
.figure-wrap + .source, .figure + .source { margin-top: 16px; }

/* aanraakbare knopen in het diagram */
.ivnode { cursor: pointer; }
.ivnode:focus { outline: none; }
.ivnode .ivring { opacity: 0; transition: opacity 160ms ease; }
.ivnode:hover .ivring { opacity: .45; }
.ivnode:focus-visible .ivring { opacity: .9; stroke-dasharray: 3 3; }

/* het tekstvakje */
.tip {
  position: absolute; z-index: 20; width: 300px; max-width: 78vw;
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px;
  padding: 16px 24px; border: 1px solid var(--line);
  opacity: 0; visibility: hidden; transform: translateY(4px);
  transition: opacity 140ms ease, transform 140ms ease, visibility 140ms;
  pointer-events: none;
}
.tip.is-open { opacity: 1; visibility: visible; transform: none; }
.tip__title {
  display: block; font-size: var(--maat-0); font-weight: 600;
  color: var(--white); margin-bottom: 8px;
}
.tip__body { display: block; font-size: var(--maat-min1); line-height: 1.5; color: var(--text); }
@media (prefers-reduced-motion: reduce) { .tip { transition: none; } }

/* ---------- Tabellen ---------- */
/* Of een tabel past hangt af van de kolom waar hij in staat, niet van de
   schermbreedte: twee tabellen op demonstraties.html staan in een smallere
   kolom en liepen op een tablet van 768px alsnog 74px buiten beeld terwijl de
   pagina zelf ruim genoeg was. Daarom is dit een container en meten de regels
   hieronder met @container. */
.table-scroll {
  width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch;
  container-type: inline-size; container-name: tabel;
}
table { width: 100%; border-collapse: collapse; min-width: 640px; font-size: var(--maat-min1); }
/* Een tabel zonder lopende tekst - alleen kleurwaarden, verhoudingen of
   aantallen - heeft die 640px niet nodig. build.py meet de langste cel: blijft
   die onder de 22 tekens, dan staat er geen zin in en krijgt de tabel
   .table--compact. Zonder dat werden de twee smalle tabellen op
   demonstraties.html naar 640px gedwongen in een kolom van 589px, en schoven ze
   ook op een scherm van 1440px. Ze hebben er zelf 422 en 365 nodig. */
.table--compact { min-width: 420px; }
/* Het kolomlabel dat build.py in elke cel zet, hoort alleen bij de gestapelde
   vorm. Staat de tabel als tabel, dan doet de <thead> het werk. */
.cel__kop { display: none; }
thead th {
  text-align: left; color: var(--white); font-weight: 600; font-size: var(--maat-min1);
  padding: 0 24px 16px 0; border-bottom: 1px solid var(--line); vertical-align: bottom;
}
tbody td, tbody th {
  text-align: left; padding: 16px 24px 16px 0;
  border-bottom: 1px solid var(--line-soft); vertical-align: top; font-weight: 400;
}
tbody th { color: var(--white); font-weight: 600; white-space: nowrap; }
tbody tr:last-child td, tbody tr:last-child th { border-bottom: 0; }
td.is-yes { color: var(--white); font-weight: 600; }
.mark { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.table-amounts td:nth-of-type(1) { white-space: nowrap; padding-right: 40px; }
.table-amounts tbody th { width: 26%; white-space: normal; }

/* De opleverlijst op brand-authority.html is een tabel omdat het paren zijn:
   een onderdeel en wat erin zit, met tussenkoppen over de volle breedte. Twee
   kolommen passen wel naast elkaar, dus die blijft een tabel. De termkolom
   stond op nowrap; op 320px duwde "Constructietekening" de tabel dan 58px
   buiten het scherm. Onder 768px mag hij daarom afbreken. */
.oplevering { min-width: 0; }
.oplevering th { text-align: left; font-weight: inherit; }
.oplevering td, .oplevering th {
  padding: 11px 24px 11px 0; border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}
.oplevering tr:not(.oplevering__groep) th:first-child {
  color: var(--white); font-weight: 600; white-space: nowrap;
}
.oplevering__groep th {
  padding: 36px 0 10px; border-bottom: 1px solid var(--line);
  font-size: var(--maat-min2); font-weight: 600; letter-spacing: .18em;
  text-transform: uppercase; color: var(--text-dim);
}
.oplevering__groep:first-child th { padding-top: 0; }
/* De inline-opmaak zette ook onder de laatste rij een lijn, waar de basisregel
   voor tabellen hem juist weghaalt. Die sluitlijn blijft. */
.oplevering tbody tr:last-child td, .oplevering tbody tr:last-child th { border-bottom: 1px solid var(--line-soft); }

@container tabel (max-width: 459px) {
  /* Twee kolommen in 327px maakt de waardekolom zo'n 22 tekens breed, en op
     320px past "Constructietekening" niet eens naast zijn waarde. Het paar komt
     daarom onder elkaar te staan: term, en daaronder wat erin zit. */
  .oplevering, .oplevering tbody, .oplevering tr, .oplevering td, .oplevering th { display: block; }
  .oplevering td, .oplevering th, .oplevering tbody tr:last-child td, .oplevering tbody tr:last-child th { border-bottom: 0; }
  .oplevering tr:not(.oplevering__groep) {
    padding: 11px 0; border-bottom: 1px solid var(--line-soft);
  }
  .oplevering tr:not(.oplevering__groep) td, .oplevering tr:not(.oplevering__groep) th { padding: 0; }
  .oplevering tr:not(.oplevering__groep) th:first-child { white-space: normal; padding-bottom: 2px; }
  .oplevering__groep th { padding: 36px 0 10px; border-bottom: 1px solid var(--line); }
  .oplevering__groep:first-child th { padding-top: 0; }
}

/* Past een tabel niet in de kolom waar hij in staat, dan klapt hij om naar
   blokken: per rij de rijkop als titel, daaronder de waarden onder elkaar.
   Losgetrokken van hun kolom weet een waarde niet meer waar hij bij hoort, dus
   draagt elke cel zijn kolomkop mee in data-label; build.py zet die erop.

   De twee blokken hieronder zijn gelijk op de drempel en de selector na: een
   tabel met tekst erin heeft 640px nodig, een compacte 420px. Ze zijn uit
   hetzelfde sjabloon geschreven, dus pas ze samen aan. */
@container tabel (max-width: 639px) {
  .table--stapel:not(.table--compact) { min-width: 0; }
  .table--stapel:not(.table--compact),
  .table--stapel:not(.table--compact) tbody,
  .table--stapel:not(.table--compact) tr,
  .table--stapel:not(.table--compact) td,
  .table--stapel:not(.table--compact) th { display: block; }
  .table--stapel:not(.table--compact) thead { display: none; }

  .table--stapel:not(.table--compact) tbody tr { padding-bottom: 24px; border-bottom: 1px solid var(--line-soft); }
  .table--stapel:not(.table--compact) tbody tr + tr { padding-top: 24px; }
  .table--stapel:not(.table--compact) tbody tr:last-child { padding-bottom: 0; border-bottom: 0; }

  .table--stapel:not(.table--compact) tbody th {
    padding: 0; border: 0;
    white-space: normal; font-size: var(--maat-0); line-height: 1.35;
  }
  .table--stapel:not(.table--compact) tbody td { padding: 0; border: 0; margin-top: 16px; }
  .table--stapel:not(.table--compact) tbody td .cel__kop {
    display: block; margin-bottom: 6px;
    font-size: var(--maat-min2); font-weight: 600; letter-spacing: .18em;
    text-transform: uppercase; line-height: 1.2; color: var(--text-dim);
  }

  /* Een tabel met .table--uitleg heeft als laatste kolom geen meetwaarde maar
     de betekenis van de rij. Als kolom werkt dat op een breed scherm; gestapeld
     werd het een klein grijs label boven een hele alinea, en dat leest als een
     invulveld in plaats van als een zin. Gestapeld valt het label daarom weg en
     is het gewoon een alinea onder de gemeten waarden. Alleen bij precies een
     zo'n kolom - staan er twee alineakolommen naast elkaar, zoals bij "Wat het
     betekent" en "Wat het kost", dan moet de lezer wel weten welke hij leest. */
  .table--uitleg tbody td:last-child .cel__kop { display: none; }
  .table--uitleg tbody td:last-child {
    margin-top: 20px; font-size: var(--maat-0); line-height: 1.55; color: var(--text);
  }
}

@container tabel (max-width: 419px) {
  .table--compact { min-width: 0; }
  .table--compact,
  .table--compact tbody,
  .table--compact tr,
  .table--compact td,
  .table--compact th { display: block; }
  .table--compact thead { display: none; }

  .table--compact tbody tr { padding-bottom: 24px; border-bottom: 1px solid var(--line-soft); }
  .table--compact tbody tr + tr { padding-top: 24px; }
  .table--compact tbody tr:last-child { padding-bottom: 0; border-bottom: 0; }

  .table--compact tbody th {
    padding: 0; border: 0;
    white-space: normal; font-size: var(--maat-0); line-height: 1.35;
  }
  .table--compact tbody td { padding: 0; border: 0; margin-top: 16px; }
  .table--compact tbody td .cel__kop {
    display: block; margin-bottom: 6px;
    font-size: var(--maat-min2); font-weight: 600; letter-spacing: .18em;
    text-transform: uppercase; line-height: 1.2; color: var(--text-dim);
  }
}

/* ---------- Prijskaarten ---------- */
.pricing { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 24px; width: 100%; }
.price-card { display: flex; flex-direction: column; padding: 32px; border-radius: 6px; border: 1px solid var(--line); background: var(--surface); }
.price-card--featured { border-color: rgba(255,255,255,.34); }
.price-card__tier { color: var(--white); font-size: var(--maat-1); font-weight: 600; margin-bottom: 8px; }
.price-card__for { font-size: var(--maat-min1); color: var(--text-dim); margin-bottom: 24px; min-height: 4.4rem; }
.price-card__amount { font-family: var(--mono); color: var(--white); font-size: var(--maat-6); font-weight: 600; line-height: 1; letter-spacing: -.02em; }
.price-card__unit { font-size: var(--maat-min1); color: var(--text-dim); margin: 8px 0 24px; }
.price-card ul { margin-bottom: 32px; }
.price-card ul li { font-size: var(--maat-min1); }
.price-card .s-button { margin-top: auto; }
.spec { display: flex; justify-content: space-between; gap: 16px; padding: 8px 0; border-top: 1px solid var(--line-soft); font-size: var(--maat-min1); }
.spec span:last-child { color: var(--white); font-weight: 600; text-align: right; font-family: var(--mono); }

/* ---------- Accordeon ---------- */
.faq { width: 100%; border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line-soft); }
.faq summary {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 24px;
  padding: 24px 0; cursor: pointer; color: var(--white); font-weight: 600;
  font-size: var(--maat-0); line-height: 1.4; list-style: none;
}
.faq summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.faq summary::after {
  content: "+"; font-weight: 400; font-size: var(--maat-2);
  color: var(--text-dim); flex: none; line-height: 1.2; transition: transform 200ms;
}
.faq details[open] summary::after { content: "–"; }
/* Zonder maximum liep een antwoord op 1440px door tot 179 tekens per regel,
   ruim twee keer de leesbare bovengrens. 62ch komt bij deze 15px-tekst op
   ongeveer 70 tekens uit, en schaalt mee als de lettergrootte verandert. */
.faq .faq__body { padding: 0 48px 24px 0; max-width: 62ch; }
.faq .faq__body p { font-size: var(--maat-min1); }

/* ---------- Tijdlijn ---------- */
.timeline { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 24px; width: 100%; }
.timeline__step { border-top: 1px solid var(--line); padding-top: 24px; }
.timeline__day { font-size: var(--maat-min2); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim); margin-bottom: 10px; }
.timeline__step h4 { margin-bottom: 8px; }
.timeline__step p { font-size: var(--maat-min1); margin-bottom: 0; }

/* ---------- Notitie / TODO ---------- */
.note {
  width: 100%; border: 1px dashed var(--line); border-radius: 6px;
  padding: 24px; font-size: var(--maat-min1); color: var(--text-dim); background: rgba(255,255,255,.02);
}
.note strong { color: var(--text); }

/* ---------- CTA-band ---------- */
.ctaband > .inner { padding-top: 80px; padding-bottom: 80px; align-items: center; text-align: center; }
.ctaband h2 { max-width: 34ch; }   /* 22ch dwong drie regels af; met balance geeft 34ch er twee */
.ctaband .s-button { align-self: center; }

/* ---------- Formulier ---------- */
.form { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 36px 32px; width: 100%; max-width: 720px; }
.field { display: flex; flex-direction: column; gap: 8px; }
.field--full { grid-column: span 2; }
.field label { font-size: var(--maat-min1); font-weight: 600; color: var(--white); }
/* 16px is hier een ondergrens en geen smaak: Safari op iOS zoomt de hele pagina
   in zodra een invoerveld met een kleinere letter focus krijgt, en zoomt daarna
   niet vanzelf terug. De bezoeker staat dan halverwege het formulier op een
   uitvergrote pagina die hij zelf moet terugslepen. Stond op 1,5rem (15px). */
.field input, .field select, .field textarea {
  font-family: inherit; font-size: var(--maat-0); color: var(--white);
  background: var(--surface); border: 1px solid var(--line-veld); border-radius: 4px;
  padding: 16px; width: 100%;
}
.field textarea { min-height: 120px; resize: vertical; }
/* Nergens vastgelegd, dus viel dit op de standaard van de browser terug en
   haalde 4,07:1. --text-dim is gemeten op 5,43:1. */
.field input::placeholder, .field textarea::placeholder { color: var(--text-dim); opacity: 1; }
.field input:focus, .field select:focus, .field textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; border-color: transparent; }
.field select { appearance: none; background-image: linear-gradient(45deg,transparent 50%,var(--text) 50%),linear-gradient(135deg,var(--text) 50%,transparent 50%); background-position: calc(100% - 18px) 22px, calc(100% - 13px) 22px; background-size: 5px 5px; background-repeat: no-repeat; }
.consent { display: flex; gap: 16px; align-items: flex-start; grid-column: span 2; font-size: var(--maat-min1); }
.consent input { width: 20px; height: 20px; flex: none; margin-top: 1px; }
.hp { position: absolute; left: -9999px; }

/* Overslaan naar de inhoud. Staat uit beeld tot hij focus krijgt; dan springt
   hij linksboven in beeld. Zonder deze link moet iemand die met het toetsenbord
   werkt op elke pagina eerst het hele menu langs voordat hij bij de tekst is. */
.overslaan {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--white); color: var(--bg);
  padding: 12px 20px; font-size: var(--maat-min1); font-weight: 600;
  text-decoration: none; border-radius: 0 0 4px 0;
}
.overslaan:focus { left: 0; outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- Footer ---------- */
#footer { border-top: 1px solid var(--line); }
#footer > .inner { padding-top: 64px; padding-bottom: 48px; gap: 56px; }
.footer__top { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 32px 24px; width: 100%; }
.footer__col h2 { color: var(--text-dim); font-size: var(--maat-min2); letter-spacing: .06em; text-transform: uppercase; font-weight: 600; margin-bottom: 16px; }
.footer__menu { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.footer__menu li { padding: 0; }
.footer__menu li::before { display: none; }
.footer__menu a { font-size: var(--maat-min1); font-weight: 400; color: var(--text); }
.footer__menu a:hover { color: var(--white); opacity: 1; }
.footer__bottom { display: flex; justify-content: space-between; align-items: center; gap: 24px; width: 100%; flex-wrap: wrap; }
.footer__bottom p { font-size: var(--maat-min2); color: var(--text-dim); margin-bottom: 0; }
/* Naam, KVK/btw en adres staan elk op hun eigen regel (drie handmatige
   afbrekingen in build.py) in plaats van één zin die zelf ergens midden in
   afbreekt. Iets extra regelhoogte erbij, anders plakken die drie regels
   tegen elkaar. */
.footer__fine { line-height: 1.85; }

/* ---------- Responsive ---------- */
@media (max-width: 991px) {
  .section > .inner { padding-top: 64px; padding-bottom: 64px; }
  .hero__grid { grid-template-columns: 1fr; row-gap: 32px; align-items: stretch; }
  .hero__headline, .hero__intro, .hero__art { grid-column: span 1; }
  .split { grid-template-columns: 1fr; }
  /* Twee secties (zelftest, brand-authority) gebruiken een split waarvan de
     linkerkolom leeg is: de kop staat daar boven de split in plaats van erin.
     Op desktop moet die lege div blijven staan, anders schuift de tekst naar
     de linkerkolom. Op mobiel is de split één kolom en levert diezelfde lege
     div een rasterrij van niets op — met de rij-tussenruimte erbij was het gat
     tussen de kop en de tekst 80px in plaats van 56px. */
  .split__intro:empty { display: none; }
  .split__intro, .split__body { grid-column: span 1; }

  /* Kop naar tekst: overal 24px.

     Op desktop staan de kop en de tekst van een split naast elkaar, dus daar
     is er geen verticaal gat. Op mobiel klapt de split dicht en bleef de
     rasterruimte van 24px staan bovenop de eigen ondermarge van de kop, ook
     24px. Dat gaf 48px, terwijl de negen secties die hun kop rechtstreeks in
     de sectie zetten op 24px staan. Twee waarden voor dezelfde relatie, en de
     meest voorkomende (52 van de 61) was de toevallige.

     Vandaar `:last-child`, en niet `row-gap: 0` op de hele split: op over.html
     staat onder de kop nog een portret in diezelfde kolom, en daar hoort de
     tekst juist niet tegenaan te schuiven. Is de kop niet het laatste element,
     dan blijft alles zoals het was. */
  .split__intro > h2:last-child { margin-bottom: 0; }
  .split--koploos { margin-top: 0; }
  .grid--onder-label { margin-top: 0; }
  .blok--onder-kop { margin-top: 0; }

  /* Scheidingslijn tussen secties, alleen op mobiel.

     Op desktop scheidt witruimte de secties; op een telefoon staat alles onder
     elkaar en liep het in elkaar over. De hero had als enige al een lijn
     (border-bottom), de rest niet.

     `section + section` raakt alleen twee secties die rechtstreeks op elkaar
     volgen. Staat er een `.divider` tussen — die zet page_hero() en divider()
     als een eigen `div.section` neer — dan slaat de regel over, want dan is er
     al een lijn. Zo komt er nergens een dubbele.

     De lijn springt in tot de kantlijn en gebruikt --line, gelijk aan die
     bestaande dividers. Vandaar een pseudo-element en geen border op de
     sectie: een border loopt over de volle breedte en zou naast een divider
     als een andere lijn lezen. De hero-lijn gaat er daarom hier ook af. */
  main > section + section > .inner { position: relative; }
  main > section + section > .inner::before {
    content: ''; position: absolute; top: 0;
    left: var(--gutter); right: var(--gutter);
    height: 1px; background: var(--line);
  }

  /* De lijn hoort midden tussen twee secties te vallen. Twee uitzonderingen
     zaten scheef: de ctaband heeft 80px eigen padding (gaf 64/80) en de hero
     had 72px onderaan (gaf 72/64). Op mobiel allebei terug naar 64. */
  .ctaband > .inner { padding-top: 64px; padding-bottom: 64px; }

  /* Een blok dat alleen een scheidingslijn bevat — page_hero() en divider()
     zetten die als eigen sectie neer — had zijn eigen padding van 64px boven
     en onder. Opgeteld bij de secties ernaast werd de ruimte rond zo'n lijn
     128px, terwijl de sectielijn hierboven op 64px staat. Twee ritmes voor
     dezelfde scheiding, op dezelfde pagina. Padding eraf: de secties ernaast
     leveren de 64px al. */
  .section--tight:has(> .inner > .divider:only-child) > .inner {
    padding-top: 0; padding-bottom: 0;
  }

  .grid-3, .grid-4, .trust, .pricing, .timeline, .stats { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .trust__item:last-child { grid-column: span 2; }
  .footer__top { grid-template-columns: repeat(2, minmax(0,1fr)); }
}

/* ---------- De telefoon ----------
   Deze staat ná het blok hierboven met opzet: beide regels wegen even zwaar,
   dus de laatste wint. Zet je hem ervóór, dan doet hij niets.

   Op een telefoon is 64 boven en onder elke sectie te veel. Gemeten op een
   iPhone 16 (393 x 852): brand-authority is 13.485 hoog, bijna zestien
   schermen, en 1.520 daarvan is alleen die padding. Op 48 scheelt dat een
   halve pagina zonder dat blokken tegen elkaar komen te staan.

   De hero krijgt bovendien minder lucht bovenin. De titel begon op 178, bijna
   een kwart van het scherm, en de knop eronder eindigde op 744 terwijl Safari
   de onderste negentig pixels afdekt met zijn eigen balk. Met 32 schuift de
   hele hero veertig pixels omhoog en komt de knop weer vrij te staan. */
@media (max-width: 767px) {
  .section > .inner { padding-top: 48px; padding-bottom: 48px; }
  .section--tight > .inner { padding-top: 40px; padding-bottom: 40px; }
  /* Met `.section` ervoor, want `.hero--plain > .inner` staat verderop in dit
     bestand met 96px en zou anders winnen op volgorde. */
  .section.page-hero > .inner,
  .section.hero--plain > .inner { padding-top: 32px; }
}

@media (max-width: 767px) {
  .dropdown {
    position: static; opacity: 1; visibility: visible; transform: none;
    background: transparent; border: 0; box-shadow: none; padding: 0 0 16px; min-width: 0;
    display: none;
  }
  .dropdown.is-open { display: block; }
  .dropdown a { text-align: left; font-size: 15px; color: var(--text); }
  .dropdown .dd-desc { display: none; }
  .grid-2, .grid-3, .grid-4, .trust, .pricing, .timeline, .stats { grid-template-columns: 1fr; }
  .trust__item:last-child { grid-column: span 1; }
  .form { grid-template-columns: 1fr; }
  /* #form-fout hoort hier ook bij. Hij staat met een inline grid-column:span 2
     in de HTML en is normaal verborgen; zodra het versturen mislukt en hij
     verschijnt, dwong hij op 375px een tweede kolom af en halveerde elk veld
     van 327 naar 129 pixels — precies op het moment dat de bezoeker zijn
     invoer moet corrigeren. */
  .field--full, .consent, #form-fout { grid-column: span 1; }
  .footer__top { grid-template-columns: 1fr; }
  .price-card__for { min-height: 0; }
}

/* ---------- Scroll reveal ----------
   Op een echt mobiel toestel scrolt een vinger met vaart een heel scherm in
   een fractie van een seconde weg; de oude 420-1300ms hier werd dan onderweg
   gevangen en bleef dof in beeld staan zodra de duim losliet. Korter (220ms,
   hero 380ms) en een kleinere val (5px, hero 10px) maakt de overgang sneller
   klaar dan een normale scrollbeweging duurt. De observer in main.js geeft
   er nu ook een kop start aan: rootMargin trekt de triggerzone onder de
   viewport, dus de animatie start al voordat een element in beeld komt. */
[data-reveal] { opacity: 0; transform: translateY(5px); transition: opacity 220ms ease, transform 220ms cubic-bezier(.22,.61,.36,1); }
[data-reveal].is-visible { opacity: 1; transform: none; }
.hero__copy[data-reveal] { opacity: 1; transform: none; transition: none; }
.hero__copy > * {
  opacity: 0; transform: translateY(10px);
  transition: opacity 380ms cubic-bezier(.16,1,.3,1), transform 380ms cubic-bezier(.16,1,.3,1);
}
.hero__copy.is-visible > * { opacity: 1; transform: none; }
.hero__copy.is-visible > *:nth-child(1) { transition-delay: 60ms; }
.hero__copy.is-visible > *:nth-child(2) { transition-delay: 120ms; }
.hero__copy.is-visible > *:nth-child(3) { transition-delay: 180ms; }
.hero__copy.is-visible > *:nth-child(4) { transition-delay: 240ms; }

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
  .hero__copy > * { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
  * { animation: none !important; transition-duration: .01ms !important; }
}

/* =========================================================
   Animaties. Alle drie hangen aan [data-reveal].is-visible,
   dus de bestaande IntersectionObserver stuurt ze aan en het
   prefers-reduced-motion-blok hierboven zet ze automatisch uit.
   ========================================================= */

/* ---- 1. Perimeter: toegelaten post komt binnen, onbekende post strandt ---- */
.perimeter { display: block; width: 100%; max-width: 840px; height: auto; margin: 0 auto; }
.perimeter__ring { fill: none; stroke: var(--white); }
.perimeter__core { fill: var(--white); }
.perimeter__trail { stroke-dasharray: 5 6; stroke-width: 1.5; fill: none; }
.perimeter__pkt { opacity: 0; }

.perimeter.is-visible .perimeter__pkt--admit { animation: arm-admit 9s cubic-bezier(.33,0,.35,1) infinite; }
.perimeter.is-visible .perimeter__pulse      { animation: arm-pulse 9s ease-out infinite; }
.perimeter.is-visible .perimeter__pkt--block { animation: arm-block 9s cubic-bezier(.33,0,.5,1) infinite; }
.perimeter.is-visible .perimeter__flare      { animation: arm-flare 9s ease-out infinite; }

@keyframes arm-admit {
  0%        { transform: translate(0,0);         opacity: 0; }
  3%        { transform: translate(0,0);         opacity: 1; }
  24%       { transform: translate(-320px,100px); opacity: 1; }
  27%, 100% { transform: translate(-320px,100px); opacity: 0; }
}
@keyframes arm-pulse {
  0%, 24%   { r: 18; opacity: 0; }
  27%       { r: 18; opacity: .55; }
  40%, 100% { r: 52; opacity: 0; }
}
@keyframes arm-block {
  0%, 45%   { transform: translate(0,0);        opacity: 0; }
  48%       { transform: translate(0,0);        opacity: 1; }
  68%       { transform: translate(168px,-63px); opacity: 1; }
  72%, 100% { transform: translate(168px,-63px); opacity: 0; }
}
@keyframes arm-flare {
  0%, 68%   { r: 4;  opacity: 0; }
  70%       { r: 4;  opacity: .85; }
  84%, 100% { r: 30; opacity: 0; }
}

/* ---- 2 en 3. Balken die vanuit nul uitgroeien ---- */
.meter { margin-top: 32px; }
.meter__track {
  position: relative; height: 34px; border-radius: 3px;
  background: rgba(255,255,255,.04); border: 1px solid var(--line-soft);
  display: flex; overflow: hidden;
}
/* De balken lopen mee met de scrollpositie: --p gaat van 0 naar 1 terwijl
   het blok door beeld komt, en weer terug als je omhoog scrolt. Zonder
   JavaScript blijft --p op 1, dan staan de balken gewoon vol.

   De segmenten houden een vaste breedte; het schalen gebeurt op de laag
   eromheen. Dat scheelt: breedte aanpassen laat de browser bij elke frame
   opnieuw de opmaak berekenen en tekenen, een transform gaat rechtstreeks
   naar de grafische kaart. Dat is waar het schokkerig van werd. */
.meter__fill {
  display: flex; width: 100%; height: 100%;
  transform: scaleX(var(--p, 1));
  transform-origin: left center;
  will-change: transform;
}
.meter__seg {
  width: var(--w);
  border-right: 1px solid var(--bg);
}
.meter__mark { opacity: var(--p, 1); transition: none; }
.is-visible .meter__mark { opacity: var(--p, 1); }
.meter__seg--t0 { background: rgba(255,255,255,.55); transition-delay: 120ms; }
.meter__seg--t1 { background: rgba(255,255,255,.34); transition-delay: 420ms; }
.meter__seg--t2 { background: rgba(255,255,255,.18); transition-delay: 720ms; }
.meter__seg--was { background: rgba(250,250,250,.20); }
.meter__seg--now { background: rgba(250,250,250,.82); }

.meter__mark {
  position: absolute; top: -8px; bottom: -8px; width: 1px;
  background: var(--line); opacity: 0; transition: opacity 500ms ease 1100ms;
}
.is-visible .meter__mark { opacity: 1; }
.meter__mark span {
  position: absolute; top: -20px; left: 6px; white-space: nowrap;
  font-family: var(--mono); font-size: var(--maat-min3); color: var(--text-dim);
}
.meter__scale {
  display: flex; justify-content: space-between; margin-top: 8px;
  font-family: var(--mono); font-size: var(--maat-min3); color: var(--text-dim);
}
.meter__legend { display: flex; flex-wrap: wrap; gap: 8px 32px; margin-top: 16px; }
.meter__legend div { display: flex; align-items: center; gap: 8px; font-size: var(--maat-min2); color: var(--text); }
.meter__legend i { width: 10px; height: 10px; border-radius: 2px; flex: none; font-style: normal; }
.meter__row { margin-bottom: 24px; }
.meter__row h4 { font-size: var(--maat-min2); color: var(--text-dim); margin: 0 0 8px; font-weight: 500; }
.meter__wrap { position: relative; padding-top: 24px; }
.meter__mark { top: 24px; height: 50px; bottom: auto; }
.meter__mark span { top: -20px; }

/* hero: tekst links, perimeter rechts */
.hero__art { grid-column: span 2 !important; display: block; }
.perimeter { max-width: 100%; }
.perimeter__key { list-style: none; margin: 24px 0 0; padding: 0; display: grid; gap: 8px; }
.perimeter__key li { display: flex; gap: 8px; align-items: flex-start; font-size: var(--maat-min2); line-height: 1.45; color: var(--text); }
.perimeter__key i { width: 8px; height: 8px; border-radius: 50%; flex: none; margin-top: 6px; }
.perimeter__key .is-admit { background: var(--white); }
.perimeter__key .is-block { background: rgba(250,250,250,.45); }
@media (max-width: 991px) { .hero__art { grid-column: span 1 !important; } }
.perimeter__key li::before { display: none; }
.perimeter__key li { position: static; }
.hero__headline .lede { margin-top: 24px; max-width: 54ch; }
.hero__headline .button-row { margin-top: 32px; }
/* Dit blok staat eerder in het bestand dan .nav--plain .wordmark__svg,
   dus bij gelijke specificiteit wint die laatste. Vandaar .nav erbij. */
@media (max-width: 767px) {
  .wordmark__logo, .nav.nav--plain .wordmark__svg { height: 12px; }
}

/* Ritme was bedoeld om in meerkoloms rasters elke kop de hoogte van twee
   regels te geven, zodat de body van alle kolommen op dezelfde lijn begint.
   Gemeten over alle rasters en kaarten op de site: geen enkele kop breekt
   ooit naar een tweede regel, op geen enkele breedte vanaf 768px. De reservering
   deed dus nergens iets nuttigs en zette overal een lege regel onder de titel. */
@media (min-width: 768px) {
  .card p { margin-bottom: 24px; }
}
.card .s-button { margin-top: auto; }

/* Cijferstrook: één regel boven de hele rij, voetnoot los van de labels,
   en minder loze ruimte tussen de hero en de cijfers. */
.stats + .source { margin-top: 32px; }
#numbers > .inner { padding-top: 16px; }
@media (max-width: 767px) {
  /* gestapeld hebben de cijfers hun eigen scheiding nodig, want de
     doorlopende lijn boven de rij scheidt ze dan niet meer */
  .stats { gap: 24px 0; }
  .stat + .stat { border-top: 1px solid var(--line); padding-top: 24px; }
}

/* Juridische links horen in de onderbalk, naast de copyright. */
.footer__legal { display: flex; flex-wrap: wrap; gap: 24px; list-style: none; margin: 0; padding: 0; }
.footer__legal li { padding: 0; position: static; }
.footer__legal li::before { display: none; }
.footer__legal a { font-size: var(--maat-min1); font-weight: 400; color: var(--text); }

/* De meters stonden in een flex-kolom met align-items:flex-start en hadden
   geen breedte, waardoor ze inkrompen tot hun inhoud in plaats van de kolom
   te vullen. Vandaar dat ze smaller waren dan de tabel erboven. */
.meter, .meter__track, .meter__wrap, .meter__scale { width: 100%; }

/* Signaalkleuren: gedempt hoort niet dof te betekenen. De vlakken gebruiken
   nu de signaalachtergronden uit het palet op volle dekking. */
.meter__seg--was { background: rgba(250,250,250,.20); }
.meter__seg--now { background: rgba(250,250,250,.82); }
.meter__seg--t0 { background: rgba(255,255,255,.62); }
.meter__seg--t1 { background: rgba(255,255,255,.42); }
.meter__seg--t2 { background: rgba(255,255,255,.26); }

/* =========================================================
   BANDEN. Het ritme komt van hele bandwisselingen, niet van
   luminantiestapjes. Een lichte sectie hertekent de tokens
   binnen zijn eigen scope, waardoor elke component die
   var(--text), var(--line) enzovoort gebruikt vanzelf meegaat.
   ========================================================= */
:root {
  --band:      #EDEDED;   /* Platinum        lichte band */
  --band-ink:  #0F0F0F;   /* koppen op licht */
  --band-text: #4A4A4A;   /* lopende tekst op licht */
  --band-dim:  #5E5E5E;   /* labels op licht */
  --band-line: #CFCFCF;   /* 1px scheiding op licht */
}


/* ---------- Hero met beeld, randloos ---------- */
/* De hero is puur typografisch. Geen beeld, geen verloop, geen laag eroverheen:
   obsidiaanzwart, een enkele haarlijn en de tekst. Wat een Zwitserse kluis
   laat zien is een deur, geen foto van een deur. */
.hero--plain {
  position: relative;
  min-height: 100vh; min-height: 100svh;
  display: flex; align-items: center;
  background: var(--bg);
  border-bottom: 1px solid var(--line-soft);
}
.hero--plain > .inner { position: relative; z-index: 2; width: 100%; padding-top: 96px; padding-bottom: 96px; }
/* Eén haarlijn links van de kolom, op het raster. Het enige grafische element. */
.hero--plain > .inner::before {
  content: ""; position: absolute; left: 0; top: 96px; bottom: 96px;
  width: 1px; background: var(--line);
}
.hero__copy { max-width: none; padding-left: 32px; display: flex; flex-direction: column; }
/* Zelfde reden als .split__body hierboven. Als blok klapten de marges hier
   samen en stond de claimregel op 32px van de kop en de knop op 40px van de
   tekst, terwijl de elf andere hero's allebei 56px doen. */
/* De kop mag de volle kolom gebruiken; de leesbreedte van de lopende tekst
   verandert daar niet door, want .hero__def en .hero__copy .lede hebben
   hun eigen max-width. Bij 62ch (670px) brak de kop naar drie regels. */
/* De kop breekt op de plek die in de tekst staat, niet op de plek waar de
   kolom toevallig ophoudt. Elke regel is een eigen blok dat niet mag afbreken;
   de grootte krimpt mee met het venster zodat de langste regel altijd past. */
/* De kop in de hero is het lichtste en zwaarste element van de site. Bij
   #FAFAFA op bijna-zwart loopt het licht zichtbaar over in de achtergrond:
   halatie, wat als een gloed leest. Dat wordt nu aan twee kanten gedempt — de
   achtergrond staat op #121212 en de kop op --display. Als de gloed daarmee
   weg is, kan --display terug naar --white en is de display-schaal weer
   eenkleurig. Eerst kijken, dan pas veranderen. */
.hero__copy h1 { letter-spacing: -0.02em; max-width: none; color: var(--display); }
.hero__copy h1 .l { display: block; white-space: nowrap; }
/* Onder 645px past de langste heroregel niet meer op een regel van 40px.
   Vanaf de mobiele breekpunt-grens laten we hem dus gewoon afbreken. */
@media (max-width: 767px) { .hero__copy h1 .l { white-space: normal; } }
/* De definitie is de claim. Hij staat op eigen hoogte tussen de kop en de uitleg,
   met een haarlijn erboven in plaats van een kader eromheen. */
.hero__def {
  margin-top: 32px; padding-top: 24px; max-width: 46ch;
  border-top: 1px solid var(--line);
  font-size: var(--maat-2); line-height: 1.35; font-weight: 600; color: var(--display);
}
/* De uitleg staat er bewust onder en bewust kleiner: verhelderend, niet dragend. */
.hero__copy .lede {
  /* Was margin-top: 24px. Toen .hero__copy nog een blok was klapte die samen
     met de ondermarge van .hero__def, ook 24px, tot 24px. Nu de container flex
     is tellen ze op en werd het 48px, terwijl twee alinea's overal op de site
     24px uit elkaar staan. De ondermarge van .hero__def levert die 24px al. */
  margin-top: 0; max-width: 56ch;
  font-size: var(--maat-0); line-height: 1.62; color: var(--text);
}
.hero__copy .button-row { margin-top: 32px; }   /* 24 + 32 = 56, gelijk aan de andere hero's */
@media (max-width: 767px) {
  .hero--plain { min-height: 0; }
  /* De scheidingslijn tussen secties (zie het mobiele blok hierboven) tekent
     de volgende sectie zelf. Deze border stond eerder ook in dat blok, maar dat
     staat vóór `.hero--plain` in het bestand en verloor dus van de basisregel.
     Bij gelijke specificiteit wint de laatste regel, niet de meest specifieke. */
  .hero--plain { border-bottom: 0; }
  /* Op mobiel staat de balk static (zie de nav-regels verderop) en neemt dus
     zelf al 83px in beslag vóór de hero begint. 120px erbovenop was dubbele
     marge: er stond dan zo'n 200px lege ruimte boven de kop op een gewoon
     telefoonscherm. Dat gold niet voor desktop, waar de balk fixed over de
     hero heen ligt en deze padding juist wél de enige ruimte is die de kop
     vrijhoudt van het beeldmerk — daar blijft 96px staan. */
  .hero--plain > .inner { padding-top: 64px; padding-bottom: 64px; }   /* 72 gaf 72/64 rond de lijn eronder */
  .hero--plain > .inner::before { display: none; }
  .hero__copy { padding-left: 0; }
  /* De kop bestaat uit twee helften die elk een eigen regel horen te zijn. Op
     een vaste 32px paste de eerste helft niet meer op één regel en brak hij in
     tweeën: dan staat er "Uw merk" op een regel van 124px in een kolom van 327,
     gevolgd door nog drie regels. Vier regels, waarvan de eerste voor een derde
     gevuld.

     De maat schaalt daarom mee met het scherm. "Uw merk wordt toegepast" meet
     11,2 keer de lettergrootte, dus bij een kolom van `100vw - 48px` past hij
     zolang de letter onder `8,9vw - 4,3px` blijft.

     Die 8,9 is alleen waar in Chromium. Op iOS Safari rendert dezelfde tekst
     **8,2 procent breder** — gemeten aan een schermfoto: "Uw merk wordt" is
     daar 210px waar Chromium 194px geeft. Een eerdere versie stond op
     `8,6vw - 4px` en hield daarmee maar 3 procent speling over; op een iPhone
     was dat niet genoeg en viel de kop alsnog in vier regels, met "toegepast"
     als losse tweede regel. `7,6vw - 4px` houdt overal 8 procent over, ruim
     boven die 8,2 procent.

     Wil je dit narekenen: meet in een gewone browser op `lettergrootte x 1,082`,
     dan zie je wat iOS doet. Meten op de echte maat geeft een uitkomst die er
     goed uitziet en het op een telefoon niet is.

     Bovengrens 32px, zodat hij op een brede telefoon niet groter wordt dan
     ontworpen. Ondergrens 20px: de formule zelf komt op geen enkele
     telefoonbreedte zo laag uit, dus dit is alleen een bodem voor extreem
     smalle schermen.

     Twee regels totaal is niet haalbaar: daarvoor zou de tweede helft naar
     ongeveer 23px moeten, en dan staat de hoofdkop kleiner dan de sectiekoppen
     eronder. Drie regels met een volle eerste regel is het optimum. */
  .hero__copy h1 { font-size: clamp(20px, calc(7.6vw - 4px), 32px); font-weight: 600; }
  .hero__def { font-size: var(--maat-1); }
}


/* =========================================================
   Regelval. balance verdeelt een kop over gelijke regels, zodat er
   nooit één woord alleen achterblijft. Dat werkt op een kop van twee
   of drie regels; het is niet bedoeld voor lopende tekst.

   Hier stond eerder ook `p, li, .source, .faq__body { text-wrap: pretty }`
   en `.lede` in de balance-lijst hieronder. Allebei verwijderd, en dat is
   geen detail: ze zorgden ervoor dat elke alinea op een eigen breedte
   afbrak. Gemeten op 375px in een kolom van 327px: .hero__def kwam op 279px
   (48px onbenut), een .lede van zes regels op 299px, en vier alinea's naast
   elkaar op 307, 313, 318 en 327px. Het blok is dus wél volledig breed —
   alleen de regels erbinnen niet, en per alinea anders. In Safari op iOS is
   dat effect veel sterker dan in Chromium, want daar herverdeelt `pretty`
   de hele alinea in plaats van alleen de laatste regel; op een telefoon
   leest dat als tekst die de kolom niet vult.

   Zet ze niet terug zonder de regelbreedtes opnieuw te meten met
   Range.getClientRects(). Meten aan het element zelf helpt niet: dat is
   altijd de volle kolombreedte, ook als de tekst erbinnen smaller valt.
   ========================================================= */
h1, h2, h3, h4, .stat__label, .trust__item h4, .card h3, .item h3, .item h4 {
  text-wrap: balance;
}

/* Hero komt langzaam tot leven: 5% inzoomen en weer terug, 32 seconden per
   richting. Het brandpunt ligt richting het raam, niet in het midden, zodat
   de beweging organisch aanvoelt in plaats van mechanisch. Het globale
   prefers-reduced-motion-blok zet dit vanzelf uit. */

/* Navigatie. Over de hero geen achtergrond. Zodra je van de bovenkant af bent
   komt er wel een achtergrond, anders landen de links op je eigen tekst.
   Omlaag scrollen verbergt de balk, terugscrollen laat hem weer zakken. */
/* Over de hero geen achtergrond. Zodra je van de bovenkant af bent komt er
   wel een achtergrond, anders landen de links op je eigen tekst.
   Omlaag scrollen verbergt de balk, terugscrollen laat hem weer zakken. */
.nav.is-scrolled {
  background-color: rgba(10, 10, 10, .82);
  backdrop-filter: saturate(140%) blur(16px);
  -webkit-backdrop-filter: saturate(140%) blur(16px);
  border-bottom-color: var(--line-soft);
}
.nav.is-hidden { transform: translateY(-100%); }
@media (prefers-reduced-motion: reduce) { .nav { transition: none; } }

/* De tekening houdt de kolombreedte aan, gelijk aan de rest van de pagina.
   De eerdere overflow-x: clip op de body hoorde bij de volle-vensterbreedte
   die hier stond. Die is weg, dus de clip ook: hij maakte de body tot
   scroll-container en dat verhoudt zich slecht tot paginawissels. */
.figure svg { min-width: 900px; }

/* Homepagina: de balk is kleurloos en blijft staan. Geen achtergrond, geen
   rand, en de verbergstand grijpt er niet op aan. Het mobiele menu houdt
   wel zijn eigen achtergrond, want dat vult het scherm. */
.nav--plain,
.nav--plain.is-scrolled {
  background-color: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom-color: transparent;
}
.nav--plain.is-hidden { transform: none; }

/* Bovenaan de homepagina heeft ook het uitklapmenu geen achtergrond: geen
   vlak, geen rand, geen schaduw. De titels blijven wit, de regel eronder grijs.
   De samengeklapte stand houdt zijn eigen paneel, dus die valt hierbuiten. */
.nav--plain:not(.is-compact) .dropdown {
  background: none; border: 0; border-radius: 0; padding: 6px 0;
}
.nav--plain:not(.is-compact) .dropdown a { color: var(--white); }
.nav--plain:not(.is-compact) .dropdown a:hover .dd-desc { color: var(--text); }

/* Twee standen op de homepagina, en de stand hangt alleen af van hoe ver je
   staat, niet van de richting waarin je scrolt.
   1. Op de hero: kleurloos, volledig logo, volledig menu.
   2. Zodra de hero weg is: schildje links, hamburger rechts, in de hoeken.
      Geen achtergrond; difference keert ze om tegen wat eronder doorschuift.
      Dat blijft zo als je terugscrolt, tot je de hero weer raakt. */

/* De balk gebruikt altijd de volle breedte; de padding brengt hem op het raster.
   Alleen die padding animeert, en dat gaat vloeiend. */
.nav--plain .nav__container {
  max-width: none;
  /* Dezelfde formule als `.section > .inner` (32px gutter, gecentreerd op
     --container). Een eigen marge van 80px vanaf 1024px is geprobeerd en
     losgelaten: de balk liep dan tot 48px verder naar binnen dan de tekst
     eronder, want de content gebruikt altijd 32px. Blijft dit gelijk aan de
     content-formule, dan lijnen logo en menu overal exact uit. */
  padding-inline: max(var(--gutter), calc((100% - var(--container)) / 2 + var(--gutter)));
  transition: padding 300ms cubic-bezier(.16,1,.3,1);
}
/* Tweede fase van het samenklappen: nadat de letters en de menu-items zijn
   weggevallen (.is-fading), schuift wat overblijft — het schildje links, de
   hamburger rechts — naar de hoeken. padding-inline raakt beide kanten
   tegelijk, dus "allebei" schiet in dezelfde beweging. De overgang staat al
   op de basisregel hierboven, dus dit springt niet: het glijdt in 300ms. */
.nav--plain.is-compact .nav__container { padding-inline: 24px; }

/* Eén inline beeldmerk in plaats van twee plaatjes die kruisvervagen. Het
   schildje staat vooraan in hetzelfde vlak en beweegt dus nooit; alleen de
   acht letters vallen weg. De doos blijft even breed, dus niets verspringt. */
.nav--plain .wordmark { display: inline-block; line-height: 0; }
.nav--plain .wordmark__svg { display: block; height: 16px; width: auto; color: #fff; overflow: visible; }
/* Letter voor letter, van de S terug naar de A, alsof het woord in het
   schildje trekt. Terug op de hero gaat het andersom: A eerst. */
.nav--plain .wm__l {
  transform-box: fill-box; transform-origin: left center;
  transition: opacity 260ms ease, transform 260ms cubic-bezier(.16,1,.3,1);
  transition-delay: calc(var(--i) * 30ms);
}
.nav--plain.is-fading .wm__l {
  opacity: 0; transform: translateX(-60px);
  transition: opacity 260ms ease, transform 260ms cubic-bezier(.16,1,.3,1);
  transition-delay: calc((2 - var(--i)) * 30ms);
}
/* Samengeklapt keert de balk om tegen de pagina; daar moet het schildje
   effen wit zijn, anders keert het verloop mee om. */
.nav--plain.is-compact .wm__mark polygon { fill: #fff; }
.nav--plain .nav__row { transition: background-color 260ms ease; }
/* De auditknop is het hoogste element in de balk en bepaalt dus de rijhoogte.
   Zolang die knop verdween met display:none kromp de rij van 89 naar 83px en
   schoof het schildje 3,3px omhoog. Nu blijft de knop in de rij staan, alleen
   nul pixels breed en onzichtbaar, dus de hoogte staat vast zonder vast getal. */
.nav--plain .nav__container { min-height: 50px; align-items: center; }

/* Eerste fase: de menu-items vallen een voor een weg, van links naar rechts,
   alsof de rij in de hamburger schuift. Spiegelbeeld van de letters, die naar
   het schildje toe verdwijnen. Zolang deze fase loopt beweegt er nog niets;
   pas daarna schuift wat overblijft naar de hoeken. */
.nav--plain .nav__menu > li {
  transition: opacity 260ms ease, transform 260ms cubic-bezier(.16,1,.3,1);
  transition-delay: calc((3 - var(--i, 0)) * 30ms);
}
.nav--plain.is-fading .nav__menu > li {
  opacity: 0; transform: translateX(14px);
  transition: opacity 260ms ease, transform 260ms cubic-bezier(.16,1,.3,1);
  transition-delay: calc(var(--i, 0) * 30ms);
}
/* In het uitschuifpaneel horen ze gewoon zichtbaar te zijn, en komen ze van
   boven naar beneden binnen. */
.nav--plain.is-compact .nav__menu.is-open > li {
  opacity: 1; transform: none;
  transition-delay: calc(90ms + var(--i, 0) * 35ms);
}
/* De hamburger verschijnt pas in de tweede fase, en meteen op zijn eindplek. */
@keyframes nav-burger-in { from { opacity: 0; } to { opacity: 1; } }

/* Samengeklapt: naar de hoeken, geen achtergrond, en omkeren tegen de pagina. */
.nav--plain.is-compact {
  background-color: transparent;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  border-bottom-color: transparent;
  mix-blend-mode: difference;
}


.nav--plain.is-compact .nav__right > .s-button {
  visibility: hidden; width: 0; min-width: 0; padding-left: 0; padding-right: 0;
  border-left-width: 0; border-right-width: 0; margin: 0; overflow: hidden;
}
.nav--plain.is-compact .nav__toggle { display: inline-flex; color: #fff; z-index: 201;
  animation: nav-burger-in 220ms ease; }
.nav--plain.is-compact .nav__toggle svg { fill: #fff; }


/* De sluier. Het paneel komt naar voren doordat de pagina wegzakt, niet
   doordat het paneel oplicht. Dat is de rustigste manier om diepte te maken
   op een site die verder één zwart vlak is, en het vangt meteen de klik
   buiten het menu op. */
.nav__scrim {
  position: fixed; inset: 0; z-index: 199;
  background-color: rgba(0, 0, 0, .5);
  opacity: 0; visibility: hidden;
  transition: opacity 240ms ease, visibility 0s linear 240ms;
}
.nav__scrim.is-on {
  opacity: 1; visibility: visible;
  transition: opacity 240ms ease, visibility 0s;
}

/* Menu open: blenden uit, anders keert het paneel tegen zichzelf om. */
.nav--plain.is-compact:has(.nav__menu.is-open) { mix-blend-mode: normal; }

/* Het paneel schuift binnen vanaf rechts. */
.nav--plain.is-compact .nav__menu {
  display: flex; position: fixed; top: 0; right: 0; bottom: 0; left: auto;
  width: min(420px, 100%); z-index: 200;
  flex-direction: column; justify-content: center; align-items: stretch; gap: 4px;
  background-color: var(--band-ink); border-left: 1px solid rgba(250, 250, 250, .16);
  margin: 0; padding: 0 32px;
  transform: translateX(100%); visibility: hidden;
  transition: transform 240ms cubic-bezier(.4,0,.2,1), visibility 0s linear 240ms;
}
.nav--plain.is-compact .nav__menu.is-open {
  transform: translateX(0); visibility: visible;
  transition: transform 240ms cubic-bezier(.4,0,.2,1), visibility 0s;
}
.nav--plain.is-compact .nav__menu > li { width: 100%; text-align: left; }
.nav--plain.is-compact .nav__menu > li > a,
.nav--plain.is-compact .nav__menu > li > button { font-size: 20px; padding: 14px 0; justify-content: flex-start; width: 100%; }

/* Op de homepagina staat de balk erbovenop en moet de hero vanaf pixel nul
   beginnen. De 72px die elders de vaste balk vrijhoudt, vervalt daar. */
/* Alleen op de homepagina hoeft de pagina geen ruimte te maken, want daar
   ligt de balk over een hero van schermhoogte. Elders houdt .page zijn
   bovenruimte, zodat de titel niet onder de balk begint. */
.nav--over + .page { padding-top: 0; }

/* 'Who it's for' binnen het paneel: geen zwevend kader maar een accordeon
   die op klik opengaat. max-height animeert wél, display niet. */
.nav--plain.is-compact .dropdown,
.nav--plain.is-compact .dropdown {
  position: static; display: block; opacity: 1; visibility: visible; transform: none;
  background: transparent; border: 0; box-shadow: none; min-width: 0;
  overflow: hidden; max-height: 0; padding: 0;
  transition: max-height 205ms cubic-bezier(.4,0,.2,1), opacity 135ms ease, padding 205ms ease;
}
.nav--plain.is-compact .dropdown.is-open { max-height: 340px; opacity: 1; padding: 4px 0 16px; }
.nav--plain.is-compact .dropdown a { text-align: left; font-size: 15px; color: var(--text); padding: 10px 0; }
.nav--plain.is-compact .dropdown a:hover { color: var(--white); }
.nav--plain.is-compact .dropdown .dd-desc { display: block; font-size: 12.5px; color: var(--text-dim); }

/* Zelfde accordeon op mobiel, in plaats van de harde display-wissel. */
@media (max-width: 767px) {
  .nav__menu {
    left: auto; right: 0; width: min(420px, 100%);
    border-left: 1px solid var(--line);
    align-items: stretch; padding: 0 24px;
    transform: translateX(100%); visibility: hidden; display: flex;
    transition: transform 420ms cubic-bezier(.4,0,.2,1), visibility 0s linear 420ms;
  }
  .nav__menu.is-open { transform: translateX(0); visibility: visible; transition: transform 420ms cubic-bezier(.4,0,.2,1), visibility 0s; }
  .nav__menu > li { text-align: left; }
  .nav__menu > li > a, .nav__menu > li > button { justify-content: flex-start; }
  .dropdown {
    display: block; overflow: hidden; max-height: 0; padding: 0;
    transition: max-height 360ms cubic-bezier(.4,0,.2,1), padding 360ms ease;
  }
  .dropdown.is-open { max-height: 340px; padding: 4px 0 16px; }
  .dropdown a { text-align: left; }
  .dropdown .dd-desc { display: block; }
}

/* Bij het wisselen van stand mag het paneel niet meeanimeren: anders zie je
   het menu eerst staan en daarna naar rechts wegschuiven. */
.nav--plain.no-anim .nav__menu,
.nav--plain.no-anim .dropdown { transition: none !important; }


/* =========================================================
   Mobiel. Dit blok staat bewust achteraan: de regels voor de balk op de
   desktop komen verderop in het bestand dan het algemene mobiele blok, en
   bij gelijke specificiteit wint de laatste. Hier stond eerst hetzelfde,
   maar dan te vroeg, waardoor het omkeren en de paneelbreedte alsnog van
   de desktop kwamen.
   ========================================================= */
@media (max-width: 767px) {
  /* Op mobiel geen samenklap-effect. De balk scrolt gewoon mee en blijft
     staan zoals hij is: beeldmerk links, de auditregel zonder kader, en de
     hamburger rechts. Alles wat de balk op de desktop laat reizen, omkeren
     of letters laat wegvallen, wordt hier uitgezet. */
  .nav, .nav--plain { position: static; }
  .nav--plain.is-compact,
  .nav--plain.is-fading { mix-blend-mode: normal; }
  .nav--plain.is-compact .wm__l,
  .nav--plain.is-fading .wm__l,
  .nav--plain.is-compact .nav__menu > li,
  .nav--plain.is-fading .nav__menu > li { opacity: 1; transform: none; transition: none; }
  .nav--over + .page { padding-top: 0; }
  .page { padding-top: 0; }

  /* De losse knop naast de hamburger is twee keer hetzelfde gebaar op deze
     breedte. Hij verdwijnt hier; de kopie in .nav__menu (hieronder) neemt het
     over, als laatste regel in de uitklaplade. */
  .nav__right > .s-button { display: none; }
  .nav__toggle { display: inline-flex; z-index: 201; order: 2; }

  /* Het paneel is ook hier een lade van rechts, alleen smaller. */
  .nav__menu, .nav--plain.is-compact .nav__menu {
    display: flex; position: fixed; top: 0; right: 0; bottom: 0; left: auto;
    width: min(320px, 84%); z-index: 200;
    flex-direction: column; justify-content: center; align-items: stretch; gap: 4px;
    background-color: var(--band-ink); border-left: 1px solid rgba(250, 250, 250, .16);
    margin: 0; padding: 0 24px;
    transform: translateX(100%); visibility: hidden;
    transition: transform 240ms cubic-bezier(.4,0,.2,1), visibility 0s linear 240ms;
  }
  .nav__menu.is-open, .nav--plain.is-compact .nav__menu.is-open {
    transform: translateX(0); visibility: visible;
    transition: transform 240ms cubic-bezier(.4,0,.2,1), visibility 0s;
  }
  .nav__menu > li { width: 100%; text-align: left; }
  .nav__menu > li > a, .nav__menu > li > button { font-size: 18px; padding: 13px 0; justify-content: flex-start; width: 100%; }

  /* Kopie van de zelftestknop, als laatste regel in de lade. Los van de vier
     tekstlinks erboven: eigen ruimte, en de opmaak van .s-button blijft
     zichtbaar in plaats van op te lossen in de platte linkstijl hierboven. */
  .nav__menu__cta { display: block; width: 100%; margin-top: 20px; }
  .nav__menu__cta > .s-button {
    display: flex; justify-content: center;
    font-size: 15px; padding: 16px 24px; width: 100%;
    border: 1px solid var(--line);
  }
}


/* =========================================================
   Eerste bezoek van de homepagina. Het schildje staat er meteen, daarna
   lopen de letters er een voor een in, en het menu erachteraan. Zelfde duur
   en zelfde trap als bij het terugscrollen: 123ms per element, 20ms ertussen.

   Dit staat bewust in CSS en niet in JavaScript. Een script draait pas na de
   eerste tekening, dus dan zie je de letters eerst staan, daarna verdwijnen
   en daarna terugkomen. Een animatie uit het stylesheet loopt vanaf de eerste
   frame.

   animation-fill-mode is backwards en niet both. Backwards zet de beginstand
   klaar voordat de animatie loopt, zodat er niets opflikkert, maar laat het
   element daarna terugvallen op zijn gewone stijl. Met both zou de eindstand
   blijven plakken en zouden de overgangen bij het scrollen daarna niet meer
   werken.
   ========================================================= */
@media (prefers-reduced-motion: no-preference) {
  .nav--over .wm__l {
    animation: nav-intro 260ms cubic-bezier(.16, 1, .3, 1) backwards;
    animation-delay: calc(90ms + var(--i) * 30ms);
  }
  .nav--over .nav__menu > li {
    animation: nav-intro 260ms cubic-bezier(.16, 1, .3, 1) backwards;
    animation-delay: calc(250ms + var(--i, 0) * 30ms);
  }
  .nav--over .nav__right > .s-button {
    animation: nav-intro 260ms cubic-bezier(.16, 1, .3, 1) backwards;
    animation-delay: 370ms;
  }
}
@keyframes nav-intro {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Contactpagina: het formulier links, de directe gegevens ernaast. Die
   gegevens zijn voor een CISO de snelste route, dus ze horen niet onder een
   formulier van zeven velden te liggen. Het formulier is 720px breed in een
   kolom van bijna 1400, dus die ruimte stond er toch al. */
/* De zijkolom krijgt een gegarandeerde breedte en het formulier krimpt eerst.
   Andersom kreeg de zijkolom wat er toevallig overbleef, en dan wordt de
   tekst daar op sommige vensterbreedtes drie woorden per regel. */
.contact__grid {
  display: grid;
  grid-template-columns: minmax(0, 720px) minmax(320px, 400px);
  gap: clamp(56px, 5vw, 104px); align-items: start;
  justify-content: start;
}
.contact__direct {
  padding-top: 4px;
}
.contact__direct .spec:first-of-type { border-top: 0; padding-top: 0; }
.contact__direct .eyebrow { display: block; margin-bottom: 16px; }
.contact__direct p { max-width: 42ch; }
.contact__direct .source { margin-top: 28px; max-width: 42ch; }
/* In een smalle kolom past een adres niet naast zijn label. Hier staat het
   label er dus boven, klein, en de waarde eronder op volle breedte. Zo kan
   demy.rink@armaegis.com nooit uit de kolom lopen. */
.contact__direct .spec {
  display: block; padding: 12px 0; margin-top: 0;
}
.contact__direct .spec span:first-child {
  display: block; font-size: var(--maat-min2); color: var(--text-dim); margin-bottom: 4px;
}
.contact__direct .spec span:last-child {
  display: block; text-align: left; font-size: var(--maat-min1);
  overflow-wrap: anywhere;
}
.contact__direct .spec a { color: var(--white); border-bottom: 1px solid var(--line); }
.contact__direct .spec a:hover { border-bottom-color: var(--white); opacity: 1; }
@media (max-width: 1199px) {
  /* Onder deze breedte wordt de zijkolom te smal om te lezen. Gestapeld staan
     de gegevens bovenaan: sneller dan zich door zeven velden heen werken, en
     dat is voor deze lezer het punt. */
  .contact__grid { grid-template-columns: 1fr; gap: 56px; }
  .contact__direct { order: -1; }
  .contact__direct p, .contact__direct .source { max-width: 60ch; }
  .contact__direct .spec { display: flex; justify-content: space-between; }
  .contact__direct .spec span:first-child { display: inline; margin-bottom: 0; }
  .contact__direct .spec span:last-child { text-align: right; }
}


/* =========================================================
   Zelftest. Zonder JavaScript is dit een gewone lijst: vijf vragen met hun
   antwoorden en beide bevindingen eronder, leesbaar en compleet. main.js zet
   er `zt--actief` op en bouwt hem dan om naar een test met een vraag tegelijk.
   Alles hieronder wat met `.zt--actief` begint geldt dus alleen met JavaScript;
   de rest is de leesbare versie.
   ========================================================= */
.zt__lijst { list-style: none; margin: 40px 0 0; padding: 0; }
.zt__lijst > li::before { display: none; }
.zt__vraag { padding: 0; }
.zt__vraag + .zt__vraag { margin-top: 48px; border-top: 1px solid var(--line-soft); padding-top: 48px; }
.zt__stap {
  font-size: var(--maat-min2); font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-dim); margin-bottom: 12px;
}
.zt__stap .mono { font-family: var(--mono); letter-spacing: 0; }
.zt__vraag h4 { margin-bottom: 16px; }
.zt__opties { list-style: none; margin: 0 0 16px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.zt__opties > li { padding: 0; }
.zt__opties > li::before { display: none; }
.zt__bevinding { margin-top: 12px; }

/* ---- Met JavaScript: één vraag tegelijk ---- */
.zt--actief .zt__vraag { display: none; }
.zt--actief .zt__vraag.is-nu { display: block; }
/* De vraag staat los; de scheidingslijn tussen vragen hoort bij de leeslijst. */
.zt--actief .zt__vraag + .zt__vraag { margin-top: 0; border-top: 0; padding-top: 0; }
.zt--actief .zt__bevinding { display: none; }

.zt__optie {
  display: block; width: 100%; text-align: left; cursor: pointer;
  font-family: inherit; font-size: var(--maat-0); line-height: 1.45; color: var(--text);
  background: none; border: 1px solid var(--line); border-radius: 6px;
  padding: 16px 18px;
  transition: color 140ms ease, border-color 140ms ease, background-color 140ms ease;
}
.zt__optie:hover { color: var(--white); border-color: var(--text-dim); }
.zt__optie:focus-visible { outline: 2px solid rgba(255,255,255,.75); outline-offset: 3px; }

/* ---- De uitkomst ---- */
.zt__uitkomst { display: none; }
.zt--klaar .zt__uitkomst { display: block; }
.zt--klaar .zt__vraag { display: none; }
.zt__uitkomst h3 { margin-bottom: 24px; }   /* gelijk aan kop -> tekst elders */
.zt__intro { font-size: var(--maat-0); line-height: 1.55; color: var(--text); margin-bottom: 32px; max-width: 58ch; }
.zt__punt { border-top: 1px solid var(--line); padding-top: 20px; margin-top: 20px; }
.zt__punt:first-of-type { margin-top: 0; }
/* p.zt__punt-laag en niet .zt__punt-laag: de regel hieronder is `.zt__punt p`
   en die is specifieker dan een losse klasse. Zonder het element ervoor won
   die met margin-bottom: 0 en plakte het label tegen zijn eigen tekst. */
p.zt__punt-laag {
  font-size: var(--maat-min2); font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-dim); margin-bottom: 8px;
}
.zt__punt p:last-child { margin-bottom: 0; }
.zt__punt p { max-width: 58ch; }
.zt__opnieuw {
  margin-top: 32px; background: none; border: 0; padding: 0; cursor: pointer;
  font-family: inherit; font-size: var(--maat-min1); color: var(--text-dim);
  text-decoration: underline; text-underline-offset: 4px;
}
.zt__opnieuw:hover { color: var(--white); }

@media (max-width: 767px) {
  .zt__lijst { margin-top: 32px; }
  .zt__vraag + .zt__vraag { margin-top: 32px; padding-top: 32px; }
  .zt__optie { font-size: var(--maat-min1); padding: 14px 16px; }
  .zt__intro { font-size: var(--maat-0); }
}

/* De drie ankerpunten op demonstraties. De scroll-marge houdt de deelkop vrij
   van de balk als je er via een ankerlink naartoe springt. */
#casus-diagnose, #casus-namen-blijven, #casus-namen-verdwijnen { scroll-margin-top: 24px; }

/* =========================================================
   Schermafdrukken in deel B van demonstraties.
   Deel A meet en blijft tekst; deel B laat zien wat er gebouwd is. Het beeld
   krijgt daarom een vast kader met rust eromheen in plaats van vol te lopen.
   Reden: de pagina eromheen is monochroom, en een schermafdruk van een
   merksysteem is het enige gekleurde vlak op de hele site. Vol laten lopen
   trekt de sectie naar zich toe en zet deel B in een ander register dan
   deel A, terwijl het contrast tussen meten en bouwen juist moet kloppen.
   ========================================================= */
.schermbeeld { margin: 32px 0 0; }
.schermbeeld figure { margin: 0; }
.schermbeeld img,
.schermbeeld figure img {
  border: 1px solid var(--line); border-radius: 4px; background-color: var(--surface);
}
.schermbeeld figcaption, .schermbeeld .source { margin: 12px 0 0; }

/* Tekst die alleen een schermlezer hoort: uit beeld genomen zonder hem uit de
   leesvolgorde te halen. Staat hier los, want hij zat in het blok hieronder dat
   met de schermfilm mee weg is - en toen stond "(opent in een nieuw tabblad)"
   ineens zichtbaar achter elke link naar de demonstratie. */
.alleen-lezer {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* De hero stond hier in vier standen en De Bron als doorloopbare film: aanwijzen
   wisselde het beeld, klikken schoof naar een hoofdstuk. Allebei weggehaald op
   verzoek; het zijn nu twee stilstaande afdrukken. De opmaak die erbij hoorde -
   `.wissel*`, `.schermfilm*` en de veertien `#bronfilm`-standen, samen 409
   regels - is mee weg en staat in de geschiedenis als hij ooit terug moet.
   De opnames worden gemaakt met `schermbeelden.mjs` naast build.py. */


/* Twee uitsnedes naast elkaar. De breekpunt hangt aan de kolom en niet aan het
   scherm, net als bij de tabellen: in een .split__body is 640px al krap. */
.schermbeeld--paar { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
@media (max-width: 767px) { .schermbeeld--paar { grid-template-columns: 1fr; gap: 32px; } }

/* Drie naast elkaar. Bedoeld voor de drie dochterstartpagina's van Kaldevo:
   naast elkaar is het de hele vergelijking in één oogopslag — zelfde opbouw,
   zelfde beeldmerk, drie eigen kleuren. Onder elkaar valt dat weg, want dan
   zie je ze niet meer tegelijk.

   De drie opnamen hebben exact dezelfde maat (800x642), dus er is geen
   `align-items` nodig om de onderranden te laten uitlijnen. Krijgt deze rij ooit
   beelden van ongelijke hoogte, dan gaat die uitlijning stuk: snijd ze dan op
   één maat in plaats van hier een aspect-ratio op te leggen, anders vervormt de
   opname.

   Twee kolommen tussenin zou één beeld alleen op een tweede regel zetten, en
   dat leest als een uitzondering. Van drie meteen naar één. */
.schermbeeld--drie { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
@media (max-width: 767px) { .schermbeeld--drie { grid-template-columns: 1fr; gap: 32px; } }

/* Het lege kader staat er tot de bestanden er zijn. Streepjesrand, zodat het
   nooit voor een afgeleverd beeld kan worden aangezien. Vervalt zodra <img>
   erin staat. */
.schermbeeld__leeg {
  display: flex; align-items: center; justify-content: center;
  min-height: 220px; padding: 24px;
  border: 1px dashed var(--line); border-radius: 4px;
  background-color: var(--surface);
  color: var(--text-dim); font-size: var(--maat-min1); line-height: 1.6; text-align: center;
}

/* =========================================================
   Kopieerknop achter een kleurwaarde op De Bron.
   Progressive enhancement: standaard verborgen. main.js zet
   .heeft-clipboard op <html> zodra navigator.clipboard bestaat; zonder
   JavaScript of klembordondersteuning blijft alleen de hexwaarde als tekst
   over, precies zoals hij daarvoor stond.
   ========================================================= */
.kopieer { display: none; }
.heeft-clipboard .kopieer {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin-left: 8px; padding: 0;
  vertical-align: -5px;
  background: none; border: 0; border-radius: 4px; cursor: pointer;
  color: var(--text-dim); transition: color 160ms;
}
.kopieer svg { width: 14px; height: 14px; }
.kopieer:hover { color: var(--white); }
.kopieer:focus-visible { outline: 2px solid rgba(255,255,255,.75); outline-offset: 2px; }
/* De klaar-vink is normaal verborgen; bij .is-gekopieerd wisselen de twee om. */
.kopieer .ic-klaar { display: none; }
.kopieer.is-gekopieerd { color: var(--white); }
.kopieer.is-gekopieerd .ic-kopieer { display: none; }
.kopieer.is-gekopieerd .ic-klaar { display: inline; }

/* ---------- Raakvlakken ----------
   WCAG 2.5.8 vraagt 24 bij 24 voor iets waar je op tikt. Gemeten op een
   telefoon: het wordmerk in de balk is 46 bij 12, dat in de voettekst 65 bij
   17, en het vinkje in de formulieren 20 bij 20. Alle drie te klein.

   Voor de twee logo's een onzichtbaar vlak eromheen in plaats van padding:
   padding zou de balk en de voettekst opnieuw uitlijnen, en dan verschuift er
   iets wat goed stond. Zo verandert er niets aan de opmaak en wordt alleen het
   gebied groter waar een vinger raak is. */
.wordmark, .footer__logo { position: relative; }
.wordmark::after,
.footer__logo::after {
  content: "";
  position: absolute;
  inset: -8px -4px;
}
/* Het vinkje mag wel gewoon groter: het staat op zijn eigen regel voor de
   tekst en duwt niets uit de rooilijn. */
.consent input[type="checkbox"] {
  width: 24px;
  height: 24px;
  flex: none;
}
