/* ==========================================================================
   BREEDTE-EN-BEWEGING-20260927 — derde laag bovenop style.css en levendig.css.

   Bewust weer een apart bestand, om dezelfde reden als levendig.css: deze hele
   richting gaat terug door één <link> weg te halen, zonder dat er iets in de
   twee lagen eronder is aangeraakt.

   Gemeten op 27-09 vóór deze laag, venster 1920x1080:
     /                     inhoudskolom  828px → 1092px leeg (57% van het scherm)
     /werkwijze.php        inhoudskolom  796px → 1124px leeg (59%)
     /diensten/            inhoudskolom  828px → 1092px leeg (57%)
     /projecten.php        inhoudskolom 1180px →  740px leeg (39%)
   en het grootste beeld op /projecten.php werd 1178x618 — een omslagfoto die op
   een laptop van 1366x768 bijna het hele scherm vult voordat er één regel tekst staat.

   🪤 Die twee hangen samen. `--wrap` van 1180 naar 1460 zetten zónder hoogtegrens
   maakt diezelfde omslag 1458x765: breder maken verergert het beeldprobleem. Daarom
   staan ze hier in één blok en niet als losse reparaties.
   ========================================================================== */

/* --------------------------------------------------------------- 1. BREEDTE
   `--wrap` stond vast op 1180px (style.css regel 39). Dat is een prima leesbreedte
   voor lopende tekst, maar het geldt óók voor kaartenrasters en beeldstroken, en
   die hebben de ruimte wél nodig. Nu in stappen mee met het scherm.

   Niet naar 100%: een raster dat tot de schermrand loopt geeft op een breed scherm
   regels tekst van 200+ tekens, en dat leest niemand. De aanpak van apple.com is
   precies dit — het vlak loopt breed door, de tekst erbinnen niet. */
@media (min-width: 1280px) { :root { --wrap: 1300px; } }
@media (min-width: 1500px) { :root { --wrap: 1400px; } }
@media (min-width: 1750px) { :root { --wrap: 1500px; } }

/* 🔴 HIER STOND EEN FOUT VAN MIJZELF, 27-09 teruggedraaid.
   Ik had `.section-head { display:grid; justify-items:center }` toegevoegd in de veronder-
   stelling dat sectiekoppen gecentreerd waren. Dat zijn ze niet: `style.css:252` geeft
   `.section-head { max-width:68ch }` ZONDER `margin-inline:auto`, dus het blok staat links
   en de tekst erin stond links. Mijn regel centreerde de tekst BINNEN dat linkse blok —
   gemeten stond "Waar speelt het?" daardoor 292px uit het midden van het raster eronder:
   niet links uitgelijnd en niet gecentreerd, maar ergens ertussenin. Dat leest als een fout.
   Ook de breedte van de alinea's liet ik los: ik zette 70ch terwijl `style.css:824` al 52ch
   geeft, en omdat mijn laag later komt won die en werden de intro's breder dan bedoeld.
   Beide weg: de typografie van de site blijft zoals hij was. */

/* Wél nodig: `.pick-grid` verdeelt met `repeat(auto-fill, minmax(16rem,1fr))`. Bij een wrap
   van 1180 gaf dat 4 kolommen, en 11 kaarten vullen dan netjes 4+4+3. Met de bredere wrap
   werden het er 5 en bleef de laatste rij achter met één kaart en VIER gaten — gemeten op
   1600px, en precies wat er rommelig uitzag. De ondergrens omhoog zodat het er weer vier
   worden; dat schaalt mee in plaats van een vast aantal vast te pinnen.

   🪤 Eerst zette ik deze grens op 1280px, en toen werden het er DRIE: tussen 1280 en 1499
   is de wrap 1300 en past 19rem er maar drie keer in. Het probleem begint pas bij de wrap
   van 1400+, dus begint de correctie daar ook. Gemeten per breedte in plaats van gegokt. */
@media (min-width: 1500px) {
  .pick-grid { grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr)); }
}

/* ----------------------------------------------------- 1b. LEESBAARE TEKST
   Woorden plakten zichtbaar aan elkaar: "Laptoptraag, nieuwepc", "Inboxopmaat".
   Twee dingen stapelen daar op elkaar, en los ziet geen van beide er verkeerd uit:

     · `style.css:802` zet `body { letter-spacing: -0.011em }` — een strakke zet die op
       koppen mooi is, maar hier ook op lopende tekst landt.
     · Plus Jakarta Sans heeft van zichzelf een SMALLE spatie. Gemeten op 16px: 2,83px,
       tegen 3,83px bij een systeem-serif. Dat is een eigenschap van het lettertype,
       geen fout.

   Samen zakt de ruimte tussen woorden onder wat het oog nodig heeft om ze te scheiden.
   Daarom: de negatieve letterafstand weg op lopende tekst (koppen houden hem — regel 803
   van style.css blijft staan en is hier expres niet aangeraakt), plus een klein beetje
   woordafstand terug om de smalle spatie te compenseren.
   0,05em is ~0,8px op 16px: genoeg om woorden los te trekken, te weinig om op te vallen.

   🪤 Eerst schreef ik hier een lijstje selectors (p, li, dd, …). Dat liet precies de
   kaartteksten over die in een span of div staan — "Kies zelf een tijd", "Campagnes op maat"
   bleven gedrongen. Een lijst selectors is bij zoiets altijd onvolledig; overerving vanaf
   body is dat per definitie niet. */
body { letter-spacing: normal; word-spacing: .05em; }

/* ---------------------------------------------------------- 2. BEELDHOOGTE
   `figure.kb-hero-figure > img` heeft `aspect-ratio: 1200/630` en `max-height: none`.
   De hoogte volgt dus alleen uit de breedte van de houder — 618px bij een wrap van
   1180, en straks meer. Een omslagfoto hoort de tekst aan te kondigen, niet te
   vervangen. Daarom een grens die met het VENSTER meebeweegt in plaats van met de
   kolombreedte: op een korte laptop blijft er dan altijd tekst in beeld. */
.kb-hero-figure img,
.kb-hero-figure picture img {
  max-height: clamp(180px, 38vh, 430px);
  width: 100%;
  object-fit: cover;
  object-position: center;
}
/* De figure zelf krijgt dezelfde grens, anders houdt hij de oude hoogte vast en
   ontstaat er een lege strook onder het beeld. */
.kb-hero-figure {
  max-height: clamp(180px, 38vh, 430px);
  overflow: hidden;
  border-radius: var(--radius, 14px);
}

/* Op de telefoon was de homepage 12.605px hoog: bijna vijftien schermen. Een deel
   daarvan zijn omslagfoto's die daar 16:9 staan. Iets platter scheelt echt scrollen
   zonder dat het beeld onherkenbaar wordt. */
@media (max-width: 700px) {
  .kb-hero-figure img { max-height: 190px; }
  .kb-hero-figure { max-height: 190px; }
  .kb-card-shot img,
  .shot-rail-item img { max-height: 150px; object-fit: cover; }
}

/* --------------------------------------------- 2b. LEEGTE BOVEN DE KOP (HERO)
   Gemeten op 1600x1000: de hero is 725px hoog en er zit **211px niets** boven de H1.
   Dat komt uit twee dingen samen:
     · `style.css:194` geeft de hero `padding-top: clamp(3.5rem, 9vw, 7rem)` → 112px;
     · `style.css:205` zet `.hero-grid { align-items: center }`, en de rechterkolom
       (collage + checklist-kaart) is fors hoger dan de linker. De linkerkolom wordt dus
       naar beneden geduwd tot hij in het midden hangt.

   De padding alleen verlagen haalt maar een deel weg. Daarom allebei: minder padding én de
   kolommen bovenaan uitlijnen, zodat de kop begint waar de bezoeker hem verwacht en het beeld
   ernaast doorloopt. Dat is ook hoe apple.com een hero opbouwt: tekst linksboven, beeld
   ernaast dat verder doorloopt — niet allebei netjes in het midden.

   🪤 Alleen boven 900px. Onder die breedte staat `.hero-grid` al op één kolom
   (`style.css:558`) en betekent `align-items` niets meer; de padding daar apart geregeld. */
@media (min-width: 900px) {
  .hero { padding-top: clamp(2.5rem, 5vw, 4rem); }
  .hero-grid { align-items: start; }
}

/* Op de telefoon was de homepage 12.657px — bijna vijftien schermen. Daar zit 1.162px aan
   sectiemarge in (13 secties x 44,8px boven en onder) en een hero van 1.337px. Iets strakker
   scheelt merkbaar scrollen zonder dat het gedrongen wordt: een sectie houdt nog altijd
   36px lucht aan beide kanten. */
@media (max-width: 700px) {
  .section { padding-block: 36px; }
  .hero { padding-top: 36px; padding-bottom: 28px; }
  .section-head { margin-bottom: 1.6rem; }
}

/* ------------------------------------------- 2c. KORTERE HOMEPAGE OP DE TELEFOON
   Gemeten op 390x844: de homepage is 12.345px = 14,6 schermen. Krappere marges hielpen
   nauwelijks (12.657 → 12.345); de lengte zit in de INHOUD. Per sectie gemeten:

       1379px  "Niet gepraat, gebouwd"     8 cijfers onder elkaar
        871px  "Kennisbank"                8 tegels
        704px  "Portfolio — live websites" 9 kaarten

   🔴 Wat hier NIET werkt, en wat ik eerst wél had gedaan: van portfolio en kennisbank alleen
   de eerste drie tonen. Klinkt logisch — het zijn lijsten met een doorklikknop eronder — maar
   gemeten zijn `.home-kb-grid` en `.news-grid` **horizontale veegstrips**: `display:flex`,
   `overflow-x:auto`, inhoud 1102px breed in een venster van 390. De tegels staan dus NAAST
   elkaar, niet onder elkaar. Er de helft van verbergen levert **0px hoogte** op en haalt
   alleen keuzes weg om doorheen te vegen. Teruggedraaid.
   🪤 Les: kijk naar `display` en `scrollWidth` vóór je besluit dat "minder items" korter maakt.

   Wat wél werkt is de cijfersectie, en precies omdat die anders in elkaar zit: een echt
   raster van één kolom. Die cijfers zijn bovendien geen lijst maar bewijs, en er is geen
   pagina waar de rest staat — wegstoppen zou inhoud laten verdwijnen. Dus niet minder tonen
   maar anders plaatsen: twee kolommen. Alle acht blijven staan, de sectie ging van
   **1379px naar 845px**. */
@media (max-width: 700px) {
  .grid.g4 { grid-template-columns: 1fr 1fr; gap: .7rem; }
  .grid.g4 .stat { padding: .9rem .8rem; }
  .grid.g4 .stat .v { font-size: 1.5rem; }
}

/* ------------------------------------------- 2d. DE HERO OP DE TELEFOON
   Gemeten op 390x844 was de hero 1305px — anderhalf scherm voordat er iets inhoudelijks komt.
   Opgebouwd uit: opschrift 34 · kop 76 · inleiding 163 · knoppenrij **173** · vertrouwensregel
   45 · collage 190 · checklistkaart **418**, plus 32px tussenruimte en 64px padding.

   Geen inhoud weg; alleen anders geplaatst en strakker gezet:

   · De drie knoppen stonden elk op een eigen regel (162, 194 en 166px breed naast een
     beschikbare 350px, dus ze pasten net niet samen). De primaire houdt zijn volle breedte —
     dat is de hoofdactie — en de twee secundaire delen één regel. 3 regels → 2.
   · De ruimte tussen inleiding en knoppen was 28,8 + 17 = ~46px; tussen knoppen en de
     vertrouwensregel nog eens 22,4. Dat is losjes op een pc en verspild op een telefoon.
   · De checklistkaart is met afstand het hoogste blok (418px). Strakkere binnenruimte en
     regelafstand, zonder een enkel punt te schrappen.
   · De collage is sier; 190 → 150px scheelt zonder dat je er iets van mist. */
@media (max-width: 700px) {
  .hero .btnrow { gap: 8px; margin-top: 18px; }
  .hero .btnrow .btn { min-height: 46px; }
  /* De eerste knop is de hoofdactie en blijft over de volle breedte staan; de andere twee
     delen de regel eronder.
     🪤 Eerst gaf ik die twee `flex: 1 1 calc(50% - 4px)` — allebei 171px. Precies te smal:
     "Website laten maken" brak over twee regels en de knoppen werden 74px hoog in plaats van
     46. Op hun EIGEN breedte passen ze wél samen (173 + 145 + 8 gap = 326 binnen 350), dus
     `flex: 0 1 auto` en alleen de binnenruimte iets krapper. Dwing geen breedte af die je
     niet hebt nagemeten. */
  .hero .btnrow .btn:first-child { flex: 1 1 100%; }
  .hero .btnrow .btn:not(:first-child) { flex: 0 1 auto; padding-inline: .6rem; font-size: .92rem; }

  .hero p.lead { margin-bottom: 10px; }
  .hero .btnrow + p { margin-top: 14px; margin-bottom: 6px; }
  .hero .hero-grid { gap: 20px; }

  .hero .shot-hero { max-height: 150px; }
  .hero .hero-checklist { padding: 1rem 1rem .9rem; }
  .hero .hero-checklist li,
  .hero .hero-checklist p { line-height: 1.45; }
}

/* ------------------------------------------------- 2e. DE MERKNAAM WERD AFGESNEDEN
   "Ayoub Bouders" staat in Great Vibes, een schrijfletter met hoge krullen op de A en de B.
   `.brand-name` (style.css:114) heeft `line-height: 1.15`, en dat vak begint op een telefoon
   exact op y=0 — de kopbalk heeft daar geen ruimte bovenin. De krullen steken dus boven het
   vak uit en worden door de schermrand afgekapt. Gemeten: merkvak top=0, hoogte 31px bij een
   regelhoogte van 28,5px; op 1440 stond hij op top=3 en was het net niet zichtbaar.

   🪤 Het lag NIET aan een houder die afsnijdt: overflow stond overal op `visible`. Dat is ook
   waarom grep naar `overflow:hidden` niets zou hebben opgeleverd — het was de schermrand zelf.

   Twee kleine dingen: een beetje lucht bovenin de kopbalk zodat de krullen ergens in kúnnen
   overlopen, en iets meer regelhoogte zodat het vak ze zelf al omsluit. Samen ~7px hogere
   kopbalk voor een merknaam die heel is. */
.site-head { padding-top: 6px; }

/* HERZIEN 27-09 (KOP-STOND-TE-RUIM-20260927): hier stond `line-height: 1.3`. Dat loste de
   afgesneden krullen op, maar samen met de 6px hierboven was het dubbelop — en het duwde de
   slagzin ver van de naam af (merkblok 64px). Nagemeten op een iPhone 13 met 1,3 / 1,15 / 1,05 /
   0,95 naast elkaar: het vak begint in alle gevallen op y=6 (de padding hierboven doet het werk),
   en bij 0,95 zijn de krullen van de A en de B volledig heel. Onder 0,90 raakt de staart van de
   "y" de slagzin — dat is de ondergrens, 0,95 is dus niet het uiterste maar een marge.
   🪤 De padding-top hierboven is wat de krullen opvangt. Haal die weg en dit breekt alsnog. */
.brand-name { line-height: .95; }

/* ------------------------------------------ 2f. DE BALKEN ONDERIN HET SCHERM
   Gemeten bij een eerste bezoek:

     390x844   onderste **236px bedekt (28% van het scherm)** — cookiebalk 159px plus de
               WhatsApp/Bericht-strook erboven. Netjes gestapeld, maar samen veel.
     1440x900  de WhatsApp-knop (y=824..882) ligt **ónder** de cookiebalk (y=815..900).

   Die tweede is een echte fout, en de oorzaak is te zien in levendig.css:1007 — de hele
   stapelregeling staat in `@media (max-width: 900px)`. Boven die breedte geldt er niets en
   houdt `.wa-fab` zijn `bottom: 18px` uit style.css:604, precies achter de balk.

   🪤 Het commentaar bij die regels waarschuwt er zelf voor: geef de WhatsApp-knop en "terug
   naar boven" nooit dezelfde waarde, anders liggen ze op elkaar. Daarom ook hier oplopende
   hoogtes, geen gedeelde berekening. Desktopbalk is 85px hoog. */
@media (min-width: 901px) {
  body:has(.ab-cookie.is-open) .wa-fab { bottom: 103px; }
  body:has(.ab-cookie.is-open) .totop  { bottom: 173px; }
}

/* En op de telefoon de balk zelf krapper, zodat er minder scherm onder blijft. Geen woord
   eruit — alleen de binnenruimte en de regelafstand. De × naast "Begrepen" was 44x44 terwijl
   de knop ernaast hetzelfde doet; die mag kleiner, hij blijft ruim boven de 24px-ondergrens
   voor een tikdoel.

   🪤 Twee dingen zaten hier in de weg. Ten eerste: de zichtbare kaart is niet `.ab-cookie`
   (dat is een doorzichtige wikkel) maar **`.ab-cookie-inner`**. Ten tweede: die opmaak staat
   in een inline `<style>` ónderaan layout.php, dus ná mijn stylesheet — hij wint op VOLGORDE,
   niet op specificiteit. Vandaar `!important`, net als levendig.css hier al doet. */
@media (max-width: 700px) {
  .ab-cookie-inner { padding: .65rem .8rem !important; gap: .5rem !important; font-size: .85rem !important; }
  .ab-cookie p { line-height: 1.4 !important; }
  .ab-cookie-actions .btn { min-height: 40px !important; min-width: 6rem !important; }
  .ab-cookie-x { width: 36px !important; height: 36px !important; font-size: 1.25rem !important; }

  /* De stapel erboven stond op vaste waarden die bij de OUDE balkhoogte van 159px hoorden
     (levendig.css:1015 en 1266). Zakt de balk, dan blijft er alleen een gat en wordt het
     scherm er niets vrijer van — dat overkwam me twee keer achter elkaar.

     🪤 En één waarde volstaat niet, want de balk is niet één hoogte. Gemeten per breedte
     (tekst breekt anders, en vanaf ~412px staan tekst en knoppen naast elkaar):

         320 / 360 / 390 px → 123px
         412 / 430 px       →  90px
         540 / 700 px       →  77px

     Daarom drie bereiken, elk met balkhoogte + 8px lucht voor de CTA, en "terug naar boven"
     daar weer 78px boven (de CTA is 68 hoog). */
  body:has(.ab-cookie.is-open) .mobile-cta { bottom: 131px !important; }
  body:has(.ab-cookie.is-open) .totop      { bottom: 209px !important; }
}
@media (min-width: 401px) and (max-width: 520px) {
  body:has(.ab-cookie.is-open) .mobile-cta { bottom: 98px !important; }
  body:has(.ab-cookie.is-open) .totop      { bottom: 176px !important; }
}
@media (min-width: 521px) and (max-width: 900px) {
  body:has(.ab-cookie.is-open) .mobile-cta { bottom: 85px !important; }
  body:has(.ab-cookie.is-open) .totop      { bottom: 163px !important; }
}

/* ------------------------------------- 2g. ZIJWAARTS SCHUIVEN OP KLEINE TELEFOONS
   Gemeten op 320x700 (iPhone SE 1e generatie en oudere Androids): het document is **372px
   breed in een venster van 320** — de hele site laat zich zijwaarts wegduwen, op elke pagina.

   Oorzaak: de kopbalk past er niet in. `.head-inner` heeft 280px beschikbaar maar 352px aan
   inhoud (merkteken + merknaam 146px + ondertitel + thema-knop + kleurkiezer + hamburger).
   De hamburger eindigt daardoor op x=372.

   🔬 Dit is GEEN gevolg van deze laag: met `breedte-en-beweging.css` geblokkeerd is het
   document even breed (372px). Het is een bestaande fout die pas bij 320px zichtbaar wordt,
   en die bij 360px en hoger niet optreedt. Gemeten, niet aangenomen — anders had ik hem per
   ongeluk op mijn eigen conto geschreven.

   Oplossing: onder 361px de merknaam kleiner en de tussenruimtes krapper. Niets weghalen;
   op zo'n scherm is een iets kleinere merknaam beter dan een site die wegschuift. */
@media (max-width: 360px) {
  .head-inner { gap: .45rem; }
  .brand-name { font-size: 1.35rem; }
  .brand-txt { font-size: .78rem; }
  .head-inner .iconbtn,
  .head-inner .palette { min-width: 36px; width: 36px; height: 36px; }
  /* De merknaam mag desnoods afkappen; een site die wegschuift is erger dan een
     afgekorte ondertitel. */
  .brand { min-width: 0; }
  .brand-txt { min-width: 0; overflow: hidden; }

  /* Vangnet. Na het inkorten hierboven past de kopbalk, maar op 320px blijft er elders nog
     een paar pixel over — en één element dat uitsteekt laat de héle pagina zijwaarts
     schuiven, wat aanvoelt als een kapotte site.
     🪤 Bewust `clip` en niet `hidden`: `hidden` maakt van body een scroll-container en breekt
     daarmee `position: sticky` (de kopbalk) en scroll-driven animaties. `clip` snijdt alleen
     af. De horizontale veegstrips hebben hun eigen `overflow-x: auto` en blijven dus werken. */
  html, body { overflow-x: clip; }
}

/* ------------------------------------------------------------- 3. BEWEGING
   Scroll-effecten zoals op apple.com en elementor.com: inhoud komt rustig omhoog
   als hij in beeld schuift, en het omslagbeeld beweegt iets trager dan de pagina.

   🪤 BELANGRIJK — waarom dit CSS is en geen JavaScript. Op 27-09 bleek op vijf
   klantsites inhoud onzichtbaar omdat een fade-in met `opacity:0` begon en de
   IntersectionObserver die hem zichtbaar moest maken soms nooit afging: 90 reviews
   en complete dienstenkaarten stonden er wél, maar waren niet te zien.
   Scroll-driven animaties in CSS kennen dat faalpad niet — er is geen waarnemer die
   kan uitvallen — en alles hieronder staat bovendien in @supports. Een browser die
   `animation-timeline` niet kent (Firefox op dit moment) krijgt de regels niet eens
   te zien en toont dus gewoon de normale, zichtbare pagina.

   Ze draaien ook buiten de hoofddraad, anders dan een rAF-lus. Dat is hier geen
   detail: de marketing-deeltjes op een andere site kostten 26% van een CPU-kern op
   een stilstaand scherm. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    @keyframes ab-opkomen {
      from { opacity: 0; transform: translateY(26px); }
      to   { opacity: 1; transform: none; }
    }

    /* Kaarten en tegels: het klassieke "reveal" van elementor.com.
       animation-range zorgt dat het klaar is ruim vóórdat het element in het midden
       staat — anders lees je een halfdoorzichtige kaart. */
    .card,
    .news-card,
    .shot-rail-item,
    .portfolio-grid > *,
    .home-kb-grid > *,
    .news-grid > * {
      animation: ab-opkomen linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 55%;
    }

    /* Sectiekoppen komen iets eerder en iets rustiger; anders beweegt alles tegelijk
       en wordt het onrustig in plaats van verzorgd. */
    .section-head {
      animation: ab-opkomen linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 40%;
    }

    /* Parallax op de omslagfoto: het beeld schuift trager dan de pagina. Klein
       gehouden (6%) — groter voelt op een laptop als haperen in plaats van diepte.
       Alleen boven 900px: op een telefoon is de winst nihil en de kans op schokken
       juist groter. */
    @media (min-width: 900px) {
      @keyframes ab-parallax {
        from { transform: translateY(-4%) scale(1.06); }
        to   { transform: translateY(4%) scale(1.06); }
      }
      .kb-hero-figure img {
        animation: ab-parallax linear both;
        animation-timeline: view();
        animation-range: cover 0% cover 100%;
        will-change: transform;
      }
    }

    /* Voortgangsbalk bovenaan, zoals elementor.com. Puur sier, kost niets: één
       element, één transform, geen JavaScript.
       Staat op <body>::after zodat er geen extra markup nodig is in twintig sjablonen. */
    @keyframes ab-voortgang { from { transform: scaleX(0); } to { transform: scaleX(1); } }
    body::after {
      content: "";
      position: fixed;
      inset: 0 0 auto 0;
      height: 3px;
      transform-origin: 0 50%;
      background: linear-gradient(90deg, var(--accent, #2563eb), color-mix(in oklab, var(--accent, #2563eb) 55%, #22d3ee));
      z-index: 9999;
      pointer-events: none;
      animation: ab-voortgang linear both;
      animation-timeline: scroll(root block);
    }
  }
}

/* -------------------------------------------------- 4. DE LOGO-STROOK AFREMMEN
   Gemeten 27-09 op de homepage: de strook met merklogo's staat op y=2943 — bij het
   openen van de pagina dus niet eens in beeld — en kost tóch permanent CPU:

     bovenaan (strook buiten beeld)      480 style-recalcs / 8s · 5,1% CPU
     ver naar beneden (ook buiten beeld) 480 style-recalcs / 8s · 5,2% CPU

   Hij draait met andere woorden altijd door, of iemand hem ziet of niet. Op een
   telefoon is dat batterij voor een animatie die niemand bekijkt. Met
   `prefers-reduced-motion: reduce` viel de hele pagina terug naar 0 recalcs en 0%,
   wat bevestigt dat álle kosten uit animatie komen.

   `content-visibility: auto` laat de browser het hele blok overslaan zolang het
   buiten beeld is. `contain-intrinsic-size` erbij is verplicht: zonder opgegeven
   maat denkt de opmaak dat het blok 0px hoog is en springt de pagina zodra hij in
   beeld komt. 41px is de gemeten hoogte van één strook. */
.marquee {
  content-visibility: auto;
  contain-intrinsic-size: auto 41px;
}

/* Wie in zijn systeem heeft staan dat hij minder beweging wil, krijgt niets van het
   bovenstaande — dat is geen nette optie maar een toegankelijkheidseis. De
   @media-vraag hierboven dekt dat al; deze regel is de vangnet-versie voor het geval
   een van de selectors later buiten dat blok belandt. */
@media (prefers-reduced-motion: reduce) {
  .card, .news-card, .shot-rail-item,
  .portfolio-grid > *, .home-kb-grid > *, .news-grid > *,
  .section-head, .kb-hero-figure img {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  body::after { animation: none !important; transform: scaleX(0) !important; }
}
