/* ==============================
   Font Face — Borna
   ============================== */

@font-face {
    font-family: 'Borna';
    src: url('fonts/Borna Roman Desktop/Borna-Regular.otf') format('opentype');
    font-weight: 400;
    font-style: normal;
    font-display: block;
}

@font-face {
    font-family: 'Borna';
    src: url('fonts/Borna Roman Desktop/Borna-Medium.otf') format('opentype');
    font-weight: 500;
    font-style: normal;
    font-display: block;
}

@font-face {
    font-family: 'Borna';
    src: url('fonts/Borna Roman Desktop/Borna-SemiBold.otf') format('opentype');
    font-weight: 600;
    font-style: normal;
    font-display: block;
}

/* Drie gewichten: 400 Regular, 500 Medium, 600 SemiBold.
   Borna-Bold (700) bewust niet geladen — hield de typografie inconsistent. */

/* ==============================
   Reset
   ============================== */

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

/* De eigen cursor-stip vervangt de systeemcursor — maar pas zodra hij er
   echt staat (script.js zet .heeft-stip bij de eerste muisbeweging). Faalt
   JS of komt er nooit een muis, dan blijft de gewone cursor zichtbaar. */
html.heeft-stip,
html.heeft-stip body,
html.heeft-stip a,
html.heeft-stip button,
html.heeft-stip input,
html.heeft-stip textarea,
html.heeft-stip select {
    cursor: none;
}

body {
    font-family: 'Borna', -apple-system, BlinkMacSystemFont, sans-serif;
    background: #F9F8F6;
    color: #1a1a1a;
    overflow-x: hidden;
    scrollbar-width: none;
}

/* ==============================
   Preloader — teller in de nav-kolom
   ============================== */

/* De lader spreekt dezelfde taal als de zijnav: een getal (0–100) op de plek
   waar straks het actieve nav-item staat, dat als een strook omhoog schuift.
   Bij 100 schiet de teller omhoog en komen de nav-items van onderen binnen. */

.preloader {
    position: fixed;
    inset: 0;
    background: #F9F8F6;
    z-index: 20000;
    transition: opacity 0.5s ease;
}

.preloader.hiding {
    opacity: 0;
    pointer-events: none;
}

.preloader-teller {
    position: absolute;
    left: 40px;
    top: 50%;
    margin-top: -17px;
    display: flex;
    align-items: center;
    gap: 12px;
    transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.35s ease;
}

.preloader.klaar .preloader-teller {
    transform: translate3d(0, -45vh, 0);
    opacity: 0;
}

.preloader-venster {
    height: 34px;
    overflow: hidden;
    min-width: 3ch;
    font-size: 28px;
    line-height: 34px;
    font-weight: 400;
    letter-spacing: -0.01em;
    color: #1a1a1a;
    font-variant-numeric: tabular-nums;
}

.preloader-strook {
    will-change: transform;
}

.preloader-strook span {
    display: block;
    height: 34px;
}

.preloader-dot {
    width: 10px;
    height: 10px;
    background: #FF3F3F;
    border-radius: 50%;
    animation: preloaderPulse 1.2s ease-in-out infinite;
}

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

@keyframes preloaderPulse {
    0%, 100% { scale: 1; opacity: 1; }
    50% { scale: 1.6; opacity: 0.5; }
}

/* ==============================
   Maten die op meer plekken terugkomen
   ============================== */

:root {
    /* Lucht links en rechts van een plaat op mobiel (besluit 2026-09-19) */
    --plaat-pad: 22px;
}

/* ==============================
   Custom Cursor — Red dot
   ============================== */

.cursor-dot {
    position: fixed;
    top: 0;
    left: 0;
    width: 10px;
    height: 10px;
    background: #FF3F3F;
    border-radius: 50%;
    pointer-events: none;
    z-index: 10000;
    will-change: translate, scale;
    scale: 1;
    /* Onzichtbaar tot script.js een echte muispositie heeft (klasse `actief`);
       anders zie je 'm eerst linksboven staan en dan wegspringen. */
    opacity: 0;
    transition: scale 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
                opacity 0.25s ease;
}

.cursor-dot.actief {
    opacity: 1;
}

.cursor-dot.hovering {
    scale: 4.8;
}

/* STIP-HINT — "hier kun je zijwaarts". Bij een stapel wordt de stip groter
   en doet hij "elastiek" (versie 2 uit stip-lab.html, gekozen 2026-10-11):
   hij trekt langzaam uit naar rechts tot een druppel, schiet los, wiebelt na
   en is weer rond — een tikje richting de kant waar meer te zien is.
   Waardes in motion.js (stip.*); script.js zet .wijst en haalt hem weg zodra
   iemand naar rechts door de platen is gegaan.
   `transform` is hier vrij: positie en grootte lopen via `translate`/`scale`.
   Druppelvorm: horizontale radii links klein en rechts groot, samen precies
   100 % — komt de som erboven, dan schaalt de browser álle radii terug en
   krijgt de druppel platte zijkanten. */
.cursor-dot.wijst:not(.hovering) {
    scale: var(--stip-schaal, 2.6);
    animation: stip-elastiek var(--stip-duur, 2400ms) linear infinite;
}

/* De stip rekt uit vanaf een punt op een kwart van links (2,5 px links van
   het midden), maar zónder transform-origin: die geldt ook voor `scale` en
   zette de vergrote stip 4 px naast de muis. Daarom schaalt hij om het midden
   en schuift translateX het ankerpunt terug: 2,5 px × (schaal − 1). */
@keyframes stip-elastiek {
    0%   { transform: translateX(0) scale(1, 1); border-radius: 50%; animation-timing-function: cubic-bezier(0.5, 0, 0.9, 0.6); }
    58%  { transform: translateX(calc((var(--stip-rek, 2) - 1) * 2.5px)) scale(var(--stip-rek, 2), 0.84); border-radius: 24% 76% 76% 24% / 50%; animation-timing-function: cubic-bezier(0.2, 0.8, 0.3, 1); }
    66%  { transform: translateX(-0.5px) scale(0.8, 1.14); border-radius: 50%; }
    74%  { transform: translateX(0.35px) scale(1.14, 0.94); }
    82%  { transform: translateX(-0.12px) scale(0.95, 1.04); }
    90%, 100% { transform: translateX(0) scale(1, 1); border-radius: 50%; }
}

@media (prefers-reduced-motion: reduce) {
    .cursor-dot.wijst:not(.hovering),
    .cursor-dot.wijst:not(.hovering)::after {
        animation: none !important;
    }
}

/* ==============================
   Header / Logo
   ============================== */

.header {
    position: fixed;
    top: 40px;
    left: 40px;
    z-index: 100;
}

/* Het logo is een link terug naar boven (script.js scrolt zacht). */
.logo {
    display: flex;
    flex-direction: column;
    color: inherit;
    text-decoration: none;
}

/* Twee regels: "Fabian Strategie +" / "Valkenberg Design"; de naam vet,
   het vak regular (2026-10-23, eerst andersom). */
.logo-regel {
    display: block;
    font-size: 18px;
    font-weight: 400;
    line-height: 1.35;
    letter-spacing: -0.01em;
    white-space: nowrap;
}

.logo-regel b {
    font-weight: 600;
}

/* Geselecteerde tekst in het rood van de site */
::selection {
    background: #FF3F3F;
    color: #fff;
}

/* ==============================
   Intro (scrollable, right of logo)
   ============================== */

.intro-section {
    padding: 140px 40px 0 380px;
    min-height: 80px;
}

/* max-width in em, zodat de regels op elke lettergrootte op dezelfde
   plek breken: "...Zien wat / het kan zijn. Kiezen wat het / wordt. Zo
   ontwerp ik met / teams heldere digitale / producten." (2026-10-23) */
.intro-text {
    max-width: 14.5em;   /* past: 13,95em · te breed: 15,08em (gemeten) */
    margin: 0;
    font-size: 36px;
    font-weight: 400;
    line-height: 1.4;
    color: #1a1a1a;
    letter-spacing: -0.01em;
}

/* De laatste zin (wat ik doe) in het rood van de site (Fabian 2026-10-23) */
.intro-rood {
    color: #FF3F3F;
}

/* Groot scherm: de intro een slag groter, anders verdrinkt hij in de
   ruimte (2026-10-11). Sinds 2026-10-23 weer regular, zoals alle koppen. */
@media (min-width: 1440px) {
    .intro-text {
        font-size: 44px;
        line-height: 1.3;
    }
}

/* ==============================
   Side Navigation
   ============================== */

.side-nav {
    position: fixed;
    left: 40px;
    top: 0;
    width: 200px;
    height: 100vh;
    z-index: 100;
    pointer-events: none;
}

.nav-item {
    position: absolute;
    left: 0;
    display: block;
    text-decoration: none;
    color: #1a1a1a;
    font-size: 28px;
    font-weight: 400;
    letter-spacing: -0.01em;
    white-space: nowrap;
    pointer-events: auto;
    will-change: transform;
    opacity: 0;
    transition: color 0.25s ease, text-shadow 0.25s ease, translate 0.25s ease;
    text-shadow: 0 0 8px rgba(249, 248, 246, 0.7);
    /* Hover shift via the separate `translate` property (composited, no layout)
       — it composes with the JS-driven `transform`, padding-left did a re-layout */
    translate: 0 0;
}

.nav-item:hover {
    translate: 8px 0;
}

.nav-item.active {
    color: #FF3F3F;
}

.nav-item.on-dark {
    color: #F9F8F6;
    text-shadow:
        0 0 12px rgba(0, 0, 0, 0.6),
        0 0 4px rgba(0, 0, 0, 0.4);
}

.nav-item.active.on-dark {
    color: #FF6B6B;
    text-shadow:
        0 0 12px rgba(0, 0, 0, 0.6),
        0 0 4px rgba(0, 0, 0, 0.4);
}


/* ==============================
   Sections
   ============================== */

/* Horizontaal clip, verticaal niet: de platen komen sinds 2026-10-23 van
   alle kanten binnen en mogen buiten hun sectie uitsteken. Daarom ook geen
   paint-containment meer (die knipt net zo hard). */
.section {
    position: relative;
    height: 100vh;
    overflow-x: clip;
    overflow-y: visible;
    contain: layout style;
    margin-top: 150px;
}

.section:first-of-type {
    margin-top: 300px;
}

/* ==============================
   Image Stack — right-aligned, large, stacked
   ============================== */

/* Vaste lucht links voor logo en nav-kolom (die eindigt rond 200 px), en
   rechts een smalle marge; het kader staat daartussen gecentreerd. */
.image-stack {
    position: absolute;
    top: 0;
    left: 240px;
    right: 40px;
    height: 100%;
}

.stack-item {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-top: 40px;
    z-index: 1;
    will-change: transform;
    /* Deal-effect: het actieve item legt zich zacht een stukje opzij/bovenop.
       Via de aparte translate-property zodat het composeert met de
       JS-gestuurde parallax-transform (geen layout, geen conflict). */
    /* deal-effect: waardes komen uit motion.js (--deal-*), fallback = de defaults daar */
    transition: translate var(--deal-duur, 800ms) var(--ds-ease-enter, cubic-bezier(0.16, 1, 0.3, 1));
}

.stack-item.active {
    z-index: 10;
    translate: var(--deal-x, 0px) var(--deal-y, 0px);
}

/* <picture> levert op mobiel de vierkante variant van een plaat; voor de
   layout bestaat hij niet, de img blijft het kind van .stack-item. */
.stack-item picture {
    display: contents;
}

.stack-item img,
.stack-item video {
    display: block;
    max-height: 90vh;
    max-width: 75vw;
    width: auto;
    height: auto;
}

/* ==============================
   Belief Cards (Over)
   ============================== */

/* Een slag groter dan de eerste versie (320 × 430), en sinds 2026-10-23
   een echte stapel: exact op elkaar, van rechts in beeld (script.js). */
.belief-card {
    width: 400px;
    height: 538px;
    border-radius: 6px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 0 44px;
    text-align: center;
}

.belief-card-icon {
    display: flex;
    gap: 10px;
    align-items: center;
    justify-content: center;
    margin-bottom: 52px;
}

.belief-card-icon img {
    display: block;
    height: 80px;
    width: auto;
    max-width: none;
}

.belief-card h3 {
    font-size: 28px;
    font-weight: 500;
    line-height: 1.1;
    margin: 0 0 8px;
}

.belief-card p {
    font-size: 19px;
    font-weight: 400;
    line-height: 1.3;
    margin: 0;
}

/* ==============================
   Over Section
   ============================== */

/* Belief cards leven in de image-stack, rechterhelft; tekst links ernaast */
/* De kaart staat gecentreerd in wat rechts van `left` overblijft. `left` is
   de rechte helft van het scherm, maar nooit dichter dan 40 px bij de tekst
   (die loopt tot 810 px; vanaf 1560 px tot 920 px). Sinds de kaarten groter
   zijn (2026-10-23) hield de oude formule op 1280 px nog 2 px over. */
#over .image-stack {
    left: max(50%, 850px);
    /* Eén scherm hoog, bovenaan de (lange) sectie: in rust, als de snap
       op het begin van Over mij staat, ligt de stapel midden in beeld naast
       de bio. Over de volle hoogte stond hij half onder de vouw. */
    height: 100vh;
}

/* De over-sectie groeit met de inhoud mee (de logo-grid maakt de kolom
   hoger dan één scherm) en houdt ademruimte onder de logo's/contact. */
#over {
    height: auto;
    min-height: 100vh;
}

.over-content {
    position: relative;
    color: #1a1a1a;
    max-width: 470px;
    z-index: 2;
    margin-left: 380px;
    padding: 150px 40px 150px 0;
}

.over-bio p {
    font-size: 16px;
    font-weight: 400;
    line-height: 1.45;
    letter-spacing: -0.01em;
    margin: 0 0 11px;
}

/* Eerste alinea als intro/lead — een slag groter.
   2026-10-25 alles een slag groter (Fabian): 15→16, lead 20→22; vanaf
   1560 px 18→20, lead 25→28. Breder kan niet: de tekst stopt 40 px voor
   de kaartstapel. */
.over-bio p:first-child {
    font-size: 22px;
    line-height: 1.4;
    letter-spacing: -0.015em;
    margin-bottom: 18px;
}

.over-bio p:last-child {
    margin-bottom: 0;
}

.over-tags {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    margin: 22px 0 0;
    padding: 0;
}

.over-tags li {
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
    color: #555;
    border: 1px solid #DcdbD7;
    border-radius: 999px;
    padding: 6px 12px;
}

.over-logos {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    align-items: center;
    justify-items: start;
    gap: 16px 20px;
    /* ruim los van de opsomming erboven: het zijn twee verschillende lijstjes */
    margin-top: 64px;
}

/* Logo's zijn vierkante PNG-blokken (assets/logos) met eigen witruimte */
.over-logos img {
    width: 100%;
    max-width: 88px;
    height: auto;
    opacity: 0.6;
    filter: grayscale(1);
}

/* Mobiele Over mij-layout — bestaat alleen op mobiel */
.over-mobiel {
    display: none;
}

/* Direct onder de biotekst, vóór de opsomming (2026-10-11). */
.over-contact {
    display: flex;
    gap: 24px;
    margin-top: 22px;
    margin-bottom: 34px;
}

.over-contact a {
    font-size: 15px;
    font-weight: 400;
    color: #1a1a1a;
    text-decoration: none;
    border-bottom: 1px solid #cfcec9;
    padding-bottom: 1px;
    transition: color 0.2s ease, border-color 0.2s ease;
}

.over-contact a:hover {
    color: #D62828;
    border-color: #FF3F3F;
}

/* Groot scherm: Over mij een slag groter, kaarten én tekst — op 1900 px
   breed stond het als een smal kolommetje in een leeg scherm (verzoek
   Fabian 2026-10-11).
   Twee dingen die hier eerder misgingen: het blok stond vóór de basisregels
   van .over-contact a en .over-logos img en verloor daar dus van (gelijke
   specificiteit, latere regel wint); en bij 1440 px liep de bredere tekst
   onder de grotere kaarten door. Vandaar onderaan, en pas vanaf 1560 px. */
@media (min-width: 1560px) {
    .over-content {
        max-width: 580px;
    }

    .over-bio p {
        font-size: 20px;
        margin-bottom: 14px;
    }

    .over-bio p:first-child {
        font-size: 28px;
        line-height: 1.35;
        margin-bottom: 22px;
    }

    .over-tags li {
        font-size: 14px;
        padding: 7px 13px;
    }

    .over-contact a {
        font-size: 18px;
    }

    .over-logos img {
        max-width: 104px;
    }

    #over .image-stack {
        left: max(50%, 960px);
    }

    .belief-card {
        width: 470px;
        height: 632px;
        padding: 0 52px;
    }

    .belief-card-icon {
        margin-bottom: 62px;
    }

    .belief-card-icon img {
        height: 94px;
    }

    .belief-card h3 {
        font-size: 33px;
    }

    .belief-card p {
        font-size: 23px;
    }
}

/* Smal desktopvenster: de rechterkolom is daar te krap voor 360 px.
   Onder ~1190 px past ook deze niet meer naast de tekst (dat deed de oude
   kaart ook niet). */
@media (min-width: 1250.02px) and (max-width: 1399px) {
    .belief-card {
        width: 360px;
        height: 484px;
        padding: 0 40px;
    }

    .belief-card-icon {
        margin-bottom: 48px;
    }

    .belief-card-icon img {
        height: 72px;
    }

    .belief-card h3 {
        font-size: 26px;
    }

    .belief-card p {
        font-size: 18px;
    }
}

@media (min-width: 768.02px) and (max-width: 1250px) {
    .belief-card {
        width: 300px;
        height: 404px;
        padding: 0 32px;
    }

    .belief-card-icon {
        margin-bottom: 40px;
    }

    .belief-card-icon img {
        height: 60px;
    }

    .belief-card h3 {
        font-size: 23px;
    }

    .belief-card p {
        font-size: 16px;
    }
}

/* EEN FORMAAT (2026-10-23). Elke plaat is een kader van 3:2 op dezelfde
   maat; het beeld staat er met `contain` in, dus er wordt niets
   afgesneden. Past een beeld niet precies, dan vult script.js de rest
   (`zetVulling`) met de randkleuren van het beeld zelf: de achtergrond
   komt uit het product, niet van de portfoliomaker.
   Alleen directe kinderen van een plaat: de iconen in de Over mij-kaarten
   zijn ook een img in een .stack-item. */
:root {
    --plaat-verhouding: 1.5;
    /* zo groot als past: de breedte tussen nav-kolom en rand, of de hoogte
       van het venster min wat lucht (2026-10-23: "een flinke slag groter") */
    --plaat-b: min(calc(100vw - 280px), calc((100vh - 110px) * var(--plaat-verhouding)));
}

/* Alleen desktop: `picture > img` is specifieker dan de mobiele regel en
   won daar anders, ook van zijn !important-breedte. */
@media (min-width: 768.02px) {
    .image-stack > .stack-item > img,
    .image-stack > .stack-item > video,
    .image-stack > .stack-item > picture > img,
    .image-stack > .stack-item > .placeholder {
        width: var(--plaat-b) !important;   /* !important: placeholders hebben inline maten */
        height: auto !important;
        max-width: none;
        max-height: none;
        aspect-ratio: var(--plaat-verhouding);
        object-fit: contain;
    }

    /* Niets onder de bovenste plaat zien (Fabian 2026-10-23). Ook zonder
       deal-effect stak er een lijn van 1 px uit: het kader is
       --plaat-b / 1,5 hoog, dus vaak een halve pixel, en dan dekt de
       bovenste plaat zijn eigen rand maar half. Elke plaat die niet bovenop
       ligt, wordt 1 px kleiner afgeknipt (het beeld, niet het
       .stack-item: dat is zo groot als de hele stapel). Bovenop = de actieve, of zonder
       actieve de eerste (hoogste z-index, script.js). */
    .image-stack:has(> .stack-item.active) > .stack-item:not(.active) > *,
    .image-stack:has(> .stack-item.active) > .stack-item:not(.active) > picture > img,
    .image-stack:not(:has(> .stack-item.active)) > .stack-item:not(:first-child) > *,
    .image-stack:not(:has(> .stack-item.active)) > .stack-item:not(:first-child) > picture > img {
        clip-path: inset(1px);
    }

    /* Vullend: valt er weinig weg, dan vult het beeld het kader en snijdt
       de rand een stukje af (script.js zet .vult; nooit bij Verf). */
    .image-stack > .stack-item > .vult,
    .image-stack > .stack-item > picture > .vult {
        object-fit: cover;
    }

    /* Tekstplaat: de eerste plaat van een case, even groot als de rest.
       Opbouw uit Figma (node 4156:4871, frame 1004 breed; 2026-10-24):
       linksboven de naam in het rood, daaronder de kern in één zin, groot,
       en daaronder een langere uitleg. Alle maten schalen mee met de plaat
       (Figma-px / 1004 · --plaat-b). */
    .tekstplaat-inner {
        width: var(--plaat-b);
        aspect-ratio: var(--plaat-verhouding);
        background: #fff;   /* wit, zoals de beeldplaten een vlak zijn (Fabian 2026-10-23) */
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        align-items: flex-start;
        gap: calc(var(--plaat-b) * 0.0159);                    /* 16 */
        padding: calc(var(--plaat-b) * 0.0558) 0 0 calc(var(--plaat-b) * 0.0508);   /* 56, 51 */
    }

    .tekstplaat-inner .tekstplaat-naam,
    .tekstplaat-inner .tekstplaat-tekst {
        font-size: max(14px, calc(var(--plaat-b) * 0.0197));   /* 22 in Figma, een slag kleiner (Fabian 2026-10-24) */
        line-height: 1.27;                                       /* 28 */
        font-weight: 400;
        margin: 0;
    }

    .tekstplaat-inner .tekstplaat-naam {
        /* Klein rood: #D62828 haalt AA (4,7:1 op de paginakleur, 5:1 op
           wit), het merkrood #FF3F3F niet (3,3–3,5). Groot rood (intro,
           citaat), de stip en de balkjes blijven #FF3F3F. Review 2026-10-25. */
        color: #D62828;
    }

    .tekstplaat-inner h2 {
        width: calc(var(--plaat-b) * 0.3616);                  /* 363 */
        font-size: max(19px, calc(var(--plaat-b) * 0.0269));   /* 30 in Figma, een slag kleiner */
        font-weight: 500;
        line-height: 1.2;
        letter-spacing: 0;
        color: #251d18;
        margin: 0;
    }

    .tekstplaat-inner .tekstplaat-tekst {
        width: calc(var(--plaat-b) * 0.3436);                  /* 345 */
        color: #17100f;
    }

    /* VASTKLIKKEN op het midden van een case: dan liggen alle platen exact
       op elkaar. proximity, niet mandatory: WebKit laat je bij mandatory
       niet door de lange Over mij-kolom (zie mobiel). */
    html {
        scroll-snap-type: y proximity;
    }

    .section {
        scroll-snap-align: center;
    }

    .intro-section,
    #over {
        scroll-snap-align: start;
    }

    /* Schilderijen (data-vulling="tint"): het werk een slag kleiner, zodat
       er rondom rand overblijft, ook boven en onder. De rand is een heel
       lichte, vervaagde tint van het werk zelf (script.js). Padding op een
       img met object-fit verkleint alleen het beeld, niet het kader. */
    [data-vulling="tint"] .image-stack > .stack-item > img,
    [data-vulling="tint"] .image-stack > .stack-item > video {
        padding: calc(var(--plaat-b) * 0.05);
    }
}

.placeholder {
    border-radius: 4px;
}

/* Beeld rechts op de tekstplaat (Fabian 2026-10-24): Den Haag het logo,
   Cooktus het doosje, Opkoers het logo met een pijl die je muis volgt,
   Klap het handje uit een gat. Geen <img>: alle `.stack-item img`-regels
   (maat, lazy laden, vulling) zouden het anders als plaat behandelen. */
.tekstplaat-inner {
    position: relative;
}

/* Elk beeld staat met zijn midden op hetzelfde punt: waar het logo in
   Figma staat (x 696 van 1004, ongeveer verticaal in het midden);
   --tb-b is zijn breedte. */
.tekstplaat-beeld {
    position: absolute;
    top: 50%;
    right: calc(var(--plaat-b) * 0.307);
    width: var(--tb-b);
    aspect-ratio: 1;
    translate: 50% -50%;
    background: center / contain no-repeat;
    pointer-events: none;
}

.tb-denhaag {
    --tb-b: calc(var(--plaat-b) * 0.235);   /* 236 in Figma */
    background-image: url("assets/logos/den-haag.svg");
}

.tb-cooktus {
    --tb-b: calc(var(--plaat-b) * 0.33);   /* een slag groter (Fabian 2026-10-24) */
    aspect-ratio: 1120 / 1240;
    background-image: url("cooktus/tekstplaat-doos.webp");
}

.tb-opkoers {
    --tb-b: calc(var(--plaat-b) * 0.2);
    overflow: visible;
}

.tb-klap {
    --tb-b: calc(var(--plaat-b) * 0.34);
}

/* Mobiel (Fabian 2026-10-25): het beeld hoort bij de slide, onder de tekst
   in het kaartje, links op de lijn van de tekst. Om in het vierkant te
   passen staat de tekst op mobiel een slag kleiner (zie de mobiele
   .tekstplaat-inner) en is het beeld klein. Eerder stond het los onder de
   plaat; dat las niet als deel van de slide. */
@media (max-width: 768px) {
    .tekstplaat-beeld {
        position: relative;
        display: block;
        flex: none;
        top: auto;
        right: auto;
        translate: none;
        width: var(--tb-m);
        margin: 4px 0 0;
    }

    /* Een slag groter sinds 2026-10-25 avond (Fabian; waren 14/13/11/16vw),
       met de hogere tekstplaat eromheen (--tekst-hoogte). */
    .tb-denhaag { --tb-m: 19vw; }
    .tb-cooktus { --tb-m: 18vw; }

    /* Cooktus heeft ook de bol-link: onder de tekst paste het doosje dan niet
       met 40 px lucht (31 px op 360 breed). Daarom rechtsonder in de hoek,
       naast de link. */
    .tekstplaat-inner .tb-cooktus {
        position: absolute;
        right: 22px;
        bottom: 20px;
        margin: 0;
    }
    .tb-opkoers { --tb-m: 15vw; }
    .tb-klap    { --tb-m: 22vw; }
}

/* Een link onder de tekst van een tekstplaat (Cooktus: bestellen bij bol).
   Zelfde vorm als de contactlinks in Over mij. */
.tekstplaat-link {
    margin: 8px 0 0;   /* bovenop de gap van de tekstplaat */
    font-size: 17px;
}

.tekstplaat-link a {
    color: #1a1a1a;
    text-decoration: none;
    border-bottom: 1px solid #cfcec9;
    padding-bottom: 1px;
    transition: color 0.2s ease, border-color 0.2s ease;
}

.tekstplaat-link a:hover {
    color: #D62828;
    border-color: #FF3F3F;
}

@media (max-width: 768px) {
    .tekstplaat-link {
        margin-top: 2px;
        font-size: 15px;
    }

    /* Op mobiel staat .stack-item op pointer-events: none (vegen gaat via de
       stapel), en dat erfde door: de bol-link was niet aan te tikken (code
       review 2026-10-25). De link zelf vangt de tik weer. */
    .tekstplaat-link a {
        pointer-events: auto;
    }
}

/* ==============================
   Aankondiging: tekst voor een case (en het AI-scharnier)
   ============================== */

/* Sinds 2026-10-23 heeft een case geen witte tekstkaart meer in zijn
   stapel. Hij wordt aangekondigd zoals het AI-scharnier: een scherpe zin op
   de paginakleur, met een klein label erboven. De stapel erna is alleen
   beeld. */
.aankondiging {
    display: flex;
    align-items: center;
}

/* Desktop: het blok is zo hoog als zijn tekst, niet een heel scherm, en de
   case erna sluit dichter aan. Als volle sectie stond er een half scherm
   lucht onder de tekst plus de gewone 150 px tussenruimte — te veel voor
   een zin die de volgende case inleidt (verzoek Fabian 2026-10-11).
   Mobiel: sinds 2026-10-25 ook compact, met eigen padding (zie onder). */
@media (min-width: 768.02px) {
    .aankondiging {
        height: auto;
    }

    .aankondiging + .section {
        margin-top: 60px;
    }

    /* Artikelen zo hoog als de kaarten, niet een heel scherm: de witruimte
       naar Verf en naar Over mij was te groot (Fabian 2026-10-23). */
    #artikelen {
        height: auto;
    }

    #artikelen .article-row {
        height: auto;
        padding-top: 70px;
        padding-bottom: 70px;
    }

    /* Iets ruimer dan de eerste inkorting (Fabian, later op 2026-10-23) */
    #over {
        margin-top: 150px;
    }

    .over-content {
        padding-top: 70px;
    }
}

.aankondiging-inner {
    max-width: 620px;
    margin-left: 380px;
    padding-right: 40px;
}

.aankondiging h2 {
    font-size: 34px;
    font-weight: 400;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: #000;
    margin: 0;
}

/* ==============================
   Article Cards
   ============================== */

.article-row {
    display: flex;
    gap: 28px;
    align-items: center;
    justify-content: center;
    height: 100vh;
    padding: 0 60px;
}

.article-card {
    will-change: transform;
}

.article-card-inner {
    background: #fff;
    border-radius: 0;
    padding: 0 36px 40px 44px;
    width: 340px;
    height: 440px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    position: relative;
}

/* Boekrug: subtiele gradient langs de linkerrand (#EAE9E8 → wit) */
.article-card-inner::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 10px;
    background: linear-gradient(to right, #EAE9E8, #ffffff);
    pointer-events: none;
}

/* Dunne haarlijn als rugvouw, iets ingesprongen */
.article-card-inner::after {
    content: '';
    position: absolute;
    left: 15px;
    top: 0;
    bottom: 0;
    width: 1px;
    background: #E4E3E1;
    pointer-events: none;
}

.article-card-inner h2 {
    font-size: 32px;
    font-weight: 400;
    line-height: 1.1;
    margin: 0 0 28px;
    color: #000;
    max-width: 280px;
}

/* De titel is een knop (toetsenbord, schermlezer); hij ziet eruit als de
   kop zelf, en de hele kaart blijft klikbaar via script.js. */
.article-card-knop {
    all: unset;
    display: block;
    cursor: inherit;
}

.visueel-verborgen {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* Eén regel waar het artikel over gaat (was de datum, tot 2026-10-11). */
.article-card-sub {
    display: block;
    font-size: 16px;
    font-weight: 400;
    line-height: 1.35;
    color: #666;
    max-width: 280px;
}

/* Tot ~1400 px breed passen drie kaarten van 340 px niet gecentreerd naast
   de navigatie: de rij werd afgesneden of schoof onder de nav-items. Daar
   staan ze rechts van de nav-kolom, krimpen ze mee met het venster (tot hun
   gewone 340 px) en schaalt de tekst mee. */
@media (min-width: 768.02px) and (max-width: 1400px) {
    .article-row {
        justify-content: flex-start;
        gap: 16px;
        padding: 0 32px 0 210px;
    }

    .article-card {
        flex: 1 1 0;
        min-width: 0;
        max-width: 340px;
    }

    .article-card-inner {
        width: auto;
        height: auto;
        aspect-ratio: 340 / 440;
        padding: 0 clamp(14px, 2.4vw, 36px) clamp(18px, 2.8vw, 40px) clamp(18px, 3vw, 44px);
    }

    .article-card-inner h2 {
        font-size: clamp(17px, 2.5vw, 32px);
        margin-bottom: clamp(12px, 2vw, 28px);
    }

    .article-card-sub {
        font-size: clamp(12px, 1.3vw, 16px);
    }
}

/* ==============================
   Article Slide-in Panel
   ============================== */

/* Blur overlay behind article panel.
   The blur radius is fixed and only opacity animates: animating the radius itself
   forces a full re-blur of the page every frame, fading the blurred layer is cheap. */
.article-backdrop {
    position: fixed;
    inset: 0;
    z-index: 199;
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    background: rgba(249, 248, 246, 0.4);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}

.article-backdrop.active {
    pointer-events: auto;
    opacity: 1;
}

.article-panel {
    position: fixed;
    top: 0;
    right: 0;
    width: 80%;
    height: 100vh;
    height: 100dvh; /* iOS: niet onder de URL-balk door */
    background: #fff;
    z-index: 200;
    transform: translateX(100%);
    /* Dicht = ook echt weg: zonder visibility zat de terugknop buiten beeld
       nog in de tabvolgorde. Hij verdwijnt pas als het paneel is uitgeschoven. */
    visibility: hidden;
    transition: transform 0.8s cubic-bezier(0.16, 1, 0.3, 1), visibility 0s linear 0.8s;
    will-change: transform;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 84px 120px 100px 140px;
    box-sizing: border-box;
}

/* Het paneel krijgt de focus bij openen met een tik (tabindex -1): geen ring.
   De terugknop alleen een ring als je met het toetsenbord komt. */
.article-panel:focus,
.article-panel-back:focus {
    outline: none;
}
.article-panel-back:focus-visible {
    outline: 2px solid #FF3F3F;
    outline-offset: 3px;
}

.article-panel.open {
    transform: translateX(0);
    visibility: visible;
    transition: transform 0.8s cubic-bezier(0.16, 1, 0.3, 1), visibility 0s;
}

/* Hover: het boekje draait een fractie open rond zijn rug (links) en komt
   iets naar voren (Fabian 2026-10-23). Op de binnenkaart, want de kaart zelf
   krijgt zijn transform van script.js (inschuiven). */
@media (hover: hover) and (min-width: 768.02px) {
    .article-card-inner {
        transform-origin: left center;
        transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.6s cubic-bezier(0.16, 1, 0.3, 1);
    }

    .article-card:hover .article-card-inner,
    .article-card:has(.article-card-knop:focus-visible) .article-card-inner {
        transform: perspective(1100px) rotateY(-9deg) rotate(-0.6deg) translateY(-6px);
        box-shadow: 14px 18px 30px -18px rgba(0, 0, 0, 0.28);
    }
}

@media (prefers-reduced-motion: reduce) {
    .article-card-inner { transition: none !important; }
}

/* Kaarten zijn met het toetsenbord te openen (tabindex + rol in de HTML). */
.article-card:has(.article-card-knop:focus-visible) {
    outline: 2px solid #FF3F3F;
    outline-offset: 4px;
}

.article-panel-back {
    /* Blijft staan als je door het artikel scrolt (Fabian 2026-10-25):
       sticky in het scrollende paneel, op een wit rondje zodat hij over de
       tekst leesbaar blijft. */
    position: sticky;
    /* sticky rekent vanaf de padding van het paneel (84 px desktop, 24 mobiel):
       zo staat hij 20 px onder de bovenrand van het scherm */
    top: calc(20px - var(--paneel-boven, 84px));
    z-index: 2;
    width: 44px;
    height: 44px;
    margin: 0 0 30px -12px;
    border-radius: 50%;
    /* Helemaal wit met een dunne lichtgrijze rand; ligt over de tekst heen
       (Fabian 2026-10-25, was 92 % wit met een schaduw). */
    background: #fff;
    border: 1px solid #e8e8e8;
    box-sizing: border-box;
    font-size: 24px;
    line-height: 42px;
    text-align: center;
    cursor: pointer;
    color: #1a1a1a;
    padding: 0;
    display: block;
}

/* Alle artikel-tekst deelt één kolombreedte, zodat koppen niet verder
   uitsteken dan de body. */
.article-panel-content {
    max-width: 580px;
}

.article-panel-content h1 {
    font-size: 40px;
    font-weight: 600;
    line-height: normal;
    margin: 0 0 22px;
    color: #1a1a1a;
}

.article-panel-content h2 {
    font-size: 18px;
    font-weight: 500;
    line-height: 30px;
    margin: 40px 0 4px;
    color: #1a1a1a;
}

.article-panel-content p {
    font-size: 18px;
    font-weight: 400;
    line-height: 30px;
    color: #1a1a1a;
    margin: 0 0 20px;
}

.article-panel-content blockquote {
    border-left: 4px solid #FF3F3F;
    padding: 8px 0 8px 28px;
    margin: 36px 0;
}

.article-panel-content blockquote p {
    font-size: 30px;
    font-weight: 500;
    line-height: 1.3;
    color: #FF3F3F;
    margin: 0;
}

/* ==============================
   Scrollbar hidden
   ============================== */

::-webkit-scrollbar {
    width: 0;
}

/* ==============================
   Page Entrance Animation
   ============================== */

@keyframes entranceFadeUp {
    from {
        opacity: 0;
        transform: translateY(14px);
    }
}

@keyframes entranceFade {
    from {
        opacity: 0;
    }
}

.header,
.intro-section,
.image-stack {
    opacity: 0;
}

body.loaded .header {
    opacity: 1;
    animation: entranceFadeUp 0.7s ease-out 0.1s backwards;
}

body.loaded .intro-section {
    opacity: 1;
    animation: entranceFadeUp 0.7s ease-out 0.25s backwards;
}

body.loaded .image-stack {
    opacity: 1;
    animation: entranceFade 0.8s ease-out 0.45s backwards;
}

body.loaded .nav-item {
    opacity: 1;
}

body.loaded .nav-item:nth-child(1) {
    animation: entranceFade 0.5s ease-out 0.3s backwards;
}

body.loaded .nav-item:nth-child(2) {
    animation: entranceFade 0.5s ease-out 0.4s backwards;
}

body.loaded .nav-item:nth-child(3) {
    animation: entranceFade 0.5s ease-out 0.5s backwards;
}

body.loaded .nav-item:nth-child(4) {
    animation: entranceFade 0.5s ease-out 0.6s backwards;
}

/* ==============================
   Mobiel menu — bestaat alleen op mobiel
   ============================== */

.menu-knop,
.mobiel-menu {
    display: none;
}

/* ==============================
   Mobile
   ============================== */

@media (max-width: 768px) {
    /* No custom cursor on touch. Met html.heeft-stip ervoor: anders won de
       desktopregel (cursor: none, specifieker) na het smaller maken van een
       desktopvenster en was er geen enkele cursor meer (review 2026-10-25). */
    html, body, a, button, input, textarea, select,
    html.heeft-stip, html.heeft-stip body, html.heeft-stip a, html.heeft-stip button,
    html.heeft-stip input, html.heeft-stip textarea, html.heeft-stip select { cursor: auto; }
    .cursor-dot { display: none; }

    /* Actief nav-item is hier 22 px: klein rood, dus de AA-tint */
    .nav-item.active { color: #D62828; }

    /* Horizontaal scrollen hard dichtzetten, op html én body: anders geeft de
       stapel die van rechts binnenreist scrollruimte. html is `hidden`; body
       is `clip` (zie SCROLL-SNAP hieronder — met `hidden` snapt er niets). */
    html {
        overflow-x: hidden;
    }

    :root {
        --plaat-verhouding: 1;
        /* tekstplaat: hoogte × breedte (de beeldplaten zijn 1) */
        --tekst-hoogte: 1.18;
    }

    /* Scroll-snap per case (2026-09-19). Dit stond eerder uit omdat snap
       samen met een horizontale veeg op iOS sprongen omhoog gaf. Dat kon
       gebeuren doordat de browser een schuine veeg als scroll oppakte; sinds
       script.js een duidelijk horizontaal gebaar claimt met preventDefault
       komt die scroll er niet meer, en is snap weer bruikbaar. Hiermee stop je
       nooit meer midden tussen twee cases — het "te grote gat" verdwijnt
       zonder dat er ooit twee cases tegelijk in beeld staan. */
    /* SCROLL-SNAP — elke case klikt vast op het scherm (aangezet 2026-10-11,
       keuze Fabian na de code review).
       Dingen die hier allemaal nodig zijn (plus `start`, zie .section):
       - `body` is `clip`, niet `hidden`. Met `hidden` is body zelf een
         scroll-container die nooit scrolt, en hangen de secties als
         snap-gebied dááraan: de regels stonden er dan wel, maar er snapte
         niets. Dat was van 2026-09-19 tot deze dag ongemerkt het geval.
       - `proximity`, niet `mandatory`: WebKit laat je bij mandatory niet door
         de lange Over mij-kolom scrollen (scrollTo naar het eind sprong terug
         naar het begin van #over).
       - de intro is zelf een snap-punt, anders kom je er na de eerste scroll
         niet meer terug.
       ⚠️ Toets snap met een echte scrollTo + teruglezen, nooit op de computed
       waarde van de property. */
    /* UIT sinds 2026-10-25 (iPhone 11 van een vriend: "haperig, alsof
       verschillende regels in conflict zijn"; filmpje: na een lichte veeg
       trok de pagina telkens terug naar de intro en naar Den Haag).
       WebKit noemt een snap-punt "dichtbij" binnen 0,3 × de vensterhoogte en
       trekt een lichte veeg daarbinnen terug naar het punt waar je vandaan
       kwam. Liggen twee punten minder dan 0,6 × vh uit elkaar, dan is er
       nergens meer vrije ruimte en is `proximity` in de praktijk `mandatory`.
       Sinds de secties vandaag compact zijn, is dat zo: intro → Den Haag
       0 px vrij, Den Haag → Cooktus 29 px (`node bronnen/snap-afstand.mjs`).
       De rust van de reis hangt niet meer aan de snap maar aan een vlak stuk
       in de keyframes (`reis`, 44–56 %). align en scroll-margin hieronder
       blijven staan: ze doen niets zonder snap-type, en de marge centreert
       nog wel een sectie die via de nav in beeld springt. */
    html {
        scroll-snap-type: none;
    }

    body {
        overflow-x: clip;
    }

    .header {
        scroll-snap-align: start;
    }

    /* `start`, niet `center`. Een sectie is --vh-vast hoog (gemeten bij load)
       en het venster wordt op iOS hoger als de URL-balk inklapt. Bij center
       lijnt de browser dan opnieuw uit en verspringt alles de helft van dat
       verschil: 47 px, precies de sprong van 2026-09-19. Bij start blijft de
       bovenkant staan en verandert er niets (urlbalk-check: 0 px in rust).
       De rustpositie is dezelfde: sectie-bovenkant = scherm-bovenkant. */
    .section {
        scroll-snap-align: start;
        /* Sinds 2026-10-25 is een sectie niet meer een vol scherm hoog maar
           zo hoog als zijn plaat plus lucht (Fabian: "veel te veel ruimte").
           De snap landt dan met de sectie midden in beeld via een marge
           erboven: (vensterhoogte − sectiehoogte) / 2, per sectie één keer
           gemeten in px (zetSectieHoogtes), dus net zo URL-balk-vast als
           start. */
        /* scroll-margin-top zet script.js per sectie, in px */
    }

    .aankondiging,
    #artikelen {
        scroll-snap-align: none;
    }

    /* Flex column on body for reordering */
    body {
        display: flex;
        flex-direction: column;
    }

    main { display: contents; }

    .header { order: 1; }
    .intro-section { order: 2; }
    .side-nav { order: 3; }
    .section { order: 4; }

    /* Header scrollt mee; maten uit het Figma-design (430-frame) */
    .header {
        position: relative;
        top: auto;
        left: auto;
        padding: 51px 35px 0;
        z-index: auto;
        will-change: transform;
    }

    /* Maten uit het 430-frame; onder de 430px schalen ze mee met de viewport */
    .logo-regel {
        font-size: clamp(17px, 4.65vw, 20px);
    }

    /* Intro onder het logo, ingesprongen zoals in het design */
    .intro-section {
        padding: 31px 35px 0 76px;
        will-change: transform;
    }

    .intro-text {
        font-size: clamp(25px, 6.98vw, 30px);
        line-height: 1.2;
        max-width: 320px;
    }

    /* Nav is op mobiel een statische lijst onder de intro (geen fixed side-nav);
       navigeren gaat daarna via het hamburger-menu. */
    .side-nav {
        position: static;
        width: auto;
        height: auto;
        padding: 33px 35px 0;
        pointer-events: auto;
        will-change: transform;
    }

    .nav-item {
        position: static;
        display: block;
        font-size: clamp(22px, 6.05vw, 26px);
        font-weight: 500;
        line-height: 1.2;
        margin-bottom: 10px;
        text-shadow: none;
    }

    /* Sections — JS zet de hoogte in pixels per stapel-sectie (--vh-vast).
       overflow-x: clip snijdt de stapel die van rechts binnenreist af op de
       schermrand zonder een scroll-container te worden. */
    .section,
    .section:first-of-type {
        height: auto;
        overflow: visible;
        overflow-x: clip;
        contain: none;
        isolation: isolate;
        margin-top: 0;
    }

    /* Image stack — de plaat plus lucht erboven en eronder (de indicator
       hangt 26 px onder de plaat). Sinds 2026-10-25, daarvoor één scherm
       hoog. Alleen vw en de eenmalig gemeten --vh-vast: niets dat met de
       iOS-URL-balk meelift. */
    .image-stack {
        position: relative;
        left: 0;
        right: auto;
        width: 100%;
        height: calc(min(100vw - 2 * var(--plaat-pad), var(--vh-vast, 100svh) * 0.72) + 2 * var(--stapel-lucht, 44px));
        z-index: 0;
        /* Browser handelt verticaal pannen (scroll) af; horizontale gebaren komen
           als pointer-events bij ons zodat de swipe-blader betrouwbaar werkt. */
        touch-action: pan-y pinch-zoom;
    }

    /* Met een (hogere) tekstplaat bovenop: zoveel hoger als die plaat. */
    .image-stack:has(.tekstplaat) {
        height: calc(min((100vw - 2 * var(--plaat-pad)) * var(--tekst-hoogte), var(--vh-vast, 100svh) * 0.8) + 2 * var(--stapel-lucht, 44px));
    }

    /* Stack items — alle platen liggen op elkaar en je ziet er één (de rest
       heeft .wacht); opacity + translate = wegveeg-animatie bij een swipe. */
    .stack-item {
        position: absolute;
        inset: 0;
        opacity: 1;
        /* Een veeg over de kaarttekst selecteerde woorden i.p.v. te bladeren;
           de blauwe selectiehendels bleven daarna staan. */
        -webkit-user-select: none;
        user-select: none;
        transition: opacity var(--veeg-duur, 450ms) ease, translate var(--veeg-duur, 450ms) cubic-bezier(0.16, 1, 0.3, 1);
        pointer-events: none;
        will-change: transform, opacity;
        translate: 0 0;
    }

    /* Weggeveegd werk: schuift een stukje naar links en fadet uit; terugvegen
       draait precies dezelfde beweging om. */
    .stack-item.weggeveegd {
        opacity: 0;
        translate: calc(-1 * var(--veeg-x, 56px)) 0;
    }

    /* Platen die nog komen (script.js zet .wacht) liggen sinds 2026-10-25
       zichtbaar onder de bovenste: alle mobiele platen zijn even groot
       (vierkant), dus er steekt in rust niets uit, en tijdens de reis
       waaieren ze uit (plaatreis, hieronder). Daarvoor stonden ze op
       opacity 0 en was het stapel-effect op mobiel weg. */

    /* Eén plaat tegelijk, op schermbreedte met wat lucht eromheen
       (besluit 2026-09-19). De stapel-met-randen is weg: alle platen liggen
       exact op elkaar, je ziet er één, en de balk eronder vertelt dat er meer
       er zijn. Breedte stuurt, hoogte volgt uit de verhouding; de max-hoogte
       is een vangnet voor extreem staand beeld (contain, dus nooit vervormd). */
    /* `.section` ervoor is nodig, niet cosmetisch: de desktopregel
       `.project-section .stack-item img { max-width: 62vw }` is specifieker dan
       een kaal `.stack-item img` en won anders — dan bleef een plaat op 62 % van
       het scherm steken. */
    .section .stack-item img,
    .section .stack-item video,
    .section .stack-item .placeholder {
        width: calc(100vw - 2 * var(--plaat-pad)) !important;
        height: auto !important;
        max-width: none;
        max-height: calc(var(--vh-vast, 100svh) * 0.72);
        /* een formaat, net als desktop: vierkant (de mobiele platen zijn dat
           al); script.js vult wat overblijft met de randkleuren */
        aspect-ratio: var(--plaat-verhouding);
        object-fit: contain;
    }

    .section .stack-item .vult {
        object-fit: cover;
    }

    /* Hoger dan de vierkante platen (Fabian 2026-10-25 avond: "dat hele vlak
       mag een slagje hoger, zodat die weer kleiner wordt als je naar de
       volgende gaat"). Ligt bovenop, dus er steekt in rust niets onder uit;
       veeg je door, dan zie je het vierkant eronder en glijdt de balk mee
       omhoog. De stapel reserveert die hoogte (.image-stack:has(.tekstplaat)). */
    .tekstplaat-inner {
        width: calc(100vw - 2 * var(--plaat-pad));
        aspect-ratio: 1 / var(--tekst-hoogte);
        max-height: calc(var(--vh-vast, 100svh) * 0.8);
        display: flex;
        flex-direction: column;
        justify-content: center;
        gap: 8px;
        padding: 24px;
        background: #fff;
    }

    /* Zelfde opbouw als desktop (naam, kern, uitleg, beeld), in het vierkant
       verticaal gecentreerd. Sinds 2026-10-25 een slag kleiner (was 4.1vw /
       5.6vw), zodat het beeld eronder in het vierkant past. */
    .tekstplaat-inner .tekstplaat-naam,
    .tekstplaat-inner .tekstplaat-tekst {
        font-size: clamp(13px, 3.8vw, 16px);
        line-height: 1.3;
        font-weight: 400;
        margin: 0;
    }

    .tekstplaat-inner .tekstplaat-naam {
        color: #D62828;
    }

    .tekstplaat-inner h2 {
        font-size: clamp(16.5px, 5.15vw, 22px);
        font-weight: 500;
        line-height: 1.2;
        letter-spacing: 0;
        color: #251d18;
        margin: 0;
    }

    .tekstplaat-inner .tekstplaat-tekst {
        color: #17100f;
    }

    .section[data-vulling="tint"] .stack-item img,
    .section[data-vulling="tint"] .stack-item video {
        padding: 6vw;
    }

    /* ONTHULLEN — tijdgebaseerd, niet aan de scroll gekoppeld.
       Zie script.js: alles wat aan de scrollpositie hing las op een telefoon
       als verspringen, omdat je de pagina direct met je vinger sleept en
       alles wat niet 1-op-1 meekomt kapot voelt. Nu komt een blok één keer
       op zodra het in beeld schuift. Verticaal staat het daarna stil; alleen
       de reis hieronder beweegt de stapel nog horizontaal met de scroll mee. */
    @keyframes onthul {
        from {
            opacity: 0;
            transform: translate3d(0, 28px, 0);
        }
    }

    /* ⚠️ `body.loaded .image-stack` (0,2,1) uit de desktop-entree is
       specifieker dan een kaal `.onthult` (0,1,0) en won: de klasse stond er
       wel, maar er bewoog niets. Vandaar `body.loaded` en `.image-stack`
       expliciet in de selector. Toets dit nooit op "staat de klasse er" maar
       op "loopt er een animatie" — zie bronnen/onthul-check.mjs. */
    body.loaded .image-stack.onthult,
    body.loaded .onthult {
        opacity: 0;
        animation: none;
    }

    body.loaded .image-stack.onthult.onthuld,
    body.loaded .onthult.onthuld {
        opacity: 1;
        animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) backwards;
    }

    /* REIS — de stapel komt van rechts het scherm in en gaat er rechts weer
       uit, gekoppeld aan de scroll (gevraagd 2026-10-11; dezelfde beweging als
       desktop). Dit is bewust het enige scroll-gestuurde op de platen, en het
       blijft binnen wat de ronde van 2026-09-19 leerde:
       - alleen horizontaal. Verticaal komt de plaat 1-op-1 met de vinger mee;
         wat toen als verspringen las, was beweging lángs de scrollrichting.
       - de stapel reist als één object (de platen liggen op elkaar).
       - de scroll-snap legt elke case precies op 50 % neer, dus in rust staat
         de plaat altijd exact in het midden — nooit half onderweg.
       - de tijdlijn loopt op de compositor (scroll()), niet via JS per frame.
       Geen view(): die hangt aan de dichtstbijzijnde scroll-container, en dat
       was hier `body` (overflow-x: hidden maakte er een van) — die scrolt nooit,
       dus de tijdlijn stond stil op 50 %. Body is inmiddels `clip`, maar
       scroll(root) hangt daar niet van af en blijft dus de veilige keuze. Daarom de pagina-scroll zelf, met
       per stapel het bereik in px uit script.js (--reis-van / --reis-tot:
       één scherm vóór tot één scherm ná de rustpositie).
       `translate` en niet `transform`: de onthul-animatie en de veeg gebruiken
       die al. Afstand: --reis-x uit motion.js (mobiel.reisX). */
    /* Rustzone 44–56 %: het bereik is 2 × vh, dus de stapel ligt stil zolang
       de sectie binnen 0,12 × vh van het midden staat (~85 px op een iPhone
       11). Zonder snap stop je nooit exact op het midden; dit vangt dat op.
       Zelfde getal als REIS_RUST in script.js (de JS-terugval). */
    @keyframes reis {
        from { translate: var(--reis-x, 90vw) 0; animation-timing-function: cubic-bezier(0.3, 0.2, 0.4, 1); }
        44%  { translate: 0 0; animation-timing-function: linear; }
        56%  { translate: 0 0; animation-timing-function: cubic-bezier(0.6, 0, 0.7, 0.8); }
        to   { translate: var(--reis-x, 90vw) 0; }
    }

    @supports (animation-timeline: scroll()) {
        @media (prefers-reduced-motion: no-preference) {
            body.loaded .image-stack.onthult.onthuld {
                animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) backwards, reis linear both;
                animation-timeline: auto, scroll(root);
                animation-range-start: normal, var(--reis-van, 0px);
                animation-range-end: normal, var(--reis-tot, 100%);
            }
        }
    }

    /* Minder beweging gevraagd: niets komt op, alles staat er gewoon. */
    @media (prefers-reduced-motion: reduce) {
        body.loaded .image-stack.onthult,
        body.loaded .onthult {
            opacity: 1;
        }

        body.loaded .onthult.onthuld,
        body.loaded .onthult.onthuld .stack-item,
        .article-row.onthuld .article-card,
        .over-kaartwaaier.onthuld .belief-mini {
            animation: none !important;
        }
    }

    /* De platen van een case komen na elkaar op, niet als één blok. */
    body.loaded .onthult.onthuld .stack-item:nth-child(1) { animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) 0.04s backwards; }
    body.loaded .onthult.onthuld .stack-item:nth-child(2) { animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) 0.09s backwards; }
    body.loaded .onthult.onthuld .stack-item:nth-child(n+3) { animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) 0.14s backwards; }

    /* STAPEL-EFFECT (2026-10-25, Fabian: "het effect van de stapel is
       helemaal verdwenen op mobiel"). Tijdens de reis reizen de platen onder
       de bovenste minder ver (--f per plaat uit script.js: bovenste 1, de
       volgende 0.45, 0.3, 0.2, daarna 0.12), dus hun randen steken links
       uit als een uitgewaaierd kaartspel. Alleen horizontaal, zelfde
       tijdlijn en easing als `reis`, in rust 0. `transform` op de plaat:
       `translate` is van de veeg, en de stapel zelf reist al met translate.
       Daarom komen de platen hier alleen met opacity op (onthulZacht); de
       stapel als geheel doet nog de onthul met beweging. */
    @keyframes plaatreis {
        from { transform: translate3d(calc(var(--reis-x, 90vw) * (var(--f, 1) - 1)), 0, 0); animation-timing-function: cubic-bezier(0.3, 0.2, 0.4, 1); }
        44%  { transform: translate3d(0, 0, 0); animation-timing-function: linear; }
        56%  { transform: translate3d(0, 0, 0); animation-timing-function: cubic-bezier(0.6, 0, 0.7, 0.8); }
        to   { transform: translate3d(calc(var(--reis-x, 90vw) * (var(--f, 1) - 1)), 0, 0); }
    }

    @keyframes onthulZacht {
        from { opacity: 0; }
    }

    /* Over mij-kaarten: alleen het binnenkomen, daarna blijven ze liggen */
    /* 88 %: het bereik is 1 × vh, dus ze liggen al 0,12 × vh vóór het midden
       stil (zelfde rustzone als `reis`). */
    @keyframes reisIn {
        from { translate: var(--reis-x, 90vw) 0; animation-timing-function: cubic-bezier(0.3, 0.2, 0.4, 1); }
        88%  { translate: 0 0; }
        to   { translate: 0 0; }
    }

    @keyframes plaatreisIn {
        from { transform: translate3d(calc(var(--reis-x, 90vw) * (var(--f, 1) - 1)), 0, 0); animation-timing-function: cubic-bezier(0.3, 0.2, 0.4, 1); }
        88%  { transform: translate3d(0, 0, 0); }
        to   { transform: translate3d(0, 0, 0); }
    }

    @supports (animation-timeline: scroll()) {
        @media (prefers-reduced-motion: no-preference) {
            body.loaded .image-stack.onthult.onthuld .stack-item {
                animation: onthulZacht var(--onthul-duur, 750ms) ease-out 0.04s backwards, plaatreis linear both;
                animation-timeline: auto, scroll(root);
                animation-range-start: normal, var(--reis-van, 0px);
                animation-range-end: normal, var(--reis-tot, 100%);
            }

            /* Over mij-kaarten ("waar ik in geloof") schuiven op mobiel ook
               van rechts in, met dezelfde waaier (Fabian 2026-10-25). */
            body.loaded .over-kaartwaaier.onthuld {
                animation: reisIn linear both;
                animation-timeline: scroll(root);
                animation-range-start: var(--reis-van, 0px);
                animation-range-end: var(--reis-tot, 100%);
            }

            body.loaded .over-kaartwaaier.onthuld .belief-mini {
                animation: onthulZacht var(--onthul-duur, 750ms) ease-out 0.05s backwards, plaatreisIn linear both;
                animation-timeline: auto, scroll(root);
                animation-range-start: normal, var(--reis-van, 0px);
                animation-range-end: normal, var(--reis-tot, 100%);
            }
        }
    }

    .article-row.onthuld .article-card:nth-child(1) { animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) 0.05s backwards; }
    .article-row.onthuld .article-card:nth-child(2) { animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) 0.17s backwards; }
    .article-row.onthuld .article-card:nth-child(3) { animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) 0.29s backwards; }

    .over-kaartwaaier.onthuld .belief-mini:nth-child(1) { animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) 0.05s backwards; }
    .over-kaartwaaier.onthuld .belief-mini:nth-child(2) { animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) 0.13s backwards; }
    .over-kaartwaaier.onthuld .belief-mini:nth-child(3) { animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) 0.21s backwards; }
    .over-kaartwaaier.onthuld .belief-mini:nth-child(4) { animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) 0.29s backwards; }
    .over-kaartwaaier.onthuld .belief-mini:nth-child(n+5) { animation: onthul var(--onthul-duur, 750ms) cubic-bezier(0.16, 1, 0.3, 1) 0.37s backwards; }

    /* Indicator onder de plaat — uit Figma (node 4136:9): een brede grijze
       balk met een korte rode balk die aangeeft waar je zit. Maten 1-op-1:
       7 px hoog, volledig rond, spoor #e8e8e8, rood #ff3f3f van 56 px.
       De rode balk schuift lineair van helemaal links (eerste plaat) naar
       helemaal rechts (laatste); script.js zet --p (0–1).
       Hangt onder de plaat die je nu ziet: script.js meet de onderrand van
       het beeld zelf en zet `--onder` in px vanaf de bovenkant van de stapel.
       Een eerdere versie rekende vanuit het midden (halve hoogte + marge) en
       stond dus óp alles wat niet precies gecentreerd lag, zoals de
       tekstkaart. */
    .stapel-indicator {
        position: absolute;
        top: var(--onder, 78%);
        left: var(--plaat-pad);
        right: var(--plaat-pad);
        height: 4px;   /* 7 uit Figma; Fabian 2026-10-25: minder hoog */
        border-radius: 100px;
        background: #e8e8e8;
        transition: top 0.45s cubic-bezier(0.16, 1, 0.3, 1);
        z-index: 20;
        pointer-events: none;
    }

    .stapel-indicator span {
        position: absolute;
        top: 0;
        left: calc((100% - 56px) * var(--p, 0));
        width: 56px;
        height: 4px;
        border-radius: 100px;
        background: #FF3F3F;
        transition: left 0.45s cubic-bezier(0.16, 1, 0.3, 1);
    }

    /* De waaier van Over mij heeft geen stapel-container; daar staat de balk
       in de tekstkolom, recht onder de kaarten. */
    .stapel-indicator--waaier {
        position: relative;
        top: auto;
        left: auto;
        right: auto;
        transition: none;
        /* even breed als de gecentreerde waaier erboven, en er recht onder */
        width: 314px;
        margin: 36px 0 36px calc(50vw - 157px - 46px);
    }

    /* De intro-lagen worden door JS geparallaxeerd (inline transform); de
       entree eroverheen is een gewone tijdanimatie op opacity, zodat de twee
       elkaar niet in de weg zitten. */
    body.loaded .header { animation: entranceFade 0.7s ease-out 0.1s backwards; }
    body.loaded .intro-section { animation: entranceFade 0.7s ease-out 0.25s backwards; }
    body.loaded .side-nav { animation: entranceFade 0.7s ease-out 0.35s backwards; }

    .side-nav {
        opacity: 0;
    }

    body.loaded .side-nav {
        opacity: 1;
    }



    /* ?diag-badge (zie script.js) */
    .diag-badge {
        position: fixed;
        left: 10px;
        bottom: 10px;
        z-index: 900;
        padding: 7px 12px;
        border-radius: 999px;
        background: rgba(0, 0, 0, 0.82);
        color: #fff;
        font-size: 12px;
        font-weight: 500;
        font-variant-numeric: tabular-nums;
        pointer-events: none;
    }

    .preloader-teller {
        left: 35px;
    }

    .preloader-venster {
        font-size: clamp(22px, 6.05vw, 26px);
        font-weight: 500;
    }

    /* Over mij — eigen mobiele layout (Figma 4118:396): kop, kaartwaaier,
       bio, pill-knoppen, logo-grid. De desktop-stack en -kolom gaan uit. */
    #over .image-stack,
    #over .over-content {
        display: none;
    }

    .over-mobiel {
        display: block;
        padding: 120px 23px 80px 46px;
    }

    .over-mobiel-kop {
        font-size: clamp(24px, 6.51vw, 28px);
        font-weight: 500;
        line-height: 1.1;
        letter-spacing: -0.02em;
        color: #000;
        max-width: 361px;
        margin: 0 0 36px;
    }

    /* Stapel van mini-kaarten, exact op elkaar zoals de werk-stapels
       (2026-10-23; daarvoor een waaier, licht verschoven). */
    .over-kaartwaaier {
        position: relative;
        height: 375px;
        /* De waaier zelf is 314 px breed (kaart 275 + 39 verschuiving) en
           staat midden op het SCHERM, niet midden in de kolom: de kolom
           heeft links 46 px en rechts 23 px lucht, dus kolom-midden is
           scheef. In het Figma-frame stond hij links — gecentreerd op
           verzoek van Fabian (2026-10-11). */
        width: 314px;
        margin: 0 0 36px calc(50vw - 157px - 46px);
        /* Zonder dit pakt de browser de veeg als scroll en gebeurt er niets
           met de kaarten (klacht 2026-09-19). Verticaal pannen blijft van de
           browser, horizontaal komt bij ons terecht — net als bij .image-stack. */
        touch-action: pan-y pinch-zoom;
    }

    .belief-mini {
        position: absolute;
        left: 19.5px;   /* midden in de waaier: (314 − 275) / 2 */
        top: 13px;      /* (375 − 349) / 2 */
        width: 275px;
        height: 349px;
        border-radius: 4px;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        text-align: center;
        padding: 0 20px;
        /* Zelfde veeg-model als de werk-stapels */
        transition: opacity var(--veeg-duur, 450ms) ease, translate var(--veeg-duur, 450ms) cubic-bezier(0.16, 1, 0.3, 1);
        translate: 0 0;
    }

    .belief-mini.weggeveegd {
        opacity: 0;
        translate: calc(-1 * var(--veeg-x, 56px)) 0;
    }

    /* Rondgaan (script.js, rondVooruit/rondTerug): .veeg-stil zet een plaat
       zonder beweging op zijn plek, .veeg-zacht laat hem alleen opkomen (niet
       schuiven), .veeg-uit laat hem op zijn plek vervagen. */
    .stack-item.veeg-zacht,
    .belief-mini.veeg-zacht {
        transition: opacity var(--veeg-duur, 450ms) ease;
    }
    .stack-item.veeg-uit,
    .belief-mini.veeg-uit {
        opacity: 0;
    }
    .stack-item.veeg-stil,
    .belief-mini.veeg-stil {
        transition: none !important;
    }

    .belief-mini-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        margin-bottom: 40px;
    }

    .belief-mini-icon img {
        display: block;
        width: auto;
        max-width: none;
    }

    .belief-mini h3 {
        font-size: 21px;
        font-weight: 600;
        line-height: 1.1;
        margin: 0 0 8px;
    }

    .belief-mini p {
        font-size: 15px;
        font-weight: 400;
        line-height: 1.3;
        margin: 0;
    }

    .over-mobiel-bio p {
        font-size: 20px;
        font-weight: 400;
        line-height: 1.3;
        letter-spacing: -0.02em;
        color: #000;
        max-width: 331px;
        margin: 0 0 16px;
    }

    .over-knoppen {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 20px;
        width: 292px;
        margin: 36px 0;
    }

    .over-pill {
        display: flex;
        align-items: center;
        justify-content: center;
        background: #D62828;   /* wit erop: AA (5:1), #FF3F3F haalde 3,5 */
        color: #fff;
        text-decoration: none;
        border-radius: 100px;
        padding: 18px 24px;
        font-size: 20px;
        font-weight: 500;
        line-height: 1.1;
        white-space: nowrap;
    }

    .over-pill--vol {
        width: 100%;
    }

    .over-mobiel-logos {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 16px 40px;
        align-items: center;
        justify-items: center;
        max-width: 361px;
        margin-top: 44px;
    }

    .over-mobiel-logos img {
        width: 100%;
        max-width: 94px;
        height: auto;
    }

    /* Aankondiging: geen stapel en geen eigen scherm meer (2026-10-25,
       Fabian: te veel ruimte tussen de secties); hij snapt ook niet, de case
       eronder wel. */
    .aankondiging {
        min-height: 0;
        padding: 40px 35px;
    }

    .aankondiging-inner {
        margin-left: 0;
        padding-right: 0;
        max-width: none;
    }

    .aankondiging h2 {
        font-size: clamp(22px, 6.2vw, 27px);
    }

    /* Artikelen: horizontale rij, native scrollen met snap per kaart */
    .article-row {
        flex-direction: row;
        align-items: center;
        /* Niet centreren: in een scroller valt de eerste kaart dan links
           buiten het scrollbare gebied */
        justify-content: flex-start;
        gap: 20px;
        /* boven ruimer: tussen Verf en Artikelen mocht meer lucht (Fabian
           2026-10-25) */
        padding: 96px 24px 44px;
        height: auto;
        overflow-x: auto;
        overflow-y: hidden;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    .article-row::-webkit-scrollbar {
        display: none;
    }

    .article-card {
        flex: 0 0 auto;
        scroll-snap-align: center;
    }

    .article-card-inner {
        width: min(76vw, 340px);
        height: 440px;
        padding: 0 24px 32px 36px;
    }

    .article-card-inner h2 {
        font-size: 1.5rem;
        line-height: 1.2;
        max-width: 100%;
    }

    .article-card-sub {
        font-size: 14px;
    }

    .article-panel {
        width: 100%;
        padding: 24px;
        --paneel-boven: 24px;
    }

    /* Mobiel dekt het paneel het hele scherm: de vervaging erachter zie je
       alleen tijdens het inschuiven, en een vervagende backdrop-filter
       flikkert in WebKit. Daar alleen een egale waas. */
    .article-backdrop {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(249, 248, 246, 0.6);
    }

    /* ------------------------------
       Hamburger-knop — schuift van boven in beeld zodra de intro-tekst
       (bijna) uit beeld is, en blijft daarna vast staan.
       ------------------------------ */
    .menu-knop {
        display: block;
        position: fixed;
        top: 32px;
        left: 33px;
        width: 43px;
        height: 43px;
        padding: 0;
        border: none;
        background: none;
        z-index: 300;
        translate: 0 -96px;
        transition: translate 0.55s cubic-bezier(0.16, 1, 0.3, 1),
                    opacity 0.2s ease;
    }

    .menu-knop svg {
        display: block;
    }

    .menu-knop.zichtbaar {
        translate: 0 0;
    }

    /* Staat er een artikel open, dan hoort de hamburger er niet overheen */
    body.artikel-open .menu-knop {
        opacity: 0;
        pointer-events: none;
    }

    /* ------------------------------
       Fullscreen menu — rood vlak dat als cirkel vanuit de hamburger
       opengroeit; content fadet gestaggerd in.
       ------------------------------ */
    .mobiel-menu {
        display: block;
        position: fixed;
        inset: 0;
        background: #D62828;   /* wit erop: AA (5:1), #FF3F3F haalde 3,5 */
        z-index: 400;
        /* Zelfde eenheid (vmax) voor dicht en open: px↔% interpoleert niet,
           waardoor de cirkel-transitie anders bevriest op het beginpunt. */
        clip-path: circle(0vmax at 54px 54px);
        visibility: hidden;
        transition: clip-path 0.5s cubic-bezier(0.3, 0, 0.2, 1),
                    visibility 0s linear 0.5s;
        overflow-x: hidden;
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    .mobiel-menu.open {
        clip-path: circle(125vmax at 54px 54px);
        visibility: visible;
        transition: clip-path 0.6s cubic-bezier(0.3, 0, 0.2, 1);
    }

    .mobiel-menu-sluit {
        position: absolute;
        top: 52px;
        left: 30px;
        width: 36px;
        height: 36px;
        padding: 4px;
        border: none;
        background: none;
    }

    .mobiel-menu-sluit svg {
        display: block;
    }

    /* Verticale maten schalen mee met de schermhoogte (svh), zodat het menu
       ook in lage viewports (in-app browsers) volledig past. */
    .mobiel-menu-inhoud {
        padding: clamp(70px, 13svh, 117px) 36px 40px;
        color: #fff;
    }

    /* Zelfde opbouw als de intro-pagina, maar dan wit op rood */
    .mobiel-menu-logo {
        display: flex;
        flex-direction: column;
    }

    .mobiel-menu-logo .logo-regel {
        font-size: clamp(17px, 4.65vw, 20px);
        color: #fff;
    }

    .mobiel-menu-intro {
        font-size: clamp(19px, min(6.98vw, 3.6svh), 30px);
        font-weight: 400;
        line-height: 1.2;
        letter-spacing: -0.01em;
        max-width: min(320px, calc(100vw - 118px));
        margin: var(--menu-gat) 0 0 41px;
    }

    /* Logo → tekst en tekst → nav even ver (Fabian 2026-10-25), zoals op de
       pagina zelf (31 en 33 px); op een laag scherm krimpt het mee. */
    .mobiel-menu {
        --menu-gat: clamp(18px, 4.3svh, 32px);
    }

    .mobiel-menu-nav {
        display: flex;
        flex-direction: column;
        margin-top: var(--menu-gat);
    }

    .mobiel-menu-nav a {
        color: #fff;
        text-decoration: none;
        font-size: clamp(18px, min(6.05vw, 3.1svh), 26px);
        font-weight: 500;
        line-height: 1.2;
        margin-bottom: 10px;
    }


    /* Gestaggerde entree van de menu-content */
    .mobiel-menu-inhoud > *,
    .mobiel-menu-nav a {
        opacity: 0;
        transform: translateY(14px);
        transition: opacity 0.35s ease, transform 0.35s ease;
    }

    /* De nav-container zelf niet dubbel faden — alleen z'n links */
    .mobiel-menu-nav {
        opacity: 1;
        transform: none;
        transition: none;
    }

    .mobiel-menu.open .mobiel-menu-inhoud > *,
    .mobiel-menu.open .mobiel-menu-nav a {
        opacity: 1;
        transform: none;
    }

    .mobiel-menu.open .mobiel-menu-logo { transition-delay: 0.18s; }
    .mobiel-menu.open .mobiel-menu-intro { transition-delay: 0.24s; }
    .mobiel-menu.open .mobiel-menu-nav a:nth-child(1) { transition-delay: 0.30s; }
    .mobiel-menu.open .mobiel-menu-nav a:nth-child(2) { transition-delay: 0.35s; }
    .mobiel-menu.open .mobiel-menu-nav a:nth-child(3) { transition-delay: 0.40s; }
    .mobiel-menu.open .mobiel-menu-nav a:nth-child(4) { transition-delay: 0.45s; }


}

/* Een sectie krijgt de focus na een menulink (tabindex -1); geen ring om
   een hele sectie heen. */
.section:focus {
    outline: none;
}

/* Minder beweging (review 2026-10-25): ook de desktop-entree, het
   artikelpaneel en de menucirkel bewegen dan niet. Ze verschijnen gewoon. */
@media (prefers-reduced-motion: reduce) {
    body.loaded .header,
    body.loaded .intro-section,
    body.loaded .image-stack,
    body.loaded .nav-item,
    body.loaded .side-nav {
        animation: none !important;
    }

    .article-panel,
    .article-backdrop,
    .mobiel-menu,
    .mobiel-menu-inhoud > *,
    .mobiel-menu-nav a {
        transition: none !important;
    }
}

/* iOS weigert autoplay soms (energiebesparing) en zet dan een speelknop op
   de video die je niet kunt aantikken. Weg ermee; script.js start de video
   bij de eerste aanraking (geefVideosVrij). */
video::-webkit-media-controls-start-playback-button,
video::-webkit-media-controls-overlay-play-button {
    display: none !important;
    -webkit-appearance: none;
}
video::-webkit-media-controls {
    display: none !important;
}
