/* =========================================================
   LAR — Marianne Robben
   Hi-fi prototype huisstijl
   ========================================================= */

@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap');

:root {
  --bg: #E0DFDD;
  --bg-alt: #FFFFFF;
  --ink: #000000;
  --ink-soft: #A5A5A5;
  --rule: #B5B5B3;

  --font-display: 'Bebas Neue', 'Arial Narrow', Impact, sans-serif;
  --font-body:    'Bebas Neue', 'Arial Narrow', Impact, sans-serif;
  /* Lopende tekst (getuned, optie D): Bebas Neue Pro, kleine letters, ruime lh.
     Adobe-kit (iir0tgs) wordt geladen op about.html, contact.html, work-detail.html
     (+ templates.html). NIET op home en werk-overzicht. Valt elders terug op Bebas Neue. */
  --font-body-pro: 'bebas-neue-pro', 'Bebas Neue', 'Arial Narrow', Impact, sans-serif;

  /* Tracking & metrics */
  --letter-display: 0.005em;
  --letter-ui: 0.06em;

  /* Layout */
  --gutter: clamp(20px, 3vw, 48px);
  --rail: clamp(16px, 2.4vw, 36px);

  --menu-h: 72px;

  /* Visible space between menu bottom and first content on every page */
  --page-top: clamp(56px, 9vh, 96px);
}

/* Make --page-top the only thing controlling space above first content */
.about > *:first-child,
.work-index > *:first-child,
.contact > *:first-child,
.detail > *:first-child {
  margin-top: 0;

  --t-fast: 180ms;
  --t-med: 360ms;
  --t-slow: 700ms;
  --ease: cubic-bezier(.2,.7,.2,1);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

body {
  min-height: 100vh;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }

img, video { display: block; max-width: 100%; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  letter-spacing: var(--letter-ui);
}

::selection { background: #000; color: var(--bg); }

/* ---------- TOP MENU ---------- */
.menu {
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--menu-h);
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  padding: 0 var(--rail);
  z-index: 50;
  font-family: var(--font-display);
  font-size: 1.5rem;
  letter-spacing: var(--letter-ui);
  text-transform: uppercase;
  background: linear-gradient(to bottom, var(--bg) 60%, rgba(224,223,221,0));
  pointer-events: none;
}
.menu > * { pointer-events: auto; }

.menu__brand {
  font-size: 1.5rem;
}

/* Rechtergroep: nav + verticale scheidslijn + taalswitch. */
.menu__right {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 22px;
}
.menu__divider {
  width: 1px;
  height: 20px;
  background: var(--rule);
}
.lang {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  color: var(--ink-soft);
  font-size: 1.5rem;
}
.lang button[aria-pressed="true"] {
  color: var(--ink);
}
.lang span.sep {
  color: var(--ink-soft);
}

.menu__nav {
  justify-self: end;
  display: flex;
  gap: 22px;
  align-items: center;
}
.menu__nav a {
  position: relative;
  padding: 4px 0;
  font-size: 1.5rem;
}
.menu__nav a[aria-current="page"]::after,
.menu__nav a:hover::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
}
.menu__nav a:hover { color: var(--ink-soft); }
.menu__nav a[aria-current="page"] { color: var(--ink); }

/* Mobile actions group (work-link + burger). Hidden on desktop. */
.menu__mobile {
  display: none;
  align-items: center;
  gap: 22px;
  justify-self: end;
}
.menu__work {
  position: relative;
  padding: 4px 0;
  font-size: 1.5rem;
}
.menu__work[aria-current="page"]::after,
.menu__work:hover::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: currentColor;
}

/* Burger for mobile */
.menu__burger {
  display: none;
  width: 28px; height: 18px;
  position: relative;
  justify-self: end;
}
.menu__burger span {
  position: absolute;
  left: 0; right: 0;
  height: 1.5px;
  background: var(--ink);
  transition: transform var(--t-med) var(--ease), top var(--t-med) var(--ease), opacity var(--t-fast);
}
.menu__burger span:nth-child(1) { top: 4px; }
.menu__burger span:nth-child(2) { top: 50%; }
.menu__burger span:nth-child(3) { top: 14px; }
body.nav-open .menu__burger span:nth-child(1) { top: 50%; transform: rotate(45deg); }
body.nav-open .menu__burger span:nth-child(2) { opacity: 0; }
body.nav-open .menu__burger span:nth-child(3) { top: 50%; transform: rotate(-45deg); }

/* Mobile nav overlay */
.mobile-nav {
  position: fixed;
  inset: 0;
  background: var(--bg);
  z-index: 40;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  padding: var(--menu-h) var(--rail) 0;
  gap: 24px;
  transform: translateY(-100%);
  transition: transform var(--t-med) var(--ease);
}
body.nav-open .mobile-nav { transform: translateY(0); }
.mobile-nav a {
  font-family: var(--font-display);
  font-size: clamp(48px, 12vw, 96px);
  letter-spacing: 0.01em;
  line-height: 0.9;
}
.mobile-nav .mlang {
  margin-top: 32px;
  color: var(--ink-soft);
  font-size: 14px;
  letter-spacing: var(--letter-ui);
  display: flex; gap: 10px;
}
.mobile-nav .mlang button[aria-pressed="true"] { color: var(--ink); }

/* ---------- PAGE WRAPPER ---------- */
.page {
  padding-top: var(--menu-h);
  min-height: 100vh;
}

.tag-line {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: var(--letter-ui);
  color: var(--ink-soft);
  text-transform: uppercase;
}

.divider {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  align-items: center;
  height: 22px;
  margin: 8vh 0 6vh;
}
.divider::before,
.divider::after,
.divider span {
  content: "";
  height: 1px;
  background: var(--ink);
}
.divider span { background: var(--ink); }
.divider .tick {
  position: relative;
  height: 1px;
  background: var(--ink);
}
.divider .tick::before {
  content: "";
  position: absolute;
  left: 0; top: -4px;
  width: 1px; height: 9px;
  background: var(--ink);
}
.divider .tick:last-child::after {
  content: "";
  position: absolute;
  right: 0; top: -4px;
  width: 1px; height: 9px;
  background: var(--ink);
}

/* ---------- HOME: Hero ---------- */
.hero {
  position: relative;
  min-height: auto;
  padding: 0 var(--rail) 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* Titelgrootte centraal — gebruikt door .hero__title én de foto-overlap/
     hoogteberekening, zodat alles synchroon meeschaalt. */
  --hero-title: clamp(72px, 15vw, 250px);
}

.hero__title {
  position: relative;
  margin: clamp(20px, 4vh, 60px) 0 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--hero-title);
  line-height: 0.85;
  letter-spacing: var(--letter-display);
  text-transform: uppercase;
  white-space: nowrap;
  text-align: center;
  z-index: 5;
  pointer-events: none;
}

/* The marquee runs BEHIND the title */
.hero__marquee {
  position: absolute;
  top: clamp(140px, 22vw, 360px);
  left: 0; right: 0;
  z-index: 2;
  overflow: hidden;
  pointer-events: none;
  display: flex;
}
.hero__marquee-track {
  display: inline-flex;
  flex-shrink: 0;
  gap: 0;
  animation: marquee 40s linear infinite;
  font-family: var(--font-display);
  font-size: clamp(48px, 9vw, 100px);
  line-height: 1;
  letter-spacing: 0.005em;
  white-space: nowrap;
  text-transform: uppercase;
  color: var(--ink);
}
.hero__marquee-track > span {
  padding-right: 0;
}
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.hero__portrait {
  position: relative;
  z-index: 4;
  /* Trek de foto omhoog zodat ~1/3 van de titelhoogte over de foto valt.
     Overlap schaalt mee met de titel-fontgrootte (clamp = zelfde als titel). */
  margin: calc(var(--hero-title) * -0.28 - 20px) auto 0;
  /* Hoogte = de kleinste van (a) de design-breedte omgerekend naar hoogte en
     (b) de beschikbare schermhoogte: 100svh − menu − titel-bovenmarge −
     het stuk titel boven de foto (titelhoogte − overlap). Zo past de foto
     altijd in beeld: niet onder het menu en niet onderin weg. De breedte
     volgt uit de hoogte, dus het kader blijft de 2:3-verhouding huggen. */
  height: min(
    calc(min(56vw, 680px) * 3200 / 2136),
    calc(100svh - var(--menu-h) - clamp(20px, 4vh, 60px) - var(--hero-title) * 0.57 + 8px)
  );
  width: auto;
  max-width: 100%;
  aspect-ratio: 2136 / 3200;
  background: var(--bg-alt);
}

.hero__caption {
  position: static;
  margin: 4vh 0 0;
  width: 180px;
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: var(--letter-ui);
  line-height: 1.45;
  color: var(--ink-soft);
  text-transform: uppercase;
  z-index: 4;
}

/* ---------- HOME: scroll reveal text ---------- */
.reveal {
  /* Bottom-padding geeft scrollruimte zodat de laatste zinnen omhoog kunnen
     scrollen en zwart worden. 24vh i.p.v. 60vh → veel minder lege scroll. */
  padding: 2vh var(--rail) 24vh;
  max-width: 1400px;
}
.reveal__lines {
  font-family: var(--font-display);
  font-size: clamp(36px, 5.4vw, 84px);
  line-height: 1.05;
  letter-spacing: 0.005em;
  text-transform: uppercase;
  /* fallback colour for browsers without background-clip:text support */
  color: var(--ink-soft);
}
.reveal__line {
  /* Spans run inline so the paragraph flows as one continuous block
     of text, wrapping naturally on the container width — no hard
     line breaks. The scroll-reveal still tints each span sequentially. */
  display: inline;
  line-height: 1.05;

  /* Each line is painted by a horizontal gradient that sweeps from
     ink (left, revealed) to ink-soft (right, not yet revealed). The JS
     scroll handler updates --p (0..1) per line. A small soft band
     (--band) keeps the boundary from feeling like a hard cut. */
  --p: 0;
  background-image: linear-gradient(
    to right,
    var(--ink)      0%,
    var(--ink)      calc(var(--p) * 100%),
    var(--ink-soft) calc(var(--p) * 100%),
    var(--ink-soft) 100%
  );
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  will-change: background-image;
}
.reveal__line:last-child { margin-bottom: 0; }

/* Browsers without background-clip:text fall back to a solid color. */
@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .reveal__line {
    background-image: none;
    color: var(--ink-soft);
    -webkit-text-fill-color: currentColor;
  }
}

/* ---------- ABOUT ---------- */
.about {
  padding: var(--page-top) var(--rail) 16vh;
  max-width: 920px;
  margin: 0;
}
.about__eyebrow {
  font-family: var(--font-display);
  font-weight: 400;
  /* Kop duidelijk groter dan de body (body = clamp(22px, 2.6vw, 36px)). */
  font-size: clamp(32px, 4vw, 54px);
  line-height: 0.95;
  letter-spacing: var(--letter-ui);
  color: var(--ink);
  text-transform: uppercase;
  margin-bottom: 4vh;
}
.about__body {
  font-family: var(--font-display);
  font-size: clamp(22px, 2.6vw, 36px);
  line-height: 1.3;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
.about__body p { margin: 0 0 1.4em; }
.about__body p:last-child { margin-bottom: 0; }

/* ---------- WORK INDEX ---------- */
.work-index {
  padding: var(--page-top) var(--rail) 12vh;
  position: relative;
  min-height: 100vh;
}
.work-index__head {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-bottom: 4vh;
  font-family: var(--font-display);
  letter-spacing: var(--letter-ui);
  text-transform: uppercase;
  font-size: clamp(20px, 2.4vw, 32px);
  color: var(--ink);
}
.work-index__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  /* Zelfde prominente kopmaat als de About-h1 — consistent over pagina's. */
  font-size: clamp(32px, 4vw, 54px);
  line-height: 0.95;
}
.work-list {
  list-style: none;
  margin: 0; padding: 0;
  max-width: 60%;
}
.work-list li {
  border-top: 1px solid var(--rule);
}
.work-list li:last-child { border-bottom: 1px solid var(--rule); }
.work-list a {
  display: grid;
  grid-template-columns: 80px 1fr auto;
  gap: 24px;
  align-items: baseline;
  padding: clamp(14px, 2.2vh, 22px) 0;
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  transition: color var(--t-fast) var(--ease);
}
.work-list .num {
  /* Jaartal even groot als Medium (.cat) op het werk-overzicht. */
  font-size: clamp(14px, 1.4vw, 20px);
  letter-spacing: var(--letter-ui);
  color: var(--ink-soft);
  /* Hover: num + title gliden samen 10px naar rechts. Transform (geen
     padding) zodat het GPU-versneld is en niet schokkerig voelt. Ease
     is een zachte soft-out — snel begin, lange uitloop. */
  transition: transform 600ms cubic-bezier(0.19, 1, 0.22, 1), color 600ms cubic-bezier(0.19, 1, 0.22, 1);
  will-change: transform;
}
.work-list .title {
  font-size: clamp(28px, 4vw, 56px);
  line-height: 1;
  transition: transform 600ms cubic-bezier(0.19, 1, 0.22, 1), color 600ms cubic-bezier(0.19, 1, 0.22, 1);
  will-change: transform;
}
.work-list .cat {
  font-size: clamp(14px, 1.4vw, 20px);
  letter-spacing: var(--letter-ui);
  color: var(--ink-soft);
  /* .cat blijft rechts staan als anker — alleen kleur wisselt. */
  transition: color var(--t-fast) var(--ease);
}
.work-list a:hover .num,
.work-list a:hover .title { transform: translateX(10px); }
.work-list a:hover .title { color: var(--ink); }
.work-list a:hover .num,
.work-list a:hover .cat { color: var(--ink); }

/* Empty state — alleen zichtbaar als window.LAR_WORKS leeg is */
.work-list__empty {
  border-top: 1px solid var(--ink);
  border-bottom: 1px solid var(--ink);
  padding: clamp(40px, 8vh, 80px) 0;
  font-family: var(--font-body);
  font-size: clamp(18px, 1.8vw, 26px);
  letter-spacing: var(--letter-ui);
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* Detail page — werk niet gevonden fallback */
.detail__empty {
  padding: clamp(40px, 8vh, 80px) 0;
  max-width: 60ch;
}
.detail__empty p {
  font-family: var(--font-body);
  font-size: clamp(16px, 1.4vw, 22px);
  letter-spacing: var(--letter-ui);
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: clamp(16px, 2vh, 24px) 0 0;
  line-height: 1.4;
}

/* Hover floating image (desktop) */
.work-hover {
  position: fixed;
  pointer-events: none;
  z-index: 30;
  width: clamp(220px, 24vw, 360px);
  opacity: 0;
  transform: translate(-50%, -50%) scale(.96);
  transition: opacity 220ms var(--ease), transform 320ms var(--ease);
  background: var(--bg-alt);
  box-shadow: 0 30px 60px -30px rgba(0,0,0,0.25);
  will-change: transform, opacity;
}
.work-hover.is-on {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
.work-hover.is-landscape { width: clamp(280px, 30vw, 440px); }
/* Het hover-kader volgt de echte verhouding van de thumbnail (hoogte volgt
   uit de foto) — geen witruimte meer. Een vaste verhouding geldt alleen nog
   als er een placeholder (geen foto) in zit. */
.work-hover img { display: block; width: 100%; height: auto; }
.work-hover .ph { width: 100%; height: 100%; }
.work-hover:has(.ph) { aspect-ratio: 3 / 4; }
.work-hover.is-landscape:has(.ph) { aspect-ratio: 4 / 3; }

/* ---------- WORK DETAIL ---------- */
.detail {
  padding: var(--page-top) var(--rail) 10vh;
  max-width: 1500px;
  margin: 0 auto;
}
.detail__back {
  display: flex;
  width: max-content;
  align-items: center;
  gap: 8px;
  line-height: 1;
  font-family: var(--font-display);
  font-size: 12px;
  letter-spacing: var(--letter-ui);
  color: var(--ink-soft);
  text-transform: uppercase;
  margin-bottom: 8vh;
}
.detail__back:hover { color: var(--ink); }

/* --- Body grid: media + text, side by side, not sticky --- */
.detail__grid {
  display: grid;
  gap: clamp(28px, 5vw, 80px);
  align-items: start;
}
.detail__grid--portrait {
  grid-template-columns: minmax(0, 5fr) minmax(280px, 4fr);
}
.detail__grid--landscape {
  grid-template-columns: minmax(0, 6fr) minmax(280px, 3fr);
}

/* Title sits with baseline flush against the top of the image,
   left-aligned with the image. */
.detail__media-col {
  display: flex;
  flex-direction: column;
}
.detail__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(56px, 9vw, 168px);
  line-height: 0.72;
  letter-spacing: var(--letter-display);
  text-transform: uppercase;
  /* line-height 0.72 trims the box above the glyphs. De bottom-margin
     bepaalt de ruimte ONDER de titel — die ruimte wordt door alignText()
     én alignPager() opgepakt zodat zowel de media als de tekstkolom
     mee zakken. Pas hier aan om de adem boven het werk te veranderen. */
  margin: 0 0 clamp(24px, 3.5vh, 56px);
  padding: 0;
  /* Titel altijd op één regel — geen automatische line breaks. */
  white-space: nowrap;
}
.detail__title + .detail__media {
  margin-top: 0;
}

.detail__media {
  background: var(--bg);
  position: relative;
  overflow: hidden;
}
/* Portret: hoogte is leidend. Wanneer er een echte foto in zit
   laten we het kader meeschalen met de viewport-hoogte i.p.v. een
   vaste 3:4-verhouding op te leggen — zo wordt de foto nooit
   bijgesneden en is de pagina rustig.
   Zonder afbeelding (placeholder) blijft 3:4 als visueel anker. */
/* Pre-JS fallback-verhoudingen + volle breedte. De échte maat zet JS
   (sizeActiveMedia) in px op .detail__media — iOS-veilig en exact passend om het
   actieve beeld, zodat er nooit zwarte randen ontstaan. width:100% voorkomt dat
   de box naar 0 krimpt vóórdat JS heeft gemeten (de slides zijn absoluut
   gepositioneerd en geven zelf geen breedte). */
.detail__media--portrait { aspect-ratio: 3 / 4; width: 100%; }
.detail__media--landscape { aspect-ratio: 4 / 3; width: 100%; }

/* Centreren: zodra JS een px-breedte < kolom zet, centreert margin-inline:auto
   de box (werkt ook op een flex-item). Standaard (≤1024) staat alles gecentreerd. */
.detail__media { margin-inline: auto; }
@media (min-width: 1025px) {
  /* Desktop: losse media links uitgelijnd langs titel/tekst. */
  .detail__media-col:not(.detail__media-col--carousel) .detail__media { margin-inline: 0; }
  /* Desktop: carrousel óók links uitgelijnd, met een linker chevron-baan zodat
     de linker chevron op de titel-links uitkomt; rechts vrije ruimte (auto). */
  .detail__media-col--carousel .detail__media {
    margin-left: calc(var(--chev-w) + var(--chev-gap));
    margin-right: auto;
  }
}

/* Body text top-aligns to image top via JS (sets --text-offset).
   First line's cap-top sits on image\u2019s top edge. Pre-JS fallback
   is sized off the title's font metrics. */
.detail__text {
  padding-top: var(--text-offset, calc(clamp(56px, 9vw, 168px) * 0.72));
  /* Horizontale uitlijning: content blok schuift naar het medium blok toe
     (JS zet --text-shift). De transitie wordt pas ná de eerste plaatsing
     ingeschakeld (.is-shift-animated), zodat er geen slide-in is bij laden. */
  transform: translateX(var(--text-shift, 0px));
}
.detail__text.is-shift-animated {
  transition: transform 480ms cubic-bezier(0.65, 0, 0.35, 1);
}
.detail__body {
  font-family: var(--font-body-pro);
  font-size: 18px;
  line-height: 1.58;
  letter-spacing: 0.006em;
  color: var(--ink);
  max-width: 42ch;
}
.detail__body p { margin: 0 0 1em; }
.detail__body p:last-child { margin-bottom: 0; }

/* Meta as horizontal-ruled key/value rows — staat nu BOVEN de body, dus
   geen marge erboven en de gap eronder (richting de body). */
.detail__meta {
  margin-top: 0;
  margin-bottom: clamp(20px, 3vh, 32px);
  display: flex;
  flex-direction: column;
  font-family: var(--font-display);
  font-size: 18px;
  letter-spacing: var(--letter-ui);
  text-transform: uppercase;
  max-width: 44ch;
}
.detail__meta-row {
  display: grid;
  grid-template-columns: minmax(80px, 1fr) 2fr;
  gap: 16px;
  padding: 10px 0;
  border-top: 1px solid var(--rule);
}
.detail__meta-row:last-child { border-bottom: 1px solid var(--rule); }
.detail__meta-key { color: var(--ink-soft); }
.detail__meta-val { color: var(--ink); }

/* Subtle inline contact link, not a button */
.detail__contact {
  margin-top: clamp(28px, 4vh, 40px);
  display: inline-block;
  font-family: var(--font-display);
  font-size: 13px;
  letter-spacing: var(--letter-ui);
  text-transform: uppercase;
  color: var(--ink-soft);
}
.detail__contact em {
  font-style: normal;
  color: var(--ink);
  border-bottom: 1px solid var(--ink);
  padding-bottom: 1px;
  margin-left: 4px;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.detail__contact:hover em {
  color: var(--ink-soft);
  border-color: var(--ink-soft);
}

/* ===== CAROUSEL =====
   Slides crossfade in place. Navigation chevrons sit OUTSIDE
   the media block, in the gutters \u2014 image stays untouched. */
.carousel {
  position: relative;
  width: 100%;
  height: 100%;
}
.carousel__viewport {
  position: relative;
  width: 100%; height: 100%;
  overflow: hidden;
}
.carousel__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-med) var(--ease);
}
.carousel__slide.is-on { opacity: 1; pointer-events: auto; }

/* Chevron buttons \u2014 pure CSS, large, in the page margin/gutter.
   The media-col is .detail__media-col; chevrons live there as
   absolutely positioned siblings of .detail__media. */
.carousel__btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--ink);
  transition: opacity var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
  z-index: 2;
}
.carousel__btn[disabled] { opacity: 0.25; cursor: default; }
.carousel__btn:not([disabled]):hover { color: var(--ink-soft); }

/* Dubbele chevron \u2014 twee dunne CSS-driehoekjes, geen glyph-fonts/SVG. */
.carousel__btn::before,
.carousel__btn::after {
  content: "";
  width: 13px;
  height: 13px;
  border-top: 1px solid currentColor;
  border-right: 1px solid currentColor;
}
.carousel__btn--prev::before,
.carousel__btn--prev::after { transform: rotate(-135deg); }
.carousel__btn--next::before,
.carousel__btn--next::after { transform: rotate(45deg); }
/* tweede driehoek overlapt de eerste licht \u2192 dubbele chevron */
.carousel__btn::after { margin-left: -7px; }

/* Place chevrons in the LEFT margin and RIGHT margin of the media block.
   Chevrons live as siblings of .carousel inside .detail__media. We make
   .detail__media position:relative (already true) and let buttons sit
   outside the box via negative offsets \u2014 buttons are NOT clipped because
   they're outside the overflow:hidden viewport. */
.detail__media {
  /* allow chevrons to render outside */
  overflow: visible;
}
.detail__media .carousel__viewport {
  overflow: hidden;
}
/* Chevrons ALTIJD buiten het beeld (links/rechts), op álle breedtes. Het beeld
   staat gecentreerd in de kolom (align-self:center) en JS reserveert links/rechts
   een chevron-baan in de breedte-berekening, dus de banen zijn symmetrisch. De
   knopbreedte volgt --chev-w zodat knop en gereserveerde baan gelijk lopen. */
.carousel__btn { width: var(--chev-w, 44px); }
.carousel__btn--prev { left: auto; right: calc(100% + var(--chev-gap)); }
.carousel__btn--next { right: auto; left: calc(100% + var(--chev-gap)); }

@media (max-width: 1024px) {
  .carousel__btn { height: 56px; }
}

/* ===== CAROUSEL: pagination dots ===== */
.carousel__dots {
  position: absolute;
  top: calc(100% + clamp(14px, 2vh, 22px));
  left: 0; right: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  /* 6px padding per dot + gap 0 = 12px tussen de rondjes. */
  gap: 0;
  z-index: 2;
}
.carousel__dot {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  margin: 0;
  padding: 6px;            /* tap-doel los van de visuele dot */
  line-height: 0;
  cursor: pointer;
}
.carousel__dot::before {
  content: "";
  display: block;
  width: 9px; height: 9px;
  border-radius: 50%;
  border: 1px solid var(--ink);
  background: transparent;                 /* open rondje = inactief */
  transition: background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.carousel__dot:hover::before { background: var(--ink-soft); }
.carousel__dot.is-active::before { background: var(--ink); transform: scale(1.15); } /* gevuld = actief */
.carousel__dot:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }

/* Reserveer ruimte onder het beeld voor de dots, zodat de pager-uitlijning
   (die de onderkant van de mediakolom meet) er automatisch rekening mee houdt.
   --chev-w/--chev-gap definiëren de "chevron-baan" naast het beeld. */
.detail__media-col--carousel {
  --chev-w: 44px;
  --chev-gap: 14px;
  padding-bottom: clamp(48px, 7vh, 64px);
}

@media (max-width: 720px) {
  .carousel__dot { padding: 11px; }       /* groter tap-doel op mobiel */
  /* Compactere chevron-baan op telefoon zodat er meer beeldbreedte overblijft. */
  .detail__media-col--carousel { --chev-w: 28px; --chev-gap: 6px; }
  .carousel__btn { height: 48px; }
}

/* Detail next/prev — with small preview thumbnails.
   Sits below the grid (full page width). JS aligns its top edge to the
   bottom of .detail__media-col via --pager-offset, so when the media
   shrinks (carousel landscape slide, short videos) the pager rides
   up with it. Falls back to a fixed clamp when JS hasn't run yet. */
.detail__pager {
  margin-top: var(--pager-offset, clamp(80px, 14vh, 180px));
  padding-top: 24px;
  border-top: 1px solid var(--ink);
  display: grid;
  /* Three slots: prev | overview-anchor | next.
     Overview is content-sized (auto) so it visually centers without
     pushing the side links inward. */
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  gap: clamp(24px, 4vw, 64px);
  font-family: var(--font-display);
  letter-spacing: var(--letter-ui);
  text-transform: uppercase;
}

/* Center "Alle werken/" link — plain text, no thumb. Slightly
   smaller than the prev/next titles so the side links keep their
   visual weight; vertically aligned with the directional labels above
   the thumbnails. */
.detail__pager-home {
  align-self: center;
  justify-self: center;
  font-size: clamp(14px, 1.4vw, 18px);
  letter-spacing: var(--letter-ui);
  color: var(--ink-soft);
  text-decoration: none;
  padding: 12px 8px;
  transition: color var(--t-fast) var(--ease);
  white-space: nowrap;
}
.detail__pager-home:hover { color: var(--ink); }
.detail__pager-link {
  display: grid;
  grid-template-columns: 64px 1fr;
  gap: 16px;
  align-items: center;
  padding: 12px 0;
}
.detail__pager-link--next {
  grid-template-columns: 1fr 64px;
  text-align: right;
  justify-self: end;
}
.detail__pager-thumb {
  width: 64px;
  aspect-ratio: 3 / 4;
  background: var(--bg-alt);
  overflow: hidden;
}
.detail__pager-link--next .detail__pager-thumb { order: 2; }
.detail__pager-thumb .ph { padding: 0; }
.detail__pager-thumb .ph__label { display: none; }
/* Beeld verticaal centreren in het 3:4-kader: een liggend plaatje plakt dan
   niet bovenaan maar staat netjes in het midden (lijnt mooier uit). */
.detail__pager-thumb .ph > img { object-position: left center; }

.detail__pager-meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.detail__pager-dir {
  font-size: 11px;
  color: var(--ink-soft);
  transition: color var(--t-fast) var(--ease);
}
.detail__pager-link:hover .detail__pager-dir { color: var(--ink); }
.detail__pager-title {
  font-size: clamp(16px, 1.6vw, 22px);
  letter-spacing: 0.01em;
  color: var(--ink);
  line-height: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- CONTACT ---------- */
.contact {
  padding: var(--page-top) var(--rail) 10vh;
  min-height: calc(100vh - var(--menu-h));
  max-width: 1500px;
  margin: 0 auto;
}
/* H1 → content: gelijk aan About/Work (4vh). */
.contact__title { margin-bottom: 4vh; }
/* De twee kolommen: quote → bio links (rij 1-2), rechterkolom vast op rij 2
   zodat de intro-tekst aan de bovenkant uitlijnt met de bio-tekst links. */
.contact__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: clamp(40px, 8vw, 120px);
  row-gap: clamp(14px, 2vh, 22px);
  align-items: start;
}
.contact__lede { grid-column: 1; grid-row: 1; }
.contact__bio  { grid-column: 1; grid-row: 2; }
.contact__col {
  grid-column: 2;
  grid-row: 2;
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: clamp(24px, 3.5vh, 44px);
}
.contact__title {
  font-family: var(--font-display);
  font-weight: 400;
  /* Paginakop-stijl, gelijk aan About/Work. */
  font-size: clamp(32px, 4vw, 54px);
  line-height: 0.95;
  letter-spacing: var(--letter-ui);
  text-transform: uppercase;
}
.contact__body {
  font-family: var(--font-display);
  font-size: clamp(16px, 1.4vw, 22px);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  line-height: 1.45;
  margin: 0;
}
/* De quote: groter en opener dan de bio eronder. Gratis Bebas, kapitaal, geen italic. */
.contact__lede {
  font-family: var(--font-display);
  font-size: 36px;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  line-height: 1.1;
  margin: 0;
}
/* Linkerkolom-bio op gelijke maat als de quote. */
.contact__bio { font-size: 36px; }
/* Foto links van de intro-tekst; de foto stretcht mee zodat 'ie ongeveer even
   hoog wordt als de tekst ernaast (cirkel, breedte volgt de hoogte). */
.contact__media {
  display: flex;
  align-items: flex-start;
  gap: clamp(20px, 3vw, 44px);
}
.contact__media .contact__body { flex: 1; min-width: 0; }
.contact__photo {
  margin: 0;
  flex: none;
  width: clamp(108px, 12vw, 158px);
  aspect-ratio: 1 / 1;
}
.contact__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}
/* E-mail onder de rechterkolom, even breed als die kolom; lijn boven én onder. */
.contact__list {
  margin: 0;
  display: flex; flex-direction: column;
}
.contact__list a {
  display: flex; justify-content: space-between;
  gap: 24px;
  font-family: var(--font-display);
  font-size: 18px;
  letter-spacing: var(--letter-ui);
  text-transform: uppercase;
  border-top: 1px solid var(--ink);
  border-bottom: 1px solid var(--ink);
  padding: 16px 0;
}
.contact__list a span:first-child { white-space: nowrap; }
.contact__list a span:last-child { white-space: nowrap; text-align: right; }
.contact__list a:hover { padding-left: 12px; }

/* ---------- PLACEHOLDERS ---------- */
.ph {
  position: relative;
  width: 100%;
  height: 100%;
  background:
    repeating-linear-gradient(
      135deg,
      rgba(0,0,0,0.05) 0 1px,
      transparent 1px 8px
    ),
    var(--bg-alt);
  display: grid;
  place-items: center;
  color: var(--ink-soft);
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.05em;
  text-align: center;
  text-transform: uppercase;
  padding: 12px;
}
.ph[data-tone="warm"] {
  background:
    repeating-linear-gradient(135deg, rgba(0,0,0,0.04) 0 1px, transparent 1px 8px),
    #d8c9b8;
}
.ph[data-tone="blue"] {
  background:
    repeating-linear-gradient(135deg, rgba(0,0,0,0.05) 0 1px, transparent 1px 8px),
    #b9c9d4;
}
.ph[data-tone="grey"] {
  background:
    repeating-linear-gradient(135deg, rgba(0,0,0,0.06) 0 1px, transparent 1px 8px),
    #cfcfcd;
}
.ph[data-tone="moss"] {
  background:
    repeating-linear-gradient(135deg, rgba(0,0,0,0.05) 0 1px, transparent 1px 8px),
    #b5b9a6;
}
.ph[data-tone="rose"] {
  background:
    repeating-linear-gradient(135deg, rgba(0,0,0,0.04) 0 1px, transparent 1px 8px),
    #d8c1bd;
}
.ph[data-tone="ink"] {
  background:
    repeating-linear-gradient(135deg, rgba(255,255,255,0.04) 0 1px, transparent 1px 8px),
    #2a2a2a;
  color: rgba(255,255,255,0.7);
}
.ph__label {
  position: absolute;
  bottom: 10px; left: 12px;
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 10px;
  letter-spacing: 0.06em;
  color: rgba(0,0,0,0.55);
  text-transform: uppercase;
}
.ph[data-tone="ink"] .ph__label { color: rgba(255,255,255,0.6); }

/* Wanneer er een echte foto in de .ph zit moet de achtergrond ALTIJD
   de paginakleur zijn — ook bij tone="ink" (zwart) of warme tones,
   anders zie je een gekleurde letterbox rond foto's met afwijkende
   ratio. Specificiteit [0,2,1] >= .ph[data-tone="ink"], dus dit wint
   omdat het hier later in de stylesheet staat. */
.ph[data-tone]:has(> img) {
  background: var(--bg);
}

/* Detail-pagina: lege placeholders (geen <img>) krijgen de paginakleur
   i.p.v. de tone-pattern. Voorkomt dat een nog-niet-gevulde slide
   (bv. een video die later komt) als opvallend gekleurd of zwart blok
   tussen de echte foto's verschijnt. */
.detail__media .ph:not(:has(> img)) {
  background: var(--bg);
  color: var(--ink-soft);
}
.detail__media .ph:not(:has(> img)) .ph__label { color: var(--ink-soft); }

/* When .ph contains a real <img>, hide the patterned background tone. */
.ph:has(> img) {
  /* Achtergrond mee-ademen met de pagina i.p.v. de witte alt-bg of de
     tone-kleur. Letterbox-ruimte rond een afbeelding die niet exact in
     het kader past valt zo onzichtbaar weg tegen de paginakleur. */
  background: var(--bg);
  padding: 0;
}
.ph > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* Foto's worden NOOIT bijgesneden — we tonen het hele beeld.
     Bij niet-passende verhoudingen verschijnt witruimte links/rechts
     of boven/onder; dat is netter dan een afgekapte foto. */
  object-fit: contain;
  object-position: left top;
  display: block;
}
.ph:has(> img) .ph__label { display: none; }

/* Echte <video> in een .ph: zelfde gedrag als een foto — paginakleur als
   achtergrond, geen padding, beeld volledig in beeld (niet bijsnijden),
   en de placeholder-tekst verbergen. */
.ph:has(> video) {
  background: var(--bg);
  padding: 0;
}
.ph > video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  /* Box matcht de ware ratio (JS), dus geen letterbox; var(--bg) i.p.v. #000
     zodat een eventueel laad-moment niet als zwart vlak oogt. */
  background: var(--bg);
}
.ph:has(> video) .ph__label { display: none; }

/* ---------- FOTO VERGROTEN (lightbox) ----------
   Alleen echte foto's op de detailpagina zijn vergrootbaar. Video's hebben
   geen <img> in hun .ph, dus ze worden hier — en in de JS — vanzelf
   overgeslagen (geldt ook voor film-only pagina's en films in de carousel). */
.detail__media .ph:has(> img) { cursor: zoom-in; }

/* Vergrootknop in de foto: donkere cirkel met hoek-haken (zie ontwerp).
   Desktop: verschijnt op hover. Mobiel (≤720px): altijd zichtbaar. */
.ph__zoom {
  position: absolute;
  top: 14px; right: 14px;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.2);
  color: #fff;
  cursor: zoom-in;
  opacity: 0;
  z-index: 2;
}
@media (prefers-reduced-motion: no-preference) {
  .ph__zoom { transition: opacity var(--t-fast) var(--ease); }
}
.ph__zoom svg { width: 20px; height: 20px; display: block; }
.detail__media .ph:hover .ph__zoom,
.ph__zoom:focus-visible { opacity: 1; }
@media (max-width: 720px) {
  .ph__zoom {
    opacity: 1;
    width: 30px; height: 30px;
    top: 10px; right: 10px;
  }
  .ph__zoom svg { width: 16px; height: 16px; }
}

/* Volledige-viewport overlay met zwarte achtergrond. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: var(--bg);
  display: grid;
  place-items: center;
  cursor: zoom-out;
}
.lightbox[hidden] { display: none; }
.lightbox__img {
  /* Altijd een smalle marge rondom de foto (net zichtbaar) — de foto raakt
     nooit de viewport-rand. */
  max-width: calc(100vw - 16px);
  max-height: calc(100vh - 16px);
  width: auto; height: auto;
  object-fit: contain;
  display: block;
}
/* Kruissymbool rechtsboven om te sluiten — even groot als het vergroot-icoon
   (20px), in CSS opgebouwd uit twee gekruiste lijnen. Boven- en rechtruimte
   gelijk. De hele lightbox sluit op klik, dus het kleine vak volstaat. */
.lightbox__close {
  position: fixed;
  top: 22px; right: 22px;
  width: 20px; height: 20px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  z-index: 1001;
}
.lightbox__close::before,
.lightbox__close::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 28px;          /* 20 × √2 → de punten reiken tot de hoeken van het 20px-vak */
  height: 1.67px;       /* even dik als de icoon-lijnen (stroke 2 @ 24-viewBox, op 20px) */
  background: var(--ink);
  transform: translate(-50%, -50%) rotate(45deg);
}
.lightbox__close::after { transform: translate(-50%, -50%) rotate(-45deg); }
/* Mobiel: kruis even groot als het mobiele vergroot-icoon (16px), lijnen even
   dik. Ná de basis-regel zodat deze wint binnen de breakpoint. */
@media (max-width: 720px) {
  .lightbox__close { width: 16px; height: 16px; }
  .lightbox__close::before,
  .lightbox__close::after { width: 23px; height: 1.33px; }
}
body.lightbox-open { overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .lightbox:not([hidden]) { animation: lb-fade-in var(--t-fast) var(--ease); }
}
@keyframes lb-fade-in { from { opacity: 0; } }

/* ---------- VIDEO indicator ---------- */
.video-mark {
  position: absolute;
  top: 14px; left: 14px;
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: var(--letter-ui);
  text-transform: uppercase;
  color: var(--ink);
  background: var(--bg-alt);
  padding: 4px 8px;
}
.video-mark::before {
  content: "";
  width: 0; height: 0;
  border-left: 6px solid var(--ink);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
}

/* ---------- LAYOUT VARIANTS for .detail__media ---------- */
/* Single video: 16:9 letterbox */
.detail__media--video {
  aspect-ratio: 16 / 9;
  width: 100%;
}

/* Dual video: two vertical videos stacked. Niet door JS gemaatvoerd; blijft op
   volle breedte met eigen 2×16:9-grid. */
.detail__media--dual-video {
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: clamp(8px, 1.2vh, 16px);
  background: transparent;
  aspect-ratio: auto;
  width: 100%;
}
.detail__media--dual-video .detail__video-cell {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--bg-alt);
  overflow: hidden;
}

/* ---------- RESPONSIVE ---------- */
@media (max-width: 1024px) {
  .work-list { max-width: 80%; }
  .work-list a { grid-template-columns: 60px 1fr auto; }
  .detail__grid--portrait,
  .detail__grid--landscape {
    grid-template-columns: 1fr;
  }
  .detail__text { padding-top: 8px; margin-top: 0; }
  .detail__meta,
  .detail__body { max-width: none; }
  /* Gestapelde layout: alignPager staat uit (≤1024), dus de pager valt terug op
     de grote desktop-marge clamp(80px,14vh,180px). Hier een rustige, kleinere
     afstand tussen de tekst en de werk-navigatie. */
  .detail__pager { margin-top: clamp(32px, 6vh, 56px); }
  .detail__header {
    grid-template-columns: 1fr;
    align-items: start;
  }
  .detail__sub { text-align: left; white-space: normal; }
  .contact__grid { grid-template-columns: 1fr; align-items: start; }
  .contact__lede,
  .contact__bio,
  .contact__col { grid-column: 1; grid-row: auto; }
}

/* Tablet: media-kolom bovenaan, daaronder meta (1/3) en body (2/3) naast elkaar. */
@media (min-width: 721px) and (max-width: 1024px) {
  .detail__text {
    display: grid;
    grid-template-columns: 1fr 2fr;
    gap: clamp(24px, 4vw, 48px);
    align-items: start;
  }
  .detail__meta { margin-bottom: 0; }
}

@media (max-width: 720px) {
  :root { --menu-h: 52px; --rail: 16px; }
  .menu__right { display: none; }
  .menu__mobile { display: flex; }
  .menu__burger { display: block; }

  .hero__caption { width: 60vw; bottom: 6vh; }
  .hero__portrait { width: 60vw; height: auto; }

  .work-list { max-width: 100%; }
  .work-list a { grid-template-columns: 48px 1fr; row-gap: 4px; }
  .work-list .num { font-size: 18px; }
  .work-list .cat { grid-column: 2; font-size: 18px; }
  .work-list .title { font-size: clamp(28px, 9vw, 44px); }

  .work-hover { display: none; }

  .reveal__lines { font-size: clamp(28px, 8vw, 56px); }

  /* Mobiel: alle contact-tekst gelijk aan Over (22px). */
  .contact__lede,
  .contact__body,
  .contact__list a { font-size: 22px; }
  .contact__lede { max-width: none; }
  .contact__media { flex-direction: column; align-items: flex-start; gap: clamp(20px, 4vh, 32px); }
  .contact__media .contact__body { max-width: none; }
  .contact__photo { align-self: flex-start; width: clamp(130px, 42vw, 180px); aspect-ratio: 1 / 1; }
  .contact__photo img { width: 100%; height: 100%; }

  /* Mobiel: lange titels mogen over meerdere regels afbreken (geen horizontale
     overflow meer → de rechter --rail-marge blijft behouden). Iets ruimere
     line-height dan de strakke 0.72 zodat twee regels niet op elkaar plakken. */
  .detail__title { font-size: clamp(48px, 14vw, 96px); white-space: normal; line-height: 0.82; }
  /* Meta-regels: alle rijen delen één grid, zodat de labelkolom zo breed
     wordt als het langste label ('Medium') en de waarden links uitlijnen.
     display:contents laat de rijen dat gedeelde grid delen; de scheidings-
     lijnen verhuizen daarom naar de cellen, met padding-right op het label
     voor de nette tussenruimte. */
  .detail__meta { display: grid; grid-template-columns: max-content 1fr; }
  .detail__meta-row { display: contents; }
  .detail__meta-key,
  .detail__meta-val { border-top: 1px solid var(--rule); padding: 10px 0; }
  .detail__meta-key { padding-right: 14px; }
  .detail__meta-row:last-child .detail__meta-key,
  .detail__meta-row:last-child .detail__meta-val { border-bottom: 1px solid var(--rule); }
  /* Mobile: pager op één horizontale lijn — thumbnail + richting/pijl;
     de werktitel wordt verborgen zodat lange titels de rij niet breken.
     (.detail__pager houdt de basis '1fr auto 1fr', alleen de gap krimpt.) */
  .detail__pager { gap: clamp(10px, 3vw, 20px); }
  .detail__pager-link { grid-template-columns: 44px 1fr; gap: 10px; }
  .detail__pager-link--next { grid-template-columns: 1fr 44px; }
  .detail__pager-thumb { width: 44px; }
  .detail__pager-title { display: none; }
  /* Alleen de pijl zichtbaar; richtinglabel blijft in de DOM voor
     screenreaders (visueel verborgen) zodat de link een naam houdt. */
  .detail__pager-dirlabel {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  .detail__pager-arrow { font-size: 16px; color: var(--ink); }
  .detail__pager-home { font-size: 13px; padding: 12px 4px; }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  .hero__marquee-track { animation: none; }
  * { transition: none !important; }
}
