/* ============================================================
   2BU$Y — visual system
   Energy: Dutch main-stage pop/house. Electric blue signal,
   near-black canvas, festival-poster display type, glossy motion.
   ============================================================ */

/* ---- Lettertypes, zelf gehost (2026-10-06) -----------------
   Stonden tot nu toe bij fonts.googleapis.com. Dat betekende dat Google het
   IP-adres van elke bezoeker zag, op elke pagina, vóórdat er iets te kiezen
   was — en het stond in geen van de twee juridische teksten. Nu van eigen
   domein: geen derde partij, geen extra DNS- en TLS-handshake.

   Dit zijn de VARIABELE versies: één bestand per familie dekt 400 t/m 700,
   waar de Google-aanroep vier losse gewichten per familie haalde (inclusief
   300, dat nergens gebruikt werd). Samen 70 kB.

   Alleen de `latin`-subset. `latin-ext` (Pools, Tsjechisch, Hongaars) is
   104 kB extra voor tekens die in Nederlandse content niet voorkomen; komt er
   ooit toch zo'n teken voorbij, dan valt alleen dát teken terug op Arial.

   De ?v=1 is handwerk en geen vergissing: serveFile() geeft alles met een ?v=
   een jaar `immutable` mee, en deze bestanden veranderen nooit. Vervang je er
   ooit één, verhoog dan het getal. */
@font-face{
  font-family:'Inter';
  src:url('fonts/inter-var.woff2?v=1') format('woff2');
  font-weight:400 700;
  font-style:normal;
  font-display:swap;
}
@font-face{
  font-family:'Oswald';
  src:url('fonts/oswald-var.woff2?v=1') format('woff2');
  font-weight:400 700;
  font-style:normal;
  font-display:swap;
}

/* ---- Tokens ------------------------------------------------ */
:root{
  --accent:#0066ff;
  --accent-2:oklch(0.62 0.20 295);     /* violet sibling, same energy */
  --accent-ink:#ffffff;                /* text on accent fills        */

  /* TWEE fonts, elk met een eigen taak:
       display = Oswald  → wat je ZIET: grote koppen, logo, menu-overlay.
                           Smal en hoog, posterachtig — dezelfde rol als het
                           oude Anton, maar met meerdere gewichten.
       text/mono = Inter → wat je LEEST: menu, knoppen, lopende tekst, labels.
                           Gemaakt voor schermen; hoge x-hoogte, dus scherp op
                           13–15px. Daar zat het leesprobleem.

     LET OP bij display: Oswald gaat tot gewicht 700 (niet 900). Koppen staan
     daarom op 600, de grootste (hero + footer-logo) op 700.
     mono is bewust dezelfde familie als text — het verschil zit nu in
     hoofdletters + letterafstand, niet in een ander lettertype. */
  --font-stack:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --font-display:'Oswald', 'Arial Narrow', var(--font-stack);
  --font-text:'Inter', var(--font-stack);
  --font-mono:'Inter', var(--font-stack);

  --motion:1;                           /* 0..1.4 motion multiplier    */

  /* dark is default */
  --bg:#050507;
  --bg-2:#0b0c11;
  --surface:#0e0f16;
  --text:#f4f5f7;
  --muted:#8b8e9c;
  /* De kleur van LOPENDE TEKST (2026-09-18). Bewust een eigen token en niet
     --muted: dat is de kleur van bijzaken (labels, eyebrows, de footerregel)
     en op een hele alinea leest die te donker. Deze zit tussen --muted en
     --text in: rustig genoeg om **vet** er wit bovenuit te laten springen,
     licht genoeg om een lap tekst prettig te lezen. Zie "RIJKE TEKST". */
  --text-soft:#c3c6d0;
  --line:rgba(255,255,255,0.12);
  --line-strong:rgba(255,255,255,0.22);
  --ph-a:rgba(255,255,255,0.05);
  --ph-b:rgba(255,255,255,0.02);
  --glass:rgba(12,13,18,0.55);
}

[data-theme="light"]{
  --bg:#eef0ee;
  --bg-2:#e4e6e4;
  --surface:#ffffff;
  --text:#07080c;
  --muted:#5b5e69;
  --text-soft:#34373f;                  /* zie --text-soft hierboven */
  --line:rgba(0,0,0,0.12);
  --line-strong:rgba(0,0,0,0.24);
  --ph-a:rgba(0,0,0,0.06);
  --ph-b:rgba(0,0,0,0.02);
  --glass:rgba(255,255,255,0.6);
  --accent-ink:#ffffff;
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}

body{
  background:var(--bg);
  color:var(--text);
  font-family:var(--font-text);
  font-weight:400;
  line-height:1.45;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
  transition:background .6s ease, color .6s ease;
}
body.no-scroll{overflow:hidden;height:100vh}

a{color:inherit;text-decoration:none}
button{font-family:inherit;cursor:pointer}
img,canvas{display:block;max-width:100%}
::selection{background:var(--accent);color:#fff}

/* Hier stond de regel die de gewone muisaanwijzer verbergde (`cursor:none`)
   ten gunste van een zelfgetekende cursor. Die is er op 2026-09-15 helemaal
   uit — zie het kopje CURSOR verderop. */

/* ---- Layout helpers --------------------------------------- */
.wrap{width:min(1400px,92vw);margin-inline:auto}
/* Kleine labels blijven in hoofdletters — dat is hier stijl, geen leestekst.
   Wel veel minder letterafstand: 0.28em was te ver uit elkaar om vlot te lezen. */
.eyebrow{
  font-family:var(--font-mono);
  font-size:clamp(11px,0.85vw,13px);
  font-weight:600;
  letter-spacing:0.13em;
  text-transform:uppercase;
  color:var(--muted);
}
.accent{color:var(--accent)}
/* Verberg op mobiel — voor bijzaak-tekst die op smalle schermen alleen
   ruimte kost (bijv. de intro-regel rechts in een .sec-head, die door
   flex-wrap onder de titel valt). Zet 'hide-mobile' naast de bestaande
   klassen; hier centraal geregeld, niet per plek. */
@media(max-width:700px){.hide-mobile{display:none}}
section{position:relative}
.sec-pad{padding:clamp(80px,11vh,160px) 0}
/* Alle secties staan op --bg. Er was een `.sec-alt` die Mixes en
   Tekst + Afbeelding op --bg-2 zette om secties van elkaar te scheiden; op
   verzoek weg (2026-09-16), zodat de pagina één doorlopend zwart vlak is.
   De FOOTER houdt --bg-2 — dat is nu het enige dat van de ondergrond afwijkt,
   en precies daardoor markeert het het einde van de pagina. */

/* De intro-regel rechtsboven in een .sec-head. Smal gehouden (ongeveer een
   halve regel), zodat hij naast de kop past en niet mee-uitdijt. De maten
   stonden eerder inline per sectie; hier is 30ch de standaard en is 34ch de
   uitzondering voor twee blokken met een langere tekst. */
.sec-intro{max-width:30ch;text-align:right}
.sec-intro-breed{max-width:34ch}
/* Contact heeft geen .sec-head maar een eigen kolom: ruimer en links uitgelijnd. */
.ct-intro{max-width:36ch;line-height:1.8}
/* Melding op de plek van een lege lijst ("Nog geen shows aangekondigd"). */
.list-empty{padding:22px 0}

.sec-head{display:flex;align-items:flex-end;justify-content:space-between;
  gap:24px;flex-wrap:wrap;margin-bottom:clamp(32px,5vh,64px)}
.sec-title{
  font-family:var(--font-display);
  font-weight:600;                 /* Oswald gaat tot 700; 600 = de koppenstijl */
  line-height:0.88;
  letter-spacing:0.01em;
  text-transform:uppercase;
  /* h1-maat. De ondergrens ging op 2026-09-18 van 42px naar 56px — zie de
     uitleg bij h2.sec-title hieronder: op alles onder 950px was de h1 KLEINER
     dan de h2 eronder, omdat deze regel op 42px bleef staan terwijl de h2 nog
     doorgroeide. Boven 700px (waar 8vw de 56px passeert) verandert er niets.
     2026-10-19 (op verzoek): h1 = clamp(52px,7vw,96px) en h2 =
     clamp(36px,4vw,56px), dus h2 ≈ 4/7 (0,57) × h1. Die verhouding vervangt
     de 0,68 uit de uitleg hieronder; de cqi-koppen (Contact, FAQ) volgen hem. */
  font-size:clamp(52px,7vw,96px);
}
/* Alle h2-koppen op 64px (2026-09-15, op verzoek). Bewust `h2.sec-title` en
   niet `.sec-title`: dezelfde klasse kan via "Kopniveau" in het CMS ook een h1
   zijn (op /mixtapes en /agenda is dat zo), en die houdt zijn eigen maat uit de
   regel hierboven. Een klasse + een tag wint van alleen de klasse, dus dit
   overschrijft precies de h2's en laat de h1's met rust.
   De twee andere koppen (.ti-title en .ct-title) staan bij hun eigen blok op
   dezelfde maat, en volgen sinds 2026-09-20 allebei hetzelfde klasse/tag-patroon
   als hier: de klasse draagt de h1-maat, `h2.ti-title` en `h2.ct-title`
   overschrijven hem naar de h2-maat. Alle drie de koppen kunnen nu dus een h1
   zijn — de keuze "Kopniveau" zit bij élk blok met een titel in het CMS.

   VLOEIEND GEMAAKT (2026-09-18) — 76px is het PLAFOND, niet de enige maat.
   Waarom: 76px stond vast terwijl elke andere maat in deze sheet meeschaalt,
   en een lang woord kan niet afbreken. "SOUNDCLOUD" is op 76px 426px breed;
   .wrap is 92vw, dus 359px op een telefoon van 390px. Die 67px verschil kon je
   op /muziek wegscrollen — de hele pagina was te breed.

   AAN DE H1 GEKOPPELD (2026-09-18, later die dag, op verzoek). De eerste versie
   hierboven gebruikte 16vw: de grootste waarde waarbij "SOUNDCLOUD" op 320px
   nog binnen 92vw past. Dat loste het scrollen op, maar legde een tweede fout
   bloot die er al langer zat: op ELK scherm onder 950px was de h1 KLEINER dan
   de h2. De twee koppen hadden namelijk niets met elkaar te maken — de h1 loopt
   op 8vw naar een plafond van 140px, de h2 liep op 16vw naar 76px, dus de h2
   groeide dubbel zo hard en de h1 stond op een ondergrens van 42px stil.
   Gemeten op een telefoon van 390px: h1 42px, h2 62px — de paginatitel was daar
   een derde KLEINER dan de sectiekop eronder, terwijl hij op een laptop van
   1400px juist 1,47× zo groot is.

   Daarom is deze maat nu AFGELEID van de h1 in plaats van los gekozen:

       h2 = 0,68 × h1   →   8vw × 0,68 = 5,44vw
       ondergrens: 56px × 0,68 = 38px     plafond: 76px (ongewijzigd)

   0,68 is niet verzonnen: 76 ÷ 112 is precies de verhouding die op een scherm
   van 1400px al op de site stond. Het gevolg is dat h1 en h2 zich nu op élke
   breedte tot 1400px als 1,47 : 1 verhouden — dezelfde verhouding als op de
   laptop waar de maten vandaan komen. Vanaf 1400px verandert er niets: daar
   loopt deze clamp tegen zijn plafond van 76px, precies als hiervoor.

   Onder 1400px wordt de h2 wél kleiner (390px: 62 → 38px, 1024px: 76 → 56px).
   Dat is de bedoeling — die 62px op een telefoon was het gevolg van een maat
   die zo ruim mogelijk was gekozen, niet van een ontwerpkeuze.

   Zelfde clamp bij h2.ti-title en h2.ct-title — die drie horen dezelfde
   maat te houden. Verander je er één, verander dan alle drie.
   Het vangnet voor woorden die zelfs voor de ondergrens te lang zijn staat
   hieronder bij overflow-wrap. */
h2.sec-title{font-size:clamp(36px,4vw,56px)}

/* VANGNET tegen een te brede pagina. De clamps hierboven dekken de koppen die
   er nu staan; een langer woord kan nog steeds uitsteken. Op
   /privacyverklaring gebeurt dat: die kop is een h1 en staat op een telefoon op
   de ondergrens van 56px, en is daar 491px breed tegen 359px ruimte. Hij brak
   ook al op de oude 42px (368px). Op /cookiebeleid gebeurt het alleen nog op
   een scherm van 320px: "COOKIEBELEID" is daar 328px tegen 294px ruimte.

   `anywhere` en NIET `break-word` — dat is hier het hele punt. setSplitText()
   zet elk woord in een <span class="kin"> met display:inline-block (nodig voor
   het kinetische effect). `break-word` laat de intrinsieke breedte van zo'n
   blokje ongemoeid, dus het blijft even breed uitsteken; `anywhere` telt wél
   mee in de min-content-breedte en laat het blokje krimpen. Zet je dit ooit om
   naar `break-word`, dan is het stil weer stuk. */
.sec-title,.ti-title,.ct-title{overflow-wrap:anywhere}
/* Hier stond .sec-index — het kleine label linksboven in elke sectie
   ([ 01 — RELEASES ] enz.). Op 2026-09-15 op verzoek helemaal verwijderd:
   het invulvak is uit het CMS en het element uit cms-render.js. */

/* Subpagina's bestaan volledig uit blokken. Er stond hier een .page-head met
   een "terug naar home"-link en de paginatitel; die is verwijderd, en daarmee
   ook .page-back en .page-title.

   Het eerste blok moet daardoor zélf onder de vaste nav vandaan komen — het
   stond op padding-top:0 omdat de kop die ruimte al maakte. Dezelfde maat als
   die kop gebruikte, dus de pagina begint op dezelfde hoogte als voorheen.
   Let op: .sec-pad begint op 80px en de nav is bij een uitgeklapte balk al
   ~90px hoog, dus dit overschrijven met alleen .sec-pad zou botsen.

   Alleen op een pagina ZONDER hero (klasse .no-hero op #page-blocks, gezet in
   pagina.html): op de homepage staat er al een hero boven #page-blocks, dus
   daar mag het eerste blok gewoon zijn normale .sec-pad-padding houden.
   Vaste maat i.p.v. vh (2026-10-19, op verzoek): de nav is overal ~90px, dus
   de ruimte eronder hoort niet met de schermHOOGTE te groeien. Met 15vh stond
   de h1 op een hoge desktop ~70–100px onder de nav, op mobiel ~20px. Nu 110px
   op mobiel (ongewijzigd) tot 130px op desktop — voor elk eerste blok, ook
   een blok met achtergrondfoto (die had een eigen regel, nu overbodig). */
#page-blocks.no-hero > section:first-child{padding-top:clamp(110px,100px + 2vw,130px)}

/* Footer tegen de onderkant op een pagina zonder inhoud (2026-09-15).
   Een pagina zonder blokken — een nieuwe pagina waar nog niets in staat, of
   /boeken — heeft een lege <main> van 0px hoog. De footer bleef daardoor
   direct onder de nav hangen, halverwege het scherm. Body als flexkolom met
   een groeiende <main> duwt hem naar beneden; staat er wél inhoud, dan
   verandert er niets omdat main dan groter is dan de resterende ruimte.

   Alleen op de subpagina-shell (pagina.html zet de klasse). De homepage heeft
   altijd een hero en de 404 regelt het zelf met .err{min-height:100vh}.

   Dit kan zo simpel omdat élk ander direct kind van body vast gepositioneerd
   is — .nav-bar, #menu en .player staan allemaal op position:fixed en doen
   dus niet mee aan de flexverdeling. Blijft dat zo als je hier iets toevoegt?
   Zo niet, dan wordt het een flexitem.

   svh naast vh: op mobiel is svh de kleinste stand van de viewport, dus de
   footer valt nooit half achter de browserbalk. Zelfde aanpak als .err. */
.page-shell{min-height:100vh;min-height:100svh;display:flex;flex-direction:column}
.page-shell > #page-blocks{flex:1 0 auto}
.page-shell > .footer{flex-shrink:0}

/* =====================================================================
   404 — foutpagina (404.html, geserveerd door sendNotFound() in server.js)

   Het grote doorzichtige cijfer is een outline-behandeling (-webkit-text-
   stroke) en de kop is een gewone .sec-title. Dat cijfer was de tweeling van
   `.foot-mega`, het outline-merklogo in de footer; dat is op 2026-09-17
   verdwenen, dus dit is nu de enige plek op de site met die behandeling.
   ===================================================================== */
/* 100svh naast 100vh: op mobiel telt vh de adresbalk mee, waardoor een
   verticaal gecentreerde pagina zichtbaar scheef komt te staan. */
.err{min-height:100vh;min-height:100svh;display:grid;align-content:center;
  justify-items:center;text-align:center;
  padding:clamp(120px,18vh,200px) 0 clamp(70px,10vh,120px)}
/* Massief, niet doorzichtig. Dit begon als de outline-behandeling van het logo
   in de footer, maar die werkt daar omdat het decoratie is: een lijn van 1px om
   een letter van 400px is een haarlijn en in een muted lijnkleur nauwelijks te
   zien. Hier is het cijfer de boodschap, dus vol in de tekstkleur. */
/* Gewoon massieve cijfers in de tekstkleur. Er zijn hier een contour, een
   accentkleur, een verloop en een gloed langsgekomen — dit is wat het werd.
   padding-block houdt lucht om de letters: met line-height .8 is de
   contentbox korter dan de letters zelf. */
.err-code{font-family:var(--font-display);font-weight:700;line-height:.8;
  font-size:clamp(100px,20vw,330px);letter-spacing:.01em;
  padding-block:.06em;color:var(--text);user-select:none}
.err-lead{max-width:44ch;margin:clamp(18px,3vh,34px) auto 0;
  font-size:clamp(15px,1.35vw,19px);line-height:1.7;color:var(--muted)}
.err-actions{margin-top:clamp(28px,4.2vh,46px);display:flex;flex-wrap:wrap;
  justify-content:center;align-items:center;gap:14px}

/* kinetic split-text primitives ----------------------------- */
.kin{display:inline-block;vertical-align:top}
.kin > span{display:inline-block;transform:translateY(0.7em) rotate(4deg);opacity:0;
  will-change:transform,opacity}
.reveal-on .kin > span{transform:none;opacity:1;
  transition:transform calc(0.9s / var(--motion)) cubic-bezier(.16,1,.3,1),
             opacity calc(0.6s / var(--motion)) ease}

.fade-up{opacity:0;transform:translateY(40px);will-change:transform,opacity}
.reveal-on.fade-up,.reveal-on .fade-up{opacity:1;transform:none;
  transition:opacity .8s ease, transform calc(.9s/var(--motion)) cubic-bezier(.16,1,.3,1)}

/* placeholder surfaces -------------------------------------- */
.ph{position:relative;overflow:hidden;background:var(--bg-2);
  background-image:repeating-linear-gradient(135deg,
     var(--ph-a) 0 2px, transparent 2px 11px);
  border:1px solid var(--line);}
.ph::after{content:attr(data-ph);position:absolute;inset:0;display:grid;
  place-items:center;font-family:var(--font-mono);font-size:11px;font-weight:600;
  letter-spacing:0.1em;text-transform:uppercase;color:var(--muted);}
.ph[data-ph=""]::after{display:none}

/* =====================================================================
   BUTTONS — centrale knop-stijl (dé plek om knoppen te beheren/toevoegen)

   De site kent DRIE knopsoorten. Nieuwe knop = alleen de juiste klasse:
     <a class="btn btn-fill">Label</a>   → 1. PRIMAIR    (gevuld blauw)
     <a class="btn">Label</a>            → 2. SECUNDAIR  (outline)
     <a class="btn btn-tertiary">Label</a> → 3. TERTIAIR (tekstknop, blauw)

   Alle hover-effecten staan hier centraal — nooit per plek dupliceren.
   In gebruik: hero (primair + secundair), nav CONTACT (primair),
   muziek "Alle releases" (primair), mixes "Alle mixes" (tertiair),
   formulier-submit (primair).
   ===================================================================== */
/* Zelfde leesbaarheidsingreep als bij de menu-links: was mono 12px in
   HOOFDLETTERS met .18em afstand. Nu gewone schrijfwijze, 14px, halfvet. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-family:var(--font-text);font-size:14px;font-weight:600;letter-spacing:.01em;
  padding:14px 24px;border-radius:999px;cursor:pointer;
  border:1px solid var(--line-strong);background:transparent;color:var(--text);
  transition:background .3s ease,color .3s ease,border-color .3s ease,
             box-shadow .3s ease,transform .3s ease;
  position:relative;overflow:hidden}

/* 1. PRIMAIR — helderder blauw + blauwe gloed op hover */
.btn-fill{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.btn-fill:hover{background:#2b7bff;border-color:#2b7bff;color:#fff;
  box-shadow:0 12px 30px rgba(0,102,255,.45)}

/* 2. SECUNDAIR — keert om op hover (vult met tekstkleur, label wordt donker) */
.btn:hover{transform:translateY(-3px);background:var(--text);color:var(--bg);
  border-color:var(--text);box-shadow:0 12px 28px rgba(0,0,0,.30)}

/* 3. TERTIAIR — kale tekstknop in accentblauw.
      Hover: lichter blauw + onderstreping (leest als "opgelicht").
      overflow:visible zodat de underline-offset niet wordt afgekapt.
      Staat ná .btn:hover, anders wint de secundaire hover. */
.btn-tertiary{border-color:transparent;background:none;color:var(--accent);
  padding-inline:0;overflow:visible}
.btn-tertiary:hover{background:none;border-color:transparent;color:#5c9dff;
  box-shadow:none;transform:translateY(-1px);
  text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:6px}

.btn .dot{width:7px;height:7px;border-radius:50%;background:currentColor;
  flex:none}

/* =====================================================================
   CURSOR — VERWIJDERD (2026-09-15, op verzoek)
   Hier stond een zelfgetekende cursor: een witte stip met een ring eromheen
   die er met vertraging achteraan liep, groter werd boven een link, en een
   label toonde uit `data-cursor`. De gewone muisaanwijzer werd daarvoor
   verborgen met `cursor:none`.

   Alles is weg: deze opmaak, het `.cursor`-element uit de drie shells, het
   blok in motion.js en alle `data-cursor`-attributen. Wil je zoiets ooit
   terug, bouw het dan opnieuw — er staat nu nergens meer een half restant
   dat bij een muisbeweging ineens tevoorschijn komt.
   ===================================================================== */

/* =====================================================================
   NAV

   Opbouw: .nav-bar is de vaste balk over de volle breedte (achtergrond,
   verbergen bij scrollen), .nav is de gecentreerde inhoud van 1400px.
   Die twee lagen zijn nodig: een achtergrond op .nav alleen zou een
   zwevend paneel van 92vw geven i.p.v. een balk van rand tot rand.
   De markup komt uit headerHtml() in server.js.
   ===================================================================== */
.nav-bar{position:fixed;top:0;left:0;right:0;z-index:7000;color:#fff;
  border-bottom:1px solid transparent;
  transition:background .35s ease,border-color .35s ease,
             color .35s ease,backdrop-filter .35s ease}

/* Voorbij de hero: leesbare ondergrond. Zonder dit zweeft de tekst over de
   cover-artwork van de muzieksectie, en die helderheid heb je niet in de hand. */
.nav-bar.is-stuck{background:var(--glass);color:var(--text);
  border-bottom-color:var(--line);
  -webkit-backdrop-filter:blur(14px) saturate(1.4);
  backdrop-filter:blur(14px) saturate(1.4)}

/* De balk blijft ALTIJD zichtbaar. Eerder verborg hij zich bij omlaag
   scrollen; op verzoek weg, want dan moet je terugscrollen om bij het menu
   te komen. De balk krimpt wel (is-stuck hieronder), dus hij kost minder
   ruimte zodra je leest. */

.nav{width:min(1400px,92vw);margin-inline:auto;
  display:flex;align-items:center;gap:24px;
  padding-block:22px;transition:padding-block .35s ease}
.nav-bar.is-stuck .nav{padding-block:12px}

/* logo links — afbeelding uit de mediabibliotheek, linkt naar de homepage.
   Was de merknaam in tekst (.nav-brand); dat is vervangen door een echt logo.
   Staat er geen logo in header.json, dan rendert de server hier niets.
   De hoogte stuurt, de breedte volgt: een horizontale rechthoek mag zo breed
   worden als hij nodig heeft, maar nooit zo breed dat hij de menu-items van
   het scherm duwt — vandaar de max-width. */
.nav-logo{display:flex;align-items:center;flex:0 0 auto;transition:opacity .3s}
.nav-logo:hover{opacity:.7}
.nav-logo img{display:block;height:38px;width:auto;max-width:min(260px,34vw);
  object-fit:contain;transition:height .35s ease}
/* Meekrimpen met de balk (die gaat van 22px naar 12px padding); zonder dit
   blijft het logo de balk op zijn oude hoogte houden. */
.nav-bar.is-stuck .nav-logo img{height:30px}
@media(max-width:860px){
  .nav-logo img{height:32px}
  .nav-bar.is-stuck .nav-logo img{height:26px}
}

.nav-links{display:flex;gap:30px;align-items:center;margin-left:auto}
/* Leesbaarheid: dit was mono 13px in HOOFDLETTERS met .16em letterafstand.
   Die drie samen maakten het lastig te lezen. Nu gewone schrijfwijze, groter
   en zwaarder, met normale letterafstand. De labels in header.json staan al
   in gewone schrijfwijze ("Muziek"), dus die komen nu tot hun recht. */
.nav-links a{font-family:var(--font-text);font-size:15px;font-weight:600;
  letter-spacing:.01em;position:relative}
.nav-links a::after{content:"";position:absolute;left:0;bottom:-5px;height:1px;
  width:0;background:currentColor;transition:width .3s}
.nav-links a:hover::after{width:100%}
.nav-links a.nav-cta::after{display:none}

/* actieve sectie (scrollspy in main.js). Niet op de CTA: die is al gevuld. */
.nav-links a.is-active:not(.nav-cta){color:var(--accent)}
.nav-links a.is-active:not(.nav-cta)::after{width:100%;background:var(--accent)}

@media(max-width:860px){.nav-links{display:none}}

/* hamburger-knop (mobiel) — drie strepen i.p.v. het woord MENU */
.nav-menu-btn{display:none;background:none;border:0;padding:0;cursor:pointer;
  width:44px;height:44px;color:inherit;margin-left:auto;
  align-items:center;justify-content:center}
@media(max-width:860px){.nav-menu-btn{display:flex}}
.nav-burger{position:relative;display:block;width:26px;height:2px;
  background:currentColor;border-radius:2px}
.nav-burger::before,.nav-burger::after{content:"";position:absolute;left:0;
  width:26px;height:2px;background:currentColor;border-radius:2px}
.nav-burger::before{top:-8px}
.nav-burger::after{top:8px}

/* overslaan naar de inhoud — alleen zichtbaar met toetsenbordfocus */
.skip-link{position:fixed;top:8px;left:8px;z-index:7600;
  transform:translateY(-160%);transition:transform .2s ease;
  background:var(--accent);color:var(--accent-ink);
  font-family:var(--font-mono);font-size:12px;letter-spacing:.14em;
  text-transform:uppercase;padding:12px 18px;border-radius:8px}
.skip-link:focus,.skip-link:focus-visible{transform:none}
#hero:focus,#page-blocks:focus{outline:none}

/* =====================================================================
   HERO
   ===================================================================== */
#hero{height:100svh;min-height:640px;position:relative;overflow:hidden;
  display:grid;place-items:center;--hero-ov:.5;--smoke-op:.7}
#liquid{position:absolute;inset:0;width:100%;height:100%;z-index:0}

/* photographic hero bg + legibility overlay */
.hero-photo{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:54% 24%;z-index:0;opacity:0;transition:opacity .6s ease}
/* Overlay = VLAKKE zwarte laag: 0% = niets, 100% = helemaal zwart.
   Bewust geen gradient + mix-blend-mode meer — daarmee was 100% niet echt zwart
   en kon je niet donkerder dan het origineel. Sterkte komt uit het hero-blok
   in het CMS en wordt als --hero-ov (0–1) op #hero gezet. */
.hero-overlay{position:absolute;inset:0;z-index:1;pointer-events:none;opacity:0;
  transition:opacity .6s ease;background:#000}

/* mode: animated shader only (original) */
#hero[data-herobg="shader"] .hero-photo,
#hero[data-herobg="shader"] .hero-overlay{opacity:0}
#hero[data-herobg="shader"] #liquid{opacity:1;mix-blend-mode:normal}

/* mode: photo only */
#hero[data-herobg="photo"] .hero-photo{opacity:1}
#hero[data-herobg="photo"] .hero-overlay{opacity:var(--hero-ov)}
#hero[data-herobg="photo"] #liquid{opacity:0}

/* mode: photo + drifting smoke (default) */
#hero[data-herobg="both"] .hero-photo{opacity:1;filter:brightness(.72) saturate(1.03)}
#hero[data-herobg="both"] .hero-overlay{opacity:var(--hero-ov)}
#hero[data-herobg="both"] #liquid{opacity:var(--smoke-op);mix-blend-mode:screen}
.hero-grain{position:absolute;inset:0;z-index:1;opacity:.5;pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  mix-blend-mode:overlay}
.hero-inner{position:relative;z-index:2;text-align:center;width:100%;
  padding-inline:4vw}
/* De titel staat stil en is gewone tekst (2026-09-17, op verzoek). Eerder zat
   elke letter in een eigen <span> voor de letter-voor-letter reveal, en was
   dit een flexrij waarin die spans de items waren.

   LETTER-SPACING — niet zomaar aanpassen. Tussen twee letters zat vroeger
   0.01em letter-spacing plus 0.01em flex-`gap`, samen 0.02em. Nu de flexrij
   weg is moet die volle 0.02em uit letter-spacing komen, anders kruipt de
   titel zichtbaar in elkaar. Vandaar 0.02em en niet 0.01em.
   Centreren gaat via `text-align:center` op .hero-inner. */
.hero-word{font-family:var(--font-display);text-transform:uppercase;
  font-weight:700;                 /* het zwaarste dat Oswald heeft */
  line-height:0.85;letter-spacing:0.02em;color:#fff;
  font-size:clamp(58px,var(--title-size,17vw),320px);
  text-shadow:0 6px 70px rgba(0,0,0,.55), 0 1px 18px rgba(0,0,0,.45)}
/* Korte tijd heeft hier een kloppende $ gestaan (hartslagritme op het
   dollarteken). Op verzoek weer weg — de titel beweegt helemaal niet meer. */
.hero-sub{margin-top:clamp(14px,2.4vh,30px);display:flex;justify-content:center;
  gap:18px;flex-wrap:wrap;font-family:var(--font-mono);
  font-size:clamp(17px,2.2vw,32px);font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:#fff}
[data-theme="light"] .hero-sub{color:rgba(0,0,0,.7)}
.hero-actions{margin-top:clamp(26px,4vh,44px);display:flex;justify-content:center;
  flex-wrap:wrap;gap:16px}
/* 15px: gelijkgetrokken met de menu-links, net als voorheen (die stonden toen
   allebei op 13px). Anders zijn de grootste knoppen van de site de kleinste tekst. */
.hero-actions .btn{font-size:15px;padding:16px 30px;
  min-width:240px;justify-content:center}
.hero-cta{position:absolute;left:50%;bottom:clamp(22px,4vh,42px);
  transform:translateX(-50%);z-index:3;display:flex;flex-direction:column;
  align-items:center;gap:10px;font-family:var(--font-mono);font-size:11px;
  letter-spacing:.22em;text-transform:uppercase;color:rgba(255,255,255,.8)}
[data-theme="light"] .hero-cta{color:rgba(0,0,0,.7)}
.hero-cta .arr-down{display:flex;flex-direction:column;align-items:center;gap:4px;
  animation:arrowBounce 1.6s ease-in-out infinite}
.hero-cta .arr-down i{display:block;width:10px;height:10px;border-right:2px solid currentColor;
  border-bottom:2px solid currentColor;transform:rotate(45deg);opacity:1}
.hero-cta .arr-down i:nth-child(2){opacity:.55}
.hero-cta .arr-down i:nth-child(3){opacity:.25}
@keyframes arrowBounce{0%,100%{transform:translateY(-4px)}50%{transform:translateY(4px)}}

.hero-play{position:absolute;top:50%;right:clamp(20px,5vw,70px);
  transform:translateY(-50%);z-index:3;width:118px;height:118px;border-radius:50%;
  border:1px solid rgba(255,255,255,.5);background:rgba(255,255,255,.06);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#fff;
  display:grid;place-items:center;font-family:var(--font-mono);font-size:10px;
  letter-spacing:.2em;text-transform:uppercase;animation:spinSlow 16s linear infinite}
@keyframes spinSlow{to{transform:translateY(-50%) rotate(360deg)}}
.hero-play .ico{position:absolute;inset:0;display:grid;place-items:center;
  animation:spinSlow 16s linear infinite reverse;font-size:20px}
@media(max-width:860px){.hero-play{display:none}}

/* =====================================================================
   MARQUEE TICKER
   ===================================================================== */
.ticker{border-block:1px solid var(--line);overflow:hidden;
  background:var(--accent);color:var(--accent-ink);padding:18px 0}
.ticker[data-variant="outline"]{background:transparent;color:var(--text)}
.ticker-track{display:flex;gap:0;white-space:nowrap;width:max-content;
  will-change:transform;font-family:var(--font-display);font-weight:600;
  text-transform:uppercase;
  font-size:clamp(30px,5vw,76px);line-height:1}
.ticker-track span{padding-inline:.35em;display:inline-flex;align-items:center;gap:.35em}
.ticker-track .star{font-size:.5em;transform:translateY(-.1em)}

/* =====================================================================
   RELEASES — cover-kaarten (1:1), 3 per rij
   Desktop : de kaart ÍS de cover. Hover → donkere overlay + inzoom,
             play-knop in het midden, titel/artiest onderin.
   Mobiel  : 1 kolom, horizontale kaart (mini-cover · tekst · play rechts).
   ===================================================================== */
.tag{display:inline-block;font-family:var(--font-mono);font-size:11px;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;padding:5px 10px;border-radius:999px;
  background:var(--accent);color:var(--accent-ink);margin-bottom:14px}

.music-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(14px,1.8vw,28px)}
.music-more,.mixes-more{padding-top:clamp(22px,3vw,36px)}

.mu-card{position:relative;aspect-ratio:1;border-radius:10px;overflow:hidden;
  background:var(--bg-2)}

/* cover = knop (hele vlak klikbaar) */
.mu-art{position:absolute;inset:0;width:100%;height:100%;padding:0;border:0;
  background:none;cursor:pointer;display:block;overflow:hidden}
.mu-art img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .6s cubic-bezier(.16,1,.3,1)}
.mu-card:hover .mu-art img{transform:scale(1.08)}
.mu-noart{position:absolute;inset:0;display:grid;place-items:center;
  font-size:34px;color:var(--muted)}

/* donkere overlay + play-knop */
.mu-ovl{position:absolute;inset:0;display:grid;place-items:center;
  background:rgba(0,0,0,.55);opacity:0;transition:opacity .35s}
.mu-card:hover .mu-ovl,.mu-card:focus-within .mu-ovl,
.mu-card.playing .mu-ovl{opacity:1}
.mu-play{width:clamp(52px,4.6vw,68px);aspect-ratio:1;border-radius:50%;
  background:var(--accent);color:var(--accent-ink);display:grid;place-items:center;
  transform:scale(.82);transition:transform .35s}
.mu-card:hover .mu-play,.mu-card.playing .mu-play{transform:scale(1)}

/* Beide iconen zitten in de knop; alleen de juiste is zichtbaar. Scheelt het
   herschrijven van HTML bij elke wisseling — de klasse .playing doet het. */
.mu-play .ic,.mu-play-btn .ic{display:none;place-items:center}
.mu-play .ic-play,.mu-play-btn .ic-play{display:grid}
.mu-card.playing .mu-play .ic-play,
.mu-card.playing .mu-play-btn .ic-play{display:none}
.mu-card.playing .mu-play .ic-pause,
.mu-card.playing .mu-play-btn .ic-pause{display:grid}
.mu-play svg{width:clamp(20px,1.85vw,27px);height:auto;display:block}
/* de driehoek oogt links-zwaar, het pauzeteken niet */
.mu-play .ic-play svg{margin-left:6%}

/* titel + artiest onderin — verschijnen bij hover */
.mu-meta{position:absolute;left:0;right:0;bottom:0;z-index:2;pointer-events:none;
  padding:clamp(14px,1.6vw,22px);
  background:linear-gradient(to top,rgba(0,0,0,.88),rgba(0,0,0,.45) 55%,transparent);
  opacity:0;transform:translateY(12px);transition:opacity .35s,transform .35s}
.mu-card:hover .mu-meta,.mu-card:focus-within .mu-meta,
.mu-card.playing .mu-meta{opacity:1;transform:none}
.mu-title{font-size:clamp(15px,1.25vw,19px);font-weight:600;line-height:1.15;color:#fff}
.mu-artist{font-family:var(--font-mono);font-size:clamp(11px,.85vw,13px);
  letter-spacing:.06em;color:rgba(255,255,255,.72);margin-top:5px}

/* Bronlinks in de kaart (SoundCloud / Spotify). .mu-meta staat op
   pointer-events:none — zodat een klik op de titel gewoon de cover-knop
   eronder raakt — dus de links zetten hun klikbaarheid zelf terug. */
.mu-srcs{display:flex;flex-wrap:wrap;gap:6px 16px;margin-top:10px}
.mu-src{pointer-events:auto;display:inline-flex;align-items:center;gap:7px;
  font-family:var(--font-text);font-size:12px;font-weight:600;
  letter-spacing:.01em;color:rgba(255,255,255,.78);transition:color .25s}
.mu-src svg{width:15px;height:15px;flex:none}
/* huisstijlkleur van de dienst, alleen bij hover */
.mu-src.is-sc:hover{color:#ff5500}
.mu-src.is-sp:hover{color:#1db954}

.mu-play-btn{display:none}   /* alleen mobiel */

/* Mobiele weergave van deze kaarten staat centraal onder
   "MOBIELE MEDIAKAARTEN" (gedeeld met de mix-archiefkaarten). */

/* =====================================================================
   MIXES — ÉÉN speler-kaart

   Bovenin de uitgelichte mix: cover, titel en een afspeelbalk. Daaronder,
   binnen dezelfde kaart, de overige mixes als regels.

   WAAROM DIT GEEN RASTER MEER IS: de sectie toont er hooguit vier (1 groot
   + 3 kaarten in een 3-koloms raster), maar in de praktijk staan er vaak
   maar één of twee ingesteld. Dan stond dat raster half leeg en had het
   grote blok een lege rechterhelft. Bovendien heeft élke mix cover-artwork
   in het CMS, en dat kwam nergens in beeld — terwijl de muzieksectie er
   juist helemaal op leunt. Dit ontwerp staat goed bij 1, 2, 3 én 4 mixes.
   ===================================================================== */

/* badge bij de uitgelichte mix (leeg = door JS verborgen) */
.mx-badge{display:inline-block;font-family:var(--font-mono);font-size:11px;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;padding:4px 9px;border-radius:999px;
  background:var(--accent);color:var(--accent-ink);line-height:1.4}

/* --mix-gap is de ENIGE verticale maat in deze kaart: de ruimte boven de cover,
   tussen de cover en de scheidingslijn, tussen lijn en regel, en onder de
   laatste regel. Eén variabele, zodat die witruimte overal gelijk blijft. */
.mix-feature{
  --mix-gap:clamp(14px,1.7vw,22px);
  border:1px solid var(--line);border-radius:16px;
  background:var(--surface);
  padding:var(--mix-gap) clamp(16px,2vw,26px)}
/* Actief = blauwe titel, zowel boven als bij de regels. Bewust GEEN rand om de
   kaart: die lichtte het geheel op terwijl er maar één mix speelt. */
.mix-feature.is-playing .mf-title{color:var(--accent)}

/* ── bovenste helft: cover · tekst · speler ── */
.mf-top{
  display:grid;
  grid-template-columns:clamp(96px,14vw,190px) 1fr;
  gap:clamp(16px,2.6vw,34px);
  align-items:center;
  cursor:pointer}
.mf-cover{position:relative;aspect-ratio:1;border-radius:10px;overflow:hidden;
  background:var(--bg-2);border:1px solid var(--line)}
.mf-cover img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .6s cubic-bezier(.2,.7,.2,1)}
.mf-top:hover .mf-cover img{transform:scale(1.05)}
.mf-noart{position:absolute;inset:0;display:grid;place-items:center;
  font-size:clamp(22px,3vw,38px);color:var(--muted)}

.mf-main{min-width:0}
.mf-header{display:flex;align-items:center;gap:12px;margin-bottom:10px}
.mf-title{font-family:var(--font-display);text-transform:uppercase;
  font-weight:600;letter-spacing:.01em;
  font-size:clamp(26px,3.8vw,58px);line-height:.95;
  overflow-wrap:anywhere;transition:color .3s}
.mf-artist{font-family:var(--font-mono);font-size:clamp(11px,1vw,13px);
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted);margin-top:8px}

/* ── de speler: ronde knop · waveform · tijd ── */
.mf-player{display:grid;grid-template-columns:auto 1fr auto;align-items:center;
  gap:clamp(12px,1.6vw,20px);margin-top:clamp(14px,2vw,22px)}
.mf-play-btn{width:clamp(44px,4vw,54px);aspect-ratio:1;flex-shrink:0;
  border:none;border-radius:50%;background:var(--accent);color:var(--accent-ink);
  display:grid;place-items:center;font-size:14px;cursor:pointer;
  transition:transform .3s,box-shadow .3s}
.mf-play-btn:hover{transform:scale(1.07);box-shadow:0 8px 32px rgba(0,102,255,.35)}
.mf-play-ico{line-height:1}

/* De balk is de waveform zelf: het gespeelde deel kleurt vol accent (zie
   assets/waveform.js). --prog wordt door cms-render.js gezet en stuurt de
   speelkop; de padding maakt de klikzone iets hoger dan de balkjes. */
.mf-bar{position:relative;cursor:pointer;padding-block:6px;--prog:0}
.mf-wave{display:block;width:100%;height:clamp(38px,4.2vw,60px)}
.mf-bar::after{content:'';position:absolute;top:6px;bottom:6px;
  left:calc(var(--prog) * 100%);width:2px;background:var(--text);
  opacity:0;transition:opacity .3s}
.mix-feature.is-playing .mf-bar::after{opacity:.8}

.mf-time{font-family:var(--font-mono);font-size:12px;letter-spacing:.06em;
  color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
.mf-sep{opacity:.45;margin:0 4px}

/* ── de overige mixes: regels binnen dezelfde kaart ──
   De negatieve ondermarge heft de padding van de kaart op, zodat de ruimte
   onder de laatste regel gelijk is aan --mix-gap in plaats van dubbel te
   tellen. De hover-band blijft daardoor wél even hoog als bij de andere. */
.mix-archive:not(:empty){margin-top:var(--mix-gap);border-top:1px solid var(--line);
  margin-bottom:calc(var(--mix-gap) * -1)}
.ma-card{
  display:grid;
  grid-template-columns:clamp(38px,4vw,50px) minmax(0,1fr) auto auto;
  align-items:center;gap:clamp(10px,1.6vw,20px);
  padding:var(--mix-gap) 2px;
  border-top:1px solid var(--line);cursor:pointer;
  transition:background .3s}
.ma-card:first-child{border-top:0}
.ma-card:hover{background:var(--ph-a)}
.ma-art{position:relative;aspect-ratio:1;border-radius:6px;overflow:hidden;
  background:var(--bg-2);display:block}
.ma-art img{width:100%;height:100%;object-fit:cover;display:block}
.ma-noart{position:absolute;inset:0;display:grid;place-items:center;
  font-size:16px;color:var(--muted)}
.ma-body{min-width:0}
.ma-title{font-family:var(--font-display);text-transform:uppercase;
  font-weight:600;letter-spacing:.01em;
  font-size:clamp(15px,1.6vw,24px);line-height:1.05;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  transition:color .3s}
.ma-artist{font-family:var(--font-mono);font-size:11px;color:var(--muted);
  letter-spacing:.12em;text-transform:uppercase;margin-top:3px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ma-dur{font-family:var(--font-mono);font-size:12px;color:var(--muted);
  letter-spacing:.06em;font-variant-numeric:tabular-nums}
.ma-play{width:38px;height:38px;border-radius:50%;
  border:1px solid var(--line-strong);display:grid;place-items:center;
  font-size:11px;color:var(--text);
  transition:background .3s,border-color .3s,color .3s}
.ma-card:hover .ma-play,.ma-card.is-playing .ma-play{
  background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.ma-card.is-playing .ma-title{color:var(--accent)}

/* Smaller: cover en titel omlaag, de tijd zakt onder de balk. */
@media(max-width:820px){
  .mf-top{grid-template-columns:clamp(84px,22vw,120px) 1fr;align-items:start}
  .mf-player{grid-template-columns:auto 1fr;row-gap:8px}
  .mf-time{grid-column:2;justify-self:end}
}
/* Te smal voor 64 balkjes: alleen knop + tijd. */
@media(max-width:560px){
  .mf-bar{display:none}
  .mf-time{grid-column:auto;justify-self:end}
}

/* =====================================================================
   MOBIELE MEDIAKAARTEN (≤700px) — GEDEELD door de muzieklijst
   (.music-grid .mu-card) en het mix-archief (.ma-card). Beide worden hier
   één horizontale lijstregel: mini-cover links · titel + kleinere artiest ·
   play rechts. Voeg een nieuw kaarttype toe door het aan deze selectors te
   hangen — niet opnieuw uitschrijven.

   LET OP: alleen de LAYOUT is gedeeld, de randen bewust niet:
     · muziek → doorlopende, schermbrede lijnen zonder doos
     · mixes  → losse rechthoek met rand rondom (zoals op desktop)
   Hou die twee gescheiden; ze zien er expres verschillend uit.

   WAAROM `.music-grid .mu-card` EN NIET GEWOON `.mu-card` (2026-09-18):
   dezelfde kaart staat sinds het Muziek highlight-blok ook op een tweede
   plek, in `.mh-card`, en die moet op mobiel juist vierkant BLIJVEN — daar
   is hij het onderwerp van de sectie, niet een regel in een lijst. Deze
   hele media query gaat dus alleen over kaarten in de lijst. Zie
   "MUZIEK HIGHLIGHT" verderop voor wat de highlight-kaart op touch doet.
   ===================================================================== */
@media(max-width:700px){
  .music-grid{grid-template-columns:1fr}

  /* GEDEELDE LAYOUT (bewust zonder randen — die verschillen per sectie) */
  .music-grid .mu-card,.ma-card{aspect-ratio:auto;display:grid;
    grid-template-columns:60px 1fr auto;align-items:center;gap:14px;
    background:transparent;transform:none}

  /* MUZIEK — doorlopende, schermbrede lijnenlijst (geen doos).
     .wrap is min(1400px,92vw) → 4vw gutter; die halen we weg met een negatieve
     marge en geven we terug als padding, zodat de lijn doorloopt tot de
     schermrand maar de inhoud uitgelijnd blijft. Elke kaart border-top, alleen
     de laatste ook border-bottom → de onderlijn van de één is de bovenlijn van
     de volgende. Werkt alleen zolang .wrap/section géén overflow:hidden hebben. */
  .music-grid{gap:0}
  .music-grid .mu-card{border:0;border-top:1px solid var(--line);border-radius:0;
    margin-inline:-4vw;padding:14px 4vw}
  .music-grid .mu-card:last-child{border-bottom:1px solid var(--line)}

  /* MIXES — regels binnen de speler-kaart, zoals op desktop. Alleen de
     kolommen worden krapper; de scheidingslijn en --mix-gap blijven. */
  .ma-card{padding:var(--mix-gap) 0}

  /* mini-cover links */
  .music-grid .mu-art,.ma-art{position:relative;width:60px;height:60px;border-radius:6px;
    overflow:hidden;display:block;background:var(--bg-2)}
  .ma-art img,.music-grid .mu-art img{width:100%;height:100%;object-fit:cover;display:block}
  .music-grid .mu-card:hover .mu-art img{transform:none}
  .music-grid .mu-ovl{display:none}
  .music-grid .mu-noart,.ma-noart{position:absolute;inset:0;display:grid;place-items:center;
    font-size:22px;color:var(--muted)}

  /* tekstblok — altijd zichtbaar (geen hover op touch) */
  .music-grid .mu-meta,.ma-body{position:static;opacity:1;transform:none;padding:0;
    background:none;pointer-events:auto;min-width:0}
  .music-grid .mu-title,.ma-title{color:var(--text);font-family:var(--font-text);
    font-size:15px;font-weight:600;line-height:1.15;text-transform:none;
    letter-spacing:normal;margin-top:0;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .music-grid .mu-artist,.ma-artist{color:var(--muted);font-size:12px;margin-top:4px;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

  /* verbergen op mobiel: de duur (te krap naast titel + knop) */
  .ma-dur{display:none}

  /* play-knop rechts */
  .music-grid .mu-play-btn,.ma-play{display:grid;place-items:center;position:static;
    width:42px;height:42px;border-radius:50%;
    border:1px solid var(--line-strong);background:transparent;color:var(--text);
    cursor:pointer;transition:background .3s,border-color .3s,color .3s}
  .music-grid .mu-play-btn svg{width:15px;height:15px;margin-left:2px}

  /* actieve staat (alleen muziek — mixes wisselen enkel hun play-icoon) */
  .music-grid .mu-card.playing{border-color:var(--accent)}
  .music-grid .mu-card.playing .mu-play-btn{background:var(--accent);border-color:var(--accent);
    color:var(--accent-ink)}
  .music-grid .mu-card.playing .mu-title{color:var(--accent)}
}

/* =====================================================================
   SHOWS (vertical list — agenda stijl)
   ===================================================================== */
.show-list{border-top:1px solid var(--line);transition:border-color .35s;
  /* Eén raster voor de hele lijst; elke regel (en elke maandgroep) neemt de
     kolommen over met `subgrid`. Zo is de knopkolom overal zo breed als de
     breedste knop en zijn alle knoppen even breed (2026-10-19, op verzoek).
     Datumkolom vast, zodat de namen in elke regel op dezelfde lijn beginnen.
     Max 112px sinds de datum 30px is (was 140 bij 40px); "DONDERDAG" op 13px
     en "28 SEP" op 30px zijn allebei zo'n 85px. */
  display:grid;
  grid-template-columns:clamp(96px,8vw,112px) minmax(0,1fr) auto;
  column-gap:clamp(14px,2.5vw,44px)}
.sh-groep,.show-row{grid-column:1/-1;display:grid;grid-template-columns:subgrid}
.sh-maand,.show-list .list-empty{grid-column:1/-1}

.show-row{
  /* kolommen + gap komen van .show-list (subgrid, zie hierboven) */
  align-items:center;
  padding:clamp(12px,1.8vw,24px) 6px;
  border-bottom:1px solid var(--line);
  /* `overflow:hidden` stond hier tot 2026-09-29 en komt niet terug: de naam en
     de plaats kappen zichzelf af met hun eigen masker, en er loopt niets anders
     buiten de regel. */
  position:relative;
  /* GEEN cursor:pointer (weg op 2026-09-29): alleen de knop is klikbaar, de
     rij zelf is nergens een link naartoe. Een handje boven de hele regel
     beloofde iets dat er niet is. */
  transition:border-color .35s}

/* ⚠️ HET HELE NAAR-VOREN-EFFECT IS ERUIT (2026-10-08, op verzoek).
   Tussen 2026-09-29 en vandaag kwam één regel als kaart naar voren — opgetild
   met `transform:scale(1.02)`, met een pseudo-element eronder dat buiten de
   regel uitstak en een schaduw naar twee kanten gaf — terwijl de rest van de
   lijst naar 70% dimde. Bij het laden stond de bovenste zo, daarna verhuisde
   het met de muis mee en bleef het staan waar de muis het laatst was.

   Dat is nu allemaal weg: elke regel staat op volle sterkte, niets tilt op,
   niets dimt. Wat eruit ging: `.show-row::before` (de kaart), `.show-row.actief`
   (optillen + aanzetten), `isolation:isolate` en de transform/opacity-overgang
   op `.show-row`, de hele `--rij`-tabel, en aan de JS-kant `volgDeMuis()` +
   `FIJNE_MUIS` + het bijhouden van die klasse in `paintShowRows()`. Ook de
   lege `.sh-fill` in elke regel is meegegaan — die was een overblijfsel van een
   nog oudere versie van dit effect en stond al op `display:none`.
   Alles staat in git (laatste versie: commit vóór v1.101.6). Zet er niets van
   terug zonder dat erom gevraagd wordt.

   Wat WEL blijft: een uitverkochte regel staat terughoudender dan de rest.
   Dat is geen hover-effect maar informatie — zo'n show is voorbij als
   mogelijkheid. 45%, de waarde die een uitverkochte regel had als hij naar
   voren stond. */
.show-list .show-row.sold{opacity:.45}

/* date block — dag en maand naast elkaar, weekdag eronder, even groot als de naam: 30px
   op desktop (2026-10-19, op verzoek; was 40px, daarvoor dag boven maand, 61/36px). */
/* Onder dag + maand de weekdag als `.sh-city` — dezelfde regel als de plaats
   onder de naam, zodat de twee kolommen exact gelijk lopen. */
.sh-date{min-width:0}
.sh-dm{display:flex;align-items:baseline;gap:.25em;line-height:1;
  font-size:clamp(24px,3vw,30px)}
.sh-day,.sh-mon{font-family:var(--font-display);font-weight:600;font-size:1em;
  line-height:.92;text-transform:uppercase;letter-spacing:.01em;
  font-variant-numeric:tabular-nums}

/* event info — naam van de locatie/het evenement, met de plaats eronder.
   Het jaar (.sh-yr) en de aparte typeregel (.sh-venue) zijn er op
   2026-09-29 uit gehaald; staan hier dus bewust niet meer. */
.sh-info{min-width:0}
.sh-name{font-family:var(--font-display);text-transform:uppercase;
  font-weight:600;letter-spacing:.01em;
  font-size:clamp(24px,3vw,30px);line-height:.92;
  transition:color .35s}
.sh-city{font-family:var(--font-mono);font-size:13px;
  letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);margin-top:8px;
  transition:color .35s}

/* Te lange namen en plaatsnamen faden uit aan de rechterkant in plaats van
   af te breken of over twee regels te lopen (2026-09-29, op verzoek).
   Zelfde truc als in de speler — zie de uitleg bij `.player .meta .t`:
   het masker zit op de DOOS, niet op de tekst. Past de naam gewoon, dan
   eindigt hij vóór het verloop en zie je niets.

   DAT WERKT ALLEEN zolang .sh-info de breedte van zijn kolom vult. Die
   kolom is `1fr` in .show-row, dus dat zit goed — maar zet .sh-info nooit
   op `width:max-content` of `justify-self:start`, want dan is de doos zo
   breed als de langste regel en faadt élke naam. `min-width:0` hierboven is
   om dezelfde reden nodig: zonder dat weigert een grid-kolom te krimpen
   onder zijn inhoud en loopt de naam de knop in. */
.sh-name,.sh-city{white-space:nowrap;overflow:hidden;
  -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 32px),transparent);
          mask-image:linear-gradient(to right,#000 calc(100% - 32px),transparent)}
/* De weekdag onder de datum (ook .sh-city) vervaagt NIET: die is nooit te
   lang, en "DONDERDAG" kwam anders net in het verloop. De datumkolom is breed
   genoeg gemaakt voor de langste dag (ook op een telefoon, zie hieronder). */
.sh-date .sh-city{-webkit-mask-image:none;mask-image:none;overflow:visible}

/* Maandkoppen (blok-vinkje "Per maand", aan op /agenda). Elke maand een
   eigen groep met de bovenrand; de lijst zelf heeft hem dan niet.
   Maat 18–22px: duidelijk een kop boven de regels, maar kleiner en gedempt
   naast de 30px namen, zodat de shows zelf de blikvanger blijven. */
.show-list.per-maand{border-top:0}
.sh-maand{font-family:var(--font-display);font-weight:600;text-transform:uppercase;
  letter-spacing:.01em;font-size:clamp(18px,1.6vw,22px);color:var(--muted);
  margin:clamp(32px,4vw,56px) 0 clamp(10px,1.2vw,16px)}
.sh-maand:first-child{margin-top:0}
.sh-groep{border-top:1px solid var(--line)}

/* right col — alleen nog de knop of "Uitverkocht" */
/* stretch: de knop vult de (gedeelde) kolom, dus alle knoppen even breed */
.sh-right{display:flex;flex-direction:column;align-items:stretch;
  gap:10px;text-align:right}
/* ⚠️ De knop is sinds 2026-09-29 `btn btn-fill` (de primaire blauwe knop).
   Zet hier dus GEEN `background`, `border`, `color` of `border-radius` meer
   neer: deze regel staat verderop in het bestand dan de knoppen-sectie en
   wint bij gelijke specificiteit — precies de fout die de oude "Meer
   shows"-knop eerder maakte. Ook het FORMAAT hoort hier niet: deze knop moet even groot
   zijn als de boekingsknop onderaan de pagina (op verzoek, 2026-09-29), en
   die is een kale `.btn.btn-fill`. Hier stond even `font-size:13px;
   padding:9px 16px` — dat maakte hem kleiner dan de rest en is er daarom uit.
   Blijft over: niet afbreken, en geen onderstreping omdat het een link is. */
.sh-btn{white-space:nowrap;text-decoration:none}
.sh-ico{width:16px;height:16px;flex:none}
.sh-sold{font-family:var(--font-mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted)}

/* sold row */
/* UITVERKOCHT staat zachter; die regel staat bovenaan deze sectie, bij wat er
   van het verwijderde naar-voren-effect overbleef. Hij stond hier tot
   2026-09-29 en zat daarna een tijd in de `--rij`-tabel die met dat effect is
   verdwenen.

   `pointer-events:none` stond hier ook achter en komt niet terug: er valt niets
   te blokkeren — bij uitverkocht wordt de knop niet getekend, dus er zit geen
   link in de regel. */

/* Knop onder de agenda — een gewone LINK, meestal naar /agenda.
   Hier stonden tot 2026-09-29 twee dingen die weg zijn met het uitklappen:
   `.show-row.show-extra` (rijen die met een max-height-animatie open
   schoven) en de opmaak van `.shows-more-btn` (een pijltje dat omklapte en
   een label dat wisselde tussen "Meer" en "Minder"). Die knop laadt niets meer
   bij; de homepage toont een handvol shows en linkt door.

   De opmaak van de knop zelf komt van `.btn.btn-fill` in de knoppen-sectie.
   Zet hier dus geen `border`, `background`, `color` of `padding` neer — dat
   overschrijft `.btn-fill`, want deze regel staat verderop in het bestand en
   wint bij gelijke specificiteit. Hier hoort alleen de plaatsing.

   Links, net als onder Muziek en Mixes (2026-10-19, op verzoek; was gecentreerd). */
.shows-more-wrap{display:flex;justify-content:flex-start;padding-top:clamp(20px,3vw,36px)}

@media(max-width:640px){
  /* De datumkolom was `clamp(60px,18vw,90px)` — op een telefoon van 390px dus
     70px breed, terwijl "05" en "OKT" daar samen zo'n 35px van vullen. Die
     lege helft las als een groot gat tussen de datum en de naam, nog vóór de
     `gap` begon. Kolom smaller én gap kleiner (2026-09-29). */
  /* min. 80px: daar past "DONDERDAG" (11px, .08em) in — zie .sh-date .sh-city */
  .show-list{grid-template-columns:clamp(80px,21vw,100px) minmax(0,1fr) auto;
    column-gap:clamp(8px,2.2vw,14px)}
  /* De plaats stond hier verborgen zolang hij in de rechterkolom zat en
     daar met de knop vocht. Sinds 2026-09-29 staat hij onder de naam en
     past hij ook op een telefoon — en hij blijft op één regel: hij breekt
     niet af maar faadt weg, net als de naam erboven. Zet hier dus geen
     `white-space:normal` neer. */
  /* 11px op een telefoon (was 13, 2026-10-19 op verzoek) — geldt ook voor de weekdag */
  .sh-city{font-size:11px;letter-spacing:.08em;margin-top:5px}
  .sh-name,.sh-city{
    -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 22px),transparent);
            mask-image:linear-gradient(to right,#000 calc(100% - 22px),transparent)}
  /* De knop is op desktop een kale `.btn.btn-fill`, even groot als de
     boekingsknop — zo gevraagd. Op een telefoon klopt dat formaat niet meer:
     die knop is daar breder dan de naam ernaast en trekt de hele regel scheef.
     Alleen hier dus kleiner. Kleur, rand en radius blijven van `.btn-fill`;
     zet die hier niet neer. */
  .sh-btn{font-size:12px;padding:10px 15px;gap:7px}
  .sh-ico{width:14px;height:14px}
}

/* =====================================================================
   MEDIA / VISUALS — vaste indeling (bloktype 'video')

   Vier plekken in plaats van een vrij raster:

       ┌───────────────────────┬─────────┐
       │  liggend 16:9         │ staand  │
       │  (2/3 breed)          │  9:16   │
       ├───────────┬───────────┤  (1/3)  │
       │  foto 1/3 │  foto 1/3 │         │
       └───────────┴───────────┴─────────┘

   Wie bepaalt welke hoogte?
   • De drie kolommen zijn even breed (w), met `gap` ertussen.
   • De staande tegel rechts is w breed en dus w × 16/9 hoog. Die hoogte
     is de hoogte van het hele blok.
   • De liggende tegel is 2w + gap breed en dus (2w+gap) × 9/16 hoog.
   • Wat er overblijft, is de hoogte van de twee foto's:
     w × 16/9 − (2w+gap) × 9/16 − gap ≈ 0,65 w − 1,6 gap. Bij een volle
     .wrap (1400px) komt dat neer op zo'n 452 × 261 — ongeveer 16:9, dus
     de rij eronder oogt vanzelf als twee liggende foto's.

   Daarom mag hier wél aspect-ratio (het oude staande raster gebruikte
   met opzet een ::before-spacer): de hoogtes zijn hier niet meer "de
   hoogste tegel wint", maar liggen vast. .med-main is een flexkolom die
   door het grid op de hoogte van de staande tegel wordt gerekt; de
   fotorij (flex:1) pakt precies wat de liggende tegel overlaat.
   ===================================================================== */
.med-grid{--med-gap:clamp(12px,1.6vw,22px);
  display:grid;grid-template-columns:repeat(3,1fr);gap:var(--med-gap);align-items:stretch}
.med-main{grid-column:span 2;display:flex;flex-direction:column;gap:var(--med-gap);min-height:0}
.med-hero{flex:0 0 auto;aspect-ratio:16/9}
.med-row{flex:1 1 auto;min-height:0;display:grid;grid-template-columns:1fr 1fr;gap:var(--med-gap)}
.med-side{aspect-ratio:9/16}
/* knoppen linksonder, onder het geheel */
.med-actions{display:flex;flex-wrap:wrap;gap:14px;margin-top:clamp(18px,2.4vw,30px)}
.vid{display:block;position:relative;border-radius:12px;overflow:hidden;cursor:pointer;
  background:#0a0a0a;border:1px solid var(--line);min-height:0}
.vid .ph{position:absolute;inset:0;border:0}
/* media uit de bibliotheek vult de tegel; zonder media blijft .ph staan */
.vid-media{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;
  transition:transform calc(.7s/var(--motion)) cubic-bezier(.16,1,.3,1)}
.vid:hover .vid-media{transform:scale(1.04)}
/* ── De waas over de tegel (2026-09-29, op verzoek) ──────────────────────
   Een tegel toont eerst alléén beeld. Ga je er met de muis overheen, dan komt
   hier een donkere laag overheen waarop de tekst verschijnt. Tot 2026-09-29
   stond het bijschrift er permanent, met alleen een verloop eronder.

   Een verloop aan de kant waar de tekst staat, meer niet: dat houdt hem
   leesbaar op een lichte foto en laat de rest van het beeld met rust. De
   vlakke verdonkering die er tot 2026-10-08 overheen lag, is eruit op verzoek
   — die was er voor de cijfers middenop, en die zijn weg. Een YouTube-tegel
   houdt hem wél (daar staat de grote speelknop middenop) en draait het verloop
   om, want daar staat de titel BOVENIN.

   Het verloop reikt tot **34%** van de tegel, niet tot 58% zoals tot 2026-10-08
   (op verzoek: het liep veel te ver door). Dat is ruim voor wat er staat: sinds
   het bijschrift op één regel wordt afgekapt is dat een naamregel plus één
   regel tekst, onderkant op 13px — samen zo'n 45px. Maak je `.cap` ooit hoger
   (meer regels, grotere letter), dan moet dit percentage mee; alleen `.vid-yt`
   staat los, want daar zit de tekst bovenin.

   Waarom een eigen element en geen ::after op de tegel: die is al bezet
   geweest, en met een element is het omdraaien voor YouTube één regel.

   Op een AANRAAKSCHERM bestaat hover niet. Daar blijft alleen het verloop
   staan — een vlakke waas zou elke foto de hele tijd donker maken. Zie het
   blok `@media(hover:none)` hieronder; daar staan alle aanraakstanden bij
   elkaar. */
.vid-ov{position:absolute;inset:0;z-index:1;pointer-events:none;
  opacity:0;transition:opacity .35s ease;
  background:linear-gradient(to top,rgba(0,0,0,.82),rgba(0,0,0,0) 34%)}
.vid-yt .vid-ov{
  background:linear-gradient(to bottom,rgba(0,0,0,.82),rgba(0,0,0,0) 58%),rgba(0,0,0,.4)}
.vid:hover .vid-ov,.vid:focus-visible .vid-ov{opacity:1}
/* Teken dat er iets te spelen valt. Alleen bij YouTube: de eigen knopvorm van
   YouTube, maar in het blauw van de site met een witte driehoek — niet in
   YouTube-rood, dat vloekt met alles eromheen. Wat TikTok en Instagram krijgen,
   is nog niet besloten; die hebben voorlopig niets.
   De svg zit in cms-render.js (YOUTUBE_PLAY_SVG); het witte vlak zit dáár, want
   het pad heeft de driehoek eruit gesneden. */
.vid .play-ico{position:absolute;inset:0;display:grid;place-items:center;z-index:2}
.yt-play{width:clamp(62px,6.4vw,96px);color:var(--accent);display:block;
  filter:drop-shadow(0 6px 22px rgba(0,0,0,.45));transition:transform .35s}
.yt-play svg{width:100%;height:auto;display:block}
.vid:hover .yt-play{transform:scale(1.07)}
/* De cijfers van de post (weergaven, likes, reacties) stonden hier tot
   2026-10-08 middenop, bij hover. Eruit op verzoek: ze lagen over de naam en
   het bijschrift heen en vroegen een vlakke waas over de hele foto. De regels
   staan in git; het blok bewaart de cijfers nog wel (CMS → Cijfers ophalen). */

/* ── De tekst op de tegel ────────────────────────────────────────────────
   Twee soorten tegel, twee plekken (de klasse komt uit medTile):

     .vid-social   accountnaam + bijschrift linksonder, als een echte post
     .vid-yt       de titel LINKSBOVEN — middenop staat de YouTube-knop

   Alles komt tegelijk met de waas in beeld en schuift daarbij een paar pixels
   mee: bij een YouTube-tegel van boven naar beneden, bij de rest andersom —
   de tekst komt zo altijd vanaf de dichtstbijzijnde rand.

   `-webkit-line-clamp:1` op `.cap-tekst`: **één regel, en wat niet past eindigt
   in …** (2026-10-08, op verzoek). Tot dan mocht een bijschrift twee regels en
   een titel drie; een lange tekst vulde daarmee een kwart van de foto. Nu
   breekt hij nergens meer naar een tweede regel. Staat op de gedeelde klasse,
   dus zowel het bijschrift als de titel doet het — en het hoort ook samen met
   `display:-webkit-box` + `overflow:hidden` daar, want alleen die drie samen
   geven dat afkappen mét puntjes.

   Elke soort zegt zelf hoe zijn tekst leest; in `.cap-tekst` staat alleen wat
   ze delen. Zo overrult de een de ander niet, en hoeft niemand op de volgorde
   in dit bestand te letten. */
.vid .cap{position:absolute;left:14px;right:14px;bottom:13px;z-index:2;pointer-events:none;
  display:flex;flex-direction:column;gap:3px;
  font-family:var(--font-mono);color:#fff;text-shadow:0 1px 8px rgba(0,0,0,.6);
  opacity:0;transform:translateY(8px);
  transition:opacity .3s ease,transform .4s cubic-bezier(.16,1,.3,1)}
.vid-yt .cap{top:14px;bottom:auto;transform:translateY(-8px)}
.vid:hover .cap,.vid:focus-visible .cap{opacity:1;transform:none}
/* ⚠️ Maten in `clamp()` en niet vast op 12px (2026-10-08, op verzoek: te klein
   om goed te lezen). Een tegel is zo breed als het venster toelaat (de `.wrap`
   is 92vw), dus schaalt de tekst met vw mee: op een telefoon blijft het de oude
   12px — daar is een socialkaart ~200px breed en leest 12px als een echte post
   — en op een breed scherm, waar diezelfde kaart het dubbele is, loopt het op.
   De bovengrens houdt het een bijschrift en geen kop. Dezelfde vorm als de
   YouTube-titel hieronder al had. */
.cap-naam{font-size:clamp(12px,.9vw,14px);font-weight:700;letter-spacing:.1em;
  text-transform:uppercase}
.cap-tekst{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;
  -webkit-line-clamp:1}
/* Het bijschrift van een post: gewone schrijfwijze, iets zachter dan de naam
   erboven. Kapitalen zouden daar als een tweede kop lezen. */
.vid-social .cap-tekst{font-size:clamp(12px,1vw,15px);line-height:1.45;letter-spacing:.02em;
  opacity:.92}
/* Een geopende foto draagt sinds 2026-10-08 geen tekst meer (op verzoek, een
   paar uur nadat hij er juist in ging): groot bekeken mag de foto alleen zijn.
   De eigen maten die `.vplay-frame` hier even had, staan in git. */
/* Bij een YouTube-tegel is diezelfde regel geen bijschrift maar de TITEL van de
   video, en die staat er alleen — geen naam erboven. Dus groter, zwaarder en op
   volle sterkte. Ook hij staat op één regel; het afkappen komt van `.cap-tekst`.
   ⚠️ Géén kapitalen en geen extra letterruimte (2026-09-29, op verzoek): de
   titel wordt in het CMS met gewone hoofd- en kleine letters ingevuld, en dan
   hoort hij er ook zo te staan. Tot dat verzoek stond hier
   `text-transform:uppercase`, geërfd van de labelvorm die de rest van de site
   gebruikt — zet dat niet terug. */
.vid-yt .cap-tekst{font-size:clamp(15px,1.5vw,21px);font-weight:600;line-height:1.25}

/* Het blauwe klikteken rechtsboven (`.vid-hint`: driehoekje bij een video,
   vergroot-teken bij een foto) is er op 2026-10-08 uit gegaan, op verzoek: de
   tegel komt bij hover al naar voren en dat zegt genoeg. De regels staan in
   git. De YouTube-knop middenop (`.play-ico`) blijft — die hoort bij het
   platform, niet bij "je kunt hier klikken". */

/* ── Aanraakscherm: geen hover, dus alles staat er meteen ─────────────────
   Het leesverloop en de tekst staan er permanent; verder is er niets dat bij
   hover hoort te verschijnen. */
@media(hover:none){
  .vid-ov{opacity:1;background:linear-gradient(to top,rgba(0,0,0,.8),rgba(0,0,0,0) 34%)}
  .vid-yt .vid-ov{background:linear-gradient(to bottom,rgba(0,0,0,.8),rgba(0,0,0,0) 55%)}
  .vid .cap{opacity:1;transform:none}
}

/* Smaller dan een laptop — en dit geldt tot en met de telefoon:

       ┌─────────────────────────┐
       │   liggend 16:9          │
       ├────────────┬────────────┤
       │  foto      │            │
       ├────────────┤  staand    │
       │  foto      │   9:16     │
       └────────────┴────────────┘

   De liggende tegel over de volle breedte, daaronder de twee foto's ONDER
   elkaar links en de staande tegel rechts — dezelfde kant als op een groot
   scherm. `display:contents` haalt .med-main uit de weg, zodat alle vier de
   tegels gewoon in hetzelfde raster liggen. De fotokolom wordt door het grid
   op dezelfde hoogte gerekt als de staande tegel ernaast en verdeelt die over
   twee (flex:1).

   Twee dingen die hier tot 2026-09-22 anders waren, allebei op verzoek weg:
   · De staande tegel stond op een tablet LINKS en de foto's rechts — precies
     omgekeerd aan het grote scherm.
   · Onder 560px klapte alles onder elkaar. Dat leek logisch (een 9:16 tegel
     is immers de vorm van het scherm zelf), maar in de praktijk werd die
     staande video daardoor loeigroot en viel het blok uit elkaar. */
@media(max-width:900px){
  .med-grid{grid-template-columns:1fr 1fr}
  .med-main{display:contents}
  .med-hero{grid-column:1/-1}
  .med-row{grid-column:1;grid-row:2;display:flex;flex-direction:column;gap:var(--med-gap)}
  .med-side{grid-column:2;grid-row:2}
  .med-foto{flex:1 1 0}
}

/* =====================================================================
   MEDIA SHOWCASE — video 16:9, YouTube-knop, dan vijf foto's

   Vaste indeling sinds 2026-10-19; zie mountMediaShowcase in cms-render.js.
   Zes kolomsporen: drie foto's van 4:5 (2 sporen elk), daaronder twee van
   3:2 (3 sporen elk). Ook op een telefoon, daar zijn ze gewoon kleiner.
   ===================================================================== */
.msc-kop{flex-direction:column;align-items:flex-start;gap:0;margin-bottom:clamp(18px,2.4vw,30px)}
.msc-intro{text-align:left;max-width:46ch;margin-top:clamp(18px,2vw,26px);color:var(--text-soft)}
.msc-video{aspect-ratio:16/9;width:100%}
iframe.msc-video{display:block;border:0;border-radius:12px;background:#000}
.msc-yt{margin-top:clamp(18px,2.4vw,30px)}
/* Onderaan de helft van .sec-pad (op verzoek): de foto's lopen tot de rand
   door, zonder knop eronder, en dan voelde de volle padding plus die van de
   volgende sectie als een gat. */
[data-block="mediashowcase"]{padding-bottom:clamp(40px,5.5vh,80px)}
.msc-grid{--msc-gap:clamp(10px,1.3vw,18px);margin-top:clamp(32px,4vw,56px);
  display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:var(--msc-gap)}
.msc-portret{grid-column:span 2;aspect-ratio:4/5}
.msc-landschap{grid-column:span 3;aspect-ratio:3/2}

/* =====================================================================
   SOCIALS — vier staande kaarten naast elkaar, knoppen linksonder

   Tot 2026-10-19 een carrousel (slepen, pijlen, timer); nu een vaste rij van
   vier, op een telefoon twee bij twee. Gap gelijk aan het Media overzicht.
   ===================================================================== */
.soc-track{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(12px,1.6vw,22px)}
.soc-card{aspect-ratio:9/16}
.soc-actions{display:flex;flex-wrap:wrap;gap:14px;margin-top:clamp(18px,2.4vw,30px)}
@media(max-width:700px){ .soc-track{grid-template-columns:1fr 1fr} }

/* ── speler-overlay: de video op ware grootte, mét geluid ─────────────
   Ligt boven de nav (7000) maar onder het mobiele menu (7200) is niet
   genoeg — hij moet er juist bovenop, want vanuit het menu is de sectie
   bereikbaar. Vandaar 7300. */
.vplay{position:fixed;inset:0;z-index:7300;background:rgba(0,0,0,.78);
  display:grid;place-items:center;padding:clamp(44px,5.5vh,64px) clamp(12px,2.4vw,32px);
  opacity:0;visibility:hidden;transition:opacity .35s ease,visibility .35s}
.vplay.open{opacity:1;visibility:visible}
/* --vplay-ruimte: wat er naast de video zelf nog aan hoogte nodig is (de rand
   boven en onder, plus het bijschrift).

   ⚠️ BEIDE `width:100%`-regels hieronder zijn nodig, en om dezelfde reden.
   `.vplay-box` is een flexkolom met `align-items:center` en `.vplay-slot` een
   flex-item daarin: zonder opgegeven breedte is zo'n item precies zo breed als
   zijn inhoud. De inhoud is een `<iframe>`, en een iframe zonder afmetingen is
   standaard 300px breed. De `width:min(100%,…)` van het venster rekende dan
   tegen die 300px af en bleef dus klein, hoeveel ruimte er ook was. Met beide
   regels erin is de keten sluitend: grid-vak → .vplay-box → .vplay-slot →
   venster. Haal je er één weg, dan schrompelt de speler weer. */
.vplay-box{display:flex;flex-direction:column;align-items:center;gap:14px;
  width:100%;max-height:100%;--vplay-ruimte:158px}
.vplay-slot{width:100%;display:flex;justify-content:center;min-height:0}
/* Het kader om de foto. Krimpt om zijn inhoud heen, zodat het kruisje in de
   rechterbovenhoek van de FOTO komt te staan en niet in die van het scherm.
   `line-height:0` haalt de paar pixels onderruimte weg die een browser onder
   een afbeelding zet — anders staat het kruisje net niet in de hoek. */
.vplay-frame{position:relative;display:inline-block;max-width:100%;line-height:0}
.vplay-media{display:block;max-width:100%;max-height:calc(100vh - var(--vplay-ruimte));
  border-radius:12px;background:#000}
/* Ingesloten speler van TikTok, Instagram of YouTube. Per platform komt mee:
   --emb-ar de verhouding (voor aspect-ratio), --emb-f dezelfde verhouding als
   getal (breedte ÷ hoogte) en --emb-h hoeveel van de beschikbare hoogte het
   mag pakken. Eerst de hoogte die er is, daaruit de breedte, en nooit breder
   dan het venster. YouTube pakt alles (--emb-h:1), de staande spelers 80% —
   dat is de lucht boven en onder bij TikTok en Instagram.
   ⚠️ De maat staat op het KADER, niet op het iframe: `width:…%` op een iframe
   heeft een ouder met een bekende breedte nodig, en een kader dat om zijn
   inhoud heen krimpt heeft die niet. Dan valt een iframe terug op de 300px
   die het van zichzelf is — dat is precies de bug van 2026-09-20. */
.vplay-frame.is-embed{aspect-ratio:var(--emb-ar,16/9);
  width:min(100%,calc((100vh - var(--vplay-ruimte)) * var(--emb-h,1) * var(--emb-f,1.7778)))}
.vplay-embed{display:block;border:0;border-radius:12px;background:#000;
  width:100%;height:100%}
/* De regel ONDER de weergave. Blijft bij een video en bij een ingesloten
   speler. Bij een geopende FOTO staat er sinds 2026-10-08 geen tekst meer — niet
   eronder en niet erin — en laat `openVideoPlayer()` deze leeg; `:empty` haalt
   hem dan weg, zodat er ook geen lege ruimte onder de foto overblijft. */
.vplay-cap{font-family:var(--font-mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted);text-align:center}
.vplay-cap:empty{display:none}
/* Hier stond de knop onder de grote weergave ("Bekijk op TikTok") plus de
   `.has-link`-stand die er 70px extra hoogte voor vrijhield in --vplay-ruimte.
   Beide eruit op 2026-10-08, op verzoek: de post speelt hier, dus hoeft er
   niemand naar het platform. Zie `platformKnop()` in cms-render.js. */
/* Kruisje in de rechterbovenhoek van de foto (stond tot 2026-09-22 in de hoek
   van het scherm). Het zit in `.vplay-frame`, dus het schuift mee met hoe
   groot de foto uitvalt. Een donker rondje eronder: zonder dat verdwijnt een
   wit kruisje in een lichte foto. */
.vplay-close{position:absolute;top:10px;right:10px;z-index:2;
  width:38px;height:38px;border-radius:50%;border:0;padding:0;cursor:pointer;
  color:#fff;background:rgba(0,0,0,.55);
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
  display:grid;place-items:center;
  transition:background .25s ease,color .25s ease}
.vplay-close::before,.vplay-close::after{content:"";position:absolute;
  width:17px;height:2px;background:currentColor;border-radius:2px}
.vplay-close::before{transform:rotate(45deg)}
.vplay-close::after{transform:rotate(-45deg)}
.vplay-close:hover{background:var(--accent);color:var(--accent-ink)}
/* ⚠️ Hier stond `.vplay-nav`: twee ronde bladerpijlen op de rand van de foto,
   waarmee je in de speler naar de volgende post ging zonder eerst te sluiten.
   Die zijn er in twee stappen op verzoek uit gegaan — op 2026-10-08 buiten het
   Socials-blok, en op 2026-10-09 ook daarbinnen ("Als ik een social post open,
   dan kan ik nog met pijltjes naar links en rechts, kan je die weghalen?").
   Met hen `vLijst`/`vIndex`/`vplayStap()` en de pijltjestoetsen in de speler.
   Het kruisje is nu het enige dat over de foto heen staat. Niet terugzetten
   zonder dat erom gevraagd is; de opmaak staat in git (v1.102.2 en eerder). */

/* =====================================================================
   ABOUT / BIO
   ===================================================================== */
/* Gelijke kolommen, zodat de GAP het midden van de pagina is (2026-09-15).
   Stond eerder op 0.9fr 1.1fr. Met ongelijke kolommen ligt de naad tussen foto
   en tekst per definitie scheef: de tekst begon op 48% — vrijwel exact de helft —
   en het midden van de gap lag 66px links van het paginamidden. Het fotoblok was
   daardoor 42,6% breed en het tekstblok 52%, wat het geheel uit het lood trok.
   De extra breedte leverde de lopende tekst bovendien weinig op: .about-copy p
   is afgetopt op 54ch, dus die ruimte werd wit. Nu is de naad de as. */
.about-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(30px,5vw,80px);
  align-items:center}
/* Gestapeld: de afbeelding ONDER de tekst (2026-09-18, op verzoek).
   Stond hier eerder bovenaan, met "Links of rechts" als een puur
   desktop-keuze. Onderaan leest beter: eerst de kop en het verhaal, dan de
   knop, en de foto als sluitstuk — in plaats van dat je op een telefoon eerst
   langs een schermvullende foto moet scrollen voor je weet waar het over gaat.
   Alleen `order` op de foto is genoeg; de tekstkolom staat op de standaard 0
   en komt daarmee vanzelf eerst. Geldt voor ELK Tekst + Afbeelding-blok, dus
   ook op /over-mij. Zelfde keuze als bij de kaart in Muziek highlight. */
@media(max-width:880px){
  .about-grid{grid-template-columns:1fr}
  .about-portrait{order:2}
}
/* afbeelding rechts i.p.v. links (Tekst + Afbeelding-blok). Alleen de volgorde
   wisselt — met gelijke kolommen is er niets aan de breedtes om te draaien.
   Alleen op desktop: gestapeld staat de foto altijd onderaan, zie hierboven. */
@media(min-width:881px){
  .about-grid.ti-flip .about-portrait{order:2}
  .about-grid.ti-flip .mh-card{order:2}     /* Muziek highlight, zie onder */
  .about-grid.ti-flip .about-copy{order:1}
}
.about-portrait{aspect-ratio:3/4;border-radius:10px}

/* ⚠️ GEEN HOVER-EFFECT OP DEZE FOTO (2026-10-09, op verzoek).
   Tussen 2026-09-29 en die dag zoomde hij bij hover 4% in, dezelfde beweging
   als een Media-tegel (`.vid:hover .vid-media`). Dat is eruit: de foto staat
   stil.

   Wat eruit ging en waarom het zo omslachtig was: deze foto is een
   CSS-ACHTERGROND op het vlak zelf (zie mountTextImage in cms-render.js:
   `port.style.background`), en een achtergrond kan niet transformeren. Het vlak
   zelf schalen kan ook niet — dan groeit de hele kolom. Daarom lag er een
   `::before` met `background:inherit` overheen, dat de foto live overnam (ook
   de foto die `achtergrondLui()` er later pas in zet) en als enige schaalde,
   met `overflow:hidden` op het vlak om het binnen de hoeken te houden, en
   `:not(.ph)` zodat de gestreepte plaatshouder niet meedeed.
   Komt er ooit een ander effect op deze foto, dan is dat pseudo-element weer de
   weg: in git staat de hele constructie. */
/* Dit was `.about-copy h2` — een TAG-selector. Sinds 2026-09-20 kan de titel
   van Tekst + Afbeelding via "Kopniveau" ook een h1 zijn, en dan greep die
   selector mis: de kop verloor in één klap Oswald, de hoofdletters en zijn
   maat. Nu staat de opmaak op de KLASSE en overschrijft `h2.ti-title` alleen
   de maat — precies hetzelfde patroon als .sec-title / h2.sec-title hierboven.
   De basismaat is daarmee de h1-maat, gelijk aan .sec-title. */
.ti-title{font-family:var(--font-display);text-transform:uppercase;font-weight:600;
  letter-spacing:.01em;
  font-size:clamp(52px,7vw,96px);line-height:.92;margin-bottom:26px}
/* zelfde maat als h2.sec-title — zie de uitleg daar (0,68 × de h1-maat) */
h2.ti-title{font-size:clamp(36px,4vw,56px)}
/* Kleur, vet, links en lijstjes staan NIET hier maar bij "RIJKE TEKST"
   verderop — dat is één blok voor élke tekstkolom van de site. Hier blijft
   alleen wat eigen is aan deze kolom: de maat en de regellengte. */
.about-copy p{font-size:clamp(16px,1.4vw,20px);max-width:54ch;
  text-wrap:pretty}
/* Hier stond `.about-copy p .mut{color:var(--muted)}`. Die regel heeft NOOIT
   gewerkt: hij zoekt een `.mut` BINNEN een <p>, terwijl de klasse op de <p>
   zelf stond. De vervolgalinea's waren daardoor net zo wit als de eerste.
   Sinds 2026-09-18 is de hele lopende tekst gedempt en is nadruk iets wat je
   zelf zet (**vet**), dus de klasse en deze regel zijn allebei overbodig. */
/* .stats had hier een eigen opmaak (flex-rij, margin-top:38px) toen de
   cijferrij ook in het Tekst + Afbeelding-blok zat. Sinds 2026-09-15 staat die
   rij alleen nog in het USP-blok, en .usp-stats overschrijft elke declaratie
   die hier stond — de regel deed dus niets meer.
   De KLASSE zelf blijft wel in de opmaak staan: motion.js zoekt op `.stats` om
   de tellers te observeren (zie scanCounters), en fillStats() haalt het
   element er ook mee op. Weghalen uit de HTML breekt het optel-effect. */
.stat .n{font-family:var(--font-display);font-weight:600;letter-spacing:0;
  font-size:clamp(35px,3.9vw,62px);line-height:1;
  color:var(--accent)}
.stat .l{font-family:var(--font-mono);font-size:11px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);margin-top:8px}

/* Knop in het Tekst + Afbeelding-blok, als sluitstuk van de tekstkolom.
   Stond eerder onder de cijferrij; die is er nu uit, dus dit is de ruimte
   tussen de laatste alinea en de knop. De alinea heeft zelf al
   margin-bottom:18px, dus er zit in de praktijk 44–58px tussen. */
.ti-cta{margin-top:clamp(26px,3.5vw,40px);display:flex;flex-wrap:wrap;gap:14px}

/* =====================================================================
   MUZIEK HIGHLIGHT  (bloktype 'muziekhighlight')

   Eén nummer uitlichten: links titel, tekst en knop — rechts dezelfde
   vierkante kaart als in het Muziek-blok, dus met hover-play en de links
   naar SoundCloud en Spotify.

   Vrijwel alle opmaak komt van elders en dat is bewust:
     · de kolommen, de gap en het omklappen naar één kolom → .about-grid
     · titel, alinea's en de knop                          → .about-copy / .ti-*
     · de kaart zelf, ook de mobiele lijstregel            → .mu-card
   Wat hier staat is dus alleen wat die drie niet al regelen.

   De kaart krijgt GEEN maximumbreedte: hij vult zijn kolom, net als de foto
   in Tekst + Afbeelding. Hij is vierkant (.mu-card heeft aspect-ratio:1) en
   daarmee altijd lager dan die foto, die op 3:4 staat.
   ===================================================================== */
.mh-card{min-width:0}
/* Geen nummer gekozen: kaartkolom verborgen (cms-render.js), dus de tekst
   krijgt de volle breedte in plaats van een halve kolom met een gat ernaast. */
.about-grid.mh-solo{grid-template-columns:1fr}

/* ── kaart kleiner, titel breder (2026-10-19, op verzoek) ──
   De kaart is 36% van .wrap: altijd groter dan een kaart in het Muziek-blok
   (3 per rij, ~30%, 448px bij volle breedte), en de tekstkolom krijgt de
   rest. Kaart rechts = 2e kolom; links (zonder .ti-flip) draait het om.
   De h1 houdt de gewone maat van de site (een kleinere maat stond hier kort,
   is op verzoek teruggedraaid); `balance` verdeelt de titelregels gelijk.
   Alleen desktop: gestapeld (≤880px) blijft alles zoals het was. */
@media(min-width:881px){
  [data-block="muziekhighlight"] .about-grid.ti-flip:not(.mh-solo){grid-template-columns:minmax(0,1fr) 36%}
  [data-block="muziekhighlight"] .about-grid:not(.ti-flip):not(.mh-solo){grid-template-columns:36% minmax(0,1fr)}
}
[data-block="muziekhighlight"] .ti-title{text-wrap:balance}
/* Tekst + Afbeelding: 50/50, met meer ruimte tussen tekst en foto dan de
   gedeelde .about-grid (2026-10-19/20, op verzoek; eerst alleen het h1-blok,
   nu elk textimage-blok. Een 36%-foto stond hier kort, is teruggedraaid). Alleen desktop. */
@media(min-width:881px){
  [data-block="textimage"] .about-grid{column-gap:clamp(48px,8vw,140px)}
}

/* ── de speler onder de tekst: play-knop (van de mixes) + waveform ──
   De waveform is dezelfde tekening als in het mix-blok (assets/waveform.js),
   maar met --wave-rest: het nog niet gespeelde deel donkergrijs, en het
   gespeelde deel kleurt van begin tot eind vol blauw. --line-strong is op de
   donkere achtergrond precies dat donkergrijs, en volgt het lichte thema. */
.mh-player{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;
  gap:clamp(12px,1.6vw,20px);margin-top:clamp(26px,3.5vw,40px);max-width:54ch}
.mh-bar{cursor:pointer;padding-block:6px}
.mh-bar .mf-wave{--wave-rest:var(--line-strong)}
.mh-player .ic{display:none;place-items:center}
.mh-player .ic-play,.mh-player.playing .ic-pause{display:grid}
.mh-player.playing .ic-play{display:none}
.mh-player svg{width:clamp(16px,1.5vw,20px);height:auto;display:block}
.mh-player .ic-play svg{margin-left:8%}
.mh-player + .ti-cta{margin-top:clamp(20px,2.5vw,28px)}

/* ── gestapeld: de kaart ONDER de tekst (2026-09-18, op verzoek) ──
   Zodra .about-grid naar één kolom klapt staat de kaart het sluitstuk van de
   sectie: eerst het verhaal en de knop, dan pas het nummer. Alleen `order` op
   de kaart is genoeg — de tekstkolom staat op de standaard 0 en komt daarmee
   vanzelf eerst. Anders dan bij Tekst + Afbeelding, waar de foto op mobiel
   juist altijd bovenaan staat; een foto is daar de opening, deze kaart is hier
   de afsluiting. */
@media(max-width:880px){
  .mh-card{order:2}
}

/* ── op touch staat de hover-staat meteen aan ──
   De kaart verbergt zijn overlay, play-knop en titel tot je erover hovert.
   Op een aanraakscherm gebeurt dat nooit, en dan is het een stille cover
   waarvan niemand ziet dat je erop kunt drukken. Dus: op elk apparaat zonder
   hover staat die laag altijd open.

   `hover:none` en niet een schermbreedte: het gaat om het invoerapparaat, niet
   om de maat van het venster. Een smal browservenster op een laptop houdt zo
   het hover-gedrag, een tablet van 1000px krijgt de open staat.

   De verdonkering gaat van 55% naar 18%: 55% is bedoeld als antwoord op een
   muisbeweging, maar permanent zou het de hoes onder een grijze deken leggen.
   18% houdt de hoes zichtbaar en laat de blauwe knop en de witte tekst (die
   onderin zijn eigen verloop heeft) nog goed opvallen. */
@media(hover:none){
  .mh-card .mu-ovl{opacity:1;background:rgba(0,0,0,.18)}
  .mh-card .mu-play{transform:scale(1)}
  .mh-card .mu-meta{opacity:1;transform:none}
}

/* =====================================================================
   TEKST  (bloktype 'tekst')
   Doorlopende tekst over de volle breedte — voor pagina's die niets anders
   zijn dan tekst (privacyverklaring, cookiebeleid). Tekst + Afbeelding kan
   dit niet: dat is een tweekolomsraster, daar krijgt de tekst altijd de
   halve breedte.

   De regel blijft wél smal. .wrap is tot 1400px breed en een regel van die
   lengte lees je niet — het oog verliest het begin van de volgende regel.
   68ch is ongeveer 600–650px bij deze lettergrootte, dezelfde maat die we
   eerder voor de tekstkolom op de homepage hebben aangehouden.
   ===================================================================== */
.tx-body{max-width:68ch;font-size:clamp(16px,1.4vw,19px);line-height:1.65;
  text-wrap:pretty}

/* =====================================================================
   TEKST + ACHTERGROND  (bloktype 'tekstbanner')

   Precies het Tekst-blok hierboven, met de foto als ACHTERGROND van het hele
   blok: van schermrand tot schermrand, 700px hoog, tekst eroverheen.

   Waarom een eigen laag (.tb-bg) en geen `background` op de sectie zelf:
   zo kan de donkere laag die de tekst leesbaar houdt er als ::after overheen
   zonder een tweede element. Zelfde opzet als .usp-bg hieronder — met één
   verschil: die blurt de foto (daar is het sfeer achter cijfers), hier niet.
   Hier is de foto het onderwerp.

   `.has-tb-bg` komt van mountTekstBanner() in cms-render.js, samen met
   --tb-img en --tb-ov. Geen foto = geen klasse, en dan gedraagt het blok zich
   exact als het Tekst-blok: gewone hoogte, gewone kleuren.
   ===================================================================== */
.tb-bg{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.tb-bg::before{content:"";position:absolute;inset:0;
  background:var(--tb-img) center/cover no-repeat}
.tb-bg::after{content:"";position:absolute;inset:0;
  background:#000;opacity:var(--tb-ov,.5)}
/* Hoogte: ongeveer een half scherm, met een bodem en een plafond.
   Stond eerst op een vaste 700px; dat was op een laptop te fors en op een
   telefoon bijna het hele scherm. `50svh` doet wat er gevraagd is — de helft
   van wat de bezoeker ziet — en de clamp houdt het aan beide kanten redelijk:
   nooit kleiner dan 320px (anders is het geen sfeerbeeld meer) en nooit groter
   dan 520px (op een hoog scherm zou de helft weer 700px+ worden).

   `svh` en niet `vh`: op mobiel is svh de KLEINSTE stand van de viewport, dus
   de hoogte springt niet mee als de browserbalk in- en uitschuift tijdens het
   scrollen. De regel erboven is het vangnet voor browsers die svh niet kennen.
   Zelfde aanpak als .page-shell.

   min-height en geen height: staat er ooit meer tekst in dan er past, dan
   groeit het blok mee in plaats van dat de tekst eruit loopt.

   `align-content` op een grid en niet flex: .wrap houdt zo zijn gewone
   blokgedrag, inclusief `width:min(1400px,92vw)` en `margin-inline:auto`. */
.has-tb-bg{min-height:clamp(320px,50vh,520px);
  min-height:clamp(320px,50svh,520px);
  display:grid;align-content:center;
  /* Overschrijft de sectiepadding van .sec-pad (clamp(80px,11vh,160px)) en
     staat daarom ná die regel in dit bestand — even zwaar, dus de laatste
     wint. Die ruime padding is voor een sectie op een egale achtergrond; hier
     is de foto de sectie, en dan telt alleen wat er in het midden staat. Met
     de oude waarde bleef het blok op een laptop vanzelf rond de 600px hangen,
     hoe laag de min-height ook stond — padding telt mee (box-sizing:border-box). */
  padding-block:clamp(48px,7vh,90px)}
/* Bovenaan een pagina zonder hero (zoals /over-mij) geldt de algemene regel
   bij .sec-pad (#page-blocks.no-hero > section:first-child) — die wint van de
   padding hierboven. Hier stond een eigen variant; sinds 2026-10-19 niet meer. */
/* De tekst hoort bóven de foto. */
.has-tb-bg .wrap{position:relative;z-index:1}
/* Op een foto is de gedempte lopende tekst (--text-soft) te zwak: die kleur is
   voor een egale donkere achtergrond gekozen. Hier één stap lichter, zodat het
   verschil tussen gewone en vetgedrukte tekst blijft bestaan — dat verschil IS
   de afspraak (zie RIJKE TEKST hierboven) — maar allebei leesbaar zijn. */
.has-tb-bg{--text-soft:#e3e5ec}

/* =====================================================================
   RIJKE TEKST  —  élke lopende tekst van de site (2026-09-18, op verzoek)

   Eén blok voor alle tekstkolommen: het Tekst-blok (`.tx-body`) én de
   tekstkolom van Tekst + Afbeelding, Muziek highlight en CTA (`.ti-body`).
   Die twee liepen uit elkaar — de ene gedempt met lijstjes en tussenkoppen,
   de andere wit zonder — terwijl het voor een bezoeker hetzelfde soort tekst
   is. De HTML komt uit dezelfde bron: RIJKETEKST.naarHtml() in
   assets/rijke-tekst.js, die het CMS ook gebruikt.

   DE AFSPRAAK: lopende tekst is GEDEMPT, nadruk is WIT.
   Dat is de reden dat dit werkt. Zou de hele tekst wit zijn, dan valt een
   vetgedrukt woord alleen op door zijn dikte en dat is op een scherm bijna
   niets. Nu is het een kleursprong: van --muted naar --text. Wie iets wil
   laten opvallen, maakt het vet — er is geen andere knop voor nodig.
   ===================================================================== */
.tx-body,.ti-body{color:var(--text-soft)}
.tx-body p,.ti-body p{margin-bottom:18px}
.tx-body > :first-child,.ti-body > :first-child{margin-top:0}
.tx-body > :last-child,.ti-body > :last-child{margin-bottom:0}
/* Nadruk en links dragen hun eigen klasse (RIJKETEKST zet die erop), NIET een
   selector per plek. Daardoor werken ze overal waar tekst uit het CMS komt —
   in een tekstkolom, in de intro naast een sectiekop, in de hero-ondertitel —
   zonder dat de stylesheet van elke nieuwe plek hoeft te weten.
   600 is de dikte die Inter hier overal voor gebruikt (knoppen, menu). */
.rt-vet{color:var(--text);font-weight:600}
/* De hero-ondertitel staat zélf al op 600; daar zou vet niets doen. */
.hero-sub .rt-vet{font-weight:700}
/* Links: wit en onderstreept, zodat ze in een gedempte alinea meteen te zien
   zijn. De onderstreping staat iets lager dan standaard en is dunner, anders
   snijdt hij door de staarten van de g en de j. */
.rt-link{color:var(--text);text-decoration:underline;
  text-decoration-thickness:1px;text-underline-offset:3px;
  transition:color .25s}
.rt-link:hover{color:var(--accent)}
/* Lijstjes. `padding-left` en niet `margin-left`: de bolletjes horen binnen de
   tekstkolom te vallen, niet in de marge ernaast. */
.rt-lijst,.rt-nummers{margin:0 0 18px;padding-left:22px}
.rt-lijst{list-style:disc}
.rt-nummers{list-style:decimal}
.rt-lijst li,.rt-nummers li{margin-bottom:6px}
/* Tussenkop (`## ` in het invulvak, alleen in het Tekst-blok). Kleiner dan de
   sectietitel en in de tekstkleur i.p.v. gedempt, zodat hij de lap tekst
   opdeelt zonder als een tweede paginatitel te lezen. */
.rt-kop{font-family:var(--font-display);text-transform:uppercase;font-weight:600;
  letter-spacing:.01em;font-size:22px;line-height:1.2;color:var(--text);
  margin:38px 0 14px}

/* =====================================================================
   CTA  (bloktype 'cta')
   De oproep aan het eind van een pagina: kop, tekst, één knop en daaronder
   de social-icoontjes. Alles gecentreerd onder elkaar — geen raster, geen
   kader, geen eigen achtergrond. Een CTA is de laatste alinea van de
   pagina, geen tweede hero.

   Eén kolom in het midden i.p.v. de volle .wrap-breedte: gecentreerde tekst
   die 1400px breed loopt, leest niet — het oog vindt het begin van de
   volgende regel niet terug. De maxima hieronder staan daarom per onderdeel,
   niet op de doos: de kop mag breder dan de lopende tekst.
   ===================================================================== */
.cta-box{display:flex;flex-direction:column;align-items:center;text-align:center;
  gap:clamp(18px,2.6vw,28px)}
/* De kop is dezelfde .sec-title als elders (zelfde font, hoofdletters en
   clamp), alleen niet links uitgelijnd en niet paginabreed. `balance` verdeelt
   de regels gelijkmatig in plaats van een laatste regel van één woord. */
.cta-box .sec-title{max-width:22ch;text-wrap:balance}
/* Alinea's komen uit setTiBody(), dezelfde functie als bij Tekst + Afbeelding.
   Kleur, vet, links en lijstjes staan bij "RIJKE TEKST" hierboven; `.about-copy
   p` geldt hier niet, dus de maat zet dit blok zelf. */
.cta-body{max-width:58ch}
.cta-body p{font-size:clamp(16px,1.4vw,20px);text-wrap:pretty}
/* Gecentreerd ziet een opsomming met de bolletjes links er scheef uit; hier
   staan lijst én bolletje in het midden. */
.cta-body .rt-lijst,.cta-body .rt-nummers{list-style-position:inside;padding-left:0}
/* Iets meer lucht boven de icoonrij dan de gap geeft: knop en socials zijn
   twee aparte aansporingen, die horen niet als één blokje te lezen. */
.cta-socials{margin-top:clamp(4px,1.2vw,14px)}

/* =====================================================================
   USP'S  (bloktype 'usp')
   Een sectie die niets anders is dan de cijferrij, over de volle breedte.
   De cijfers delen hun HTML met het Tekst + Afbeelding-blok (.stat .n /
   .stat .l), maar krijgen hier een eigen uiterlijk. Alles hieronder staat
   daarom achter .usp-stats: dat is één stap specifieker dan `.stat .n`,
   dus het wint hier en laat het andere blok met rust.
   ===================================================================== */
/* Precies drie gelijke kolommen (geen auto-fit): alleen zo ligt het hart van
   de middelste kolom exact op het midden van de pagina. .wrap staat
   gecentreerd en de gaps zijn gelijk, dus het raster is symmetrisch.
   Let op: met vier USP's valt de vierde op een tweede rij, links. */
/* ---- Achtergrondfoto (optioneel, uit het CMS) -----------------
   Alleen aanwezig als er een foto gekozen is; `.has-usp-bg` komt van
   applyUspBg() in cms-render.js, samen met --usp-img en --usp-ov.

   Waarom een aparte laag met ::before en niet gewoon `filter:blur()` op de
   sectie: blur werkt op ALLES in het element, dus ook op de cijfers — die
   zouden onleesbaar worden. De foto zit daarom in een eigen laag eronder.

   En waarom `inset:-40px` op die laag: een blur sampelt buiten de randen van
   het element, waar niets staat. Zonder uitvergroting krijg je daardoor een
   vage, doorzichtige rand rondom. 40px dekt de 10px blur ruim af, en de
   `overflow:hidden` op .usp-bg zelf houdt die uitloop binnen de sectie — de
   sectie hoeft daar dus niets voor te doen. */
.usp-bg{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.usp-bg::before{content:"";position:absolute;inset:-40px;
  background:var(--usp-img) center/cover no-repeat;
  filter:blur(10px)}
.usp-bg::after{content:"";position:absolute;inset:0;
  background:#000;opacity:var(--usp-ov,.6)}
/* de cijfers moeten bóven de foto blijven */
.has-usp-bg .wrap{position:relative;z-index:1}
/* Op een foto verliest accentblauw het; wit houdt zich staande tegen elke
   ondergrond. Vier klassen diep, dus dit wint van de blauwe regels hieronder. */
.has-usp-bg .usp-stats .stat .n,
.has-usp-bg .usp-stats .stat .l{color:#fff}

.usp-stats{display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(20px,3vw,48px);margin-top:0}
.usp-stats .stat{text-align:center}
/* Inter, niet Oswald: in dit blok wordt bewust één lettertype gebruikt.
   letter-spacing terug naar 0 — de waarde op .stat .l was voor een label van
   11px bedoeld en wordt op 30px een gatenkaas. */
.usp-stats .stat .n{font-family:var(--font-text);font-size:90px;
  font-weight:600;letter-spacing:0;line-height:1.05}
/* Ook de tekst onder het cijfer in accentblauw (2026-09-16, op verzoek) — in
   dit blok horen cijfer en label bij elkaar als één uitspraak. Overschrijft de
   var(--muted) van de gedeelde `.stat .l`; dat is één klasse dieper, dus het
   wint zonder trucs. */
.usp-stats .stat .l{font-family:var(--font-text);font-size:30px;
  letter-spacing:.01em;margin-top:12px;line-height:1.25;color:var(--accent)}
/* Onder de 900px past een cijfer van 90px niet meer in een derde van het
   scherm; daar stapt hij omlaag in plaats van uit zijn kolom te lopen. */
@media(max-width:900px){
  .usp-stats .stat .n{font-size:64px}
  .usp-stats .stat .l{font-size:22px}
}
@media(max-width:560px){
  .usp-stats{grid-template-columns:1fr;gap:26px}
  .usp-stats .stat .n{font-size:56px}
  .usp-stats .stat .l{font-size:20px}
}

/* =====================================================================
   BOOKING / CONTACT
   ===================================================================== */
/* Twee kolommen: links de kop met de redenen om te boeken, rechts het
   formulier in een vlak. Zie contactSectionHtml() in cms-render.js voor wat
   er waar staat. */
.book-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(30px,5vw,80px)}
@media(max-width:880px){.book-grid{grid-template-columns:1fr}}
/* Dit was `.book-left h2` — een TAG-selector. Sinds 2026-09-20 kan de titel van
   het Contact-blok via "Kopniveau" ook een h1 zijn, en dan greep die selector
   mis: de kop verloor in één klap Oswald, de hoofdletters en zijn maat. Nu
   staat de opmaak op de KLASSE en overschrijft `h2.ct-title` alleen de maat —
   precies hetzelfde patroon als .sec-title en .ti-title. De basismaat is
   daarmee de h1-maat, gelijk aan die twee. */
/* WAAROM cqi EN GEEN vw (2026-10-09, op verzoek: "zou die niet mee moeten
   schalen met wat mogelijk is qua ruimte? Zodat hij dus niet afbreekt").
   Deze kop staat in een HALVE kolom, maar rekende met `8vw` — de breedte van
   het hele scherm. Op een breed scherm werd hij daardoor breder dan zijn eigen
   kolom en viel "2BU$Y BOEKEN" op twee regels. `cqi` is 1% van de breedte van
   de container, en `.book-left` is sinds vandaag zelf die container; 13cqi is
   dus 13% van de kolom, wat er ook naast staat. De verhouding h1 : h2 blijft
   0,68 (8,84 = 0,68 × 13), net als bij .sec-title.
   ⚠️ `container-type` op .book-left is geen vormgeving maar de ankerpunt van
   die rekensom — haal je die weg, dan valt cqi terug op de schermbreedte en
   is de kop ineens groter dan de kolom. */
.book-left{container-type:inline-size}
.ct-title{font-family:var(--font-display);text-transform:uppercase;font-weight:600;
  letter-spacing:.01em;
  font-size:clamp(52px,13cqi,96px);line-height:.88;margin-bottom:30px}
/* zelfde verhouding als h2.sec-title — zie de uitleg daar (4/7 × de h1-maat,
   7,43 = 13 × 4/7; grenzen 36–56px) */
h2.ct-title{font-size:clamp(36px,7.43cqi,56px)}

/* ── de redenen om te boeken (2026-10-09, op verzoek) ──
   Per regel een blauw vinkje in een donkerblauw rondje, met de tekst ernaast.
   Het rondje is de accentkleur op 16%: op deze donkere achtergrond is dat
   donkerblauw, en het blijft meeveranderen als --accent ooit wijzigt.
   `align-items:flex-start` zodat het rondje bij een regel van twee regels
   bovenaan blijft staan en niet in het midden gaat zweven. */
.ct-usps{list-style:none;display:flex;flex-direction:column;
  gap:14px;margin-top:34px}
.ct-usps li{display:flex;align-items:flex-start;gap:14px;
  font-size:17px;line-height:1.5;color:var(--text-soft)}
.ct-usps strong{color:var(--text)}
.ct-vink{flex:0 0 auto;width:26px;height:26px;border-radius:50%;
  display:grid;place-items:center;margin-top:1px;
  background:color-mix(in srgb,var(--accent) 16%,transparent);
  color:var(--accent)}
.ct-vink svg{width:15px;height:15px;display:block}

/* ── het vlak om het formulier (2026-10-09, op verzoek) ──
   Zelfde achtergrond als de footer (--bg-2) met een lichte, doorzichtige
   rand. Het formulier wordt hierdoor smaller; dat is de bedoeling — de knop
   mag daardoor over de volle breedte. */
.ct-paneel{display:flex;flex-direction:column;gap:20px;
  background:var(--bg-2);border:1px solid var(--line);border-radius:14px;
  padding:clamp(24px,2.6vw,40px)}
/* De titel van het formulier: het eerste veld van het formulier zelf, type
   "kop". Als kopje in een formulier is 13px mono genoeg, maar bovenaan dit
   vlak is het de titel — vandaar Oswald. Alleen de EERSTE: een tussenkop
   verder in het formulier blijft een tussenkop. */
.ct-paneel .form-kop:first-child{padding-top:0}
.ct-paneel .form-kop:first-child h3{font-family:var(--font-display);
  font-size:clamp(21px,2vw,27px);font-weight:600;letter-spacing:.01em;
  color:var(--text)}
/* De verstuurknop over de volle breedte van het vlak, zonder het rondje dat
   de knoppen elders wél hebben (op verzoek: "geen pijltjes of rondje erin").
   Het rondje is een <span class="dot"> uit mountForm(); hier verbergen we hem
   in plaats van hem uit die functie te halen, want elders hoort hij er wel. */
.ct-paneel .form .submit{justify-self:stretch;width:100%}
.ct-paneel .form .submit .dot{display:none}

/* ── onder de knop ──
   Gecentreerd op verzoek (2026-10-09). Het e-mailadres eronder gaat mee: dat
   is dezelfde mededeling in twee regels ("liever direct contact?" → het
   adres), en één van de twee links laten staan zou scheef lezen onder een
   knop die het hele vlak vult. `align-items:center` hoort erbij: de regels
   zijn flex-kinderen, dus `text-align` alleen zou de tekst in een linkse
   kolom centreren. */
.ct-na{display:flex;flex-direction:column;align-items:center;gap:14px;
  text-align:center}
.ct-na-tekst{font-size:15px;line-height:1.6;color:var(--muted)}
.book-contacts{display:flex;flex-direction:column;gap:12px}
.book-contacts .item .k{font-family:var(--font-mono);font-size:11px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);margin-bottom:4px}
/* Stond tot 2026-10-09 in de linker kolom en was daar clamp(18px,1.8vw,24px).
   Onder de knop in het vlak is dat te groot: het adres zou harder roepen dan
   de knop erboven. */
.book-contacts .item .v{font-size:16px;font-weight:600}
.book-contacts .item a:hover{color:var(--accent)}

.form{display:flex;flex-direction:column;gap:32px}
/* Zes kolommen: een heel veld pakt er zes, een half drie en een derde twee.
   Vóór 2026-09-25 plakte de JS zelf twee korte velden in een .form-row; nu
   staat de breedte per veld in het CMS en doet het raster de rest. Onder de
   560px gaat alles over de volle breedte — twee kolommen is daar te krap. */
.form-fields{display:grid;grid-template-columns:repeat(6,1fr);gap:32px 20px;align-items:start}
.form-fields > *{grid-column:span 6}
.form-fields > .b-half{grid-column:span 3}
.form-fields > .b-derde{grid-column:span 2}
@media(max-width:560px){.form-fields > *{grid-column:span 6}}
.field{display:flex;flex-direction:column;gap:8px}
/* > label en niet `label`: een keuzerondje heeft zijn eigen label binnenin,
   en dat moet géén klein hoofdletter-kopje worden. */
.field > label{font-family:var(--font-mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted)}
.field input,.field select,.field textarea{
  background:transparent;border:1px solid var(--line-strong);
  color:var(--text);font-family:var(--font-text);font-size:17px;padding:12px 14px;
  outline:none;transition:border-color .3s;border-radius:8px}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--accent)}
.field select option{background:var(--bg);color:var(--text)}
.field textarea{resize:vertical;min-height:90px}
.field.err input,.field.err select,.field.err textarea{border-color:#ff4d4d}
.field .msg{font-family:var(--font-mono);font-size:11px;color:#ff6b6b;display:none}
.field.err .msg{display:block}
.field .hint{font-size:14px;color:var(--muted);line-height:1.5}

/* ── keuzevelden: rondjes, vinkjes en het akkoordvinkje ── */
.keuzes{display:flex;flex-wrap:wrap;gap:10px 22px;padding-top:4px}
.keuze{display:inline-flex;align-items:center;gap:10px;cursor:pointer;
  font-size:17px;line-height:1.4}
.keuze input{flex:0 0 auto;width:19px;height:19px;padding:0;accent-color:var(--accent);
  cursor:pointer}
.keuze input[type=radio]{border-radius:50%}
.field.err .keuze input{outline:1px solid #ff4d4d;outline-offset:2px}
.veld-akkoord .keuze{align-items:flex-start}
.veld-akkoord .keuze input{margin-top:2px}
.veld-akkoord a{text-decoration:underline;text-underline-offset:3px}
.veld-akkoord a:hover{color:var(--accent)}

/* ── opmaakvelden: een tussenkop en een blokje uitleg ── */
.form-kop{padding-top:8px}
.form-kop h3{font-family:var(--font-mono);font-size:13px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--text)}
.form-kop p{font-size:15px;color:var(--muted);margin-top:8px;line-height:1.6}
.form-uitleg{font-size:16px;color:var(--muted);line-height:1.7}
.form-uitleg a{text-decoration:underline;text-underline-offset:3px}

/* Het lokvakje tegen bots: buiten beeld in plaats van display:none, want een
   slimmere bot slaat verborgen velden over. Zie mountForm in cms-render.js. */
.form-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
/* Een veld dat door een voorwaarde (nog) niet getoond wordt. Hier wél
   display:none: dit gaat over de indeling, niet over bots. */
.form-fields > .is-verborgen{display:none}
.form .submit{justify-self:start;margin-top:8px}
.form-success{padding:30px;border:1px solid var(--accent);border-radius:10px;
  font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.1em;
  display:none}
/* Weigert de server de inzending, dan komt de reden hier te staan — beter dan
   "Bedankt" tonen terwijl er niets is opgeslagen. */
.form-error{padding:16px 18px;border:1px solid #ff4d4d;border-radius:10px;
  font-family:var(--font-mono);font-size:13px;color:#ff6b6b;line-height:1.5}
.form.sent .form-fields{display:none}
.form.sent .form-success{display:block}
/* Het losse Formulier-blok: één kolom, niet schermbreed uitgerekt. */
.fm-kolom{max-width:760px}

/* =====================================================================
   VEELGESTELDE VRAGEN (2026-10-09, op verzoek)
   Links de kop, rechts de vragen als uitklappers. Zelfde kolomverdeling en
   hetzelfde omslagpunt als het Contact-blok erboven — ze staan op /boeken
   onder elkaar en moeten dus op één lijn liggen.

   Het open- en dichtklappen doet de browser: dit zijn echte
   `<details>`/`<summary>`-elementen, geen knoppen met JavaScript. Hier staat
   dus alleen hoe ze eruitzien, inclusief het plusje dat een minnetje wordt.
   ===================================================================== */
/* Een derde voor de kop, twee derde voor de vragen (2026-10-09, op verzoek:
   *"de veelgestelde vragen drop downs ook 2/3 deel van de pagina laten
   opnemen en de h1/h2 1/3 van de pagina"*). Het omslagpunt blijft 880px,
   gelijk aan `.book-grid` erboven — de kolomverdeling wijkt dus bewust af van
   dat blok, het omslagpunt niet. */
.faq-grid{display:grid;grid-template-columns:1fr 2fr;
  gap:clamp(30px,5vw,80px);align-items:start}
@media(max-width:880px){.faq-grid{grid-template-columns:1fr}}
/* In een kolom van een derde past de h2-maat van een sectiekop niet meer:
   `.sec-title` heeft `overflow-wrap:anywhere`, dus "VEELGESTELDE" zou
   MIDDEN IN HET WOORD afbreken. Daarom hier dezelfde aanpak als bij
   `.ct-title`: `.faq-kop` is zelf de container en de maat rekent met `cqi`,
   een percentage van die kolom. De verhouding h1 : h2 blijft 0,68
   (16 = 0,68 × 23,5), net als bij elke andere kop.
   ⚠️ De h1-maat is en blijft te groot voor een derde kolom — die wrapt. Dat
   is geen fout maar de aard van die maat; dit blok staat daarom op h2, en op
   /boeken is de h1 al de kop van het Contact-blok. */
.faq-kop{container-type:inline-size}
/* 2026-10-19: verhouding 4/7 (11,77 = 20,6 × 4/7), plafonds 96/56px zoals
   elke andere kop; de lagere ondergrenzen blijven, die zijn voor een derde kolom */
.faq-kop .sec-title{font-size:clamp(40px,20.6cqi,96px)}
.faq-kop h2.sec-title{font-size:clamp(32px,11.77cqi,56px)}
/* `.sec-intro` is gemaakt voor de plek rechts naast een sectiekop en staat
   daarom rechts uitgelijnd; in deze kolom leest dat als een fout. */
.faq-kop .sec-intro{text-align:left;max-width:34ch;margin-top:22px}
.faq-lijst{display:flex;flex-direction:column}
/* Lijnen tussen de vragen, en één onder de laatste — geen rand om elke vraag:
   dat zou een rij losse kaartjes worden naast een kop die al groot is. */
.faq-item{border-top:1px solid var(--line)}
.faq-item:last-child{border-bottom:1px solid var(--line)}
/* Inter en niet Oswald, op verzoek (2026-10-09). Oswald is wat je ZIET (grote
   koppen); dit is wat je LEEST — een vraag is een regel tekst, niet een kop.
   Het antwoord stond al in Inter (dat is de standaard van `body`), dus
   hiermee staan vraag en antwoord in hetzelfde lettertype. 600 is de dikte
   die Inter in dit project overal voor nadruk gebruikt, en de letterafstand
   van Oswald (.01em) hoort er dan niet meer bij. */
.faq-item summary{display:flex;align-items:center;justify-content:space-between;
  gap:20px;padding:22px 2px;cursor:pointer;
  font-family:var(--font-text);font-size:clamp(17px,1.5vw,20px);
  font-weight:600;line-height:1.4;color:var(--text);
  transition:color .25s ease;
  /* het standaard driehoekje weg: het plusje rechts is de aanwijzing */
  list-style:none}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary:hover{color:var(--accent)}
.faq-item[open] summary{color:var(--accent)}
/* Het plusje: twee streepjes op elkaar. Open valt het rechtopstaande streepje
   weg, en dan is het een minnetje. Geen tekstteken (+ en − verschillen per
   lettertype in breedte en hoogte) en geen tweede svg. */
.faq-teken{position:relative;flex:0 0 auto;width:18px;height:18px;
  color:var(--accent)}
.faq-teken::before,.faq-teken::after{content:'';position:absolute;
  background:currentColor;border-radius:2px}
.faq-teken::before{top:50%;left:0;right:0;height:2px;margin-top:-1px}
.faq-teken::after{left:50%;top:0;bottom:0;width:2px;margin-left:-1px;
  transition:transform .25s ease}
.faq-item[open] .faq-teken::after{transform:scaleY(0)}
/* `.ti-body` staat er al op voor de alinea-opmaak; hier alleen de ruimte. */
.faq-antwoord{padding:0 2px 24px;max-width:60ch}

/* =====================================================================
   PLAYER BAR
   ===================================================================== */
.player{position:fixed;left:0;right:0;bottom:0;z-index:6000;
  transform:translateY(120%);transition:transform .55s cubic-bezier(.16,1,.3,1);
  background:#000;border-top:1px solid var(--line)}
.player.up{transform:none}

/* Ruimte onder de footer zodra de speler in beeld is (2026-09-17, op verzoek).
   De balk staat `position:fixed` over de pagina heen en dekte de onderste
   regel van de footer af — precies waar de juridische links staan. Die waren
   daardoor niet aan te klikken, op desktop én op mobiel.

   De footer krijgt er onderaan net zoveel ruimte bij als de balk hoog is. Dat
   maakt het hele document hoger, dus alles wat eronder verdween is weer weg te
   scrollen — niet alleen de footer.

   --player-h wordt gemeten in main.js en niet hier vastgelegd: op mobiel is de
   balk fors hoger dan op desktop (daar staat de seekbar op een tweede regel),
   en hij groeit mee met de tekstgrootte. De waarde achter de komma is de
   terugval als dat script niet draait — ruim genomen, want te veel ruimte valt
   niet op en te weinig betekent dat je er weer niet bij kunt.

   Waarom `:has()`: de klasse `.up` staat op .player zélf, en die komt ná de
   footer in de HTML. Een gewone combinator kan niet terug in het document.
   Kent een browser `:has()` niet, dan wordt deze regel genegeerd en is het
   precies zoals het hiervoor was. */
body:has(.player.up) .footer{padding-bottom:var(--player-h,120px)}
.player-inner{width:min(1400px,92vw);margin-inline:auto;
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr) minmax(0,1fr);
  gap:clamp(16px,3vw,44px);align-items:center;padding:12px 0}

/* LINKS — cover + titel/artiest */
.pl-left{display:flex;align-items:center;gap:14px;min-width:0}
.pl-cover{width:52px;height:52px;border-radius:6px;flex:none;overflow:hidden;
  background:linear-gradient(135deg,var(--line-strong),var(--bg-2));
  box-shadow:0 2px 10px rgba(0,0,0,.35)}
.pl-cover-img{width:100%;height:100%;object-fit:cover;display:none}
.pl-cover-img[src]{display:block}
/* `flex:1` is hier geen opmaak maar de voorwaarde voor de fade hieronder.
   Zonder groei is dit vak precies zo breed als de langste van de twee regels,
   en dan raakt die regel áltijd de rechterrand — dus faadde elke titel, ook
   een korte. Met `flex:1` vult het vak de ruimte die er is, eindigt korte
   tekst ruim vóór het verloop en faadt alleen wat echt niet past.
   De tekst staat links, dus zichtbaar verandert er verder niets. */
.player .meta{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}
/* Te lange titels en artiestennamen faden uit aan de rechterkant in plaats van
   af te breken met "…" (2026-09-17, op verzoek).

   Het masker werkt op de DOOS en niet op de tekst: past de titel gewoon, dan
   eindigt hij vóór de laatste 28px en is er niets te faden. Loopt hij door,
   dan loopt hij het masker in en lost hij op. Er is dus geen meting of
   JavaScript nodig om te weten of er afgekapt moet worden.

   DAT WERKT ALLEEN als .player .meta kan groeien — zie de `flex:1` hierboven.
   Zonder die regel is het vak zo breed als de langste regel en faadt élke
   titel, ook een korte. Haal `flex:1` dus niet weg.

   `text-overflow` staat daarom weer op de standaard (clip): met ellipsis zou
   je én drie puntjes én een fade krijgen. `-webkit-mask-image` moet erbij voor
   Safari. Geldt ook op desktop — twee verschillende manieren van afkappen in
   dezelfde balk is niet uit te leggen. */
.player .meta .t,
.player .meta .s{white-space:nowrap;overflow:hidden;
  -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent);
          mask-image:linear-gradient(to right,#000 calc(100% - 28px),transparent)}
.player .meta .t{font-weight:600;font-size:15px}
.player .meta .s{font-family:var(--font-mono);font-size:11px;color:var(--muted);
  letter-spacing:.06em}

/* MIDDEN — play-knop boven de seekbar */
.pl-center{display:flex;flex-direction:column;align-items:center;gap:8px;
  min-width:0;width:100%}
.player .pp{width:38px;height:38px;border-radius:50%;border:0;background:#fff;
  color:#000;display:grid;place-items:center;font-size:14px;flex:none;cursor:pointer;
  transition:transform .15s ease}
.player .pp:hover{transform:scale(1.06)}
/* Iconen als SVG i.p.v. de tekstglyphs ► en ❚❚ — die waren per platform een
   ander formaat en stonden scheef in de ronde knop. */
.player .pp svg{width:15px;height:15px;display:block}
.player .pp .i-play{margin-left:2px}   /* driehoek oogt anders links-zwaar */
.pl-seek{display:flex;align-items:center;gap:10px;width:100%}
.seek-bar{flex:1;height:4px;background:var(--line);border-radius:2px;cursor:pointer;
  position:relative;transition:height .15s ease;min-width:0}
.seek-bar:hover,.seek-bar.dragging{height:6px}
.seek-played{position:absolute;inset:0 auto 0 0;background:var(--accent);
  border-radius:2px;width:0;pointer-events:none}
.seek-played::after{content:"";position:absolute;right:-6px;top:50%;
  width:12px;height:12px;border-radius:50%;background:#fff;
  transform:translateY(-50%) scale(0);transition:transform .15s ease}
.seek-bar:hover .seek-played::after,
.seek-bar.dragging .seek-played::after{transform:translateY(-50%) scale(1)}
.player .time-cur,.player .time-dur{font-family:var(--font-mono);font-size:11px;
  color:var(--muted);letter-spacing:.06em;flex:none;min-width:38px}
.player .time-cur{text-align:right}
.player .time-dur{text-align:left}

/* RECHTS — volumeregelaar */
.pl-right{display:flex;align-items:center;gap:10px;justify-content:flex-end;min-width:0}
.pl-vol-ico{display:grid;place-items:center;background:none;border:0;padding:0;flex:none;
  color:var(--muted);cursor:pointer;line-height:0;transition:color .2s}
.pl-vol-ico:hover{color:#fff}
.pl-vol-ico svg{width:18px;height:18px;display:block}
.pl-vol-slider{-webkit-appearance:none;appearance:none;height:4px;border-radius:2px;
  width:clamp(72px,8vw,120px);flex:none;cursor:pointer;
  background:linear-gradient(to right,var(--accent) 100%,var(--line) 100%)}
.pl-vol-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
  width:12px;height:12px;border-radius:50%;background:#fff;cursor:pointer;
  border:0;box-shadow:0 1px 4px rgba(0,0,0,.4)}
.pl-vol-slider::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:50%;
  background:#fff;cursor:pointer;box-shadow:0 1px 4px rgba(0,0,0,.4)}
/* ── Spotify: verborgen embed achter de eigen speler ──
   Zelfde truc als de SoundCloud-widget: het iframe draait buiten beeld en de
   eigen balk bedient het (play/pauze/spoelen via de iFrame API, zie SP_PLAY in
   cms-render.js). Het element hangt in <body>, niet in de balk — .player heeft
   een transform, en die zou een fixed kind meeslepen.

   LET OP: dit is een bewuste keuze van de eigenaar. Spotify's voorwaarden
   vragen dat hun speler zichtbaar blijft. Wil je dat terugdraaien, zet dit
   element dan weer in .player-inner met grid-column:2 en haal de verberging
   hieronder weg — de besturing blijft dan gewoon werken. */
.pl-spotify{position:fixed;top:-2px;left:-2px;width:1px;height:1px;
  overflow:hidden;opacity:0;pointer-events:none;z-index:-1}
.pl-spotify iframe{width:300px;height:80px;border:0}
/* Volume: Spotify's iFrame API biedt er geen ingang voor (SoundCloud wel, via
   setVolume). SP_PLAY controleert dat bij elk nummer en zet .no-vol als het
   niet kan — een schuif die niets doet is erger dan geen schuif. Blijkt de
   methode er ooit wél te zijn, dan komt de schuif vanzelf terug. */
.player.no-vol .pl-right{display:none}

@media(max-width:760px){
  /* Twee regels: bovenin cover + titel/artiest met de speelknop rechts ernaast,
     daaronder de seekbar over de volle breedte.

     De knop en de seekbar zitten samen in .pl-center, en die wikkel stond de
     knop in de weg — hij kon niet los naar rechts. `display:contents` laat die
     wikkel als doos verdwijnen, waardoor .pp en .pl-seek zélf items van dit
     raster worden en ieder hun eigen plek kunnen krijgen. LET OP: padding,
     achtergrond en `order` op .pl-center doen daardoor niets meer op mobiel;
     wil je daar iets mee, doe het dan op de twee kinderen. */
  .player-inner{grid-template-columns:minmax(0,1fr) auto;gap:0 12px;
    align-items:center}
  .pl-left{grid-column:1;grid-row:1;min-width:0}
  .pl-center{display:contents}
  .player .pp{grid-column:2;grid-row:1}
  .pl-seek{grid-column:1 / -1;grid-row:2;margin-top:10px}
  .pl-right{display:none}
}

/* =====================================================================
   FOOTER
   ===================================================================== */
/* `overflow:hidden` stond hier voor .foot-mega: dat outline-logo was
   `white-space:nowrap` op maximaal 196px en liep bij een lange merknaam de
   pagina uit. Dat element bestaat niet meer, dus de rem ook niet. */
.footer{padding-top:clamp(70px,9vh,130px);background:var(--bg-2);
  border-top:1px solid var(--line)}
/* Bovenste helft: DRIE KOLOMMEN (2026-10-09, op verzoek).
   Links het logo met daaronder "Volg mij op" + de social-icoontjes, dan "Menu"
   met alle links van de site, dan "Contact" met het mailadres, de blauwe knop
   "Boek 2BU$Y" en de presskit-knop.

   Eerdere versies op deze plek — niet opnieuw voorstellen zonder dat erom
   gevraagd wordt: (1) twee kolommen met links de socials als vijf enorme
   tekstlinks (Oswald, tot 64px, met een uitschuivend pijltje) en rechts
   `.foot-mega`, de merknaam als doorzichtig outline-logo tot 196px — inclusief
   brandMarkup() in server.js die de $-tekens daarin blauw maakte; (2) het
   logo gecentreerd met de socials eronder; (3) alleen het logo, gecentreerd.

   KOLOMBREEDTES (2026-10-09, derde ronde — op verzoek)
   `auto auto 1fr`, en niet drie keer `fr`. De twee tekstkolommen (Menu en
   Contact) zijn precies zo breed als hun inhoud en staan daarmee als paar
   tegen de LINKERRAND; de `1fr` erachter slokt alle vrije ruimte op, en
   `.foot-merk` (logo + socials) wordt daarin met `justify-self:end` tegen de
   RECHTERRAND gezet — op één lijn met de juridische links in de onderregel.
   Dat was de vraag: *"het logo en de social icons rechts zetten en dan menu
   helemaal links en dan naast menu komt contact"*.

   ⚠️ Twee eerdere versies — niet opnieuw voorstellen zonder dat erom gevraagd
   wordt: `minmax(0,1.3fr) minmax(0,1fr) minmax(0,1fr)` (logo links, maar dan
   begint het menu halverwege het scherm) en `auto minmax(0,1fr) auto` (logo
   links, Contact rechts). Drie `fr`-kolommen kunnen hier helemaal niet: dan
   staat niets meer op een rand en breekt een lange link af.

   `align-items:start` houdt de kopjes "Menu" en "Contact" op één lijn —
   zonder dat zou de langste kolom de andere uitrekken. `.foot-merk` is de
   uitzondering, zie daar. */
.foot-top{display:grid;align-items:start;
  grid-template-columns:repeat(var(--foot-n,2),auto) minmax(0,1fr);
  gap:clamp(34px,5vh,54px) clamp(28px,5vw,80px)}
/* Drie linkkolommen + logoblok passen pas vanaf ±1000px naast elkaar;
   daaronder gaat het logoblok op een eigen regel onder de kolommen. */
@media(min-width:761px) and (max-width:1000px){
  .foot-top{grid-template-columns:repeat(var(--foot-n,2),auto)}
  .foot-merk{grid-column:1/-1}
}
/* Telefoon en kleine tablet: alles onder elkaar, en dan ook het logoblok
   gewoon links. Drie kolommen vragen samen ±530px plus twee tussenruimtes;
   onder deze breedte is dat niet meer te doen zonder dat een lange link
   ("info@2busyofficial.nl", "Privacyverklaring") gaat afbreken.
   In één kolom komt het logo onderaan te staan, net boven de onderregel —
   dat volgt uit de leesvolgorde in de HTML en is bewust niet met `order`
   omgedraaid. */
@media(max-width:760px){
  /* Linkkolommen twee aan twee (2026-10-20, op verzoek); logoblok eronder over de volle breedte.
     Het mailadres is te breed voor een halve telefoon: server.js zet er een <wbr> na de @. */
  .foot-top{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:20px}
  .foot-merk{grid-column:1/-1}
}
/* ── Kolom 1: logo + "Volg mij op" + de icoontjes ──
   Het logo moet precies zo breed zijn als de rij icoontjes eronder. Die
   breedte staat hier UITGEREKEND: n rondjes + (n−1) tussenruimtes. `--soc-n`
   is het aantal ingevulde platforms en komt als inline stijl uit footerHtml()
   mee, dus het volgt Instellingen → Social links. De maat van een rondje en
   de tussenruimte staan hier als variabele en worden hieronder door de
   icoontjes zelf gebruikt — één bron, dus de twee kunnen niet uit de pas lopen.

   ⚠️ Dit stond eerst als `width:fit-content`, met de gedachte dat de kolom dan
   tot zijn breedste kind (de icoonrij) zou krimpen. Dat werkt níet: voor zo'n
   intrinsieke maat telt een `<img width:100%>` mee met de breedte van het
   BESTAND (2000px), dus de kolom werd zo breed als de pagina en het logo
   daarmee veel breder dan de icoontjes. Koraa zag het meteen. Niet opnieuw
   proberen — ook niet als `max-content` of `min-content`.

   `align-self:stretch` + `margin-top:auto` op `.foot-volg` duwen de icoontjes
   naar de ONDERKANT van de rij, zodat ze op één lijn staan met de onderste
   menulink. Dat werkt zolang de menukolom de hoogste van de drie is — met vijf
   menu-items tegen (kopje + mailadres + twee knoppen) is dat zo, met ruimte
   over. ⚠️ Haalt iemand drie menu-items weg, kijk dit dan na;
   `tools/check-footer.js` rekent het na.

   `justify-self:end` zet dit blok tegen de rechterrand van de footer. De
   INHOUD blijft links uitgelijnd: het kopje begint boven het eerste rondje,
   net zoals "Menu" en "Contact" boven hun eerste regel beginnen. Het blok is
   even breed als de icoonrij, dus de rechterkant valt vanzelf samen met de
   rand — er is geen `text-align:right` nodig en die zou de drie kopjes juist
   uit elkaar laten lopen. */
.foot-merk{--soc-maat:44px;--soc-gap:12px;
  display:flex;flex-direction:column;align-items:flex-start;
  width:calc(var(--soc-n,5) * var(--soc-maat)
             + (var(--soc-n,5) - 1) * var(--soc-gap));
  max-width:100%;align-self:stretch;justify-self:end;
  gap:clamp(20px,3vh,30px)}
.foot-logo{display:block;width:100%;transition:opacity .3s}
.foot-logo:hover{opacity:.7}
/* Breedte stuurt hier, hoogte volgt — andersom dan bij .nav-logo, want deze
   moet de icoonrij precies volgen. `height:auto` houdt de verhouding van het
   bestand (2000 × 482); `aspect-ratio` zou een tweede plek zijn waar die
   verhouding staat. */
.foot-logo img{display:block;width:100%;height:auto;object-fit:contain}
/* "Volg mij op" + de icoontjes als één groep, zodat het kopje meeschuift als
   de groep naar de onderkant van de kolom wordt geduwd. Dezelfde afstand
   kopje → inhoud als in de andere twee kolommen (13px gap + 4px onder het
   kopje). */
.foot-volg{display:flex;flex-direction:column;gap:13px;margin-top:auto}
/* Socials: rondje met een WITTE RAND en het icoon erin (2026-10-09, op
   verzoek) — niet de gevulde blauwe knop van het CTA-blok hieronder. Hover
   keert om: het rondje vult zich wit en het icoon wordt donker, precies wat
   de secundaire .btn doet.
   `flex-wrap` omdat er vijf platforms zijn en deze kolom op een telefoon
   smaller kan zijn dan vijf rondjes naast elkaar. Zelfde grid-truc als bij
   .cta-socials hieronder: `place-items:center` centreert de svg in één
   declaratie in beide richtingen. */
.foot-socials{display:flex;flex-wrap:wrap;gap:var(--soc-gap,12px)}
.foot-socials a{width:var(--soc-maat,44px);height:var(--soc-maat,44px);border-radius:999px;
  display:grid;place-items:center;
  border:1px solid rgba(255,255,255,.55);color:#fff;
  transition:background .25s ease,color .25s ease,border-color .25s ease,transform .25s ease}
.foot-socials a:hover{background:#fff;color:var(--bg);border-color:#fff;
  transform:translateY(-3px)}
.foot-socials svg{width:20px;height:20px}
/* ⚠️ Moet NA de basisregel van .foot-merk staan (die zet justify-self:end): bij
   gelijke specificiteit wint wat later in het bestand staat. Stond eerder bij
   .foot-top hierboven en deed daardoor niets. */
@media(min-width:761px) and (max-width:1000px){ .foot-merk{justify-self:start} }
/* Telefoon: logo + "Volg mij op" + icoontjes horizontaal gecentreerd (2026-10-20, op verzoek). */
@media(max-width:760px){
  .foot-merk{justify-self:center}
  .foot-volg{align-items:center}
  .foot-socials{justify-content:center}
}
/* Kopjes boven de kolommen. Oswald in hoofdletters met ruime letterafstand —
   zelfde toon als .foot-bottom, zodat de footer één geheel blijft en de
   kopjes niet met de sectiekoppen van de pagina concurreren. */
.foot-kop{font-family:var(--font-display);font-size:13px;font-weight:600;
  text-transform:uppercase;letter-spacing:.16em;color:var(--muted);
  margin:0 0 4px}
.foot-kolom{display:flex;flex-direction:column;align-items:flex-start;gap:13px}
/* `:not(.btn)` staat er als vangnet: sinds 2026-10-09 staat er geen knop meer
   in deze kolommen (de twee bij Contact zijn op verzoek gewone links
   geworden), maar komt er ooit een terug, dan houdt hij zo zijn eigen kleur en
   hover van .btn in plaats van die van een tekstlink. */
.foot-kolom a:not(.btn){color:var(--text-soft);font-size:15px;
  transition:color .25s ease}
.foot-kolom a:not(.btn):hover{color:var(--accent)}
/* Het mailadres is de kern van deze kolom, dus wit en halfvet in plaats van
   de rustige linkkleur. Twee klassen = wint van de regel hierboven, ongeacht
   de volgorde in dit bestand. */
.foot-kolom .foot-mail{color:var(--text);font-weight:600}
.foot-kolom .foot-mail:hover{color:var(--accent)}
/* ── De Contact-kolom had twee KNOPPEN; die bestaan niet meer ──
   Op 2026-10-09 zijn ze op verzoek gewone tekstlinks geworden: "de knoppen bij
   contact worden gewoon linkjes". Wat hier stond en waarom het weg is:
     .foot-contact{align-items:stretch}  — rekte de twee knoppen tot de
       kolombreedte. Die kolom staat nu niet meer rechts, en er is niets meer
       om even wijd te maken.
     .foot-mail + .btn{margin-top:7px}   — lucht tussen het mailadres en de
       knoppenrij. Drie gewone links op één afstand (de 13px gap van
       .foot-kolom) lezen als één lijstje; extra lucht ertussen zou suggereren
       dat het twee losse dingen zijn.
   De links hebben geen eigen opmaak nodig: `.foot-kolom a` hierboven doet
   alles. `.foot-presskit` bestaat sinds dezelfde dag ook niet meer: Kolom 2 is
   een vrije lijst in het CMS geworden, en dan is "de presskit" niet langer een
   vaste regel om aan te wijzen. De enige regel die zich nog onderscheidt is de
   MAILREGEL hierboven, en die kent de server aan zijn `mailto:` — niet aan een
   plek in de lijst. Er staat sindsdien geen enkele .btn in de footer.
   `.foot-boek` bestond ook, voor "Boek 2BU$Y" in deze kolom; die link is er
   op verzoek weer uit (hij stond al in de menukolom) en de klasse dus ook. */
/* Socials als ronde blauwe knoppen met een wit icoon. `place-items:center`
   op een grid centreert de svg in beide richtingen tegelijk; met flex zou je
   daar twee declaraties voor nodig hebben.

   Dit was `.foot-socials,.cta-socials`: die twee hadden dezelfde vorm en het
   CTA-blok kloonde zijn rij uit de footer. Sinds 2026-10-09 heeft de footer
   een EIGEN vorm (het rondje met de witte rand, hierboven) — deze blauwe knop
   is dus alleen nog van het CTA-blok.
   Het CTA-blok kloont zijn <a>'s uit het mobiele menu; die hebben zelf geen
   klasse, dus ze worden vanzelf de ronde blauwe knop van hieronder en niet het
   grijze menu-icoontje of het witte footer-rondje. */
.cta-socials{display:flex;flex-wrap:wrap;justify-content:center;gap:12px}
.cta-socials a{width:46px;height:46px;border-radius:999px;
  background:var(--accent);color:var(--accent-ink);
  display:grid;place-items:center;
  transition:background .25s,transform .25s}
.cta-socials a:hover{background:#2b7bff;transform:translateY(-3px)}
.cta-socials svg{width:21px;height:21px}
/* Onderregel: links de copyright, rechts de juridische links.
   Stond hier eerder als drie losse tekstjes (locatie · made by · copyright)
   die space-between uit elkaar trok. Sinds 2026-09-17 zijn het er twee, en
   dan doet space-between precies wat de naam belooft: het eerste blok tegen
   links, het tweede tegen rechts. */
.foot-bottom{display:flex;justify-content:space-between;align-items:center;
  flex-wrap:wrap;gap:12px 24px;
  padding:26px 0;font-family:var(--font-mono);font-size:11px;color:var(--muted);
  letter-spacing:.06em;text-transform:uppercase;border-top:1px solid var(--line);
  margin-top:clamp(40px,6vh,68px)}
/* "© 2026 2BUSY" is één waarde; die mag nooit over twee regels breken. */
.foot-cpr{white-space:nowrap}
.foot-legal{display:flex;flex-wrap:wrap;gap:8px 24px}
.foot-legal a{color:var(--muted);transition:color .25s}
.foot-legal a:hover{color:var(--accent)}
/* Op smalle schermen passen twee blokken niet naast elkaar. Ze wikkelen dan
   al vanzelf; dit zorgt alleen dat het tweede blok links begint in plaats van
   rechts te blijven plakken — anders staat de copyright links en de linkrij
   er rechts ónder, en dat leest als een fout. */
@media(max-width:640px){
  .foot-bottom{justify-content:flex-start}
}

/* Hier stonden twee dingen die allebei op verzoek zijn verwijderd:
   de blauwe scroll-progressbalk (element uit headerHtml() in server.js) en
   de ronde naar-boven-knop rechtsonder (2026-09-17) — element uit alle drie
   de shells, aansturing en klik-afhandeling uit motion.js. */

/* =====================================================================
   LOGO'S — eindeloze rij, rechts naar links (mountLogos in cms-render.js)
   ===================================================================== */
.logo-sec{overflow:hidden}
.logo-band{-webkit-mask-image:linear-gradient(90deg,transparent,#000 10%,#000 90%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 10%,#000 90%,transparent)}
.logo-track ul{display:flex;width:max-content;margin:0;padding:0;list-style:none;
  animation:logo-loop var(--logo-duur,50s) linear infinite}
/* elk logo een vierkant vlak, het logo past erin zonder vervorming */
.logo-track li{flex:none;width:300px;aspect-ratio:1;margin:0 48px;display:flex;align-items:center;justify-content:center}
/* 10px = zelfde als de andere vierkante beelden (.mu-card, .mf-cover) */
/* width/height 100% i.p.v. max-*: vult altijd het vlak, ook een klein bestand.
   Met max-* bleef een logo met srcset kleiner (de browser rekent 447px-bestand
   als "480w" om naar ~280px, op retina ~175px). */
.logo-track img{display:block;width:100%;height:100%;object-fit:contain;border-radius:10px}
.logo-band:hover ul{animation-play-state:paused}
@keyframes logo-loop{to{transform:translateX(-50%)}}
@media(max-width:699px){.logo-track li{width:130px;margin:0 24px}}

/* =====================================================================
   TIJDLIJN — per jaar een kaart in een schuifbare rij (mountTijdlijn)
   Native scroll-snap; JS zet alleen .is-nu en stuurt pijlen/jaartallen.
   De ::after-spatie laat ook de laatste kaart links uitlijnen.
   ===================================================================== */
.tl-nav{display:flex;gap:10px;margin-left:auto}
.tl-pijl{display:grid;place-items:center;width:46px;height:46px;padding:0;
  border-radius:50%;border:1px solid var(--line-strong);background:transparent;color:var(--text);
  cursor:pointer;transition:background .25s ease,opacity .25s ease,border-color .25s ease}
.tl-pijl svg{width:48%;height:48%;display:block}
.tl-pijl.is-volgende svg{transform:rotate(180deg)}
.tl-pijl:hover:not(:disabled){background:var(--accent);border-color:transparent}
.tl-pijl:disabled{opacity:.28;cursor:default}
.tl-rail{--tl-w:85%;--tl-gap:clamp(16px,2.4vw,40px);position:relative;
  display:flex;gap:var(--tl-gap);overflow-x:auto;scroll-snap-type:x mandatory;
  scroll-behavior:smooth;scrollbar-width:none}
.tl-rail::-webkit-scrollbar{display:none}
.tl-rail::after{content:"";flex:0 0 calc(100% - var(--tl-w) - var(--tl-gap))}
.tl-kaart{flex:0 0 var(--tl-w);min-height:clamp(340px,34vw,540px);scroll-snap-align:start;display:grid;grid-template-columns:1fr 1fr;
  border-radius:12px;overflow:hidden;background:var(--surface);border:1px solid var(--line);
  opacity:.3;cursor:pointer;transition:opacity .4s ease}
.tl-kaart.is-nu{opacity:1;cursor:auto}
.tl-foto{position:relative;min-height:100%}
.tl-foto :is(img,video){position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.tl-tekst{padding:clamp(28px,4vw,72px) clamp(24px,3.5vw,64px);align-self:center}
.tl-jaar{font-family:var(--font-display);font-weight:600;font-size:clamp(18px,1.6vw,24px);
  color:var(--accent);letter-spacing:.04em;margin:0 0 10px}
.tl-titel{font-family:var(--font-display);text-transform:uppercase;font-weight:600;
  font-size:clamp(28px,2.8vw,42px);line-height:.95;margin:0 0 20px;overflow-wrap:anywhere}
.tl-jaren{--tl-jgap:clamp(8px,1.2vw,18px);position:relative;display:flex;gap:var(--tl-jgap);margin-top:clamp(24px,3vw,44px);
  overflow-x:auto;scrollbar-width:none}
.tl-jaren::-webkit-scrollbar{display:none}
.tl-jaren button{flex:1 0 auto;min-width:72px;padding:0 0 12px;text-align:left;cursor:pointer;
  background:none;border:0;border-bottom:1px solid var(--line-strong);color:var(--muted);
  font-family:var(--font-display);font-weight:600;font-size:clamp(18px,1.8vw,28px);
  transition:color .25s ease,border-color .25s ease}
.tl-jaren button:hover{color:var(--text)}
.tl-jaren button[aria-current="true"]{color:var(--text)}
/* Automatisch doorschuiven: het lijntje onder het actieve jaar kleurt in --tl-duur
   van links naar rechts blauw; animationend (mountTijdlijn) springt naar het volgende
   jaar. Stil zolang de muis op de kaarten staat of het blok niet in beeld is.
   Reduced motion: geen animatie, dus ook geen doorschuiven — het lijntje is dan gewoon blauw. */
.tl-jaren button{position:relative}
.tl-jaren button::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;
  background:var(--accent);transform:scaleX(0);transform-origin:left}
.tl-jaren button[aria-current="true"]::after{animation:tl-vul var(--tl-duur,7s) linear forwards}
[data-block="tijdlijn"]:not(.is-zichtbaar) .tl-jaren button::after,
[data-block="tijdlijn"]:has(.tl-rail:hover) .tl-jaren button::after{animation-play-state:paused}
@keyframes tl-vul{to{transform:scaleX(1)}}
@media (prefers-reduced-motion: reduce){
  .tl-jaren button[aria-current="true"]::after{animation:none;transform:scaleX(1)}
}
@media(max-width:880px){
  .tl-rail{--tl-w:88%}
  /* Alle kaarten worden zo hoog als de langste (flex-rij). Zonder `auto 1fr`
     verdeelde het grid die extra hoogte over foto én tekst: foto's werden te
     lang en de tekst zakte weg. Nu houdt de foto zijn 3:2 en vangt de tekst de rest op. */
  .tl-kaart{grid-template-columns:1fr;grid-template-rows:auto 1fr;min-height:0}
  .tl-foto{aspect-ratio:3/2;min-height:0}
  .tl-tekst{align-self:start}
  /* Mobiel: zelf vegen, geen pijlen en niet vanzelf doorschuiven (lijntje staat dan vol). */
  .tl-nav{display:none}
  .tl-jaren button[aria-current="true"]::after{animation:none;transform:scaleX(1)}
  /* 3,5 jaartal in beeld: het halve zegt dat er meer is. mountTijdlijn schuift
     de rij mee zodat het actieve jaar links staat. */
  .tl-jaren{--tl-jgap:12px}
  .tl-jaren button{flex:0 0 calc((100% - 3 * var(--tl-jgap)) / 3.5);min-width:0}
}

@media (prefers-reduced-motion: reduce){
  *{animation-duration:.001ms!important;animation-iteration-count:1!important}
  .kin > span{transform:none!important;opacity:1!important}
  .fade-up{opacity:1!important;transform:none!important}
}

/* =====================================================================
   MOBILE MENU OVERLAY
   ===================================================================== */
/* overflow-y:auto + ruime padding: met zes menu-items van max 90px én de
   socials past het niet meer op een laag scherm (telefoon in landschap),
   en body heeft dan .no-scroll — zonder dit was dat niet te bereiken. */
/* Twee rijen (2026-09-17, op verzoek): de links gecentreerd in de vrije
   ruimte, de socials tegen de onderkant. Was één rij met `place-items:center`,
   waardoor alles als één blok in het midden hing.
   Zijn er geen socials ingevuld, dan is de tweede rij `auto` = 0 hoog en vult
   de linklijst de hele overlay — precies zoals het daarvoor was. */
#menu{position:fixed;inset:0;z-index:7200;background:var(--bg);
  display:grid;grid-template-rows:1fr auto;justify-items:center;
  overflow-y:auto;
  padding:88px 4vw 40px;opacity:0;visibility:hidden;
  transition:opacity .4s ease,visibility .4s}
#menu.open{opacity:1;visibility:visible}
/* kruisje rechtsboven — staat BINNEN de overlay, want #menu (7200) ligt over .nav (7000)
   en dekte daardoor de hamburger-knop af (menu was niet te sluiten). */
.menu-close{position:absolute;top:22px;right:4vw;width:44px;height:44px;
  background:none;border:0;padding:0;cursor:pointer;color:var(--text);
  display:grid;place-items:center}
.menu-close::before,.menu-close::after{content:"";position:absolute;
  width:26px;height:2px;background:currentColor;border-radius:2px}
.menu-close::before{transform:rotate(45deg)}
.menu-close::after{transform:rotate(-45deg)}
.menu-close:hover{color:var(--accent)}
/* logo linksboven, symmetrisch met het kruisje rechtsboven. Zelfde bron als
   .nav-logo (header.json → logo); geen logo gekozen = server rendert niets. */
.menu-logo{position:absolute;top:22px;left:4vw;display:flex;align-items:center;transition:opacity .3s}
.menu-logo:hover{opacity:.7}
.menu-logo img{display:block;height:32px;width:auto;max-width:min(200px,40vw);object-fit:contain}
/* Hier stond .menu-panel: een wikkel om de links én de socials, nodig toen de
   overlay één gecentreerd kind moest hebben. Met twee rijen is die wikkel juist
   in de weg — hij zou beide blokken weer aan elkaar plakken. */
.menu-inner{align-self:center;
  display:flex;flex-direction:column;gap:6px;text-align:center}
.menu-inner a{font-family:var(--font-display);text-transform:uppercase;
  font-weight:600;letter-spacing:.01em;
  font-size:clamp(38px,11vw,86px);line-height:1;color:var(--text)}
.menu-inner a:hover{color:var(--accent)}

/* socials in de overlay — stonden alleen in de footer, op mobiel ver weg */
/* icoontjes, altijd op één rij — vijf platforms passen ruim, dus geen wrap nodig.
   `align-self:end` duwt ze tegen de onderkant van hun rij; de padding erboven
   houdt ze los van de laatste menu-link, ook als het scherm zo laag is dat de
   overlay moet scrollen. */
.menu-socials{align-self:end;padding-top:clamp(28px,5vh,48px);
  display:flex;flex-wrap:nowrap;justify-content:center;gap:22px}
.menu-socials a{display:flex;color:var(--muted);transition:color .3s}
.menu-socials a:hover{color:var(--accent)}
.menu-socials svg{width:22px;height:22px}

/* drag-and-drop hint when loading a track */
body.drag-over::after{content:"DROP JE TRACK";position:fixed;inset:14px;z-index:9500;
  border:2px dashed var(--accent);border-radius:14px;display:grid;place-items:center;
  font-family:var(--font-mono);letter-spacing:.2em;color:var(--accent);
  background:color-mix(in srgb,var(--bg) 70%,transparent);pointer-events:none}

/* =====================================================================
   COOKIEBANNER  (2026-10-06)

   Patroon overgenomen van staging.vhc.nl op verzoek van Koraa: een
   gecentreerd paneel over een donkere overlay, met een vaste kop, een
   scrollend midden en een vaste knoppenbalk. Niet de huisstijl van VHC —
   alles hier loopt via de tokens, dus de banner volgt automatisch het
   donkere én het lichte thema.

   WAAROM EEN MODAL EN GEEN BALK ONDERAAN. Bij een balk kun je doorklikken
   zonder te kiezen, en dan weet je van een bezoeker niet of hij ja of nee
   bedoelde. Een modal dwingt één keer een keuze af en is daarna weg.

   WAAROM .btn HERGEBRUIKT. De knoppen zijn gewoon .btn / .btn-fill /
   .btn-tertiary uit deze stylesheet; .ck-btn zet alleen de maat bij. Een
   eigen knoppenfamilie zou hier een tweede waarheid worden.

   z-index 10000: boven de hoogste bestaande laag (9500, de drop-hint).
   ===================================================================== */
.ck-overlay{position:fixed;inset:0;z-index:10000;display:flex;
  align-items:center;justify-content:center;padding:20px;
  background:rgba(0,0,0,.62)}
/* overflow:hidden op <html> i.p.v. <body>: de site zet zelf dingen op body. */
html.ck-vast{overflow:hidden}

/* Het paneel krijgt bij het openen de focus (zie consent.js). Geen ring
   eromheen: dat is de afspraak voor een dialoogvenster dat je programmatisch
   focust -- de ring hoort bij de knoppen die je daarna met Tab bereikt, en
   die houden hun eigen focusstijl. */
.ck-paneel:focus{outline:none}
.ck-paneel{display:flex;flex-direction:column;overflow:hidden;
  width:100%;max-width:560px;max-height:calc(100dvh - 40px);
  background:var(--surface);color:var(--text);
  border:1px solid var(--line-strong);border-radius:12px;
  box-shadow:0 24px 60px rgba(0,0,0,.5)}

.ck-kop{flex:none;position:relative;z-index:1;background:var(--surface);
  padding:24px 24px 12px;transition:box-shadow .15s ease}
/* Schaduw zodra er tekst onder de kop door scrollt: anders lijkt het paneel
   afgesneden in plaats van doorlopend. consent.js zet de klas. */
.ck-kop-schaduw{box-shadow:0 6px 14px -6px rgba(0,0,0,.55)}

/* De logo-rij. Het logo staat gecentreerd; de terug-knop ligt er absoluut
   links overheen, zodat het logo in het MIDDEN van het paneel blijft en niet
   verschuift zodra die knop erbij komt. Dat is precies waarom VHC het ook zo
   doet. min-height houdt de rij even hoog met en zonder knop. */
.ck-kop-rij{position:relative;display:flex;align-items:center;
  justify-content:center;min-height:40px;margin-bottom:16px}
.ck-logo{display:block;height:32px;width:auto;max-width:60%;object-fit:contain}
.ck-terug{position:absolute;left:0;background:none;border:0;padding:4px;
  cursor:pointer;font-family:var(--font-text);font-size:14px;font-weight:600;
  color:var(--accent)}
.ck-terug:hover{color:#5c9dff;text-decoration:underline;
  text-decoration-thickness:1px;text-underline-offset:4px}
/* Over de volle breedte van het paneel, dus de padding van .ck-kop eruit
   trekken met een negatieve marge. */
.ck-streep{border-top:1px solid var(--line);margin:0 -24px 18px}
.ck-titel{font-family:var(--font-display);text-transform:uppercase;
  font-weight:600;letter-spacing:.01em;font-size:24px;line-height:1.1;margin:0;
  padding-right:32px}
.ck-kruis{position:absolute;top:14px;right:14px;
  background:none;border:0;padding:6px;cursor:pointer;
  font-family:var(--font-text);font-size:22px;line-height:1;color:var(--muted)}
.ck-kruis:hover{color:var(--text)}

.ck-body{flex:auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  padding:0 24px 20px}
.ck-p{font-family:var(--font-text);font-size:14px;line-height:1.65;
  color:var(--text-soft);margin:0 0 12px}
.ck-p:last-child{margin-bottom:0}
.ck-link{color:var(--accent);font-weight:600;text-decoration:underline}
.ck-link:hover{color:#5c9dff}

.ck-regel{display:flex;align-items:flex-start;gap:16px;
  border:1px solid var(--line);border-radius:8px;padding:12px 14px;
  margin-bottom:12px}
.ck-regel:last-child{margin-bottom:0}
.ck-regel-mid{flex:1;min-width:0}
.ck-label{display:block;font-family:var(--font-text);font-weight:600;
  font-size:14px;margin-bottom:4px}
.ck-uitleg{display:block;font-family:var(--font-text);font-size:13px;
  line-height:1.55;color:var(--muted)}
.ck-altijd{flex:none;font-family:var(--font-text);font-size:12px;
  font-weight:600;color:var(--accent);white-space:nowrap;margin-top:2px}

/* Het schuifje. 44×24 met een knop van 20 — groot genoeg om op een telefoon
   met je duim te raken (44px is de ondergrens die Apple en WCAG aanhouden). */
.ck-schuif{flex:none;width:44px;height:24px;padding:2px;margin-top:2px;
  display:flex;justify-content:flex-start;align-items:center;
  border:0;border-radius:999px;cursor:pointer;
  background:var(--line-strong);transition:background .2s ease}
.ck-schuif-aan{background:var(--accent);justify-content:flex-end}
.ck-knop{display:block;width:20px;height:20px;border-radius:50%;
  background:#fff}

.ck-voet{flex:none;display:flex;flex-wrap:wrap;align-items:center;gap:10px;
  padding:16px 24px 18px;border-top:1px solid var(--line)}
/* De tekstknop links, de twee echte knoppen rechts. */
.ck-txt{flex:none;margin-right:auto;font-size:14px}
.ck-btn{flex:none;padding:12px 20px;font-size:14px}

/* Weigeren en accepteren zijn even groot en staan naast elkaar: weigeren mag
   niet moeilijker zijn dan accepteren. Daarom is "Weigeren" een gewone .btn
   met een volwaardige rand en geen weggemoffelde tekstlink. */
@media (max-width:600px){
  .ck-overlay{padding:12px}
  .ck-paneel{max-height:calc(100dvh - 24px)}
  .ck-kop{padding:18px 18px 10px}
  .ck-kop-rij{min-height:34px;margin-bottom:12px}
  .ck-logo{height:26px}
  .ck-streep{margin:0 -18px 14px}
  .ck-titel{font-size:20px}
  .ck-body{padding:0 18px 16px}
  .ck-voet{gap:8px;padding:12px 18px 14px}
  .ck-btn{flex:1 1 0;text-align:center;padding:12px 10px}
  /* De tekstknop zakt naar een eigen regel ONDER de twee knoppen: op een
     telefoon is de onderste rij het dichtst bij je duim, en daar hoort de
     minst belangrijke keuze niet. Vandaar order:3 én margin-right:0. */
  .ck-txt{order:3;flex:1 0 100%;margin:2px 0 0;text-align:center}
}

/* De regel op /cookiebeleid waarmee je je keuze terugziet en kunt wijzigen —
   intrekken moet net zo makkelijk zijn als geven. */
.ck-keuze{display:flex;flex-wrap:wrap;align-items:center;gap:16px;
  /* 68ch = dezelfde maat als .tx-body hierboven, zodat het paneel exact
     onder de tekstkolom uitlijnt. Geen margin:0 auto -- die kolom is
     linksuitgelijnd in de .wrap, niet gecentreerd. */
  max-width:68ch;margin-top:28px;
  padding:16px 18px;border:1px solid var(--line);border-radius:12px}
.ck-keuze-t{flex:1;min-width:200px;font-family:var(--font-text);font-size:14px;
  line-height:1.6;color:var(--text-soft)}
.ck-keuze-btn{flex:none}
