/* =========================================================================
   Letters. Zelf gehost, zodat de site niets bij een derde partij opvraagt
   en er dus ook geen toestemming of banner nodig is. Variabele bestanden:
   één bestand dekt het hele gewichtsbereik.

   Per letter twee bestanden, gescheiden op unicode-range. Een gewone
   Nederlandse pagina laadt alleen "latin"; "latin-ext" komt pas binnen
   als er echt een teken in staat dat daarin zit. Niet met de hand
   bijwerken: gegenereerd uit de Google Fonts-bron.
   ========================================================================= */

@font-face {
  font-family: "DM Sans";
  src: url("/fonts/dm-sans-italic-latin-ext.woff2") format("woff2");
  font-weight: 100 1000;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "DM Sans";
  src: url("/fonts/dm-sans-italic-latin.woff2") format("woff2");
  font-weight: 100 1000;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "DM Sans";
  src: url("/fonts/dm-sans-latin-ext.woff2") format("woff2");
  font-weight: 100 1000;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "DM Sans";
  src: url("/fonts/dm-sans-latin.woff2") format("woff2");
  font-weight: 100 1000;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/jetbrains-mono-latin-ext.woff2") format("woff2");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/jetbrains-mono-latin.woff2") format("woff2");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Space Grotesk";
  src: url("/fonts/space-grotesk-latin-ext.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Space Grotesk";
  src: url("/fonts/space-grotesk-latin.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body, h1, h2, h3, h4, p, figure, blockquote, ol, ul { margin: 0; padding: 0; }
ol, ul { list-style: none; }
img, video { display: block; max-width: 100%; height: auto; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
a { color: inherit; }

:root {
  /* Kleur. Overgenomen van de huidige site. */
  --wit:      #ffffff;
  --papier:   #f7f7f7;
  --inkt:     #0a0a0a;
  /* Eén tint donkerder dan de #ababab van de oude site. Die haalde 2,3:1 op
     wit, en dat is voor de kleine kapitaaltjeslabels (FORMAT, CREW, VORIGE)
     te weinig om comfortabel te lezen. Nu 3,2:1, en op het lichtgrijs van de
     footer 3,0:1. Bewust niet doorgezet naar de 4,5:1 van WCAG AA: dat vraagt
     #767676 en dan worden de labels net zo zwaar als de tekst eronder, wat
     precies de rangorde weghaalt waar ze voor zijn. */
  --grijs:    #8f8f8f;
  --lijn:     rgba(10, 10, 10, .12);
  --lijn-zacht: rgba(10, 10, 10, .06);

  --bg:        var(--wit);
  --bg-zacht:  var(--papier);
  --tekst:     var(--inkt);
  --tekst-dim: var(--grijs);

  /* Chrome over een donkere hero: nav-tekst is dan wit. */
  --nav-over-beeld: #ffffff;
  /* De matte balk bij scrollen. Kleur en dekking staan los van elkaar,
     want de dekking loopt mee met de scrollpositie (--nav-voortgang). */
  --nav-glas-kleur: 10 10 10;
  --nav-glas-alfa:  .72;

  /* Typografie: drie lagen, elk met een eigen taak.
     Koppen en titels dragen het karakter, de tekst leest, de mono
     doet de interface (menu, labels, credits, jaartallen).
     Alle drie zelf gehost, dus geen verzoek naar een derde partij. */
  --font-kop:   "Space Grotesk", "Helvetica Neue", Arial, sans-serif;
  --font-tekst: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-meta:  "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Tekstgroottes voor de interface (menu, labels, meta).
     Groeien mee op grote schermen, zoals bij mathieu-peters.com. */
  --ui-xs:  10px;
  --ui-sm:  11px;
  --ui-md:  12px;
  --ui-nav: 13px;

  /* Maatvoering. 1080 is de gedeelde kolom waar lijst, films,
     tekst en footer allemaal op uitlijnen. */
  --kolom:      1200px;
  --lees:        860px;
  --rand:         24px;
  --nav-hoogte:   72px;

  /* De hoogte van een headerbeeld: projectpagina's, /over, /contact, /av.
     De showreel op de homepage valt hier bewust buiten, die vult het scherm.
     Begon op clamp(320px, 62vh, 700px) en is een slag groter gezet: een
     banner die ruim driekwart van het scherm pakt laat de bezoeker eerst
     het beeld zien en pas daarna de tekst. Eén plek om aan te draaien; per
     pagina kan het nog met `bannerHoogte` in de frontmatter. */
  --banner-hoogte: clamp(400px, 78vh, 900px);

  --ritme:  clamp(3rem, 6vw, 6rem);
  /* De projectpagina staat dichter op elkaar: de blokken horen daar bij
     elkaar te horen, niet als losse secties te lezen. Ongeveer de helft. */
  --ritme-project: clamp(1.5rem, 3vw, 3rem);
  --traag:  .85s cubic-bezier(.16, 1, .3, 1);
  --snel:   .25s cubic-bezier(.16, 1, .3, 1);

  /* Een veer: schiet een klein stukje voorbij het doel en zakt terug. Als
     linear() met de punten uitgeschreven en niet als cubic-bezier, want een
     bezier kan maar één keer doorschieten; hiermee komt hij terug, gaat er
     nog een fractie overheen en staat dan stil. Dat laatste is wat het als
     veer laat lezen in plaats van als een zwiep.

     Hoogste punt is 1,08, dus hij schiet 8% voorbij. Bij een lijst van elf
     regels is dat zo'n 25px extra ruimte die meteen weer dichtklapt: genoeg
     om te voelen, te weinig om als een fout te lezen. */
  --veer: linear(
    0, .132 6%, .448 14%, .776 22%, .967 28%,
    1.057 34%, 1.077 40%, 1.049 48%, 1.004 58%,
    .987 68%, .998 82%, 1
  );
}

/* Nodig om van hoogte 0 naar 'auto' te kunnen overgaan; zonder dit klapt
   een uitklapper in één keer open. Browsers die het niet kennen negeren
   het en doen precies dat, wat de terugval is. */
:root { interpolate-size: allow-keywords; }

@media (min-width: 810px)  { :root { --rand: 40px; } }
@media (min-width: 1600px) { :root { --rand: 64px; --nav-hoogte: 84px; } }

@media (min-width: 1920px) { :root { --ui-xs: 11px; --ui-sm: 12px; --ui-md: 13px; --ui-nav: 14px; } }
@media (min-width: 2560px) { :root { --ui-xs: 12px; --ui-sm: 13px; --ui-md: 14px; --ui-nav: 15px; } }
@media (min-width: 3200px) { :root { --ui-xs: 13px; --ui-sm: 14px; --ui-md: 16px; --ui-nav: 17px; } }

body {
  font-family: var(--font-tekst);
  font-size: clamp(1rem, .95rem + .25vw, 1.125rem);
  line-height: 1.6;
  color: var(--tekst);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--font-kop); font-weight: 500; line-height: 1.1; letter-spacing: -.03em; }
h1 { font-size: clamp(2rem, 1.2rem + 3.4vw, 4rem); }
h2 { font-size: clamp(1.5rem, 1.1rem + 1.8vw, 2.5rem); }
h3 { font-size: clamp(1.15rem, 1rem + .7vw, 1.5rem); }

/* ---------- Layout ------------------------------------------------------ */

.kolom {
  width: 100%;
  max-width: var(--kolom);
  margin-inline: auto;
  padding-inline: var(--rand);
}
.lees { max-width: var(--lees); }

/* ---------- Toegankelijkheid -------------------------------------------- */

.overslaan {
  position: absolute;
  left: -9999px;
  z-index: 100;
  padding: .75rem 1.25rem;
  background: var(--inkt);
  color: var(--wit);
}
.overslaan:focus { left: var(--rand); top: 1rem; }

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* ---------- Nav --------------------------------------------------------- */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  height: var(--nav-hoogte);
  padding-inline: var(--rand);
  color: var(--tekst);

  /* De balk komt op met de scroll. --nav-voortgang loopt van 0 naar 1 over
     de eerste 220px en wordt door site.js gezet. Zonder JavaScript blijft
     hij 0 en is er dus geen balk, precies zoals het hiervoor ook was.

     Let op: hier hoort geen transition op background of backdrop-filter.
     De waarde volgt de scrollpositie al, en een transition erbovenop laat
     de balk achter je scroll aan hobbelen. Alleen de kleuromslag heeft er
     een nodig, want die springt wel. */
  --nav-voortgang: 0;
  background: rgb(var(--nav-glas-kleur) / calc(var(--nav-glas-alfa) * var(--nav-voortgang)));
  transition: color var(--snel);
}

.nav[data-balk] {
  backdrop-filter: saturate(calc(1 + .4 * var(--nav-voortgang))) blur(calc(14px * var(--nav-voortgang)));
  -webkit-backdrop-filter: saturate(calc(1 + .4 * var(--nav-voortgang))) blur(calc(14px * var(--nav-voortgang)));
}

/* Over een openingsbeeld: witte tekst, geen balk.

   Wit alleen is niet genoeg, want een banner kan net zo goed licht zijn als
   donker. De bovenrand van de Bamboek-foto is bijna wit; daar verdwijnt
   witte tekst even hard als zwarte. Daarom loopt er een donkere waas van
   boven naar beneden achter de nav.

   De sterkte is niet op gevoel gekozen. Bij elke banner is de helderheid
   gemeten op de plekken waar de nav-tekst staat (logo links, menu rechts),
   en wel van de felste 5% van de pixels daar, want dat is het lastigste
   geval. Bamboek is de zwaarste: die vraagt 54% dekking op de hoogte van de
   tekst om witte letters op 4,5:1 te houden, de ondergrens van WCAG AA voor
   tekst op deze grootte. Vandaar 75% bovenaan, aflopend naar niets. Het
   verloop is expres hoger dan de nav zelf (2,4x), want een korte harde fade
   leest als een balk en een lange als schaduw.

   Zodra je scrolt neemt de matte balk van [data-vast] het over en fadet de
   waas weg, anders zou je twee lagen over elkaar krijgen. */
.nav[data-over-beeld] { color: var(--nav-over-beeld); }

.nav[data-over-beeld]::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: calc(var(--nav-hoogte) * 2.4);
  background: linear-gradient(to bottom,
    rgba(0, 0, 0, .75) 0%,
    rgba(0, 0, 0, .55) 25%,
    rgba(0, 0, 0, .22) 60%,
    rgba(0, 0, 0, 0) 100%);
  pointer-events: none;
}

/* De waas dooft uit terwijl de balk opkomt, zodat je nooit twee donkere
   lagen over elkaar krijgt. Ook dit volgt de scroll, dus geen transition. */
.nav[data-over-beeld]::before { opacity: calc(1 - var(--nav-voortgang)); }

/* De waas is een absoluut gepositioneerd pseudo-element en zou daarmee
   bovenop de niet-gepositioneerde navkinderen landen. Dit zet ze terug
   boven de waas. */
.nav > * { position: relative; }

/* De regel onder de naam staat normaal op 60% dekking, wat over een foto
   te weinig is: op de lichtste banner haalt hij dan 3,1:1. Over beeld gaat
   hij daarom omhoog. Het verschil met de naam erboven blijft zichtbaar in
   grootte en letterafstand, dus de rangorde gaat niet verloren. */
.nav[data-over-beeld] .nav__naam-sub,
.nav[data-vast] .nav__naam-sub { opacity: .9; }

/* De balk zelf komt hierboven geleidelijk op. Wat hier overblijft is de
   kleuromslag: die kan niet meebewegen, want een tekst die halverwege grijs
   is valt op elke ondergrond weg. Hij springt daarom in één keer om, op het
   punt waar de balk donker genoeg is dat wit beter uitkomt dan zwart. */
.nav[data-vast] { color: var(--nav-over-beeld); }

.nav__logo {
  display: flex;
  align-items: center;
  gap: .625rem;
  text-decoration: none;
}
.nav__mark {
  /* Groeit mee met de naam ernaast, anders wordt het merkteken een stipje.

     `display: block` is geen overbodige regel: een <picture> is standaard
     inline en geeft zijn maten dan niet door, waardoor het teken naast de
     naam wegzakt. Dezelfde valkuil speelde eerder bij .banner en bij de
     covertegels.

     Hier stond een open cirkel in currentColor, die vanzelf meekleurde met
     de nav. Het merk is een dekkend donker vlak en doet dat niet: het blijft
     donker, ook wanneer de navtekst over beeld wit wordt. Dat is een bewuste
     keuze, want het teken brengt zijn eigen achtergrond mee en blijft
     daardoor overal leesbaar. */
  display: block;
  /* 44px is geen gekozen getal: dat is precies de hoogte van het naamblok
     ernaast (naam 24px plus de regel eronder), dus het teken lijnt boven uit
     met de bovenkant van de naam en onder met de onderkant van de ondertitel.
     Gemeten 20-64 tegenover 19,92-64,08.

     Het moet daarom mee als de naam ooit een andere maat krijgt. Automatisch
     koppelen via `align-self: stretch` is geprobeerd en werkt niet: het teken
     valt dan terug op zijn eigen 88px en duwt de navbalk mee omhoog. */
  width: 44px; height: 44px;
  flex: none;
}
.nav__mark img { display: block; width: 100%; height: 100%; }
.nav__naam { display: flex; flex-direction: column; line-height: 1.15; }

/* De naam stond op de maat van de menu-items (13px) en de regel eronder op
   10px. Dat las niet: dit is de enige plek op de site waar je naam staat,
   dus die mag zich laten zien. De naam staat nu op ongeveer 24px op een
   breed scherm en 20px op een telefoon, met een clamp ertussen. De regel
   eronder groeit bewust minder hard mee: hoe groter het verschil tussen die
   twee, hoe duidelijker welke van de twee de naam is. */
.nav__naam-regel {
  font-family: var(--font-kop);
  font-size: clamp(1.25rem, 1.05rem + .45vw, 1.625rem);
  font-weight: 500;
  letter-spacing: -.02em;
}
.nav__naam-sub {
  font-family: var(--font-meta);
  font-size: clamp(.75rem, .7rem + .2vw, .9375rem);
  opacity: .6;
}

.nav__lijst { display: flex; gap: clamp(1.25rem, 2.5vw, 2.25rem); }

/* Onderstreping die vanaf links ingroeit en bij weghalen terugtrekt.
   Overgenomen uit het Framer-ontwerp. */
.nav__link {
  position: relative;
  display: inline-block;
  font-family: var(--font-meta);
  font-size: var(--ui-nav);
  text-decoration: none;
  padding-block: .25rem;
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--snel);
}
.nav__link:hover::after,
.nav__link:focus-visible::after,
.nav__link.is-huidig::after { transform: scaleX(1); }

.nav__knop { display: none; font-family: var(--font-meta); font-size: var(--ui-nav); }

/* ---------- Mobiele drawer ---------------------------------------------- */

/* Matglas in plaats van een dicht vlak, zodat de pagina eronder vaag
   doorschemert. Dezelfde kleur en dezelfde gedachte als de navbalk die bij
   het scrollen opkomt (--nav-glas-kleur), alleen sterker vervaagd: dit dekt
   het hele scherm, en dan leest een lichte blur als een vies venster.

   De dekking is niet op gevoel gekozen. In het slechtste geval staat er een
   witte pagina achter het glas, en dan moet witte tekst nog steeds op 4,5:1
   uitkomen, de ondergrens van WCAG AA voor het kleine nummertje naast een
   menu-item. Dat vraagt minimaal 56% dekking; hieronder loopt het van 58%
   bovenaan naar 74% onderaan, dus de lichtste kant houdt 4,9:1 en de
   donkerste 8,9:1. Veel lager kan dus niet: 56% is de bodem en die zit er
   vlak onder. Het verloop zit er omdat een vlak met één dekking juist weer
   als een vlak leest, en dat was het probleem dat we oplosten. */
.drawer {
  position: fixed;
  inset: 0;
  z-index: 45;
  display: flex;
  align-items: flex-end;
  padding: var(--rand);
  padding-bottom: clamp(2rem, 8vh, 4rem);
  background: linear-gradient(180deg,
    rgb(var(--nav-glas-kleur) / .58) 0%,
    rgb(var(--nav-glas-kleur) / .74) 100%);
  backdrop-filter: blur(28px) saturate(1.4);
  -webkit-backdrop-filter: blur(28px) saturate(1.4);
  color: var(--nav-over-beeld);
}

/* Zonder backdrop-filter zou je door een half doorzichtig vlak heen op de
   pagina kijken zonder vervaging, en dat is onleesbaar. Daar valt het dan
   terug op het dichte vlak van hiervoor. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .drawer { background: linear-gradient(180deg, #141414 0%, #0a0a0a 100%); }
}

.drawer[hidden] { display: none; }

/* De nav blijft boven de drawer staan en houdt anders de kleur van de
   pagina eronder: op een lichte pagina dus donkere letters op donker glas.
   Zolang de drawer openstaat is de ondergrond altijd donker. */
body.drawer-open .nav { color: var(--nav-over-beeld); }
body.drawer-open .nav__naam-sub { opacity: .9; }

.drawer__nav { width: 100%; }
.drawer__item { border-top: 1px solid rgba(255, 255, 255, .16); }
.drawer__item:last-child { border-bottom: 1px solid rgba(255, 255, 255, .16); }

.drawer__link {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding-block: clamp(.9rem, 2.4vh, 1.4rem);
  text-decoration: none;
}
.drawer__label { font-family: var(--font-kop); font-size: clamp(1.75rem, 9vw, 2.75rem); font-weight: 500; letter-spacing: -.03em; }
.drawer__nr    { font-family: var(--font-meta); font-size: var(--ui-sm); opacity: .45; }

@media (max-width: 809px) {
  .nav__links      { display: none; }
  .nav__knop       { display: block; }
  .nav__mark       { display: none; }
}

/* Zolang de drawer open staat mag de pagina eronder niet meescrollen. */
body.drawer-open { overflow: hidden; }

/* ---------- Homepage ---------------------------------------------------- */

/* Blok 1: de showreel met het statement erop. Het statement is wat de pagina
   sprekend maakt, naar het model van mathieu-peters.com. Daar staat het op
   152px; hier tot 96px. Groot genoeg om het beeld mee te laten praten, kalm
   genoeg voor een site die verder rustig is. Het ligt tussen de 64px van een
   h1 elders en Mathieu's maat in. */
.home-hero { position: relative; }

.home-hero__tekst {
  position: absolute;
  inset: auto 0 0 0;
  padding-block: clamp(4rem, 10vw, 9rem) clamp(2rem, 5vw, 4rem);
  color: #fff;
  /* Donker verloop van onderen, zodat witte letters leesbaar zijn op elk
     beeld. Zelfde gedachte als de waas achter de nav, maar dan vanaf de
     onderkant, waar de tekst staat. */
  background: linear-gradient(to top,
    rgba(0, 0, 0, .66) 0%,
    rgba(0, 0, 0, .38) 55%,
    rgba(0, 0, 0, 0) 100%);
  pointer-events: none;
}
/* De tekst op de showreel lijnt uit met het logo linksboven, niet met de
   tekstkolom van de rest van de site. De showreel loopt van rand tot rand,
   en dan is de linkerkant van de nav de lijn die het oog al volgt: logo
   boven, statement onder, recht onder elkaar. De kolom behoudt zijn padding
   (--rand), alleen de maximale breedte en het centreren vallen weg. */
.home-hero__tekst .kolom { max-width: none; }

/* Statement links, de link naar de volledige showreel rechts. Die eindigt op
   dezelfde lijn als het menu rechtsboven, en staat op de laatste regel van
   de sub, zodat hij bij het statement hoort en niet los in het beeld zweeft.
   Op een telefoon staat hij onder het statement. */
.home-hero__tekst .kolom { display: grid; gap: 1.5rem; }
@media (min-width: 810px) {
  .home-hero__tekst .kolom {
    grid-template-columns: 1fr auto;
    column-gap: 3rem;
    align-items: end;
    align-items: last baseline;
  }
}
.home-hero__reel {
  justify-self: start;
  /* Het tekstblok laat kliks door naar het beeld; deze link niet. */
  pointer-events: auto;
  font-family: var(--font-meta);
  font-size: var(--ui-md);
  color: #fff;
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 1px solid rgba(255, 255, 255, .5);
  padding-bottom: 2px;
}
.home-hero__reel:hover,
.home-hero__reel:focus-visible { border-bottom-color: #fff; }

.home-hero__kop {
  font-size: clamp(2.75rem, 1.4rem + 5vw, 6rem);
  line-height: 1.02;
  letter-spacing: -.035em;
  max-width: 14ch;
  /* Verdeelt de kop zo gelijk mogelijk over de regels, in plaats van de
     eerste regel zo vol mogelijk te stoppen. Zonder dit brak "Jij in beeld.
     Ik erachter." als "Jij in beeld. Ik / erachter.", met een los woord aan
     het eind van de eerste regel. Werkt voor elke kop, niet alleen deze. */
  text-wrap: balance;
}
.home-hero__sub {
  margin-top: 1.25rem;
  /* 41ch en niet 44: bij 44 paste het woordje "en" nog net achter de komma op
     de eerste regel, en dan hangt er een los voegwoord aan het regeleinde.
     Gemeten op 1600px is de zin tot en met de komma 619px en mét dat "en"
     650px; 41ch is 623px en valt daar precies tussen.

     In ch en niet in pixels, zodat het bij elke lettergrootte dezelfde woorden
     zijn die passen: de maat schaalt mee met de zetting. Op een telefoon
     bindt deze grens niet, daar is de kolom smaller. */
  max-width: 41ch;
  font-size: clamp(1.05rem, .95rem + .45vw, 1.375rem);
  line-height: 1.4;
  color: rgba(255, 255, 255, .88);
  /* Geen los woord op de laatste regel. */
  text-wrap: pretty;
}

/* Blok 2 en 3 */
/* De homepage staat iets dichter op elkaar dan de rest van de site: 75% van
   het gewone ritme. Tussen de blokken hoort daar ruimte, maar de pagina moet
   als één geheel lezen en niet als losse secties. */
.home-sectie { padding-top: calc(var(--ritme) * .75); }

/* Ook de ruimte boven de footer, maar alleen hier: de footer is op elke
   pagina hetzelfde bestand, en elders blijft het gewone ritme staan. */
main:has(.home-sectie) + .footer { margin-top: calc(var(--ritme) * .75); }

.home-label {
  font-family: var(--font-meta);
  font-size: var(--ui-xs);
  font-weight: 400;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tekst-dim);
  margin-bottom: 1.25rem;
}
.home-meer {
  margin-top: 1.125rem;
  font-family: var(--font-meta);
  font-size: var(--ui-md);
}
.home-meer a {
  text-decoration: none;
  border-bottom: 1px solid var(--lijn);
  padding-bottom: 2px;
}
.home-meer a:hover { border-bottom-color: currentColor; }

/* Geselecteerd werk als spreads. Elk project krijgt een groot beeld met de
   titel ernaast, om en om gespiegeld. Dit is bewust iets anders dan de rijen
   op /projecten: die zijn gemaakt om veel projecten te scannen, dit is gemaakt
   om er drie indruk te laten maken.

   Het beeld loopt aan zijn kant door tot de rand van het scherm; de tekst
   blijft binnen de kolom van de rest van de site. De sectie zelf is daarom
   niet in een .kolom gezet, en de maten worden in het grid berekend:
     --k   de breedte van de gewone inhoudskolom
     60%   daarvan voor het beeld, 40% voor de tekst
   plus de lege ruimte aan weerszijden (de twee 1fr-sporen). Het beeld loopt
   aan zijn kant door tot de schermrand; de tekst loopt aan zijn kant door tot
   de paginamarge (--rand), dezelfde lijn als het logo en de tekst op de
   showreel. Zo krijgt de headliner ruimte zonder dat het beeld veel inlevert.
   Geen 100vw nodig, dus ook geen horizontale scroll door een scrollbalk.

   --spread-gat is de lucht tussen beeld en tekst. */
.spreads__lijst {
  display: grid;
  row-gap: clamp(1.3125rem, 3vw, 3rem);
}

.spread {
  --k: min(calc(var(--kolom) - 2 * var(--rand)), calc(100% - 2 * var(--rand)));
  display: grid;
  grid-template-columns: [l] var(--rand) [a] 1fr [c] var(--rand) [r];
  row-gap: 1.5rem;
  align-items: center;
  color: inherit;
  text-decoration: none;
}
.spread__beeld {
  grid-column: l / r;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--bg-zacht);
}
.spread__tekst { grid-column: a / c; }

@media (min-width: 810px) {
  .spread {
    --spread-gat: clamp(2rem, 6vw, 6rem);
    grid-template-columns: [l] 1fr [a] calc(var(--k) * .6) [b] calc(var(--k) * .4) [c] 1fr [r];
  }
  .spread__beeld { grid-column: l / b; grid-row: 1; }
  .spread__tekst {
    grid-column: b / r;
    grid-row: 1;
    padding-left: var(--spread-gat);
    padding-right: var(--rand);
  }

  .spread--gespiegeld {
    grid-template-columns: [l] 1fr [a] calc(var(--k) * .4) [b] calc(var(--k) * .6) [c] 1fr [r];
  }
  .spread--gespiegeld .spread__beeld { grid-column: b / r; }
  /* Gespiegeld staat de rafelige rechterkant van de tekst naar het beeld toe
     in plaats van de rechte linkerkant, dus oogt dezelfde tussenruimte hier
     groter. Twee correcties:
       - justify-self: end. Is er meer ruimte dan de tekst nodig heeft (op een
         breed scherm houdt de headliner op bij 44ch), dan schuift het blok
         tegen het beeld aan in plaats van tegen de paginamarge.
       - --schuif. Het blok schuift een halve tussenruimte naar het beeld toe,
         want de langste regel komt zelden tot de rand. Maar nooit dichter dan
         2,5rem, want soms komt hij dat wel. De breedte blijft gelijk, zodat de
         regels net zo breken als zonder. */
  .spread--gespiegeld .spread__tekst {
    --schuif: min(var(--spread-gat) / 2, var(--spread-gat) - 2.5rem);
    grid-column: l / b;
    justify-self: end;
    padding-left: calc(var(--rand) + var(--schuif));
    padding-right: calc(var(--spread-gat) - var(--schuif));
  }
}

/* Afstammelingsselectors: de beeldpipeline wikkelt een <img> in een
   <picture>, zie de covertegels. */
.spread__beeld picture { display: block; height: 100%; }
.spread__beeld img,
.spread__beeld video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
  transition: transform var(--traag);
}
.spread:hover .spread__beeld img,
.spread:hover .spread__beeld video,
.spread:focus-visible .spread__beeld img,
.spread:focus-visible .spread__beeld video { transform: scale(1.03); }

.spread__kicker {
  font-family: var(--font-meta);
  font-size: var(--ui-sm);
  color: var(--tekst-dim);
  margin-bottom: 1rem;
}
.spread__titel {
  font-size: clamp(2rem, 1.2rem + 2.6vw, 3.5rem);
  line-height: 1.04;
  letter-spacing: -.03em;
}
.spread__haak {
  margin-top: 1rem;
  max-width: 44ch;
  font-size: clamp(1.05rem, .95rem + .35vw, 1.25rem);
  text-wrap: pretty;
  line-height: 1.45;
  color: var(--tekst-dim);
}
.spread__link {
  display: inline-block;
  margin-top: 1.5rem;
  font-family: var(--font-meta);
  font-size: var(--ui-md);
  border-bottom: 1px solid var(--lijn);
  padding-bottom: 2px;
}
.spread:hover .spread__link,
.spread:focus-visible .spread__link { border-bottom-color: currentColor; }

@media (prefers-reduced-motion: reduce) {
  .spread__beeld img, .spread__beeld video { transition: none; }
  .spread:hover .spread__beeld img,
  .spread:hover .spread__beeld video { transform: none; }
}

/* Quotes: naast elkaar als het er twee zijn, anders over de volle breedte. */
/* Zonder JavaScript: gewoon onder elkaar. Dat is de terugval en meteen de
   opmaak bij prefers-reduced-motion. */
.quotes { display: grid; gap: var(--ritme); }

/* Met JavaScript legt het script ze op elkaar. Alle drie in dezelfde grid-cel,
   zodat het blok de hoogte van de langste aanhoudt en de pagina niet springt
   bij het wisselen.

   De breedte is ruim de helft van de kolom en de quote blijft links staan,
   op dezelfde lijn als de tekst erboven. Bewust niet gecentreerd: dan zou het
   blok als los element midden op de pagina gaan zweven. */
.quotes[data-loop] {
  grid-template-areas: "quote";
  gap: 0;
}
/* De oude quote gaat eerst helemaal weg en pas daarna komt de nieuwe op. Een
   gewone crossfade lijkt logisch maar werkt niet voor tekst: halverwege staan
   er dan twee regels op halve dekking over elkaar en lees je dubbele letters.
   Vandaar de vertraging op de inkomende: 0,35s uit, dan 0,45s in. */
.quotes[data-loop] .quote {
  grid-area: quote;
  opacity: 0;
  transition: opacity .35s ease;
  /* Wat niet in beeld staat mag ook niet aanklikbaar zijn. */
  pointer-events: none;
}
.quotes[data-loop] .quote[data-actief] {
  opacity: 1;
  transition: opacity .45s ease .35s;
  pointer-events: auto;
}

/* De afzenderregel onder de quote: portret, wie het zegt, en rechts het
   tellertje. Alles op één lijn met de quote erboven; het portret is het enige
   dat hoogte toevoegt. */
.quote__afzender {
  margin-top: 1.5rem;
  display: flex;
  align-items: center;
  gap: .875rem;
  font-family: var(--font-meta);
}
/* Stonden allebei op --ui-sm, en dat is 11px: te klein voor een naam, die is
   geen labeltje maar de afzender van wat erboven staat. */
.quote__naam { font-size: .9375rem; }
.quote__rol { font-size: .8125rem; color: var(--tekst-dim); }
.quote__foto {
  flex: none;
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 50%;
  object-fit: cover;
  /* Een portret staat meestal met het hoofd in de bovenste helft; midden
     uitsnijden hakt dan de kin eraf. */
  object-position: 50% 30%;
  background: var(--bg-zacht);
}
/* De beeldpipeline wikkelt elke <img> in een <picture>, en die is standaard
   inline: dan geeft hij de vorm en de maat niet door. Zelfde valkuil als bij
   .banner en de covertegels. */
.quote__afzender picture { flex: none; display: block; }
.quote__afzender picture > img {
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 50%;
  object-fit: cover;
  object-position: 50% 30%;
  display: block;
}
.quote__wie { display: flex; flex-direction: column; gap: .25rem; }

/* Het tellertje helemaal rechts, en alleen in de draaiende versie: zonder
   script staan de quotes onder elkaar en slaat een positie in een reeks
   nergens op. */
.quote__teller {
  display: none;
  margin-left: auto;
  font-size: .8125rem;
  color: var(--tekst-dim);
  /* Vaste cijferbreedte, anders verspringt het getal bij elke wissel. */
  font-variant-numeric: tabular-nums;
  letter-spacing: .04em;
}
.quotes[data-loop] .quote__teller { display: block; }
.quote { margin: 0; }

.quote blockquote { margin: 0; }
/* Groter dan de lopende tekst, want het is een citaat en geen alinea, maar
   niet zoveel groter dat het schreeuwt. Op 1600px is dit 30px tegen 20px
   voor de tekst ernaast, dus anderhalf keer.

   Het stond op 44px. Dat kwam ervan toen het quoteblok nog los onder een
   foto over de volle breedte hing en daar in het wit wegviel; de zetting
   moest dat toen in zijn eentje dragen. Sinds de tekst en de foto naast
   elkaar staan is dat niet meer zo, en dan is 44px te veel van het goede. */
.quote blockquote p {
  font-family: var(--font-kop);
  font-size: clamp(1.375rem, 1.22rem + .65vw, 1.875rem);
  line-height: 1.3;
  letter-spacing: -.015em;
}

/* Op /over staan de quotes onder de foto, op dezelfde afstand als de foto
   onder de tekst. Geen omkadering: geprobeerd met lijnen en met een grijs
   vlak, allebei teruggedraaid. Wat het blok gewicht geeft is de zetting zelf,
   de quote staat op 44px. */
/* Tekst en foto naast elkaar vanaf tabletbreedte; zie over.njk voor het
   waarom. Onder 810px doet dit niets en staat de foto gewoon onder de tekst.

   align-items: start houdt de foto bovenaan uitlijnen met de eerste regel,
   in plaats van hem midden in de rij te laten zweven. */
@media (min-width: 810px) {
  .over-body {
    display: grid;
    grid-template-columns: minmax(0, 32em) minmax(0, 1fr);
    gap: clamp(2rem, 4vw, 4rem);
    align-items: stretch;
  }
  /* De leesmaat komt hier van de kolom, niet van de tekst zelf. */
  .over-body .tekst { max-width: none; }
  /* De foto loopt even hoog als de tekst ernaast en snijdt bij. Zonder dat
     zou hij op zijn eigen verhouding blijven staan: een liggend beeld wordt
     in een kolom van 430px maar 240 hoog, en dan bungelt er een postzegel
     naast een blok tekst. Zo blijft de onderkant van beide op één lijn en
     volgen de quotes direct op de laatste regel. */
  .over-body .beeldblok { margin: 0; height: 100%; }
  .over-body .beeldblok img { height: 100%; object-fit: cover; }
}

.over-quotes { margin-top: var(--ritme); }

/* ---------- Footer ------------------------------------------------------ */

.footer {
  margin-top: var(--ritme);
  padding-block: var(--ritme) 2.5rem;
  background: var(--bg-zacht);
  border-top: 1px solid var(--lijn-zacht);
}

/* De projectpagina zet er zelf al ruimte onder; de footer hoeft daar niets
   bovenop, anders stapelt het ritme dubbel. */
.projectpagina .footer { margin-top: 0; }
.footer__kolom {
  width: 100%;
  max-width: var(--kolom);
  margin-inline: auto;
  padding-inline: var(--rand);
  display: grid;
  gap: var(--ritme);
}

/* De afsluiter is de laatste zin die de site zegt, dus die mag zich laten
   horen. Loopt tot 60px op een breed scherm, net onder de 64px van een h1:
   de footer spreekt op, maar niet harder dan de kop van de pagina zelf.
   Beide regels delen dezelfde maat, alleen de kleur verschilt. */
.footer__kop,
.footer__sub {
  font-family: var(--font-kop);
  font-size: clamp(2.125rem, 1.35rem + 2.8vw, 3.75rem);
  font-weight: 500;
  letter-spacing: -.02em;
  line-height: 1.1;
}
.footer__sub { color: var(--tekst-dim); }
.footer__contact { margin-top: 1.5rem; display: flex; flex-direction: column; align-items: flex-start; gap: .625rem; }
.footer__contact a { text-decoration: none; border-bottom: 1px solid var(--lijn); padding-bottom: 2px; }
.footer__contact a:hover { border-bottom-color: currentColor; }

.footer__nav { display: flex; flex-wrap: wrap; gap: var(--ritme); }

/* Vanaf tabletbreedte staan de afsluiter en de linkjes naast elkaar in plaats
   van onder elkaar. Dat vult de rechterhelft, die anders leeg bleef omdat er
   niets stond dat hem kon vullen.

   De linkjes schuiven als blok naar rechts met justify-self, niet met
   text-align: dan blijven de lijsten zelf links uitgelijnd en lopen de
   woorden onder elkaar door. Zelfde reden als bij de titelkaart op een
   projectpagina.

   align-items: start houdt ze bovenaan uitlijnen met de afsluiter; zonder dat
   zouden ze verticaal midden in dat hoge blok gaan zweven. */
@media (min-width: 810px) {
  .footer__kolom {
    grid-template-columns: 1fr auto;
    align-items: start;
  }
  .footer__nav { justify-self: end; }
  .footer__onderbalk { grid-column: 1 / -1; }
}
.footer__lijst { display: grid; gap: .375rem; }
.footer__lijst a { font-family: var(--font-meta); font-size: var(--ui-md); text-decoration: none; opacity: .75; }
.footer__lijst a:hover { opacity: 1; }
.footer__labeltje {
  font-family: var(--font-meta);
  font-size: var(--ui-xs);
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--tekst-dim);
  margin-bottom: .625rem;
}

.footer__onderbalk {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: .5rem 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--lijn-zacht);
  font-family: var(--font-meta);
  font-size: var(--ui-sm);
  color: var(--tekst-dim);
}
.footer__onderbalk a { text-decoration: none; }
.footer__onderbalk a:hover { color: var(--tekst); }

/* ---------- Bewegingsreductie ------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- Pagina's ---------------------------------------------------- */

/* Elke pagina moet onder de vaste nav beginnen. */
.pagina, .hero { padding-top: calc(var(--nav-hoogte) + var(--ritme)); }

.hero__kop  { max-width: 20ch; }
.hero__lead { margin-top: 1.5rem; font-size: 1.25em; color: var(--tekst-dim); }

/* De openingszin onder de kop, op /over en /contact. Eén stijl voor allebei:
   ze stonden los van elkaar (28px in de kopletter op /over, 22px in de
   broodletter op /contact) en dat maakte er twee losse pagina's van.
   De broodletter wint, want een lead in de kopletter concurreert met de h1
   erboven en de site is verder sober. */
.lead {
  /* Stond op 1.5rem, wat naast de 64px onder de lead uit balans oogde.
     Niet gelijkgetrokken met die 64: dan zweeft de lead los tussen de kop en
     de lijn, terwijl hij bij de kop hoort. */
  margin: clamp(2rem, 3vw, 3rem) 0 0;
  /* 34em bij de leadzetting komt op ongeveer dezelfde pixelbreedte uit als
     de 42em van de lopende tekst eronder (762 tegen 756 op een breed
     scherm), zodat de twee blokken rechts op dezelfde lijn eindigen. Em en
     niet px, want allebei schalen ze mee met het venster. */
  max-width: 38.5em;
  font-size: clamp(1.25rem, 1.1rem + .45vw, 1.4rem);
  line-height: 1.45;
  color: var(--tekst-dim);
  text-wrap: pretty;
}
.lead p { margin: 0; }

/* De lopende tekst op /over staat even breed als de foto eronder (1072px op
   een breed scherm). Dat is een bewuste keuze uit 09-09, maar bij 18px gaf
   het 87 tekens per regel, en boven de 80 raakt je oog de volgende regel
   kwijt bij het terugspringen. Vandaar hier een grotere zetting in plaats
   van een smallere kolom: op 1600px levert 20px precies 67 tekens op, de
   maat waar lopende tekst het prettigst leest.

   De clamp houdt het op smalle schermen bij 18px, want daar is de kolom
   smal en zou 20px de regels juist te kort maken. */
.tekst {
  /* In em, niet in pixels: zo blijft het aantal tekens per regel gelijk,
     ook als de zetting hierboven meeschaalt met het venster. 36em komt neer
     op ongeveer 83 tekens per volle regel. Dat is bewust boven de 60 tot 80
     die als comfortabel geldt: de kolom is in drie stappen verbreed (36em,
     42em, 48em) omdat een smalle tekst raar oogt onder een lijn die de volle
     kolom pakt. Ter vergelijking, over die hele kolom waren het er 125, en
     dat las echt niet meer. Nog breder kan alleen door de zetting mee te
     vergroten; voor de volle 1072px kom je op ongeveer 28px uit. */
  max-width: 48em;
}
.tekst p {
  font-size: clamp(1.125rem, 1rem + .35vw, 1.25rem);
  line-height: 1.55;
}
.tekst > * + * { margin-top: 1.5rem; }

/* De lijn tussen de kop en wat erop volgt, op /over. Dezelfde maatvoering
   als de lijn boven mail en telefoon op /contact, zodat de twee pagina's
   hetzelfde ritme houden. Een <hr> en geen border op de tekst eronder: die
   staat op leesmaat en is smaller dan de kolom, de lijn moet de volle
   breedte pakken. */
.scheiding {
  border: 0;
  border-top: 1px solid var(--lijn);
  /* Even veel ruimte boven als onder, zodat de lijn midden tussen de lead en
     de tekst hangt in plaats van naar de tekst toe te zakken. Zelfde maat
     als de lijn boven mail en telefoon op /contact (.contact__kaart), zodat
     beide pagina's hetzelfde ritme aanhouden. */
  margin: clamp(2.5rem, 5vw, 4rem) 0;
}

/* ---------- Contactpagina ---------------------------------------------- */
/* De pagina bestond eerst uit een kop en twee regels, en zei daarmee precies
   hetzelfde als de footer die er direct onder staat. Nu doet hij iets wat de
   footer niet kan: uitleggen wat er ná dat eerste telefoontje gebeurt. Geen
   formulier, dat is een bewuste keuze (zie contact.njk). */


/* Mail en telefoon naast elkaar op een breed scherm, onder elkaar op een
   telefoon. auto-fit met een minimum van 20rem doet dat zonder mediaquery:
   past er geen tweede kolom van 20rem meer bij, dan stapelt hij vanzelf. */
.contact__kaart {
  /* Even veel ruimte boven als onder de lijn; zie .scheiding op /over. */
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: clamp(2.5rem, 5vw, 4rem);
  border-top: 1px solid var(--lijn);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: clamp(2rem, 5vw, 4.5rem);
}

.contact__labeltje {
  margin: 0;
  font-size: var(--ui-md);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--tekst-dim);
}

.contact__groot {
  margin: .5rem 0 0;
  font-family: var(--font-kop);
  font-size: clamp(1.375rem, 1.1rem + 1.1vw, 2rem);
  letter-spacing: -.01em;
  /* Een mailadres en een telefoonnummer zijn één geheel: liever laten
     uitsteken dan midden in het nummer afbreken. */
  overflow-wrap: anywhere;
}
.contact__groot a { text-decoration: none; border-bottom: 1px solid var(--lijn); }
.contact__groot a:hover { border-bottom-color: currentColor; }

.contact__hint {
  margin: .875rem 0 0;
  max-width: 38ch;
  color: var(--tekst-dim);
  line-height: 1.55;
  text-wrap: pretty;
}

.contact__uitleg {
  margin-top: clamp(3rem, 6vw, 5rem);
  padding-top: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--lijn);
  max-width: var(--lees);
}
.contact__uitleg h2 { margin: 0 0 1.5rem; }

.plaatsvervanger {
  margin-top: 2rem;
  padding: 1.5rem;
  border: 1px dashed var(--lijn);
  color: var(--tekst-dim);
  font-size: var(--ui-md);
}

/* ---------- Juridische pagina's ----------------------------------------- */
/* Lange lopende tekst: smallere kolom, rustiger ritme. */

/* Breder dan de leeskolom: deze pagina lijnt uit met de rest van de site,
   niet met de smalle tekstkolom die voor lopend verhaal bedoeld is. Je leest
   voorwaarden anders dan een projecttekst: je scant naar het artikel dat je
   zoekt, en dan helpt het dat de nummers dicht bij elkaar staan.

   Gemeten op een venster van 1600px levert dit 115 tekens per regel op. Dat
   is aan de lange kant (voor lopende tekst wordt 60 tot 80 aangehouden), maar
   voor een document dat je scant in plaats van leest is dat te verdedigen.
   Valt het tegen bij het teruglezen, dan is dit het enige getal dat je hoeft
   te veranderen: `--lees` (860px) is de oude waarde. */
.juridisch main {
  max-width: var(--kolom);
  margin-inline: auto;
  padding: calc(var(--nav-hoogte) + var(--ritme)) var(--rand) 0;
}

/* Let op: alles hieronder staat binnen main. Zonder die begrenzing lekt
   'list-style: disc' naar de nav, de footer en de drawer, want de klasse
   .juridisch zit op <body>. */
.juridisch main h1 { margin-bottom: .5rem; }
.juridisch main h2 {
  margin-top: 3.5rem;
  margin-bottom: 1rem;
  font-size: clamp(1.25rem, 1.1rem + .6vw, 1.5rem);
}
.juridisch main p  { margin-bottom: 1.125rem; font-size: 1.125rem; line-height: 1.65; }
.juridisch main ul { margin: 0 0 1.125rem 1.25rem; list-style: disc; }
.juridisch main li { margin-bottom: .5rem; font-size: 1.125rem; line-height: 1.65; }

/* ---------- Projectoverzicht: de editorial rij ------------------------- */
/* Thomas' eigen ontwerp uit de Framer-versie: de beeldenstrook groeit
   omhoog bij hover, zodat de rij zich opent zonder dat er iets verspringt. */

.verborgen-kop {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* De lijst breekt rechts uit de tekstkolom, tot aan de paginarand. Daardoor
   is er meer breedte voor de beeldstrook zonder dat de titels verschuiven:
   die blijven links uitlijnen met de rest van de site. Asymmetrisch dus, en
   dat is de bedoeling.

   De rekensom: 50% is de halve breedte van de kolom, 50vw de halve breedte
   van het venster. Het verschil is precies de ruimte die naast de kolom
   overblijft; daar gaat de paginarand nog af. Is het venster smaller dan de
   kolom, dan komt er nul of minder uit en gebeurt er niets. Zo is er geen
   mediaquery nodig en klopt het op elke breedte.

   Een scrollbalk telt wel mee in 100vw maar niet in de layoutbreedte. Dat
   maakt de uitloop een paar pixels krapper dan de rand, nooit ruimer, dus
   het levert geen horizontale scroll op. */
.rijen {
  display: grid;
  margin-right: min(0px, calc(50% - 50vw + var(--rand)));

  /* Links loopt hij ook een stukje uit, maar hooguit de kolompadding: dan
     staan de titels op de rand van de kolom in plaats van erbinnen. Dat is
     precies genoeg om de brede beeldstrook rechts wat tegenwicht te geven,
     zonder dat de tekst in het niets naast de pagina komt te hangen. De
     bovengrens is `--rand` en niet een los getal, zodat het meeschaalt met
     de paginamarge.

     Op een venster dat smaller is dan de kolom valt dit vanzelf weg: daar
     ís de kolompadding de paginamarge, en dan zou de tekst tegen de rand
     van het scherm plakken. */
  margin-left: min(0px, max(calc(-1 * var(--rand)), calc(50% - 50vw + var(--rand))));
}

.rij {
  display: grid;
  /* De titelkolom heeft een bovengrens, zodat alle extra breedte naar de
     beeldstrook gaat in plaats van naar witruimte naast de titel. */
  grid-template-columns: minmax(180px, 300px) 1fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: start;
  padding-block: clamp(1.25rem, 2.5vw, 2rem);
  border-top: 1px solid var(--lijn-zacht);
  text-decoration: none;
}
.rijen .rij:last-child { border-bottom: 1px solid var(--lijn-zacht); }

.rij__nr {
  display: block;
  font-family: var(--font-meta);
  font-size: var(--ui-xs);
  color: var(--tekst-dim);
  margin-bottom: .75rem;
}
.rij__titel {
  font-size: clamp(1.125rem, 1rem + .5vw, 1.375rem);
  font-weight: 500;
}
.rij__meta {
  margin-top: .375rem;
  font-family: var(--font-meta);
  font-size: var(--ui-md);
  color: var(--tekst-dim);
}

.rij__strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; }
.rij__tegel {
  aspect-ratio: 2.4;
  overflow: hidden;
  background: var(--bg-zacht);
  transition: aspect-ratio var(--traag);
}

/* Let op de afstammelingsselector: de beeldpipeline wikkelt elke <img> in
   een <picture>, dus een `>` mist zijn doel. Toen dat hier nog stond kreeg
   de img geen height en viel hij terug op zijn eigen verhouding. Bij het
   openklappen wordt de tegel hoger dan het beeld zelf, en dan zag je de
   achtergrond van de tegel als een lichte rand onderaan.

   Het <picture>-element moet er zelf ook bij: dat is standaard inline en
   geeft de hoogte anders niet door aan het beeld erin. */
.rij__tegel picture { display: block; width: 100%; height: 100%; }
.rij__tegel img,
.rij__tegel video { width: 100%; height: 100%; object-fit: cover; }

.rij:hover .rij__tegel,
.rij:focus-visible .rij__tegel { aspect-ratio: 1.35; }

/* Hier heeft op 15-09 een accent per tegel gestaan: het beeld onder de muis
   zoomde in, en in een eerdere versie zakte alles waar je niet op stond terug
   in dekking. Allebei op verzoek weer weggehaald. De fade oogde als een
   pagina die half uit staat, en de zoom per tegel legde de nadruk op één
   beeld terwijl de rij als geheel de eenheid is die je aanklikt.

   Wat overblijft is wat er altijd al stond: de strook klapt open bij hover.
   Dat is één gebaar voor één link, en dat bleek genoeg.

   Voor als het ooit terugkomt: het was transform scale(1.08) op img en video
   onder `.rij__tegel:hover`, en daarvoor opacity .45 op een andere rij en
   .55 op een buurtegel. */

@media (max-width: 809px) {
  .rij { grid-template-columns: 1fr; gap: 1rem; }
}

/* De strook staat open zodra het apparaat geen muis heeft.

   Dit hangt bewust aan `hover: none` en niet aan een schermbreedte. Een iPad
   Air is 820px breed en kreeg daarmee de bureaubladopmaak: stroken van 136 bij
   57 pixels die alleen opengaan als je er met een muis overheen gaat, en die
   muis is er niet. Je zag dus acht projecten met drie onleesbare snippers
   ernaast, zonder enige manier om ze groter te krijgen.

   Een breekpunt verschuiven lost dat maar voor één apparaat op; de vraag is
   niet hoe breed het scherm is maar of er iets is om mee aan te wijzen. Zo
   valt elk toekomstig formaat er vanzelf goed in. */
@media (hover: none) {
  .rij__tegel { aspect-ratio: 1.6; }
  .rij:hover .rij__tegel { aspect-ratio: 1.6; }
}

/* ---------- Projectpagina --------------------------------------------- */

/* De header vult altijd de hele breedte en snijdt het beeld bij. Welk deel
   behouden blijft regelt `bannerFocus` in de frontmatter, via object-position
   op het beeld zelf. De hoogte is per project te overschrijven met
   `bannerHoogte`. */
.banner {
  width: 100%;
  height: var(--hoogte, var(--banner-hoogte));
  overflow: hidden;
  background: var(--bg-zacht);
}
/* De showreel op de homepage vult het scherm tot je scrollt. Stond eerst op
   90vh, waarbij je onderaan een reepje van het volgende blok zag.

   Twee keer height, en dat is geen slordigheid: dvh is de hoogte die je
   werkelijk ziet. Op een telefoon telt 100vh de adresbalk mee, ook als die
   in beeld staat, en dan valt de onderkant van het beeld eronder weg. De
   eerste regel is de terugval voor browsers die dvh niet kennen. */
.home-hero .banner {
  height: 100vh;
  height: 100dvh;
}

.banner > img, .banner > video,
.banner picture, .banner picture > img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
}

/* Op smalle schermen valt dezelfde uitsnede vaak anders uit. Staat er geen
   aparte mobiele waarde, dan geldt gewoon die van desktop. */
@media (max-width: 809px) {
  .banner { height: var(--hoogte-mobiel, var(--hoogte, var(--banner-hoogte))); }
  .banner > img, .banner > video,
  .banner picture, .banner picture > img {
    object-position: var(--focus-mobiel, var(--focus, 50% 50%));
  }
}

.project { display: grid; gap: var(--ritme-project); padding-bottom: var(--ritme-project); }
/* Ruimte tussen de banner en de titel. Begon op clamp(2.5rem, 5vw, 4rem) en
   is in twee stappen krapper gezet, ongeveer een derde eraf. De regel
   eronder, voor een pagina zonder banner, blijft ongemoeid: daar vult die
   ruimte de navbalk op en zou krapper de titel eronder schuiven. */
.project > .kolom:first-child { padding-top: clamp(1.5rem, 3.25vw, 2.75rem); }
.project--zonder-banner > .kolom:first-child { padding-top: calc(var(--nav-hoogte) + var(--ritme)); }

.projectkop h1 { max-width: 16ch; }
.projectkop__lead {
  margin-top: 1.5rem;
  max-width: var(--lees);
  font-size: clamp(1.25rem, 1.05rem + .8vw, 1.625rem);
  line-height: 1.35;
  color: var(--tekst-dim);
}

.verhaal > * + * { margin-top: 1.25rem; }

/* ---------- Film: eigen poster, speler pas bij klik ------------------- */

/* ---------- Film ------------------------------------------------------ */

/* Een <video controls> zonder opsmuk: de bediening komt van de browser, dus
   die hoeven we niet te bouwen en hij werkt met toetsenbord en schermlezer
   zoals de bezoeker gewend is. Wat wij regelen is alleen de vorm.

   Hier stond de opmaak van een eigen speelknop, een posterafbeelding en een
   doorzichtige laag over de YouTube-speler. Dat is met de embed verdwenen. */
.film { margin: 0; }
.film video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  background: #101010;
  border-radius: 2px;
}

/* ---------- Beeldreeksen ---------------------------------------------- */

/* Video: een strook filmbeelden naast elkaar. */
/* De beelden houden hun eigen verhouding, er wordt niets bijgesneden. Stond
   eerst op een vaste 1.6 met object-fit: cover, en dat kostte bij 16:9 een
   strook links en rechts en bij 4:3 een strook boven en onder.

   align-items: start omdat een rasterrij anders alle cellen even hoog rekt.
   Binnen één project zijn de verhoudingen meestal gelijk en valt dat niet op;
   meng je liggend en staand, dan loopt de onderkant niet gelijk. */
.stills { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; align-items: start; }
.stills img { width: 100%; height: auto; }
@media (max-width: 809px) { .stills { grid-template-columns: repeat(2, 1fr); } }

/* Foto: één kolom, beelden op hun eigen verhouding, niets bijgesneden. */
/* Het mozaïek: de fotoreeks op een projectpagina.

   Gebouwd met kolommen (column-count) en niet met grid. Reden: in een grid
   moet je de hoogte van elk beeld vooraf kennen om de rijen te laten sluiten,
   en die hoogte verschilt per foto. Kolommen doen dat vanzelf: elk beeld
   houdt zijn eigen verhouding, de kolommen vullen zich tot ze op zijn, en de
   onderkant loopt niet gelijk. Dat is hier gewenst.

   LET OP bij de volgorde. Beelden vullen eerst de linkerkolom van boven naar
   beneden, dan de volgende. Bij drie kolommen staat beeld 1, 2, 3 dus onder
   elkaar links, niet naast elkaar. Voor een reeks waar de opeenvolging ertoe
   doet is dat iets om rekening mee te houden bij het ordenen van de lijst.

   De reeks loopt breder dan de tekstkolom, tot 90% van het scherm. `50%` is
   de halve breedte van de kolom eromheen en `45vw` de halve reeks; het
   verschil is precies de verschuiving die hem weer op het midden zet. Onder
   1100px vervalt dat en volgt de reeks gewoon de kolom, want daar zou 90%
   juist smaller uitvallen dan de tekst. */
.mosaic {
  /* Eén waarde voor de ruimte tussen de beelden, zowel naast als onder
     elkaar. Krap gehouden: in een mozaïek doen de beelden het werk en is
     witruimte vooral onderbreking. Dit is 30% van wat de rest van de site
     als ritme aanhoudt. */
  --mozaiek-gat: clamp(.3rem, .75vw, .6rem);

  columns: 1;
  column-gap: var(--mozaiek-gat);
}
.mosaic__item {
  /* Een beeld mag nooit over twee kolommen gebroken worden. */
  break-inside: avoid;
  page-break-inside: avoid;
  margin-bottom: var(--mozaiek-gat);
}
/* Afstammelingsselector: de beeldpipeline wikkelt elke <img> in een
   <picture>, dus een `>` zou zijn doel missen. */
.mosaic__item picture { display: block; }
.mosaic__item img { width: 100%; height: auto; display: block; }

@media (min-width: 600px)  { .mosaic { columns: 2; } }
@media (min-width: 1100px) {
  .mosaic {
    /* Het aantal komt uit de template en hangt af van hoeveel beelden er
       zijn; zie de opmerking daar. Drie is de terugval. */
    columns: var(--kolommen, 3);
    width: 90vw;
    max-width: 90vw;
    margin-inline-start: calc(50% - 45vw);
  }
}

/* ---------- Credits ---------------------------------------------------- */

/* Staat bovenaan het project, direct onder titel en omschrijving: de
   feiten eerst, dan pas het werk. Leest als een titelkaart. */
.credits {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1.5rem 2rem;
  margin-top: 2.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--lijn-zacht);
}
.credits dt {
  font-family: var(--font-meta);
  font-size: var(--ui-xs);
  color: var(--tekst-dim);
  margin-bottom: .35rem;
}
.credits dd { margin: 0; font-size: .9375rem; }

/* Het eerste blok tegen de linkerrand, het laatste tegen de rechter, de rest
   in het midden van hun eigen kolom. Dat geeft de regel twee ankers in plaats
   van één, en dan hoeft de ruimte ertussen niet meer te kloppen.

   Dit gebeurt met justify-self en niet met text-align, en dat verschil doet
   er hier toe. Een grid-item met justify-self krimpt tot zijn inhoud en
   verschuift als geheel; de tekst erin blijft gewoon links uitgelijnd. Bij
   text-align zou de tekst zelf naar rechts vallen en dan zou het labeltje
   ('Rol') net zo goed tegen de rand komen te staan als de waarde eronder.
   Nu bepaalt de langste regel de breedte van het blok, en het label blijft
   aan de linkerkant daarvan hangen. */
.credits > *              { justify-self: center; }
.credits > *:first-child  { justify-self: start; }
.credits > *:last-child   { justify-self: end; }

/* ---------- Vorige / volgende ------------------------------------------ */

.projectnav {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 1.5rem;
  align-items: center;
  /* Half ritme: de projectdetails erboven horen bij dezelfde pagina en niet
     als losse sectie te lezen. Een gewone marge, dus de lijn zakt vanzelf
     mee als de apparatuurlijst opengaat. */
  margin-top: calc(var(--ritme) / 2);
  padding-top: 1.75rem;
  border-top: 1px solid var(--lijn-zacht);
}
.projectnav a { text-decoration: none; }
.projectnav__rechts { text-align: right; }
.projectnav__label {
  display: block;
  font-family: var(--font-meta);
  font-size: var(--ui-xs);
  color: var(--tekst-dim);
  margin-bottom: .25rem;
}
.projectnav__titel { font-family: var(--font-kop); font-size: 1.0625rem; }
.projectnav__alle { font-family: var(--font-meta); font-size: var(--ui-md); color: var(--tekst-dim); }
.projectnav__alle:hover { color: var(--tekst); }
@media (max-width: 599px) {
  .projectnav { grid-template-columns: 1fr 1fr; }
  .projectnav__alle { grid-column: 1 / -1; text-align: center; order: 3; }
}

/* ---------- Homepage ---------------------------------------------------- */


/* De ruimte tussen een banner en de kop eronder: /over en /contact. Stond op
   het volle --ritme (96px op een breed scherm) en is met 30% teruggebracht.
   Het beeld en de kop horen bij elkaar; met het volle ritme lazen ze als twee
   losse blokken. De projectpagina heeft hiervoor zijn eigen, nog krappere
   regel bij `.project > .kolom:first-child`. */
.na-hero { padding-top: calc(var(--ritme) * .7); }

/* Een los beeld binnen een lopende pagina, bijvoorbeeld onder de tekst op
   /over. Volle breedte van de kolom.

   De tekst ernaast staat op leesmaat en is dus smaller; dat verschil hoort
   zo, een beeld mag meer ruimte pakken dan een regel tekst. */
.beeldblok {
  margin: var(--ritme) 0 0;
}
.beeldblok img {
  width: 100%;
  height: auto;
  display: block;
}
/* /showreel/: de film hangt in het venster met ruimte eromheen, als een werk
   aan een muur. Twee keer height voor het vak, net als bij de homepagebanner:
   dvh is de hoogte die je werkelijk ziet, en op een telefoon telt 100vh de
   adresbalk mee. De eerste regel is de terugval.

   De lucht eromheen is één waarde, en de film pakt alles wat overblijft. Zo
   staat de witruimte vast en groeit de film mee met het scherm, in plaats van
   andersom. Wil je hem groter of kleiner: draai aan --reel-lucht. */
.reel {
  --reel-lucht: clamp(.75rem, 1.5vw, 1.5rem);
  height: 100vh;
  height: 100dvh;
  display: grid;
  place-items: center;
  /* De nav ligt over de bovenkant, dus die hoogte telt niet mee als ruimte:
     zonder deze padding staat de film optisch te hoog. Boven en onder de film
     blijft daarmee even veel lucht staan. */
  padding: calc(var(--nav-hoogte) + var(--reel-lucht)) calc(var(--rand) / 2) var(--reel-lucht);
}
.reel__speler {
  display: block;
  /* De breedte is het kleinste van twee dingen: wat er aan breedte over is,
     en wat er bij de beschikbare hoogte hoort. Zo groeit de film mee met het
     scherm in plaats van te blijven steken op de resolutie van het bestand,
     wat met `width: auto` wel gebeurt: dan blijft een 720p-reel op een breed
     scherm een klein vlakje. */
  width: min(100%, calc((100dvh - var(--nav-hoogte) - var(--reel-lucht) * 2) * 16 / 9));
  height: auto;
  aspect-ratio: 16 / 9;
  /* Zwart, want tot het posterbeeld er is kijk je anders door de speler heen
     naar de witte pagina. */
  background: #000;
}

/* Op een telefoon is er geen ruimte over om weg te geven: de film neemt de
   volle breedte en het vak krimpt mee, met wat lucht erboven en eronder. */
@media (max-width: 809px) {
  .reel {
    height: auto;
    /* Op een telefoon blijft de paginamarge wel de volle --rand: de halve
       marge van hierboven is bedoeld om op een breed scherm ruimte terug te
       winnen, en die valt hier juist te krap uit. */
    padding: calc(var(--nav-hoogte) + var(--ritme)) var(--rand) var(--ritme);
  }
  .reel__speler {
    width: 100%;
    max-height: none;
  }
}

.beeldblok figcaption {
  margin-top: .75rem;
  font-family: var(--font-meta);
  font-size: var(--ui-sm);
  color: var(--tekst-dim);
}
.home__werk { margin-top: var(--ritme); }
.home__alle { margin-top: 2rem; }
.home__alle a { font-family: var(--font-meta); font-size: var(--ui-md); color: var(--tekst-dim); text-decoration: none; }
.home__alle a:hover { color: var(--tekst); }

/* ---------- Projectdetails --------------------------------------------- */
/* Het diepteblok onderaan een project: format, thema, locatie, crew,
   talent, apparatuur. Alles optioneel; lege velden verdwijnen inclusief
   hun label, en zonder ingevulde velden verschijnt het blok niet. */

.details { padding-top: 1.75rem; border-top: 1px solid var(--lijn-zacht); }

/* Het blok als geheel is een uitklapper (zie projectdetails.njk). Op een
   breed scherm zie je daar niets van: de kop is gewoon een kop, zonder
   pijltje, en site.js houdt hem open. */
.details__uitklap-kop {
  display: flex;
  align-items: center;
  gap: .625rem;
  list-style: none;          /* Firefox */
  margin-bottom: 1.75rem;
  cursor: default;
}
.details__uitklap-kop::-webkit-details-marker { display: none; }
.details__uitklap-kop .details__kop { margin-bottom: 0; }
.details__uitklap-kop > .details__vouw-pijl { display: none; }

/* Op een telefoon wordt het een echte uitklapper in de vorm van de
   apparatuur: de hele regel is aanklikbaar, pijltje rechts, en de inhoud
   schuift open op dezelfde curve. */
@media (max-width: 809px) {
  .details__uitklap-kop {
    cursor: pointer;
    /* Ruimer raakvlak dan de kop zelf; de padding van .details telt mee. */
    margin-top: -.75rem;
    padding-block: .75rem;
    margin-bottom: 1rem;
  }
  .details__uitklap-kop > .details__vouw-pijl { display: block; margin-left: auto; }
  .details__uitklap:not([open]) > .details__uitklap-kop { margin-bottom: 0; }
  .details__uitklap-kop:hover .details__kop { color: var(--tekst); }
  .details__uitklap-kop:hover .details__vouw-pijl { opacity: .9; }
  .details__uitklap-kop:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

  /* Het dichtklappen bij het laden (site.js) hoort niemand te zien. Pas als
     het script klaar is, komt data-klaar erop en mag het bewegen. */
  .details__uitklap::details-content {
    block-size: 0;
    overflow: hidden;
  }
  .details__uitklap[open]::details-content { block-size: auto; }
  .details__uitklap[data-klaar]::details-content {
    transition: block-size .3s cubic-bezier(.16, 1, .3, 1),
                content-visibility .3s allow-discrete;
  }
  .details__uitklap[data-klaar][open]::details-content {
    transition: block-size .5s var(--veer),
                content-visibility .5s allow-discrete;
  }
}
@media (max-width: 809px) and (prefers-reduced-motion: reduce) {
  .details__uitklap[data-klaar]::details-content,
  .details__uitklap[data-klaar][open]::details-content { transition: none; }
}

.details__kop {
  font-family: var(--font-meta);
  font-size: var(--ui-xs);
  font-weight: 400;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--tekst-dim);
  margin-bottom: 1.75rem;
}

/* Zo veel kolommen als er gevulde groepen zijn: wat het is, wie het maakten,
   waarmee. Gelijke breedtes, want alle drie kunnen ze de langste zijn: een
   crewlijst met volledige regels loopt net zo hard uit als een apparatuurlijst.
   Welke groepen er zijn bepaalt projectdetails.njk. */
.details__kolommen { display: grid; gap: 0 clamp(2rem, 4vw, 4rem); }
/* auto-fit met een minimumbreedte in plaats van een vast aantal: zo stapelen
   de groepen vanzelf zodra ze te smal worden, zonder mediaquery. Drie
   kolommen van 81px op een telefoon is wat er anders gebeurt. De grens ligt
   lager bij drie kolommen, want daar staat het label boven de waarde en heeft
   een kolom dus minder breedte nodig. */
.details__kolommen--2 { grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); }
.details__kolommen--3 { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }

.details__lijst { display: grid; gap: 0; align-content: start; }

.details__rij {
  display: grid;
  grid-template-columns: minmax(140px, 1fr) 3fr;
  gap: 1.5rem;
  padding-block: .875rem;
  border-top: 1px solid var(--lijn-zacht);
}
.details__rij:first-child { border-top: 0; padding-top: 0; }

/* Bij drie kolommen past het label niet meer naast de waarde: een kolom is dan
   ongeveer 315px en het label eet daar 140 van op, waardoor een crewregel over
   vier regels breekt. Het label gaat daarom boven de waarde staan, wat de
   volle kolombreedte vrijmaakt en tegelijk beter bij een aftiteling past. */
.details__kolommen--3 .details__rij {
  grid-template-columns: 1fr;
  gap: .35rem;
}

/* Op een telefoon is er voor geen enkel blok ruimte om het label naast de
   waarde te zetten: van de 327px die er zijn gaat er dan 140 naar het label.
   Dus daar altijd boven elkaar, ook bij één of twee kolommen. */
@media (max-width: 599px) {
  .details__rij { grid-template-columns: 1fr; gap: .35rem; }
}

.details__rij dt {
  font-family: var(--font-meta);
  font-size: var(--ui-xs);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tekst-dim);
  padding-top: .2em;
}
.details__rij dd { margin: 0; font-size: .9375rem; line-height: 1.5; }

/* Een lijstwaarde (meerdere thema's, meerdere lenzen) komt onder elkaar. */
.details__regel { display: block; }
.details__regel + .details__regel { margin-top: .2rem; }

/* De apparatuurlijst vouwt dicht open. Zie projectdetails.njk voor het
   waarom; hier staat alleen de vorm.

   Altijd label boven waarde, ook waar een gewone rij ze naast elkaar zet:
   een uitklapper met zijn label links en zijn inhoud rechts leest niet als
   iets wat je kunt opentrekken. De hele kop is daarom één regel over de
   volle kolombreedte, met het aantal en het pijltje rechts. */
.details__vouw { display: block; padding-block: 0; }
/* Een <details> mag niet rechtstreeks in een <dl> staan, dus hij zit in de
   gewone rij-div. Die houdt daarmee de lijn, de marges en het gedrag van
   :first-child gelijk aan de andere kolommen; de padding verhuist naar de
   kop, zodat het hele blok aanklikbaar is en niet alleen de tekst erin. */
.details__vouw > details { display: block; }

.details__vouw-kop {
  display: flex;
  align-items: center;
  gap: .625rem;
  cursor: pointer;
  list-style: none;          /* Firefox */
  padding-block: calc(.875rem + .2em);
  /* Een tik naast de woorden mag ook openen, dus de kop pakt de volle
     breedte; op een telefoon scheelt dat mikken. */
  width: 100%;
  /* Die royale padding telt hier weer terug, zodat de afstand tussen label
     en inhoud gelijk is aan die in een gewone rij (.35rem).

     Bewust op de kop en niet als negatieve marge op de inhoud: het vak dat
     opengaat (::details-content) heeft overflow: hidden, dus inhoud die er
     bovenuit steekt wordt afgekapt, en dan valt de eerste regel van de
     lijst weg. Zo schuift het hele vak omhoog in plaats van zijn inhoud. */
  margin-bottom: -.75rem;
}
.details__vouw-kop::-webkit-details-marker { display: none; }
/* Boven de eerste rij van een kolom staat geen lijn en dus ook geen ruimte;
   de andere kolommen doen dat via .details__rij:first-child. */
.details__rij:first-child .details__vouw-kop { padding-top: .2em; }
.details__vouw-kop:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

/* Zelfde zetting als een gewoon label (dt), zodat de uitklapper in het rijtje
   past en niet als een knop van elders leest. */
.details__vouw-label {
  font-family: var(--font-meta);
  font-size: var(--ui-xs);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tekst-dim);
}

/* Het aantal staat erbij zodat je ziet wat je opentrekt: drie regels of
   dertig is een ander besluit. Het stond op .6 dekking bovenop --tekst-dim
   en haalde daarmee 1,6:1 op wit: zichtbaar, niet leesbaar. Nu dezelfde
   kleur als het label ernaast, wat het ook is: een nummertje bij een kop,
   geen aparte rang. */
.details__vouw-aantal {
  font-family: var(--font-meta);
  font-size: var(--ui-xs);
  color: var(--tekst-dim);
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}

/* Pijltje van twee lijnen, geen letterteken: dat schaalt mee met de kleur en
   staat op elke telefoon hetzelfde. */
.details__vouw-pijl {
  width: .5rem; height: .5rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-.15em) rotate(45deg);
  opacity: .5;
  transition: transform .5s var(--veer);
  flex: none;
}
/* Alleen het pijltje in de eigen kop: met een losse spatie ertussen zou een
   open buitenblok ook het pijltje van de dichte apparatuur omdraaien. */
details[open] > summary > .details__vouw-pijl { transform: translateY(.1em) rotate(225deg); }

.details__vouw-kop:hover .details__vouw-label,
.details__vouw-kop:hover .details__vouw-aantal { color: var(--tekst); }
.details__vouw-kop:hover .details__vouw-pijl { opacity: .9; }

/* De inhoud schuift open in plaats van te verspringen. ::details-content is
   het vak waar de browser zelf alles buiten de <summary> in zet; dat is het
   enige wat je kunt animeren, want de hoogte ligt niet vooraf vast.

   content-visibility moet mee in de overgang met allow-discrete, anders zet
   de browser de inhoud meteen op verborgen en zie je het dichtgaan niet.

   Dichtklappen gaat op de gewone curve. Een veer die naar nul toe doorschiet
   zou onder nul moeten en dat kan een hoogte niet; dan hapert hij op het
   eind. Alleen het opengaan veert dus. */
.details__vouw details::details-content {
  block-size: 0;
  overflow: hidden;
  transition: block-size .3s cubic-bezier(.16, 1, .3, 1),
              content-visibility .3s allow-discrete;
}
.details__vouw details[open]::details-content {
  block-size: auto;
  transition: block-size .5s var(--veer),
              content-visibility .5s allow-discrete;
}

/* Wie beweging heeft uitgezet krijgt gewoon open en dicht. */
@media (prefers-reduced-motion: reduce) {
  .details__vouw details::details-content,
  .details__vouw details[open]::details-content,
  .details__vouw-pijl { transition: none; }
}

.details__vouw-inhoud {
  padding-bottom: .875rem;
  font-size: .9375rem;
  line-height: 1.5;
}

/* ---------- Showreel in een venster ------------------------------------ */
/* De reel zweeft boven de homepage. Het glas erachter is dat van de drawer:
   dezelfde kleur, blur en dekking, dus dezelfde onderbouwing (zie daar).

   Het venster zelf is onzichtbaar en vult het hele scherm; de speler staat
   erin gecentreerd. Zo is alles naast de speler 'het glas', en een klik daar
   sluit (zie site.js). Maat van de speler: dezelfde rekensom als op
   /showreel/, alleen zonder de nav, want die ligt nu onder het glas. */
.reel-venster {
  --reel-lucht: clamp(1rem, 4vw, 3rem);
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: var(--reel-lucht);
  border: 0;
  background: transparent;
  color: var(--nav-over-beeld);
  overflow: hidden;
  /* Het venster staat in het tekstblok van de banner, en dat laat kliks door
     naar het beeld. Zonder deze regel erft het venster dat, en valt een klik
     op het glas er dwars doorheen. */
  pointer-events: auto;
}
/* Drie rijen: glas, speler, glas. De speler staat zo zelf in het midden, en
   Sluit hangt erboven in de bovenste rij zonder hem omlaag te duwen. */
.reel-venster[open] {
  display: grid;
  grid-template-rows: 1fr auto 1fr;
  justify-items: center;
}
/* Op een telefoon is het scherm hoog en de film plat, en dan oogt het exacte
   midden te laag. De onderste rij is daar groter, zodat de speler optisch in
   het midden staat: het hart van de film komt rond 44% van de hoogte. */
@media (max-width: 809px) {
  .reel-venster[open] { grid-template-rows: 1fr auto 1.3fr; }
}
.reel-venster::backdrop {
  background: linear-gradient(180deg,
    rgb(var(--nav-glas-kleur) / .58) 0%,
    rgb(var(--nav-glas-kleur) / .74) 100%);
  backdrop-filter: blur(28px) saturate(1.4);
  -webkit-backdrop-filter: blur(28px) saturate(1.4);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .reel-venster::backdrop { background: linear-gradient(180deg, #141414 0%, #0a0a0a 100%); }
}

.reel-venster__speler {
  grid-row: 2;
  display: block;
  width: min(100%, calc((100dvh - var(--reel-lucht) * 2 - 3rem) * 16 / 9));
  height: auto;
  aspect-ratio: 16 / 9;
  background: #000;
}

/* Sluit staat rechtsboven de speler, in de letter van het menu. */
.reel-venster__sluit {
  grid-row: 1;
  align-self: end;
  margin-bottom: .75rem;
  font-family: var(--font-meta);
  font-size: var(--ui-nav);
  color: inherit;
  background: none;
  border: 0;
  padding: .25rem 0;
  cursor: pointer;
  opacity: .8;
}
.reel-venster__sluit:hover,
.reel-venster__sluit:focus-visible { opacity: 1; }
/* De knop lijnt uit met de rechterkant van de speler, niet van het scherm. */
.reel-venster[open] > * { width: min(100%, calc((100dvh - var(--reel-lucht) * 2 - 3rem) * 16 / 9)); }
.reel-venster__sluit { text-align: right; }

/* De pagina eronder scrolt niet mee zolang het venster open is. */
html.reel-open { overflow: hidden; }

/* Rustig opkomen: glas en speler vloeien in. Wie minder beweging wil,
   krijgt het venster meteen. */
@media (prefers-reduced-motion: no-preference) {
  .reel-venster[open],
  .reel-venster[open]::backdrop { animation: reel-in .35s ease-out; }
}
@keyframes reel-in { from { opacity: 0; } }
