/* Componentenbibliotheek Ares Flow
 *
 * Samengesteld door bouw-componenten.js uit de vier categorieën.
 * Niet met de hand wijzigen; pas het bronbestand in componenten/<categorie>/ aan.
 *
 * Laadt na het tokenbestand van het project, want elke regel hier leest een rol.
 * De volgorde is layouts, atoms, blocks, sections: van structuur naar samenstelling,
 * zodat een sectie een atom kan overschrijven en niet andersom.
 */
/* LAYOUTS
 *
 * Structuur zonder eigen inhoud of kleur. Deze vier bepalen waar dingen staan;
 * ze bepalen nooit hoe iets eruitziet.
 *
 * Regel die hier vandaan komt: een sectie draagt de achtergrond en de verticale
 * ruimte, de container draagt de breedte en de zijmarges, en stack of grid draagt
 * de ruimte tussen de onderdelen. Zolang dat gescheiden blijft, kan een sectie
 * niet uit de pas lopen met de rest van de pagina.
 */

/* ---------- container ----------
 * Staat ook in tokens.css, omdat de maten uit het thema komen. Hier alleen de
 * varianten die er niets aan de breedte veranderen. */

.container--smal { max-width: 720px; }
.container--breed { max-width: none; }

/* ---------- section ----------
 * De volle-breedte plak. Draagt achtergrond en verticale ruimte, verder niets.
 * Nooit padding-inline hier; dat is het werk van de container. */

.section {
  padding-block: var(--sp-4);
}
.section--kort { padding-block: var(--sp-3); }
.section--lang { padding-block: calc(var(--sp-4) * 1.5); }

.section--alt { background: var(--color-bg-alt); }
.section--surface { background: var(--color-surface); }
.section--inverse {
  background: var(--color-bg-inverse);
  color: var(--color-text-inverse);
}

/* Twee secties met dezelfde achtergrond naast elkaar zouden dubbele ruimte
 * geven; de tweede haalt zijn bovenruimte weg zodat het één vlak blijft. */
.section--alt + .section--alt,
.section--inverse + .section--inverse,
.section--surface + .section--surface { padding-block-start: 0; }

/* ---------- stack ----------
 * Verticale ruimte tussen kinderen, zonder marges op de kinderen zelf. Het
 * lobotomized owl-patroon: alleen ruimte tússen elementen, dus geen extra ruimte
 * aan de boven- of onderkant die je later moet wegpoetsen. */

.stack > * + * { margin-block-start: var(--sp-1); }
.stack--dicht > * + * { margin-block-start: var(--sp-0); }
.stack--ruim > * + * { margin-block-start: var(--sp-2); }
.stack--zeer-ruim > * + * { margin-block-start: var(--sp-3); }

/* ---------- grid ----------
 * Kolommen die vanzelf terugvallen. auto-fit met minmax betekent dat een
 * breakpoint niet nodig is: past een kolom niet meer, dan stapelt hij.
 * De minimumbreedte is per variant vast, want die hangt af van wat erin staat. */

.grid {
  display: grid;
  gap: var(--sp-2);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.grid--smal { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.grid--breed { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }

/* Twee kolommen die niet gelijk zijn, voor tekst naast beeld. Onder 860 pixels
 * stapelen ze, want een tekstkolom van minder dan 300 pixels leest niet. */
.grid--split {
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
  align-items: center;
}
.grid--split-zwaar { grid-template-columns: 1.4fr 1fr; }
@media (max-width: 860px) {
  .grid--split,
  .grid--split-zwaar { grid-template-columns: 1fr; gap: var(--sp-2); }
}

/* ---------- hulpklassen ----------
 * Alleen wat met layout te maken heeft. Geen kleur, geen typografie. */

.leeskolom { max-width: var(--leeskolom-max); }
.midden { margin-inline: auto; }
.tekst-midden { text-align: center; }
.verbergen-mobiel { }
@media (max-width: 860px) { .verbergen-mobiel { display: none; } }


/* ATOMS
 *
 * De kleinste eenheden. Niet verder op te delen, en overal bruikbaar.
 *
 * Elke interactieve atom heeft alle vier de toestanden uit de states-matrix van
 * het thema: hover, focus, active en disabled. Dat is geen netheid maar de reden
 * dat Art of Cuts nul regels zichtbare toetsenbordfocus had: er was geen plek
 * waar die regel hoorde te staan.
 */

/* ---------- button ---------- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-0);
  font: var(--type-label);
  padding: var(--sp-0) var(--sp-2);
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  text-align: center;
  transition: background-color .2s, border-color .2s, transform .2s;
}

.button--primair {
  background: var(--color-action);
  color: var(--color-on-action);
}
.button--primair:hover { background: var(--color-action-hover); transform: translateY(-2px); }

/* Secundair heeft een rand in plaats van een vlak, en gebruikt de leesbare
 * accentkleur en niet de actiekleur.
 *
 * Dat verschil is geen detail. De actiekleur is gekozen om als vlak te werken met
 * tekst erop; hij hoeft zelf geen tekst te kunnen dragen. In de huisstijl van
 * Ares Flow is dat lime, dat op cream 1,22:1 haalt. Deze knop stond daardoor in
 * lime op cream en was onleesbaar. Gevonden door Codex op 12 augustus 2026, nadat
 * beide controlescripts groen waren: de bibliotheek had geen kleurwaarde en het
 * thema haalde alle drempels, maar de combinatie van die twee niet. */
.button--secundair {
  background: transparent;
  color: var(--color-accent-text);
  border-color: var(--color-accent-text);
}
.button--secundair:hover { background: var(--color-accent-text); color: var(--color-bg); }

/* Op een donkere sectie keert de knop om. Zonder deze variant valt een primaire
 * knop weg tegen de inverse achtergrond, want die deelt de actiekleur. */
.section--inverse .button--primair {
  background: var(--color-text-inverse);
  color: var(--color-bg-inverse);
}
.section--inverse .button--secundair {
  color: var(--color-text-inverse);
  border-color: var(--color-text-inverse);
}

.button:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  /* Binnenring zodat de focus ook op de knop zelf leesbaar blijft, want de
   * buitenring valt weg tegen een achtergrond met dezelfde kleur als de knop. */
  box-shadow: 0 0 0 2px var(--color-on-action) inset;
}
.button:active { transform: scale(.98); }
.button:disabled,
.button[aria-disabled="true"] {
  opacity: .45;
  cursor: not-allowed;
  transform: none;
}

/* WhatsApp draagt de merkkleuren van WhatsApp en niet die van het project. Ze
 * staan daarom in het thema apart, buiten de rollen. */
.button--whatsapp {
  background: var(--brand-whatsapp);
  color: var(--brand-whatsapp-text);
}
.button--whatsapp:hover { background: var(--brand-whatsapp-hover); transform: translateY(-2px); }
/* Het icoon houdt het herkenbare lichte groen; de tekst ernaast staat op de
 * donkere merkkleur en blijft daardoor leesbaar. */
.button--whatsapp svg { width: 20px; height: 20px; fill: var(--brand-whatsapp-icoon); }

/* ---------- link ---------- */

.link {
  color: var(--color-accent-text);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.link:hover { text-decoration-thickness: 2px; }
.link:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; border-radius: 2px; }
.section--inverse .link { color: var(--color-text-inverse); }

/* ---------- heading ----------
 * De koppen dragen alleen de tekststijl. Ruimte eromheen komt van stack.
 *
 * Nederlands schrijft samenstellingen aan elkaar, en een woord als
 * "componentenbibliotheek" of "kraamzorgorganisatie" past op 360 pixels niet in
 * één regel van een kop. Een lang woord breekt standaard niet af en duwt dan de
 * hele pagina breder. Deze twee regels vangen dat: eerst netjes afbreken met een
 * koppelteken waar dat kan, en anders hard afbreken. Gevonden op 12 augustus 2026
 * toen de stijlgids op mobiel 42 pixels te breed werd door de eigen titel. */
.heading--display,
.heading--1,
.heading--2,
.heading--3 {
  hyphens: auto;
  overflow-wrap: break-word;
}

.heading--display { font: var(--type-display); }
.heading--1 { font: var(--type-h1); }
.heading--2 { font: var(--type-h2); }
.heading--3 { font: var(--type-h3); }

/* Het bovenschrift boven een kop. Uppercase met ruime letterspatiëring, want op
 * deze grootte is een gewoon woord anders niet als label te herkennen. */
.eyebrow {
  font: var(--type-eyebrow);
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--color-accent-text);
  display: block;
}
.section--inverse .eyebrow { color: var(--color-text-inverse); opacity: .8; }

.lead { font: var(--type-lead); color: var(--color-text-subtle); }
.caption { font: var(--type-caption); color: var(--color-text-subtle); }
.section--inverse .lead,
.section--inverse .caption { color: var(--color-text-inverse); opacity: .85; }

/* De gewone focuskleur kan op een inverse sectie onder de 3:1 zakken. De
 * inverse tekstkleur is al voor dit vlak getoetst en houdt de bediening zichtbaar. */
.section--inverse .button:focus-visible,
.section--inverse .link:focus-visible,
.section--inverse a:focus-visible {
  outline-color: var(--color-text-inverse);
}

/* ---------- tag ---------- */

.tag {
  display: inline-block;
  font: var(--type-caption);
  padding: 2px var(--sp-0);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  color: var(--color-text-subtle);
}
.tag--accent {
  border-color: var(--color-accent);
  color: var(--color-accent-text);
}

/* ---------- media ----------
 * Een afbeelding krijgt altijd een vaste verhouding, zodat de pagina niet
 * verspringt terwijl het beeld laadt. De breedte en hoogte horen daarnaast als
 * attribuut op de img zelf te staan. */

.media {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 8px;
  background: var(--color-bg-alt);
}
.media--vierkant { aspect-ratio: 1 / 1; }
.media--portret { aspect-ratio: 3 / 4; }
.media--breed { aspect-ratio: 16 / 9; }


/* BLOCKS
 *
 * Samengesteld uit atoms, past binnen een sectie. Een block bepaalt zijn eigen
 * binnenruimte wel en zijn buitenruimte niet; die komt van stack of grid.
 */

/* ---------- card ----------
 * Op een lichte site scheelt een kaart weinig van de achtergrond, ongeacht het
 * thema: wit op gebroken wit haalt 1,20:1 en wit op zand 1,23:1. De rand doet
 * daarom het werk en is geen sierelement. */

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  padding: var(--sp-2);
}
.card--vlak { background: transparent; border-color: transparent; padding: 0; }
.card--accent { background: var(--color-bg-alt); }

/* Een kaart die in zijn geheel een link is. De hele kaart krijgt de focusring,
 * niet alleen de titel erin, want de titel is niet het klikvlak. */
.card--link { display: block; transition: border-color .2s, transform .2s; }
.card--link:hover { border-color: var(--color-accent); transform: translateY(-2px); }
.card--link:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }

.card__title { font: var(--type-h3); }
.card__meta { font: var(--type-caption); color: var(--color-text-subtle); }

/* ---------- service ----------
 * Eén dienst. De prijs staat in de kop en niet onderaan, want dat is wat de
 * bezoeker zoekt zodra hij weet dat de dienst bestaat. */

.service__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-1);
}
.service__price { font: var(--type-label); color: var(--color-accent-text); white-space: nowrap; }
.service__list { list-style: none; }
.service__list li {
  font: var(--type-body-sm);
  padding-block: 4px;
  padding-inline-start: var(--sp-1);
  position: relative;
}
.service__list li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: .7em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-accent);
}

/* ---------- review ---------- */

.review__quote {
  font: var(--type-lead);
  color: var(--color-text);
}
.review__author {
  font: var(--type-caption);
  color: var(--color-text-subtle);
  margin-block-start: var(--sp-0);
}
.review__stars { color: var(--color-accent); letter-spacing: 2px; }

/* ---------- faq ----------
 * Op details en summary, zodat het zonder JavaScript werkt en de browser het
 * open- en dichtklappen zelf toegankelijk maakt. */

.faq { border-bottom: 1px solid var(--color-border); }
.faq__vraag {
  font: var(--type-label);
  padding-block: var(--sp-1);
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-1);
  list-style: none;
}
.faq__vraag::-webkit-details-marker { display: none; }
.faq__vraag::after {
  content: '+';
  font: var(--type-h3);
  color: var(--color-accent);
  line-height: 1;
  transition: transform .2s;
}
.faq[open] .faq__vraag::after { transform: rotate(45deg); }
.faq__vraag:hover { color: var(--color-accent-text); }
.faq__vraag:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.faq__antwoord {
  font: var(--type-body);
  padding-block-end: var(--sp-1);
  max-width: var(--leeskolom-max);
}

/* ---------- field ----------
 * Een fout is nooit alleen kleur. De rand verandert, er komt tekst onder, en
 * aria-invalid maakt het voorleesbaar. */

.field { display: block; }
.field__label { font: var(--type-caption); color: var(--color-text-subtle); display: block; margin-block-end: 4px; }
.field__input {
  display: block;
  width: 100%;
  font: var(--type-body);
  padding: var(--sp-0);
  /* Eigen randrol: de grens van een bedieningselement moet 3:1 halen, en de
   * gewone scheidingsrand haalt dat niet. Zie theme-schema.json. */
  border: 1px solid var(--color-border-input);
  border-radius: 6px;
  background: var(--color-surface);
  color: var(--color-text);
}
.field__input:hover { border-color: var(--color-accent); }
.field__input:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 1px;
  border-color: var(--color-accent);
}
.field__input:disabled { opacity: .45; cursor: not-allowed; }
.field__input[aria-invalid="true"] { border-color: var(--color-error); border-width: 2px; }
.field__fout { font: var(--type-caption); color: var(--color-error); margin-block-start: 4px; }
textarea.field__input { min-height: 120px; resize: vertical; }

/* ---------- hours ----------
 * De dag van vandaag wordt met JavaScript gemarkeerd via .is-vandaag. Die klasse
 * zet alleen een toestand; de opmaak staat hier. */

.hours { width: 100%; border-collapse: collapse; }
.hours td {
  font: var(--type-body-sm);
  padding-block: 6px;
  border-bottom: 1px solid var(--color-border);
}
.hours td:last-child { text-align: end; color: var(--color-text-subtle); }
.hours tr.is-vandaag td { font: var(--type-label); color: var(--color-accent-text); }
.hours tr.is-vandaag td:last-child { color: var(--color-accent-text); }


/* SECTIONS
 *
 * Volle-breedte paginaplakken. Een sectie bevat altijd een .container; de sectie
 * zelf heeft nooit padding-inline of een eigen max-width.
 *
 * De sectievolgorde van een klantsite ligt vast in de bouwregel: diensten komen
 * vóór elke sectie die de USP uitdraagt, en de h1 draagt het vak en de plaats.
 * Dat is een inhoudseis en staat daarom niet in deze CSS, maar de checker toetst
 * het op de gebouwde pagina.
 */

/* ---------- nav ----------
 * Vast bovenaan, met een achtergrond die pas verschijnt na scrollen. De klasse
 * .is-gescrold wordt door JavaScript gezet. */

.nav {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 100;
  transition: background-color .25s, box-shadow .25s;
}
.nav.is-gescrold {
  background: color-mix(in srgb, var(--color-bg) 88%, transparent);
  backdrop-filter: blur(12px);
  box-shadow: 0 1px 0 var(--color-border);
}

/* Variant voor een transparante navigatie boven een inverse eerste sectie.
 * Zodra de balk een achtergrond krijgt, neemt hij de gewone tekstkleuren weer
 * over. De drawer houdt zijn eigen lichte vlak en dus ook de gewone tekstkleur. */
.nav--op-donker:not(.is-gescrold) { color: var(--color-text-inverse); }
.nav--op-donker:not(.is-gescrold) .nav__toggle span { background: var(--color-text-inverse); }
.nav--op-donker:not(.is-gescrold) .nav__link:hover { color: var(--color-action); }
.nav--op-donker:not(.is-gescrold) .nav__drawer { color: var(--color-text); }
.nav--op-donker:not(.is-gescrold) .nav__link:focus-visible,
.nav--op-donker:not(.is-gescrold) .nav__toggle:focus-visible,
.nav--op-donker:not(.is-gescrold) .nav__inner .button:focus-visible {
  outline-color: var(--color-text-inverse);
}
.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  min-height: 68px;
}
.nav__links { display: flex; gap: var(--sp-2); align-items: center; }
.nav__link { font: var(--type-label); }
.nav__link:hover { color: var(--color-accent-text); }
.nav__link:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 4px; }
.nav__link[aria-current="page"] { color: var(--color-accent-text); }

/* De hamburger is een echte knop met aria-expanded, geen div met een klik. */
.nav__toggle { display: none; background: none; border: none; padding: var(--sp-0); cursor: pointer; }
.nav__toggle:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.nav__toggle span {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--color-text);
  transition: transform .25s, opacity .25s;
}
.nav__toggle span + span { margin-block-start: 5px; }
.nav__toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.nav__drawer { display: none; }
@media (max-width: 860px) {
  .nav__links { display: none; }
  .nav__toggle { display: block; }
  .nav__drawer {
    display: block;
    background: var(--color-surface);
    border-block-start: 1px solid transparent;
    max-height: 0;
    overflow: hidden;
    visibility: hidden;
    transition: max-height .3s, visibility 0s linear .3s;
  }
  .nav__drawer.is-open {
    border-block-start-color: var(--color-border);
    max-height: 70vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    visibility: visible;
    transition-delay: 0s;
  }
  .nav__drawer a { display: block; font: var(--type-label); padding-block: var(--sp-1); border-bottom: 1px solid var(--color-border); }
}

/* ---------- hero ----------
 * Geen 100vh. Een hero die het scherm vult duwt de eerste inhoud onder de vouw,
 * en op een telefoon in liggende stand valt de knop weg. */

.hero { padding-block: calc(var(--sp-4) * 1.4) var(--sp-4); }
.hero__inner { display: grid; grid-template-columns: 1.3fr 1fr; gap: var(--sp-3); align-items: center; }
@media (max-width: 860px) { .hero__inner { grid-template-columns: 1fr; } }

.hero__titel { font: var(--type-h1); max-width: 18ch; }
.hero__lead { font: var(--type-lead); color: var(--color-text-subtle); max-width: 46ch; }
.hero__acties { display: flex; flex-wrap: wrap; gap: var(--sp-1); }

/* De feitenregel onder de knoppen: prijs, doorlooptijd of voorwaarde. Staat er
 * bewust vlak onder, want dat is de vraag die na de knop komt. */
.hero__feiten { font: var(--type-caption); color: var(--color-text-subtle); }

.section--inverse .hero__lead,
.section--inverse .hero__feiten {
  color: var(--color-text-inverse);
  opacity: .85;
}

/* ---------- services ---------- */

.services__grid { display: grid; gap: var(--sp-2); grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

/* De belangrijkste dienst mag twee kolommen innemen. Welke dat is volgt uit de
 * omzet en niet uit de visuele balans. */
.services__grid > .is-hoofddienst { grid-column: span 2; }
@media (max-width: 860px) { .services__grid > .is-hoofddienst { grid-column: span 1; } }

/* ---------- gallery ----------
 * Horizontaal schuiven met snap. Uitsluitend echte foto's; AI-beeld hoort hier
 * nooit, want een galerij leest als bewijs van uitgevoerd werk. */

.gallery {
  display: flex;
  gap: var(--sp-1);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-block-end: var(--sp-1);
  scrollbar-width: thin;
}
.gallery__item { flex: 0 0 auto; width: min(320px, 76vw); scroll-snap-align: start; }
.gallery__item img { border-radius: 8px; }

/* ---------- reviews ----------
 * Een langzaam doorlopende regel. Staat stil bij hover en bij focus, en bij
 * prefers-reduced-motion, want tekst die beweegt en niet te stoppen is sluit
 * mensen uit. */

/* De omhulling klipt wat er buiten valt. Zonder deze regel maakt de track, die
 * met max-content breder is dan het scherm, de hele pagina horizontaal
 * scrollbaar; op 360 pixels liep de stijlgids daardoor door tot 989. */
.reviews {
  overflow: hidden;
}
.reviews__track {
  display: flex;
  gap: var(--sp-2);
  animation: reviews-schuif 60s linear infinite;
  width: max-content;
}
.reviews:hover .reviews__track,
.reviews:focus-within .reviews__track { animation-play-state: paused; }
.reviews__item { width: min(360px, 80vw); }
@keyframes reviews-schuif {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* ---------- contact ---------- */

.contact__grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
@media (max-width: 860px) { .contact__grid { grid-template-columns: 1fr; } }
.contact__regel { display: flex; gap: var(--sp-0); align-items: baseline; font: var(--type-body); }
.contact__label { font: var(--type-caption); color: var(--color-text-subtle); min-width: 5.5em; }

/* ---------- scrollvoortgang ----------
 * Hoort als laatste kind in een gepositioneerde navigatie. JavaScript schrijft
 * alleen een genormeerde waarde tussen nul en een naar --scroll-progress. */

.scroll-progress {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 3px;
  overflow: hidden;
  pointer-events: none;
}
.scroll-progress__bar {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--color-accent);
  transform: scaleX(var(--scroll-progress, 0));
  transform-origin: left center;
}

/* ---------- vast contact ----------
 * De links zijn inhoud en blijven daarom configureerbaar in de markup. De dock
 * verschijnt alleen op desktop; mobiel kan dezelfde actie in een bestaande
 * mobiele hulp of navigatie worden opgenomen. */

.contact-dock { display: none; }

@media (min-width: 861px) {
  .contact-dock {
    position: fixed;
    inset-inline-start: var(--sp-2);
    inset-block-end: var(--sp-2);
    z-index: 80;
    display: flex;
    align-items: center;
    gap: var(--sp-0);
    padding: var(--sp-0);
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: var(--color-surface);
    color: var(--color-text);
    box-shadow: 0 12px 32px color-mix(in srgb, var(--color-text) 10%, transparent);
    opacity: 0;
    transform: translateY(var(--sp-0));
    visibility: hidden;
    pointer-events: none;
    transition: opacity .25s, transform .25s, visibility 0s linear .25s;
  }
  .contact-dock.is-visible {
    opacity: 1;
    transform: translateY(0);
    visibility: visible;
    pointer-events: auto;
    transition-delay: 0s;
  }
}

.contact-dock__label {
  padding-inline-start: var(--sp-0);
  font: var(--type-caption);
  color: var(--color-text-subtle);
}
.contact-dock__actions { display: flex; align-items: center; gap: 4px; }
.contact-dock__link,
.contact-dock__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  border-radius: 999px;
}
.contact-dock__link {
  padding-inline: var(--sp-0);
  font: var(--type-caption);
  color: var(--color-accent-text);
}
.contact-dock__close {
  width: 36px;
  border: 0;
  background: transparent;
  color: var(--color-text-subtle);
  cursor: pointer;
  font: var(--type-label);
}
@media (hover: hover) and (pointer: fine) {
  .contact-dock__link:hover,
  .contact-dock__close:hover {
    background: var(--color-bg);
    color: var(--color-text);
  }
}
.contact-dock__link:focus-visible,
.contact-dock__close:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

/* ---------- footer ---------- */

.footer { padding-block: var(--sp-3); }
.footer__inner { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--sp-2); }
.footer__meta { font: var(--type-caption); }

/* ---------- beweging ----------
 * Alles in deze bibliotheek staat stil zodra de bezoeker dat vraagt. */

@media (prefers-reduced-motion: reduce) {
  .reviews__track { animation: none; }
  .button,
  .card--link,
  .nav,
  .nav__drawer,
  .nav__toggle span,
  .contact-dock { transition: none; }
  .button:hover,
  .card--link:hover,
  .contact-dock { transform: none; }
  .gallery { scroll-behavior: auto; }
}
