/* ============================================================
   The Synths — global digital human studio
   Design tokens uit design_handoff_the_synths_onepager 2/README.md (v7)

   Accentsysteem: --acc (vlakken), --acc2 (signalen), --acc-ink /
   --acc2-ink (tekst óp accentvlakken, YIQ-drempel 160). Waarden
   worden door script.js op :root gezet; hieronder de combi-default.
   ============================================================ */

:root {
  --paper: #FFFFFF; /* echt wit (was het warme parelwit #F8F8F8) */
  /* Eén knop voor de sterkte van het signaal: scanlines en tv-ruis in de
     opening, op de reel-rij en in het slotblok met de CTA. 1 is de oude
     sterkte, 0 zet het uit. Op 16 september 2026 op 0.8 gezet: rustiger dan
     voorheen, maar de textuur blijft het merkmotief. Boven en onder zijn
     bewust identiek — zelfde sterkte, zelfde trilritme. */
  --ruis: 0.8;
  /* Het slotblok met de CTA staat over zijn hele hoogte even hard, terwijl het
     signaal in de opening naar onderen uitdooft. Even sterk instellen gaf
     daardoor een zichtbaar luidruchtiger blok (gemeten: helderheid 14,5 en
     korrel 7,9 tegenover 10,4 en 4,9 bovenaan). Deze knop brengt de CTA terug
     naar het gemiddelde van de opening. */
  --ruis-cta: 0.5;
  /* Inkt staat voluit zwart: titels én lopende tekst. Op 16 september 2026 op
     verzoek van Maarten van #222222 hierheen. */
  --ink: #000000;
  /* De uitzonderingen op dat zwart, allemaal ondersteunende tekst die naast of
     onder iets anders staat: de zijtekst naast een titel, de regel onder een
     titel, de body in een blok, en de footer. Die houden de oude, zachtere
     tint. In donkere secties beweegt hij mee met de lichte inkt. */
  --ink-zacht: #222222;
  --ink-rgb: 34, 34, 34; /* triplet voor alle inkt-tinten; dark zet hier 242, 241, 238 */
  /* cyaan is de primaire kleur (vlakken, accenten, het strijklicht in
     het logo); roze is de tweede stem. Elke kleur draagt zijn eigen
     contrastinkt: op cyaan leest zwarte tekst, op roze witte. */
  --acc: #64D0EB;
  --acc2: #DA5597;
  /* de contrastinkt op cyaan: ook voluit zwart, zodat een titel op een
     accentvlak net zo hard staat als op wit (16-09-2026) */
  --acc-ink: #000000;
  --acc2-ink: #FBFBFA;
  /* de primaire kleur voor gevulde vlakken: vlak, geen verloop. Blijft als
     eigen token bestaan zodat alle gevulde vlakken op één plek te sturen zijn */
  --acc-grad: var(--acc);
  --panel-bg: #FFFFFF; /* vlakken mee naar echt wit */
  --film-bg: #000000;
  --film-video-bg: #161614;
  --img-fallback: #EBEBEB;
  --vlak-placeholder: #F5F5F5; /* neutraal lichtgrijs op het witte papier */
  /* ---- inkt-ladder: vier treden, één rol per trede ----
     --ink       (100%)  koppen, namen — wat je móét lezen
     --ink-75            lopende tekst
     --ink-45            mono-labels, eyebrows, meta
     --hairline  (10/12) lijnen en randen
     De tussentreden 65/60/55/35 blijven bestaan voor de enkele plek die
     ze echt nodig heeft (placeholders, gedimde staten), maar wie twijfelt
     pakt 75 of 45. Donkere blokken zetten deze tokens lokaal om naar
     lichte waarden (zie "inkt op donker"), zodat elk component gewoon
     var(--ink-75) kan schrijven en de juiste kleur er per context uitrolt. */
  --hairline: rgba(var(--ink-rgb), 0.10);
  --hairline-row: rgba(var(--ink-rgb), 0.12);
  --ink-75: rgba(var(--ink-rgb), 0.75);
  --ink-65: rgba(var(--ink-rgb), 0.65);
  --ink-60: rgba(var(--ink-rgb), 0.6);
  --ink-55: rgba(var(--ink-rgb), 0.55);
  --ink-45: rgba(var(--ink-rgb), 0.45);
  --ink-35: rgba(var(--ink-rgb), 0.35);
  --paper-75: rgba(251, 251, 250, 0.75);
  --paper-60: rgba(251, 251, 250, 0.6);
  --font-display: 'Inter Tight', 'Helvetica Neue', Arial, sans-serif;
  --font-body: 'Inter Tight', 'Helvetica Neue', Arial, sans-serif;
  /* eyebrow/systeem-labels in IBM Plex Mono (test) */
  --font-mono: 'IBM Plex Mono', ui-monospace, monospace;
  /* zijmarge van álle niet-full-width contentblokken: exact de 12px-voeg
     van de roster-wand en de kaartrasters — één maat, op elk schermformaat */
  --mx: 12px;
  /* de tekstmarge: alles wat puur tekst is (sectiekoppen, zijteksten,
     hero, topline, rollenlijst, cta, footer) staat bewust ruimer dan de
     contentblokken met beeld/vlakken (die op --mx staan) */
  --mx-kop: clamp(16px, 3vw, 48px);

  --sect: clamp(180px, 26vh, 320px); /* sectie-marge: één consistent, ruim ritme (DEPT-achtig: secties zweven vrij) */
  --band-lucht: clamp(160px, 22vh, 280px); /* lege ruimte bínnen de zwarte banden, boven en onder de content */
}

/* mobiel: strakker en overal exact gelijk sectieritme (geen vh-variatie) */
@media (max-width: 700px) {
  :root {
    --sect: 150px;
    --band-lucht: 130px;
  }
}

/* ============ donkere variant: één class-switch op <html> ============
   Ongewijzigd blijven: accentkleuren + YIQ-berekening, foto-captions
   (wit op gradient), play-cirkels, de witte CTA-knop, film-overlay en
   het zwevende menu (waren al donker). */
html.thema-donker {
  --paper: #000000;
  --ink: #EDECE9;
  --ink-zacht: var(--ink);
  --ink-rgb: 242, 241, 238;
  --ink-75: rgba(242, 241, 238, 0.75);
  --ink-65: rgba(242, 241, 238, 0.65);
  --ink-60: rgba(242, 241, 238, 0.6);
  --ink-55: rgba(242, 241, 238, 0.55);
  --ink-45: rgba(242, 241, 238, 0.45);
  --ink-35: rgba(242, 241, 238, 0.35);
  --panel-bg: #1A1A18;
  --img-fallback: #232321;
  --vlak-placeholder: #1D1D1B;
}

/* ============ thema "zwart / wit": donkere opening tot onder de video ============
   Lift mee op thema-blokken (de rest van de pagina is identiek aan
   wit / zwart); alleen de opening — topline, lockup, one-liner en de
   reel — staat op zwart. JS meet de onderkant van de hero-reel en zet
   die als --zwartwit-h op :root. */
html.thema-zwartwit body::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--zwartwit-h, 175vh); /* ruime terugval tot JS gemeten heeft */
  background: #000000; /* zelfde opgetilde zwart als het donkere thema: warmer, en de ruis-textuur blijft leesbaar */
  z-index: -1;
  pointer-events: none;
}

/* de content in de donkere opening praat in lichte inkt; alles wat op
   var(--ink)/--ink-rgb leunt (wordmark, subline, one-liner, tuner,
   zijtekst, scanlines) keert vanzelf mee om */
html.thema-zwartwit .topline,
html.thema-zwartwit .hero__lockup,
html.thema-zwartwit .herofx,
html.thema-zwartwit .hero__scene,
html.thema-zwartwit .hero__zijtekst,
html.thema-zwartwit .hero__reelwrap {
  --ink: #EDECE9;
  --ink-zacht: var(--ink);
  --ink-rgb: 242, 241, 238;
  --ink-75: rgba(242, 241, 238, 0.75);
  --ink-65: rgba(242, 241, 238, 0.65);
  --ink-60: rgba(242, 241, 238, 0.6);
  --ink-55: rgba(242, 241, 238, 0.55);
  --ink-45: rgba(242, 241, 238, 0.45);
  --ink-35: rgba(242, 241, 238, 0.35);
  color: var(--ink);
}

/* eigen ruislaag binnen de band, achter de content */
html.thema-blokken .psych::before {
  content: '';
  position: absolute;
  inset: -40px;
  z-index: -1;
  background-image: url('noise.png');
  /* iets sterker dan elders (0.09): over het diepere videozwart (#000)
     oogt dezelfde ruis vlakker */
  opacity: 0.12;
  pointer-events: none;
  animation: tvStatic 0.4s steps(1) infinite;
}

/* mobiel: geen video (autoplay is daar onbetrouwbaar, o.a. bij spaarstand)
   maar een still uit dezelfde loop, rechtsboven naast de titel */
.psych__still { display: none; }

@media (max-width: 899.98px) {
  /* de still hangt aan de bovenkant van het grid, dus de onderkant van het
     frame valt precies samen met de eerste scheidslijn boven de kaarten */
  html.thema-blokken .psych__grid { position: relative; }

  /* de titel houdt ruimte vrij voor de still, maar mag doorlopen tot onder
     de uitgefadete linkerrand ervan; de kaarten (en dus de scheidslijnen)
     lopen weer over de volle breedte */
  html.thema-blokken .section-title--psych {
    padding-right: 30vw;
    max-width: calc(16ch + 30vw); /* de 16ch geldt voor de tekst, niet voor de vrije ruimte */
  }
}

@media (min-width: 900px) {

  /* de ruis blijft op het zwart maar fadet uit over het personage,
     zodat het gezicht levensecht blijft */
  html.thema-blokken .psych::before {
    -webkit-mask-image: linear-gradient(90deg, #000 62%, transparent 86%);
    mask-image: linear-gradient(90deg, #000 62%, transparent 86%);
  }
}

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* de pagina zelf toont geen scrollbar: het canvas loopt tot de rand van
     het venster (scrollen blijft werken; er is ook geen layout-shift meer
     wanneer een overlay de body-scroll lockt, dus geen gutter nodig).
     scrollbar-width erft niet door: panelen houden hun eigen scrollbar. */
  scrollbar-width: none;
  /* scrollbar in de accentkleur (erft wél door naar de panelen) */
  scrollbar-color: var(--acc) transparent;
}

html::-webkit-scrollbar { display: none; } /* Safari: pagina-scrollbar weg */

/* binnen-scrollers (panelen e.d.): accentkleur — WebKit/Safari */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb {
  background: var(--acc);
  border-radius: 0;
}
::-webkit-scrollbar-track { background: transparent; }

body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  /* de rustige leesfont net iets minder standaard: een haartje meer tracking
     (koppen/labels hebben hun eigen letter-spacing en overrulen dit) */
  letter-spacing: 0.012em;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

body.panel-open { overflow: hidden; }

/* geen browser-terugnavigatie bij een horizontale veeg: de site houdt zijn
   eigen geschiedenis met replaceState, dus "terug" zou de bezoeker meteen
   de site uit sturen — en het gebaar gaf een schuif naar rechts midden in
   een case-overgang. */
html { overscroll-behavior-x: none; }

img { max-width: 100%; }

/* ============ animaties ============ */

@keyframes panelIn {
  from { transform: translateY(4%); opacity: 0; }
  to { transform: none; opacity: 1; }
}

@keyframes backdropIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* scroll-choreografie: content komt aan terwijl je scrolt. JS zet .sin op
   elementen die nog onder de vouw staan en .is-in zodra ze in beeld komen
   (met een kleine stagger binnen een groep). Zonder JS of met
   prefers-reduced-motion gebeurt er niets: dan staat alles er gewoon. */
.sin {
  opacity: 0;
  transform: scale(0.92);
}

.sin.is-in {
  opacity: 1;
  transform: none;
  /* eerst iets kleiner, dan rustig naar volle grootte groeien */
  transition:
    opacity 0.7s cubic-bezier(0.32, 0.72, 0.28, 1),
    transform 0.7s cubic-bezier(0.32, 0.72, 0.28, 1);
}

/* titels per woord: elk woord komt met zijn eigen vertraging (inline
   transition-delay uit script.js) omhoog zodra de titel in beeld schuift */
.sin-w .tw {
  display: inline-block;
  opacity: 0;
  /* 0.35em schaalt mee met de korpsgrootte: op een kop van 108px legden de
     woorden 38px af tegen 18px bij de sectietitels, en dat las als schuiven
     in plaats van zetten. De bovengrens houdt elke titel op dezelfde
     beweging; onder die grens (mobiel) blijft de em-verhouding staan. */
  transform: translateY(min(0.35em, 18px));
  transition:
    opacity 0.42s cubic-bezier(0.32, 0.72, 0.28, 1),
    transform 0.42s cubic-bezier(0.32, 0.72, 0.28, 1);
}

.sin-w.is-in .tw {
  opacity: 1;
  transform: none;
}

/* de wordmark zakt één keer op zijn plek bij het openen van de pagina;
   daarna beweegt hij nooit meer. De subline typt er meteen achteraan. */
@keyframes wordmarkIn {
  from { opacity: 0; transform: translateY(30px); }
}

@media (prefers-reduced-motion: reduce) {
  .hero__wordmark { animation: none; }
}

@keyframes caretBlink {
  0%, 55% { opacity: 1; }
  60%, 100% { opacity: 0; }
}

@keyframes tvStatic {
  0% { transform: translate(0, 0); }
  25% { transform: translate(-14px, 9px); }
  50% { transform: translate(11px, -13px); }
  75% { transform: translate(-7px, -5px); }
  100% { transform: translate(0, 0); }
}

/* entree-glitch: direct na het binnenzakken glitcht de wordmark een paar
   keer kort (twee bursts), daarna neemt de rustige 40s-cyclus het over */
/* de echo's zijn drop-shadows (geen text-shadow): die schaduwen de
   gerenderde letters en blijven dus netjes áchter de gradient-vulling
   van de wordmark, in plaats van er doorheen te schijnen */
@keyframes logoGlitchIntro {
  0%, 44%, 58%, 72%, 86%, 100% { transform: none; filter: none; opacity: 1; }
  46% { transform: translate(-2px, 1px) skewX(-1.5deg); filter: drop-shadow(2px 0 rgba(34, 68, 221, 0.6)) drop-shadow(-2px 0 rgba(232, 85, 45, 0.45)); opacity: 0.97; }
  50% { transform: translate(2px, -1px); filter: drop-shadow(-2px 0 rgba(34, 68, 221, 0.6)) drop-shadow(2px 0 rgba(232, 85, 45, 0.45)); }
  54% { transform: translate(-1px, 0) skewX(1deg); filter: drop-shadow(1px 0 rgba(34, 68, 221, 0.6)); opacity: 0.98; }
  76% { transform: translate(1px, 0) skewX(1deg); filter: drop-shadow(-2px 0 rgba(34, 68, 221, 0.6)) drop-shadow(1px 0 rgba(232, 85, 45, 0.45)); opacity: 0.98; }
  80% { transform: translate(-1px, 1px); filter: drop-shadow(2px 0 rgba(34, 68, 221, 0.6)); }
  83% { transform: translate(1px, 0); filter: drop-shadow(-1px 0 rgba(232, 85, 45, 0.45)); }
}

@keyframes logoGlitch {
  0%, 95.2%, 98%, 100% { transform: none; filter: none; opacity: 1; }
  95.4% { transform: translate(-2px, 1px) skewX(-1.5deg); filter: drop-shadow(2px 0 rgba(34, 68, 221, 0.6)) drop-shadow(-2px 0 rgba(232, 85, 45, 0.45)); opacity: 0.97; }
  95.8% { transform: translate(2px, -1px); filter: drop-shadow(-2px 0 rgba(34, 68, 221, 0.6)) drop-shadow(2px 0 rgba(232, 85, 45, 0.45)); }
  96.2% { transform: translate(-1px, 0) skewX(1deg); filter: drop-shadow(1px 0 rgba(34, 68, 221, 0.6)); opacity: 0.98; }
  96.6% { transform: translate(1px, 0); filter: drop-shadow(-1px 0 rgba(232, 85, 45, 0.45)); }
  97.2% { transform: none; filter: drop-shadow(1px 0 rgba(34, 68, 221, 0.6)); }
}

/* ============ sfeer-lagen ============ */

.noise {
  position: fixed;
  inset: -40px;
  pointer-events: none;
  z-index: 0;
  opacity: 0.08;
  background-image: url('noise.png');
  animation: tvStatic 0.4s steps(1) infinite;
}

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

/* ============ kleurkiezer (tijdelijk, voor review) ============ */

/* kleurenpaneel (review-instrument): boven gecentreerd, in/uitklapbaar,
   rechthoek met rechte hoeken */

/* ============ inkt op donker ============
   Permanent donkere blokken (het slotblok met CTA + footer, de studio-
   viewer, en in het blokken-thema de banden van features en privacy)
   zetten de inkt-ladder lokaal om naar lichte waarden. Daardoor kan élk
   component gewoon var(--ink-75) / var(--ink-45) / var(--hairline)
   schrijven en rolt de juiste kleur er per context uit — zelfde
   mechaniek als de panelen verderop. */
.slotblok,
.sviewer__venster,
html.thema-blokken .features,
html.thema-blokken .privacy {
  --ink: #FBFBFA;
  --ink-zacht: var(--ink);
  --ink-rgb: 251, 251, 250;
  --ink-75: rgba(251, 251, 250, 0.75);
  --ink-65: rgba(251, 251, 250, 0.65);
  --ink-60: rgba(251, 251, 250, 0.6);
  --ink-55: rgba(251, 251, 250, 0.55);
  --ink-45: rgba(251, 251, 250, 0.45);
  --ink-35: rgba(251, 251, 250, 0.35);
  --hairline: rgba(251, 251, 250, 0.16);
  --hairline-row: rgba(251, 251, 250, 0.16);
}

/* ============ gedeelde patronen ============ */

.path-label {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--acc); /* eyebrows in de primaire/accentkleur */
}

.path-label--head { margin-bottom: 32px; }

/* de afspraak spreekt overal de tweede merkkleur — knop, kaart en dus
   ook de kop van het paneel */
.path-label--acc2 { color: var(--acc2); }

/* typcursor van de pad-labels: knippert in de accentkleur en
   verdwijnt zodra de tekst volledig is uitgetypt */
.typ-cursor {
  display: inline-block;
  width: 8px;
  height: 11px;
  margin-left: 3px;
  background: var(--acc);
  animation: caretBlink 1.1s steps(1) infinite;
}

.section-title {
  /* ruim gat tussen kop en content: de kop krijgt zijn eigen moment */
  margin: 0 0 clamp(64px, 9vh, 110px);
  /* de stijl van de hero-oneliner ("Digital humans zijn…"), een
     maatje groter: alle koppen onder het roster spreken dezelfde taal */
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.015em;
  font-size: max(31px, 3.6vw);
  line-height: 1.12;
  max-width: 24ch;
  text-wrap: balance;
  color: var(--ink);
}

/* sectiekop-duo: grote kop links, kleine rechts uitgelijnde regel rechts
   — zelfde editorial-paar als de roster-intro */
.sectiekop-duo {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(28px, 4vw, 72px);
  margin-bottom: clamp(64px, 9vh, 110px);
}

/* het eigenschappenblok lijnt bovenlangs uit: de kop begint direct
   onder de eyebrow, de zijtekst zakt er met een eigen marge onder */
/* de kop hangt bovenaan; de zijtekst zakt met zijn eigen bovenmarge naar
   beneden. Met flex-end trok de lage zijtekst de titel mee omlaag en viel
   er 83px tussen de eyebrow en de kop, tegen 32 elders */
.features .sectiekop-duo,
.process .sectiekop-duo { align-items: flex-start; }

.sectiekop-duo .section-title { margin-bottom: 0; }

@media (max-width: 899.98px) {
  /* smal: onder elkaar, met een krappere voeg — de horizontale gap
     (tot 72px) is als verticale ruimte veel te veel */
  .sectiekop-duo {
    flex-direction: column;
    align-items: flex-start;
    gap: clamp(14px, 2.4vh, 26px);
  }
}

/* toepassingen: kop én intro staan links in het duo, zodat de
   one-liner rechts onderlangs met de alinea uitlijnt in plaats van
   met de titel. De sectiemarge verhuist mee naar het duo. */
.sectiekop-duo--cases { margin-bottom: clamp(48px, 7vh, 84px); }

/* compositie-ritme: de toepassingen-sectie centreert zijn kop, zoals
   het "Wij maken digital humans"-statement in de hero */
.path-label--midden {
  text-align: center;
  margin-bottom: 14px; /* titel dicht op de eyebrow: één compact kop-blok */
}

.section-title--process {
  margin-bottom: clamp(56px, 8vh, 96px);
  /* de regelval ligt vast in de HTML (br): altijd precies twee regels */
  max-width: none;
}

.section-title em {
  font-style: normal;
  color: inherit; /* koppen kennen geen grijstinten meer */
}

/* de kop-elementen springen binnen hun sectie (die op --mx staat) in
   tot de ruimere tekstmarge; de contentblokken eronder blijven op --mx.
   De sectiekop-duo neemt zijn rechts uitgelijnde zijtekst daarin mee. */
.path-label--head,
.sectiekop-duo,
.section-title--privacy {
  /* de proceskop staat bewust niet in deze lijst: die hangt in een
     sectiekop-duo, die de kopmarge zelf al meeneemt */
  margin-inline: calc(var(--mx-kop) - var(--mx));
}

/* ============ topregel ============ */

.topline {
  /* boven de hero-wordmark: op brede schermen hangt de titel over deze
     regel heen en blokkeerde hij de log-in-link */
  position: relative;
  z-index: 2;
  /* bewuste uitzondering op de tekstmarge: de twee systeemlinks
     (thesynths.studio / enter the vault) staan strak in de hoeken */
  padding: 24px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.topline__item {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  /* zelfde trede als de links in de footer: tekst, geen kop */
  color: var(--ink-75);
}

/* ============ in-tekst links ============
   Vaste onderstreping: bij hover wipet de streep naar rechts weg, in
   dezelfde beweging als waarmee hij bij het loslaten weer van links
   binnenkomt. Herbruikbaar op elke tekstuele link. */
.tekstlink {
  color: inherit;
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-size: 100% 1px;
  background-position: 0 100%;
  padding-bottom: 2px;
  transition: background-size 0.35s cubic-bezier(0.22, 0.61, 0.21, 1);
}

.tekstlink:hover {
  background-size: 0% 1px;
  background-position: 100% 100%; /* op volle breedte is de anker-wissel onzichtbaar: de lijn wipet rechts uit */
}

/* ============ hero ============ */

.hero {
  /* geen eigen top-padding: de topline heeft boven en onder dezelfde 24px,
     daarna volgt de titel direct. Tekstmarge: de hero is puur tekst */
  padding: 0 var(--mx-kop);
  position: relative;
}

/* ============ scroll-hint ============
   Een ronde badge in dezelfde taal als de "open in studio"-cursor:
   dunne witte lijn, mono-kapitalen, met een pijl-indicator eronder.
   Verschijnt pas na 10 seconden stilte op het beginscherm. */
.scrollhint {
  position: fixed;
  left: 50%;
  bottom: 42px;
  transform: translate(-50%, 12px);
  width: 96px;
  height: 96px;
  border-radius: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid #FBFBFA;
  color: #FBFBFA;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1;
  opacity: 0;
  pointer-events: none;
  z-index: 4;
  transition: opacity 0.9s ease, transform 0.9s cubic-bezier(0.22, 0.61, 0.21, 1);
}

.scrollhint.is-zichtbaar { opacity: 1; transform: translate(-50%, 0); }

/* de indicator: een pijlpunt die rustig zakt en terugkomt */
.scrollhint__pijl {
  width: 9px;
  height: 9px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  animation: hintZak 1.8s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

@keyframes hintZak {
  0%, 100% { transform: rotate(45deg) translate(0, 0); opacity: 0.5; }
  50% { transform: rotate(45deg) translate(3px, 3px); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .scrollhint__pijl { animation: none; transform: rotate(45deg); opacity: 1; }
}

.hero__lockup {
  width: 100%; /* wordmark en subregel spannen van marge tot marge; JS schaalt het font passend */
  position: relative;
  z-index: 2; /* boven de herofx-signaallaag: de letters blijven schoon */
  /* clean openen: merk + payoff vullen het hele eerste scherm, verticaal
     gecentreerd; al het andere (het statement) begint pas onder de vouw.
     De 72px compenseert de topline erboven. */
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(100vh - 72px);
  min-height: calc(100svh - 72px);
  /* de gemeten schermhoogte (script.js, --scherm-h) wint: op iOS Safari is
     100svh kleiner dan wat je echt ziet, en dan hing het merk te hoog */
  min-height: calc(var(--scherm-h, 100svh) - 72px);
  /* optisch centreren: het lockup hangt een paar procent bóven het
     wiskundige midden (de padding onderin duwt het geheel omhoog) */
  padding-bottom: clamp(48px, 9vh, 120px);
  padding-bottom: clamp(48px, calc(var(--scherm-h, 100svh) * 0.09), 120px);
}

/* ============ hero-statisch: vault-signaal over de opening ============
   Dezelfde signaal-taal als de overlays (scanlines + jitter-ruis), maar
   subtiel over het eerste scherm. JS laat --fx van 1 naar 0 lopen terwijl
   je scrolt, zodat het signaal langzaam oplost. */
.herofx {
  position: absolute;
  /* vol scherm: tot de schermranden links/rechts en tot bovenaan de pagina
     (de -80px duikt onder de topline door naar de bovenrand) */
  top: -80px;
  bottom: 0;
  left: calc(-1 * var(--mx-kop));
  right: calc(-1 * var(--mx-kop));
  z-index: 0; /* ónder het merk: het signaal leeft achter de titel */
  overflow: hidden; /* de jitter-ruis (inset -60px) mag geen scroll geven */
  pointer-events: none;
  opacity: var(--fx, 1);
  /* geen harde onderrand: het signaal vloeit onderaan héél geleidelijk
     uit — een lange fade met tussenstops (zachte ease) zodat nergens
     een overgang aanwijsbaar is */
  -webkit-mask-image: linear-gradient(to bottom,
    #000 62%, rgba(0, 0, 0, 0.6) 78%, rgba(0, 0, 0, 0.25) 90%, transparent 100%);
  mask-image: linear-gradient(to bottom,
    #000 62%, rgba(0, 0, 0, 0.6) 78%, rgba(0, 0, 0, 0.25) 90%, transparent 100%);
}

/* ============ zonneflare achter de wordmark ============
   Een warme zon/camera-flare ongeveer achter de "th" van Synths. JS zet
   --zon op het lockup (0 bovenaan → 1 voorbij de opening): de zon stijgt,
   groeit en wordt feller, en de gloed-laag erboven wast het beginscherm
   in licht zodat de opening in overbelichting verdwijnt. */
.hero__lockup {
  /* het brandpunt van de flare: ~achter de "th" van Synths; verticaal zo
     dat de lens-streep in rust precies tussen de wordmark en de subline
     "DIGITAL HUMAN STUDIO" valt */
  --flare-x: 73%;
  --flare-y: 44%;
  /* flare-palet afgeleid van de accentkleur: met het oranje swatch is
     dit de warme zon, met roze een synthwave-magenta gloed — het licht
     draait mee met het merk (browsers zonder color-mix houden de vaste
     oranje gradients hieronder) */
  --flare-c1: color-mix(in srgb, var(--acc) 24%, #FFEFD8);
  --flare-c2: color-mix(in srgb, var(--acc) 55%, #FFD9A2);
  --flare-c3: color-mix(in srgb, var(--acc) 76%, #FF9E4A);
  --flare-c4: color-mix(in srgb, var(--acc) 86%, #E86020);
}

.heroflare {
  position: absolute;
  left: var(--flare-x);
  top: var(--flare-y);
  /* groter maar zachter: de gloed is breder en de randen lopen veel
     geleidelijker uit — minder fel in de kern, langere staart */
  width: 52vmin;
  height: 52vmin;
  pointer-events: none;
  background: radial-gradient(circle,
    rgba(255, 234, 198, 0.68) 0%,
    rgba(255, 182, 88, 0.46) 16%,
    rgba(255, 136, 44, 0.22) 38%,
    rgba(238, 98, 28, 0.09) 58%,
    transparent 78%);
  /* in rust staat de kern (en dus de lens-streep) exact op het gemeten
     brandpunt tussen wordmark en subline. Bij het scrollen klimt de zon
     zelf maar minimaal: in het eerste derde van de scroll een klein
     stukje omhoog (9vh, via max() afgekapt), daarna beweegt hij gewoon
     met de pagina mee en doet alleen het licht nog het werk */
  transform: translate(-50%, -50%)
    translateY(max(calc(var(--zonstijg, 0) * -27vh), -9vh))
    scale(calc(0.62 + var(--zon, 0) * 1.25));
  opacity: calc(0.34 + var(--zon, 0) * 0.15);
}

/* anamorfische lens-streep door de kern: het camera-deel van de flare.
   Fadet vrijwel direct uit zodra er gescrold wordt (×14: bij ~7% van de
   eerste schermhoogte is hij weg) — de streep hoort bij het rustmoment */
.heroflare::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 200%;
  height: 2px;
  transform: translate(-50%, -50%);
  background: linear-gradient(90deg, transparent, rgba(255, 190, 110, 0.7), transparent);
  opacity: calc(1 - var(--zonstijg, 0) * 14);
}

/* overbelichting óver de letters, vanuit hetzelfde brandpunt; het
   centrum klimt mee met de zon en de sterkte groeit kwadratisch — pas
   in de tweede helft van de scroll slaat het licht echt door. De laag
   loopt ruim voorbij de onderkant van het lockup en vervaagt daar via
   het masker naar niets: nergens een zichtbare scheidingslijn met het
   blok eronder. */
.heroflare-gloed {
  position: absolute;
  z-index: 4; /* boven het vault-signaal (herofx, z3) */
  top: -80px;
  bottom: -34vh;
  left: calc(-1 * var(--mx-kop));
  right: calc(-1 * var(--mx-kop));
  pointer-events: none;
  background: radial-gradient(circle at var(--flare-x) calc(var(--flare-y) - var(--zonstijg, 0) * 8%),
    rgba(255, 238, 212, 0.75) 0%,
    rgba(255, 202, 122, 0.5) 26%,
    rgba(255, 158, 66, 0.26) 48%,
    rgba(244, 116, 38, 0.08) 68%,
    transparent 82%);
  opacity: calc(var(--zon, 0) * var(--zon, 0) * 0.17);
  /* het licht blijft netjes bóven de content na de opening: de fade
     begint al op ~1/3 van de laag en is volledig uitgedoofd ruim vóór
     de onderrand — een lange, onzichtbare overgang in plaats van een
     zichtbare lichtband op de blokgrens */
  -webkit-mask-image: linear-gradient(to bottom, #000 38%, transparent 76%);
  mask-image: linear-gradient(to bottom, #000 38%, transparent 76%);
}

/* accent-gekoppelde tinten: het licht draait mee met de gekozen
   merkkleur — met het oranje swatch is dit de warme zon van hiervoor,
   met roze een synthwave-magenta gloed. Browsers zonder color-mix
   houden gewoon de vaste oranje gradients hierboven. */
@supports (color: color-mix(in srgb, red 50%, blue)) {
  .heroflare {
    background: radial-gradient(circle,
      color-mix(in srgb, var(--flare-c1) 68%, transparent) 0%,
      color-mix(in srgb, var(--flare-c2) 46%, transparent) 16%,
      color-mix(in srgb, var(--flare-c3) 22%, transparent) 38%,
      color-mix(in srgb, var(--flare-c4) 9%, transparent) 58%,
      transparent 78%);
  }

  .heroflare::before {
    background: linear-gradient(90deg, transparent,
      color-mix(in srgb, var(--flare-c2) 70%, transparent), transparent);
  }

  .heroflare-gloed {
    background: radial-gradient(circle at var(--flare-x) calc(var(--flare-y) - var(--zonstijg, 0) * 8%),
      color-mix(in srgb, var(--flare-c1) 75%, transparent) 0%,
      color-mix(in srgb, var(--flare-c2) 50%, transparent) 26%,
      color-mix(in srgb, var(--flare-c3) 26%, transparent) 48%,
      color-mix(in srgb, var(--flare-c4) 8%, transparent) 68%,
      transparent 82%);
  }
}

/* reviewpaneel: de zon volledig uit */
html.geen-zon .heroflare,
html.geen-zon .heroflare-gloed { display: none; }

/* in de donkere openingen telt het licht op: echte tegenlicht-bloom */
html.thema-zwartwit .heroflare,
html.thema-donker .heroflare,
html.thema-zwartwit .heroflare-gloed,
html.thema-donker .heroflare-gloed {
  mix-blend-mode: screen;
}

.herofx::before {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(0deg, rgba(var(--ink-rgb), calc(0.05 * var(--ruis))) 0 2px, transparent 2px 5px);
}

.herofx::after {
  content: '';
  position: absolute;
  inset: -60px; /* jitter mag geen randen tonen */
  background-image: url('noise.png');
  opacity: calc(0.11 * var(--ruis));
  animation: vaultJitter 0.5s steps(2) infinite;
}

/* de ruis-schakelaar in het kleurenpaneel gaat alleen over de
   achtergrondruis van de pagina; dit signaal blijft gewoon staan */

@media (prefers-reduced-motion: reduce) {
  .herofx::after { animation: none; }
}

.hero__wordmark {
  /* de font-leading geeft optisch te veel lucht boven de kapitalen;
     trek de titel omhoog zodat hij direct onder de topline begint */
  margin: -0.08em 0 0;
  /* de wordmark hoort nu ook bij het Inter Tight-systeem, in het zwaarste
     gewicht zodat het als logo-lockup overeind blijft */
  font-family: var(--font-display);
  font-weight: 600; /* oude variant, maar minder dik dan 800 */
  letter-spacing: -0.04em;
  font-size: clamp(64px, 13.5vw, 250px);
  line-height: 0.96;
  white-space: nowrap;
  position: relative;
  /* alleen de entree: één keer rustig op zijn plek zakken */
  animation: wordmarkIn 0.9s cubic-bezier(0.32, 0.72, 0.28, 1) 0.05s both;
}

/* titelvarianten via het kleurenpaneel: met ® of kaal; de wordmark
   staat altijd in kleine letters (vaste merkstijl) */
/* tekst die er is voor schermlezers en zoekmachines, maar niet in beeld:
   de categorie in de h1 (de getypte subregel eronder is de zichtbare versie) */
.verborgen { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.hero__punt { display: none; }
html.titel-klein .hero__wordmark { text-transform: lowercase; }

/* ® hangt aan het einde van de tekst (niet aan de volle h1-breedte) */
.hero__wordmark-tekst {
  position: relative;
  display: inline-block;
  /* glans ín de letterforms: de romp is inkt en loopt schuin (licht
     gekanteld, als strijklicht) over in de primaire kleur — het verloop
     zit bewust in de zichtbare letterzone, niet onder de baseline */
  background-image: linear-gradient(163deg,
    var(--ink) 38%,
    color-mix(in srgb, var(--ink) 42%, var(--acc)) 92%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* de clip schildert alleen binnen de box en de krappe line-height
     (0.96) knipt anders de staart van de y af: ruimte geven en de
     layout met negatieve marge exact terugbetalen */
  padding: 0.1em 0.06em 0.18em;
  margin: -0.1em -0.06em -0.18em;
  /* bewuste kap-lijn: de staartletters worden op één strakke horizontale
     lijn gesneden — het signaal is groter dan zijn kader. --logo-snede
     is de draaiknop: groter = diepere snede (0 = geen snede). */
  --logo-snede: 0.22em;
  clip-path: inset(-0.3em -0.3em var(--logo-snede) -0.3em);
  transition: clip-path 0.14s linear; /* de kap valt als snelle slice */
  /* eigen compositor-laag: voorkomt de Chrome-bug waarbij de geclipte
     gradient-tekst na ver scrollen half/verkeerd geschilderd terugkomt */
  transform: translateZ(0);
  will-change: transform;
}

/* tijdens het typen van de subregel is de y nog heel: JS zet .is-heel
   bij de start en haalt hem weg zodra de loper-cursor onder de y-staart
   doorkomt — de typemachine "snijdt" de letter. Zonder JS blijft
   gewoon de gekapte eindstand staan. */
.hero__wordmark.is-heel .hero__wordmark-tekst {
  clip-path: inset(-0.3em -0.3em -0.3em -0.3em);
}

/* de ® staat absoluut buiten het tekstvak en zou met de geclipte
   gradient onzichtbaar worden: die krijgt gewoon zijn eigen inkt */
/* de ® draagt hetzelfde strijklicht als de letters ernaast: één logo.
   Eigen mini-verloop (niet meeliften op de ouder-clip): de ® hangt
   deels buiten de tekstbox, waar de ouder-gradient niet schildert */
.hero__wordmark-tekst .hero__reg {
  background-image: linear-gradient(163deg,
    color-mix(in srgb, var(--ink) 78%, var(--acc)) 0%,
    color-mix(in srgb, var(--ink) 42%, var(--acc)) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero__reg {
  position: absolute;
  left: 100%;
  top: 0.22em;
  margin-left: -0.2em;
  font-size: 0.3em;
  letter-spacing: 0;
}

.hero__subline {
  /* strak tegen de kap-lijn van de wordmark aan: wordmark, snede en
     subregel lezen zo als één logo-lockup */
  margin-top: clamp(0px, 0.15vw, 4px);
  /* de letters staan iets dichter op elkaar: een paar pixels smaller dan
     de wordmark (de zij-padding drukt de space-between-verdeling in) */
  padding: clamp(6px, 0.8vw, 14px) 7px;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-family: var(--font-mono);
  /* de subregel spant met de wordmark van marge tot marge, dus hij moet
     onbegrensd meeschalen: met een plafond van 32px liep de verhouding
     wordmark/subregel op een 34-inch scherm van 12 naar 23 uiteen */
  font-size: max(12px, 1.75vw);
  text-transform: uppercase;
  color: var(--ink); /* vol zwart, net als de wordmark */
}

.hero__gap { width: 0.5em; }

.hero__cursor {
  align-self: center;
  width: 0.5em;
  height: 1em;
  /* het staartje van het wordmark-verloop, doorlopend naar de volle
     accentkleur: de cursor is het eindpunt van het logo-strijklicht */
  background: linear-gradient(163deg,
    color-mix(in srgb, var(--ink) 42%, var(--acc)),
    var(--acc));
  animation: caretBlink 1.1s steps(1) infinite;
}

/* het statement zweeft gecentreerd tussen de wordmark en de video
   (DEPT-achtig). Geen entree: de keuze eronder moet er altijd staan */
.hero__statement {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: clamp(36px, 5vh, 56px);
  margin: clamp(170px, 26vh, 370px) 0 var(--statement-onder);
}

.hero__row {
  position: relative;
  z-index: 1;
  min-height: clamp(520px, 86vh, 960px);
  /* full-bleed: breekt uit de hero-marges tot de schermranden */
  margin-left: calc(-1 * var(--mx-kop));
  margin-right: calc(-1 * var(--mx-kop));
  overflow: hidden;
  /* DEPT-achtige reel: start klein en groeit al scrollend naar full-bleed.
     --reel komt van de wrapper (JS-scrub); zonder JS blijft hij daar 1 */
  transform: scale(calc(0.72 + 0.28 * var(--reel)));
  transform-origin: 50% 18%;
  transition: transform 0.25s cubic-bezier(0.22, 0.61, 0.21, 1);
}

/* de twee alinea's liggen netjes onderin de video, in twee kolommen;
   klikken gaat door de tekst heen naar de filmtegel */
.hero__intro {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  padding: clamp(24px, 3.5vw, 48px) var(--mx-kop);
  pointer-events: none;
}

/* de blokken schalen niet mee met de binnenkomende band: zolang de reel
   nog groeit (scrub-modus) wachten ze onzichtbaar, en pas op volle
   breedte (.is-vol, door JS gezet) faden ze langzaam omhoog. Zonder JS
   is er geen scrub en staan ze er gewoon. */
.hero__reelwrap.is-scrub .hero__intro {
  opacity: 0;
  transform: translateY(44px);
  transition: opacity 1.1s cubic-bezier(0.22, 0.61, 0.21, 1),
              transform 1.1s cubic-bezier(0.22, 0.61, 0.21, 1);
}

.hero__reelwrap.is-scrub.is-vol .hero__intro {
  opacity: 1;
  transform: none;
}

/* zolang ze onzichtbaar zijn, mogen ze ook geen kliks vangen */
.hero__reelwrap.is-scrub:not(.is-vol) .hero__blok {
  pointer-events: none;
}

/* de film is pas "open" op volle breedte: tot die tijd vangt de tegel
   geen kliks en dus ook geen hover — de play-knop (die op hover
   verschijnt) blijft daarmee vanzelf weg */
.hero__reelwrap.is-scrub:not(.is-vol) .filmtile {
  pointer-events: none;
}

/* twee statement-blokken: titel + tekst, samen onderuitgelijnd en naar
   de buitenranden geduwd (het dock zweeft in het midden) */
.hero__blokken {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(32px, 7vw, 140px);
}

.hero__blok {
  flex: 0 1 44ch;
  padding: clamp(20px, 2.2vw, 32px);
  /* het blok is zelf géén knop: alleen de in-tekst "Lees meer" is
     klikbaar. pointer-events blijft aan zodat kliks op het blok niet
     doorvallen naar de filmtegel eronder. */
  pointer-events: auto;
}

/* blok 1: primaire kleur, met de bijbehorende inktkleur */
.hero__blok--acc {
  background: var(--acc-grad);
  color: var(--acc-ink);
}

.hero__blok--acc .hero__blok-titel { color: var(--acc-ink); }
.hero__blok--acc .hero__body { color: var(--acc-ink); opacity: 0.88; }

/* twee alinea's in één blok: rustige tussenruimte */
.hero__blok .hero__body + .hero__body { margin-top: 12px; }

/* in-tekst link onderin een blok; klikbaar ondanks de doorlaatbare
   intro-laag. Zelfde stem als de topline-links: mono, 12px, kapitalen. */
.hero__blok-link {
  display: inline-block;
  margin-top: 16px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  pointer-events: auto;
}

/* zolang de reel nog groeit is het signaal niet "locked": de hele band
   (video én blokken) staat vaag en onder levende ruis — pas bij volle
   breedte wordt het beeld scherp. Alles scrubt mee op --reel (0..1). */
.hero__row {
  filter: blur(calc((1 - var(--reel, 1)) * 9px));
}

/* het signaal over de complete band, boven video en blokken: dezelfde
   twee lagen als de vault en de opening — scanlines + jitter-ruis */
.hero__row::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  /* duale lijnen: donker + een licht randje, zodat ze ook op de donkere
     video zichtbaar zijn (op licht papier doet vooral de donkere lijn het) */
  background: repeating-linear-gradient(0deg,
    rgba(10, 10, 9, calc(0.3 * var(--ruis))) 0 2px,
    rgba(251, 251, 250, calc(0.06 * var(--ruis))) 2px 3px,
    transparent 3px 5px);
  opacity: calc(1 - var(--reel, 1));
  pointer-events: none;
}

.hero__row::after {
  content: '';
  position: absolute;
  inset: -60px; /* jitter mag geen randen tonen */
  z-index: 3;
  background-image: url('noise.png');
  opacity: calc((1 - var(--reel, 1)) * 0.95 * var(--ruis));
  animation: vaultJitter 0.5s steps(2) infinite;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  /* geen reel-scrub: beeld direct scherp, signaal stil en weg */
  .hero__row { filter: none; }
  .hero__row::before { opacity: 0; }
  .hero__row::after { animation: none; opacity: 0; }
}

.hero__blok-titel {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: clamp(19px, 1.9vw, 26px);
  line-height: 1.05;
}

/* de twee routes onder het statement: geen knoppen maar een typografisch
   duo met mono-indexen, zoals de genummerde feature-rijen verderop */
/* de keuze onder het statement: 'Voor' als stille aanloop, de twee
   paden eronder. Eén blok, zodat de grote gap van het statement er
   maar één keer tussen zit */
.hero__keuze {
  /* het blok spant de volle breedte van het statement, zodat de twee
     kolommen eronder echt met de proposities samenvallen */
  align-self: stretch;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* 'Voor' staat boven de knoppen, op de pagina-as, met wat lucht eronder:
   een eigen rij over beide kolommen. Dezelfde letter als de lead, vet,
   volle inkt */
.hero__voor {
  grid-column: 1 / -1;
  justify-self: center;
  margin: 0 0 clamp(6px, 1.2vh, 14px);
  font-family: var(--font-display);
  font-size: clamp(26px, 2.9vw, 44px);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--ink);
}

/* de afstand van het statement tot de proposities; de lijn onder de
   knoppen loopt precies dat stuk. De marges raken elkaar (geen rand of
   padding ertussen), dus ze vallen samen: de grootste telt */
:root {
  --statement-onder: clamp(80px, 12vh, 160px);
  --voorwie-boven: clamp(72px, 11vh, 130px);
}

/* twee kolommen die samenvallen met de twee proposities eronder: zelfde
   zijmarge (12px) en zelfde voeg. De hero heeft een eigen tekstmarge,
   daar stappen de routes overheen */
.hero__routes {
  position: relative; /* anker voor 'Voor' */
  align-self: stretch;
  margin-inline: calc(12px - var(--mx-kop));
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

/* de knop: merkkleur als vlak, de inkt die daarbij hoort, harde hoeken.
   --knop draagt de kleur, ook naar de lijn eronder */
.hero__route {
  --knop: var(--acc);
  --knop-ink: var(--acc-ink);
  position: relative;
  justify-self: center;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  height: 52px;
  margin: 0;
  padding: 0 24px;
  border: 0;
  border-radius: 0;
  background: var(--knop);
  color: var(--knop-ink);
  cursor: pointer;
  text-decoration: none;
}
.hero__route--pers {
  --knop: var(--acc2);
  --knop-ink: var(--acc2-ink);
}
.hero__route:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* de lijn: recht omlaag, in de kleur van de knop, tot de bovenrand van
   de propositie. Buiten de knop getekend, dus niet meeschalen bij hover */
.hero__route::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  width: 2px;
  height: max(var(--statement-onder), var(--voorwie-boven));
  margin-left: -1px;
  background: var(--knop);
  pointer-events: none;
}

/* het cijfer staat nu óp het vlak: dezelfde inkt als het woord, iets
   teruggezet. De accentkleur zou op het eigen vlak wegvallen */
.hero__route-index {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: currentColor;
  opacity: 0.72;
}
.hero__route-index--twee { color: currentColor; }

.hero__route-label {
  /* de routes zijn een uitnodiging, geen spec-label: display-font, ruim leesbaar */
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

/* filmknop in de primaire kleur, zoals de andere accentknoppen */
.hero__lees--film {
  background: var(--acc-grad);
  color: var(--acc-ink);
  border-color: transparent;
}

/* ============ one-liner met wisselwoord ============
   Gewone, luchtige sectie (alleen de lockup bovenaan mag het volle scherm
   vullen). Het wisselwoord stapt op scrollpositie door zijn opties, met
   een korte signaal-glitch bij elke wissel. */

.hero__oneliner {
  /* editorial: links uitgelijnd, ruim ónder de payoff van het beginscherm
     (mag deels onder de vouw uitsteken) — de entree is een scrub: de
     regel rijst en wordt scherp als direct gevolg van de scroll */
  position: relative;
  z-index: 2;
  margin: 0;
  text-align: left;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.015em;
  /* geen bovengrens: schaalt op grote schermen gewoon met de viewport mee */
  font-size: max(28px, 3.2vw);
  line-height: 1.12;
  will-change: opacity, transform, filter;
}

/* het slotstatement van de opening: prominent en centraal op het
   podium, vlak voordat de reel arriveert */
.hero__zijtekst {
  position: relative;
  z-index: 2;
  margin: clamp(80px, 13vh, 180px) 0 clamp(110px, 20vh, 280px) auto;
  max-width: 22ch;
  text-align: right;
  text-wrap: balance;
  /* exact dezelfde letter als de one-liner links */
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.015em;
  font-size: max(28px, 3.2vw);
  line-height: 1.12;
  color: var(--ink);
  will-change: opacity, transform, filter;
}

@keyframes slotGlitch {
  0% { transform: translate(-4px, 1px) skewX(-2deg); text-shadow: 5px 0 color-mix(in srgb, var(--acc) 70%, transparent), -5px 0 color-mix(in srgb, var(--acc2) 55%, transparent); }
  35% { transform: translate(3px, -1px); text-shadow: -4px 0 color-mix(in srgb, var(--acc) 70%, transparent), 4px 0 color-mix(in srgb, var(--acc2) 55%, transparent); }
  65% { transform: translate(-1px, 0) skewX(1deg); text-shadow: 2px 0 color-mix(in srgb, var(--acc) 60%, transparent); }
  100% { transform: none; text-shadow: none; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__zijtekst.is-af { animation: none; }
}

@media (max-width: 900px) {
  .hero__zijtekst { font-size: max(24px, 6.2vw); }
}

/* stappen-indicator: alleen zichtbaar in scrub-modus */
.hero__wisselstappen { display: none; }

.hero__scene.is-scrub .hero__wisselstappen {
  display: flex;
  justify-content: flex-start; /* links, in lijn met de editorial tekst */
  flex-wrap: wrap; /* lange woorden (fr/de) mogen op smal scherm doorlopen */
  gap: 6px clamp(18px, 2vw, 32px);
  margin-top: clamp(16px, 2.4vh, 28px);
}

/* tuner: de drie wisselwoorden zelf als kleine mono-labels, in exact
   dezelfde stijl als de topline (thesynths.studio): 12px, 0.08em,
   uppercase, gewicht 500; het actieve woord licht op in de accentkleur */
.hero__wisselstappen i {
  font-family: var(--font-mono);
  font-style: normal;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  /* 55% is de laagste trede die op de donkere opening nog leesbaar is
     (5,4:1); 35% haalde maar 2,9:1 en verdween in het zwart */
  color: var(--ink-55);
  transition: color 0.3s ease;
}

.hero__wisselstappen i.is-actief { color: var(--acc); }

/* de reel + zwevende one-liner delen deze wrapper; JS zet er --reel op
   (0..1). Zonder JS blijft hij 1: beeld gewoon scherp en vol. */
.hero__reelwrap {
  position: relative;
  --reel: 1;
  /* het statement erboven levert de rust; de film volgt er direct op */
  margin-top: 0;
}

/* ============ laadbalk ============
   Een roze lijn bovenaan die vanaf de eerste scroll meegroeit en pas
   vol staat op het moment dat de film full-bleed in beeld is: het
   verhaal is dan geladen. */
.laadbalk {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: 55; /* onder het dock (60), boven de content */
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
}

.laadbalk.is-aan { opacity: 1; }

.laadbalk i {
  display: block;
  height: 100%;
  width: calc(var(--laad, 0) * 100%);
  background: var(--acc);
}

/* vol: de lijn blijft nog even staan en lost dan rustig op */
.laadbalk.is-vol { opacity: 0; transition: opacity 1s ease 0.5s; }

/* ============ onderregel bij de video ============
   Direct onder de film, op de witte pagina: het merk links, de
   herkomst rechts — in het mono-idioom van de topline. */
.hero__onderregel {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: clamp(16px, 2.2vh, 26px) 0 0;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-zacht);
}

@media (max-width: 700px) {
  /* smal: alleen de kern van beide regels, zodat ze naast elkaar passen */
  .hero__onderregel { font-size: 11px; letter-spacing: 0.06em; }
  .alleen-breed { display: none; }
}

/* ============ scene: boodschap + gezicht ============
   Geen vast scherm meer: een gewoon blok dat snel na de opening komt
   en bewust minder dan een viewport hoog is. Tekst links, gezicht
   rechts; het wisselwoord en het gezicht stappen mee met de scroll. */
.hero__scene {
  position: relative;
  margin-top: clamp(120px, 20vh, 280px);
  min-height: 42vh;
}

/* Mobiel: het eerste scherm blijft schoon (alleen het merk), maar daarna
   moet de tekst niet nog een half scherm lucht krijgen. De scene sluit
   direct aan op het lockup, houdt net genoeg hoogte voor de scrub van
   het wisselwoord, en het slotstatement volgt kort erna. De ruimte
   ónder het slotstatement naar de film blijft zoals hij is. */
@media (max-width: 700px) {
  .hero__scene {
    margin-top: 0;
    min-height: 24vh;
  }
  .hero__zijtekst {
    margin-top: clamp(56px, 11vh, 96px);
  }
}

/* de one-liner staat gewoon vast boven de video, ruim onder de vouw
   zodat hij niet in het beginscherm piept; het wisselwoord + de stappen
   scrubben wel gewoon mee op de scroll */

/* het wisselwoord krijgt via JS een vaste breedte (breedste woord van de
   actieve taal): de regel ervóór verspringt nooit bij een wissel */
.hero__wissel {
  display: inline-block; /* transform van de glitch mag de regel niet raken */
  text-align: left;
  color: var(--acc);
}

/* korte split bij elke woordwissel: geen vaste RGB-kleuren maar een
   dubbele echo in de primaire kleur, zodat de glitch altijd de gekozen
   accentkleur spreekt */
.hero__wissel.is-glitch {
  animation: wisselGlitch 0.3s steps(1) both;
}

@keyframes wisselGlitch {
  0% { transform: translate(-5px, 1px) skewX(-4deg); text-shadow: 5px 0 var(--acc), -5px 0 color-mix(in srgb, var(--acc) 55%, transparent); opacity: 0.9; }
  35% { transform: translate(4px, -1px); text-shadow: -5px 0 var(--acc), 5px 0 color-mix(in srgb, var(--acc) 55%, transparent); }
  65% { transform: translate(-2px, 0) skewX(3deg); text-shadow: 3px 0 var(--acc); opacity: 0.95; }
  100% { transform: none; text-shadow: none; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .hero__wissel.is-glitch { animation: none; }
}

.hero__lead {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  /* het openingsstatement is bewust het grootste element na de wordmark */
  font-size: clamp(44px, 7.5vw, 120px);
  line-height: 0.98;
  max-width: none;
  color: var(--ink);
}

.hero__body {
  margin: 0;
  max-width: 46ch;
  font-size: 16px;
  line-height: 1.75;
  color: var(--ink-65);
}

/* introfilm-tile (hero) */

.filmtile {
  position: absolute;
  inset: 0;
  z-index: 0; /* achter de scrim (1) en de copy (2) */
  display: block;
  padding: 0;
  border: none;
  width: 100%;
  height: 100%;
  background: var(--acc-grad);
  cursor: pointer;
  overflow: hidden;
  text-align: left;
  font: inherit;
}

/* Klein AI-merkje linksboven in de tegel: dezelfde melding als over de film
   zelf, want dit is beeld uit diezelfde film. Rustig en zonder doos-drukte,
   want hij staat hier permanent op de homepage. */
.filmtile__ai {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 2;
  padding: 4px 7px;
  background: rgba(0, 0, 0, 0.42);
  color: rgba(251, 251, 250, 0.78);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  line-height: 1.3;
  text-transform: uppercase;
  border-radius: 0;
  pointer-events: none;
}

@media (max-width: 700px) {
  .filmtile__ai {
    top: 10px;
    left: 10px;
    padding: 3px 5px;
    font-size: 9px;
    letter-spacing: 0.04em;
  }
}

/* grote play-knop middenin de video, alleen bij hover */
.filmtile__play {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 2;
  /* geen cirkelvlak meer: alleen de losse play-driehoek */
  display: flex;
  align-items: center;
  justify-content: center;
  transform: translate(-50%, -50%) scale(0.55);
  opacity: 0;
  transition:
    opacity 0.3s ease,
    transform 0.35s cubic-bezier(0.34, 1.3, 0.4, 1);
}

/* witte driehoek, los op het beeld (met zachte schaduw voor lichte shots) */
.filmtile__play::after {
  content: '';
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 18px 0 18px 29px;
  border-color: transparent transparent transparent #FBFBFA;
  filter: drop-shadow(0 2px 14px rgba(10, 10, 9, 0.45));
}

@media (hover: hover) {
  .filmtile:hover .filmtile__play {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
}


/* HUD-stempel rechtsonder in de video: spiegelt het label linksboven,
   maar in wit i.p.v. accent zodat de mark linksboven leidt. De halo houdt
   het leesbaar, ook op de lichte delen van de zwart-witbeelden */

/* de kop staat nu in de copy; de tile-eigen titel vervalt */
.filmtile__title { display: none; }

/* de aparte mobiele tile-kop is niet meer nodig: de copy ligt al over de video */
.filmtile__lead { display: none; }

/* ============ zwevend PiP-kaartje rechtsonder ============
   verschijnt zodra de hero-filmtegel uit beeld is; kleine loop-video die
   klikbaar naar het /film-paneel springt. Sluitbaar (blijft dan weg deze sessie). */
.filmpip {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 45; /* boven de content, onder de panels (49/50) en het dock (60) */
  width: 300px;
  border-radius: 0;
  /* zelfde donkerder vlak als het zwevende menu */
  background: rgba(9, 9, 8, 0.96);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  /* geen omlijning meer: het kader staat op zijn eigen schaduw */
  box-shadow: 0 18px 50px rgba(20, 20, 18, 0.34);
  padding: 10px;
  /* entree: rustig van rechtsonder omhoog schuiven */
  opacity: 0;
  transform: translateY(14px) scale(0.98);
  transition: opacity 0.5s cubic-bezier(0.32, 0.72, 0.28, 1),
              transform 0.5s cubic-bezier(0.32, 0.72, 0.28, 1);
  pointer-events: none;
}

.filmpip[hidden] { display: none; }

.filmpip.is-in {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* verbergen zodra er een venster openstaat: dan is de video toch al leidend */
body.panel-open .filmpip {
  opacity: 0;
  transform: translateY(14px) scale(0.98);
  pointer-events: none;
}

.filmpip__card {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  color: #FBFBFA;
  text-decoration: none;
  color: inherit;
}

.filmpip__media {
  display: block;
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: 0;
  overflow: hidden;
  background: #000000;
}

.filmpip__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* subtiele play-driehoek middenop de video */
.filmpip__tekst {
  display: block;
  padding: 12px 6px 6px;
}

.filmpip__label {
  display: block;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--acc);
}

.filmpip__titel {
  display: block;
  margin-top: 6px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 16px;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: #FBFBFA;
}

.filmpip__close {
  position: absolute;
  top: -9px;
  right: -9px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid rgba(251, 251, 250, 0.16);
  background: rgba(17, 17, 16, 0.98);
  color: rgba(251, 251, 250, 0.75);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s ease, color 0.2s ease, transform 0.2s ease;
}

.filmpip__close:hover {
  background: #000;
  color: #FBFBFA;
  transform: scale(1.08);
}

/* op telefoons botst een kaartje rechtsonder met het gecentreerde dock:
   daar draagt de hero-filmtegel de video al, dus het zwevende kaartje blijft weg */
@media (max-width: 719px) {
  .filmpip { display: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  .filmpip { transition: opacity 0.3s ease; }
  .filmpip.is-in { transform: none; }
}

@media (max-width: 600px) {
  /* de videoband mag op mobiel wat lager: het statement erboven draagt de intro al */
  .hero__row { min-height: clamp(340px, 52vh, 520px); }

  .hero__statement { --statement-onder: clamp(56px, 9vh, 96px); margin: clamp(64px, 10vh, 110px) 0 var(--statement-onder); }

  /* routes onder elkaar, gecentreerd */
  .hero__routes {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 14px;
  }
  .hero__voor { margin-bottom: 4px; }

  .hero__blok-titel { font-size: 20px; }
}

/* ============ ticker ============ */

/* ============ roster-intro: kop links, zijtekst rechts ============
   Zelfde editorial-duo als de hero (grote regel links, kleinere rechts
   uitgelijnde regel rechts), als opmaat naar de beeldwand */
.rosterintro {
  /* puur een kop-blok (kop links, zijtekst rechts): de ruimere tekstmarge */
  margin: var(--sect) var(--mx-kop) clamp(56px, 9vh, 110px);
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(28px, 4vw, 72px);
}

.rosterintro__links { margin: 0; }

.rosterintro__kop {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.015em;
  font-size: max(34px, 4vw); /* een maat boven de hero-oneliner */
  line-height: 1.12;
}

/* jaartal in het systeemfont, zoals de tuner en de topline */
.rosterintro__jaar {
  margin: clamp(12px, 1.8vh, 20px) 0 0;
  font-family: var(--font-mono);
  /* altijd de twee geschreven regels (de <br>), nooit meer */
  white-space: pre-line;
  line-height: 1.6;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-zacht);
}

.rosterintro__zijtekst {
  margin: 0;
  text-align: right;
  font-size: max(21px, 2vw);
  line-height: 1.5;
  font-weight: 500;
  color: var(--ink-zacht);
  white-space: nowrap; /* altijd precies de twee geschreven regels (de <br>) */
}

@media (max-width: 899.98px) {
  /* onder 900 staan de proposities niet betrouwbaar naast elkaar: dan
     wijst een lijn naar de verkeerde plek, dus geen lijnen */
  .hero__route::after { display: none; }
  /* smal: onder elkaar, beide links uitgelijnd */
  .rosterintro { flex-direction: column; align-items: flex-start; }
  .rosterintro__zijtekst { text-align: left; }
}

@media (max-width: 480px) {
  /* heel smal: liever netjes wrappen dan buiten beeld lopen */
  .rosterintro__zijtekst { white-space: normal; }
}

/* ============ roster / beeldwand ============ */

.roster {
  /* zijmarge via het gedeelde token (= de voeg tussen de foto's) */
  padding: clamp(40px, 6vh, 72px) var(--mx) 0;
}

.roster__wall {
  columns: 350px;
  column-gap: 12px;
}

/* JS-masonry: script.js verdeelt de tegels over kolommen zodat de
   bovenste rij van links naar rechts leest (brand-blok, dan Ruud) en
   het tweede brand-blok altijd rechts staat. Zonder JS vallen we
   terug op de CSS-kolommen hierboven. */
.roster__wall--js {
  columns: auto;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.roster__col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* ronde cursor-badge over de roster-foto's: de muis wordt een cirkel
   met "OPEN STUDIO" — de native cursor verdwijnt daar zolang */
.cursorbadge {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 95; /* boven de wand en het dock, onder de viewer/panelen */
  width: 96px;
  height: 96px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  /* clean: geen vlak, alleen een dunne lijn en tekst in ons wit */
  background: transparent;
  border: 1px solid #FBFBFA;
  color: #FBFBFA;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.5;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.55);
  transition: opacity 0.25s ease, transform 0.3s cubic-bezier(0.34, 1.3, 0.4, 1);
}

.cursorbadge.is-actief {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

@media (hover: hover) {
  /* de badge ís daar de cursor: wint bewust van de latere
     .roster .synth { cursor: pointer }-regel (klik-affordance).
     Zelfde verhaal op de hero-film ("Bekijk de film"). */
  .roster .roster__wall .synth,
  .roster .roster__wall .synth *,
  .hero__row .filmtile,
  .hero__row .filmtile * { cursor: none; }
  /* de proposities: het hele paneel klapt open op klik, dus ook daar is
     de badge de cursor ("Lees meer" / "Sluiten"); de afspraak-knop erin
     houdt zijn eigen pijl */
  .voorwie__paneel,
  .voorwie__paneel * { cursor: none; }
  .voorwie__paneel [data-open-panel],
  .voorwie__paneel [data-open-panel] * { cursor: pointer; }
}

@media (hover: none) {
  .cursorbadge { display: none; }
}

/* de wand start strak: alle kolommen op één lijn aan de bovenkant */

.roster__col .synth,
.roster__col .statement,
.roster__col .yourbrand {
  margin: 0;
}

/* synth-foto's */

.synth {
  margin: 0 0 12px;
  break-inside: avoid;
  position: relative;
  border-radius: 0;
  overflow: hidden;
  background: var(--img-fallback);
}

/* de link om de wandfoto: voor crawlers en nieuwe tabbladen; layout blijft
   gelijk, de figure vangt de klik en opent de viewer */
.synth__link { display: block; color: inherit; text-decoration: none; }

.synth img {
  display: block;
  width: 100%;
  object-fit: cover;
}

/* zachte zoom bij hover; de tegel (overflow hidden) houdt de crop strak */
.synth img { transition: transform 0.7s cubic-bezier(0.32, 0.72, 0.28, 1); }
.synth:hover img { transform: scale(1.045); }

/* de hele kaart groeit een minimaal tikje bij hover, net als de "jouw merk?"-
   CTA in het roster — de foto zoomt daarbovenop nog iets verder in */
.synth { transition: transform 0.4s cubic-bezier(0.32, 0.72, 0.28, 1); }
.synth:hover { transform: scale(1.02); }

@media (prefers-reduced-motion: reduce) {
  .synth:hover img { transform: none; }
  .synth:hover { transform: none; }
}

/* uitzondering: een halflijfs-bron (nieuwe lara) zoomt op de wand iets
   in, zodat het gezicht dezelfde maat heeft als de koppen ernaast; de
   hover zoomt daar bovenop nog een fractie verder */
.synth img.synth__zoom { transform: scale(1.16); transform-origin: 50% 20%; }

/* de wand toont alleen de portretten: de caption fadet pas in bij
   hover — naam met de merknaam eronder; de rol is van de wand
   verdwenen, die leeft in de studioviewer */
.synth__caption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 56px 18px 16px;
  background: linear-gradient(transparent, rgba(10, 10, 9, 0.55));
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 7px;
  opacity: 0;
  transition: opacity 0.45s ease;
}

.synth:hover .synth__caption,
.synth:focus-within .synth__caption { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .synth__caption { transition: none; }
}

.synth__name {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: 28px;
  line-height: 1;
  color: #FBFBFA; /* altijd wit op de foto-gradient, ook in dark */
}

/* de merknaam onder de naam, in het stille mono van de site */
.synth__client {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  line-height: 1;
  color: var(--paper-75);
}

/* statement-blokken */

.statement {
  margin: 0 0 12px;
  break-inside: avoid;
  border-radius: 0;
  padding: 20px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.statement p {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  /* één maat voor alle statement-blokken op de wand */
  font-size: clamp(26px, 2.8vw, 38px);
  line-height: 1.12;
}

/* het openingsstatement van de wand staat in backstage-zwart */
.statement--zwart {
  aspect-ratio: 1 / 1;
  background: #000000;
}

.statement--zwart p { color: #FBFBFA; }

/* de twee beloftes dragen elk de kleur van hun kant: merken in de
   primaire kleur, creators en icons in de tweede */
.statement--merk {
  background: var(--acc);
  aspect-ratio: 1 / 1.2; /* iets hoger dan het vierkante brand-blok */
}

.statement--mens {
  background: var(--acc2);
  aspect-ratio: 4 / 3;
}
.statement--merk p { color: var(--acc-ink); }
.statement--mens p { color: var(--acc2-ink); }

/* jouw merk-tile */

.yourbrand {
  display: flex;
  flex-direction: column;
  /* aanloop bovenaan links, de vraag onderin — dezelfde opbouw als de
     open kaart in het eigenschappen-raster */
  justify-content: space-between;
  width: 100%;
  margin: 0 0 12px;
  break-inside: avoid;
  aspect-ratio: 1 / 1;
  background: transparent;
  border: 1px dashed rgba(var(--ink-rgb), 0.3);
  border-radius: 0;
  padding: 18px;
  cursor: pointer;
  text-align: left;
  font: inherit;
  transition: border-color 0.25s ease;
}

.yourbrand__body {
  margin: 0;
  max-width: 26ch;
  /* dezelfde maat als de open kaart in het eigenschappen-raster */
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink); /* CTA: zelfde kleur als de titel erboven */
}

.yourbrand__title {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: clamp(26px, 2.8vw, 38px);
  line-height: 1.1;
  color: var(--ink);
}

/* onder deze grens is de tegel nog maar 177px in het vierkant: daar past
   geen aanloop meer boven de vraag zonder dat het volgepropt oogt */
@media (max-width: 480px) {
  .yourbrand__body { display: none; }
}

/* roster op mobiel: twee smallere kolommen, compactere captions */
@media (max-width: 600px) {
  .synth__caption {
    padding: 32px 12px 10px;
    gap: 8px;
  }

  .synth__name { font-size: 17px; }
  .synth__client { font-size: 9px; }

  .statement { padding: 14px; }
  .statement p { font-size: 16px; }

  .yourbrand { padding: 14px; }
  .yourbrand__title { font-size: 20px; }
}

/* ============ voor wie ============
   kleurcodering is betekenis: accent = merkkant, zwart/backstage = personality-kant */

.voorwie {
  overflow: hidden; /* de scrub schuift de panelen horizontaal; niet laten uitsteken */
  margin: var(--voorwie-boven) 12px 0; /* zijmarge exact gelijk aan de voeg/zijmarge van de roster-wand */
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  /* elk paneel houdt zijn eigen hoogte: de gekozen kant groeit, de
     andere blijft compact — de asymmetrie ís de keuze */
  align-items: start;
  gap: 12px;
}

.voorwie__paneel {
  position: relative;
  overflow: hidden;
  isolation: isolate; /* eigen stacking context: ruis kan achter de content */
  border-radius: 0;
  padding: clamp(28px, 3.4vw, 52px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
}

.voorwie__paneel--merk,
.voorwie__paneel--personality {
  background: #000000;
  color: #FBFBFA;
}

/* de accentkleuren leven alleen in de eyebrow: roze voor de merkkant,
   cyaan voor de creators/celebrities-kant */
.voorwie__label { color: var(--acc); opacity: 1; }
.voorwie__paneel--personality .voorwie__label { color: var(--acc2); }

/* typ-cursor volgt hier de paneeltekst; het accentblokje valt weg op het accentvlak */
.voorwie .typ-cursor { background: currentColor; }

.voorwie__kop {
  /* geen eigen ondermarge meer: de leadregel volgt direct, de flex-gap
     van het paneel bepaalt de afstand */
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  /* zelfde maat als de hero-oneliner ("Digital humans zijn het nieuwe
     gezicht van…"): de twee blokken praten op hetzelfde volume. balance
     verdeelt de woorden gelijkmatig, zodat de twee koppen (vrijwel even
     lang van tekst) naast elkaar hetzelfde aantal regels pakken */
  font-size: clamp(28px, 3.2vw, 48px);
  line-height: 1.12;
  max-width: 24ch;
  text-wrap: balance;
  /* ruimte voor twee regels, ook als de kop er maar één pakt: zo
     beginnen de hoofdstukjes in beide panelen op dezelfde hoogte,
     ongeacht de taal */
  min-height: 2.24em;
}

/* de leadregel onder de kop: op vol contrast en een maat groter dan de
   hoofdstukjes, zodat de belofte los staat van de onderbouwing */
.voorwie__lead {
  margin: 0;
  font-size: clamp(17px, 1.5vw, 21px);
  font-weight: 500;
  line-height: 1.5;
  max-width: 36ch;
  text-wrap: balance;
}

/* keuzeknop: standaard tonen de panelen alleen de belofte; de vijf
   hoofdstukken klappen pas open als de bezoeker die kant kiest.
   Zo blijft het blok kort en houdt het roster eronder de aandacht. */
/* dezelfde intext-stijl als de tekstlinks: een streep die bij hover
   wegloopt. De caret verschijnt juist pas bij hover, zodat de regel in
   rust puur typografie is */
.voorwie__meer {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0;
  margin: 4px 0 0;
  padding: 0 0 3px;
  border: 0;
  background: none;
  cursor: pointer;
  color: inherit;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* de streep hangt onder de tekst zelf, niet onder de hele knop —
   anders loopt hij door onder de ruimte voor de caret */
.voorwie__meer > span:first-child {
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-size: 100% 1px;
  background-position: 0 100%;
  padding-bottom: 3px;
  transition: background-size 0.35s cubic-bezier(0.22, 0.61, 0.21, 1);
}

.voorwie__meer:hover > span:first-child,
.voorwie__meer:focus-visible > span:first-child {
  background-size: 0% 1px;
  background-position: 100% 100%;
}

/* de caret scheidt 'lees verder' van de padnaam en klapt om als de
   kant open staat */
.voorwie__meer-caret {
  width: 8px;
  height: 8px;
  margin: 0 12px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: rotate(-45deg) translate(-2px, 2px);
  opacity: 0.62;
  transition: opacity 0.3s ease, transform 0.35s cubic-bezier(0.32, 0.72, 0.28, 1);
}

.voorwie__meer:hover .voorwie__meer-caret,
.voorwie__meer:focus-visible .voorwie__meer-caret { opacity: 1; }

.voorwie__paneel.is-open .voorwie__meer-caret {
  opacity: 1;
  transform: rotate(225deg) translate(-3px, -3px);
}

/* de padnaam: 'voor merken' / 'voor creators en icons'. Weg zodra de
   kant open staat: dan is de keuze gemaakt */
.voorwie__meer-pad {
  opacity: 0.62;
  transition: opacity 0.3s ease;
}
.voorwie__meer:hover .voorwie__meer-pad,
.voorwie__meer:focus-visible .voorwie__meer-pad { opacity: 1; }
.voorwie__paneel.is-open .voorwie__meer-pad { display: none; }

/* de klembak: van 0fr naar 1fr — geen vaste hoogtes nodig */
.voorwie__klem {
  align-self: stretch;
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.5s cubic-bezier(0.32, 0.72, 0.28, 1);
}

.voorwie__paneel.is-open .voorwie__klem { grid-template-rows: 1fr; }

.voorwie__klem > * { min-height: 0; overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .voorwie__klem { transition: none; }
  .voorwie__meer-caret { transition: none; }
}

/* de vijf hoofdstukjes als editorial rijen: monolabel in een eigen
   kolom links, de tekst rechts — de witruimte is de voeg, zonder
   hairlines */
.voorwie__secties {
  align-self: stretch; /* het paneel zet flex-start; de rijen lopen door tot de rand */
  padding-top: clamp(14px, 2.2vw, 30px);
  display: flex;
  flex-direction: column;
}

.voorwie__sectie {
  display: grid;
  grid-template-columns: clamp(118px, 10.5vw, 156px) 1fr;
  column-gap: clamp(18px, 2vw, 32px);
  row-gap: 6px;
  padding: 13px 0;
}

.voorwie__sectie-kop {
  margin: 0;
  padding-top: 4px; /* optisch gelijk met de eerste bodyregel */
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  /* de tussenkopjes dragen de kleur van hun propositie, net als de
     eyebrow erboven: cyaan bij merken, roze bij creators & icons */
  color: var(--acc);
}

.voorwie__paneel--personality .voorwie__sectie-kop { color: var(--acc2); }

.voorwie__sectie-body {
  margin: 0;
  font-size: 15.5px;
  line-height: 1.7;
  max-width: 48ch;
  opacity: 0.85;
}

/* de onderrij: foto's linksonder, de knop rechtsonder — op dezelfde
   basislijn verankerd; bij te weinig breedte wikkelt de knop eronder */
.voorwie__onder {
  margin-top: auto;
  align-self: stretch;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
  padding-top: 6px;
}

@media (max-width: 640px) {
  /* smal: het label boven de tekst, de hairline-rijen blijven */
  .voorwie__sectie { grid-template-columns: 1fr; }
  .voorwie__sectie-kop { padding-top: 0; }
}

/* de fotorij leeft in de onderrij (.voorwie__onder), die zelf onderin
   het paneel is verankerd */
.voorwie__fotos {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* lege plek in de fotorij, zoals "Jouw merk?" in het roster; klikbaar */
/* de vierde tegel naast de foto's: de actie als stippelkader, in dezelfde
   maat en verhouding als de portretten. Altijd zichtbaar, open of dicht */
.voorwie__placeholder {
  width: clamp(96px, 8.5vw, 132px);
  aspect-ratio: 3 / 4;
  border: 1px dashed color-mix(in srgb, currentColor 50%, transparent);
  border-radius: 0;
  background: transparent;
  color: inherit;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  cursor: pointer;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  text-align: left;
  padding: 10px;
}

.voorwie__fotos img {
  width: clamp(96px, 8.5vw, 132px);
  aspect-ratio: 3 / 4; /* zelfde verhouding als de portretten in de studio */
  object-fit: cover;
  border-radius: 0;
  display: block;
  transition: transform 0.6s cubic-bezier(0.32, 0.72, 0.28, 1);
}

.voorwie__fotos img:hover { transform: scale(1.04); }

/* het derde portret is er alleen als de vier tegels op één rij passen;
   daaronder (en op mobiel) blijft het bij twee plus de open plek */
.voorwie__fotos img.voorwie__foto--extra { display: none; }
@media (min-width: 1080px) {
  .voorwie__fotos img.voorwie__foto--extra { display: block; }
}

/* ============ vertrouwd door ============ */

.trusted {
  /* het sectieritme minus een correctie voor de parallax: de
     roster-kolommen erboven schuiven tot 175px omhoog, waardoor de wand
     optisch veel eerder eindigt dan zijn layoutbox. Met de oude aftrek
     van 36px stond er optisch 392px boven de band tegen 221 eronder —
     te veel leeg wit. */
  margin: calc(var(--sect) - clamp(48px, 9vh, 130px)) var(--mx) 0;
}

/* eronder vrijwel het volle sectieritme: de logo's als rustige band
   met ruimte naar de eigenschappen */
.trusted + .features { margin-top: calc(var(--sect) - clamp(8px, 1.5vh, 24px)); }

@media (max-width: 700px) {
  /* de kolommen-parallax loopt hier wél (twee kolommen, de tweede stijgt
     tot 175px), dus ook hier eindigt de wand optisch eerder dan zijn
     layoutbox. Een kleinere correctie dan op desktop: het gat was 300px
     tegen 203 op desktop, dat is net te veel. Eronder blijft het volle
     sectieritme, want daar speelt de parallax niet mee. */
  .trusted { margin-top: calc(var(--sect) - 56px); }
  .trusted + .features { margin-top: var(--sect); }
}

/* logos in een net 3-koloms raster (6 logo's = 2 rijen van 3) */
.trusted__row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  place-items: center;
  gap: clamp(32px, 5vh, 56px) clamp(28px, 4vw, 64px);
  margin-top: 0;
}

.trusted__row img {
  width: auto;
  /* brightness trekt donkere merken naar hetzelfde grijs als de lichte:
     groter mogen ze zijn, maar subtieler in toon */
  filter: grayscale(1) brightness(1.25);
  opacity: 0.5;
  mix-blend-mode: multiply; /* witte logo-achtergronden (o.a. CNV) vallen weg tegen het papier */
}

/* de zwaardere merken een tint zachter dan de basis, zodat de rij
   één grijstoon spreekt */
.trusted__row img.logo-zachter {
  filter: grayscale(1) brightness(1.6);
  opacity: 0.38;
}

/* CNV en InHolland ogen van zichzelf het zwaarst: de zachtste stand */
.trusted__row img.logo-zachtst {
  filter: grayscale(1) brightness(1.8);
  opacity: 0.3;
}

/* donker thema: de invert-behandeling blijft leidend, alleen iets gedempter */
html.thema-donker .trusted__row img.logo-zachter,
html.thema-donker .trusted__row img.logo-zachtst {
  filter: grayscale(1) invert(1);
  opacity: 0.45;
}

/* ============ eigenschappen ============ */

.features {
  margin: var(--sect) var(--mx) 0;
}

/* zwart blok, alleen in het wit/zwart-thema; het donkere thema volgt
   dezelfde spacing/hoogte als het lichte thema */
html.thema-blokken .features {
  background: #000000;
  margin: var(--sect) 0;
  /* onder bewust minder lucht dan boven: het blok stopt eerder */
  padding: var(--band-lucht) var(--mx) clamp(56px, 8vh, 110px);
  position: relative;
  /* clip: knipt de ruis-jitter zonder een scroll-container te maken */
  overflow: clip;
  isolation: isolate; /* eigen stacking context: ruis kan achter de content */
}

/* eigen ruislaag binnen het blok, achter de content */
html.thema-blokken .features::before {
  content: '';
  position: absolute;
  inset: -40px;
  z-index: -1;
  background-image: url('noise.png');
  opacity: 0.09;
  pointer-events: none;
  animation: tvStatic 0.4s steps(1) infinite;
}

/* ============ specs-grid: negen bouwstenen als 3×3 raster ============
   Volle breedte, hairline-voegen. Niets verspringt: de uitleg heeft zijn
   plek onderin de tegel al gereserveerd en licht alleen op (hover, of
   op touch via JS zodra de tegel de middenband passeert). Het accent:
   de titel flitst één tel met de merk-glitch, de index kleurt accent. */
/* fallback (geen JS of reduced-motion): rustige verticale lijst */
.features__list {
  --voeg-kleur: var(--hairline-row); /* de standaard hairline van de site */
  display: flex;
  flex-direction: column;
}

.feature-row {
  --kaart-pad-y: clamp(18px, 2vw, 28px);
  --kaart-pad-x: clamp(16px, 1.8vw, 26px);
  display: flex;
  flex-direction: column;
  padding: var(--kaart-pad-y) var(--kaart-pad-x);
}

/* ============ eigenschappen-raster (JS zet .is-rail op de sectie) ============
   Negen fotokaarten in kolommen die — net als het roster — uit de
   beschikbare breedte volgen (dus niet altijd vier naast elkaar), met
   de roster-voeg van 12px; de typografie schaalt niet mee met het
   scherm. Elke kaart is hetzelfde type: fotostrook (duotoon in de
   logo-gradient) met index, titel en uitleg eronder. De strookhoogtes
   rouleren voor ritme. */
.features.is-rail .features__list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 12px;
  align-items: start; /* wisselende kaarthoogtes: bovenlangs uitlijnen */
}

.features.is-rail .feature-row {
  position: relative;
  /* de kaartrug is op elk formaat zwart; alleen de index kleurt accent */
  background: #000000;
  /* geen hairline-kader: het gekleurde vlak zelf is de kaart */
  overflow: hidden;
}

.features.is-rail .feature-row .feature-row__index { color: var(--acc); }
.features.is-rail .feature-row .feature-row__title { color: #FBFBFA; }
.features.is-rail .feature-row .feature-row__body { color: rgba(251, 251, 250, 0.75); }

/* vaste typografie: de kaarttitel ademt niet mee met de viewport */
.features.is-rail .feature-row__title { font-size: 21px; }

/* de fotostrook: full-bleed bovenin, als een banner. Was 3/2.6 — een beeld
   van ruim 270px op een kaart van 317, waarmee de foto de kaart droeg in
   plaats van hem aan te kondigen. Nu een strook van zo'n 95px. */
.features.is-rail .feature-row__beeld {
  height: auto;
  aspect-ratio: 3 / 0.9;
}

/* ritme: de strookhoogtes verschillen licht per positie, zodat de kolommen
   niet in één lijn vallen. Vaste klassen (in de HTML) i.p.v. nth-child: de
   masonry verplaatst kaarten naar kolommen, waardoor posities in de DOM
   verschuiven */
.features.is-rail .feature-row--s1 .feature-row__beeld { aspect-ratio: 3 / 1; }
.features.is-rail .feature-row--s2 .feature-row__beeld { aspect-ratio: 3 / 0.78; }
.features.is-rail .feature-row--s3 .feature-row__beeld { aspect-ratio: 3 / 0.88; }

/* ============ rolkaarten in het raster ============
   Om de drie eigenschappen onderbreekt een toepassing het ritme:
   een vlak in een merkkleur, zonder beeld — capaciteit, dan de rol
   waarin die capaciteit landt. Dat maakt "strategische asset" waar. */
.features.is-rail .rolkaart {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 240px;
}

/* de toepassingen zijn kleurvlakken, korter dan de kaarten met beeld, in
   drie hoogtes zodat het raster niet in één maat valt: klein, midden,
   groot — de merkambassadeur (de eerste rol) krijgt de grote */
.features.is-rail .rolkaart--vlak { min-height: clamp(200px, 16vw, 240px); }
.features.is-rail .rolkaart--vlak-m { min-height: clamp(240px, 20vw, 290px); }
.features.is-rail .rolkaart--vlak-l { min-height: clamp(280px, 24vw, 340px); }

/* de toepassingen onderbreken het zwarte ritme in de merkkleuren: de
   capaciteiten blijven zwart, de rol waarin ze landen krijgt kleur */
.features.is-rail .rolkaart--acc { background: var(--acc); }
.features.is-rail .rolkaart--acc2 { background: var(--acc2); }

.features.is-rail .rolkaart--acc .feature-row__index,
.features.is-rail .rolkaart--acc .feature-row__title { color: var(--acc-ink); }
.features.is-rail .rolkaart--acc .feature-row__body {
  color: color-mix(in srgb, var(--acc-ink) 82%, transparent);
}

.features.is-rail .rolkaart--acc2 .feature-row__index,
.features.is-rail .rolkaart--acc2 .feature-row__title { color: var(--acc2-ink); }
.features.is-rail .rolkaart--acc2 .feature-row__body {
  color: color-mix(in srgb, var(--acc2-ink) 82%, transparent);
}

/* de open plek: dezelfde gestippelde kaart als "Jouw merk? Jouw gezicht?"
   onder aan de wand — geen vlak, alleen een omtrek die zegt dat er nog
   plaats is. Hier klikt hij door naar de afspraak. */
.features.is-rail .rolkaart--open {
  background: transparent;
  border: 1px dashed rgba(var(--ink-rgb), 0.3);
  cursor: pointer;
  text-align: left;
  font: inherit;
  align-items: flex-start;
  /* tekst bovenaan, de vraag onderin — dezelfde opbouw als "Jouw merk?
     Jouw gezicht?" onder aan de wand */
  justify-content: space-between;
  /* dezelfde veer als de andere knoppen; deze regel is specifieker dan
     de gedeelde lijst verderop, dus transform hoort hier mee */
  transition:
    transform 0.32s cubic-bezier(0.34, 1.3, 0.4, 1),
    border-color 0.25s ease;
}

.features.is-rail .rolkaart--open:hover,
.features.is-rail .rolkaart--open:focus-visible {
  border-color: rgba(var(--ink-rgb), 0.55);
  transform: scale(1.02);
}

.features.is-rail .rolkaart--open:active { transform: scale(0.99); }

/* de body staat hier bovenaan in plaats van onder de titel, dus de
   scheiding van 18px uit .feature-row__body is hier dode ruimte: de tekst
   begon 45px onder de kaartrand in plaats van tegen de binnenmarge */
.features.is-rail .rolkaart--open .feature-row__body { padding-top: 0; }

.features.is-rail .rolkaart.rolkaart--open .feature-row__title {
  color: var(--ink);
  margin: 0;
  /* een maat kleiner dan de andere rolkaarten: "Your application?" vulde
     op 1920 al 92% van de kaartbreedte. Compound met .rolkaart, anders
     wint de generieke rolkaart-maat hieronder op gelijke kracht */
  font-size: clamp(21px, 1.9vw, 27px);
}

.features.is-rail .rolkaart--open .feature-row__body {
  /* CTA-kaart: zelfde kleur als de titel eronder */
  color: var(--ink);
  margin: 0 0 clamp(28px, 4vh, 52px);
}

/* de rol krijgt zijn eigen maat: groter dan een eigenschapstitel,
   want dit is de toepassing waar de rest naartoe werkt */
.features.is-rail .rolkaart .feature-row__title {
  font-size: clamp(26px, 2.4vw, 34px);
  letter-spacing: -0.02em;
  margin-bottom: 10px;
}

.features.is-rail .rolkaart .feature-row__index {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 16px;
  opacity: 0.7;
}

.features.is-rail .rolkaart .feature-row__body {
  font-size: 15.5px;
  line-height: 1.6;
  max-width: 34ch;
}

/* de intro onder de sectiekop: de zin die het hele raster inleidt */
/* zelfde stem als de zijtekst bij de roster-intro: dezelfde maat,
   regelval en gewicht. Hij zakt bewust onder de onderlijn van de kop
   uit — speelser dan strak uitlijnen */
/* de zijtekst bij het proces én de intro bij de eigenschappen: één stem,
   één regel — dezelfde maat, regelval, gewicht en uitlijning als de
   zijtekst bij de roster-intro */
.proces__zijtekst,
.features__intro {
  margin: clamp(56px, 9vh, 130px) 0 0;
  max-width: 24ch;
  text-align: right;
  font-size: max(21px, 2vw);
  line-height: 1.5;
  font-weight: 500;
  color: var(--ink-zacht);
}

/* de eerste zin past op één regel en de tweede verdeelt balance gelijk
   over de regels daaronder; op 24ch brak "human." er als los woord af */
.proces__zijtekst {
  max-width: 34ch;
  text-wrap: balance;
  color: var(--ink-zacht);
}

/* de intro bij de eigenschappen staat op twee regels, niet op vier: een
   ruimere maatstaf dan de zijtekst bij het proces, en balance verdeelt de
   twee regels gelijk. Maat, gewicht en kleur blijven die van de zijtekst */
.features__intro {
  max-width: 52ch;
  text-wrap: balance;
}
/* de titel breekt alleen op zijn eigen <br>: hij mag niet krimpen voor
   de intro en niet op drie regels vallen */
.features .sectiekop-duo .section-title {
  flex: 0 0 auto;
  white-space: nowrap;
}

@media (max-width: 899.98px) {
  .proces__zijtekst,
  .features__intro { text-align: left; margin-top: clamp(20px, 3vh, 40px); }
  /* smal: de kaarten sluiten dichter op de kop aan */
  .features .sectiekop-duo { margin-bottom: clamp(24px, 4vh, 48px); }
}

/* masonry (JS): kolommen zoals de roster-wand — de kaarten sluiten
   verticaal op elkaar aan, de wisselende strookhoogtes blijven het spel */
.features.is-rail .features__list--js {
  display: flex;
  flex-direction: row; /* de basislijst staat op column; hier naast elkaar */
  align-items: flex-start;
  gap: 12px;
}

.features__col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* de kolommen beginnen niet op één lijn: een kleine versprong per kolom,
   hetzelfde ritme als de beeldwand. Bewust ingehouden — genoeg om de
   strakke lijn te breken, niet zoveel dat het scheef gaat staan. Het
   patroon herhaalt zich per vier, zodat het klopt bij twee tot zes
   kolommen. */
.features__col:nth-child(4n+2) { margin-top: clamp(12px, 1.6vw, 26px); }
.features__col:nth-child(4n+3) { margin-top: clamp(6px, 0.8vw, 12px); }
.features__col:nth-child(4n+4) { margin-top: clamp(18px, 2.2vw, 36px); }

/* de beelden staan in kleur; zwart-wit was grayscale(1) contrast(1.04) */
.features.is-rail .feature-row__beeld img { filter: none; }

/* de kaarten staan er gewoon: geen entree-animatie en geen
   placeholder-fase — het raster is meteen compleet in beeld. */

@media (prefers-reduced-motion: reduce) {
  .features.is-rail .feature-row::after { animation: none; }
}

@media (max-width: 767.98px) {
  /* smal scherm: de rail vervalt — de kaarten stapelen op volle breedte
     met dezelfde voeg (12px) als de roster-wand en het raster */
  .features.is-rail .features__list {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  .features.is-rail .features__list--js { flex-direction: column; }
  .features__col { width: 100%; }
  /* ook de toepassingskaarten vullen de breedte en houden dezelfde
     binnenruimte als de kaarten met beeld */
  .features.is-rail .rolkaart {
    width: 100%;
    min-height: 0;
    padding: clamp(26px, 7vw, 40px) var(--kaart-pad-x);
  }
  .features.is-rail .feature-row { position: static; width: auto; min-height: 0; aspect-ratio: auto; justify-content: flex-start; transform: none !important; opacity: 1 !important; filter: none !important; border: none; }
  /* na de generieke regel, anders wint diens width:auto op gelijke kracht */
  .features.is-rail .rolkaart { width: auto; min-height: 0; }
  /* idem voor de omtrek van de open kaart: de regel hierboven zet
     border:none op elke feature-row */
  .features.is-rail .rolkaart--open {
    border: 1px dashed rgba(var(--ink-rgb), 0.3);
  }
  /* smal: terug naar de fotostrook bovenin de lijst-rij */
  /* smal: terug naar de fotostrook bovenin de lijst-rij. Geen vaste hoogte:
     die overstemde de aspect-ratio hierboven, waardoor de strook op mobiel
     5,4:1 werd tegen 3:1 op desktop -- dezelfde foto sneed dan anders uit
     en moest per breedte een eigen focus krijgen. Nu houdt hij overal
     dezelfde verhouding, dus één object-position volstaat. */
  .features.is-rail .feature-row__beeld { position: relative; inset: auto; z-index: auto; margin: calc(-1 * var(--kaart-pad-y)) calc(-1 * var(--kaart-pad-x)) 16px; }
  .features.is-rail .feature-row__index { position: static; margin: 0 0 14px; }
  .features.is-rail .feature-row__body { margin: auto 0 0; max-width: 40ch; opacity: 1; }
  /* de kaart is ook hier zwart: eigen binnenruimte zodat de tekst niet
     tegen de randen staat */
  .features.is-rail .feature-row { padding: var(--kaart-pad-y) var(--kaart-pad-x); }
}

.feature-row__index {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-45);
  margin-bottom: 14px;
  transition: color 0.25s ease;
}

/* zodra een blok de rail binnenschuift (JS zet .is-in) kleurt de index
   accent en blijft zo — de band kleurt zich al scrubbend in */
.feature-row.is-in .feature-row__index { color: var(--acc); }

/* beeldslot bovenin de kaart: een full-bleed strook tot de kaartranden.
   Nu nog een stille placeholder in signaal-stijl; de foto's schuiven er
   later in — een <img> in het slot vult het vlak (object-fit: cover),
   de scanlines blijven er als merklaag overheen liggen */
.feature-row__beeld {
  position: relative;
  height: clamp(84px, 11vh, 140px);
  margin: calc(-1 * var(--kaart-pad-y)) calc(-1 * var(--kaart-pad-x)) 16px;
  background: var(--vlak-placeholder);
  overflow: hidden;
}

.feature-row__beeld img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* focuspunt per banner. De strook is veel breder dan hoog, dus cover snijdt
   boven en onder weg; hiermee bepaal je wélk deel blijft staan. De verhouding
   is op mobiel en desktop gelijk, dus één waarde volstaat. */
.feature-row__beeld--voet img { object-position: 50% 80%; }

/* het actieve blok is de spelende step van de sequencer: dekking en
   scherpte komen per frame uit de diepte-scrub (JS), en bij de index
   knippert een accent-LED — het statuslampje van een synth-pad */

.feature-row__index::after {
  content: '';
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-left: 10px;
  background: var(--acc);
  opacity: 0;
}

.features.is-rail .feature-row.is-actief .feature-row__index::after {
  animation: caretBlink 1.1s steps(1) infinite;
}

.feature-row__title {
  margin: 0;
  font-size: clamp(19px, 1.8vw, 27px);
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
  transition: color 0.25s ease;
}

/* de korte RGB-flits speelt op het moment dat de naald het blok
   selecteert (elke keer opnieuw), niet meer bij binnenschuiven */
.features.is-rail .feature-row.is-actief .feature-row__title {
  animation: wisselGlitch 0.55s steps(1) both;
}

.feature-row__body {
  margin: auto 0 0; /* onderin de tegel: titel boven, uitleg beneden */
  padding-top: 18px;
  max-width: 40ch;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-zacht);
}

@media (prefers-reduced-motion: reduce) {
  .features.is-rail .feature-row.is-actief .feature-row__title { animation: none; }
}

/* ============ toepassingen, psychologie & proces: kaarten ============ */

.cases,
.psych,
.process {
  margin: var(--sect) var(--mx) 0;
}

/* ============ proces als kaarten ============
   Dezelfde kaartentaal als het eigenschappen-raster: gevulde
   accentvlakken met de roster-voeg van 12px, harde hoeken en vaste
   typografie. Drie stappen naast elkaar; daaronder — precies zoals
   elke vierde kaart in het raster — een zwarte vierde kaart over de
   volle breedte voor het vervolg na launch. Geen entree-animaties:
   de kaarten staan er gewoon. */
.proceskaarten {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}

/* entree: de drie stappen stijgen gestaffeld in zodra de sectie in beeld
   komt (JS zet .is-in op .process). Buiten beeld gaat de klasse er
   weer af, zodat de entree bij elke scroll opnieuw speelt en de
   pagina blijft leven. De vertragingen staan alleen op de open
   staat: het resetten gebeurt in één stille beweging.
   Het fase-twee-blok doet hier niet aan mee: dat staat er altijd, en
   heeft zijn eigen hover-onthulling. */
.proceskaarten .proceskaart:not(.proceskaart--na) {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.6s ease, transform 0.6s cubic-bezier(0.32, 0.72, 0.28, 1);
}

.process.is-in .proceskaart:not(.proceskaart--na) {
  opacity: 1;
  transform: none;
}

.process.is-in .proceskaart:nth-child(2) { transition-delay: 0.12s; }
.process.is-in .proceskaart:nth-child(3) { transition-delay: 0.24s; }

.proceskaart {
  --kaart-pad-y: clamp(20px, 2.2vw, 30px);
  --kaart-pad-x: clamp(18px, 2vw, 28px);
  display: flex;
  flex-direction: column;
  /* De drie stappen dragen geen beeld meer, alleen tekst. De oude ondergrens
     (260-400px) was op dat beeld afgestemd en liet zonder beeld 79px leeg op
     1440 en 137px op 1920. Nu een lage vloer: de inhoud bepaalt de hoogte,
     het raster maakt de drie onderling gelijk. */
  min-height: 200px;
  padding: var(--kaart-pad-y) var(--kaart-pad-x);
  /* TEST: wit papier met een dunne grijze rand in plaats van het volle
     cyaan vlak — datzelfde grijs als de stippelkaders elders, maar
     doorlopend. Terug naar cyaan? background: var(--acc-grad) en de
     border eruit. */
  background: var(--panel-bg);
  /* lichter dan de stippelkaders. Bij het blok met beeld (fase twee) loopt
     de foto over de lijn heen, zodat die er niet naast staat */
  border: 1px solid rgba(var(--ink-rgb), 0.18);
}

/* smalle beeldbanner bovenin: full-bleed tot de kaartranden. De foto
   staat gewoon in kleur — geen zwart-wit en geen duotoon-gradient,
   alleen de scanlines als stille merklaag erover */
.proceskaart__beeld {
  position: relative;
  height: clamp(96px, 13vh, 160px);
  /* één pixel verder dan de padding: over de rand heen, zodat het beeld
     tot de buitenkant van de kaart loopt en de lijn er niet naast staat */
  margin: calc(-1 * var(--kaart-pad-y) - 1px) calc(-1 * var(--kaart-pad-x) - 1px) 20px;
  overflow: hidden;
  background: var(--vlak-placeholder);
}

.proceskaart__beeld img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.proceskaart__beeld::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: repeating-linear-gradient(0deg, rgba(var(--ink-rgb), 0.05) 0 2px, transparent 2px 5px);
}

.proceskaart__stap {
  display: block;
  margin-bottom: 16px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--acc);
}

/* vaste typografie, net als de kaarttitels in het raster: die staan op
   21px en groeien niet mee met het venster. Deze schaalden wel mee (1,7vw)
   en stonden daardoor op brede schermen los van de rest van de pagina. */
.proceskaart__titel {
  margin: 0;
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.2;
  color: var(--ink);
}

/* de uitleg staat direct onder de titel (niet uitgeduwd naar de
   onderrand): stap, titel en tekst lezen als één blok bovenin */
.proceskaart__body {
  margin: 0;
  padding-top: 14px;
  max-width: 44ch;
  /* gelijk aan de kaartteksten in het raster */
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-zacht);
}

/* de vierde kaart: zwart, vol breed — het na-launch-vervolg als
   backstage-laag, met de scanlines als stille merklaag erover.
   Binnenin hetzelfde kolomritme als de stapkaarten erboven: links een
   foto over twee kolommen, rechts — precies onder Campaign & Launch —
   het rijtje vervolg-items onder elkaar. De foto rekt mee met de
   hoogte van dat rijtje: altijd een strak rechthoekig vlak. */
.proceskaart--na {
  grid-column: 1 / -1;
  position: relative;
  overflow: hidden;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  padding: 0;
  background: #000000;
}

/* scanlines horen bij de dichte, wachtende staat: zodra de kaart
   opengaat lost het signaal op en staat de tekst op strak zwart,
   net als in de andere tekstblokken. Standaard (touch/smal, waar de
   kaart altijd open staat) dus uit. */
.proceskaart--na::after {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  background: repeating-linear-gradient(0deg, rgba(251, 251, 250, 0.04) 0 2px, transparent 2px 5px);
  transition: opacity 0.45s ease;
}

/* de foto vult de linker twee kolommen tot de kaartranden; de
   rechterrand valt samen met de rechterrand van stapkaart 02.
   De foto doet niet mee in de hoogtebepaling (absolute binnen het
   slot): het rijtje rechts bepaalt de kaarthoogte, de foto wordt
   gewoon gesneden (cover) */
.proceskaart__beeld--na {
  grid-column: 1 / 3;
  height: auto;
  margin: 0;
}

.proceskaart__beeld--na img {
  position: absolute;
  inset: 0;
}

.proceskaart__na-inhoud {
  grid-column: 3;
  padding: clamp(20px, 2.2vw, 30px) clamp(18px, 2vw, 28px);
}

.proceskaart__badge { margin: 0 0 14px; }

/* de kop van fase twee: dezelfde maat als de kaarttitels in het raster,
   maar op het zwarte vlak. Twee regels via de <br> in de tekst */
.proceskaart__nakop {
  margin: 0 0 clamp(20px, 3vh, 30px);
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.3;
  color: #FBFBFA;
}

.proceskaart__items {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 3vh, 32px);
}

/* ============ na launch: dichte kaart die uitklapt ============
   Op hover-schermen toont de zwarte kaart eerst alleen "Na launch?"
   met het knipperende accent-blokje (dezelfde caret als in de
   rollenlijst). Bij hover of focus klapt de inhoud stap voor stap
   uit: het beeld veegt van links binnen, dan de eyebrow, dan de
   drie items na elkaar. De kaart houdt altijd zijn volledige hoogte
   (het rijtje reserveert zijn ruimte), dus er verschuift niets. */
.proceskaart__naprikkel {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: none; /* alleen op hover-schermen actief */
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: #FBFBFA;
  pointer-events: none;
  transition: opacity 0.3s ease;
}

.proceskaart__naknipper {
  width: 0.5em;
  height: 0.82em;
  margin-left: 0.14em;
  background: var(--acc);
  animation: caretBlink 1.1s steps(1) infinite;
}

@media (hover: hover) and (min-width: 900px) {
  .proceskaart__naprikkel { display: flex; }

  .proceskaart--na { outline: none; }

  /* dicht: het signaal staat aan onder de prikkel; open: weg */
  .proceskaart--na::after { opacity: 1; }
  .proceskaart--na:hover::after,
  .proceskaart--na:focus-visible::after { opacity: 0; }

  /* dichte staat: beeld weggeveegd, inhoud onzichtbaar en iets gezakt */
  .proceskaart__beeld--na {
    clip-path: inset(0 100% 0 0);
    transition: clip-path 0.55s cubic-bezier(0.32, 0.72, 0.28, 1);
  }

  .proceskaart--na .proceskaart__badge,
  .proceskaart--na .proceskaart__nakop,
  .proceskaart--na .proceskaart__item {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.4s ease, transform 0.4s cubic-bezier(0.32, 0.72, 0.28, 1);
  }

  .proceskaart--na:hover .proceskaart__naprikkel,
  .proceskaart--na:focus-visible .proceskaart__naprikkel { opacity: 0; }

  /* de uitklap-choreografie: beeld → eyebrow → item 1 → 2 → 3.
     De vertragingen staan alleen op de open staat, zodat het
     dichtklappen in één rustige beweging gebeurt. */
  .proceskaart--na:hover .proceskaart__beeld--na,
  .proceskaart--na:focus-visible .proceskaart__beeld--na {
    clip-path: inset(0 0 0 0);
  }

  .proceskaart--na:hover .proceskaart__badge,
  .proceskaart--na:focus-visible .proceskaart__badge {
    opacity: 1;
    transform: none;
    transition-delay: 0.18s;
  }

  /* de kop komt tussen de eyebrow en het eerste item in de rij */
  .proceskaart--na:hover .proceskaart__nakop,
  .proceskaart--na:focus-visible .proceskaart__nakop {
    opacity: 1;
    transform: none;
    transition-delay: 0.24s;
  }

  .proceskaart--na:hover .proceskaart__item,
  .proceskaart--na:focus-visible .proceskaart__item {
    opacity: 1;
    transform: none;
  }

  .proceskaart--na:hover .proceskaart__item:nth-child(1),
  .proceskaart--na:focus-visible .proceskaart__item:nth-child(1) { transition-delay: 0.3s; }
  .proceskaart--na:hover .proceskaart__item:nth-child(2),
  .proceskaart--na:focus-visible .proceskaart__item:nth-child(2) { transition-delay: 0.45s; }
  .proceskaart--na:hover .proceskaart__item:nth-child(3),
  .proceskaart--na:focus-visible .proceskaart__item:nth-child(3) { transition-delay: 0.6s; }
}

@media (prefers-reduced-motion: reduce) {
  .proceskaart__naknipper { animation: none; }
  .proceskaart__naprikkel,
  .proceskaart__beeld--na,
  .proceskaart--na::after,
  .proceskaart--na .proceskaart__badge,
  .proceskaart--na .proceskaart__item { transition: none; }
  /* geen entree: de kaarten staan er gewoon */
  .proceskaarten .proceskaart { opacity: 1; transform: none; transition: none; }
}

.proceskaart__itemtitel {
  margin: 0 0 10px;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: #FBFBFA;
}

.proceskaart__itembody {
  margin: 0;
  max-width: 40ch;
  font-size: 16px;
  line-height: 1.7;
  color: rgba(251, 251, 250, 0.75);
}

@media (max-width: 899.98px) {
  /* smal: de stappen stapelen, de kaarten volgen hun inhoud */
  .proceskaarten { grid-template-columns: 1fr; }
  .proceskaart { min-height: 0; }
  .proceskaart__body { margin-top: 0; }
  /* de na-launch-kaart stapelt ook: foto als banner boven het rijtje */
  .proceskaart--na { grid-template-columns: 1fr; gap: 0; }
  .proceskaart__beeld--na { grid-column: 1; height: clamp(160px, 26vh, 240px); }
  .proceskaart__na-inhoud { grid-column: 1; }
}

/* ============ rollenlijst: rollen tussen hairlines ============
   Rustige typografische regels in de taal van de alinea erboven.
   Hover is een frame-wissel: de naamregel schuift omhoog het kader
   uit en van onderen stijgt de uitleg — in de primaire kleur, met
   een kleine studiofoto — het kader in. */
.rollenlijst {
  /* lijnen tot de schermranden; de negatieve marges heffen de sectiemarge
     (--mx) op, de tekst zelf staat op de tekstmarge — puur-tekstblok,
     uitgelijnd met de sectiekop erboven */
  margin-left: calc(-1 * var(--mx));
  margin-right: calc(-1 * var(--mx));
  padding-left: var(--mx-kop);
  padding-right: var(--mx-kop);
}

/* de lijst dimt, alleen de rij onder de cursor blijft vol — zelfde
   focus-gedachte als de inactieve blokken in het strategieblok */
.rollenlijst:hover .rolregel { opacity: 0.25; }

/* hover: de strook zelf wordt signaal — heel subtiele scanlines en
   tv-ruis faden in met de frame-wissel mee, over de volle schermbreedte
   (de rij knipt alleen verticaal). In inkt-tinten, dus de behandeling
   keert in het donkere thema vanzelf mee om. */
/* scanlines op de actieve rij; de tv-ruis is bewust weg — die maakte
   de hover onrustig */
.rolregel::before {
  content: '';
  position: absolute;
  inset: 0 calc(-1 * var(--mx-kop));
  z-index: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s ease;
  background: repeating-linear-gradient(0deg, rgba(var(--ink-rgb), 0.03) 0 2px, transparent 2px 5px);
}

/* de uitleg-laag wacht buiten beeld, onder de eigen regel */
.rolregel__laag--uitleg {
  position: absolute;
  inset: 0;
  transform: translateY(100%);
}

/* uitleg-laag: alleen tekst in de primaire kleur, geen beeld */
.rolregel__body {
  margin: 0;
  flex: 1;
  min-width: 0;
  /* zelfde maat als de naamregel die hij vervangt */
  font-size: clamp(24px, 2.6vw, 40px);
  line-height: 1.15;
  letter-spacing: -0.015em;
  font-weight: 500;
  color: var(--acc);
  white-space: nowrap; /* één regel in het kader; te lang loopt uit in … */
  overflow: hidden;
  text-overflow: ellipsis;
}

/* alleen de slotregel ("Jouw rol?") heeft een pijl — de rollen zelf
   zijn geen links. Rechte hoeken: haakse caps, geen ronde uiteinden */
.rolregel__pijl {
  flex: none;
  display: flex;
  line-height: 0;
  color: var(--acc);
}

/* "Jouw rol?": de open regel, klikbaar naar een afspraak */
.rolregel--open { cursor: pointer; }

/* psychologie: tekstblokken links, beeldvlak rechts */

.psych__grid {
  display: flex;
  flex-wrap: wrap;
  gap: 40px clamp(32px, 4vw, 64px);
  align-items: stretch;
}

/* op desktop loopt het beeldvlak als portrait-strook van de bovenkant
   van de sectie (in het zwarte-blokken-thema: de band) tot de onderkant */
@media (min-width: 900px) {
  .psych { position: relative; }

  .psych__media {
    position: absolute;
    top: 0;
    right: calc(-1 * var(--mx));
    bottom: 0;
    width: min(38vw, 560px);
    max-width: none;
    min-height: 0;
    margin: 0;
  }

  /* tekst blijft links van de strook */
  .psych__grid {
    padding-right: calc(min(38vw, 560px) - var(--mx) + clamp(32px, 4vw, 64px));
  }

  /* in de zwarte band zit de marge in de padding: strook tot de viewportrand */
  html.thema-blokken .psych__media { right: 0; }
}

/* ============ na launch ============ */

.after__label { margin: 56px 0 16px; }

/* compacter dan de drie stappen erboven: kleinere koppen, tekst en marges */
.cards--na { gap: 24px 28px; }

/* ============ privacy & compliance ============ */

.privacy {
  margin: var(--sect) var(--mx) 0;
  /* onder de rij staat precies de langste uitklap gereserveerd (JS meet
     die en zet --uitklap-ruimte) plus een kleine gap, zodat een open
     tegel netjes bóven het zwarte slotblok eindigt en er nooit overheen
     valt. Zonder JS blijft de oude, ruime onderrand staan. */
  --uitklap-gap: clamp(24px, 3.5vh, 44px);
  padding-bottom: clamp(48px, 7vh, 80px);
  /* de uitklap-lagen moeten boven het slotblok (later in de DOM) uitkomen */
  position: relative;
  z-index: 2;
}

/* zwart blok, alleen in het wit/zwart-thema; het donkere thema volgt
   dezelfde spacing/hoogte als het lichte thema */
html.thema-blokken .privacy {
  background: #000000;
  margin: var(--sect) 0 0;
  padding: var(--band-lucht) var(--mx);
  position: relative;
  overflow: hidden;
  isolation: isolate; /* eigen stacking context: ruis kan achter de content */
}

/* eigen ruislaag binnen het blok, achter de content */
html.thema-blokken .privacy::before {
  content: '';
  position: absolute;
  inset: -40px;
  z-index: -1;
  background-image: url('noise.png');
  opacity: 0.09;
  pointer-events: none;
  animation: tvStatic 0.4s steps(1) infinite;
}
/* in de zwarte band van het blokken-thema geen accentvlakken maar
   donkere tegels (zoals de rasterkaarten daar), met vaste lichte inkt */

.section-title--privacy { max-width: 18ch; }

/* ============ privacy als dichte tegels ============
   Vier zwarte vakjes in de kaartentaal van het eigenschappenraster
   (roster-voeg, harde hoeken, mono-index in het accent). De uitleg
   staat er gewoon — geen uitklap-spel. */
/* de vier vakjes staan als losse blokken op het papier: twee kolommen
   die elkaar verspringen, met wisselende breedtes en verticale versprong
   — dezelfde speelse ordening als de roster-wand, niet een net raster */
/* vier gelijke tegels in dezelfde kaartentaal als het raster en de wand:
   één breedte, één voeg van 12px, gelijke hoogte per rij. De vorige opzet
   gaf ze vier verschillende breedtes (400/686/686/440) met versprongen
   marges; dat las als toeval in plaats van als compositie, en liet gaten
   van tachtig pixels vallen. */
/* drie kolommen van twee tegels, elk op een eigen starthoogte */
.privacy__tegels {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  align-items: stretch;
}


/* De zes tegels staan gewoon naast elkaar: geen versprong per kolom en
   geen wisselende tegelhoogtes meer. De kolommen rekken tot dezelfde
   hoogte (align-items: stretch hierboven) en verdelen die over twee
   gelijke rijen, zodat de tegels ook bij langere vertalingen exact op
   één lijn blijven. De basishoogte staat verderop op .privacytegel. */
.privacy__kol {
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: 12px;
  min-width: 0;
}


@media (max-width: 700px) {
  /* smal: gewoon onder elkaar. De span moet hier terug, anders dwingt de
     brede tegel een tweede kolom af en scheurt het raster in tweeën */
  .privacy__tegels { grid-template-columns: 1fr; }
  .privacy__kol[class] { margin-top: 0; }
  .privacytegel--lead { grid-column: auto; }
}

.privacytegel {
  --kaart-pad-y: clamp(18px, 2vw, 26px);
  --kaart-pad-x: clamp(18px, 2vw, 28px);
  position: relative;
  padding: var(--kaart-pad-y) var(--kaart-pad-x);
  /* TEST: wit papier met een dunne grijze rand in plaats van het zwarte
     vlak — net als de procesblokken. Terug: background #121211, border
     eruit, en de titel/tekst weer op #FBFBFA. */
  background: var(--panel-bg);
  border: 1px solid rgba(var(--ink-rgb), 0.18);
}

/* de ondergrens staat per tegel hierboven; dit is de terugval */
.privacytegel { min-height: 190px; }

.privacytegel--lead { grid-column: auto; }

/* twee waarborgen springen eruit: "geen black box" staat zwart tussen de
   witte (dezelfde kaart, omgekeerde inkt) en "altijd herkenbaar" draagt
   het roze van het merk. Beide labels houden hun eigen inkt. */
.privacytegel--zwart {
  background: #000000;
  border-color: #000000;
}
.privacytegel--zwart .privacytegel__titel { color: #FBFBFA; }
.privacytegel--zwart .privacytegel__body { color: rgba(251, 251, 250, 0.75); }

.privacytegel--blauw {
  background: var(--acc);
  border-color: var(--acc);
}
.privacytegel--blauw .privacytegel__titel { color: var(--acc-ink); }
.privacytegel--blauw .privacytegel__body { color: color-mix(in srgb, var(--acc-ink) 82%, transparent); }
.privacytegel--blauw .privacytegel__index { color: var(--acc-ink); }

.privacytegel--roze {
  background: var(--acc2);
  border-color: var(--acc2);
}
.privacytegel--roze .privacytegel__titel { color: var(--acc2-ink); }
.privacytegel--roze .privacytegel__body { color: color-mix(in srgb, var(--acc2-ink) 82%, transparent); }
.privacytegel--roze .privacytegel__index { color: var(--acc2-ink); }

/* de sectietitel: twee zinnen op de eerste regel, de derde eronder (de
   <br>). De algemene maatstaf van .section-title zou de eerste regel
   nog eens breken; hier dus geen maatstaf en boven 900 geen zachte
   afbreking. Smal mag hij gewoon wikkelen. */
.privacy .section-title--privacy { max-width: none; }
@media (min-width: 900px) {
  .privacy .section-title--privacy { white-space: nowrap; }
}

@media (max-width: 700px) {
  .privacytegel[class] { min-height: 0; margin-top: 0; }
  /* smal: alles onder elkaar in één kolom */
  .privacy__tegels { grid-template-columns: 1fr; }
  .privacy__kol[class] { margin-top: 0; }
}

/* de zware waarborg spreekt een maat luider dan de vier eronder */
.privacytegel--lead .privacytegel__titel {
  font-size: 24px; /* vast: schaalde mee met het venster */
  letter-spacing: -0.02em;
}

.privacytegel--lead .privacytegel__body { max-width: 44ch; }

.privacytegel__index {
  display: block;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--acc);
  margin-bottom: 12px;
}

/* vaste maat, net als de kaarttitels in het raster */
.privacytegel__titel {
  margin: 0;
  /* de tegel rekt mee met de sectie, dus de tekst groeit mee — anders
     krimpt de letter optisch weg in een steeds groter vak */
  font-size: 21px; /* vast, gelijk aan de kaarttitels in het raster */
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.privacytegel__meer { display: block; }
.privacytegel__klem { min-height: 0; }

.privacytegel__body {
  margin: 0;
  padding-top: 12px;
  max-width: 40ch;
  font-size: 15.5px; /* vast, gelijk aan de kaartteksten */
  line-height: 1.6;
  color: var(--ink-zacht);
}

/* ============ contact-cta ============ */

.cta {
  margin: 0; /* sluit direct aan op het blok erboven */
  position: relative;
  background: transparent; /* het slotblok draagt zwart + signaal */
  color: #FBFBFA;
  /* de content zakt bewust naar onderen: daar is het signaal het
     sterkst, dus de CTA zit ín de ruis in plaats van erboven */
  padding: clamp(150px, 24vh, 300px) var(--mx-kop) clamp(150px, 24vh, 300px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 36px;
}

/* ============ slotblok: de CTA als zwarte slotbalk ============
   Het signaal zwelt aan over het blok: bovenaan stil zwart, naar
   onderen worden scanlines en ruis sterker — de CTA staat ín dat
   signaal, in dezelfde taal als de opening van de pagina. De footer
   valt er bewust buiten en staat weer op het witte papier. */
.slotblok {
  position: relative;
  isolation: isolate; /* eigen stapelcontext: het signaal blijft achter de content */
  overflow: hidden; /* de ruis-jitter (inset -40px) mag geen randen tonen */
  background: #000000; /* zelfde opgetilde zwart als de opening */
}

.slotblok::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  /* zelfde lijnen als in de opening, even sterk */
  background: repeating-linear-gradient(0deg, rgba(251, 251, 250, calc(0.05 * var(--ruis-cta))) 0 2px, transparent 2px 5px);
  /* hetzelfde verloop als in de opening: het signaal is sterk waar het blok
     begint en dooft naar onderen uit. Zonder dit stond de ruis over het hele
     blok even hard, en dat oogde meer dan bovenaan de pagina (gemeten:
     helderheid 14,3 tegen 11,2 en korrel 6,4 tegen 5,0). */
  -webkit-mask-image: linear-gradient(to bottom, #000 62%, rgba(0, 0, 0, 0.6) 78%, rgba(0, 0, 0, 0.25) 90%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 62%, rgba(0, 0, 0, 0.6) 78%, rgba(0, 0, 0, 0.25) 90%, transparent 100%);
}

.slotblok::after {
  content: '';
  position: absolute;
  inset: -40px;
  z-index: -1;
  pointer-events: none;
  background-image: url('noise.png');
  /* de ruis ligt over de héle balk: sinds de footer eronder vandaan is,
     viel de oude onderwaartse mask vrijwel volledig buiten beeld */
  /* zelfde ritme als de opening, eigen sterkte (zie --ruis-cta) */
  opacity: calc(0.11 * var(--ruis-cta));
  animation: vaultJitter 0.5s steps(2) infinite;
  /* hetzelfde verloop als in de opening: het signaal is sterk waar het blok
     begint en dooft naar onderen uit. Zonder dit stond de ruis over het hele
     blok even hard, en dat oogde meer dan bovenaan de pagina (gemeten:
     helderheid 14,3 tegen 11,2 en korrel 6,4 tegen 5,0). */
  -webkit-mask-image: linear-gradient(to bottom, #000 62%, rgba(0, 0, 0, 0.6) 78%, rgba(0, 0, 0, 0.25) 90%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 62%, rgba(0, 0, 0, 0.6) 78%, rgba(0, 0, 0, 0.25) 90%, transparent 100%);
}

@media (prefers-reduced-motion: reduce) {
  .slotblok::after { animation: none; }
}

.cta__title {
  margin: 0 0 12px;
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  /* fors, maar niet meer schreeuwend: de ruis eromheen doet het werk.
     Twee zinnen nu, dus een trede kleiner en een ruimere maatstaf: drie
     tot vier regels, de tweede zin op zijn eigen regel (de <br>) */
  font-size: clamp(34px, 5vw, 80px);
  line-height: 0.98;
  max-width: 24ch;
  text-wrap: balance;
}

.cta__title em {
  font-style: normal;
  color: inherit; /* volle acc-ink, geen grijstint */
}

.cta__actions {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  justify-content: center;
}

.cta__demo {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 52px;
  background: var(--acc-grad);
  color: var(--acc-ink);
  text-decoration: none;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  padding: 0 32px;
  border-radius: 0;
  font-size: 15px;
  font-weight: 500;
  transition: background 0.25s ease;
}

.cta__contact {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 52px;
  background: var(--acc2);
  border: 0;
  color: var(--acc2-ink);
  padding: 0 28px;
  border-radius: 0;
  font-size: 15px;
  font-family: inherit;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 0.25s ease;
}

/* ============ footer ============ */

.footer {
  margin: 0;
  position: relative;
  background: transparent; /* staat op het witte papier */
  /* aanloop na de zwarte CTA-balk — kort gehouden: dit is een regel
     informatie, geen sectie */
  padding: clamp(34px, 5vh, 56px) var(--mx-kop) 24px;
  /* kolommen op hun eigen breedte, gelijkmatig verdeeld: de eerste
     staat strak op de linkermarge, de laatste strak op de rechter
     (die lijnt zijn tekst dus rechts uit), en de twee middelste
     verdelen de ruimte ertussen */
  display: grid;
  grid-template-columns: repeat(4, auto);
  justify-content: space-between;
  gap: clamp(32px, 4vw, 64px);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-75); /* informatie, geen label */
}

/* elke kolom: een accent-kopje met de regels eronder */
.footer__kolom {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 7px;
}

/* de laatste kolom eindigt op de rechtermarge (via space-between),
   maar de regels beginnen gewoon links — geen rafelrand */

/* de kolomkopjes spreken de primaire kleur, net als de eyebrows
   elders op de pagina */

/* links dragen de onderstreping van de topregel (.tekstlink): de
   streep wipet bij hover naar rechts weg. Alleen de inkt is hier
   lichter, passend bij het zwarte slotblok. */
.footer__link { color: var(--ink-75); } /* onderstreping is het onderscheid, niet de tint */

.footer__link--caps { text-transform: uppercase; }

/* twee bij twee zodra vier kolommen niet meer ruim staan. De grens lag op
   700px, waardoor grote telefoons en smalle tablets nog vier kolommen
   naast elkaar persten */
@media (max-width: 900px) {
  .footer {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    justify-content: stretch;
    gap: 28px 24px;
  }
}

/* De twee CTA-kaarten (Jouw merk? en Jouw rol?) zijn knoppen, geen
   inhoudsblok: daar staat alle tekst in dezelfde kleur als de titel. De
   gewone eigenschapkaarten houden hun zachtere bloktekst. De kleur van de
   rollen-CTA staat bij .features.is-rail .rolkaart--open hierboven, want die
   regel is specifieker. */

/* De footer is ondersteunende tekst: adres, links, kleine lettertjes. Die
   houdt de zachtere inkt nu de rest voluit zwart is. */
.footer,
.footer a,
.footer p,
.footer span { color: var(--ink-zacht); }

/* ============ zwevend menu ============ */

/* sfeer-ruis op de pagina staat vast uit: alleen het signaal in de
   opening (herofx/vault), de storing-band onderaan het scherm en de
   ruis in de overlays horen bij het merk en blijven staan */
.noise,
html.thema-blokken .psych::before,
html.thema-blokken .features::before,
html.thema-blokken .privacy::before { display: none; }

.dock {
  position: fixed;
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 8px;
  /* bewuste uitzondering op de harde hoeken: het dock is het enige
     element met een subtiele afronding, en zonder rand eromheen */
  border-radius: 6px;
  /* donkerder dan het oude rgba(17,17,16): dichter bij het zwart van de
     pagina, maar bewust niet helemaal zwart, zodat het menu een eigen vlak
     blijft boven de content (16-09-2026) */
  background: rgba(9, 9, 8, 0.94);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 14px 44px rgba(20, 20, 18, 0.3);
  max-width: 96vw;
  justify-content: center;
  transition: opacity 0.65s ease, transform 0.65s ease;
}

/* het beginscherm blijft leeg: het dock fadet rustig in zodra de
   bezoeker in beweging komt (JS zet .dock-wacht op <html> bovenin).
   Onderaan de pagina fadet hij op dezelfde manier weer weg, zodat de
   footer vrij blijft (JS zet .dock-weg). */
html.dock-wacht .dock,
html.dock-weg .dock {
  opacity: 0;
  transform: translateX(-50%) translateY(14px);
  pointer-events: none;
}

.dock__brand {
  border: none;
  background: transparent;
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: 15px;
  white-space: nowrap; /* "The Synths" breekt nooit over twee regels */
  color: #FBFBFA; /* dock is altijd donker */
  height: 44px; /* hover-pill even groot als de demo-knop */
  display: inline-flex;
  align-items: center;
  padding: 0 16px;
  border-radius: 3px; /* subtiel hoekje, in lijn met de dock-afronding */
  transition: background 0.25s ease;
}

.dock__brand:hover,
.dock__brand.is-actief { background: rgba(251, 251, 250, 0.12); }

.dock__reg {
  font-size: 9px;
  vertical-align: super;
}

.dock__btn {
  border: none;
  background: transparent;
  cursor: pointer;
  padding: 0; /* zonder dit knijpt de browserpadding de vlag tot een ovaal */
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--paper-75);
  transition: background 0.25s ease, color 0.25s ease;
}

.dock__btn:hover,
.dock__btn.is-actief {
  background: rgba(251, 251, 250, 0.12);
  color: #FBFBFA;
}

/* hover/actief: het icoon zelf kleurt accent (de achtergrond-hover
   blijft zoals hij was; de vlag heeft geen currentColor en doet dus
   vanzelf niet mee) */
.dock__btn:hover svg,
.dock__btn.is-actief svg { color: var(--acc); }

/* hover-hint: de naam van het item schokt boven het dock binnen,
   gecentreerd boven de knop die je aanwijst (JS zet left) — als klein
   signaalvlak: backstage-zwart met scanlines en tv-ruis, lichte inkt
   erop (zelfde grijs als de footer). */
.dock__hint {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 24px; /* startwaarde; JS positioneert per knop */
  padding: 8px 16px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: var(--acc-grad);
  color: var(--acc-ink);
  white-space: nowrap;
  pointer-events: none;
  /* wachtstand: fadet zacht omhoog binnen, zoals tekst op de pagina */
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.45s cubic-bezier(0.22, 0.61, 0.21, 1),
              transform 0.45s cubic-bezier(0.22, 0.61, 0.21, 1);
}

.dock__hint.is-aan {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .dock__hint { transition: none; transform: none; }
}

/* op touch is er geen hover: hint blijft weg */
@media (hover: none) {
  .dock__hint { display: none; }
}

/* taalswitch: de knop toont de actieve vlag als cirkel; klik klapt een kolom
   met de overige vlaggen omhoog uit, als een tabblad achter het dock vandaan
   met een ronde bovenkant. Vaste 44px-knop zodat het dock nooit verspringt. */
.vlag-sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* de vlag wordt in een cirkel gecropt (slice), als een portret in het roster */
.dock__flag {
  display: block;
  width: 26px;
  height: 26px;
  border-radius: 50%;
}

/* rekt mee met de binnenhoogte van het dock, zodat de tab zich altijd
   op de bovenrand van het dock uitlijnt en niet op de knop */
.dock__langwrap {
  position: relative;
  display: flex;
  align-items: center;
  align-self: stretch;
}

/* het tabblad: even breed als een dockknop plus de dockpadding, met een
   ronde bovenkant zoals de zijkant van het menu, en een open onderkant die
   1px over de dockrand valt zodat het één doorlopend vlak wordt */
.dock__langmenu {
  position: absolute;
  bottom: calc(100% + 8px); /* 8px dockpadding: bodem valt op de dockrand */
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 60px;
  padding: 8px 8px 10px;
  border-radius: 6px 6px 0 0; /* onder vlak: valt daar op de dockrand */
  background: rgba(23, 23, 21, 0.93);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.22s ease, transform 0.22s cubic-bezier(0.32, 0.72, 0.28, 1), visibility 0.22s;
}

.dock__langwrap.is-open .dock__langmenu {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}

/* zelfde ronde hover als de dockknoppen */
.dock__langopt {
  border: none;
  background: transparent;
  padding: 0;
  cursor: pointer;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.24s ease, background 0.25s ease;
}

.dock__langopt .dock__flag {
  opacity: 0.8;
  transition: opacity 0.2s ease;
}

.dock__langopt:hover { background: rgba(251, 251, 250, 0.12); }
.dock__langopt:hover .dock__flag { opacity: 1; }

/* van onder naar boven opbouwen */
.dock__langwrap.is-open .dock__langopt { opacity: 1; }
.dock__langwrap.is-open .dock__langopt:nth-child(5) { transition-delay: 0.04s; }
.dock__langwrap.is-open .dock__langopt:nth-child(4) { transition-delay: 0.08s; }
.dock__langwrap.is-open .dock__langopt:nth-child(3) { transition-delay: 0.12s; }
.dock__langwrap.is-open .dock__langopt:nth-child(2) { transition-delay: 0.16s; }
.dock__langwrap.is-open .dock__langopt:nth-child(1) { transition-delay: 0.2s; }

/* de actieve taal staat al op de knop zelf */
.dock__langwrap[data-toon="nl"] .dock__langopt--nl,
.dock__langwrap[data-toon="en"] .dock__langopt--en,
.dock__langwrap[data-toon="fr"] .dock__langopt--fr,
.dock__langwrap[data-toon="de"] .dock__langopt--de { display: none; }

.dock__cta {
  margin-left: 6px;
  background: var(--acc-grad);
  color: var(--acc-ink);
  text-decoration: none;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  height: 44px;
  /* beide taalvarianten stapelen in dezelfde grid-cel: de knop is
     altijd zo breed als de langste tekst, dus geen verspringen */
  display: inline-grid;
  place-items: center;
  padding: 0 20px;
  border-radius: 3px; /* subtiel hoekje, in lijn met de dock-afronding */
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
  transition: background 0.25s ease;
}

.dock__cta > span {
  grid-area: 1 / 1;
  text-align: center;
}

/* de tweede CTA draagt de tweede accentkleur, zodat de twee
   hoofdacties naast elkaar elk hun eigen merkkleur hebben */
.dock__cta--afspraak {
  background: var(--acc2);
  color: var(--acc2-ink);
}

.dock__cta-ghost { visibility: hidden; }

/* korte CTA voor smalle schermen; in elke taal gewoon "Demo" */
.dock__cta-kort { display: none; }

/* ============ dock op smalle schermen ============ */

/* iconen behouden altijd hun cirkel */
.dock > * { flex: 0 0 auto; }

/* de taalknop zit in een wrapper en valt buiten `.dock > *`: expliciet
   vastzetten, anders krimpt hij tot een ovaal als het dock krap wordt */
.dock__langwrap,
.dock__lang { flex: 0 0 auto; }

@media (max-width: 600px) {
  .dock {
    gap: 3px;
    padding: 6px;
  }

  .dock__brand {
    font-size: 12.5px;
    padding: 0 8px;
  }

  .dock__btn {
    width: 36px;
    height: 36px;
  }

  /* korte CTA: dat scheelt genoeg breedte voor lucht tussen de iconen */
  .dock__cta-lang,
  .dock__cta-ghost { display: none; }
  .dock__cta-kort { display: block; }

  /* smal scherm: alles blijft op één rij. Het merk valt weg en de CTA's
     krimpen mee met de korte labels hierboven, zodat de iconen hun maat
     houden in plaats van samengeperst te worden. */
  .dock__brand { display: none; }

  .dock__cta {
    height: 36px;              /* gelijk aan de iconen: één strakke strip */
    padding: 0 10px;
    margin-left: 2px;
    font-size: 11.5px;
  }
}

@media (max-width: 380px) {
  /* de smalste telefoons: alles een tandje krapper, maar de iconen
     blijven aantikbaar — de CTA's leveren de breedte in, niet zij */
  .dock { gap: 2px; }
  .dock__brand { font-size: 12px; padding: 0 6px; }
  .dock__btn { width: 34px; height: 34px; }
  .dock__cta { height: 34px; padding: 0 8px; font-size: 11px; }
}

/* actief venster: de demo-knop verdiept zijn eigen cyaan. De afspraak
   staat er bewust buiten — die is overal roze en sloeg hier opeens om
   naar blauw. */
.dock__cta.is-actief:not(.dock__cta--afspraak) {
  background: color-mix(in srgb, var(--acc) 82%, #000);
}

/* ============ overlay-panelen ============ */

/* "signaal geblokkeerd": gedempt beeld met scanlines en ruis. Eén laag voor
   alle overlays, altijd gemount — zo begint de ruis niet opnieuw wanneer je
   in het menu van het ene venster naar het andere wisselt. */
.panelfx {
  position: fixed;
  inset: 0;
  z-index: 49; /* onder de vensters (50+), boven de pagina */
  overflow: hidden; /* de jitter-ruis (inset -60px) mag geen scroll geven */
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  background: rgba(17, 17, 16, 0.55);
  -webkit-backdrop-filter: blur(7px) saturate(0.6) brightness(0.82);
  backdrop-filter: blur(7px) saturate(0.6) brightness(0.82);
  transition: opacity 0.25s ease, visibility 0.25s; /* backdrop komt eerst */
}

body.panel-open .panelfx {
  opacity: 1;
  visibility: visible;
}

.panelfx::before {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(0deg, rgba(10, 10, 9, 0.16) 0 2px, transparent 2px 5px);
}

.panelfx::after {
  content: '';
  position: absolute;
  inset: -60px; /* jitter mag geen randen tonen */
  background-image: url('noise.png');
  opacity: 0.07;
  animation: vaultJitter 0.5s steps(2) infinite;
}

/* .panel is het klikvlak rond het venster; de backdrop komt van .panelfx */
.panel {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 50;
  padding: clamp(16px, 4vh, 48px) clamp(16px, 4vw, 48px);
  align-items: center;
  justify-content: center;
}

.panel.is-open {
  display: flex;
  animation: backdropIn 0.3s ease both;
}

.panel__inner {
  position: relative;
  z-index: 1; /* boven de scanline/ruis-lagen van de backdrop */
  background: var(--panel-bg);
  border-radius: 0;
  box-shadow: 0 24px 80px rgba(20, 20, 18, 0.35);
  max-width: 1060px;
  width: 100%;
  max-height: 100%;
  overflow-y: auto;
  /* top-padding zit in .panel__top zodat die als sticky balk het
     venster tot de rand afdekt */
  padding: 0 clamp(24px, 5vw, 64px) clamp(48px, 8vh, 96px);
  /* vast openingsritme voor alle overlays: eerst de backdrop (0.25s),
     dan het venster met dezelfde curve, een tel later */
  animation: panelIn 0.4s cubic-bezier(0.32, 0.72, 0.28, 1) 0.06s both;
}

.panel__inner--contact {
  min-height: min(70vh, 100%);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

/* ============ artikel-paneel (SEO) ============ */

/* het artikelvenster is altijd even groot (lijst of artikel): vaste hoogte
   en een altijd zichtbare scrollbar, dus geen verspringen bij het wisselen */
#panel-artikel .panel__inner {
  height: 100%;
  overflow-y: scroll;
}

/* nieuwssectie: standaard een overzichtslijst; een open artikel vult
   het venster, met een terugknop naar het overzicht */
.artikel-layout.is-lijst .artikel-hoofd { display: none; }

.artikel-hoofd { max-width: 880px; }

/* één artikel tegelijk zichtbaar */
.artikel-item { display: none; }
.artikel-item.is-actief { display: block; }

/* zachte fade-randen boven en onder: scrollende content loopt netjes uit
   in de paneelkleur. Alleen in de lange, scrollende panelen (studio,
   contact, artikelen) — niet in de korte formulier-overlays en de film.
   Sticky pseudo-elementen zonder eigen ruimte in de flow. */
.panel--scrollfade .panel__inner::before,
.panel--scrollfade .panel__inner::after {
  content: '';
  position: sticky;
  z-index: 4;
  display: block;
  width: 100%;
  height: 44px;
  flex: 0 0 auto;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.25s ease;
}

.panel--scrollfade .panel__inner::before {
  top: 0;
  margin-bottom: -44px;
  background: linear-gradient(var(--panel-bg), transparent);
}

.panel--scrollfade .panel__inner::after {
  /* het venster heeft onderin padding; de strook mag tot de echte rand */
  bottom: calc(-1 * clamp(48px, 8vh, 96px));
  margin-top: -44px;
  background: linear-gradient(transparent, var(--panel-bg));
}

/* de fade hoort er alleen te zijn als er in die richting nog content
   voorbij loopt: bovenin geen top-fade, onderaan geen bottom-fade
   (anders lijkt het alsof de laatste regels wegvloeien terwijl er
   niets meer onder staat). Past niets? Dan zijn beide klassen gezet
   en is er dus nergens een fade. JS zet de klassen. */
.panel--scrollfade .panel__inner.is-bovenin::before { opacity: 0; }
.panel--scrollfade .panel__inner.is-onderin::after { opacity: 0; }

/* zwevende knoppen rechtsboven: terug (alleen bij open artikel) + sluiten.
   Plakken aan de bovenrand terwijl de content eronderdoor scrolt; de
   negatieve ondermarge geeft de laag netto nul hoogte in de flow */
.panel__topknoppen {
  position: sticky;
  top: 0;
  z-index: 6;
  width: 100%; /* ook in flex-panelen (contact) volle breedte: knoppen rechts */
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  padding-top: 24px;
  margin-bottom: -68px; /* padding 24 + knophoogte 44 */
  pointer-events: none; /* de laag zelf vangt geen klikken af */
}

.panel__topknoppen .panel__close {
  pointer-events: auto;
  background: var(--panel-bg); /* dekt scrollende tekst onder de knop af */
}

/* hidden wint van de flex-display van de knop zelf */
.panel__close[hidden] { display: none; }

/* korte paneelnaam op smalle schermen */
.artikel-pad--kort { display: none; }

@media (max-width: 600px) {
  .artikel-pad--lang { display: none; }
  .artikel-pad--kort { display: inline; }
}

/* overzicht: artikelen clean onder elkaar, kleine foto links,
   scheidingslijnen ertussen */
.artikel-overzicht {
  display: none;
  max-width: 880px;
  padding-top: 10px;
}

.artikel-layout.is-lijst .artikel-overzicht { display: block; }

.nieuws-item {
  display: grid;
  grid-template-columns: 116px 1fr;
  gap: 18px;
  align-items: center;
  padding: 16px 0;
  text-decoration: none;
  /* scanbare lijst: alleen een fluisterlijn tussen de items, geen kader */
  border-top: 1px solid rgba(var(--ink-rgb), 0.05);
}

.nieuws-item:first-child { border-top: 0; }

.nieuws-item img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: 0;
}

.nieuws-item__titel {
  display: block;
  font-size: 15.5px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--ink);
}

.nieuws-item:hover .nieuws-item__titel {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.nieuws-item__datum {
  display: block;
  margin-top: 6px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--ink-zacht);
}

/* nieuwste artikel uitgelicht: groot beeld met de titel eroverheen */
.nieuws-item--groot {
  display: block;
  position: relative;
  padding: 0;
  margin-bottom: 8px;
  border-top: 0;
  border-radius: 0;
  overflow: hidden;
}

.nieuws-item--groot img {
  aspect-ratio: 21 / 9;
}

.nieuws-item--groot > span {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 56px 18px 16px;
  background: linear-gradient(transparent, rgba(17, 17, 16, 0.88));
}

.nieuws-item--groot .nieuws-item__titel {
  color: #FBFBFA;
  font-size: clamp(19px, 2.4vw, 24px);
  line-height: 1.25;
  max-width: 26ch;
}

.nieuws-item--groot .nieuws-item__datum { color: rgba(251, 251, 250, 0.7); }

@media (max-width: 600px) {
  .nieuws-item--groot img { aspect-ratio: 16 / 9; }
}

@media (max-width: 900px) {
  /* compactere lijst op mobiel */
  .nieuws-item {
    grid-template-columns: 96px 1fr;
    gap: 14px;
    padding: 13px 0;
  }

  .nieuws-item__titel { font-size: 14px; }

  /* artikel meteen prominenter: kleinere titel, dicht onder de terugknop */
  .artikel-item .panel__title--artikel {
    font-size: clamp(23px, 6.4vw, 30px);
    margin-top: 20px;
  }

  .artikel__meta { margin-top: 12px; }
  .artikel__banner { margin-top: 16px; }
  .artikel { margin-top: 24px; }
}

/* standaard banner-slot: openingsbeeld onder titel + byline */
.artikel__banner {
  margin-top: 24px;
  aspect-ratio: 21 / 9;
  background: var(--vlak-placeholder);
  border: 1px dashed rgba(var(--ink-rgb), 0.18);
  border-radius: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-45);
}

/* in About staat de banner los in het venster (geen artikel-item eromheen):
   dezelfde breedte als de artikelen */
#panel-studio .artikel__banner { max-width: 880px; }

/* About: de opening van de site als banner. De wordmark hergebruikt de
   hero-klassen (zelfde strijklicht, kap-lijn en ®) op het opgetilde zwart
   van de kop, met scanlines en ruis als in .herofx (zonder de jitter).
   De inkt-tokens staan hier lokaal op de donkere waarden, want het
   venster zelf is wit. Het font schaalt met de bannerbreedte (cqw):
   bij 100px font is de wordmark met ® 461px breed, 19.5cqw vult 90%. */
.artikel__banner--lockup {
  border: none;
  background: #000000;
  --ink: #EDECE9;
  --ink-zacht: var(--ink);
  --ink-rgb: 242, 241, 238;
  container-type: inline-size;
}
.artikel__banner--lockup::before {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(0deg, rgba(var(--ink-rgb), 0.05) 0 2px, transparent 2px 5px);
}
.artikel__banner--lockup::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('noise.png');
  opacity: 0.11;
}
.aboutmerk { position: relative; z-index: 1; }
.aboutmerk .hero__wordmark {
  animation: none;
  margin: 0;
  font-size: clamp(40px, 12vw, 172px); /* browsers zonder cqw */
  font-size: 19.5cqw;
}

/* gevuld banner-slot: het beeld vult het kader, de stippellijn vervalt */
.artikel__banner--beeld { border: none; }

.artikel__banner--beeld img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
}

.panel__title--artikel { max-width: 24ch; }

/* standaard byline onder een artikeltitel: datum — auteur */
.artikel__meta {
  margin: 20px 0 0;
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--ink-zacht);
}

.artikel__meta-scheiding { color: var(--ink-zacht); }

.artikel {
  max-width: 80ch; /* breder dan de klassieke 68ch: het venster is 932px binnenwerks en liet rechts 300px leeg */
  margin-top: 36px; /* ademruimte tussen titel/byline en de eerste alinea */
}

.artikel h3 {
  margin: 48px 0 14px;
  font-size: clamp(19px, 2.2vw, 30px);
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.artikel h4 {
  margin: 26px 0 8px;
  font-size: 15.5px;
  font-weight: 600;
  color: var(--ink);
}

.artikel p {
  margin: 0 0 14px;
  font-size: 15px;
  line-height: 1.75;
  color: var(--ink-zacht); /* artikeltekst net zo zacht als de body in een blok */
}

.artikel__lead {
  font-size: 15px;
}

.artikel strong { color: var(--ink); font-weight: 600; }
.artikel em { font-style: italic; }

.artikel ul {
  margin: 0 0 14px;
  padding-left: 20px;
  font-size: 15px;
  line-height: 1.75;
  color: var(--ink-75);
}

.artikel li { margin: 4px 0; }

.artikel li::marker { color: var(--acc); }

/* menu-icoontje subtiel vóór het pad in de overlay-kop */
.path-label__icoon {
  /* zelfde maat als in het dock */
  width: 22px;
  height: 22px;
  vertical-align: -6px;
  margin-right: 9px;
  opacity: 0.75;
}

.panel__top {
  /* de padregel scrolt gewoon mee met de content; alleen de knoppen
     (terug/sluiten) blijven staan via .panel__topknoppen */
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: 40px 0 14px;
}

.panel__close {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(var(--ink-rgb), 0.2);
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  flex: 0 0 auto;
  transition: background 0.25s ease, color 0.25s ease;
}

.panel__title {
  margin: 56px 0 28px;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.03em;
  font-size: clamp(36px, 5.2vw, 72px);
  line-height: 1.04;
  max-width: 18ch;
  color: var(--ink);
}

.panel__title--contact { margin-top: 64px; }

.panel__intro {
  margin: 32px 0 0;
  max-width: 58ch;
  font-size: 15px;
  line-height: 1.75;
  color: var(--ink-zacht);
}

.panel__intro--contact {
  margin-top: 28px;
  max-width: 52ch;
}

.panel__path { margin-top: 64px; }


.panel__cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 36px 40px;
  margin-top: 28px;
}

.panel-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.panel-card__title {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
}

.panel-card__role {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-45);
}

.panel-card__contact {
  margin: 6px 0 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
}

.panel-card__contact a {
  color: var(--ink-75);
  text-decoration: none;
  width: fit-content;
}

.panel-card__contact a:hover {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.panel-card__body {
  margin: 0;
  font-size: 15px;
  line-height: 1.75;
  color: var(--ink-60);
}

.panel__signoff {
  margin: 56px 0 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-style: italic;
  letter-spacing: -0.02em;
  font-size: clamp(24px, 3vw, 38px);
  line-height: 1.2;
  max-width: 22ch;
}

/* contact-paneel */

.panel__actions {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 44px;
}

/* alle panel-knoppen: vaste hoogte én vaste breedte, zodat elke
   variant (afspraak, demo, verzenden, log in) exact even groot is */
/* "Maak een afspraak" is de tweede hoofdactie en draagt daarom overal
   de tweede merkkleur, net als in het dock en de slot-CTA */
.panel__demo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 50px;
  width: 230px;
  max-width: 100%;
  background: var(--acc-grad);
  color: var(--acc-ink);
  text-decoration: none;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  padding: 0 16px;
  border-radius: 0;
  font-size: 14.5px;
  font-weight: 500;
  transition: background 0.25s ease;
}

/* de afspraak-actie draagt overal de tweede merkkleur: in het dock, in
   de slot-CTA en in de panelen. Zo is één actie altijd één kleur. */
.panel__demo[data-open-panel="afspraak"],
.panel__ghost[data-open-panel="afspraak"],
#panel-afspraak .login-form__knop {
  background: var(--acc2);
  color: var(--acc2-ink);
  border: 0;
}

.panel__ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 50px;
  width: 230px;
  max-width: 100%;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--ink-35);
  cursor: pointer;
  font-family: inherit;
  text-decoration: none;
  padding: 0 16px;
  border-radius: 0;
  font-size: 14.5px;
  font-weight: 500;
  transition: border-color 0.25s ease;
}

.contact-grid {
  margin-top: 56px;
  width: 100%;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 28px 40px;
}

.contact-grid__item {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.contact-grid__label {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-zacht);
}

.contact-grid__value {
  color: var(--ink);
  text-decoration: none;
  font-size: 16px;
  font-weight: 500;
}

.panel__footnote {
  margin: auto 0 0;
  padding-top: 96px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-zacht);
}

/* log-in-paneel: zelfde chrome, compacter venster */

.panel__inner--login {
  position: relative; /* anker voor de storing- en EU-lagen */
  z-index: 1; /* boven de scanline/ruis-lagen van de backdrop */
  overflow: hidden;
  max-width: 440px;
  padding: 0 clamp(24px, 4vw, 40px) 32px;
  /* de vault staat op het witte papier, net als de andere overlays */
  background: var(--panel-bg);
  color: var(--ink);
}

/* de formulierpanelen (afspraak en demo) delen de layout van de vault;
   sinds de vault zelf ook wit is hoeven ze niets meer terug te zetten */

/* backdrop: "signaal geblokkeerd" — gedempt beeld met scanlines en ruis */
@keyframes vaultJitter {
  0% { transform: translate(0, 0); }
  25% { transform: translate(-14px, 9px); }
  50% { transform: translate(11px, -13px); }
  75% { transform: translate(-7px, 6px); }
  100% { transform: translate(0, 0); }
}

/* ============ vault-intro (fase 1) ============ */

.vault-intro {
  min-height: 445px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.vault-intro[hidden] { display: none; }

/* de intro staat er gewoon: geen storing, glitch of gefaseerde entree —
   het paneel schuift zelf al open, dat is beweging genoeg */
.vault-intro__titel {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: 34px;
  color: var(--ink);
}

.vault-intro__reg {
  font-size: 14px;
  vertical-align: super;
}

.vault-intro__sub {
  margin: 0 0 28px;
  max-width: 30ch;
  font-size: 14.5px;
  line-height: 1.75;
  color: var(--ink-65);
}

.vault-intro__knop {
  height: 50px;
  padding: 0 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 0;
  background: var(--acc-grad);
  color: var(--acc-ink);
  font-family: inherit;
  font-size: 15px;
  font-weight: 500;
  cursor: pointer;
}

.vault-intro__eu {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 22px;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-55);
}

/* op desktop staat het venster net iets boven het midden */
@media (min-width: 701px) {
  .panel__inner--login { margin-bottom: 5vh; }
}

/* onderregel: subtiel, in dezelfde toon als de statusregel */
.login-code__fout {
  margin: 4px 0 0;
  min-height: 15px; /* hoogte gereserveerd: het venster verspringt nooit */
  visibility: hidden;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  /* cyaan las prima op het oude backstage-zwart, maar verdwijnt op het
     witte papier — een foutmelding moet je juist kunnen lezen */
  color: var(--ink);
}

.login-code__fout.is-fout { visibility: visible; }

.panel__intro--login {
  margin-top: 12px;
  max-width: none;
  font-size: 15.5px;
}

.login-form {
  position: relative; /* anker voor de zwevende foutballon */
  margin-top: 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.login-form__veld {
  font: inherit;
  font-size: 16px; /* nooit kleiner: onder 16px zoomt iOS automatisch in bij focus */
  color: var(--ink);
  background: transparent;
  border: 1px solid rgba(var(--ink-rgb), 0.25);
  border-radius: 0;
  padding: 14px 16px;
  outline: none;
  transition: border-color 0.2s ease;
}

.login-form__veld::placeholder { color: var(--ink-45); }

/* ============ toegangscode (iPhone-stijl) ============ */

/* korte fade bij de faseovergang intro → codepad, zodat het venster
   niet hard omklapt (de enige beweging die de vault nog kent) */
@keyframes codepadIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

.login-code {
  min-height: 445px; /* even hoog als de intro: het venster verspringt niet */
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  animation: codepadIn 0.45s ease both;
}

.login-code[hidden] { display: none; }

.login-code__dots {
  display: flex;
  gap: 16px;
  margin: 0; /* de centrering en de pad-marge houden de lucht in balans */
}

.login-code__dots span {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 1px solid rgba(var(--ink-rgb), 0.5);
  transition: background 0.15s ease, border-color 0.15s ease;
}

.login-code__dots span.is-vol {
  background: var(--ink);
  border-color: var(--ink);
}

/* foute code: dots schudden even, zoals op de iPhone */
@keyframes codeSchud {
  0% { transform: translateX(-9px); }
  25% { transform: translateX(8px); }
  50% { transform: translateX(-6px); }
  75% { transform: translateX(4px); }
  100% { transform: none; }
}

.login-code__dots.is-schud { animation: codeSchud 0.4s ease; }

.login-code__pad {
  margin-top: 17px; /* extra lucht onder de dots, bovenop de kolom-gap */
  display: grid;
  grid-template-columns: repeat(3, 72px);
  gap: 14px 24px;
  justify-content: center;
}

.login-code__pad button {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  border: none;
  background: rgba(var(--ink-rgb), 0.07);
  color: var(--ink);
  font-family: inherit;
  font-size: 27px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  transition: background 0.15s ease;
}

.login-code__pad button:active { background: rgba(var(--ink-rgb), 0.2); }

.login-code__pad button span {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.18em;
  color: var(--ink-45);
}

/* wisknop zonder cirkel, zoals op de iPhone */
.login-code__pad .login-code__wis { background: transparent; }

.login-form__veld:focus { border-color: var(--acc); }

/* eigen veldkeuring: het veld krijgt de roze rand en er komt een ballon
   onder te hangen. Die zweeft — JS zet zijn top — zodat de velden en de
   knop nooit verspringen. Harde hoeken, geen schaduw, zoals overal. */
.login-form__veld.is-fout { border-color: var(--acc2); }
.veldfout {
  position: absolute;
  z-index: 3;
  left: 0;
  max-width: 100%;
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 9px 12px;
  background: var(--acc-ink);
  color: #FBFBFA;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.4;
  /* de ballon mag de knop eronder nooit blokkeren */
  pointer-events: none;
  animation: veldfoutIn 0.18s ease both;
}
/* het uitroepteken in de accentkleur */
.veldfout::before {
  content: '!';
  flex: 0 0 auto;
  color: var(--acc2);
  font-weight: 600;
}
/* het puntje wijst omhoog naar het veld */
.veldfout::after {
  content: '';
  position: absolute;
  bottom: 100%;
  left: 14px;
  border: 6px solid transparent;
  border-bottom-color: var(--acc-ink);
}
@keyframes veldfoutIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .veldfout { animation-duration: 0.01ms; }
}

.login-form__knop {
  border: none;
  cursor: pointer;
  font: inherit;
  font-size: 14.5px;
  font-weight: 500;
  text-align: center;
  margin-top: 12px; /* ademruimte boven de knop, bovenop de formulier-gap */
}

/* berichtveld (textarea) en het berichtformulier in het contactpaneel */
.login-form__veld--bericht {
  resize: none; /* vast formaat */
  height: 180px;
  line-height: 1.5;
}

/* het contactpaneel zet kinderen op shrink-to-fit; het formulier moet juist breed */
.login-form--contact {
  width: 100%;
  max-width: 640px;
}

/* toestemmings-checkbox */
/* ============ het berichtvak na versturen ============
   De velden verdwijnen en het bericht komt op hun plek in beeld, in het
   gewone lettertype — geen kleine mono-regel meer onder de knop. De
   eyebrow en de sluitknop van het venster blijven staan. */
.formbericht { display: none; }
/* De bevestiging is overal hetzelfde kleine venster — alleen de tekst
   verschilt. Ook het brede contactvenster krimpt hiernaartoe. */
.panel__inner[data-verstuurd] {
  max-width: 440px;
  min-height: 0;
  padding-bottom: clamp(24px, 3vw, 36px);
}
[data-verstuurd] .formbericht {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  width: 100%;
  min-height: 168px;
  padding: 16px 0;
  text-align: center;
  animation: formberichtIn 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}
[data-verstuurd] [data-formvak] { display: none; }
.formbericht__tekst {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(20px, 1.8vw, 27px);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.25;
  color: var(--ink);
  max-width: 22ch;
}
.formbericht__opnieuw {
  border: 0;
  padding: 0;
  background: none;
  font-family: inherit;
  font-size: 15px;
  color: var(--ink-55);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.formbericht__opnieuw:hover { color: var(--ink); }
@keyframes formberichtIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  [data-verstuurd] .formbericht { animation-duration: 0.01ms; }
}

/* op mobiel opent het login-venster bovenaan: zo duwt het toetsenbord
   het venster niet omhoog en blijft de pagina op zijn plek */
@media (max-width: 700px) {
  .panel--boven.is-open {
    align-items: flex-start;
    /* zelfde lucht boven als opzij, zodat het venster nooit achter het menu valt */
    padding-top: clamp(16px, 4vw, 48px);
  }
  .panel--boven .panel__inner { margin-top: 0; }
}

/* ============ donkere overlays ("backstage") ============
   Geldt in het wit/zwart-thema én bij een puur witte achtergrond: de pagina
   zelf blijft licht, alle overlay-panelen volgen het filmpaneel — achtergrond
   #111110, basistekst #FBFBFA. De overlay-schakelaar in het kleurenpaneel zet
   ze desgewenst weer licht (.overlay-wit).
   De inkt-tokens worden hier lokaal opnieuw gezet — custom properties erven
   hun op :root berekende waarde, dus alleen --ink-rgb omzetten zou de tinten
   niet meenemen. */
html.thema-blokken:not(.overlay-wit) .panel__inner,
html.thema-zwartwit:not(.overlay-wit) .panel__inner {
  --ink: #FBFBFA;
  --ink-zacht: var(--ink);
  --ink-rgb: 251, 251, 250;
  --ink-75: rgba(251, 251, 250, 0.78);
  --ink-65: rgba(251, 251, 250, 0.7);
  --ink-60: rgba(251, 251, 250, 0.62);
  --ink-55: rgba(251, 251, 250, 0.55);
  --ink-45: rgba(251, 251, 250, 0.45);
  --ink-35: rgba(251, 251, 250, 0.35);
  --hairline: rgba(251, 251, 250, 0.16);
  --hairline-row: rgba(251, 251, 250, 0.16);
  --panel-bg: #000000;
  --vlak-placeholder: #1B1B19;
  color: var(--ink);
}

/* sluitknop: witte rand; hover licht op via de lokale --ink-rgb */
html.thema-blokken:not(.overlay-wit) .panel__inner .panel__close,
html.thema-zwartwit:not(.overlay-wit) .panel__inner .panel__close { border-color: rgba(251, 251, 250, 0.3); }

/* outline-knoppen: witte rand + witte tekst */
html.thema-blokken:not(.overlay-wit) .panel__inner .panel__ghost,
html.thema-zwartwit:not(.overlay-wit) .panel__inner .panel__ghost {
  color: #FBFBFA;
  border-color: rgba(251, 251, 250, 0.3);
}

/* invoervelden (login, demo, afspraak, contact) */
html.thema-blokken:not(.overlay-wit) .panel__inner .login-form__veld,
html.thema-zwartwit:not(.overlay-wit) .panel__inner .login-form__veld {
  background: #1B1B19;
  border-color: rgba(251, 251, 250, 0.3);
}

/* ============ lara-venster (live demo) ============
   Zelfde kader als het filmpaneel; zolang de LiveAvatar-omgeving er
   niet is draait de loopvideo als plaatshouder, met de belofte eroverheen. */
.laraframe {
  position: relative;
  background: #000000;
}

.laraframe__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* leesbare voet over het beeld, in de taal van de PiP-kaart */
/* ============ het formulier in het Lara-kader ============
   Het staat meteen open, links in beeld, op wit papier zoals de andere
   formuliervensters. Na versturen komt de gespreksstand op dezelfde plek.
   Zonder JS blijft het gewoon een formulier dat naar Netlify post. */
.laraframe__paneel {
  position: absolute;
  z-index: 2;
  left: clamp(20px, 3vw, 56px);
  top: 50%;
  transform: translateY(-50%);
  width: min(400px, 44%);
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: clamp(24px, 2.4vw, 38px);
  background: #FFFFFF;
  color: var(--ink);
}



.laraframe__paneel .path-label { margin: 0; }
/* het formulier zit nu ín het paneel; de bovenmarge komt van het paneel */
.laraframe__form { margin-top: 0; gap: 10px; }
.laraframe__paneel .formbericht { min-height: 132px; padding: 12px 0; }
.laraframe__paneel .formbericht__tekst { font-size: clamp(19px, 1.6vw, 24px); }

/* Lara offline (kill switch in The Synths® Insights): de melding staat midden
   in het kader, zonder eyebrow, met een korte subtekst eronder */
.laraframe__paneel.is-offline { left: 50%; transform: translate(-50%, -50%); }
.laraframe__paneel.is-offline > .path-label { display: none; }
.formbericht__sub {
  margin: 0;
  max-width: 34ch;
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink-55);
}
.formbericht__sub[hidden] { display: none; }

.laraframe__paneel-titel {
  /* de introzin eronder is weg, dus de titel maakt zelf de ruimte naar het
     eerste veld; de paneel-gap van 10px is daarvoor te krap */
  margin: 4px 0 20px;
  font-family: var(--font-display);
  font-size: clamp(21px, 1.9vw, 30px);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--ink);
}

.laraframe__paneel-intro {
  margin: 0 0 6px;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink-75);
}

.laraframe__paneel .login-form__knop { margin-top: 4px; }

/* Een gesprek kan publiek nog niet: de velden blijven gewoon staan, de
   knop staat gedempt met de melding erop. Het script zet hem ook echt op
   disabled, dus hij is niet alleen grijs maar ook dood. */
.laraframe__paneel--binnenkort .login-form__knop {
  opacity: 0.4;
  cursor: not-allowed;
}
/* de melding staat op de knop zelf, in plaats van het gewone opschrift */
.laraframe__binnenkort { display: none; }
.laraframe__paneel--binnenkort .login-form__knoptekst { display: none; }
.laraframe__paneel--binnenkort .laraframe__binnenkort { display: inline; }



/* zodra het gesprek begint valt het formulierpaneel weg: de verbinding
   komt op deze plek in beeld, zonder tussenscherm */
/* Lara vult haar kader: geen lijstje eromheen zoals bij de film. Het beeld
   ís hier het venster, en tijdens het gesprek helemaal. */
.panel__inner--film.panel__inner--lara { --film-rand: 0px; }

/* de disclaimer neemt de plek van het formulier in, in hetzelfde venster.
   JS zet de hoogte vast zodat het paneel niet verspringt. */
.laraframe__akkoord { display: flex; flex-direction: column; gap: 10px; flex: 1; min-height: 0; }
/* het paneel houdt de maat van het formulier (JS zet de hoogte); past de
   tekst er in een taal niet in, dan scrolt het tekstvak en blijven de
   knoppen precies waar 'Start gesprek' stond */
.laraframe__paneel.is-akkoord { overflow: hidden; }
.laraframe__akkoordtekst { display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: thin; margin-bottom: 58px; /* ruimte voor de vastgepinde knoppenrij */ }
.laraframe__akkoord[hidden] { display: none; }
.laraframe__akkoord .path-label { margin: 0; }
/* eigen stijl, niet die van de introregel: die wordt op smal verborgen en
   de disclaimer hoort daar juist te staan */
.laraframe__disclaimer {
  margin: 4px 0 0;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink-75);
}
.laraframe__disclaimer a { color: inherit; text-underline-offset: 3px; }

/* in de disclaimerstand draagt dit blok zijn eigen eyebrow */
.laraframe__paneel.is-akkoord > .path-label,
.laraframe__paneel.is-akkoord .formbericht { display: none; }

/* de knoprij zakt naar onderen: auto-marge zet hem op dezelfde hoogte als
   de knop in het formulier, die daar ook tegen de onderrand staat */
.laraframe__akkoordknoppen {
  /* vastgepind aan de onderrand van het paneel, op dezelfde afstand als de
     knop 'Start gesprek' in het formulier: wat er ook laadt of meet, deze
     rij kan nergens anders staan */
  position: absolute; left: clamp(24px, 2.4vw, 38px); right: clamp(24px, 2.4vw, 38px); bottom: clamp(24px, 2.4vw, 38px);
  display: flex; gap: 10px;
}
.laraframe__akkoordknoppen > * { flex: 1 1 0; min-width: 0; }

/* Starten is de primaire actie; Annuleren staat ernaast in dezelfde maat,
   maar als omlijnd vlak in plaats van gevuld */
.laraframe__starten {
  width: auto;
  height: 48px;
}
.laraframe__annuleer {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  padding: 0 16px;
  border: 1px solid rgba(var(--ink-rgb), 0.25);
  border-radius: 0;
  background: transparent;
  font-family: inherit;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 0.25s ease;
}
.laraframe__annuleer:hover { border-color: var(--ink); }

.laraframe.is-gesprek .laraframe__paneel { display: none; }

/* de live demo zelf: draait op /lara en vult het hele kader. Same-origin,
   dus de app mag gewoon de microfoon gebruiken */
/* de app ligt bovenop, maar is onzichtbaar tot de stream er is: zolang hij
   laadt zie je de laadvideo van de site erdoorheen (de app maakt zichzelf
   transparant met ?laad=site). Zodra de stream binnen is vloeit hij in. */
.laraframe__app { position: absolute; inset: 0; z-index: 3; width: 100%; height: 100%; border: 0; display: block; background: transparent; opacity: 0; transition: opacity 0.7s ease; }
/* de app komt achter het zwart tevoorschijn, dus zonder eigen overvloei */
.laraframe__app.is-klaar { opacity: 1; transition: none; }

/* de laadvideo ligt over de pratende loop; aan/uit gebeurt achter het zwart */
.laraframe__laadvideo { z-index: 1; opacity: 0; }
.laraframe.is-laden .laraframe__laadvideo { opacity: 1; }

/* zwart voor de scènewissels: vlot erin (0,18 s), iets langzamer eruit */
.laraframe__zwart { position: absolute; inset: 0; z-index: 4; background: #000000; opacity: 0; pointer-events: none; transition: opacity 0.25s ease; }
.laraframe.is-zwart .laraframe__zwart { opacity: 1; transition-duration: 0.18s; }

/* Laadlijn: een dunne streep onderlangs het kader die heen en weer loopt.
   Geen vorm die om aandacht vraagt, wel onmiskenbaar beweging, en in dezelfde
   taal als de balkjes onder de vensters in de app. Hij verschijnt pas als zij
   is aangelopen en de verbinding er nog niet is. */
/* Zolang zij bij het raam staat draait hier een ring in de accentkleur. De
   dunne lijn onderaan die hier eerst stond viel te weinig op: op een bewegend
   beeld zag je hem nauwelijks. Hij verdwijnt op het moment dat zij gaat lopen,
   want dan is de beweging zelf het teken dat het zover is. */
.laraframe__spinner,
.filmframe__spinner {
  position: absolute; left: 50%; top: 50%; z-index: 3;
  width: 46px; height: 46px; margin: -23px 0 0 -23px;
  border: 4px solid rgba(251, 251, 250, 0.22);
  border-top-color: var(--acc);
  border-radius: 50%;
  opacity: 0; transition: opacity 0.3s ease; pointer-events: none;
  /* op een licht beeld zou een cyaan ring anders wegvallen */
  filter: drop-shadow(0 1px 6px rgba(8, 22, 40, 0.45));
  animation: laraSpin 0.85s linear infinite;
}
.laraframe.is-wacht .laraframe__spinner,
.filmpanel__frame.is-wacht .filmframe__spinner { opacity: 1; }
@keyframes laraSpin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .laraframe__spinner,
  .filmframe__spinner { animation-duration: 2.4s; }
}
/* de disclaimertekst laat onderin zien dat er meer staat (alleen als hij
   scrolt: JS zet is-scrolt en haalt de fade weg op de bodem) */
.laraframe__akkoordtekst.is-scrolt:not(.is-onderin) {
  -webkit-mask-image: linear-gradient(#000 calc(100% - 30px), transparent);
  mask-image: linear-gradient(#000 calc(100% - 30px), transparent);
}

/* de titel van de uitwijk: dezelfde maat en letter als de titel in het
   formulierpaneel ('Praat met Lara over…'), maar in wit op het beeld */
/* stille knop: de live demo is de hoofdroute, dit is het alternatief */
@media (max-width: 700px) {
  /* smal: Lara staat rechtop. Haar loop vult het kader (cover), dus een
     staand paneel levert geen lege vlakken op — de film blijft 16:9,
     want die zou in een staand vak juist balken krijgen */
  /* compound: .panel__inner--film zet de verhouding met dezelfde
     specificiteit en staat verderop in het bestand */
  .panel__inner--film.panel__inner--lara { --film-b: 9; --film-h: 16; }
  /* smal: het formulier vult de breedte en staat bovenin, de uitwijk
     eronder — naast elkaar past hier niets */
  .laraframe__paneel {
    left: 12px;
    right: 12px;
    top: 12px;
    width: auto;
    transform: none;
    gap: 8px;
    padding: 18px;
  }
  .laraframe__akkoordknoppen { left: 18px; right: 18px; bottom: 18px; }
  .laraframe__paneel-intro { display: none; }
  .laraframe__paneel .login-form__veld { padding: 11px 13px; }
  /* offline: over de volle breedte, verticaal in het midden */
  .laraframe__paneel.is-offline { left: 12px; right: 12px; top: 50%; transform: translateY(-50%); }
}

/* Het formulier bij Lara is op mobiel een venster zoals de andere
   (Maak een afspraak): het zweeft bovenin het scherm, met dezelfde marges
   en schaduw, óver het kader van Lara in plaats van erin opgesloten. Zo
   wordt het breder en staat het hoger, en blijft zij eronder in beeld.
   Let op: panelIn animeert transform en blijft met fill 'both' van kracht,
   en zolang dat zo is vangt het venster elk fixed element als een gewoon
   kader. Het Lara-venster fadet op mobiel daarom alleen in; het formulier
   krijgt zelf de bekende opwaartse beweging. */
@media (max-width: 700px) {
  .panel__inner--film.panel__inner--lara { animation-name: laraVensterIn; }

  .panel__inner--lara .laraframe__paneel {
    animation: panelIn 0.4s cubic-bezier(0.32, 0.72, 0.28, 1) 0.06s both;
    position: fixed;
    top: clamp(16px, 4vw, 48px);
    left: clamp(16px, 4vw, 48px);
    right: clamp(16px, 4vw, 48px);
    width: auto;
    transform: none;
    z-index: 5;
    max-height: calc(var(--scherm-h, 100svh) - 2 * clamp(16px, 4vw, 48px));
    overflow-y: auto;
    /* bovenin ruimte voor het kruis, net als in het afspraakvenster: de titel
       begint pas onder de onderrand van het kruis */
    padding: 52px clamp(24px, 5vw, 64px) 28px;
    box-shadow: 0 24px 80px rgba(20, 20, 18, 0.35);
  }

  /* in de voorwaardenstap zet JS een vaste hoogte en scrolt alleen de
     tekst; het venster zelf mag dan niet scrollen, anders schuiven de
     vastgepinde knoppen mee */
  .panel__inner--lara .laraframe__paneel.is-akkoord { overflow: hidden; }
  /* offline: het zwevende venster bovenin, net als het formulier */
  .panel__inner--lara .laraframe__paneel.is-offline {
    left: clamp(16px, 4vw, 48px);
    right: clamp(16px, 4vw, 48px);
    top: clamp(16px, 4vw, 48px);
    transform: none;
  }

  .panel__inner--lara .laraframe__akkoordknoppen {
    left: clamp(24px, 5vw, 64px);
    right: clamp(24px, 5vw, 64px);
    bottom: 24px;
  }

  /* het kruis hoort bij het venster: rechtsboven op het witte vlak, in de
     stijl van de andere vensters. Tijdens het gesprek is het formulier weg
     en keert het terug naar zijn plek op het beeld. */
  .panel__inner--lara:not(:has(.laraframe.is-gesprek)) .panel__close--film {
    position: fixed;
    top: calc(clamp(16px, 4vw, 48px) + 24px);
    right: calc(clamp(16px, 4vw, 48px) + 24px);
    z-index: 6;
    color: var(--ink);
    background: transparent;
    border-color: rgba(var(--ink-rgb), 0.2);
  }
}

/* Lara op mobiel in beeld houden. De films zijn 16:9, het kader staat
   rechtop (9:16): van het beeld is maar een derde te zien. In het midden
   uitsnijden liet alleen de kamer zien, want zij staat rechts bij het raam.
   De uitsnede ligt daarom rechts. Loopt ze na het laden naar je toe, dan
   schuift de uitsnede rustig mee naar het midden, zodat ze gecentreerd zit
   op het moment dat ze gaat zitten. Tijden volgen de laadfilm (7,04 s):
   tot halverwege staat of loopt ze rechts, rond 90% zit ze in het midden. */
@media (max-width: 700px) {
  .laraframe__video { object-position: 96% 50%; }

  .laraframe.is-laden .laraframe__laadvideo {
    animation: laraFocusNaarMidden 7.04s linear both;
  }
}

@keyframes laraVensterIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes laraFocusNaarMidden {
  0%, 50% { object-position: 96% 50%; animation-timing-function: cubic-bezier(0.45, 0, 0.35, 1); }
  90%, 100% { object-position: 50% 50%; }
}

@media (max-width: 700px) and (prefers-reduced-motion: reduce) {
  /* geen meeschuivend beeld: meteen de eindstand, waar zij zit */
  .laraframe.is-laden .laraframe__laadvideo { animation: none; object-position: 50% 50%; }
}

/* film-paneel: staat op het witte papier zoals de andere overlays —
   alleen de studioviewer houdt zijn backstage-zwart */

/* net zo ruim als de studioviewer: die vult de viewport minus dezelfde
   zijmarge (48px) en laat onderaan ruimte voor het dock */
.panel__inner--film {
  /* het paneel neemt de verhouding van het beeld erin over, in plaats van
     een vast vak van bijna de hele viewport te zijn. Op een breed scherm
     stonden er anders vlakken wit naast een 16:9-kader. Wat overblijft is
     de rand hieronder — een lijstje, geen vlak.
     content-box: de aspect-ratio slaat zo op het beeld zelf, waardoor de
     rand aan alle vier de kanten even breed is */
  --film-b: 16;
  --film-h: 9;
  --film-rand: clamp(10px, 1.2vw, 16px);
  box-sizing: content-box;
  background: var(--panel-bg);
  max-width: none;
  width: min(
    calc(100vw - 48px - 2 * var(--film-rand)),
    calc((100vh - 136px - 2 * var(--film-rand)) * var(--film-b) / var(--film-h))
  );
  height: auto;
  aspect-ratio: var(--film-b) / var(--film-h);
  padding: var(--film-rand);
  display: flex;
  flex-direction: column;
  overflow: hidden; /* nooit een scrollbar; de video schaalt mee */
}

/* De Synths-film houdt zijn venstermaat, maar zonder lijst eromheen:
   het beeld loopt tot de rand, net als het kader waarin straks met Lara
   gepraat wordt. --film-rand op 0 haalt de padding en daarmee de rand weg;
   de 16:9-maatvoering hierboven blijft gewoon staan. */
#panel-film .panel__inner--film {
  --film-rand: 0px;
  background: var(--film-video-bg);
}

/* Op een staand telefoonscherm is het filmvenster een klein 16:9-vlak midden
   op het zwart: daar lag het kruisje óver het beeld. Boven het kader is
   ruimte zat, dus daar hangt het. Alleen bij de film, en alleen staand —
   liggend vult het kader het scherm en is er geen plek boven. */
@media (max-width: 700px) and (orientation: portrait) {
  #panel-film .panel__inner--film { overflow: visible; }
  #panel-film .panel__close--film {
    top: -54px;
    right: 0;
  }
  /* de knop voor volledig scherm gaat mee omhoog, naast het kruisje — maar
     alleen zolang we niet ín volledig scherm zitten: daar is het kader het
     hele scherm en zou de knop erbuiten vallen */
  #panel-film .filmpanel__frame:not(:fullscreen) { overflow: visible; }
  #panel-film .filmpanel__frame:not(:fullscreen) .filmvol { top: -54px; right: 54px; }
  #panel-film .filmpanel__frame:not(:-webkit-full-screen) { overflow: visible; }
  #panel-film .filmpanel__frame:not(:-webkit-full-screen) .filmvol { top: -54px; right: 54px; }
  /* de AI-melding gaat mee omhoog, maar dan links: zo staat boven het beeld
     links de melding en rechts de twee knoppen, en blijft de film zelf vrij */
  #panel-film .filmpanel__frame:not(:fullscreen) .filmframe__ai { top: -43px; left: 0; }
  #panel-film .filmpanel__frame:not(:-webkit-full-screen) .filmframe__ai { top: -43px; left: 0; }
}

/* het kruis zweeft boven de film, rechtsboven in het paneel */
.panel__close--film {
  position: absolute;
  /* net binnen het beeld, niet op de witte rand */
  top: calc(var(--film-rand) + 12px);
  right: calc(var(--film-rand) + 12px);
  z-index: 2;
  border-color: rgba(251, 251, 250, 0.3);
  color: #FBFBFA;
  /* leesbaar op elk filmbeeld, zonder een balk te introduceren */
  background: rgba(13, 13, 12, 0.45);
}

.filmpanel__stage {
  flex: 1;
  min-height: 0; /* laat de stage krimpen binnen het venster i.p.v. overflowen */
  display: flex;
  align-items: center;
  justify-content: center;
  /* de rand zit op het paneel zelf, hier niets meer bij */
  padding: 0;
}

.filmpanel__frame {
  /* het kader vult het paneel: dat heeft de verhouding van het beeld al */
  position: relative; /* anker voor de spinner en de ondertitels */
  width: 100%;
  height: 100%;
  border: none; /* geen omlijning: de film ís het paneel */
  border-radius: 0;
  background: var(--film-video-bg);
  overflow: hidden;
}

.filmpanel__frame video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover; /* alleen de loop van Lara nog; die vult het kader */
  background: var(--film-video-bg);
}

/* plaatshouder in het filmvenster zolang de film er niet is; zelfde opzet
   als het Lara-kader ernaast */
/* Twee knoppen over de film, alleen op smalle schermen (zie index.html). */
.filmknoppen { display: none; }

@media (max-width: 700px) {
  .hero__intro { display: none; }
  .filmknoppen {
    display: flex;
    gap: 8px;
    position: absolute;
    left: 12px;
    right: 12px;
    bottom: 12px;
    z-index: 3;
  }
  .filmknop {
    flex: 1 1 0;
    min-width: 0;
    border: 0;
    padding: 13px 10px;
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -0.01em;
    cursor: pointer;
    /* harde hoeken, zoals overal in het merk */
    border-radius: 0;
    background: rgba(0, 0, 0, 0.82);
    color: var(--paper);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
  }
  .filmknop--acc {
    background: var(--acc);
    color: var(--acc-ink);
  }
}

/* De ondertitels bij de film tekenen we zelf: script.js leest de regels uit
   het vtt-spoor en zet ze hieronder. Zo houdt de speler een schone balk (een
   ondertitelspoor zou er een instellingenmenu bij zetten, en de taal komt al
   van de site) en bepalen we zelf de plek: JS zet --ondertitel-b, zodat de
   regel onderin het beeld staat maar altijd boven de bedieningsbalk blijft.
   Strak vlak achter de letters, harde hoeken, zoals overal in het merk. */
.filmframe__ondertitel {
  position: absolute;
  left: 50%;
  bottom: var(--ondertitel-b, 12%);
  transform: translateX(-50%);
  z-index: 2;
  width: min(88%, 44em);
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s linear;
}

.filmframe__ondertitel.is-aan { opacity: 1; }

.filmframe__ondertitel span {
  /* elke regel een eigen vlak, precies zo breed als de tekst */
  display: table;
  margin: 2px auto 0;
  padding: 0.14em 0.44em;
  background: rgba(0, 0, 0, 0.78);
  color: #FBFBFA;
  font-family: var(--font-display);
  font-size: var(--ondertitel-fs, 18px);
  line-height: 1.35;
  border-radius: 0;
}

/* Volledig scherm zetten we op het kader en niet op de video zelf, anders
   valt onze ondertitel erbuiten (zie script.js). De knop van de speler zou
   alleen de video pakken; die staat daarom uit en we zetten er zelf een naast
   het kruisje, binnen het kader zodat hij in volledig scherm mee is. */
.filmframe__video::-webkit-media-controls-fullscreen-button { display: none !important; }

.filmpanel__frame:fullscreen,
.filmpanel__frame:-webkit-full-screen {
  width: 100%;
  height: 100%;
  background: #000000;
}

/* De AI-melding over de film: mono-label linksboven, klein en rustig. Hij
   staat er de hele film, zodat iedereen hem bij het eerste beeld ziet. */
.filmframe__ai {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 2;
  /* ruim genoeg voor één regel; wordt hij toch langer, dan breekt hij af */
  max-width: min(72%, 34em);
  width: fit-content;
  margin: 0;
  padding: 5px 8px;
  background: rgba(0, 0, 0, 0.5);
  color: rgba(251, 251, 250, 0.82);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  line-height: 1.35;
  text-transform: uppercase;
  /* harde hoeken, en klikken gaat door naar de speler */
  border-radius: 0;
  pointer-events: none;
}

@media (max-width: 700px) {
  .filmframe__ai {
    top: 10px;
    left: 10px;
    max-width: 56%; /* nooit tot aan de knoppen rechtsboven */
    padding: 4px 6px;
    font-size: 9px;
    letter-spacing: 0.04em;
  }
}

/* ============ onze eigen bedieningsbalk bij de film ============
   De balk van de browser was niet te kleuren (het afgespeelde deel blijft
   wit, wat je ook probeert) en zette er op een telefoon knoppen bij voor
   casten en instellingen. Deze balk is van ons: voortgang in de accentkleur,
   verder niets. script.js haalt het controls-attribuut van de video af zodra
   hij bestaat; laadt het script niet, dan blijft de browserbalk staan. */
.filmbalk {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 26px 16px 12px;
  /* leesbaar op elk filmbeeld, zonder een harde balk te introduceren */
  background: linear-gradient(to top, rgba(0, 0, 0, 0.72), rgba(0, 0, 0, 0));
  opacity: 1;
  transition: opacity 0.25s ease;
}

/* tijdens het spelen verdwijnt de balk als je de muis stilhoudt */
.filmpanel__frame.is-rust .filmbalk {
  opacity: 0;
  pointer-events: none;
}

.filmbalk__knop {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: #FBFBFA;
  cursor: pointer;
}

.filmbalk__knop:hover { color: var(--acc); }
.filmbalk svg[hidden] { display: none; }

.filmbalk__tijd {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.02em;
  color: rgba(251, 251, 250, 0.85);
  font-variant-numeric: tabular-nums;
}

.filmbalk__spoor {
  position: relative;
  flex: 1 1 auto;
  height: 16px; /* ruim aanraakgebied; de lijn zelf is dun */
  cursor: pointer;
  touch-action: none;
}

.filmbalk__spoor::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 7px;
  height: 2px;
  background: rgba(251, 251, 250, 0.28);
}

/* wat er al gebufferd is, iets lichter dan het lege spoor */
.filmbalk__geladen {
  position: absolute;
  left: 0;
  top: 7px;
  height: 2px;
  width: 0;
  background: rgba(251, 251, 250, 0.45);
}

.filmbalk__gevuld {
  position: absolute;
  left: 0;
  top: 7px;
  height: 2px;
  width: 0;
  background: var(--acc);
}

.filmbalk__greep {
  position: absolute;
  right: -5px;
  top: -4px;
  width: 10px;
  height: 10px;
  background: var(--acc);
  /* harde hoeken, zoals overal */
  border-radius: 0;
}

.filmbalk__spoor:focus-visible { outline: 2px solid var(--acc); outline-offset: 3px; }

@media (max-width: 700px) {
  .filmbalk { gap: 10px; padding: 22px 12px 10px; }
  .filmbalk__tijd { font-size: 11px; }
}

.filmvol {
  position: absolute;
  top: 12px;
  right: 60px;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid rgba(251, 251, 250, 0.3);
  border-radius: 50%;
  /* leesbaar op elk filmbeeld, net als het kruisje ernaast */
  background: rgba(13, 13, 12, 0.45);
  color: #FBFBFA;
  cursor: pointer;
}

.filmvol:hover { background: rgba(13, 13, 12, 0.7); }

/* één van de twee iconen tegelijk; een algemene regel elders zet svg's op
   display:block en wint het anders van het hidden-attribuut */
.filmvol svg[hidden] { display: none; }

/* op de iPhone neemt de systeemspeler het beeld over; daar toont iOS de
   ondertitels zelf (script.js zet het spoor dan even op subtitles) */
.filmframe__video::cue {
  background-color: rgba(0, 0, 0, 0.78);
  color: #FBFBFA;
  font-family: var(--font-display);
  font-size: 0.95em;
  line-height: 1.35;
}

/* de lus achter de filmtegel: vult de tegel, staat achter de scrim en de copy */
.filmtile__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  pointer-events: none;
}

/* de film vult het kader; zwart eromheen als de verhouding niet precies past */
.filmframe__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000000;
}

.filmframe__overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: clamp(24px, 3vw, 46px);
  background: linear-gradient(transparent 45%, rgba(13, 13, 12, 0.72));
}

.filmframe__label {
  margin: 0 0 10px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--acc);
}

.filmframe__titel {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.02em;
  font-size: clamp(23px, 2.4vw, 38px);
  line-height: 1.12;
  color: #FBFBFA;
}

/* ============ knop-hover: één korte signaalstoring ============ */

/* alle knoppen en button-achtige links krijgen op hover één subtiele
   1–2px glitch (niet loopend) — bewust zonder kleurverandering */
/* levende knoppen: een subtiele lift bij hover en licht indrukken bij klik
   (verving de btnGlitch-shake — rustiger, en elk klikmoment voelt bewuster).
   De veer-curve geeft nét een beetje overshoot. */
.hero__lees,
.yourbrand,
.voorwie__placeholder,
.hero__route,
.cta__demo,
.cta__contact,
.dock__cta,
.panel__demo,
.panel__ghost,
.rolkaart--open {
  transition:
    transform 0.32s cubic-bezier(0.34, 1.3, 0.4, 1),
    border-color 0.25s ease,
    background-color 0.3s ease,
    color 0.3s ease;
}

.hero__lees:hover,
.yourbrand:hover,
.voorwie__placeholder:hover,
.hero__route:hover,
.cta__demo:hover,
.cta__contact:hover,
.dock__cta:hover,
.panel__demo:hover,
.panel__ghost:hover,
.rolkaart--open:hover,
.rolkaart--open:focus-visible {
  transform: scale(1.02);
}

.hero__lees:active,
.yourbrand:active,
.voorwie__placeholder:active,
.hero__route:active,
.cta__demo:active,
.cta__contact:active,
.dock__cta:active,
.panel__demo:active,
.panel__ghost:active,
.rolkaart--open:active {
  transform: scale(0.97);
  transition-duration: 0.1s;
}

/* ronde icoonknoppen: iets meer lift, want ze zijn klein */
.panel__close,
.sviewer__pijl {
  transition:
    transform 0.32s cubic-bezier(0.34, 1.3, 0.4, 1),
    border-color 0.25s ease,
    background-color 0.3s ease;
}

.panel__close:hover,
.sviewer__pijl:hover { transform: scale(1.08); }

.panel__close:active,
.sviewer__pijl:active {
  transform: scale(0.92);
  transition-duration: 0.1s;
}

@media (prefers-reduced-motion: reduce) {
  .hero__lees:hover, .hero__lees:active,
  .yourbrand:hover, .yourbrand:active,
  .voorwie__placeholder:hover, .voorwie__placeholder:active,
  .hero__route:hover, .hero__route:active,
  .cta__demo:hover, .cta__demo:active,
  .cta__contact:hover, .cta__contact:active,
  .dock__cta:hover, .dock__cta:active,
  .panel__demo:hover, .panel__demo:active,
  .panel__ghost:hover, .panel__ghost:active,
  .panel__close:hover, .panel__close:active,
  .sviewer__pijl:hover, .sviewer__pijl:active,
  .hero__lees:hover .hero__lees-icoon {
    transform: none;
  }
}

/* ============ knoppen: awwwards-stijl ============
   Inter Tight in sentence-case, 8px afronding en 48px hoog. De kleuren
   blijven contextbewust (accent op licht, wit/outline op donker). */
.hero__lees,
.cta__demo,
.cta__contact,
.panel__demo,
.panel__ghost {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.005em;
  text-transform: none;
  border-radius: 0;
  height: 48px;
}

/* hover: geen kleurwissel — alle knoppen groeien alleen een tikje
   (de scale-lift hierboven); elke knop houdt zijn eigen vlak */

/* de kleur van het studiolicht is een geregistreerde property: alleen
   dan kan de browser hem interpoleren en fadet de wissel tussen de twee
   merkkleuren in plaats van te springen */
@property --bundel {
  syntax: '<color>';
  inherits: true;
  initial-value: #64D0EB;
}

/* ============ studio-viewer: fullscreen carrousel in studiosetting ============ */

.sviewer {
  /* de lichtkleur fadet naar de kant van de nieuwe synth */
  transition: --bundel 0.7s ease;
  /* portrethoogte en slidebreedte: foto (3:4) + call sheet ernaast.
     Ruimer dan voorheen: de call sheet is even hoog als de foto, dus
     een groter portret geeft de casetekst direct meer ruimte. */
  --ph: min(62vh, 560px, 72vw);
  /* waar de smalle spotkegel en de vloercirkel op richten: op desktop de
     cutout rechts van de case (zie de 700px-query), op mobiel het midden */
  --spotX: 50%;
  /* nooit breder dan de stage in het venster: viewport minus de
     overlay-padding links/rechts, met wat lucht */
  --iw: min(calc(var(--ph) * 0.75 + 400px), calc(100vw - 2 * clamp(16px, 4vw, 48px) - 28px));
  position: fixed;
  inset: 0;
  z-index: 55; /* onder het dock (60): het menu blijft zichtbaar */
  display: flex;
  /* de backdrop komt van .panelfx, zodat de ruis doorloopt bij wisselen */
  /* extra ruimte onderaan zodat het venster boven het zwevende menu eindigt */
  padding: clamp(16px, 4vh, 40px) clamp(16px, 4vw, 48px) 96px;
}

.sviewer[hidden] { display: none; }

/* het venster zelf: de studio leeft hierbinnen */
.sviewer__venster {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #000000;
  border-radius: 0;
  overflow: hidden;
  box-shadow: 0 24px 80px rgba(20, 20, 18, 0.35);
  color: #FBFBFA;
  /* zelfde openingsritme als de panels: backdrop eerst, venster een tel later */
  animation: panelIn 0.4s cubic-bezier(0.32, 0.72, 0.28, 1) 0.06s both;
}

/* ---- studiosetting (cyclorama): alle lagen puur decor ---- */

.sviewer__studio {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.sviewer__studio > div { position: absolute; }

/* doek: lichte kern hoog in het midden die rondom wegvalt in het donker */
.sviewer__doek {
  inset: 0;
  background: radial-gradient(ellipse 130% 100% at 50% 24%, rgba(60, 60, 56, 0.9), rgba(23, 23, 21, 0.5) 52%, transparent 76%);
}

/* vloer-verloop onderin */
.sviewer__vloer {
  left: 0;
  right: 0;
  bottom: 0;
  height: 32%;
  background: linear-gradient(transparent, rgba(5, 5, 4, 0.6));
}

/* breed top-spot + smalle spotkegel op het midden */
.sviewer__spot { inset: 0; }

.sviewer__spot--breed {
  background: radial-gradient(ellipse 58% 78% at 50% -12%, rgba(251, 251, 250, 0.38), rgba(251, 251, 250, 0.08) 46%, transparent 66%);
  /* eerst opflikkeren als een lamp, dán pas ademen */
  animation: lampAan 0.55s steps(1) 0.1s both, spotAdem 5.5s ease-in-out 0.7s infinite;
  /* zachte tegendrift bij een wissel (trager/subtieler dan de main-kegel) */
  translate: var(--licht-par, 0px) 0;
  transition: translate 1.6s cubic-bezier(0.2, 0.6, 0.2, 1);
}

.sviewer__spot--smal {
  /* de kegel staat niet in het midden maar op de cutout: de spot "vindt" hem.
     Het zwaartepunt ligt hoog — op het gezicht, niet op de vloer */
  background: radial-gradient(ellipse 30% 92% at var(--spotX, 50%) -18%, rgba(251, 251, 250, 0.56), rgba(251, 251, 250, 0.11) 48%, transparent 68%);
  animation: lampAan 0.5s steps(1) 0.2s both, spotAdem 4.2s ease-in-out 0.75s infinite;
  /* bij een switch drijft de kegel heel even mee met de cutout-parallax
     (--spot-par uit script.js), met dezelfde na-ijl-curve als de cutout */
  translate: var(--spot-par, 0px) 0;
  transition: translate 1.2s cubic-bezier(0.22, 0.61, 0.21, 1);
}

/* de spots ademen: als echte lampen die net niet constant branden */
@keyframes spotAdem {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.62; }
}

/* twee schuine lichtbundels van boven: links wit, rechts accentkleur */
.sviewer__bundel {
  top: -14%;
  height: 82%;
  width: min(24vw, 280px);
  filter: blur(30px);
  transform-origin: top center;
  /* zachte tegendrift bij een wissel; los van de rotate-zwaai (transform) */
  translate: var(--licht-par, 0px) 0;
  transition: translate 1.9s cubic-bezier(0.2, 0.6, 0.2, 1);
}

.sviewer__bundel--links {
  left: 10%;
  transform: rotate(14deg);
  background: linear-gradient(rgba(251, 251, 250, 0.28), transparent 78%);
  animation: lampAan 0.6s steps(1) 0.25s both, bundelZwaaiL 7.5s ease-in-out 0.9s infinite alternate;
}

.sviewer__bundel--rechts {
  right: 10%;
  transform: rotate(-14deg);
  /* de kleur van het licht vertelt de kant: de merkenkleur voor de
     digital humans die een merk vertegenwoordigen, de tweede kleur
     voor de klonen van echte personen (JS zet --bundel per synth) */
  background: linear-gradient(color-mix(in srgb, var(--bundel, var(--acc)) 55%, transparent), transparent 78%);
  animation: lampAan 0.65s steps(1) 0.35s both, bundelZwaaiR 5.5s ease-in-out 1.05s infinite alternate;
}

/* de bundels zwaaien heel traag, ieder in eigen tempo en tegengesteld */
@keyframes bundelZwaaiL {
  from { transform: rotate(9deg); opacity: 0.8; }
  to { transform: rotate(20deg); opacity: 1; }
}

@keyframes bundelZwaaiR {
  from { transform: rotate(-22deg); opacity: 1; }
  to { transform: rotate(-6deg); opacity: 0.72; }
}

/* lichtcirkel op de vloer, onder de actieve slide */
.sviewer__cirkel {
  left: var(--spotX, 50%); /* onder de kegel, dus op de cutout */
  bottom: 5%;
  width: min(64vw, 600px);
  height: min(16vw, 150px);
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(251, 251, 250, 0.32), transparent 68%);
  filter: blur(16px);
  animation: lampAan 0.5s steps(1) 0.45s both, cirkelAdem 7s ease-in-out 1s infinite;
}

/* de vloercirkel ademt mee met de brede spot */
@keyframes cirkelAdem {
  0%, 100% { opacity: 1; transform: translateX(-50%) scaleX(1); }
  50% { opacity: 0.7; transform: translateX(-50%) scaleX(0.94); }
}

/* ---- "lampen gaan aan"-intro bij het openen van de studio ---- */

/* zwarte afdekking bovenop het carrouselvlak die weg-flikkert (studio start donker) */
.sviewer__blackout {
  position: absolute;
  inset: 0;
  z-index: 6;
  background: #000000;
  pointer-events: none;
  animation: studioDonker 0.85s steps(1) both;
}

@keyframes studioDonker {
  0% { opacity: 0.97; }
  9% { opacity: 0.62; }
  15% { opacity: 0.88; }
  24% { opacity: 0.45; }
  31% { opacity: 0.74; }
  42% { opacity: 0.24; }
  52% { opacity: 0.5; }
  62% { opacity: 0.16; }
  74% { opacity: 0.08; }
  86% { opacity: 0.03; }
  100% { opacity: 0; }
}

/* lamp die opwarmt/aanflitst */
@keyframes lampAan {
  0% { opacity: 0; }
  12% { opacity: 0.4; }
  18% { opacity: 0.06; }
  30% { opacity: 0.7; }
  38% { opacity: 0.32; }
  52% { opacity: 0.92; }
  100% { opacity: 1; }
}

@keyframes kaartenIn {
  from { opacity: 0; transform: translateY(36px); }
  to { opacity: 1; transform: none; }
}

/* de cutout onthult mee met de flitsen van de smalle kegel: per flits blijft
   er meer zichtbaar (oplopend met dips, nooit terug naar 0). De waarden
   schalen mee met --cut-eind, de rust-opacity van de betreffende synth */
@keyframes cutoutAan {
  0% { opacity: 0; }
  12% { opacity: calc(var(--cut-eind, 0.48) * 0.3); }
  18% { opacity: calc(var(--cut-eind, 0.48) * 0.08); }
  30% { opacity: calc(var(--cut-eind, 0.48) * 0.55); }
  38% { opacity: calc(var(--cut-eind, 0.48) * 0.28); }
  52% { opacity: calc(var(--cut-eind, 0.48) * 0.78); }
  64% { opacity: calc(var(--cut-eind, 0.48) * 0.5); }
  76% { opacity: calc(var(--cut-eind, 0.48) * 0.92); }
  100% { opacity: var(--cut-eind, 0.48); }
}

@keyframes zachtIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .sviewer__spot--breed,
  .sviewer__spot--smal,
  .sviewer__bundel--links,
  .sviewer__bundel--rechts,
  .sviewer__cirkel {
    animation: none;
  }
  /* geen "lampen aan"-intro: de studio staat meteen verlicht */
  .sviewer__blackout { animation: none; opacity: 0; }
}

/* ---- header ---- */

/* zweeft over de studio in plaats van er ruimte boven te claimen: anders
   begint de carrousel pas onder de titel en tekent zich een harde rand af
   tussen het onbedekte doek en de donkere buurslides */
.sviewer__top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px clamp(20px, 3vw, 32px) 0;
  pointer-events: none; /* de carrousel mag hieronder gewoon gesleept worden */
}

.sviewer__close { pointer-events: auto; }

.sviewer__label {
  display: flex;
  align-items: center;
  gap: 9px;
  color: var(--acc);
}

.sviewer__close {
  border-color: rgba(251, 251, 250, 0.3);
  color: #FBFBFA;
}

/* ---- navigatie ---- */

.sviewer__pijl {
  position: absolute;
  /* gecentreerd via top-rekensom, niet via transform: de hover-lift
     (scale) gebruikt transform en zou de knop anders verplaatsen */
  top: calc(50% - 23px);
  z-index: 3;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(251, 251, 250, 0.3);
  background: rgba(13, 13, 12, 0.4);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: #FBFBFA;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  /* faden mee met de foto — zelfde vertraging en duur als de kaarten
     hierboven, zodat de knoppen er meteen bij staan in plaats van er
     ruim achteraan te komen. 'backwards' zodat de animatie na afloop de
     opacity niet vastpint (info-open moet ze nog kunnen wegfaden) */
  animation: zachtIn 0.9s ease 0.7s backwards;
}

.sviewer__pijl--links { left: 18px; }
.sviewer__pijl--rechts { right: 18px; }

/* ---- carrousel ---- */

.sviewer__stage {
  position: relative;
  z-index: 1;
  flex: 1;
  min-height: 0;
  /* lucht onder de zwevende titel en boven de vensterrand; het blok
     zakt iets zodat het grotere portret in balans blijft */
  padding: 56px 0 48px;
  display: flex;
  align-items: center;
  overflow: hidden;
  /* sleepbaar met muis of vinger; pan-y houdt verticaal scrollen vrij */
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}

.sviewer__stage:active { cursor: grabbing; }

.sviewer__tik { display: none; }

/* zachte fade-randen links en rechts, zoals boven/onder in de artikelen:
   de buurslides lopen uit in het venster-zwart in plaats van hard af te
   snijden op de rand. Onder de pijlknoppen (z-index 3), boven de track. */
.sviewer__stage::before,
.sviewer__stage::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 2;
  pointer-events: none;
}

/* Op smalle schermen vult één slide het hele venster: er zijn geen
   buurslides om te laten uitlopen, en deze twee stroken lagen dus over
   de foto en over de casetekst. Dat las als een fade links en rechts. */
@media (max-width: 699.98px) {
  .sviewer__stage::before,
  .sviewer__stage::after { display: none; }
}

.sviewer__stage::before {
  left: 0;
  /* subtiel randje: de kier met de vorige case moet juist zichtbaar blijven */
  width: clamp(36px, 4vw, 70px);
  background: linear-gradient(90deg, #000000, transparent);
}

.sviewer__stage::after {
  right: 0;
  /* subtiel randje: de strook met de volgende foto moet zichtbaar blijven */
  width: clamp(36px, 4vw, 70px);
  background: linear-gradient(270deg, #000000, transparent);
}

/* entree: één fade+rise op de wrapper; herstart vanzelf bij elk openen
   omdat [hidden] de viewer uit de rendering haalt */
.sviewer__rise {
  width: 100%;
  /* de kaarten rijzen pas binnen ná het opflikkeren van de lampen */
  animation: kaartenIn 0.9s cubic-bezier(0.32, 0.72, 0.28, 1) 0.9s both;
}

@keyframes sviewerRise {
  from { opacity: 0; transform: translateY(36px); }
  to { opacity: 1; transform: none; }
}

.sviewer__track {
  display: flex;
  gap: 48px; /* moet gelijk zijn aan SV_GAP in script.js */
  will-change: transform;
  transition: transform 0.45s cubic-bezier(0.32, 0.72, 0.28, 1);
}

/* stille sprong terug naar de middelste kopie of live slepen: geen transitie */
.sviewer__track.is-stil,
.sviewer__track.is-stil .sviewer__slide { transition: none; }

/* ---- slide: vrijstaand portret + call sheet ---- */

.sviewer__slide {
  position: relative;
  z-index: 1;
  flex: 0 0 var(--iw);
  width: var(--iw);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-content: center;
  gap: 24px clamp(24px, 3vw, 32px);
  border: none;
  padding: 0;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transform: scale(0.86);
  /* dimmen alleen via opacity: een filter-transitie (brightness) dwingt
     bij elke selectie een repaint van de foto af en liet hem flikkeren */
  opacity: 0.25;
  transition: transform 0.45s cubic-bezier(0.32, 0.72, 0.28, 1), opacity 0.45s cubic-bezier(0.32, 0.72, 0.28, 1);
}

/* de actieve staat in de spot — en boven zijn buren, zodat zijn uitsnede
   de volgende synth overlapt in plaats van andersom */
/* Slides verder dan twee van de actieve staan nooit in beeld, maar
   hielden wel elk een eigen compositielaag: een transform, een fade op het
   beeld en een scrollbare sheet -- 36 stuks, want de track houdt drie
   kopieën van de lijst. Op een 3x-scherm was dat honderden MB aan backing
   stores en legde iOS de tab om bij het openen. JS zet is-ver op alles
   buiten SV_BEELDBUREN; visibility hidden houdt de plek in de track maar
   rastert niets en laat de animaties niet meer schilderen. */
.sviewer__slide.is-ver { visibility: hidden; }

.sviewer__slide.is-actief {
  z-index: 2;
  transform: scale(1);
  opacity: 1;
  cursor: default;
}

.sviewer__beeld {
  position: relative;
  z-index: 1; /* boven de uitsnede in dezelfde slide */
  flex: 0 0 auto;
  line-height: 0;
}

/* alleen voor mobiel; op desktop staat de call sheet gewoon ernaast */
.sviewer__scrim,
.sviewer__bijschrift,
.sviewer__tik { display: none; }

.sviewer__foto {
  display: block;
  width: calc(var(--ph) * 0.75);
  height: var(--ph);
  object-fit: cover;
  border-radius: 0;
  box-shadow: 0 34px 70px rgba(0, 0, 0, 0.55);
  /* vloerreflectie onder het portret */
  -webkit-box-reflect: below 3px linear-gradient(transparent 74%, rgba(251, 251, 250, 0.09));
  pointer-events: none; /* geen native beeld-drag; de stage vangt het slepen */
}

/* ---- call sheet ---- */

.sviewer__sheet {
  position: relative;
  z-index: 1; /* boven de uitsnede in dezelfde slide */
  flex: 1 1 220px;
  /* 430 i.p.v. 370: op desktop is er ruimte, en een breder vel is minder
     scrollen in de casetekst. --iw (hierboven) groeit met dezelfde 60px mee */
  max-width: 430px;
  min-width: 0;
  pointer-events: none;
}

/* grote vrijstaande uitsnede van de digital human: gewoon onderdeel van de
   kaart. De kaart is er extra breed voor (--iw-tot), dus in de carrousel kan
   een buurkaart nooit met de uitsnede interfereren — vorige en volgende synth
   blijven zichtbaar zoals in het oorspronkelijke ontwerp.
   Alleen op bredere schermen; op mobiel ligt de sheet over de foto. */
.sviewer__cutout { display: none; }

@media (min-width: 700px) {
  .sviewer {
    /* hoogte van de uitsnede: vloer tot plafond. Hij groeit gewoon mee
       met de vensterhoogte, zodat hij op grote schermen niet klein
       blijft steken; het portret vormt alleen nog een ruime bovengrens */
    --cut-h: min(calc(var(--sv-vh, 0px) * 1.35), calc(var(--ph) * 2.6));
    /* kaartbreedte: case plus de ruimte waarin de uitsnede zichtbaar is
       (de flankfade eindigt ruim binnen 0.45 × zijn hoogte rechts van de case) */
    --iw-tot: min(calc(var(--iw) + 0.4 * var(--cut-h)), calc(100vw - 2 * clamp(16px, 4vw, 48px) - 28px));
    /* de smalle kegel richt op de cutout rechts van de case */
    --spotX: 70%;
  }

  /* de entree verhuist van de wrapper naar foto + case: de cutout (die ín
     de slide zit) moet al tijdens de lichtflitsen zichtbaar worden, terwijl
     foto en case pas daarna binnenrijzen */
  .sviewer__rise { animation: none; }

  /* geen lichtcirkel op de vloer: de cutouts zijn ingezoomd en raken de
     grond niet — het licht zit in de kegel, op het gezicht */
  .sviewer__cirkel { display: none; }

  .sviewer__beeld,
  .sviewer__sheet {
    animation: kaartenIn 0.9s cubic-bezier(0.32, 0.72, 0.28, 1) 0.7s both;
  }

  .sviewer__slide {
    flex-basis: var(--iw-tot);
    width: var(--iw-tot);
    /* de call sheet lijnt bovenlangs uit met de foto in plaats van
       gecentreerd mee te bewegen: de kop staat zo bij elke synth op
       exact dezelfde plek */
    align-items: flex-start;
    align-content: flex-start;
  }

  /* de sheet is even hoog als het portret: kop (soort, naam, rijen)
     staat vast bovenin, de casetekst eronder scrollt in zijn eigen
     venster. Zo kunnen caseteksten langer worden zonder dat er iets
     verspringt. De kop begint bewust nét onder de bovenrand van de
     foto in plaats van erboven uit te steken. */
  .sviewer__sheet {
    display: flex;
    flex-direction: column;
    height: var(--ph);
    padding-top: calc(var(--ph) * 0.055);
  }

  .sviewer__case {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: 18px;
    pointer-events: auto; /* scrollen mag hier wél */
    /* alleen de duim, geen rail erachter */
    scrollbar-width: thin;
    scrollbar-color: var(--bundel, var(--acc)) transparent;
  }

  /* de tekst loopt aan beide randen uit in plaats van hard af te breken.
     Geen overlay-gradient: de casetekst ligt op de belichte kaart, niet op
     een vlakke kleur, dus een gekleurde strook zou als blok opvallen. Een
     masker vervaagt de tekst zelf en werkt op elke ondergrond. JS zet
     is-bovenin en is-onderin zodra die rand in beeld is. */
  .sviewer__case {
    --fade-boven: 30px;
    --fade-onder: 44px;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--fade-boven),
      #000 calc(100% - var(--fade-onder)), transparent 100%);
    mask-image: linear-gradient(to bottom, transparent 0, #000 var(--fade-boven),
      #000 calc(100% - var(--fade-onder)), transparent 100%);
  }
  .sviewer__case.is-bovenin { --fade-boven: 0px; }
  .sviewer__case.is-onderin { --fade-onder: 0px; }

  /* WebKit/Blink: expliciete breedte houdt de duim permanent zichtbaar;
     track, hoek en knoppen blijven volledig onzichtbaar */
  .sviewer__case::-webkit-scrollbar { width: 4px; background: transparent; }
  .sviewer__case::-webkit-scrollbar-track,
  .sviewer__case::-webkit-scrollbar-track-piece,
  .sviewer__case::-webkit-scrollbar-corner,
  .sviewer__case::-webkit-scrollbar-button { background: transparent; box-shadow: none; border: 0; }
  .sviewer__case::-webkit-scrollbar-thumb { background: var(--bundel, var(--acc)); }

  .sviewer__cutout {
    display: block;
    position: absolute;
    z-index: 0; /* onder de foto en de call sheet van zijn eigen kaart */
    height: var(--cut-h);
    width: auto;
    max-width: none;
    /* horizontaal blijft hij aan de case (--iw) hangen, niet aan de brede kaart */
    left: calc(var(--cut-x, 109) / 100 * var(--iw));
    top: 50%;
    /* met beide voeten op de vloer van het venster, ook als de hoogte tegen het
       plafond loopt. De 20px corrigeert de stagepadding (64 boven, 24 onder). */
    transform: translate(-50%, calc(-50% + var(--sv-vh, 0px) / 2 - 0.31 * var(--cut-h) - 20px + var(--cut-y, 0px)));
    pointer-events: none;
    /* --cut-demp temt synths in lichte kleding (zie SV_SHEET.cutoutDemp) */
    --cut-eind: calc(0.48 * var(--cut-demp, 1));
    opacity: var(--cut-eind);
    /* iets gedimd met een contactschaduw naar de vloer: hij staat ín het
       licht van de kegel, niet erbovenop geplakt */
    filter: brightness(0.9) drop-shadow(0 22px 26px rgba(4, 4, 3, 0.55));
    /* onthulling loopt gelijk op met de smalle kegel (zelfde startdelay) */
    animation: cutoutAan 0.8s steps(1) 0.2s both;
    /* parallax: --par komt uit svTeken. Bewust veel trager dan de track
       (0.45s): de uitsnede komt rustig achter de kaart aan en zakt dan op
       zijn plek — hoe verder weg, hoe trager, zoals in een echte studio */
    translate: var(--par, 0px) 0;
    /* per-synth schaal (SV_SHEET.cutoutSchaal) */
    scale: var(--cut-schaal, 1);
    transition: translate 1.2s cubic-bezier(0.22, 0.61, 0.21, 1);
    /* zachte uitloop aan weerszijden: het silhouet staat in het midden van zijn
       canvas (~37%-72% van de breedte), dus de fade pakt precies zijn flanken */
    /* --cut-fl: waar de linkerflank begint; --cut-fr: waar de rechterflank
       volledig is uitgevloeid; --cut-zacht: breedte-factor van beide fades —
       alle drie per synth te verleggen (zie SV_SHEET.cutoutFadeL/FadeR/Zacht) */
    -webkit-mask-image: linear-gradient(to right,
      transparent var(--cut-fl, 33%),
      #000 calc(var(--cut-fl, 33%) + var(--cut-zacht, 1) * 15%),
      #000 calc(var(--cut-fr, 71%) - var(--cut-zacht, 1) * 11%),
      transparent var(--cut-fr, 71%));
    mask-image: linear-gradient(to right,
      transparent var(--cut-fl, 33%),
      #000 calc(var(--cut-fl, 33%) + var(--cut-zacht, 1) * 15%),
      #000 calc(var(--cut-fr, 71%) - var(--cut-zacht, 1) * 11%),
      transparent var(--cut-fr, 71%));
  }

  /* live slepen: de parallax volgt de vinger direct, zonder na-ijlen */
  .sviewer__track.is-stil .sviewer__cutout { transition: none; }
}

/* soortmerk naast de naam: cyaan bij een verzonnen personage, roze bij
   een kloon van een echt mens. Schaalt mee met de naam eromheen. */
.sviewer__merk {
  flex: none;
  width: 0.52em;
  height: 0.52em;
  /* optisch op de x-hoogte, niet op het midden van de regel */
  margin-top: 0.12em;
}

.sviewer__merk svg { display: block; width: 100%; height: 100%; overflow: visible; }

/* op desktop staat het merkje rechtsboven in het vel, op de rechterkant
   van de rijen eronder (min een paar pixels); op mobiel blijft het naast
   de naam, want daar hangt de sluitknop rechtsboven */
@media (min-width: 700px) {
  .sviewer__merk { margin-left: auto; margin-right: 4px; }
}

.sviewer__naam {
  display: flex;
  align-items: center;
  gap: 0.34em;
  margin: 0 0 20px;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  /* compacter dan de sectiekoppen: de casetekst eronder krijgt de ruimte */
  font-size: clamp(28px, 3.2vw, 44px);
  line-height: 1.05;
  color: #FBFBFA;
}

.sviewer__rijen { margin: 0; }

.sviewer__rij {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 9px 0;
  border-top: 1px solid var(--hairline-row);
}

.sviewer__rij dt {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-45);
}

.sviewer__rij dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink);
  text-align: right;
}

.sviewer__balk { display: none; }

.sviewer__case {
  border-top: 1px solid var(--hairline-row);
  padding-top: 26px;
}

/* de case staat in blokken: aanleiding, aanpak, impact, en een kernzin
   als slot. De labels zijn dezelfde mono-caps als de rijen erboven. */
.sviewer__caseblok + .sviewer__caseblok { margin-top: 24px; }

.sviewer__caselabel {
  display: block;
  margin-bottom: 8px;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  /* de kopjes nemen de kleur van het licht op deze synth over: --bundel
     staat op de merkkleur, en op de tweede kleur bij de klonen van echte
     personen (JS zet hem per synth, zie MENSEN in script.js). Hij
     verkleurt met dezelfde overgang van 0,7s als de lichtbundel. */
  color: var(--bundel, var(--acc));
}

.sviewer__case p {
  margin: 0;
  font-size: 15px;
  line-height: 1.75;
  color: var(--ink-75);
}

/* de kernzin opent de case, zonder scheidingslijn eronder */
.sviewer__case .sviewer__kernzin {
  margin: 0 0 28px;
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.4;
  color: var(--ink);
}

/* de roster-wand is klikbaar */
.roster .synth { cursor: pointer; }

/* ============ studio-viewer op smalle schermen ============
   Alleen het portret met de naam linksonder en een info-knop. Bij een tik
   verduistert de foto langzaam en schuift de call sheet omhoog. */
@media (max-width: 699.98px) {
  /* de overlay blijft ingeklemd zoals de andere panelen (backdrop rondom);
     de foto vult wél de hele venster: de actieve slide is even breed als de
     venster, buren staan volledig buiten beeld */
  .sviewer { --iw: calc(100vw - 2 * clamp(16px, 4vw, 48px)); }

  .sviewer__stage {
    padding: 0;
    align-items: stretch; /* de slides vullen de volle hoogte */
  }

  /* hoogte-keten tot aan de slide, zodat het beeld de stage vult */
  .sviewer__rise { height: 100%; }
  .sviewer__track { height: 100%; }

  /* op mobiel gewoon de foto's. De rise-wrapper staat uit (die zou de hele
     track pas laat tonen) en de fade zit op het beeld zelf — opacity-only,
     zodat een full-bleed foto niet verschuift. De foto stond hier 1,7s te
     wachten tot de lampen klaar waren; nu komt hij vrijwel meteen en
     flitsen de lampen eroverheen. Speelt één keer bij openen; swipen
     daarna is direct. */
  .sviewer__rise { animation: none; }
  .sviewer__beeld { animation: zachtIn 0.3s ease 0.04s both; }

  /* de zwarte laag die de studio donker houdt tijdens het aanflitsen dooft
     mee versneld: anders zou hij de foto de eerste 0,85s alsnog afdekken.
     De lampen zelf houden hun eigen ritme. */
  .sviewer__blackout { animation-duration: 0.28s; }

  /* de titel valt weg; de sluitknop blijft zweven rechtsboven */
  .sviewer__top {
    justify-content: flex-end;
    padding: 12px 12px 0;
  }

  .sviewer__label { display: none; }

  /* de navigatiepijlen blijven zichtbaar (zelfde stijl als de terugknop in
     het artikelvenster): ze wijzen op swipen en werken ook als knop */
  .sviewer__pijl {
    display: flex;
    width: 44px;
    height: 44px;
    top: calc(50% - 22px);
    background: rgba(13, 13, 12, 0.35);
  }

  .sviewer__pijl--links { left: 10px; }
  .sviewer__pijl--rechts { right: 10px; }

  /* de pijlen houden dezelfde timing aan als de foto */
  .sviewer__pijl { animation: zachtIn 0.3s ease 0.04s backwards; }

  /* de pijlen faden weg zodra de casetekst verschijnt (swipen blijft werken) */
  .sviewer__pijl { transition: opacity 0.3s ease, background 0.25s ease, transform 0.32s cubic-bezier(0.34, 1.3, 0.4, 1); }
  .sviewer.info-open .sviewer__pijl { opacity: 0; pointer-events: none; }

  .sviewer__slide {
    position: relative;
    display: block;
    height: 100%;
  }

  .sviewer__beeld {
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: 0;
    overflow: hidden;
  }

  .sviewer__foto {
    width: 100%;
    height: 100%;
    box-shadow: none;
    /* geen vloerreflectie: het beeld vult de slide, dus de spiegeling
       valt buiten beeld. Bewust 'initial' en niet 'none': die waarde
       wordt door de parser verworpen, waardoor deze reset stilletjes
       niets deed en er 36 dubbele renders bleven staan. */
    -webkit-box-reflect: initial;
  }

  /* verduistert langzaam zodra de gegevens verschijnen */
  .sviewer__scrim {
    display: block;
    position: absolute;
    inset: 0;
    background: rgba(8, 8, 7, 0.74);
    opacity: 0;
    transition: opacity 0.6s ease;
    pointer-events: none;
  }

  .sviewer__slide.is-info .sviewer__scrim { opacity: 1; }

  /* naam linksonder, met een zachte voet zodat hij op elk beeld leesbaar is */
  .sviewer__bijschrift {
    display: block;
    position: absolute;
    left: 24px;
    bottom: 26px;
    z-index: 2;
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.02em;
    font-size: 26px;
    line-height: 1;
    color: #FBFBFA;
    text-shadow: 0 2px 18px rgba(8, 8, 7, 0.6);
    transition: opacity 0.3s ease;
    pointer-events: none;
  }

  .sviewer__slide.is-info .sviewer__bijschrift { opacity: 0; }

  /* tooltip die uitlegt dat een tik de case opent: klein, gecentreerd, en
     verticaal halverwege de pijlen (50%) en de onderkant van de foto.
     De hele foto blijft klikbaar; dit is puur de uitleg */
  /* alleen op de zichtbare slide. De track houdt drie kopieën van de
     lijst, dus dit stond 36 keer in de DOM — en elke backdrop-filter
     dwingt op iOS een eigen compositielaag met een backdrop-readback af.
     Zesendertig daarvan tegelijk legde Safari om bij het openen. */
  .sviewer__tik { display: none; }

  .sviewer__slide.is-actief .sviewer__tik {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    z-index: 2;
    left: 50%;
    top: 76%;
    transform: translateX(-50%);
    max-width: calc(100% - 40px);
    padding: 7px 13px;
    border-radius: 0;
    border: 1px solid rgba(251, 251, 250, 0.16);
    background: rgba(13, 13, 12, 0.55);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 400;
    line-height: 1.25;
    text-align: center;
    color: rgba(251, 251, 250, 0.86);
    transition: opacity 0.3s ease;
    pointer-events: none; /* de stage vangt de tik af */
    /* geen animatie: de hint staat gewoon altijd op zolang je de foto ziet.
       Tijdens de donkere intro dekt de blackout-laag (z-index 6) hem af, dus
       hij "verschijnt" vanzelf als het licht aangaat. Bij een open case fadet
       hij weg via de is-info-regel hieronder (en weer terug bij sluiten) */
  }

  .sviewer__slide.is-info .sviewer__tik { opacity: 0; }

  /* wie de case al twee keer met een tik heeft geopend, weet het nu:
     de uitleg komt niet meer terug (JS onthoudt het in localStorage) */
  .sviewer.tik-gezien .sviewer__tik { display: none; }

  /* de call sheet vult het venster en schuift van onderen omhoog. Stond
     eerder op 82% met een doorzichtige bovenrand: dat gaf een gat van
     ruim 100px bovenin, de tekst begon halverwege en de foto schemerde
     erachter door. Nu van rand tot rand en dekkend. */
  .sviewer__sheet {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: 2;
    max-width: none;
    max-height: none;
    /* pas scrollbaar zodra hij open staat (zie .is-info hieronder): een
       dichte sheet is anders al een eigen scroll-laag, en dat 36 keer */
    overflow: hidden;
    overscroll-behavior: contain;
    touch-action: pan-y; /* verticaal scrollen; horizontaal blijft swipen */
    /* het kruis zweeft rechtsboven; de eyebrow eindigt ruim 100px links
       daarvan, dus de tekst mag er gewoon naast beginnen */
    padding: 26px 18px 64px;
    background: #000000;
    transform: translateY(100%);
    opacity: 0;
    pointer-events: none;
    /* dicht = ook echt onzichtbaar, anders blijft hij een getransformeerde
       laag ter grootte van de sheet (vijf keer, bij dpr 3). De visibility
       flipt bij sluiten pas ná de fade, zodat die nog te zien is. */
    visibility: hidden;
    transition: transform 0.45s cubic-bezier(0.32, 0.72, 0.28, 1), opacity 0.35s ease,
                visibility 0s linear 0.45s;
  }

  .sviewer__slide.is-info .sviewer__sheet {
    transform: none;
    opacity: 1;
    pointer-events: auto;
    overflow-y: auto;
    /* geen systeembalk: die kwam in de accentkleur náást onze eigen balk
       (.sviewer__balk, in de kleur van de synth) — bij een kloon liepen er
       zo een roze en een cyaan balk naast elkaar mee */
    scrollbar-width: none;
    visibility: visible;
    transition-delay: 0s, 0s, 0s; /* openen: meteen zichtbaar, dan faden */
  }

  /* onderfade zoals in de panelen (zie .panel--scrollfade): een sticky
     strook aan de onderrand die de laatste regels laat uitlopen, en
     verdwijnt zodra er niets meer onder staat. JS zet is-onderin. */
  .sviewer__sheet::after {
    content: '';
    position: sticky;
    bottom: -64px; /* de sheet heeft 64px padding onderin; tot de echte rand */
    z-index: 2;
    display: block;
    height: 44px;
    margin-top: -44px;
    pointer-events: none;
    background: linear-gradient(transparent, #000000);
    transition: opacity 0.25s ease;
  }
  .sviewer__sheet.is-onderin::after { opacity: 0; }

  /* eigen scrollbalk, altijd zichtbaar zolang de case open staat: de
     systeembalk van iOS is een overlay die pas tijdens het scrollen
     verschijnt. JS zet hoogte en positie van de duim. */
  .sviewer__slide.is-info .sviewer__balk {
    display: block;
    position: absolute;
    top: 26px;
    right: 5px;
    bottom: 26px;
    width: 3px;
    z-index: 3;
    background: rgba(251, 251, 250, 0.16);
    pointer-events: none;
  }

  .sviewer__slide.is-info .sviewer__balk.is-uit { display: none; }

  /* WebKit (iOS Safari): de overlay-balk van het systeem ook verbergen */
  .sviewer__sheet::-webkit-scrollbar { display: none; }

  .sviewer__balk i {
    display: block;
    width: 100%;
    /* zelfde licht als de kopjes: merkkleur, of de tweede kleur bij de
       klonen van echte personen */
    background: var(--bundel, var(--acc));
  }

  .sviewer__naam { margin-bottom: 16px; }
}

@keyframes sviewerTik {
  0%, 100% { opacity: 0.78; }
  50% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .sviewer__track,
  .sviewer__slide { transition: none; }
  /* dit blok staat ná alle sviewer-regels, dus deze animation: none wint
     ook van de entree-animaties in de 700px-query hierboven */
  .sviewer__rise,
  .sviewer__pijl,
  .sviewer__cutout,
  .sviewer__beeld,
  .sviewer__sheet,
  .sviewer__tik { animation: none; }
}

/* ============ landscape-blokkade (alleen telefoons) ============ */

/* de one-pager is op portrait ontworpen; draait iemand zijn telefoon,
   dan dekt dit scherm de hele site af tot hij terugdraait.
   hover: none sluit desktops met een breed-laag venster uit */
.draaiblok {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 100; /* boven alles, ook de roster-viewer en het kleurenpaneel */
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 24px clamp(24px, 8vw, 64px);
  background: #000000;
  color: #FBFBFA;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: lowercase;
  text-align: center;
  touch-action: none; /* ook niet doorheen scrollen */
  isolation: isolate;
}

/* exact dezelfde ruis als achter de overlays (.panelfx): fijne scanlines
   plus de jitterende korrel — de oude tv-static gebruiken we niet meer */
.draaiblok::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: repeating-linear-gradient(0deg, rgba(10, 10, 9, 0.16) 0 2px, transparent 2px 5px);
  pointer-events: none;
}

.draaiblok::after {
  content: '';
  position: absolute;
  inset: -60px; /* jitter mag geen randen tonen */
  z-index: -1;
  background-image: url('noise.png');
  opacity: 0.07;
  pointer-events: none;
  animation: vaultJitter 0.5s steps(2) infinite;
}

.draaiblok p { margin: 0; max-width: 34ch; line-height: 1.7; }

@media (orientation: landscape) and (max-height: 480px) and (hover: none) {
  .draaiblok { display: flex; }
}

/* ============ kop-stem: alle koppen en namen in kapitalen ============
   Barlow Semi Condensed (via --font-display), gewicht 800 en uppercase.
   Eén regel achteraan zodat hij álle individuele kop-definities overschrijft,
   ook die verderop in het bestand (sviewer-namen). De wordmark valt hier
   bewust buiten: dat is het logo-lockup en blijft Helvetica. */
.hero__lead,
.voorwie__kop,
.yourbrand__title,
.statement p,
.panel__title,
.synth__name,
.sviewer__naam,
.sviewer__bijschrift {
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

/* ============ labels: Barlow in caps (was Geist Mono) ============
   De kleine "systeem"-labels komen nu ook uit de Barlow-familie, maar
   lichter (500) en in kapitalen — zodat ze duidelijk labels blijven en
   niet met de zware koppen concurreren. Bestaande letter-spacings per
   selector blijven staan (die geven de getrackte label-look). */
.artikel__banner,
.artikel__meta,
.contact-grid__label,
.feature-row__index,
.footer,
.hero__subline,
.login-code__fout,
.nieuws-item__datum,
.panel-card__contact,
.panel-card__role,
.panel__footnote,
.path-label,
.privacytegel__index,
.psych__media-label,
.sviewer__caselabel,
.sviewer__rij dt,
.sviewer__rij dd,
.synth__client,
.topline__item,
.vault-intro__eu {
  font-weight: 500;
  text-transform: uppercase;
}

/* ============ koppen: Inter Tight in sentence-case (gewicht 600) ============
   Onze display-koppen staan standaard in normale case, zoals awwwards. Caps
   is opt-in via de .text-uppercase-utility hieronder (zet die op een element
   dat je juist wél in kapitalen wilt). card__index (STAP 01) staat bewust
   níét in deze lijst: die blijft in kapitalen. */
.hero__lead,
.section-title,
.cta__title,
.voorwie__kop,
.yourbrand__title,
.statement p,
.panel__title,
.synth__name,
.sviewer__naam,
.sviewer__bijschrift {
  text-transform: none;
  font-weight: 700; /* vetter, DEPT-achtig statement-gewicht */
  letter-spacing: -0.02em;
}

/* opt-in kapitalen op een kop (awwwards gebruikt dit gericht, bv. W.CREATORS) */
.text-uppercase { text-transform: uppercase; }
