/* =========================================================================
   Multiware, HTML-mockup
   Palet 1 uit docs/kleuronderzoek.md. Alle contrastwaarden daar nagerekend.
   Geen JavaScript. Geen kleur die niet in de tokenlijst staat.
   ========================================================================= */

:root {
  /* --- kleur: palet 1, nachtblauw met hi-vis oranje ---
     Gekozen op 9 augustus 2026, ter vervanging van palet B. Dat had een fel
     blauw als grondvlak en geen aparte accentkleur, waardoor elke actie
     dezelfde kleur had als de ondergrond waar hij op stond. Elke waarde
     hieronder is nagerekend, zie docs/kleuronderzoek.md. */
  --blauw:        #0b3a6f;   /* grondvlak, wit erop 11,36:1 */
  --blauw-diep:   #062741;   /* voet, nutbalk, hover, wit erop 15,28:1 */
  --accent:       #ff8a3d;   /* de enige actiekleur, inkt erop 7,66:1 */
  --accent-diep:  #b3450a;   /* accent op een licht vlak, wit erop 5,57:1 */
  --inkt:         #0e1726;   /* bodytekst, 17,96:1 op wit */
  --inkt-zacht:   #4a5568;   /* bijschrift, 7,53:1 op wit */
  --wit:          #ffffff;
  --vlak:         #f3f6fb;   /* kaartachtergrond, nooit tekstkleur */
  --rand-veld:    #6b7d95;   /* formulierveld, 4,21:1 op wit, WCAG 1.4.11 */
  --rand-sier:    #d8e2f0;   /* alleen decoratief */

  /* Regel: witte tekst op --accent haalt 2,35:1 en mag dus nooit. Een knop in
     de accentkleur draagt altijd --inkt. Op een lichte ondergrond waar het
     accent zelf tekst is, geldt --accent-diep, want dat haalt wel 5,57:1. */

  /* --- type --- */
  --display: "Archivo", "Segoe UI", system-ui, -apple-system, sans-serif;
  --body:    "Public Sans", "Segoe UI", system-ui, -apple-system, sans-serif;

  /* --- ruimte, viervoud --- */
  --s1: .25rem;  --s2: .5rem;   --s3: .75rem;  --s4: 1rem;
  --s5: 1.5rem;  --s6: 2rem;    --s7: 3rem;    --s8: 4rem;
  --s9: 6rem;    --s10: 8rem;

  /* --- vorm --- */
  --r-s: 6px; --r-m: 12px; --r-l: 20px; --r-xl: 40px; --r-pil: 999px;

  --breed: 1200px;
  --smal: 760px;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--blauw);
  color: var(--inkt);
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* Het paginakader uit referentie 13: de hele site ligt als een wit afgerond
   paneel op een blauw veld. Daarmee is blauw niet langer alleen de kleur van
   losse secties maar de ondergrond van het geheel, en dat is de Vlak-regel
   uit DESIGN.md doorgetrokken naar de buitenste laag. */
.paneel {
  background: var(--wit);
  border-radius: var(--r-xl);
  /* clip en niet hidden. Allebei snijden ze de inhoud af op de afronding, maar
     overflow: hidden maakt van dit paneel een scrollcontainer, en dan meet een
     scroll-tijdlijn tegen het paneel in plaats van tegen het venster. Het
     paneel is even hoog als zijn inhoud en scrollt dus nooit, waardoor de
     trechter-animatie op een vaste stand bleef staan en nooit liep. clip snijdt
     af zonder scrollcontainer te worden. */
  overflow: clip;
  margin: var(--s4);
}

/* Browservlakken die we niet zelf tekenen horen ook bij het ontwerp. */
::selection { background: var(--blauw); color: var(--wit); }
html { scrollbar-color: var(--blauw-diep) var(--blauw); }

img { max-width: 100%; display: block; }

/* =========================================================================
   Typografie. Display is Archivo op 800 met strakke tracking: de grammatica
   van busbelettering en gereedschapsmerken, niet die van een tijdschrift.
   ========================================================================= */

h1, h2, h3, h4 { font-family: var(--display); font-weight: 800; margin: 0; text-wrap: balance; }
h1 { font-size: clamp(2.1rem, 1.4rem + 3.2vw, 3.9rem); line-height: 1.04; letter-spacing: -.035em; }
h2 { font-size: clamp(1.6rem, 1.2rem + 1.7vw, 2.6rem); line-height: 1.1;  letter-spacing: -.028em; }
h3 { font-size: clamp(1.1rem, 1rem + .5vw, 1.35rem);   line-height: 1.25; letter-spacing: -.015em; }
h4 { font-size: 1rem; line-height: 1.35; letter-spacing: -.01em; }

p { margin: 0; }
.prose > * + * { margin-top: var(--s4); }
.prose p { max-width: 66ch; }

.opschrift {
  font-family: var(--display);
  font-size: .72rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
}

.lead { font-size: clamp(1rem, .95rem + .35vw, 1.18rem); line-height: 1.6; }

/* Links dragen de accentkleur, want een link is een actie. */
a { color: var(--accent-diep); }

/* Zichtbare focus, overal. Nachtblauw haalt 11,36:1 op wit, ruim boven de
   3:1 die WCAG voor een focusindicator eist. */
:focus-visible {
  outline: 3px solid var(--blauw);
  outline-offset: 3px;
  border-radius: 2px;
}
.op-blauw :focus-visible { outline-color: var(--wit); }

/* =========================================================================
   Structuur
   ========================================================================= */

.omhulsel { width: 100%; max-width: var(--breed); margin-inline: auto; padding-inline: var(--s5); }

section { padding-block: clamp(var(--s8), 6vw, var(--s10)); }
section.strak { padding-block: clamp(var(--s7), 4vw, var(--s8)); }


/* Een blauwe sectie waar wit met een afronding overheen schuift, heeft
   onderaan de ruimte van die afronding extra nodig. */
section.voor-tilt { padding-bottom: calc(clamp(var(--s8), 6vw, var(--s10)) + var(--r-xl)); }

/* Meer ruimte boven een kop dan eronder, overal dezelfde maat. */
.sectiekop { display: flex; flex-direction: column; gap: var(--s3); margin-bottom: var(--s7); max-width: 62ch; }
.sectiekop .opschrift { color: var(--accent-diep); }
.sectiekop p { color: var(--inkt-zacht); }

/* Dekking op het nachtblauwe vlak is nagerekend, niet geschat. Wit haalt er
   11,36:1 op, en met 0,95 dekking blijft daar 10.40:1 van over. Met het felle
   blauw van palet B was 0,92 nog de ondergrens en 0,90 zakte al door; op deze
   donkere ondergrond is die marge veel ruimer. De rand van de secundaire knop
   op 0,70 haalt 6.39:1, ruim boven de 3:1 die WCAG 1.4.11 eist. */
.op-blauw { background: var(--blauw); color: var(--wit); }
.op-blauw .sectiekop .opschrift { color: var(--wit); opacity: .95; }
.op-blauw .sectiekop p { color: var(--wit); opacity: .95; }
.op-diep { background: var(--blauw-diep); color: var(--wit); }
.op-vlak { background: var(--vlak); }

/* De grote afronding waarmee wit over blauw schuift, uit referentie 12. */
.tilt { border-radius: var(--r-xl) var(--r-xl) 0 0; margin-top: calc(var(--r-xl) * -1); position: relative; background: var(--wit); }

/* =========================================================================
   Knoppen. Palet 1 heeft wel een aparte actiekleur, dus de primaire knop is
   overal hetzelfde oranje en hoeft niet meer per ondergrond om te keren. De
   vorm blijft toch vast: dezelfde hoogte, radius en letterdikte overal.
   ========================================================================= */

.knop {
  font-family: var(--display); font-size: .92rem; font-weight: 700;
  letter-spacing: -.005em;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 3rem; padding: 0 var(--s5);
  border-radius: var(--r-pil); border: 2px solid transparent;
  text-decoration: none; cursor: pointer;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}

/* De primaire knop is overal dezelfde kleur, op wit en op nachtblauw. Dat kon
   met palet B niet: daar was de knopkleur gelijk aan de sectiekleur, dus moest
   de knop per ondergrond omkeren. Met een eigen accentkleur vervalt die regel,
   en dat is precies wat een accent oplevert: de bezoeker herkent de actie aan
   de kleur in plaats van aan de vorm alleen. */
.knop-primair  { background: var(--accent); color: var(--inkt); }
.knop-primair:hover  { background: var(--accent-diep); color: var(--wit); }
.knop-secundair { background: transparent; color: var(--blauw-diep); border-color: var(--rand-veld); }
.knop-secundair:hover { background: var(--vlak); border-color: var(--blauw-diep); }

.op-blauw .knop-secundair { background: transparent; color: var(--wit); border-color: rgba(255,255,255,.7); }
.op-blauw .knop-secundair:hover { border-color: var(--wit); background: rgba(255,255,255,.1); }

.knop-groep { display: flex; flex-wrap: wrap; gap: var(--s3); }

/* =========================================================================
   Kop van de site
   ========================================================================= */

.nutbalk { background: var(--blauw-diep); color: var(--wit); font-size: .82rem; }
.nutbalk .omhulsel { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); justify-content: space-between; padding-block: var(--s2); }
.nutbalk ul { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); margin: 0; padding: 0; }
.nutbalk a { color: var(--wit); text-decoration: none; }
.nutbalk a:hover { text-decoration: underline; }
.nutbalk li { display: flex; align-items: center; gap: var(--s2); }
.nutbalk svg { width: 15px; height: 15px; flex: none; opacity: .8; }

.kop { background: var(--wit); border-bottom: 1px solid var(--rand-sier); }
.kop .omhulsel { display: flex; align-items: center; gap: var(--s5); padding-block: var(--s4); flex-wrap: wrap; }

.merk { display: flex; align-items: center; gap: var(--s3); text-decoration: none; color: var(--inkt); margin-right: auto; }
.merk-teken { width: 34px; height: 34px; flex: none; }
.merk-naam {
  font-family: var(--display); font-weight: 800; font-size: 1.3rem;
  letter-spacing: -.045em; text-transform: uppercase;
}
.merk-naam span { color: var(--blauw); }

.hoofdnav ul { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s5); margin: 0; padding: 0; }
.hoofdnav a {
  font-family: var(--display); font-size: .92rem; font-weight: 600;
  color: var(--inkt); text-decoration: none; padding-block: var(--s2);
  border-bottom: 2px solid transparent;
}
.hoofdnav a:hover { color: var(--blauw-diep); border-bottom-color: var(--blauw); }
.hoofdnav a[aria-current="page"] { color: var(--blauw-diep); border-bottom-color: var(--blauw); }

.kop-telefoon {
  font-family: var(--display); font-weight: 700; font-size: .95rem;
  color: var(--inkt); text-decoration: none; white-space: nowrap;
  display: inline-flex; align-items: center; gap: var(--s2);
}
.kop-telefoon:hover { color: var(--blauw-diep); }
.kop-telefoon svg { width: 17px; height: 17px; flex: none; }

/* =========================================================================
   Mobiel menu en vaste actiebalk

   Er is geen JavaScript in deze mockup en de CSP zet `script-src` op 'none',
   dus een schakelaar moet met CSS alleen werken. Een selectievakje met een
   label is dan het enige dat overblijft dat ook met het toetsenbord bedienbaar
   is: tab brengt je erheen, spatie klapt open en dicht, en een schermlezer
   meldt de aan- of uitstand. Wat het niet doet is `aria-expanded` op een echte
   knop zetten; dat kan zonder script niet en dat is de prijs.
   ========================================================================= */

/* Weggeklemd in plaats van display:none, want dat laatste haalt het vakje uit
   de tabvolgorde en dan is het menu niet meer met het toetsenbord te openen. */
.menu-schakelaar {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}
.menu-knop { display: none; }
.actiebalk { display: none; }

/* =========================================================================
   Hero
   ========================================================================= */

.hero { background: var(--blauw); color: var(--wit); padding-block: clamp(var(--s7), 6vw, var(--s9)) 0; }
.hero .omhulsel { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); gap: clamp(var(--s5), 4vw, var(--s8)); align-items: end; }

/* De tekst draagt de onderruimte van de sectie, want het beeld moet juist
   tot de onderrand doorlopen. Plus de afronding, die er straks overheen komt. */
.hero-tekst {
  display: flex; flex-direction: column; gap: var(--s5);
  padding-bottom: calc(clamp(var(--s7), 6vw, var(--s9)) + var(--r-xl));
}
.hero-tekst .opschrift { opacity: .95; }
.hero-tekst .lead { max-width: 44ch; opacity: .92; }


/* De vrijgestelde figuur uit referentie 12. Geen kader, geen afgeronde doos:
   de figuur staat direct op het blauwe vlak en loopt door tot de onderrand,
   waar de witte afronding eroverheen schuift. Erachter een boog in
   nachtblauw. Dat is diepte uit gestapelde vlakken, precies zoals DESIGN.md
   het voorschrijft, en niet uit een schaduw.

   De hoogte staat in een variabele omdat de boog eraan vastzit. Stond eerst
   op 82% van de kolom, maar de kolom is zo hoog als de tekst en dat zegt
   niets meer over de figuur: de foto is nu een borstbeeld in plaats van een
   staande figuur, dus de boog moet met de figuur meebewegen en niet met de
   tekst. De bovengrens van 400px is geen smaak maar rekenwerk: de vrijstelling
   is 391px hoog, dus hierboven wordt er opgeschaald en dat zie je meteen. Zie
   img/BRONNEN.md. */
.hero-beeld {
  --figuur: clamp(300px, 32vw, 400px);
  position: relative; display: flex; justify-content: center; align-items: flex-end; min-height: 0;
}
.hero-beeld::before {
  content: "";
  position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
  width: min(100%, calc(var(--figuur) * 1.08)); height: calc(var(--figuur) * .88);
  background: var(--blauw-diep);
  border-radius: var(--r-pil) var(--r-pil) 0 0;
}
.hero-beeld img {
  position: relative;
  width: auto; max-width: 100%;
  height: var(--figuur);
  object-fit: contain; object-position: bottom center;
}

/* Parallax in de hero: drie lagen die met verschillende snelheid wegscrollen.

   Wat diepte geeft is niet dat er iets beweegt, maar dat lagen verschillend
   bewegen. De boog staat het verst weg en blijft dus het meest achter, de
   figuur iets minder, en de tekst gaat juist iets sneller weg. Alles binnen
   zestig pixels: parallax die je opmerkt is parallax die te ver gaat.

   Het bereik is 'exit'. De hero staat bovenaan het document, dus die begint bij
   scrollpositie nul en loopt precies zolang als de hero het beeld verlaat.

   De boog heeft in zijn ruststand al translateX(-50%) om hem te centreren. Die
   moet in elke keyframe herhaald worden, anders gooit de animatie hem terug
   naar links.

   De figuur en de boog zakken naar beneden weg. Dat kan omdat de witte sectie
   met de afronding van 40 pixels eroverheen ligt, dus ze schuiven achter dat
   vlak in plaats van eronderuit te steken. */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    @keyframes hero-boog   { from { transform: translateX(-50%) translateY(0); }
                             to   { transform: translateX(-50%) translateY(110px); } }
    @keyframes hero-tekst  { from { transform: translateY(0); }
                             to   { transform: translateY(-46px); } }

    .hero { view-timeline-name: --hero; }

    /* De vrijgestelde figuur beweegt niet mee. Hij staat op het vlak in plaats
       van in een kader, dus verschuiven laat hem los van zijn eigen boog komen
       en dat leest als een fout in plaats van als diepte. De boog erachter
       beweegt wel: dan wijkt de achtergrond terwijl de persoon blijft staan. */
    .hero-beeld::before,
    .hero-tekst {
      animation-timeline: --hero;
      animation-range: exit 0% exit 100%;
      animation-fill-mode: both;
      animation-timing-function: linear;
    }
    .hero-beeld::before { animation-name: hero-boog; }
    .hero-tekst         { animation-name: hero-tekst; }
  }
}

/* =========================================================================
   Beeld. Foto's staan in hun eigen kleuren.

   Hier stond eerst een duotoon: ontkleurd en met screen op diep blauw. Dat
   maakte elke foto merkeigen, maar het maakte ook elke foto blauw, en dan is
   een afgeronde badkamer niet meer van een dakpan te onderscheiden. Volgens
   productprincipe 2 is beeld van afgerond werk het belangrijkste bewijs dat
   er is, en bewijs in een blauwe waas bewijst niets. De merkeenheid komt nu
   uit de vlakken eromheen in plaats van uit een filter over de foto.
   ========================================================================= */

.beeld { position: relative; background: var(--vlak); overflow: clip; }
.beeld img { position: absolute; left: 0; right: 0; top: -25%; width: 100%; height: 150%; object-fit: cover; }



/* =========================================================================
   Diensten. Beeldvullende kaarten in een bento-raster, naar het patroon dat
   de opdrachtgever aanwees: foto over de hele kaart, tekst linksonder op het
   beeld. Vier kolommen, eerste kaart dubbel breed, dus rij 1 is 2+1+1 en rij 2
   is 1+1+1+1. Zeven gelijke kaarten in een raster van vier zou 4+3 geven en
   dus een gat rechtsonder.
   ========================================================================= */

.diensten {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s4);
}

.dienst {
  position: relative; overflow: clip;
  border-radius: var(--r-m);
  background: var(--wit);
  border: 1px solid var(--rand-sier);
  display: flex; flex-direction: column;
  text-decoration: none; color: var(--inkt);
  transition: transform .15s ease, border-color .15s ease;
}
.dienst--breed { grid-column: span 2; }
.dienst:hover { transform: translateY(-3px); border-color: var(--blauw); }

/* De foto staat in een eigen kader met een vaste hoogte, niet in een
   verhouding. Met een verhouding zou de dubbelbrede kaart twee keer zo hoog
   worden als zijn buren en zou de hele rij scheeflopen. Vaste hoogte houdt de
   onderkanten van een rij gelijk; de brede kaart wordt daardoor een panorama en
   dat staat goed voor de belangrijkste dienst.

   Overmaat van 150 procent, want de foto beweegt hier met parallax mee. */
.dienst-beeld { position: relative; overflow: clip; height: 200px; flex: none; background: var(--vlak); }
.dienst-beeld img { position: absolute; left: 0; right: 0; top: -25%; width: 100%; height: 150%; object-fit: cover; }

.dienst-lijf {
  padding: var(--s5);
  display: flex; flex-direction: column; gap: var(--s2);
}
.dienst-naam {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1.2rem, 1.05rem + .5vw, 1.45rem); letter-spacing: -.025em;
  line-height: 1.15;
}
.dienst-tekst { font-size: .9rem; max-width: 34ch; color: var(--inkt-zacht); }

/* Zonder foto: hetzelfde vlak, geen sluier, en het gereedschapsteken groot en
   half doorzichtig erachter. Zodra er beeld is vervangt de foto het teken. */
.dienst--leeg { background: var(--blauw); color: var(--wit); }
.dienst--leeg:hover { background: var(--blauw-diep); }
.dienst--leeg .dienst-tekst { color: var(--wit); }
.dienst-teken {
  position: absolute; right: -20px; bottom: 34%;
  width: 150px; height: 150px; color: var(--wit); opacity: .22;
  pointer-events: none;
}


/* Opsomming van vakken op een dienstpagina. Dit zijn geen kaarten en geen
   links, dus ze krijgen ook niet het beeldvullende kaartformaat: alleen het
   teken, de naam en een regel. Ze stonden eerder op .dienst met
   pointer-events:none, en dat brak zodra .dienst een beeldvullende kaart werd. */
.vak-blok {
  background: var(--wit);
  border: 1px solid var(--rand-sier);
  border-radius: var(--r-m);
}
.vak-blok-lijf { padding: var(--s5); display: flex; flex-direction: column; gap: var(--s2); }
.vak-blok-teken { color: var(--blauw); }
.vak-blok h3 { color: var(--inkt); }
.vak-blok p { color: var(--inkt-zacht); font-size: .92rem; }

/* Twee kaarten naast elkaar in plaats van vier, voor de verwante diensten
   onder aan een dienstpagina. */
.diensten--twee { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* =========================================================================
   Het mechanisme: zeven vakgebieden, een aanspreekpunt.
   Dit is wat Multiware kan en de eenmans-klusser niet, dus het krijgt een
   eigen sectie in plaats van een zin in een lijstje.
   ========================================================================= */

.mechanisme { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(var(--s6), 5vw, var(--s9)); align-items: center; }
.trechter { width: 100%; height: auto; }
.trechter .lijn { stroke: rgba(255,255,255,.5); stroke-width: 1.5; fill: none; }
.trechter .vak { fill: rgba(255,255,255,.12); stroke: rgba(255,255,255,.4); stroke-width: 1; }
.trechter .vaktekst { font-family: var(--display); font-size: 11px; font-weight: 600; fill: #ffffff; }
/* Het eindpunt is geen pil maar het merk zelf.

   DESIGN.md beschrijft het merkteken als acht lijnen die samenkomen in een
   dikke streep, en zegt erbij dat de trechter datzelfde teken op groot formaat
   is. Een witte pil eromheen maakte er een label van in plaats van een merk.
   Nu komen de zeven lijnen samen in die dikke streep en staat het woordmerk
   erachter, precies zoals in de kop en de voet: MULTI vol, WARE zachter. */
.trechter .knoop-streep { stroke: var(--wit); stroke-width: 8; stroke-linecap: butt; fill: none; }
.trechter .knooptekst {
  font-family: var(--display); font-size: 15.5px; font-weight: 800;
  letter-spacing: -.035em; fill: var(--wit);
  dominant-baseline: auto;
}
.trechter .knoop-zacht { opacity: .6; }

/* De trechter tekent zichzelf terwijl hij in beeld komt.

   Dit is het enige beweegmoment op de pagina en het heeft inhoud: zeven vakken
   die samenkomen in één aanspreekpunt is de positionering uit PRODUCT.md, en
   het merkteken is diezelfde vorm. De lijnen laten dat gebeuren in plaats van
   het te beweren.

   Drie dingen maken dit veilig:

   1. De standaardstaat is getekend, niet leeg. Zonder ondersteuning, met
      prefers-reduced-motion en in print staan alle zeven lijnen er gewoon. De
      animatie voegt toe, ze onthult niet.
   2. pathLength="1" in de HTML rekent elke lijn even lang, ongeacht zijn echte
      lengte, dus de zeven lopen synchroon.
   3. Geen JavaScript. Deze mockup draait op script-src 'none', dus dat is geen
      voorkeur maar een voorwaarde.

   De tijdlijn hangt aan de SVG en niet aan de paden zelf: een <path> heeft geen
   eigen layout-box, dus view() erop is onbetrouwbaar. De paden verwijzen naar
   de benoemde tijdlijn van hun voorouder.

   Steun: Chrome, Edge en Safari 26. Firefox zit nog achter een vlag, dus de
   @supports is geen formaliteit. */

.trechter .lijn path { stroke-dasharray: 1; stroke-dashoffset: 0; }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    @keyframes trechter-trek { from { stroke-dashoffset: 1; } }

    .trechter { view-timeline-name: --trechter; }

    .trechter .lijn path {
      animation: trechter-trek both cubic-bezier(.22, 1, .36, 1);
      animation-timeline: --trechter;
    }

    /* Elk pad krijgt zijn eigen venster, zodat de zeven na elkaar aanlopen in
       plaats van als één blok. Van boven naar beneden.

       Waarom cover en niet entry. Met entry loopt het hele bereik af terwijl
       het blok nog aan de onderrand van het scherm staat: op het moment dat je
       het echt bekijkt is het al klaar en heb je niets gezien. Cover loopt door
       tot het blok het scherm weer verlaat, dus met 28 tot 66 procent tekenen
       de lijnen zich terwijl het blok door het midden van het beeld reist.

       Expliciete waarden en geen calc met een custom property: als die
       berekening op één browser faalt, valt animation-range terug op het volle
       bereik en loopt de trap eruit. */
    .trechter .lijn path:nth-child(1) { animation-range: cover 28% cover 48%; }
    .trechter .lijn path:nth-child(2) { animation-range: cover 31% cover 51%; }
    .trechter .lijn path:nth-child(3) { animation-range: cover 34% cover 54%; }
    .trechter .lijn path:nth-child(4) { animation-range: cover 37% cover 57%; }
    .trechter .lijn path:nth-child(5) { animation-range: cover 40% cover 60%; }
    .trechter .lijn path:nth-child(6) { animation-range: cover 43% cover 63%; }
    .trechter .lijn path:nth-child(7) { animation-range: cover 46% cover 66%; }
  }
}

.mechanisme-lijst { list-style: none; margin: var(--s5) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--s3); }
.mechanisme-lijst li { display: flex; gap: var(--s3); align-items: flex-start; }
.mechanisme-lijst svg { width: 20px; height: 20px; flex: none; margin-top: .2rem; }

/* =========================================================================
   Werkwijze
   ========================================================================= */

.stappen { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--s5); counter-reset: stap; }
.stap { display: flex; flex-direction: column; gap: var(--s2); padding-top: var(--s5); border-top: 1px solid var(--rand-sier); position: relative; }
.stap::before {
  counter-increment: stap; content: counter(stap);
  font-family: var(--display); font-weight: 800; font-size: .82rem;
  position: absolute; top: calc(var(--s3) * -1); left: 0;
  background: var(--blauw); color: var(--wit);
  width: 26px; height: 26px; border-radius: var(--r-pil);
  display: grid; place-items: center;
}
.stap h3 { margin-top: var(--s2); }
.stap p { color: var(--inkt-zacht); font-size: .94rem; }

/* =========================================================================
   Werkgebied
   ========================================================================= */

/* De zeven gemeenten zijn informatie en geen actie. Ze stonden hier als pil met
   een rand en een hover, en in dit systeem betekent een pil "hier klikken". Dat
   was een belofte die nergens toe leidde: het zijn spans, niet eens links.
   Nu een opsomming met een speld ervoor. Geen rand, geen hover, geen pil. */
.plaatsen { display: flex; flex-wrap: wrap; gap: var(--s4) var(--s6); }
.plaats {
  font-family: var(--display); font-weight: 600; font-size: 1rem;
  color: var(--inkt);
  display: inline-flex; align-items: center; gap: var(--s2);
}
.plaats svg { width: 16px; height: 16px; color: var(--blauw); flex: none; }

/* =========================================================================
   Twee kolommen, gebruikt voor zakelijk en voor de dienstpagina
   ========================================================================= */

.duo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(var(--s6), 5vw, var(--s8)); align-items: center; }
.duo-beeld { border-radius: var(--r-l); overflow: clip; aspect-ratio: 3 / 2; }

.vinklijst { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s3); }
.vinklijst li { display: flex; gap: var(--s3); align-items: flex-start; }
.vinklijst svg { width: 20px; height: 20px; flex: none; color: var(--blauw); margin-top: .2rem; }
.op-blauw .vinklijst svg { color: var(--wit); }

/* =========================================================================
   Afsluitende oproep
   ========================================================================= */

/* De CTA-band uit referentie 13: links een vrijgestelde figuur die op de
   onderrand van de band staat, rechts de kopregel met het telefoonnummer
   groot naast de knop. Het nummer is hier geen link tussen de tekst maar het
   op een na grootste element van de band, want productprincipe 3 zegt dat
   elke pagina in een aanvraag eindigt en bellen de kortste weg is. */
.oproep { padding-block: clamp(var(--s7), 5vw, var(--s8)) 0; overflow: clip; }
.oproep .omhulsel {
  display: grid; grid-template-columns: minmax(0, .86fr) minmax(0, 1.14fr);
  gap: clamp(var(--s5), 3vw, var(--s7)); align-items: end;
}

/* Zelfde constructie als de hero: de boog hangt aan de figuurhoogte en niet
   aan de kolom, want de kolom is zo hoog als de tekst ernaast. De bovengrens
   van 380px komt uit de bron: de vrijstelling is 384px hoog. */
.oproep-beeld {
  --figuur: clamp(260px, 28vw, 380px);
  position: relative; display: flex; align-items: flex-end; justify-content: center;
}
.oproep-beeld::before {
  content: "";
  position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
  width: calc(var(--figuur) * .82); height: calc(var(--figuur) * .84);
  background: var(--blauw-diep);
  border-radius: var(--r-pil) var(--r-pil) 0 0;
}
.oproep-beeld img {
  position: relative;
  width: auto; max-width: 100%;
  height: var(--figuur);
  object-fit: contain; object-position: bottom center;
}

.oproep-tekst {
  display: flex; flex-direction: column; gap: var(--s4); max-width: 52ch;
  padding-bottom: clamp(var(--s7), 5vw, var(--s8));
}
.oproep-actie { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s4); margin-top: var(--s2); }
.oproep-of { font-size: .92rem; opacity: .95; }
.oproep-telefoon {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1.5rem, 1.1rem + 1.5vw, 2.3rem); letter-spacing: -.03em;
  color: var(--wit); text-decoration: none;
  display: inline-flex; align-items: center; gap: var(--s3);
}
.oproep-telefoon:hover { text-decoration: underline; }
.oproep-telefoon svg { width: 28px; height: 28px; flex: none; }

/* =========================================================================
   Parallax over de hele site

   Eén keyframe voor alles, met de begin- en eindwaarde per element in een
   custom property. Zo staat de beweging op één plek en de dosering bij het
   element waar hij hoort.

   Het bereik is cover: van het moment dat het element onderaan het scherm
   binnenkomt tot het bovenaan verdwijnt. Dat is de hele reis, en dus precies
   het venster waarin parallax hoort te werken.

   Richting. Een foto in een kader beweegt trager dan het kader zelf, dus ten
   opzichte van dat kader zakt hij naar beneden: van min naar plus. Dat is wat
   het oog leest als verder weg.

   Budget: geen enkele laag verplaatst meer dan zestig pixels over de volle
   reis, conform DESIGN.md. Alle kaders staan op overflow: clip en niet hidden,
   anders wordt het kader zelf de scrollcontainer en meet de tijdlijn tegen iets
   dat nooit scrollt.
   ========================================================================= */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    @keyframes zweef     { from { transform: translateY(var(--van)); }
                           to   { transform: translateY(var(--naar)); } }
    /* Aparte set voor lagen die al gecentreerd staan met translateX(-50%). */
    @keyframes zweef-mid { from { transform: translateX(-50%) translateY(var(--van)); }
                           to   { transform: translateX(-50%) translateY(var(--naar)); } }

    .dienst-beeld img,
    .beeld img,
    .duo-beeld img,
    .oproep-beeld::before {
      animation: zweef linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }

    /* De zeven dienstkaarten. De foto zakt binnen de kaart weg terwijl de kaart
       zelf met de pagina meegaat. */
    .dienst-beeld img { --van: -72px; --naar: 72px; }  /* 144 over ~1200 = 12% */

    /* Beeldkaders op de dienstpagina en het zakelijk-blok. Iets rustiger, want
       daar staat de foto naast lopende tekst. */
    .beeld img      { --van: -60px; --naar: 60px; }   /* 120 over ~1250 = 10% */
    .duo-beeld img  { --van: -60px; --naar: 60px; }

    /* De oproepband volgt de hero: de boog wijkt, de figuur staat stil. */
    .oproep-beeld::before { --van: -70px; --naar: 70px; animation-name: zweef-mid; }
  }
}

/* =========================================================================
   Voet
   ========================================================================= */

.voet { background: var(--blauw-diep); color: var(--wit); padding-block: var(--s8) var(--s6); }
.voet-raster { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: var(--s6); }
.voet h3 { font-size: .78rem; letter-spacing: .14em; text-transform: uppercase; opacity: .72; margin-bottom: var(--s4); }
.voet ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s2); }
.voet a { color: var(--wit); text-decoration: none; opacity: .9; }
.voet a:hover { text-decoration: underline; opacity: 1; }
.voet p { opacity: .85; font-size: .92rem; }
.voet .merk-naam { color: var(--wit); }
.voet .merk-naam span { color: var(--wit); opacity: .6; }
.voet-onder {
  margin-top: var(--s8); padding-top: var(--s5);
  border-top: 1px solid rgba(255,255,255,.22);
  display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5); justify-content: space-between;
  font-size: .84rem; opacity: .8;
}

/* =========================================================================
   Paginakop voor onderliggende pagina's
   ========================================================================= */

.paginakop { background: var(--blauw); color: var(--wit); padding-block: var(--s8) calc(var(--s8) + var(--r-xl)); }
.paginakop .omhulsel { display: flex; flex-direction: column; gap: var(--s4); max-width: var(--breed); }
.kruimels { display: flex; flex-wrap: wrap; gap: var(--s2); font-size: .85rem; opacity: .95; list-style: none; margin: 0; padding: 0; }
.kruimels a { color: var(--wit); }
.kruimels li + li::before { content: "/"; margin-right: var(--s2); opacity: .6; }

/* =========================================================================
   Formulier
   ========================================================================= */

.aanvraag { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: clamp(var(--s6), 5vw, var(--s8)); align-items: start; }

.veldgroep { display: flex; flex-direction: column; gap: var(--s5); }
.veld { display: flex; flex-direction: column; gap: var(--s2); }
.veld-rij { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--s5); }

.veld label, .keuze-titel {
  font-family: var(--display); font-weight: 700; font-size: .88rem; color: var(--inkt);
}
.veld .hint { font-size: .82rem; color: var(--inkt-zacht); }

input[type="text"], input[type="email"], input[type="tel"], select, textarea {
  font-family: var(--body); font-size: 1rem; color: var(--inkt);
  background: var(--wit);
  border: 1px solid var(--rand-veld);   /* 3,72:1 op wit, WCAG 1.4.11 */
  border-radius: var(--r-s);
  padding: var(--s3) var(--s4); min-height: 3rem; width: 100%;
}
textarea { min-height: 9rem; resize: vertical; line-height: 1.55; }
input:hover, select:hover, textarea:hover { border-color: var(--blauw-diep); }
input:focus, select:focus, textarea:focus { border-color: var(--blauw); outline: 3px solid var(--blauw); outline-offset: 1px; }
/* Geen extra dekking: --inkt-zacht haalt 7,58:1 op wit, met 0,75 eroverheen
   zakt dat naar 4,04:1 en dat is onder de 4,5:1 die placeholdertekst nodig heeft. */
::placeholder { color: var(--inkt-zacht); opacity: 1; }

fieldset { border: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s3); }
legend { padding: 0; }
.keuzes { display: flex; flex-wrap: wrap; gap: var(--s3); }
.keuze {
  display: inline-flex; align-items: center; gap: var(--s3);
  border: 1px solid var(--rand-veld); border-radius: var(--r-pil);
  padding: var(--s3) var(--s5); cursor: pointer; background: var(--wit);
  font-family: var(--display); font-weight: 600; font-size: .92rem;
}
.keuze:hover { border-color: var(--blauw-diep); }
.keuze input { accent-color: var(--blauw); width: 18px; height: 18px; margin: 0; }
.keuze:has(input:checked) { border-color: var(--blauw); background: var(--vlak); color: var(--blauw-diep); }

/* De vakkeuze in het offerteformulier: zeven aanvinkbare kaarten.

   Radius 12 en niet de pilvorm. In dit systeem betekent een pil een actie, en
   dit is een keuze. De keuzepillen "Particulier / Zakelijk" hierboven zijn wel
   pillen, dat is een oudere inconsistentie; nieuwe keuzes krijgen de kaartvorm.

   De rand is potloodgrijs en niet krijtlijn: hij draagt betekenis, en dan geldt
   WCAG 1.4.11 met 3:1. Zie de Twee-Randen-regel in DESIGN.md.

   Minimale hoogte 3rem, gelijk aan het invoerveld, wat op een telefoon meteen
   het raakdoel van 44 pixels haalt. */
.vakkeuze .hint { margin-bottom: var(--s1); }
.vakken { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--s3); }
.vak-keuze {
  display: flex; align-items: center; gap: var(--s3);
  border: 1px solid var(--rand-veld); border-radius: var(--r-m);
  padding: var(--s3) var(--s4); min-height: 3rem;
  background: var(--wit); cursor: pointer;
  font-family: var(--display); font-weight: 600; font-size: .92rem;
  color: var(--inkt);
  transition: border-color .15s ease, background-color .15s ease, color .15s ease;
}
.vak-keuze:hover { border-color: var(--blauw-diep); }
.vak-keuze input { accent-color: var(--blauw); width: 18px; height: 18px; margin: 0; flex: none; }
.vak-keuze svg { width: 22px; height: 22px; flex: none; color: var(--blauw); }
.vak-keuze:has(input:checked) { border-color: var(--blauw); background: var(--vlak); color: var(--blauw-diep); }
.vak-keuze:has(input:checked) svg { color: var(--blauw-diep); }

.turnstile {
  border: 1px dashed var(--rand-veld); border-radius: var(--r-s);
  padding: var(--s4); display: flex; align-items: center; gap: var(--s3);
  color: var(--inkt-zacht); font-size: .88rem; background: var(--vlak);
}
.turnstile svg { width: 20px; height: 20px; flex: none; color: var(--blauw-diep); }

.zijpaneel { background: var(--vlak); border-radius: var(--r-m); padding: var(--s6); display: flex; flex-direction: column; gap: var(--s5); }
.zijpaneel h2, .zijpaneel h3 {
  color: var(--inkt);
  /* Zelfde maat als een h3, want visueel is dit een paneelkop en geen
     paginasectie. Het niveau is semantisch, de maat is optisch. */
  font-size: clamp(1.1rem, 1rem + .5vw, 1.35rem);
  line-height: 1.25; letter-spacing: -.015em;
}
.zijpaneel dl { margin: 0; display: flex; flex-direction: column; gap: var(--s3); }
.zijpaneel dt { font-family: var(--display); font-weight: 700; font-size: .8rem; letter-spacing: .1em; text-transform: uppercase; color: var(--inkt-zacht); }
.zijpaneel dd { margin: 0; }
.zijpaneel a { font-weight: 600; }

/* =========================================================================
   Markering van tijdelijk materiaal. Zichtbaar, want dit is een mockup en
   niets hiervan mag ongemerkt doorschuiven naar productie.
   ========================================================================= */

.tijdelijk {
  background: transparent;
  border: 1px dashed var(--rand-veld); border-radius: var(--r-s);
  padding: var(--s5); font-size: .88rem; color: var(--inkt-zacht);
  display: flex; flex-direction: column; gap: var(--s2);
}
.tijdelijk b { font-family: var(--display); color: var(--inkt); }

/* =========================================================================
   Overgang tussen pagina's

   Je klikt op de brede dienstkaart en de foto groeit door naar het beeld op de
   dienstpagina. Geen witte flits, geen zichtbare herlaadbeurt.

   Dit werkt alleen omdat CLAUDE.md al eist dat elke route een eigen
   geprerenderd bestand krijgt: cross-document view transitions hebben precies
   dat nodig. Geen JavaScript.

   De naam mag per pagina maar een keer voorkomen. Op de homepage draagt de
   brede kaart hem, op de dienstpagina het beeldkader met .vt-badkamer. Die
   twee selectors raken elkaar nergens, dus er is geen botsing.

   Steun: Chrome 126 en hoger, Safari 18.2 en hoger. Waar het niet werkt krijg
   je een gewone paginawissel, dus de terugval is de huidige situatie.
   ========================================================================= */

@view-transition { navigation: auto; }

@media (prefers-reduced-motion: no-preference) {
  .dienst--breed .dienst-beeld img,
  .vt-badkamer img { view-transition-name: badkamer; }

  /* De rest van de pagina kruist zachtjes over, iets sneller dan de standaard
     zodat het niet als vertraging voelt. */
  ::view-transition-old(root),
  ::view-transition-new(root) { animation-duration: .28s; }
  ::view-transition-group(badkamer) { animation-duration: .42s; animation-timing-function: cubic-bezier(.22, 1, .36, 1); }
}

/* =========================================================================
   Zekerheden, tweekoloms sectiekop, stapcijfers en het woordmerk in de voet
   ========================================================================= */


/* De sectiekop in twee kolommen: kop links, uitleg rechts. Twee van de vijf
   krijgen deze vorm. Alle vijf hetzelfde was precies wat de pagina braaf
   maakte, en alle vijf tweekoloms zou dezelfde fout in spiegelbeeld zijn. */
.sectiekop--breed {
  max-width: none;
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: clamp(var(--s5), 4vw, var(--s8));
  align-items: end;
}
.sectiekop--breed p { max-width: 46ch; }

/* Het stapcijfer. Stond als cirkel van 26 pixels op de scheidingslijn, wat
   netjes was en verder niets. Nu een zwaar cijfer in de displaystijl, want de
   volgorde is hier de informatie: aanvraag, contact, offerte, uitvoering. Dat
   is precies de uitzondering die grote nummers rechtvaardigt. */
.stap::before {
  counter-increment: stap;
  content: "0" counter(stap);
  position: static;
  display: block;
  width: auto; height: auto;
  background: none; border-radius: 0;
  font-family: var(--display); font-weight: 800;
  font-size: clamp(2.4rem, 1.8rem + 2vw, 3.6rem);
  line-height: .95; letter-spacing: -.045em;
  color: var(--blauw);
  margin-bottom: var(--s3);
}
.stap { padding-top: var(--s4); }


/* =========================================================================
   Raakdoelen en formulierdetails

   DESIGN.md eist 44 pixels op smal. Een audit met Playwright liet zien dat drie
   dingen dat niet haalden: het grote telefoonnummer in de oproepband, het logo
   en het nummer in de kop. Juist dat telefoonnummer is volgens productprincipe
   3 de kortste weg naar een aanvraag, dus daar is het geen detail.

   De voetlinks blijven onder de 44 en dat is een bewuste keuze: ze op 44 zetten
   maakt de voet twee keer zo hoog. Ze halen wel de 24 pixels die WCAG 2.2 als
   ondergrens stelt, en er komt ruimte tussen zodat je er niet naast tikt.
   ========================================================================= */

.oproep-telefoon { min-height: 44px; }
.merk { min-height: 44px; }
.kop-telefoon { min-height: 44px; }
.voet a { display: inline-block; padding-block: 3px; }
.voet ul { gap: var(--s3); }

/* Een rij met maar één veld erin hoort niet over de volle breedte te lopen: een
   plaatsnaam of een e-mailadres is geen lange invoer. Met auto-fit rekt een
   enkel kind vanzelf op, dus die krijgt hier twee kolommen opgelegd. */
.veld-rij:has(> .veld:only-child) { grid-template-columns: repeat(2, minmax(220px, 1fr)); }

/* De knip tussen "wat is de klus" en "wie bent u". Een haarlijn, geen kop:
   het is één formulier en geen twee stappen. */
.veld-scheiding {
  border: 0; border-top: 1px solid var(--rand-sier);
  margin: var(--s2) 0 0;
}

/* =========================================================================
   Toestemmingsbanner

   Wordt door js/toestemming.js in de pagina gezet, niet door de HTML. Zonder
   JavaScript is er geen banner en wordt er ook geen Google Analytics geladen,
   dus dat klopt met elkaar.

   Accepteren staat links, Weigeren rechts. Die volgorde is vrij; wat niet
   vrij is, is het gewicht. Beide knoppen zijn even groot, even hoog en even
   leesbaar, alleen de kleur verschilt. Een banner waarin weigeren kleiner of
   grijzer is dan accepteren levert onder de AVG geen geldige toestemming op,
   en dat is een ontwerpregel en geen detail.

   Contrast nagerekend, zelfde methode als docs/kleuronderzoek.md:
     --inkt op --accent      7,66:1   knop Accepteren
     --blauw-diep op --wit  15,28:1   knop Weigeren
     --inkt op --wit        17,96:1   de tekst
   ========================================================================= */

.toestemming {
  position: fixed; inset: auto 0 0 0; z-index: 30;
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s4) var(--s5);
  justify-content: space-between;
  background: var(--wit); border-top: 2px solid var(--blauw);
  padding: var(--s4) clamp(var(--s4), 4vw, var(--s6))
           calc(var(--s4) + env(safe-area-inset-bottom, 0px));
}

.toestemming-tekst {
  margin: 0; max-width: 72ch;
  font-size: .95rem; line-height: 1.5; color: var(--inkt);
}
.toestemming-tekst a { color: var(--accent-diep); }

.toestemming-knoppen { display: flex; gap: var(--s3); flex: none; }

.toestemming-knop {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; min-width: 8.5rem; padding: 0 var(--s5);
  border-radius: var(--r-pil); border: 2px solid transparent;
  font-family: var(--display); font-weight: 700; font-size: .95rem;
  cursor: pointer;
}
.toestemming-nee { background: var(--wit); color: var(--blauw-diep); border-color: var(--rand-veld); }
.toestemming-ja  { background: var(--accent); color: var(--inkt); border-color: var(--accent); }
.toestemming-nee:hover { background: var(--vlak); }
.toestemming-ja:hover  { background: var(--accent-diep); color: var(--wit); }

@media (max-width: 620px) {
  /* Boven de vaste actiebalk, anders dekt de een de ander af. De balk is
     48px hoog plus 1rem padding, afgerond 4,25rem. */
  .toestemming {
    bottom: calc(4.25rem + env(safe-area-inset-bottom, 0px));
    padding-bottom: var(--s4);
  }
  .toestemming-knoppen { width: 100%; }
  .toestemming-knop { flex: 1; min-width: 0; padding: 0 var(--s3); }
}

/* =========================================================================
   Meebewegen
   ========================================================================= */

@media (max-width: 900px) {
  .hero .omhulsel,
  .mechanisme,
  .duo,
  .oproep .omhulsel,
  .aanvraag { grid-template-columns: minmax(0, 1fr); }

  /* Tekst eerst op smal. De particulier leest dit op een telefoon, en met het
     beeld bovenaan valt de propositie onder de vouw. In de hero staat de tekst
     al eerst in de HTML, in de oproepband niet, dus die draait hier om. */
  .hero-tekst { padding-bottom: var(--s6); }
  /* Alleen de maat verandert hier. De boog hangt aan --figuur en houdt zijn
     verhouding dus vanzelf, op elke breedte. */
  .hero-beeld { --figuur: clamp(280px, 52vw, 400px); }

  .oproep-beeld { order: 2; --figuur: clamp(240px, 44vw, 320px); }

  .sectiekop--breed { grid-template-columns: minmax(0, 1fr); }
  .oproep-tekst { padding-bottom: 0; }

  /* Twee kolommen; de brede kaart vult die dan allebei. */
  .diensten { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .dienst--breed { grid-column: span 2; }
  .dienst { min-height: 260px; }

  .voet-raster { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s6); }
  .trechter { display: none; }        /* de trechter is te fijn voor smal, de lijst eronder draagt de boodschap */
}

@media (max-width: 620px) {
  :root { --r-xl: 24px; }
  /* Het kader krimpt mee, anders eet het op een telefoon de leesbreedte op. */
  .paneel { margin: var(--s2); border-radius: var(--r-l); }
  .diensten { grid-template-columns: minmax(0, 1fr); }
  .dienst--breed { grid-column: auto; }
  .dienst { min-height: 240px; }

  .voet-raster { grid-template-columns: minmax(0, 1fr); }

  /* De nutbalk kost op een telefoon drie regels donkerblauw voordat het logo
     in beeld komt. Adres en werkgebied staan ook in de voet, dus die gaan hier
     weg; e-mail en telefoon blijven, want dat zijn de twee dingen waarop
     iemand met een lekkende kraan meteen wil klikken. */
  .nutbalk li:nth-child(3) { display: none; }
  .nutbalk ul + ul { display: none; }

  /* --- kop wordt logo plus menuknop --- */
  .kop .omhulsel { gap: var(--s3); flex-wrap: wrap; }
  .menu-knop {
    display: inline-flex; align-items: center; gap: var(--s2);
    font-family: var(--display); font-weight: 700; font-size: .88rem;
    color: var(--inkt); cursor: pointer;
    background: var(--wit);
    border: 1px solid var(--rand-veld); border-radius: var(--r-pil);
    padding: 0 var(--s4); min-height: 44px;   /* 44px is de kleinste maat die
                                                 een duim betrouwbaar raakt */
  }
  .menu-icoon { width: 20px; height: 20px; flex: none; }
  .menu-icoon-dicht { display: none; }
  .menu-schakelaar:checked + .menu-knop .menu-icoon-open { display: none; }
  .menu-schakelaar:checked + .menu-knop .menu-icoon-dicht { display: block; }
  .menu-schakelaar:focus-visible + .menu-knop {
    outline: 3px solid var(--blauw); outline-offset: 3px;
  }

  /* Telefoon en offerteknop staan onderin in de vaste balk, dus hier weg. */
  .kop-telefoon, .kop .knop-primair { display: none; }

  /* --- het uitklapmenu zelf --- */
  .hoofdnav { display: none; order: 3; width: 100%; }
  .menu-schakelaar:checked ~ .hoofdnav { display: block; }
  .hoofdnav ul { flex-direction: column; gap: 0; }
  .hoofdnav li + li { border-top: 1px solid var(--rand-sier); }
  .hoofdnav a {
    display: block; width: 100%;
    padding: var(--s3) 0; font-size: 1rem;
    border-bottom: none;
  }
  .hoofdnav a:hover,
  .hoofdnav a[aria-current="page"] { color: var(--blauw-diep); border-bottom: none; }

  /* --- vaste actiebalk --- */
  .actiebalk {
    display: grid; grid-template-columns: 1fr 1.35fr; gap: var(--s2);
    position: fixed; inset: auto 0 0 0; z-index: 20;
    background: var(--wit); border-top: 1px solid var(--rand-sier);
    padding: var(--s2) var(--s3) calc(var(--s2) + env(safe-area-inset-bottom, 0px));
  }
  .actie {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
    min-height: 48px; border-radius: var(--r-pil);
    font-family: var(--display); font-weight: 700; font-size: .95rem;
    text-decoration: none;
    color: var(--blauw-diep); background: var(--wit);
    border: 2px solid var(--rand-veld);
  }
  .actie svg { width: 18px; height: 18px; flex: none; }
  .actie-nadruk { background: var(--accent); color: var(--inkt); border-color: var(--accent); }

  /* Ruimte onder de pagina, anders dekt de balk de laatste regels af. */
  body { padding-bottom: 5rem; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
  .dienst:hover { transform: none; }
}

@media print {
  .nutbalk, .hoofdnav, .oproep { display: none; }
  body { color: #000; }
}

/* ---------------------------------------------------------------------------
   Juridische pagina's: privacyverklaring en algemene voorwaarden.

   Eigen blok omdat deze pagina's iets zijn wat de rest van de site niet is:
   lange lopende tekst met genummerde artikelen die iemand moet kunnen
   naslaan. Smallere regellengte dan .prose, want juridische tekst wordt
   gescand op een artikelnummer en niet gelezen als een verhaal.
   --------------------------------------------------------------------------- */

.juridisch { max-width: 68ch; padding-block: var(--s8); }
.juridisch > * + * { margin-top: var(--s4); }
.juridisch h2 {
  font-size: clamp(1.15rem, 1rem + .5vw, 1.4rem);
  margin-top: var(--s7);
  padding-top: var(--s5);
  border-top: 1px solid var(--rand-sier);
}
.juridisch h2:first-of-type { margin-top: var(--s6); }
.juridisch h3 { font-size: 1rem; margin-top: var(--s5); }
.juridisch p, .juridisch li { color: var(--inkt); }
.juridisch ul, .juridisch ol { margin-left: var(--s5); }
.juridisch li + li { margin-top: var(--s2); }
.juridisch table { border-collapse: collapse; width: 100%; }
.juridisch th, .juridisch td {
  text-align: left; vertical-align: top;
  padding: var(--s3) var(--s4) var(--s3) 0;
  border-bottom: 1px solid var(--rand-sier);
}
.juridisch th { font-weight: 600; width: 34%; }

/* Wat de opdrachtgever nog moet invullen of bevestigen. Opzettelijk lelijk,
   zodat het niet ongemerkt live gaat.

   NIET IN GEBRUIK sinds 5 september 2026. De drie blokken die er waren, twee op
   de privacyverklaring en een op de algemene voorwaarden, stonden op pagina's
   die voor klanten zijn bedoeld. Huiswerk voor de opdrachtgever hoort daar niet
   te staan, hoe opvallend de balk ook is. Ze staan nu in PRODUCT.md.

   De klasse blijft staan omdat hij nuttig is tijdens het bouwen van een nieuwe
   pagina. Regel voor gebruik: hij mag in de repo staan, hij mag nooit mee de
   deploy in. Controleer dat met een grep voordat je publiceert. */
.nog-invullen {
  background: #fff4e5;
  border-left: 3px solid var(--accent);
  padding: var(--s4);
}

/* Juridische links in de onderbalk van de voet. Op een smal scherm vallen ze
   onder elkaar in plaats van dat ze de KVK-regel wegdrukken. */
.voet-juridisch { display: flex; flex-wrap: wrap; gap: var(--s3) var(--s4); }

/* De knop Cookievoorkeuren, die js/toestemming.js hier neerzet. Hij moet niet
   te onderscheiden zijn van de links ernaast: toestemming intrekken hoort net
   zo makkelijk te zijn als geven, en dan hoort de weg terug net zo zichtbaar
   te zijn als de rest. Het blijft een button en geen link, want er wordt niet
   genavigeerd. */
.voet-knop {
  background: none; border: 0; padding: 0;
  font: inherit; color: inherit;
  text-decoration: underline; text-underline-offset: 3px;
  cursor: pointer;
}

/* =========================================================================
   Gemeentepagina's. Zeven pagina's die per gemeente iets anders vertellen,
   gegenereerd door scripts/gemeentepaginas.py.

   Bewust sober: de homepage doet het beeldwerk, deze pagina's doen de tekst.
   Wie hier terechtkomt zoekt op vak plus plaats en wil weten of dit bedrijf
   zijn soort woning kent, niet nog een keer een fotogalerij.
   ========================================================================= */

.uitleg-raster {
  display: grid; gap: var(--s5);
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}
.dienst-uitleg {
  background: var(--wit);
  border: 1px solid var(--rand-sier);
  border-radius: var(--r-m);
  padding: var(--s5);
}
.dienst-uitleg h3 { margin-bottom: var(--s3); }
.dienst-uitleg p { color: var(--inkt-zacht); }

/* De zeven vakken als lijst en niet als kaarten met foto's: op deze pagina
   dragen ze het verhaal niet, ze bevestigen alleen de breedte. */
.vak-lijst {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--s3);
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}
.vak-regel {
  display: flex; align-items: center; gap: var(--s3);
  background: var(--wit);
  border: 1px solid var(--rand-sier);
  border-radius: var(--r-s);
  padding: var(--s4);
}
.vak-regel svg { width: 1.25rem; height: 1.25rem; flex: none; color: var(--blauw); }

/* De vakken die bij deze gemeente het meest spelen, krijgen nadruk. Met een
   rand en een vetter woord, niet met kleur alleen: kleur is geen informatie
   voor wie hem niet ziet. */
.vak-regel--nadruk {
  border-color: var(--blauw);
  border-width: 2px;
  font-weight: 600;
}

.plaats-lijst {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: var(--s3);
}
.plaats-lijst a {
  display: inline-block;
  border: 1px solid var(--rand-sier);
  border-radius: 999px;
  padding: var(--s3) var(--s5);
  text-decoration: none;
  font-weight: 500;
}
.plaats-lijst a:hover { border-color: var(--blauw); }

/* De paginakop heeft een blauwe achtergrond maar niet de klasse op-blauw, dus
   de regels daarvoor golden er niet. Zolang er alleen tekst in stond viel dat
   niet op; zodra er een secundaire knop in kwam wel: donkerblauwe letters op
   blauw, contrast 1,34 waar 4,5 de eis is. Gevonden door Lighthouse op
   klusbedrijf-zoetermeer.

   Hier gerepareerd en niet in de zeven gemeentepagina's, zodat de volgende die
   een knop in een paginakop zet er geen last van heeft. */
.paginakop .knop-secundair {
  background: transparent;
  color: var(--wit);
  border-color: rgba(255,255,255,.7);
}
.paginakop .knop-secundair:hover {
  border-color: var(--wit);
  background: rgba(255,255,255,.1);
}
.paginakop :focus-visible { outline-color: var(--wit); }
