/* DOEE — design system. Poppins, orange #FF8400 on black/white/cream. */

/* ---------- fonts ---------- */
@font-face{font-family:'Poppins';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/poppins-400.woff2') format('woff2')}
@font-face{font-family:'Poppins';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/poppins-600.woff2') format('woff2')}
@font-face{font-family:'Poppins';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/poppins-700.woff2') format('woff2')}
@font-face{font-family:'Poppins';font-style:normal;font-weight:800;font-display:swap;src:url('/fonts/poppins-800.woff2') format('woff2')}

/* ---------- tokens ---------- */
:root{
  --orange:#FF8400;
  --orange-dark:#E06F00;
  --orange-soft:#FFF3E3;
  --orange-onlight:#B34700; /* the brand accent at text strength on a LIGHT surface: 5.50:1 on --paper, 4.96:1 on --cream, 5.02:1 on --orange-soft. Also still the underline/indicator colour on light/cream header glass. Never put it on a dark surface — use --orange there (see the surface contract below). */
  --black:#0B0B0C;
  --black-2:#161617;
  --paper:#FFFFFF;
  --cream:#F6F3EC;
  --border:#E0E0E0;            /* decorative hairlines (cards, dividers) */
  --border-control:#8C8C8C;    /* WCAG 1.4.11: a control's own outline, >=3:1 on paper AND cream */
  --ink:#111112;
  --text:#4B4B4B;
  --muted:#6F6F6F;             /* 5.02:1 on --paper, 4.53:1 on --cream */
  --r-lg:20px;
  --r-md:14px;
  --shadow:0 10px 30px rgba(11,11,12,.08);
  --shadow-lg:0 24px 60px rgba(11,11,12,.14);
  --container:1200px;
  --header-h:74px;

  /* ---- surface contract (see the block after the tokens) ----
     The :root values are the LIGHT ones on purpose: body's own background is
     --paper, so anything not explicitly on a dark surface is on a light one. */
  --on-surface:var(--ink);
  --on-surface-border:var(--border-control);
  --accent-onsurface:var(--orange-onlight);
}

/* ---------- surface contract ----------
   Every surface declares what legible text ON it looks like; components read
   these tokens instead of hard-coding #fff. A component dropped on the wrong
   surface then degrades to the legible variant instead of vanishing, which is
   the failure mode that shipped .btn--ghost white-on-cream at 1.11:1.
   Custom properties inherit, so nesting works without descendant selectors. */
.section--black,.hero,.hero-sub,.cta-band,.site-footer,.nav{
  --on-surface:#fff;
  --on-surface-border:rgba(255,255,255,.45);
  --accent-onsurface:var(--orange);
}
/* ...and light components nested inside a dark surface switch back. */
.usp,.mini-card,.svc-card,.review-card,.form-card,.fab__action,.faq details,
.carousel__btn,.field,.price-chip,.usp__icon,.towns li,.ph{
  --on-surface:var(--ink);
  --on-surface-border:var(--border-control);
  --accent-onsurface:var(--orange-onlight);
}

/* ---------- base ---------- */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{margin:0;font-family:'Poppins',system-ui,sans-serif;font-size:1rem;line-height:1.7;color:var(--text);background:var(--paper)}
img{max-width:100%;height:auto;display:block}
h1,h2,h3,h4{color:var(--ink);line-height:1.15;margin:0 0 .6em;font-weight:800;letter-spacing:-.02em;text-wrap:balance}
h1{font-size:clamp(2.2rem,5vw,3.6rem)}
h2{font-size:clamp(1.7rem,3.4vw,2.5rem)}
h3{font-size:1.25rem;letter-spacing:-.01em}
p{margin:0 0 1em}
a{color:var(--accent-onsurface);text-decoration:none}
a:hover{text-decoration:underline}
ul{margin:0 0 1em;padding-left:1.2em}
:focus-visible{outline:3px solid var(--orange);outline-offset:2px;border-radius:4px}
.container{max-width:var(--container);margin:0 auto;padding:0 24px}
.skip-link{position:absolute;left:-999px;top:0;background:var(--orange);color:#000;padding:10px 18px;z-index:200;border-radius:0 0 10px 0;font-weight:700}
.skip-link:focus{left:0}

/* ---------- kicker + section shells ---------- */
.kicker{display:inline-block;font-size:.78rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--accent-onsurface);margin:0 0 14px}
.section{padding:88px 0}
.section--cream{background:var(--cream)}
.section--black{background:var(--black);color:#CFCFCF}
.section--black h2,.section--black h3{color:#fff}
.section--black .kicker{color:var(--orange)}
.section-head{max-width:720px;margin-bottom:44px}
.section-head--center{margin-left:auto;margin-right:auto;text-align:center}
/* :not(.kicker) so this (0,1,1) rule cannot out-rank .kicker (0,1,0) and
   repaint the brand accent as muted grey - it did, on every light section. */
.section-head p:not(.kicker){color:var(--muted)}
.section--black .section-head p:not(.kicker){color:#A8A8A8}

/* ---------- buttons ---------- */
.btn{position:relative;overflow:hidden;display:inline-flex;align-items:center;gap:10px;padding:14px 28px;border-radius:999px;font-weight:700;font-size:.95rem;line-height:1.2;text-decoration:none;border:2px solid transparent;cursor:pointer;transition:transform .15s ease,background .15s ease,color .15s ease,border-color .15s ease,box-shadow .25s ease}
.btn:hover{text-decoration:none;transform:translateY(-2px)}
.btn::before{content:"";position:absolute;inset:-2px;border-radius:inherit;background:radial-gradient(130px circle at var(--mx,50%) var(--my,50%),var(--spot,rgba(255,255,255,.3)),transparent 65%);opacity:0;transition:opacity .35s ease;pointer-events:none}
.btn>*{position:relative}
.btn--outline{--spot:rgba(255,132,0,.16)}
.btn--primary{--spot:rgba(255,255,255,.4)}
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .btn:hover::before{opacity:1}
  .btn:hover{box-shadow:0 12px 26px rgba(11,11,12,.16)}
  .btn--primary:hover{box-shadow:0 12px 26px rgba(255,132,0,.35)}
}
.btn svg{flex:none}
.btn--primary{background:var(--orange);color:#0B0B0C}
.btn--primary:hover{background:var(--orange-dark);color:#0B0B0C}
.btn--ghost{background:transparent;color:var(--on-surface);border-color:var(--on-surface-border)}
.btn--ghost:hover{border-color:var(--on-surface);color:var(--on-surface)}
.btn--dark{background:var(--black);color:#fff}
.btn--dark:hover{background:var(--black-2);color:#fff}
.btn--outline{background:transparent;color:var(--ink);border-color:var(--border-control)}
.btn--outline:hover{border-color:var(--ink);color:var(--ink)}
.btn--wa{background:#25D366;color:#062b12}
.btn--wa:hover{background:#1EBE59;color:#062b12}
.btn-row{display:flex;flex-wrap:wrap;gap:14px;align-items:center}

/* ---------- header ---------- */
/* glass header: solid/near-solid fallback first, translucent+blur under @supports, more opaque once scrolled.
   Base rule = the "dark" tint AND the safe fallback for any untagged/unset state (L1). */
.site-header{position:sticky;top:0;z-index:100;background:rgba(11,11,12,.96);border-bottom:1px solid rgba(255,255,255,.08);transition:background-color .2s ease,border-bottom-color .2s ease}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .site-header{background:rgba(11,11,12,.82);-webkit-backdrop-filter:blur(16px) saturate(1.4);backdrop-filter:blur(16px) saturate(1.4)}
}
.site-header.is-scrolled{background:rgba(11,11,12,.98);box-shadow:var(--shadow)}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .site-header.is-scrolled{background:rgba(11,11,12,.92);-webkit-backdrop-filter:blur(20px) saturate(1.4);backdrop-filter:blur(20px) saturate(1.4)}
}
.site-header .container{display:flex;align-items:center;gap:28px;height:var(--header-h)}
.brand{display:flex;align-items:center;flex:none}
.brand img{width:132px;height:44px;object-fit:contain}
.nav{display:flex;align-items:center;gap:4px;margin-left:auto}
.nav a{color:#EDEDED;font-weight:600;font-size:.92rem;padding:10px 13px;border-radius:10px;transition:color .2s ease}
.nav a:hover{color:var(--orange);text-decoration:none}
.nav a[aria-current="page"]{color:var(--orange)}
/* No colour here: .nav .btn (0,2,0) loses to .nav a[aria-current] (0,2,1),
   which repainted the current-page CTA --orange ON --orange = 1.00:1. Each
   variant states its own on-orange ink at (0,3,0) so nothing can out-rank it. */
.nav .btn{margin-left:12px;padding:11px 22px}
.nav .btn--primary,.nav .btn--primary[aria-current="page"],
.nav .btn--primary:hover{color:#0B0B0C}
.has-sub{position:relative;display:flex;align-items:center}
.nav-caret{background:none;border:0;color:#EDEDED;cursor:pointer;padding:6px 4px;display:inline-flex;border-radius:8px;transition:color .2s ease}
.nav-caret svg{transition:transform .2s}
.nav-caret[aria-expanded="true"] svg{transform:rotate(180deg)}
/* dropdown panel: frosted glass, consistent with the header (L2). Solid/near-solid fallback first;
   translucent+blur under @supports. Panel floats over arbitrary content (photo/video/white section),
   so it always keeps its OWN dark tint regardless of header tint — verified AA for #EDEDED item text
   even over a near-black backdrop (see BUILD notes for the contrast math). */
.dropdown{position:absolute;top:calc(100% + 10px);left:0;min-width:270px;background:rgba(11,11,12,.94);border:1px solid rgba(255,255,255,.14);border-radius:16px;padding:10px;box-shadow:var(--shadow-lg);display:none;flex-direction:column}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .dropdown{background:rgba(11,11,12,.74);-webkit-backdrop-filter:blur(20px) saturate(1.35);backdrop-filter:blur(20px) saturate(1.35)}
}
.dropdown a{padding:9px 14px;border-radius:10px;font-size:.9rem}
.dropdown a:hover{background:rgba(255,132,0,.12)}
.dropdown .dropdown__all{color:var(--orange);border-bottom:1px solid rgba(255,255,255,.1);border-radius:10px 10px 0 0;margin-bottom:6px;padding-bottom:12px}
.has-sub:hover .dropdown,.has-sub:focus-within .dropdown,.dropdown.is-open{display:flex}
@media (min-width:981px){
  .dropdown::before{content:"";position:absolute;left:0;right:0;top:-12px;height:12px}
}

/* ---------- header: adaptive tint (L1) ---------- */
/* data-tint is written by js/site.js from each section's data-header-tint as it passes behind the
   header band. No attribute (JS not run yet, or an untagged gap) = the base/dark rule above, which
   is always legible — the safe fallback. "dark" itself never needs its own rule: it IS the base. */
.site-header[data-tint="light"],.site-header[data-tint="cream"]{border-bottom-color:rgba(11,11,12,.1)}
.site-header[data-tint="light"]{background:rgba(255,255,255,.9)}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .site-header[data-tint="light"]{background:rgba(255,255,255,.78);-webkit-backdrop-filter:blur(16px) saturate(1.3);backdrop-filter:blur(16px) saturate(1.3)}
}
.site-header[data-tint="light"].is-scrolled{background:rgba(255,255,255,.96)}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .site-header[data-tint="light"].is-scrolled{background:rgba(255,255,255,.9);-webkit-backdrop-filter:blur(20px) saturate(1.3);backdrop-filter:blur(20px) saturate(1.3)}
}
.site-header[data-tint="cream"]{background:rgba(246,243,236,.93)}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .site-header[data-tint="cream"]{background:rgba(246,243,236,.8);-webkit-backdrop-filter:blur(16px) saturate(1.3);backdrop-filter:blur(16px) saturate(1.3)}
}
.site-header[data-tint="cream"].is-scrolled{background:rgba(246,243,236,.97)}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .site-header[data-tint="cream"].is-scrolled{background:rgba(246,243,236,.92);-webkit-backdrop-filter:blur(20px) saturate(1.3);backdrop-filter:blur(20px) saturate(1.3)}
}
/* foreground on light/cream: ink text (always >=11:1 measured), icons flip dark; the logo itself is
   NEVER filtered (owner rule: the wordmark must render natural/original in every header state) —
   contrast for the header as a whole is instead carried by the glass backdrop's own opacity below */
.site-header[data-tint="light"] .nav-caret,.site-header[data-tint="cream"] .nav-caret{color:var(--ink)}
.site-header[data-tint="light"] .menu-toggle span,.site-header[data-tint="cream"] .menu-toggle span{background:var(--ink)}
@media (min-width:981px){
  /* Scoped to the top-level trigger links ONLY (.nav > a = Home/Offerte-btn, .has-sub > a =
     Diensten/Over ons) — never .dropdown a: the panel is one level deeper and always keeps its
     own fixed dark glass (L2), so its #EDEDED item text must never be caught by this selector.
     Also scoped to desktop: on mobile the same trigger links sit inside the always-solid-black
     .nav dropdown panel (see the max-width:980px block below), where ink-on-black is unreadable. */
  .site-header[data-tint="light"] .nav>a:not(.btn),.site-header[data-tint="light"] .has-sub>a,
  .site-header[data-tint="cream"] .nav>a:not(.btn),.site-header[data-tint="cream"] .has-sub>a{color:var(--ink)}
  .site-header[data-tint="light"] .nav>a:not(.btn):hover,.site-header[data-tint="light"] .nav>a[aria-current="page"]:not(.btn),
  .site-header[data-tint="light"] .has-sub>a:hover,.site-header[data-tint="light"] .has-sub>a[aria-current="page"],
  .site-header[data-tint="cream"] .nav>a:not(.btn):hover,.site-header[data-tint="cream"] .nav>a[aria-current="page"]:not(.btn),
  .site-header[data-tint="cream"] .has-sub>a:hover,.site-header[data-tint="cream"] .has-sub>a[aria-current="page"]{color:var(--ink);text-decoration:none;box-shadow:inset 0 -2px 0 var(--orange-onlight)}
}
/* mobile menu open: header goes fully solid regardless of tint, matching the solid nav panel below it */
.site-header.menu-open{background:rgba(11,11,12,.98)}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .site-header.menu-open{-webkit-backdrop-filter:none;backdrop-filter:none}
}
.site-header.menu-open .nav-caret{color:#EDEDED}
.site-header.menu-open .menu-toggle span{background:#fff}
@media (min-width:981px){
  .site-header.menu-open .nav>a:not(.btn),.site-header.menu-open .has-sub>a{color:#EDEDED;box-shadow:none}
  .site-header.menu-open .nav>a:not(.btn):hover,.site-header.menu-open .nav>a[aria-current="page"]:not(.btn),
  .site-header.menu-open .has-sub>a:hover,.site-header.menu-open .has-sub>a[aria-current="page"]{color:var(--orange)}
}
@media (prefers-reduced-motion:no-preference){
  .has-sub:hover .dropdown,.has-sub:focus-within .dropdown,.dropdown.is-open{animation:ddin .18s ease}
}
@keyframes ddin{from{opacity:0;transform:translateY(6px)}}
.menu-toggle{display:none;margin-left:auto;background:none;border:0;cursor:pointer;padding:10px;border-radius:10px}
.menu-toggle span{display:block;width:24px;height:2px;background:#fff;margin:5px 0;transition:transform .2s,opacity .2s,background .2s ease}
.menu-toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.menu-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
.menu-toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

@media (max-width:980px){
  .nav{position:fixed;inset:var(--header-h) 0 auto 0;max-height:calc(100dvh - var(--header-h));overflow-y:auto;flex-direction:column;align-items:stretch;gap:2px;background:var(--black);padding:18px 24px 28px;border-bottom:1px solid rgba(255,255,255,.1);display:none;margin:0}
  .nav.is-open{display:flex}
  .nav a{padding:12px 10px;font-size:1.02rem}
  .nav .btn{margin:14px 0 0;justify-content:center}
  .menu-toggle{display:block}
  .has-sub{flex-direction:column;align-items:stretch}
  .has-sub>a{flex:1}
  .nav-caret{position:absolute;right:0;top:4px}
  .dropdown{position:static;display:none;box-shadow:none;border:0;background:rgba(255,255,255,.04);margin:2px 0 8px}
  .dropdown.is-open{display:flex}
  /* mobile: .is-open is the ONLY thing that may show a panel. BOTH CSS-only openers inherited
     from the desktop rule above have to be neutralised here. :hover was; :focus-within was not,
     and since media queries add no specificity that (0,3,0) rule outranked the (0,1,0) reset
     above it: clicking a trigger focuses its <a>, so a panel the user had just closed re-appeared
     the moment the pointer left the row (the :hover neutraliser had been masking it), and could
     never be closed at all from the keyboard. */
  .has-sub:hover .dropdown:not(.is-open),
  .has-sub:focus-within .dropdown:not(.is-open){display:none}
}

/* ---------- hero (home) ---------- */
.hero{position:relative;background:var(--black);display:flex;align-items:center;min-height:min(88vh,760px);overflow:hidden}
/* poster is the base layer, visible from first paint and forever on mobile/reduced-motion/save-data
   (JS never touches <video> on those paths, so it just sits on top, opacity:0, showing this through) */
.hero__poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 40%;filter:saturate(.96)}
/* video stays hidden until JS marks it .is-ready (buffered end-to-end) — cheap filter blur/desaturate
   instead of a backdrop-filter over the playing video, so the loop reads as a soft backdrop without
   the compositor re-sampling a full-viewport video every frame (that expense is what caused the jitter) */
.hero__bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 40%;background:var(--black);opacity:0;filter:saturate(.96)}
.hero__bg.is-ready{opacity:1}
@media (prefers-reduced-motion:no-preference){.hero__bg{transition:opacity .9s ease}}
/* scrim (item 3, lightened): directional wash (left edge + bottom vignette), now warmer and much
   more transparent, plus a soft WHITE veil (not black) across the frame — the owner's steer that
   "lighter and whiter" reads better on this brand than lighter-and-darker. The glass H1 panel
   carries its own separate contrast budget (.hero__inner.glass below), so this scrim is free to be
   this light: measured well past WCAG AA even at the video's brightest frame (see BUILD notes). */
.hero__scrim{position:absolute;inset:0;background:linear-gradient(100deg,rgba(10,9,8,.62) 0%,rgba(10,9,8,.42) 42%,rgba(10,9,8,.26) 70%,rgba(10,9,8,.20) 100%),linear-gradient(0deg,rgba(10,9,8,.30) 0%,rgba(10,9,8,.04) 30%),linear-gradient(rgba(10,9,8,.18),rgba(10,9,8,.18))}
/* Left-centred, then pulled left OUT of the container so the card breaks past the header
   wordmark. The wordmark -- not the <img> box -- is the reference: doee-logo-transparant-1.png
   carries 12.775% transparent padding on its left (alpha bbox starts at x=261 of 2043), so at the
   rendered 132px width the visible "D" begins 16.9px right of the logo box, i.e. at container
   padding + 16.9px. The old flat -20px put the PANEL 36.9px left of that ink but the H1 text
   8.1px RIGHT of it, so headline and wordmark read as aligned and the break never registered.
   The pull is now the container's outer gutter + 4px, capped at 68px:
     - below 1232px viewport it clamps to the old 20px, so <=900px and the <=600px reset further
       down are untouched (measured identical: panel x=4, text x=49);
     - from 1232px to 1328px it eats exactly the gutter, holding the panel a constant 20px off the
       viewport edge (11.5px worst case behind a 17px classic scrollbar) -- never 0, never negative;
     - at >=1328px it caps at 68px, landing the H1 text on the container's border-box left (+1px
       for the panel border) with the glass 44px beyond it: 39.9px clear of the wordmark ink.
   620px max-width and the 44px inner padding are unchanged, so the text measure stays 530px and
   the H1 line breaks are identical at every width. The plain -20px first is the fallback for
   engines without clamp(): they simply keep the previous behaviour. */
.hero__inner{position:relative;max-width:620px;margin-left:-20px;margin-left:calc(-1 * clamp(20px, (100vw - 1200px)/2 + 4px, 68px));padding:60px 44px 68px}
.hero .container{position:relative;width:100%}
/* glass panel: solid/near-solid fallback first (no blur support), translucent+blur under @supports.
   Alpha chosen against the brightest measured frame of hero.mp4 so body text (#D6D6D6) still
   clears WCAG AA (~5.3:1) even over the video's worst-case (overexposed) pixels. */
.hero__inner.glass{background:rgba(11,11,12,.85);border:1px solid rgba(255,255,255,.14);border-radius:var(--r-lg);box-shadow:0 24px 70px rgba(0,0,0,.4)}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .hero__inner.glass{background:rgba(11,11,12,.72);-webkit-backdrop-filter:blur(22px) saturate(1.3);backdrop-filter:blur(22px) saturate(1.3)}
}
.hero__tag{font-weight:700;color:var(--orange);font-size:1.02rem;margin-bottom:16px;letter-spacing:.01em}
.hero h1{color:#fff;margin-bottom:20px}
.hero h1 .mark{color:var(--orange)}
.hero__lead{color:#D6D6D6;font-size:1.08rem;max-width:34em;margin-bottom:30px}
.hero__proof{display:inline-flex;align-items:center;gap:10px;margin-top:34px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);padding:9px 18px;border-radius:999px;color:#EDEDED;font-size:.88rem;font-weight:600;backdrop-filter:blur(4px)}
.hero__proof .stars{font-size:.8rem}

/* sub-page hero (service/city/info) */
.hero-sub{background:var(--black);color:#CFCFCF;padding:72px 0 60px;position:relative;overflow:hidden}
.hero-sub h1{color:#fff;max-width:16em}
.hero-sub p{color:#C4C4C4;max-width:40em}
.hero-sub--photo{padding:0;display:flex;align-items:flex-end;min-height:420px}
.hero-sub--photo .hero__bg{object-position:center}
.hero-sub--photo .hero__inner{padding:110px 0 54px;max-width:none}
/* The photo variant above was never wired up. `.hero__bg` ships at opacity:0 and is only
   revealed by JS adding .is-ready to the homepage <video> (js/site.js), so a static <img>
   here renders invisible -- the black hero. And the `width:100%` that stops .container
   collapsing to max-content inside this flex parent is scoped to `.hero`, not `.hero-sub`. */
.hero-sub--photo img.hero__bg{opacity:1}
.hero-sub--photo .container{position:relative;width:100%}
.hero-sub--photo .hero__inner{margin-left:0}
/* Left-weighted wash, heavier than the homepage scrim because this variant has no
   .hero__inner.glass panel carrying its own contrast budget. Tuned by rendering both pages
   and sampling the brightest 5% of the real backdrop under every text run. */
.hero-sub--photo .hero__scrim{background:linear-gradient(90deg,rgba(10,9,8,.93) 0%,rgba(10,9,8,.88) 38%,rgba(10,9,8,.50) 68%,rgba(10,9,8,.12) 100%),linear-gradient(0deg,rgba(10,9,8,.62) 0%,rgba(10,9,8,.30) 55%,rgba(10,9,8,.38) 100%)}
.hero-sub--photo p{color:#DCDCDC}
/* No .hero__inner.glass on this variant, so the proof pill has no dark panel
   under it - it needs its own fill or the orange stars sit on the photo. */
.hero-sub--photo .hero__proof{background:rgba(11,11,12,.72);border-color:rgba(255,255,255,.24)}
.hero-sub--photo .breadcrumb{color:#CFCFCF}
.hero-sub--photo .breadcrumb a{color:#E8E8E8}
.hero-sub--photo .breadcrumb li:not(:last-child)::after{color:#A8A8A8}
.breadcrumb{display:flex;flex-wrap:wrap;gap:6px;list-style:none;padding:0;margin:0 0 22px;font-size:.85rem;color:#9C9C9C}
.breadcrumb a{color:#C9C9C9}
.breadcrumb a:hover{color:var(--orange)}
.breadcrumb li:not(:last-child)::after{content:"/";margin-left:6px;color:#5B5B5B}
.breadcrumb [aria-current="page"]{color:var(--orange)}

/* ---------- ribbon (marquee) ---------- */
.ribbon{background:var(--orange);overflow:hidden;padding:14px 0;transform:none}
.ribbon__track{display:flex;gap:0;width:max-content;animation:ribbon 36s linear infinite}
.ribbon__seq{display:flex;flex:none;align-items:center;white-space:nowrap;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:#0B0B0C;font-size:1rem}
.ribbon__seq span{padding:0 14px}
.ribbon__seq span::after{content:"·";margin-left:28px;color:rgba(11,11,12,.55)}
@keyframes ribbon{to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .ribbon__track{animation:none;width:auto;flex-wrap:wrap;justify-content:center}
  .ribbon__seq[aria-hidden="true"]{display:none}
  .ribbon__seq{white-space:normal;justify-content:center;flex-wrap:wrap}
  .btn:hover{transform:none}
  .btn::before{display:none}
  .svc-card:hover{transform:none}
  .fab__main:hover{transform:none}
  .tt-card:hover img{transform:none}
  .tt-card:hover .tt-card__play span{transform:none}
  .svc-card:hover .svc-card__link::after{transform:none}
}

/* ---------- USP trio ---------- */
.usp-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.usp{background:var(--paper);border:1px solid var(--border);border-radius:var(--r-lg);padding:30px 28px;box-shadow:var(--shadow)}
.section--cream .usp{border-color:transparent}
.usp__icon{width:52px;height:52px;border-radius:14px;background:var(--orange-soft);color:var(--accent-onsurface);display:flex;align-items:center;justify-content:center;margin-bottom:18px}
.usp h3{margin-bottom:8px}
.usp p{margin:0;font-size:.95rem}

/* ---------- split (media + text) ---------- */
.split{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center}
.split__media img{border-radius:var(--r-lg);box-shadow:var(--shadow-lg);width:100%;object-fit:cover}
.split__media{position:relative}
.badge-float{position:absolute;left:-18px;bottom:26px;background:var(--black);color:#fff;border-radius:16px;padding:14px 20px;display:flex;align-items:center;gap:12px;box-shadow:var(--shadow-lg)}
.badge-float b{font-size:1.4rem;color:var(--orange);font-weight:800}
.badge-float span{font-size:.8rem;color:#C9C9C9;line-height:1.3}
.mini-cards{display:grid;gap:16px;margin-top:26px}
.mini-card{background:var(--paper);border-radius:var(--r-md);padding:20px 22px;border:1px solid var(--border);box-shadow:var(--shadow)}
.section--cream .mini-card{border-color:transparent}
.mini-card h3{display:flex;align-items:center;gap:10px;font-size:1.05rem;margin-bottom:6px}
.mini-card h3 svg{color:var(--accent-onsurface);flex:none}
.mini-card p{margin:0;font-size:.93rem}

/* checklist */
.checklist{list-style:none;padding:0;margin:24px 0 0;display:grid;gap:18px}
.checklist li{display:flex;gap:14px}
.checklist .check{flex:none;width:30px;height:30px;border-radius:50%;background:var(--orange);color:#0B0B0C;display:flex;align-items:center;justify-content:center;margin-top:3px}
.checklist b{display:block;color:var(--ink);font-weight:700;margin-bottom:2px}
.checklist p{margin:0;font-size:.93rem}

/* ---------- stats band ---------- */
.stats-band{display:grid;grid-template-columns:repeat(3,1fr);gap:26px;text-align:center}
.stat b{display:block;font-size:clamp(2.2rem,4.5vw,3.1rem);font-weight:800;color:#fff;letter-spacing:-.02em;line-height:1.1}
.stat b em{font-style:normal;color:var(--orange)}
.stat span{display:block;margin-top:6px;color:#A8A8A8;font-size:.92rem;font-weight:600}
.stat .stars{margin-top:8px;color:var(--accent-onsurface)}

/* ---------- service cards ---------- */
.svc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.svc-card{position:relative;display:flex;flex-direction:column;background:var(--paper);border:1px solid var(--border);border-radius:var(--r-lg);padding:28px;transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease}
.svc-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg);border-color:var(--orange)}
.section--cream .svc-card{border-color:transparent;box-shadow:var(--shadow)}
.svc-card__title{font-size:1.16rem;margin-bottom:10px}
.svc-card__title .doee{color:var(--accent-onsurface);font-weight:800;letter-spacing:.02em}
.svc-card p{font-size:.93rem;margin-bottom:18px;flex:1}
.svc-card__link{font-weight:700;font-size:.92rem;color:var(--ink);display:inline-flex;align-items:center;gap:8px;margin-top:auto}
.svc-card__link::after{content:"→";color:var(--accent-onsurface);transition:transform .18s}
.svc-card:hover .svc-card__link::after{transform:translateX(4px)}
.svc-card__link:hover{text-decoration:none;color:var(--accent-onsurface)}
.svc-card>a.svc-card__cover::before{content:"";position:absolute;inset:0;border-radius:var(--r-lg)}

/* ---------- diensten: asymmetric aside + progressive disclosure + photo-hover cards (homepage only, scoped to .svc-sec) ---------- */
.svc-layout{display:grid;grid-template-columns:5fr 7fr;gap:56px;align-items:start}
.svc-aside{position:sticky;top:calc(var(--header-h) + 32px);display:flex;flex-direction:column;align-items:flex-start}
.svc-aside .section-head{margin-bottom:26px;max-width:none}
.svc-sec .svc-grid{display:flex;flex-direction:column;gap:22px}
.svc-toggle{margin-top:22px}

/* progressive disclosure: base HTML has no hidden cards (no-JS = all 9 visible).
   JS adds .is-progressive to the grid + inert to .svc-more, so only then does the collapse apply. */
.svc-more__inner{display:flex;flex-direction:column;gap:22px;overflow:hidden}
.is-progressive .svc-more{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows .5s cubic-bezier(.22,.61,.36,1),opacity .4s ease}
.is-progressive .svc-more.is-open{grid-template-rows:1fr;opacity:1}
@media (prefers-reduced-motion:reduce){
  .is-progressive .svc-more{transition:none}
}

/* photo reveal on hover/focus: rest state is the plain white card; media layer is absolutely
   positioned + pointer-events:none so it never intercepts clicks on the card's own link. */
.svc-sec .svc-card{overflow:hidden}
.svc-card__media{position:absolute;inset:0;pointer-events:none}
.svc-card__photo{display:block;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .4s ease}
.svc-card__photo--voorna{object-position:center 78%}
/* item 3, lightened: white text sits directly on this scrim (no separate glass layer behind it
   like the hero has), so it stays black-based rather than white-tinted — a white veil would fight
   the white text instead of protecting it. More TRANSPARENT is the right lever here; tuned by
   rendering + sampling the brightest of the 9 service photos (see BUILD notes for the numbers). */
.svc-card__scrim{position:absolute;inset:0;opacity:0;transition:opacity .4s ease;background:linear-gradient(165deg,rgba(11,11,12,.58) 0%,rgba(11,11,12,.72) 100%)}
.svc-card__body{position:relative;z-index:1;display:flex;flex-direction:column}
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .svc-sec .svc-card:hover .svc-card__photo,.svc-sec .svc-card:focus-within .svc-card__photo,
  .svc-sec .svc-card:hover .svc-card__scrim,.svc-sec .svc-card:focus-within .svc-card__scrim{opacity:1}
  .svc-sec .svc-card:hover .svc-card__title,.svc-sec .svc-card:hover p,.svc-sec .svc-card:hover .svc-card__link,
  .svc-sec .svc-card:focus-within .svc-card__title,.svc-sec .svc-card:focus-within p,.svc-sec .svc-card:focus-within .svc-card__link{color:#fff}
  .svc-sec .svc-card:hover .svc-card__link::after,.svc-sec .svc-card:focus-within .svc-card__link::after{color:var(--orange)}
}
/* touch (hover:none) and reduced-motion both fall back to the existing plain orange-border hover already on .svc-card */
@media (max-width:900px){
  .svc-layout{grid-template-columns:1fr;gap:36px}
  .svc-aside{position:static}
}

/* ---------- reviews ---------- */
.stars{color:var(--accent-onsurface);letter-spacing:2px;font-size:1rem;line-height:1}
.review-summary{display:flex;flex-wrap:wrap;align-items:center;gap:22px;margin-bottom:40px}
.review-summary__score{display:flex;align-items:center;gap:16px}
.review-summary__score b{font-size:3rem;font-weight:800;color:var(--ink);letter-spacing:-.03em;line-height:1}
.review-summary__meta b{display:block;color:var(--ink);font-weight:700}
.review-summary__meta span{color:var(--muted);font-size:.9rem}
.review-summary__meta .stars{color:var(--accent-onsurface);font-size:1rem}
.review-summary img{height:30px;width:auto;margin-left:auto}
.review-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.review-card{margin:0;background:var(--paper);border:1px solid var(--border);border-radius:var(--r-lg);padding:26px;display:flex;flex-direction:column;gap:12px;box-shadow:var(--shadow)}
.section--cream .review-card{border-color:transparent}
.review-card blockquote{margin:0;font-size:.94rem;color:var(--text);flex:1}
.review-card figcaption{font-weight:700;color:var(--ink);font-size:.9rem}
.review-card figcaption span{display:block;font-weight:400;color:var(--muted);font-size:.82rem}

/* ---------- review card clamp + expander (item 5) ----------
   JS-added class only (never in base CSS) so a no-JS visitor always gets the full, unclamped
   quote. -webkit-line-clamp is the primary mechanism (all evergreen browsers); the standard
   `line-clamp` property is included for the browsers now shipping it; max-height is a belt-and-
   braces guard for anything supporting neither. Height changes are driven by JS setting an
   explicit inline max-height (see js/site.js) so the expand/collapse can transition smoothly —
   the class below only supplies the AT-REST clamped/expanded end states. */
.review-card.is-clamped blockquote{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;line-clamp:3;overflow:hidden;max-height:5.1em}
.review-card.is-rv-expanded blockquote{display:block;-webkit-line-clamp:unset;line-clamp:unset;overflow:hidden;max-height:none}
@media (prefers-reduced-motion:no-preference){
  .review-card.rv-animatable blockquote{transition:max-height .4s cubic-bezier(.22,.61,.36,1)}
}
.review-card__toggle{align-self:flex-start;display:inline-flex;align-items:center;gap:5px;background:none;border:0;padding:0;margin-top:-2px;font:inherit;font-weight:700;font-size:.85rem;color:var(--accent-onsurface);cursor:pointer}
.review-card__toggle:hover{text-decoration:underline}
.review-card__toggle svg{flex:none;transition:transform .2s}
.review-card__toggle[aria-expanded="true"] svg{transform:rotate(180deg)}
.review-card__toggle[hidden]{display:none}

/* ---------- TikTok facade ---------- */
.tt-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:16px}
.tt-card{position:relative;aspect-ratio:9/16;border-radius:var(--r-md);overflow:hidden;background:var(--black-2);border:0;padding:0;cursor:pointer;display:block;width:100%}
.tt-card img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .25s ease,opacity .25s ease}
.tt-card:hover img{transform:scale(1.05);opacity:.85}
.tt-card__play{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
.tt-card__play span{width:52px;height:52px;border-radius:50%;background:rgba(255,132,0,.94);display:flex;align-items:center;justify-content:center;color:#0B0B0C;box-shadow:0 8px 24px rgba(0,0,0,.4);transition:transform .2s}
.tt-card:hover .tt-card__play span{transform:scale(1.1)}
.tt-card iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.tt-card__fallback{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;padding:16px;gap:8px;background:rgba(11,11,12,.6);color:#fff;font-weight:700;font-size:.86rem;transition:background .2s}
.tt-card__fallback span{display:inline-flex;align-items:center;gap:7px;background:rgba(255,132,0,.94);color:#0B0B0C;border-radius:999px;padding:9px 16px}
.tt-card.is-fallback:hover .tt-card__fallback{background:rgba(11,11,12,.78)}

/* ---------- TikTok strip (homepage): horizontal scroll-snap, alternating high/low (E1) ---------- */
.tt-track{display:flex;gap:16px;padding:4px 4px 10px}
.tt-track>.tt-card{flex:0 0 min(80%,300px);scroll-snap-align:start}
@media (min-width:700px){
  .tt-track{align-items:flex-start;padding:22px 4px 34px}
  .tt-track>.tt-card{flex-basis:calc((100% - 32px)/3)}
  .tt-track>.tt-card:nth-child(even){margin-top:26px}
}
@media (min-width:1080px){.tt-track>.tt-card{flex-basis:calc((100% - 80px)/6)}}

/* ---------- CTA band ---------- */
.cta-band{background:var(--black);padding:88px 0;text-align:center}
.cta-band h2{color:#fff;font-size:clamp(1.9rem,4vw,2.8rem);margin-bottom:12px}
.cta-band h2 em{font-style:normal;color:var(--orange)}
.cta-band p{color:#B9B9B9;margin-bottom:30px}
.cta-band .btn-row{justify-content:center}

/* ---------- footer ---------- */
.site-footer{background:var(--black);color:#B9B9B9;border-top:1px solid rgba(255,255,255,.08);padding:64px 0 0;font-size:.92rem}
.site-footer a{color:#D8D8D8}
.site-footer a:hover{color:var(--orange);text-decoration:none}
.footer-grid{display:grid;grid-template-columns:1.5fr 1fr .95fr .95fr 1.15fr;gap:32px;padding-bottom:48px}
.site-footer h3 a{color:#fff}
.footer-brand img{width:150px;height:50px;object-fit:contain;margin-bottom:18px}
.footer-brand p{font-size:.9rem;color:#9C9C9C}
.socials{display:flex;gap:12px;margin-top:18px}
.socials a{width:40px;height:40px;border-radius:12px;background:rgba(255,255,255,.07);display:flex;align-items:center;justify-content:center;color:#EDEDED;transition:background .15s,color .15s}
.socials a:hover{background:var(--orange);color:#0B0B0C}
.site-footer h3{color:#fff;font-size:.95rem;letter-spacing:.04em;text-transform:uppercase;margin-bottom:16px}
.footer-links{list-style:none;padding:0;margin:0;display:grid;gap:9px}
.footer-contact{list-style:none;padding:0;margin:0;display:grid;gap:13px}
.footer-contact li{display:flex;gap:11px;align-items:flex-start}
.footer-contact svg{flex:none;color:var(--orange);margin-top:4px}
.footer-bottom{border-top:1px solid rgba(255,255,255,.08);padding:20px 0;display:flex;flex-wrap:wrap;gap:14px;align-items:center;justify-content:space-between;font-size:.84rem;color:#8A8A8A}
.footer-bottom ul{list-style:none;display:flex;flex-wrap:wrap;gap:20px;margin:0;padding:0}
.footer-bottom a{color:#8A8A8A}

/* ---------- FAB ---------- */
.fab{position:fixed;right:20px;bottom:20px;z-index:120;display:flex;flex-direction:column;align-items:flex-end;gap:12px}
.fab__menu{display:none;flex-direction:column;gap:10px}
.fab.is-open .fab__menu{display:flex}
.fab__action{display:flex;align-items:center;gap:10px;background:#fff;color:var(--ink);border:1px solid var(--border);border-radius:999px;padding:10px 18px 10px 12px;font-weight:700;font-size:.88rem;font-family:inherit;box-shadow:var(--shadow-lg);cursor:pointer;text-decoration:none}
.fab__action:hover{text-decoration:none;border-color:var(--orange);color:var(--ink)}
.fab__action .ic{width:34px;height:34px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex:none;color:#fff}
.ic--wa{background:#25D366}
.ic--chat{background:var(--orange)}
.ic--tel{background:var(--black)}
.fab__main{width:60px;height:60px;border-radius:50%;background:var(--orange);border:0;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#0B0B0C;box-shadow:0 12px 32px rgba(255,132,0,.45);transition:transform .18s,background .18s}
.fab__main:hover{transform:scale(1.06)}
.fab__main svg{transition:transform .2s}
.fab__main[aria-expanded="true"] svg{transform:rotate(135deg)}

/* ---------- forms ---------- */
.form{display:grid;gap:18px}
.form-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.field label{display:block;font-weight:600;font-size:.9rem;color:var(--ink);margin-bottom:7px}
.field input,.field select,.field textarea{width:100%;padding:13px 16px;border:1px solid var(--border-control);border-radius:12px;font-family:inherit;font-size:.95rem;color:var(--ink);background:#fff}
.field input:focus,.field select:focus,.field textarea:focus{outline:2px solid var(--orange);outline-offset:0;border-color:var(--orange)}
.field textarea{min-height:130px;resize:vertical}
.consent{display:flex;gap:10px;align-items:flex-start;font-size:.86rem;color:var(--muted)}
.consent input{width:18px;height:18px;margin-top:3px;accent-color:var(--orange)}
.form-note{font-size:.82rem;color:var(--muted)}
.form-card{background:#fff;border:1px solid var(--border);border-radius:var(--r-lg);padding:34px;box-shadow:var(--shadow)}

/* ---------- FAQ ---------- */
.faq{display:grid;gap:14px;max-width:820px}
.faq details{background:#fff;border:1px solid var(--border);border-radius:var(--r-md);padding:0}
.section--cream .faq details{border-color:transparent;box-shadow:var(--shadow)}
.faq summary{cursor:pointer;list-style:none;display:flex;justify-content:space-between;align-items:center;gap:16px;font-weight:700;color:var(--ink);padding:18px 22px}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";font-size:1.4rem;font-weight:400;color:var(--accent-onsurface);transition:transform .2s;flex:none}
.faq details[open] summary::after{transform:rotate(45deg)}
.faq details>div{padding:0 22px 20px;font-size:.94rem}

/* ---------- gallery ---------- */
.gallery-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.gallery-grid img{border-radius:var(--r-md);width:100%;height:100%;object-fit:cover;aspect-ratio:1}

/* ---------- misc ---------- */
.price-chip{display:inline-block;background:var(--orange-soft);color:var(--accent-onsurface);font-weight:700;border-radius:999px;padding:6px 16px;font-size:.9rem}
.center{text-align:center}
.mt-lg{margin-top:44px}
.lead{font-size:1.08rem}

/* ---------- responsive ---------- */
@media (max-width:1080px){
  .tt-grid{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:900px){
  /* Below ~900px the copy fills the container, so the left-to-right desktop wash stops
     sitting under it: measured 3.40-4.41:1 on the /over-ons/ lead from 601px to 800px,
     below AA. Flatten the wash here and carry the contrast vertically instead. */
  .hero-sub--photo .hero__scrim{background:linear-gradient(90deg,rgba(10,9,8,.88) 0%,rgba(10,9,8,.78) 60%,rgba(10,9,8,.66) 100%),linear-gradient(0deg,rgba(10,9,8,.45) 0%,rgba(10,9,8,.20) 55%,rgba(10,9,8,.34) 100%)}
  .section{padding:64px 0}
  .usp-grid,.svc-grid,.review-grid{grid-template-columns:repeat(2,1fr)}
  .split{grid-template-columns:1fr;gap:36px}
  .footer-grid{grid-template-columns:1fr 1fr;gap:32px}
  .gallery-grid{grid-template-columns:repeat(3,1fr)}
  .badge-float{left:12px}
}
@media (max-width:600px){
  .usp-grid,.svc-grid,.review-grid,.form-grid-2{grid-template-columns:1fr}
  .tt-grid{grid-template-columns:repeat(2,1fr)}
  .gallery-grid{grid-template-columns:repeat(2,1fr)}
  .footer-grid{grid-template-columns:1fr}
  /* mobile: .hero carries no vertical padding, so once min-height drops to 0 the flex box
     collapses to exactly the card's height -- align-items:center becomes a no-op and the glass
     panel sits flush against the sticky header above and the USP band below (measured 0px on
     both edges at 320/360/375/390/412/430/600-wide phones). Padding is the only lever that
     gives a CONSTANT gap: any mobile min-height still leaves 0px on the short phones, where the
     card is already taller than the min-height, then swings to 57-124px on taller/wider ones
     (measured for both min(88vh,760px) and calc(100dvh - var(--header-h))). 24px matches the
     container's own 24px side gutter so the panel is evenly inset on all four sides; the extra
     4px at the bottom echoes the card's own 36/40 padding asymmetry and gives its downward
     box-shadow somewhere to land. */
  .hero{min-height:0;padding:24px 0 28px}
  .hero__inner{padding:28px 20px 30px;margin-left:0}
  .hero__tag{font-size:.95rem;margin-bottom:10px}
  .hero h1{font-size:2rem;line-height:1.12;margin-bottom:14px}
  .hero__lead{font-size:1rem;line-height:1.6;margin-bottom:22px}
  /* One row, the owner's ask. Two labelled pills genuinely cannot fit: measured 204.7px +
     171.1px + 14px gap = 389.8px against a 283-338px card interior, and solving for a fit at
     375px gives 4*padX + gap <= 19.2px -- impossible at any sane padding, or font-size <= 12.2px.
     So the WhatsApp label goes visually-hidden below 600px and the button becomes a 50x50 icon
     circle (>=44x44 per WCAG 2.5.5; glyph 19.7:1, ring 4.5:1, both clear of 1.4.11's 3:1).
     Its accessible name stays "WhatsApp", and the .fab menu still carries a labelled wa.me link
     on every page. max-width caps the primary at 340px so it does not stretch to 448px at 600w. */
  .hero .btn-row{flex-wrap:nowrap;gap:12px}
  .hero .btn-row .btn--primary{flex:1 1 auto;max-width:340px;justify-content:center}
  .hero .btn-row .btn--ghost{flex:0 0 auto;padding:14px;gap:0}
  .hero .btn-row .btn--ghost .btn__label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
  /* The chip's 1-line width is 322.8px at .88rem/9px 18px -- wider than the 283-320px interior,
     so it silently wrapped to two lines on 375/390/412. .82rem/8px 14px/gap 8 needs 295.7px and
     fits from 390 up. margin-bottom is the global p{margin:0 0 1em}: 14.08px that never collapses
     because the card has padding-bottom. Scoped to .hero so /over-ons/ and /offerte-aanvraag/,
     which reuse .hero__proof, are untouched. */
  .hero .hero__proof{margin-top:20px;margin-bottom:0;font-size:.82rem;padding:8px 14px;gap:8px}
  .hero .hero__proof .stars{font-size:.76rem}
  /* Phone: the copy is full-width, so weight the scrim at BOTH ends (breadcrumb/kicker at
     the top, buttons at the bottom) and lighten mid-frame. The padding override is required
     because `.hero-sub--photo .hero__inner` (0,2,0) outranks `.hero__inner` (0,1,0), so the
     desktop 110px top padding would otherwise survive on phones. */
  .hero-sub--photo .hero__scrim{background:linear-gradient(0deg,rgba(10,9,8,.88) 0%,rgba(10,9,8,.68) 48%,rgba(10,9,8,.86) 100%)}
  .hero-sub--photo .hero__inner{padding:64px 0 46px}
  .stats-band{grid-template-columns:1fr;gap:34px}
  .review-summary img{margin-left:0}
  /* "Uitstekend" is also matched by the DESCENDANT selector .review-summary__score b above, so it
     inherits the 3rem score size: one unbreakable 253px word that floors .review-summary's
     min-content at 379.5px. Below ~428px CSS width that no longer fits the container's 24px
     gutters and .g-reviews{overflow:hidden} slices the chip off at the screen edge (OnePlus 9 Pro
     is 412px; iPhone Pro Max is 430px, which is why it only shows on some phones). Give the meta
     label its own size at the phone breakpoint; the desktop chip is untouched. */
  .review-summary__meta b{font-size:1rem;letter-spacing:normal;line-height:1.45}
  .form-card{padding:24px}
  .fab{right:14px;bottom:14px}
}

/* Very narrow phones (iPhone SE 1st gen 320, Galaxy Fold cover 344). The one-row CTA
   above lets .btn--primary shrink below its 204.7px max-content width, so "Offerte
   aanvragen" broke onto a second line inside its own pill at <=355px (measured: 168px
   available at 320, 203px at 355 -- 355 misses a one-line fit by 1.7px). Trimming the
   card and button padding buys back the difference: the row then needs 240.7px against
   a 292px interior at 320. 360px and up never entered this branch. */
@media (max-width:355px){
  .hero__inner{padding:26px 14px 28px}
  .hero .btn-row{gap:8px}
  .hero .btn-row .btn--primary{padding:14px 18px}
  .hero .btn-row .btn--ghost{padding:12px}
}

/* ---------- alive: ken burns hero ---------- */
/* img.hero__bg only — the homepage hero background is now a <video> and supplies its own
   motion, so it's excluded here; inner-page photo heroes (hero-sub--photo) keep the effect */
@media (prefers-reduced-motion:no-preference){
  img.hero__bg{animation:kenburns 14s ease-in-out infinite alternate}
}
@keyframes kenburns{from{transform:scale(1)}to{transform:scale(1.06)}}

/* ---------- alive: scroll reveal ---------- */
@media (prefers-reduced-motion:no-preference){
  .rv{opacity:0;transform:translateY(14px);transition:opacity .65s cubic-bezier(.22,.61,.36,1) var(--rvd,0s),transform .65s cubic-bezier(.22,.61,.36,1) var(--rvd,0s)}
  .rv.in-view{opacity:1;transform:none}
}

/* ---------- alive: card hovers ---------- */
.stat b{font-variant-numeric:tabular-nums}
.svc-card__link{padding-bottom:2px;background:linear-gradient(var(--orange),var(--orange)) no-repeat left bottom/0 2px}
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .svc-card__link{transition:background-size .25s ease}
  .svc-card:hover .svc-card__link{background-size:100% 2px}
  .review-card{transition:transform .25s ease,box-shadow .25s ease,border-color .25s ease}
  .review-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg);border-color:var(--orange)}
  .gallery-grid img{transition:transform .3s ease,box-shadow .3s ease}
  .gallery-grid img:hover{transform:translateY(-4px) scale(1.02);box-shadow:var(--shadow-lg)}
  .usp{transition:border-color .25s ease,transform .25s ease}
  .usp:hover{border-color:var(--orange);transform:translateY(-3px)}
  .mini-card{transition:border-color .25s ease}
  .mini-card:hover{border-color:var(--orange)}
}

/* ---------- alive: FAB pop ---------- */
@media (prefers-reduced-motion:no-preference){
  .fab.is-open .fab__action{animation:fabin .3s cubic-bezier(.34,1.56,.64,1) backwards}
  .fab.is-open .fab__action:nth-child(2){animation-delay:.05s}
  .fab.is-open .fab__action:nth-child(1){animation-delay:.1s}
}
@keyframes fabin{from{opacity:0;transform:translateY(10px) scale(.92)}}

/* ---------- review carousel ---------- */
.carousel{position:relative}
.carousel__track{display:flex;gap:22px;overflow-x:auto;scroll-snap-type:x mandatory;padding:4px 4px 10px;margin:0 -4px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.carousel__track::-webkit-scrollbar{display:none}
@media (prefers-reduced-motion:no-preference){.carousel__track{scroll-behavior:smooth}}
.carousel__track>*{flex:0 0 min(85%,340px);min-width:0;scroll-snap-align:start}
@media (min-width:700px){.carousel__track>*{flex-basis:calc((100% - 22px)/2)}}
@media (min-width:1000px){.carousel__track>*{flex-basis:calc((100% - 44px)/3)}}
.carousel__track.is-drag{cursor:grabbing;scroll-snap-type:none;scroll-behavior:auto;user-select:none}
.carousel__btn{position:absolute;top:50%;transform:translateY(-50%);z-index:5;width:44px;height:44px;border-radius:50%;background:#fff;border:1px solid var(--border);box-shadow:var(--shadow-lg);color:var(--ink);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .2s,color .2s,border-color .2s,opacity .2s}
.carousel__btn:hover{background:var(--orange);color:#0B0B0C;border-color:var(--orange)}
.carousel__btn--prev{left:-10px}
.carousel__btn--next{right:-10px}
.carousel__btn[hidden]{display:none}
.carousel__btn[disabled]{opacity:.35;cursor:default}
.carousel__btn[disabled]:hover{background:#fff;color:var(--ink);border-color:var(--border)}
@media (max-width:600px){
  .carousel__btn{width:40px;height:40px}
  .carousel__btn--prev{left:-4px}
  .carousel__btn--next{right:-4px}
}
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ---------- infinite carousel (opt-in: [data-infinite], transform ring instead of native scroll) ---------- */
.carousel__viewport{min-width:0}
.carousel.is-infinite-active .carousel__viewport{overflow:hidden;border-radius:var(--r-lg)}
.carousel.is-infinite-active .carousel__track{overflow:visible;scroll-snap-type:none;flex-wrap:nowrap;margin:0;padding:4px 0 10px;will-change:transform;transition:transform .5s cubic-bezier(.22,.8,.28,1)}
.carousel.is-infinite-active .carousel__track>*{scroll-snap-align:none}
@media (prefers-reduced-motion:reduce){.carousel.is-infinite-active .carousel__track{transition:none}}

/* ---------- reviews band: real project photo + glass cards over it (C1/F1) ---------- */
.g-reviews{position:relative;isolation:isolate;overflow:hidden;padding:120px 0}
.g-reviews__bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 38%;filter:blur(3px) saturate(1.05);transform:scale(1.06);z-index:-2}
.g-reviews::before{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(180deg,rgba(9,8,7,.80) 0%,rgba(9,8,7,.68) 42%,rgba(9,8,7,.84) 100%)}
.g-reviews .kicker{color:var(--orange)}
.g-reviews__head{margin-bottom:36px}
/* score + Werkspot chip: light glass so the (fixed-color) Werkspot logo stays legible on a dark photo */
.g-reviews .review-summary{display:inline-flex;margin:0;background:rgba(255,255,255,.94);border:1px solid rgba(255,255,255,.7);border-radius:20px;padding:16px 24px;box-shadow:0 20px 50px rgba(0,0,0,.35)}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .g-reviews .review-summary{background:rgba(255,255,255,.9);-webkit-backdrop-filter:blur(18px) saturate(1.3);backdrop-filter:blur(18px) saturate(1.3)}
}
.g-reviews .review-summary__meta span{color:#59544D}
/* review cards: dark glass (same recipe as .hero__inner.glass) so white text always reads */
/* This section flips .review-card / .carousel__btn to dark glass, so they must
   re-declare the dark surface tokens; the generic light-component reset above
   is (0,1,0) and this is (0,2,0). */
.g-reviews .review-card,.g-reviews .carousel__btn,.g-reviews .btn--outline{
  --on-surface:#fff;
  --on-surface-border:rgba(255,255,255,.45);
  --accent-onsurface:var(--orange);
}
.g-reviews .review-card{background:rgba(11,11,12,.88);border:1px solid rgba(255,255,255,.16);box-shadow:0 20px 55px rgba(0,0,0,.4)}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .g-reviews .review-card{background:rgba(11,11,12,.62);-webkit-backdrop-filter:blur(18px) saturate(1.25);backdrop-filter:blur(18px) saturate(1.25)}
}
.g-reviews .review-card blockquote{color:#F2F0EA}
.g-reviews .review-card figcaption{color:#fff}
.g-reviews .review-card figcaption span{color:rgba(255,255,255,.64)}
.g-reviews .review-card__toggle{color:var(--orange)}
/* item 5: clamped cards no longer vary wildly in height, so let each expand independently
   instead of the whole (very long, cloned-for-looping) track stretching every card to match —
   only this carousel's own track is touched, other pages' review carousels are unaffected */
.g-reviews .review-track{align-items:flex-start}
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .g-reviews .review-card:hover{border-color:rgba(255,132,0,.6)}
}
.g-reviews .carousel__btn{background:rgba(11,11,12,.6);border-color:rgba(255,255,255,.3);color:#fff}
@supports ((-webkit-backdrop-filter:blur(4px)) or (backdrop-filter:blur(4px))){
  .g-reviews .carousel__btn{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
}
.g-reviews .btn--outline{color:#fff;border-color:rgba(255,255,255,.5)}
.g-reviews .btn--outline:hover{border-color:#fff;color:#fff}
@media (max-width:900px){.g-reviews{padding:80px 0}}
@media (max-width:600px){
  .g-reviews .review-summary{padding:14px 18px;gap:14px}
}

/* ---------- voor/na ---------- */
.ba{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.ba__item{position:relative;margin:0;border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-lg);aspect-ratio:3/4;background:var(--black-2)}
.ba__item img{width:100%;height:100%;object-fit:cover;border-radius:0;box-shadow:none}
.ba__item figcaption{position:absolute;top:12px;left:12px;background:var(--black);color:#fff;font-weight:700;font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;padding:5px 13px;border-radius:999px}
.ba__item--na figcaption{background:var(--orange);color:#0B0B0C}
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .ba__item img{transition:transform .5s ease}
  .ba__item:hover img{transform:scale(1.04)}
}

/* ---------- werkgebied ---------- */
.towns{display:flex;flex-wrap:wrap;gap:8px;list-style:none;padding:0;margin:18px 0 0}
.towns li{background:var(--orange-soft);color:var(--accent-onsurface);font-weight:600;font-size:.85rem;border-radius:999px;padding:6px 14px}
.region-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:22px}
.region-card .svc-card__title{font-size:1.3rem}
.region-card p+p{margin-top:-8px}
@media (max-width:700px){.region-grid{grid-template-columns:1fr}}
