/* ==========================================================================
   The Fix Center — base.css
   Design tokens, reset, typography, header, footer, buttons, utilities.
   Shared by the standalone preview (index.html) and the WordPress block theme
   (enqueued via functions.php). Values here are the single source of truth for
   the custom layouts; theme.json mirrors the palette for the block editor UI.
   ========================================================================== */

:root {
  /* Light, clean, modern. Warm off-white surfaces + one orange accent.
     The --ink-* ramp used to be the dark surfaces (hero/waarom/cta/footer);
     it now carries a soft light ramp so those sections read light too. */

  /* --- feature surfaces (hero / waarom / cta / footer) — light --- */
  --ink-950: oklch(97.2% 0.005 80);
  --ink-900: oklch(95% 0.006 78);
  --ink-850: oklch(93% 0.008 76);
  --ink-800: oklch(90% 0.009 74);
  --ink-700: oklch(82% 0.01 70);

  /* --- content surfaces --- */
  --paper:   oklch(98.6% 0.004 85);
  --paper-2: oklch(96.3% 0.006 80);
  --paper-3: oklch(93.5% 0.008 76);
  --line:    oklch(89% 0.008 74);

  /* --- text (dark on light everywhere) --- */
  --fg:      oklch(26% 0.015 60);
  --fg-dim:  oklch(44% 0.012 58);
  --fg-mute: oklch(56% 0.01 56);
  --ink:     oklch(26% 0.015 60);
  --ink-dim: oklch(46% 0.012 58);

  /* --- accent: orange (one accent, used sparingly) --- */
  --accent:        oklch(67% 0.19 45);   /* vivid orange for fills/buttons */
  --accent-strong: oklch(50% 0.17 44);   /* deep orange, legible as TEXT on light (>=4.5:1) */
  --accent-soft:   oklch(90% 0.06 55);
  --accent-ink:    oklch(21% 0.03 40);   /* dark text sitting on the orange */
  --accent-glow:   oklch(67% 0.19 45 / 0.24);
  --accent-text:   oklch(50% 0.17 44);   /* orange TEXT on light bg (>=4.5:1) */

  /* --- geometry --- */
  --radius-sm: 8px;
  --radius:    14px;
  --radius-lg: 22px;
  --radius-xl: 30px;

  --container: 1240px;
  --gutter: clamp(1.15rem, 4vw, 3rem);

  /* --- fluid spacing --- */
  --space-section: clamp(4.5rem, 3rem + 7vw, 9rem);

  /* --- type --- */
  --font-display: "Space Grotesk", "Segoe UI", system-ui, sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "Space Mono", ui-monospace, "SFMono-Regular", "Menlo", monospace;

  --text-hero: clamp(2.9rem, 1.1rem + 7.4vw, 6.6rem);
  --text-h2:   clamp(2rem, 1.2rem + 3vw, 3.4rem);
  --text-h3:   clamp(1.3rem, 1.05rem + 1vw, 1.7rem);
  --text-lead: clamp(1.1rem, 1rem + 0.5vw, 1.35rem);
  --text-base: clamp(1rem, 0.96rem + 0.2vw, 1.08rem);

  /* --- motion --- */
  --dur-fast: 160ms;
  --dur: 340ms;
  --dur-slow: 720ms;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);

  --shadow-sm: 0 1px 2px oklch(50% 0.02 60 / 0.06), 0 4px 12px oklch(50% 0.02 60 / 0.06);
  --shadow-md: 0 10px 28px oklch(46% 0.02 60 / 0.10), 0 2px 8px oklch(46% 0.02 60 / 0.07);
  --shadow-lg: 0 30px 64px oklch(40% 0.02 60 / 0.18);
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; cursor: pointer; background: none; border: none; }
ul { list-style: none; padding: 0; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

/* skip-to-content — visible only on keyboard focus */
.skip-link {
  position: fixed;
  left: 0.75rem; top: 0.75rem;
  z-index: 200;
  transform: translateY(-180%);
  padding: 0.7em 1.1em;
  background: var(--accent); color: var(--accent-ink);
  font-family: var(--font-display); font-weight: 600; font-size: 0.95rem;
  border-radius: 10px;
  box-shadow: var(--shadow-md);
  transition: transform var(--dur) var(--ease);
}
.skip-link:focus { transform: translateY(0); outline: 2px solid var(--fg); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .skip-link { transition: none; } }

/* ---------- typography ---------- */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -0.02em;
}
.kicker {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  color: var(--ink-dim);
}
.kicker--light { color: var(--fg-dim); }

/* ---------- layout helpers ---------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.section { padding-block: var(--space-section); }
.section-head { max-width: 46ch; margin-bottom: clamp(2.2rem, 4vw, 3.4rem); }
.section-head h2 { font-size: var(--text-h2); margin-top: 0.7rem; }
.section-head p { color: var(--ink-dim); font-size: var(--text-lead); margin-top: 1rem; }

.eyebrow-num {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--accent-text);
}

/* ---------- buttons ---------- */
.btn {
  --btn-bg: var(--accent);
  --btn-fg: var(--accent-ink);
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.95em 1.5em;
  border-radius: 999px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.98rem;
  letter-spacing: -0.01em;
  /* a pill button must never wrap — a two-line label breaks the radius and
     blows up the header height on narrow screens */
  white-space: nowrap;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid transparent;
  transition: transform var(--dur-fast) var(--ease),
              box-shadow var(--dur) var(--ease),
              background var(--dur-fast) var(--ease),
              filter var(--dur-fast) var(--ease);
  box-shadow: 0 6px 20px var(--accent-glow);
  will-change: transform;
}
.btn:hover { transform: translateY(-2px); filter: brightness(1.04); box-shadow: 0 12px 30px var(--accent-glow); }
.btn:active { transform: translateY(0); }
.btn .btn-arrow { transition: transform var(--dur) var(--ease); }
.btn:hover .btn-arrow { transform: translate(3px, -3px); }

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--fg);
  border-color: color-mix(in oklch, var(--fg) 26%, transparent);
  box-shadow: none;
}
.btn--ghost:hover { background: color-mix(in oklch, var(--fg) 8%, transparent); filter: none; box-shadow: none; }

.btn--ghost-ink {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  border-color: var(--line);
  box-shadow: none;
}
.btn--ghost-ink:hover { background: var(--paper-2); filter: none; box-shadow: none; }

.btn--sm { padding: 0.7em 1.15em; font-size: 0.9rem; }

.link-arrow {
  display: inline-flex; align-items: center; gap: 0.45em;
  font-family: var(--font-display); font-weight: 600;
  color: var(--accent-text);
}
.link-arrow svg { transition: transform var(--dur) var(--ease); }
.link-arrow:hover svg { transform: translateX(4px); }

/* ==========================================================================
   Header
   ========================================================================== */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              backdrop-filter var(--dur) var(--ease);
  border-bottom: 1px solid transparent;
}
.site-header .container {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  height: 74px;
}
.site-header.scrolled {
  background: color-mix(in oklch, var(--ink-950) 82%, transparent);
  backdrop-filter: blur(14px) saturate(1.2);
  border-bottom-color: color-mix(in oklch, var(--fg) 12%, transparent);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.12rem;
  letter-spacing: -0.03em;
  color: var(--fg);
  align-items: baseline;
}
.brand__word { white-space: nowrap; }
.brand__thin { font-weight: 500; }

/* the "i" of Fix as the amber solder-point (shared: brand wordmark + preloader).
   nudge --i-top / --i-size if it renders high/low for your font. */
.fx-i { position: relative; display: inline-block; line-height: 1; }
.fx-i::after {
  content: ""; position: absolute; left: 50%; top: var(--i-top, 0.05em);
  width: var(--i-size, 0.19em); height: var(--i-size, 0.19em);
  transform: translateX(-50%); border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0.14em var(--accent), 0 0 0.5em var(--accent-glow);
}
.brand small {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-mute);
  align-self: center;
  margin-left: 0.5em;
  padding-left: 0.6em;
  border-left: 1px solid color-mix(in oklch, var(--fg) 20%, transparent);
}

.site-nav { margin-left: auto; }
.nav {
  display: flex;
  align-items: center;
  gap: 0.2rem;
}
/* Kinetic label swap (reference vibe: sharebien.com — original implementation).
   The label masks and slides up to reveal an accent duplicate, echoing the
   hero's masked line-reveal for motion/style consistency. */
.nav-link {
  display: inline-flex;
  padding: 0.55em 0.85em;
  border-radius: 8px;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-dim);
  transition: color var(--dur-fast) var(--ease);
}
.nav-link__mask { position: relative; display: block; overflow: hidden; }
.nav-link__mask > span {
  display: block;
  line-height: 1.15;
  transition: transform var(--dur) var(--ease-out-expo);
}
.nav-link__mask > span::after {
  content: attr(data-text);
  position: absolute;
  left: 0; top: 100%;
  color: var(--accent);
}
.nav-link:hover { color: var(--fg); }
/* keep a real, visible keyboard focus ring (the label swap is a bonus, not the
   sole indicator) — the global :focus-visible outline applies here too. */
.nav-link:focus-visible { color: var(--fg); }
.nav-link:hover .nav-link__mask > span,
.nav-link:focus-visible .nav-link__mask > span { transform: translateY(-100%); }

/* ---------- header search ----------
   Sits first in the menu. Deliberately quiet: it borrows the nav's mono
   micro-label language and only picks up the accent on focus, so it never
   competes with the "Afspraak maken" CTA. */
.u-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.nav-search {
  position: relative;
  display: flex;
  align-items: center;
  margin-right: 0.6rem;
}
.nav-search__ico {
  position: absolute;
  left: 0.72rem;
  display: grid;
  place-items: center;
  color: var(--fg-mute);
  pointer-events: none;
  transition: color var(--dur-fast) var(--ease);
}
.nav-search__input {
  width: 9.5rem;
  padding: 0.5em 0.8em 0.5em 2.1rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: color-mix(in oklch, var(--paper) 55%, white);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--fg);
  /* border/shadow only — width and other layout-bound props stay static */
  transition: border-color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
.nav-search__input::placeholder {
  color: var(--fg-mute);
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.nav-search__input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}
.nav-search:focus-within .nav-search__ico { color: var(--accent-strong); }
/* drop the UA clear button so the pill keeps its shape */
.nav-search__input::-webkit-search-cancel-button { -webkit-appearance: none; }

/* staggered header entrance on load */
@keyframes tfcNavIn {
  from { opacity: 0; transform: translateY(-9px); }
  to   { opacity: 1; transform: none; }
}
.site-header .brand,
.site-header .nav-link,
.site-header .header-actions > *,
.site-header .nav-toggle { animation: tfcNavIn 600ms var(--ease) backwards; }
.site-header .brand { animation-delay: 40ms; }
.site-header .nav-link:nth-child(1) { animation-delay: 130ms; }
.site-header .nav-link:nth-child(2) { animation-delay: 185ms; }
.site-header .nav-link:nth-child(3) { animation-delay: 240ms; }
.site-header .nav-link:nth-child(4) { animation-delay: 295ms; }
.site-header .header-phone { animation-delay: 330ms; }
.site-header .header-actions .btn { animation-delay: 385ms; }
.site-header .nav-toggle { animation-delay: 330ms; }
@media (prefers-reduced-motion: reduce) {
  .site-header .brand,
  .site-header .nav-link,
  .site-header .header-actions > *,
  .site-header .nav-toggle { animation: none; }
  .nav-link__mask > span { transition: none; }
}

.header-actions { display: flex; align-items: center; gap: 0.9rem; }
.header-phone {
  display: inline-flex; align-items: center; gap: 0.5em;
  font-family: var(--font-mono); font-size: 0.9rem;
  color: var(--fg-dim);
  transition: color var(--dur-fast) var(--ease);
}
.header-phone:hover { color: var(--fg); }
.header-phone svg { color: var(--accent); }

.nav-toggle { display: none; }

/* mobile nav */
@media (max-width: 960px) {
  .header-phone span { display: none; }
}
@media (max-width: 860px) {
  .nav-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; margin-left: auto;
    border-radius: 10px; color: var(--fg);
    border: 1px solid color-mix(in oklch, var(--fg) 18%, transparent);
  }
  .nav {
    position: fixed;
    inset: 74px 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    margin: 0;
    padding: 1rem var(--gutter) 1.5rem;
    background: color-mix(in oklch, var(--ink-950) 96%, transparent);
    backdrop-filter: blur(16px);
    border-bottom: 1px solid color-mix(in oklch, var(--fg) 12%, transparent);
    transform: translateY(-8px);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
  }
  .nav-link { padding: 0.95em 0.2em; font-size: 0.9rem; letter-spacing: 0.1em; border-bottom: 1px solid color-mix(in oklch, var(--fg) 8%, transparent); }
  /* search leads the panel and goes full-width instead of staying a chip */
  .nav-search { margin: 0 0 0.9rem; }
  .nav-search__input { width: 100%; font-size: 0.85rem; padding-block: 0.8em; }
  .site-nav.open .nav { opacity: 1; transform: translateY(0); pointer-events: auto; }
  .header-actions .header-phone { display: none; }
}
@media (max-width: 520px) {
  /* "Afspraak maken" -> "Afspraak": the header only has room for brand + CTA +
     menu toggle at this width. */
  .header-actions .btn span.cta-label-long { display: none; }
  .header-actions .btn {
    padding: 0.6em 0.95em;
    font-size: 0.85rem;
    gap: 0.4em;
    box-shadow: 0 4px 14px var(--accent-glow);
  }
  .header-actions .btn .btn-arrow { width: 13px; height: 13px; }
}

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer {
  background: var(--ink-950);
  color: var(--fg-dim);
  border-top: 1px solid var(--line);
  padding-block: clamp(3.5rem, 6vw, 5.5rem) 2.5rem;
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, 1fr);
  gap: 2.5rem 2rem;
}
.footer-brand .brand { font-size: 1.4rem; margin-bottom: 1rem; }
.footer-brand p { max-width: 34ch; color: var(--fg-mute); font-size: 0.95rem; }
.footer-col h4 {
  font-family: var(--font-mono);
  font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--fg-mute); font-weight: 400; margin-bottom: 1.1rem;
}
.footer-col ul { display: grid; gap: 0.65rem; }
.footer-col a { font-size: 0.95rem; transition: color var(--dur-fast) var(--ease); }
.footer-col a:hover { color: var(--accent); }
/* ==========================================================================
   Intro preloader — F·I·X drawn as circuit traces, then the wordmark.

   Auto-dismisses in pure CSS so it can never trap the page, even if the script
   fails to load; an inline <head> script marks the session so repeat views skip
   it with no flash; reduced-motion skips it entirely.
   ========================================================================== */
.tfc-preloader {
  position: fixed; inset: 0; z-index: 9999;
  display: grid; place-items: center;
  background: var(--paper); color: var(--ink);
  animation: plDismiss 0.6s var(--ease) 2.6s forwards;
}
.intro-seen .tfc-preloader { display: none; }
.tfc-preloader__logo { display: grid; justify-items: center; gap: 1.4rem; }
.tfc-preloader__mark { position: relative; width: clamp(190px, 30vw, 300px); }
.tfc-preloader__mark svg { position: relative; width: 100%; height: auto; }
.tfc-preloader__mark .pl-glow {
  position: absolute; left: 47%; top: 8%; width: 26%; aspect-ratio: 1;
  transform: translateX(-50%); border-radius: 50%;
  background: radial-gradient(circle, var(--accent-glow), transparent 65%);
  opacity: 0; filter: blur(7px);
  animation: plGlow 1.1s var(--ease) 1.55s both;
}

/* pathLength="1" on every trace normalises the dash maths, so one keyframe
   drives strokes of completely different lengths at the same rate. */
.pl-seg {
  stroke: currentColor; fill: none; stroke-width: 3.4; stroke-linecap: round;
  stroke-dasharray: 1; stroke-dashoffset: 0;
  animation: plDraw 0.5s var(--ease) both;
}
.pl-seg1 { animation-delay: 0.10s; }
.pl-seg2 { animation-delay: 0.34s; }
.pl-seg3 { animation-delay: 0.50s; }
.pl-seg4 { animation-delay: 0.70s; }
.pl-seg5 { animation-delay: 0.92s; }
.pl-seg6 { animation-delay: 1.10s; }

.pl-pad {
  fill: currentColor; transform-box: fill-box; transform-origin: center;
  animation: plPop 0.45s var(--ease) both;
}
.pl-pad-a { animation-delay: 0.55s; }
.pl-pad-b { animation-delay: 0.70s; }
.pl-pad-c { animation-delay: 1.10s; }
.pl-pad-d { animation-delay: 1.42s; }
.pl-pad-e { animation-delay: 1.50s; }

.pl-lit {
  fill: var(--accent); transform-box: fill-box; transform-origin: center;
  animation: plPopLit 0.6s var(--ease) 1.55s both;
}
.tfc-preloader__word { overflow: hidden; }
.tfc-preloader__word .brand__word {
  display: block; font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.2rem, 0.9rem + 1.6vw, 1.7rem); letter-spacing: -0.03em;
  animation: plRise 0.75s var(--ease-out-expo) 1.85s both;
}
@keyframes plDraw   { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes plPop    { 0% { transform: scale(0); } 68% { transform: scale(1.28); } 100% { transform: scale(1); } }
@keyframes plPopLit { 0% { transform: scale(0); } 55% { transform: scale(1.5); } 100% { transform: scale(1); } }
@keyframes plGlow   { 0% { opacity: 0; } 45% { opacity: 1; } 100% { opacity: 0.7; } }
@keyframes plRise   { from { transform: translateY(115%); } to { transform: translateY(0); } }
@keyframes plDismiss { to { opacity: 0; visibility: hidden; pointer-events: none; } }
@media (prefers-reduced-motion: reduce) { .tfc-preloader { display: none; } }

/* ==========================================================================
   "Kom langs" — the shop on a map, with the practical details beside it.
   Sits directly above the footer on every page.
   ========================================================================== */
.locatie { background: var(--paper); color: var(--ink); }
.locatie__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
}
.locatie__eyebrow {
  display: inline-block;
  font-family: var(--font-mono); font-size: 0.72rem;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent-text);
  margin-bottom: 1rem;
}
.locatie h2 {
  font-size: clamp(1.9rem, 1.2rem + 2.2vw, 3rem);
  line-height: 1.05; letter-spacing: -0.03em; margin-bottom: 1rem;
}
.locatie__city { color: var(--accent-text); }
.locatie__lead { color: var(--ink-dim); max-width: 42ch; margin-bottom: 1.8rem; }

.locatie__facts {
  display: grid; gap: 1.1rem;
  padding: 1.3rem 0; margin-bottom: 1.8rem;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.locatie__facts dt {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-dim); margin-bottom: 0.2rem;
}
.locatie__facts dd { margin: 0; color: var(--ink); line-height: 1.5; }
.locatie__facts a { color: var(--ink); border-bottom: 1px solid var(--line); }
.locatie__facts a:hover { color: var(--accent-text); border-color: currentColor; }
.locatie__actions { display: flex; flex-wrap: wrap; gap: 0.7rem; align-items: center; }

/* The frame is what makes the embed feel designed rather than pasted in: the
   map keeps Google's own colours (a recoloured map is harder to read) and the
   warm border, radius and shadow do the work of tying it to the page. */
.locatie__mapwrap { position: relative; }
.locatie__map {
  position: relative; overflow: hidden;
  border-radius: var(--radius-xl);
  border: 1px solid var(--line);
  box-shadow: 0 22px 50px oklch(46% 0.02 60 / 0.16);
  aspect-ratio: 4 / 3;
  background: var(--paper-2);
}
.locatie__map iframe { display: block; width: 100%; height: 100%; border: 0; }

/* Address chip floating over the bottom-left of the map — repeats the address
   at the moment someone is looking at where it is, and doubles as the route
   link so the whole card is one target. */
.locatie__card {
  position: absolute; left: 1rem; right: auto; bottom: 1rem;
  display: inline-flex; align-items: center; gap: 0.8rem;
  max-width: calc(100% - 2rem);
  padding: 0.8rem 1rem;
  border-radius: var(--radius-lg);
  background: color-mix(in oklch, var(--paper) 92%, transparent);
  -webkit-backdrop-filter: blur(12px) saturate(150%);
          backdrop-filter: blur(12px) saturate(150%);
  border: 1px solid color-mix(in oklch, white 60%, var(--line));
  box-shadow: 0 10px 26px oklch(46% 0.02 60 / 0.2);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.locatie__card:hover { transform: translateY(-2px); box-shadow: 0 16px 34px oklch(46% 0.02 60 / 0.26); }
.locatie__card-ico {
  flex: none; display: grid; place-items: center;
  width: 36px; height: 36px; border-radius: 11px;
  color: var(--accent-strong);
  background: color-mix(in oklch, var(--accent) 14%, white);
  border: 1px solid color-mix(in oklch, var(--accent) 20%, var(--line));
}
.locatie__card-body { min-width: 0; display: grid; gap: 0.05rem; }
.locatie__card-body b { font-family: var(--font-display); font-size: 0.95rem; color: var(--ink); }
.locatie__card-body small { font-size: 0.78rem; color: var(--ink-dim); }
.locatie__card-go { flex: none; color: var(--ink-dim); transition: transform var(--dur) var(--ease), color var(--dur) var(--ease); }
.locatie__card:hover .locatie__card-go { color: var(--accent-strong); transform: translate(2px, -2px); }

@media (max-width: 900px) {
  .locatie__grid { grid-template-columns: 1fr; gap: 2.2rem; }
  .locatie__map { aspect-ratio: 16 / 11; }
}
@media (max-width: 520px) {
  .locatie__card { left: 0.6rem; bottom: 0.6rem; padding: 0.65rem 0.8rem; gap: 0.6rem; }
  .locatie__card-body small { font-size: 0.72rem; }
}
@media (prefers-reduced-motion: reduce) {
  .locatie__card { transition: none; }
  .locatie__card:hover { transform: none; }
}

/* ==========================================================================
   Floating WhatsApp button — fixed bottom-right on every page.
   A circle that widens into a pill on hover/focus: out of the way while
   scrolling, but it says what it is the moment you reach for it.
   ========================================================================== */
.wa-fab {
  position: fixed;
  right: calc(1.15rem + env(safe-area-inset-right, 0px));
  bottom: calc(1.15rem + env(safe-area-inset-bottom, 0px));
  z-index: 900;                 /* over the page, under the intro preloader */
  display: inline-flex; align-items: center; gap: 0.6rem;
  height: 56px; padding: 0 15px;
  border-radius: 999px;
  background: #25d366; color: #fff;
  box-shadow: 0 8px 24px oklch(46% 0.02 60 / 0.3), 0 2px 6px oklch(46% 0.02 60 / 0.2);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), background var(--dur) var(--ease);
}
.wa-fab__ico { flex: none; display: grid; place-items: center; }
/* The label is laid out but clipped to zero width, so opening it animates
   instead of reflowing the button from nothing. */
.wa-fab__label {
  max-width: 0; overflow: hidden; white-space: nowrap;
  font-family: var(--font-display); font-weight: 600; font-size: 0.95rem;
  opacity: 0;
  transition: max-width var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.wa-fab:hover, .wa-fab:focus-visible {
  background: #1fbe5a;
  transform: translateY(-2px);
  box-shadow: 0 14px 32px oklch(46% 0.02 60 / 0.34), 0 2px 6px oklch(46% 0.02 60 / 0.2);
}
.wa-fab:hover .wa-fab__label,
.wa-fab:focus-visible .wa-fab__label { max-width: 8rem; opacity: 1; }
.wa-fab:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
/* Touch has no hover, and a bare green circle is ambiguous — show the word. */
@media (hover: none) {
  .wa-fab__label { max-width: 8rem; opacity: 1; }
}
@media (max-width: 520px) {
  .wa-fab { height: 52px; padding: 0 13px; }
  .wa-fab__label { font-size: 0.9rem; }
}
@media (prefers-reduced-motion: reduce) {
  .wa-fab, .wa-fab__label { transition: none; }
  .wa-fab:hover, .wa-fab:focus-visible { transform: none; }
}
/* Printing a floating chat button wastes ink and means nothing on paper. */
@media print { .wa-fab { display: none; } }

/* At maximum scroll the button parks over the last thing on the page, and on a
   narrow screen that is the footer's legal links — which you then cannot scroll
   out from under it. Reserve the button's height at the very bottom so nothing
   ends up permanently covered. Only needed where the footer's bottom row is
   narrow enough to reach under the button. */
@media (max-width: 620px) {
  .site-footer { padding-bottom: calc(2.5rem + 56px + env(safe-area-inset-bottom, 0px)); }
}

/* ---------- footer: reviews, chat, socials ----------
   Two wide "proof" cards plus the social row. They sit between the link
   columns and the legal line because that is where someone lands when they
   have finished reading and are deciding whether to get in touch. */
.footer-connect {
  margin-top: 2.8rem; padding-top: 2rem;
  border-top: 1px solid color-mix(in oklch, var(--fg) 10%, transparent);
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.9rem;
}
.footer-reviews,
.footer-wa {
  display: flex; align-items: center; gap: 0.8rem;
  padding: 0.75rem 1.15rem; border-radius: 999px;
  border: 1px solid color-mix(in oklch, var(--fg) 16%, transparent);
  background: color-mix(in oklch, var(--fg) 5%, transparent);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.footer-reviews:hover,
.footer-wa:hover {
  transform: translateY(-2px);
  border-color: color-mix(in oklch, var(--accent) 55%, transparent);
  background: color-mix(in oklch, var(--fg) 9%, transparent);
}
.footer-reviews__g {
  flex: none; display: grid; place-items: center;
  width: 34px; height: 34px; border-radius: 50%; background: #fff;
}
.footer-reviews__body { display: grid; gap: 0.1rem; line-height: 1.25; }
.footer-reviews b,
.footer-wa b { font-family: var(--font-display); font-size: 0.95rem; color: var(--fg); font-weight: 600; }
.footer-reviews__stars { color: #fbbc05; font-size: 0.8rem; letter-spacing: 0.08em; }
.footer-reviews small,
.footer-wa small { display: block; font-size: 0.78rem; color: var(--fg-mute); }
.footer-wa { color: #25d366; }
.footer-wa span { display: grid; gap: 0.1rem; line-height: 1.25; }
.footer-wa svg { flex: none; }

.footer-social { display: flex; gap: 0.55rem; margin-left: auto; }
.footer-social a {
  display: grid; place-items: center; width: 42px; height: 42px; border-radius: 50%;
  color: var(--fg-dim);
  border: 1px solid color-mix(in oklch, var(--fg) 16%, transparent);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.footer-social a:hover {
  color: var(--accent); border-color: var(--accent); transform: translateY(-2px);
}
/* The phone number is the one thing people scan for, so it is not styled like
   the other list links. */
.footer-phone {
  font-family: var(--font-display); font-size: 1.15rem; font-weight: 600;
  color: var(--fg); letter-spacing: -0.01em;
}
.footer-phone:hover { color: var(--accent); }
@media (max-width: 620px) {
  .footer-connect { flex-direction: column; align-items: stretch; }
  .footer-social { margin-left: 0; justify-content: center; margin-top: 0.4rem; }
}
@media (prefers-reduced-motion: reduce) {
  .footer-reviews, .footer-wa, .footer-social a { transition: none; }
  .footer-reviews:hover, .footer-wa:hover, .footer-social a:hover { transform: none; }
}

.footer-bottom {
  margin-top: 2rem; padding-top: 1.5rem;
  border-top: 1px solid color-mix(in oklch, var(--fg) 10%, transparent);
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
  font-size: 0.85rem; color: var(--fg-mute);
}
.footer-bottom .footer-legal { display: flex; gap: 1.4rem; flex-wrap: wrap; }
@media (max-width: 780px) {
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .footer-brand { grid-column: 1 / -1; }
}
@media (max-width: 480px) {
  .footer-grid { grid-template-columns: 1fr; }
}

/* ---------- reveal utility (JS toggles .is-in) ----------
   Hidden initial state is gated on html.js so the page is fully visible
   if scripts are blocked or fail to load. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity var(--dur-slow) var(--ease),
              transform var(--dur-slow) var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

/* Directional variants so the reveal reads as composed rather than one
   uniform rise on every element. Applied sparingly (see sections markup). */
.js [data-reveal="left"]  { transform: translateX(-30px); }
.js [data-reveal="right"] { transform: translateX(30px); }
.js [data-reveal="scale"] { transform: translateY(14px) scale(0.965); }
.js [data-reveal="fade"]  { transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}

