/* BESPOKE — Van Gool Hef- en Hijstechniek. Geladen via
   BESPOKE_CSS=/bespoke/vangool/vangool.css (per deployment).
   Alleen klant-specifieke afwijkingen die NIET uit ucm_settings komen (die gaan via /api/cms/theme:
   deep=#002A65, accent=#4379BD, ink=#46525B). Bron: legacy Bespoke/Styles/uc_global.css +
   vuejs-styles.css (palet: #002a65 donkerblauw, #38a4dd lichtblauw, #941680 magenta prijzen,
   #4379bd bestelknop, #3ddc97 sale-badge, #d0d3d5 borders, radius 2px, Montserrat koppen). */

/* Live laadt Open Sans via Google Fonts (Unify-theme) en zet koppen in MontserratBold - gemeten op
   vangool.nl: content-alinea's 16px Open Sans #46525b, koppen 20px MontserratBold. ucm_settings
   header_font/buttons_font zijn leeg voor deze tenant, dus er is geen datasignaal: bespoke dus. */
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600&display=swap");

:root {
  --font-sans: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  /* Live gebruikt Bootstrap's 1170px container (gemeten: contentrand op l=107 bij vw=1400); onze
     productdefault is 1200, wat alles 13px naar links schoof t.o.v. live. Dit is óók de breedte die
     de full-bleed calc(50% - 585px)-regels hieronder al aanhielden - nu consistent. */
  --container-max: 1170px;
  --radius: 2px;
  --color-border: #d0d3d5;
  --color-muted: #f2f4f7;
  --color-accent-strong: #38a4dd; /* lichtblauw voor link-hover, zoals live body_link_color */
  /* legacy: koppen in Montserrat (Light/SemiBold/Bold) — next/font levert dezelfde familie */
  --vg-price: #941680;            /* magenta — prijzen + "prijs op aanvraag" */
  --vg-sale: #3ddc97;             /* sale-action badge */
}

/* Standaard knop-look Van Gool (gemeten op de "Ik heb advies nodig"-knop, doorgevoerd naar elke
   primaire tekst-knop, bv. formulier-submits als "Versturen"): vet gecentreerde tekst, pijl op een
   eigen regel eronder i.p.v. inline. Uitsluitingen: .btn-secondary (eigen witte/subtiele stijl, geen
   primaire CTA), :has(svg) - icoon-only knoppen (zoekveld-knop, hamburger-menu, etc.) hebben geen
   tekst om te centreren en zouden een ongewenst tweede glyph naast hun icoon krijgen - en
   .product-tab: een tab-knop is geen CTA, moet plat/inline blijven (zie eigen tab-stijl verderop).
   .read-more-toggle-inline: de productdetail-"Lees meer"-knop, ook geen CTA, eigen plat-links-
   uitgelijnde stijl verderop (live's .collapse-button). .qty-stepper ("+"/"-") expliciet los
   uitgesloten: dat zijn geen SVG's maar ook geen CTA's.
   :not(:where(.qty-stepper button)):not(.shell-search-suggest-btn):not(.favorite-link):not(.concept-order-resume) toegevoegd nadat bleek dat de +/- knoppen zelf geen eigen
   klasse dragen (alleen hun ouder .qty-stepper heeft er een) - zonder deze uitsluiting matcht déze
   zwaardere selector ze óók en wint hij van de lichtere .qty-stepper button-regels hieronder
   (specificity: 4x :not(.klasse) > 1x .qty-stepper), met een ongewenste flex-column layout + de
   witte pijl-::after als gevolg (stond zichtbaar onder de "+"-knop). :where() maakt deze
   uitsluiting zelf specificity-neutraal, dus dit verandert niets aan de rest van de regel.
   .shell-lang-option: de taalkiezer-dropdown-rijen (vlag + naam, "Nederlands"/"English" etc.) zijn
   ook kale <button>'s - de huidige taal heeft een svg-vinkje kind en werd al uitgesloten via
   :not(:has(svg)), maar een NIET-geselecteerde rij (bv. "English", geen vinkje) matchte deze regel
   alsnog: flex-direction:column zette vlag+tekst onder elkaar i.p.v. naast elkaar (rij werd 2x zo
   hoog) en de ::after-pijl hieronder verscheen ongewenst na de taalnaam - een dropdown-optie is geen
   CTA-knop.
   .cart-line-remove: de winkelwagen-regel-verwijderknop ("×", CartLineRow.tsx) is ook een kaal
   <button> zonder svg - matchte deze regel dus ook, met de "×" en de ongewenste witte pijl
   onder elkaar gestapeld i.p.v. alleen het kruisje. Een verwijderknop is geen CTA.
   .btn-checkout-cta: "Verder winkelen"/"Bestellen"/"Plaats bestelling" (SingleCheckout.tsx, .checkout-
   actions) EN "Winkelwagen leegmaken" (.cart-lines-buttons) zijn navy CTA-knoppen net als de rest,
   maar zonder pijltje - ze staan al naast elkaar in een rij, een pijl-icoon eronder zou de knoppen
   uit het lood laten oogen t.o.v. elkaar. Alleen uitgesloten van de ::after-arrowregel hieronder, NIET
   van de bold/flex-column-regel hier: globals.css's eigen button-basisstijl is font-weight:400, dus
   zonder deze regel zouden ze dunner ogen dan elke andere CTA-knop (was eerder fout aangenomen dat dit
   "geen verschil" zou maken - "Toevoegen" op /account/addresses toonde het gat pas echt aan). */
/* a.button toegevoegd (2026-08-06): "Mijn account"/"Naar winkelwagen"-achtige standalone CTA-links
   (Link/`<a className="button">`, geen .btn/.qty-stepper-context) matchten deze regel niet - ze
   bleven font-weight:400 (dunner) zonder pijltje, duidelijk anders dan een `<button>`/`.btn`-CTA
   direct erboven/ernaast ondanks hetzelfde visuele doel. Zelfde exclusies als de andere twee
   selectors (geen van die klassen komt ooit samen met .button voor, maar consistent houden is
   goedkoper dan opnieuw uitzoeken welke subset relevant is). */
.btn:not(.btn-secondary):not(:has(svg)):not(.product-tab):not(.category-hero-toggle):not(.btn-order-main):not(.read-more-toggle-inline):not(.shell-lang-option):not(.cart-line-remove):not(.shell-logout):not(.order-entry-suggest-btn):not(.order-entry-add-btn):not(.facet-dropdown-trigger):not(:where(.qty-stepper button)):not(.shell-search-suggest-btn):not(.favorite-link):not(.cookie-banner-accept),
button:not(.btn-secondary):not(:has(svg)):not(.product-tab):not(.category-hero-toggle):not(.btn-order-main):not(.read-more-toggle-inline):not(.shell-lang-option):not(.cart-line-remove):not(.shell-logout):not(.order-entry-suggest-btn):not(.order-entry-add-btn):not(.facet-dropdown-trigger):not(:where(.qty-stepper button)):not(.shell-search-suggest-btn):not(.favorite-link):not(.cookie-banner-accept),
a.button:not(.btn-secondary):not(:has(svg)) {
  font-weight: 700; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: var(--space-1);
}
/* Zelfde witte SVG-pijl (geen Unicode "→"-teken) als de nieuwsbrief-knop (.newsletter-signup-row
   button::after hieronder) - consistent icoon overal, i.p.v. het dunnere/anders-ogende tekstteken.
   .shell-logout: "Uitloggen" is nu ook een kaal <button> (sinds het in .vg-utility-links naast
   Webshop/Registratie kwam, zie Header.tsx) - matchte deze regel dus ook, met een ongewenst wit
   pijltje eronder. Een topbar-tekstlink is geen CTA-knop, zelfde categorie als .shell-lang-option/
   .cart-line-remove hierboven.
   .order-entry-suggest-btn: "Snel bestellen"'s autocomplete-suggestieregels (kale <button>'s,
   app/account/order-entry/page.tsx) matchten deze regel ook - flex-column+center+wit pijltje maakte
   elke suggestie een dubbele, gecentreerde, vetgedrukte regel i.p.v. de generieke compacte
   code+omschrijving-rij (.order-entry-suggest button hieronder). Ook geen CTA-knop.
   .facet-dropdown-trigger: de zoekresultaten-filterknoppen (Merk/Materiaal/Diameter,
   components/catalog/FacetFilters.tsx) werden ook kale <button>'s zodra <details>/<summary> is
   vervangen door een echte knop (voor de hover-open-fix) - zonder deze exclusie werd elke knop een
   volle navy blok (flex-column+center+witte pijl) i.p.v. de eigen 32px-hoge input-achtige stijl,
   met het label onleesbaar/afgeknot. Ook geen CTA-knop.
   .favorite-link: "♡ Voeg toe aan mijn favorieten" (ProductDetailClient.tsx) is ook een kaal
   <button> zonder svg - matchte deze regel dus ook, met een ongewenst wit pijltje onder de tekst.
   Zelfde categorie als .shell-lang-option/.cart-line-remove hierboven: een tekst-link, geen CTA.
   .concept-order-resume: "Hervatten" (app/account/concept-orders/page.tsx) staat naast "Verwijderen"
   in één rij - zelfde categorie als .btn-checkout-cta hierboven (bold blijft, alleen het pijltje weg,
   dus ook hier alleen uitgesloten van DEZE ::after-regel, niet van de bold-regel hierboven).
   .profile-change-request-btn: "Wijzigingen doorgeven" (app/account/profile/page.tsx) mag WEL bold+
   gecentreerd blijven (Wesley wil dat behouden, alleen het pijltje moet weg) - dus alleen uitgesloten
   van DEZE ::after-regel, niet van de bold/flex-column-regel hierboven zoals de andere uitsluitingen.
   .address-form-btn: "Opslaan"/"Annuleren" (AddressForm.tsx) staan rechts-uitgelijnd naast elkaar in
   .address-form-actions - zelfde categorie als .btn-checkout-cta/.concept-order-resume hierboven,
   bold blijft, alleen uitgesloten van DEZE ::after-regel.
   .favorites-add-all-btn: "Alles in winkelwagen" (app/account/favorites/page.tsx) mag WEL bold+
   gecentreerd blijven, alleen het pijltje moet weg - zelfde categorie als .profile-change-request-btn
   hierboven, dus ook alleen uitgesloten van DEZE ::after-regel.
   .cookie-banner-accept: "Accepteren" in de cookiebalk. Gemeten op vangool.nl (echte computed style op
   de knop): 105x30, geen ::after en geen achtergrondafbeelding - live heeft daar dus GEEN pijltje. En
   omdat de ::after hierboven `display: block` is, kwam het pijltje op een EIGEN REGEL: de knop werd
   twee regels hoog naast een "Instellen" van één regel, en dat is precies wat er scheef uitzag. */
.btn:not(.btn-secondary):not(:has(svg)):not(.product-tab):not(.category-hero-toggle):not(.btn-order-main):not(.read-more-toggle-inline):not(.shell-lang-option):not(.cart-line-remove):not(.btn-checkout-cta):not(.shell-logout):not(.order-entry-suggest-btn):not(.order-entry-add-btn):not(.facet-dropdown-trigger):not(:where(.qty-stepper button)):not(.shell-search-suggest-btn):not(.favorite-link):not(.concept-order-resume):not(.profile-change-request-btn):not(.address-form-btn):not(.favorites-add-all-btn):not(.cookie-banner-accept)::after,
button:not(.btn-secondary):not(:has(svg)):not(.product-tab):not(.category-hero-toggle):not(.btn-order-main):not(.read-more-toggle-inline):not(.shell-lang-option):not(.cart-line-remove):not(.btn-checkout-cta):not(.shell-logout):not(.order-entry-suggest-btn):not(.order-entry-add-btn):not(.facet-dropdown-trigger):not(:where(.qty-stepper button)):not(.shell-search-suggest-btn):not(.favorite-link):not(.concept-order-resume):not(.profile-change-request-btn):not(.address-form-btn):not(.favorites-add-all-btn):not(.cookie-banner-accept)::after,
a.button:not(.btn-secondary):not(:has(svg))::after {
  content: ""; display: block; width: 12px; height: 12px;
  background: url("/bespoke/vangool/fa-arrow-right-white.svg") center/contain no-repeat;
}
.qty-stepper button {
  display: inline-flex; flex-direction: row; align-items: center; justify-content: center;
  /* Van Gool houdt de tekstglyphs. globals.css tekent de min en plus sinds kort als balken op
     ::before/::after met font-size: 0 op de knop; de regel hieronder haalt bij deze tenant al elke
     ::after weg (die bestaat om het witte pijltje van de generieke knop te wissen), dus de plus zou
     hier zijn verticale streep kwijtraken en als een MIN op het scherm komen. Vandaar: balken uit,
     lettergrootte terug. */
  font-size: 1.1rem;
}
.qty-stepper button::before { content: none; }
/* Twee selectors, geen luxe: de generieke balk staat op .qty-stepper button:last-child::after en die
   weegt door dat :last-child zwaarder dan een losse .qty-stepper button::after. Zonder de tweede regel
   kreeg de plus hier een verticaal streepje NAAST zijn tekstglyph. */
.qty-stepper button::after,
.qty-stepper button:last-child::after { content: none; }

/* Links in lopende tekst: lichtblauw (ucm_settings.body_link_color, niet generiek gemapt) */
.cms-text a, .cms-page a:not(.btn):not(.btn-secondary) { color: #38a4dd; }
/* Live (Unify-theme) reset het linkgewicht naar 400, óók binnen <strong> in de CMS-content
   (gemeten op nl/1/diensten.aspx: strong>a>span rendert 400; alle contentlinks daar 400). */
.cms-text a { font-weight: 400; }

/* Typografie CMS-content, 1:1 met live: alinea's 16px/1.6 grijs, koppen MontserratBold in hetzelfde
   grijs (niet navy - gemeten #46525b op vangool.nl). .account-intro (het account-dashboard's
   welkomsttekst) rendert dezelfde ruwe CMS-HTML (TEXT_ACCOUNT_INFORMATION) maar zonder de
   .cms-text-klasse omheen, dus miste deze basis-typografie: de eerste alinea's vielen terug op de
   generieke 13px body-tekst, terwijl de latere "Actuele zaken"-alinea/lijstitems zelf al een eigen
   inline `style="font-size:16-18px"` hadden (in de CMS-tekst zelf) en daardoor toevallig wél goed
   oogden. Zelfde klasse-lijst dus ook hier. */
.cms-text p, .cms-text li, .cms-text td, .account-intro p, .account-intro li, .read-more-body p, .read-more-body li { font-size: 16px; line-height: 1.6; color: #46525b; }
/* Uitzondering: op de PRODUCTPAGINA is .read-more-body geen CMS-pagina-tekst maar de inhoud van een
   tabblad, en dat tabblad staat zelf al op 13px (.product-tabs in globals.css). De regel hierboven
   trok de alinea's en lijstitems daar mee naar 16px, waardoor de omschrijving een maat groter stond
   dan het kader eromheen. Alleen dit paneel uitzonderen - de CMS-pagina's en het accountdashboard
   houden hun 16px, die is tegen live gemeten. line-height blijft de 1.6 hierboven, dus die schaalt
   gewoon mee (20.8px). */
.product-tab-panel .read-more-body p,
.product-tab-panel .read-more-body li,
.product-tab-panel .read-more-body td { font-size: 13px; }
/* De opsommingen bleven na die regel toch op 14px staan: in de CMS-tekst zelf zit per <li> een
   `<span style="font-size:14px">` (geteld: 15 stuks op deze ene productpagina, allemaal inline).
   Een inline style verliest van niets behalve !important, dus hier wel. Strak afgebakend tot spans
   BINNEN een alinea, lijstitem of tabelcel van dit ene paneel - de koppen houden hun eigen inline
   maten (de h1 op 25px, de span van 18px erin), want die zijn geen lopende tekst.
   Wel een echte afwijking van legacy: daar rendert dezelfde HTML die 14px gewoon uit. Dit is de
   uitdrukkelijke wens ("maak die tekst 13px"), niet een meting. */
.product-tab-panel .read-more-body :is(p, li, td) span { font-size: 13px !important; }
.cms-text h1, .cms-text h2, .cms-text h3, .cms-text h4 {
  font-family: var(--font-heading); font-weight: 700; color: #46525b;
}
.cms-text h3 { font-size: 20px; }
.cms-text h4 { font-size: 18px; }
/* Hexagon-tegels (cms-row--grid met span-4 blokken): live toont dit als 3 kolommen zonder zichtbare
   gap (390px x 3 = 1170px volle breedte). Onze generieke grid-gap:24px schoof alles ineen, en main's
   16px padding reduceerde de effectieve rij-breedte van 1170px naar 1138px (dus 379px per kolom
   i.p.v. 390px). Het rij-element zit in main en kan de padding niet omzeilen, dus compenseren:
   width: calc(100% + 32px) (2x 16px padding) + negative margin om niet af te schuiven.
   BUG-GESCHIEDENIS (tweemaal te breed gescoped geweest, allebei dezelfde specificiteitsval-klasse):
   eerst `:has(> .cms-block:nth-child(3))` (matcht ELKE grid-rij met 3-of-meer children, dus ook
   Diensten.aspx' 3-tegel-rij), toen `:has(> [style*="grid-column: span 12"])` (een span-4-tegels-
   PLUS-span-12-tekstblok-mix is GEEN unieke hexagon-signatuur - Kalibratiecentrum.aspx' losse
   afbeelding+tekst-rij (banner span-6 + tekst span-6 + een 3e, span-12 blok) matcht 'm ook, en
   verloor zo zijn gap TUSSEN afbeelding en tekst). Geen structureel kenmerk van de rij zelf is
   uniek genoeg gebleken - dus scopen op de PAGINA: alleen de homepage heeft deze hexagon-rij.
   page.key is "home" voor de root-route (een ander resolutiepad dan /pagina/{slug}, dus NIET de
   "" die GetPage(path="") teruggeeft voor andere aanroepen - geverifieerd via de daadwerkelijke
   data-page-key in de DOM, niet aangenomen). */
.cms-page[data-page-key="home"] .cms-row--grid:has(> [style*="grid-column: span 12"]) {
  gap: 0;
  width: calc(100% + 32px);
  margin-left: -16px;
  margin-right: -16px;
}
/* Live's "header-light" content blocks (bv. de gecentreerde adviestekst onder de tegel-rij: "Of u
   zich nu bezighoudt...") gebruiken MontserratLight i.p.v. de generieke Bold - gemeten fontWeight:400
   met font-family MontserratLight, tegenover fontWeight:400/MontserratBold bij de icoon-koppen
   (Veilig/Alles onder één dak/Service). Onze renderer behoudt legacy's ".header-light"-wrapper niet,
   dus scopen op het enige structurele verschil dat wél overleeft: deze koppen hebben een inline
   text-align:center (icoon-koppen zijn links uitgelijnd, geen inline style). */
.cms-text h2[style*="center"], .cms-text h3[style*="center"], .cms-text h4[style*="center"] {
  font-family: var(--font-heading); font-weight: 300; color: #46525b;
}
/* BUG (3e keer, zelfde klasse als de background-image-rij-fix hieronder): de header-light-regel
   hierboven matcht ook Diensten.aspx' icoon-tegels (uc_text_block met een <table>-lay-out: icoon +
   kop + tekst + 2 links in <tr><td>-rijen, elke kop óók toevallig text-align:center) - live's
   icoon-koppen zijn juist Bold (font-weight:700, bevestigd via de <strong> erin: gemeten 700 op
   live, geen relatieve "bolder"-afgeleide). De header-light-adviestekst zit NOOIT in een tabel, dus
   `table` is hier het enige overlevende structurele onderscheid. Hogere specificiteit (extra
   element) wint. */
.cms-text table h2[style*="center"], .cms-text table h3[style*="center"], .cms-text table h4[style*="center"] {
  font-family: var(--font-heading); font-weight: 700; color: #46525b;
}

/* Nieuwskaarten, gemeten op live (.news_block): geen kaartrand/schaduw, titel 24px MontserratBold
   navy (niet grijs), foto 4:3 landscape (niet vierkant). Publicatiedatum: eerdere meting hier zei
   "wel op de losse /nieuws-pagina" (vandaar scoped op .cms-block-news) - dat bleek bij herverificatie
   fout: live toont GEEN datum op zowel de home-teaser als de losse /nieuws-lijstpagina (getest via
   nl/1/nieuws.aspx), alleen op de losse artikelpagina zelf (nl/5/uitbreiding-....aspx toont "17 juli
   2026" boven de titel). Dus globaal verbergen, en expliciet terugzetten binnen .news-article. */
.news-list-item { border: none; box-shadow: none; background: none; }
.news-list-image { aspect-ratio: 4 / 3; }
.news-list-title { font-size: 24px; font-weight: 700; color: #002a65; }
/* HERZIEN 2026-08-12 op verzoek van Wesley. Hier stond dat de titel bij hover donkerblauw moest
   BLIJVEN en dat de onderstreping het enige signaal was. Dat is omgedraaid: GEEN onderstreping, en
   allebei de teksten lichten op. Let op de afwijking van live: daar onderstreept de titel wél
   (gemeten met de CSSOM-herschrijving, staat zo in de theming-skill) - dit is dus een bewuste keuze
   van Wesley boven de meting, geen vergeten detail.
   #60ccff is Van Gools eigen opklaringskleur en al in gebruik op "Lees meer", "Meer nieuws" en de
   producttabs - dus geen nieuwe kleur, wel dezelfde taal.
   Zelfde selectorvorm als de generieke regel (`.news-list-body:has(a:hover)`), en niet de kortere
   `.news-list-item:hover`: die laatste weegt één pseudo-class lichter dan de generieke regel en
   verloor daar stil van, waardoor de kleur alsnog de generieke accentkleur werd. */
.news-list-body:has(a:hover) .news-list-title,
.news-list-body:has(a:focus-visible) .news-list-title,
.news-list-body:has(a:hover) .news-list-more,
.news-list-body:has(a:focus-visible) .news-list-more { color: #60ccff; text-decoration: none; }
/* En de hele tegel komt een stukje omhoog (op verzoek, 2026-08-12). Foto en tekst samen, dus op
   .news-list-item en niet op het tekstvlak. 4px met een lage schaduw in de merk-navy: de schaduw doet
   het werk, want alleen verschuiven leest als verspringen. `:has(a:hover)` en niet `:hover`, zodat de
   tegel niet omhoog komt als je over de witruimte ernaast staat - alleen de teksten zijn links.
   De schaduw moet de `box-shadow: none` uit de rustregel hierboven verslaan; dat lukt op
   specificiteit ((0,2,1) tegen (0,1,0)), niet op volgorde. */
.news-list-item { transition: transform .18s ease, box-shadow .18s ease; }
.news-list-item:has(a:hover),
.news-list-item:has(a:focus-visible) {
  transform: translateY(-4px);
  box-shadow: 0 6px 18px rgba(0, 42, 101, .12);
}
/* Wie geen beweging wil, krijgt alleen de schaduw - dan is er nog steeds terugkoppeling. */
@media (prefers-reduced-motion: reduce) {
  .news-list-item { transition: none; }
  .news-list-item:has(a:hover),
  .news-list-item:has(a:focus-visible) { transform: none; }
}
.news-list-more { color: #38a4dd; font-size: 16px; font-family: var(--font-heading); font-weight: 700; }
/* Nergens een publicatiedatum, ook niet op de artikelpagina zelf (besluit Wesley 2026-08-16).
 * Hier stond eerst `.news-article .news-list-date { display: block }` om live na te doen: daar staat
 * de datum wél op het losse bericht (gemeten: nl/5/uitbreiding-van-ons-wagenpark.aspx toont "17 juli
 * 2026" in 13px/rgb(85,85,85)) en NIET in de home-teaser of de /nieuws-lijst. Die uitzondering is er
 * bewust uit - dit is dus een gewilde afwijking van live, geen gemiste meting; wie hier later langs
 * komt met "live doet dit anders" heeft gelijk maar moet het zo laten staan.
 * Waarom in de tenantlaag en niet via de instelling: legacy hééft er een vlag voor
 * (ucm_news_blocks.date_is_hidden, "Datum verbergen"), maar die kolom bestaat in vangool_full niet -
 * de tabel heeft daar 13 kolommen en deze zit er niet bij. Er is dus niets om aan te zetten.
 * Bovendien werkt die vlag bij ons alleen op de LIJST: de artikelpagina rendert zijn datum
 * onvoorwaardelijk (app/nieuws/[slug]/page.tsx), dus zelfs met de kolom erbij zou dit hier nodig zijn. */
.news-list-date { display: none; }
/* Gemeten op live (.news_block): 30px gap tussen kaarten, niet de generieke 16px - dat trekt ook de
   kaartbreedte scheef (360px op live vs 273px bij ons met de kleinere gap). */
.cms-block-news .news-list { gap: 30px; }
/* De generieke .cms-banner-grid--full-width (globals.css) heeft margin:var(--space-5) 0 (24px) - prima
   voor een bannergrid dat ergens MIDDENIN een pagina staat, maar geeft bij de hero-foto bovenaan de
   homepage een zichtbare witte reep boven EN onder de foto (de rij zelf heeft geen eigen achtergrond,
   dus de pagina-achtergrond schemert door in die marge). Gemeten op live: de hero-foto staat kaal
   tegen zowel de nav als de eronder liggende rij aan, 0px marge. VanGool-scoped (niet de generieke
   regel aangepast, want niet geverifieerd dat andere tenants hier ook 0 marge willen). */
.cms-banner-grid--full-width { margin: 0; }
/* Live: de hele nieuws-rij (tegels + "Meer nieuws" eronder) zit in één "row-breakout ... news-blocks-row
   full-width-row" met een lichtgrijze achtergrond (#f2f4f7 !important) die tot de viewport-rand loopt,
   terwijl de content zelf op de normale containerbreedte blijft (gemeten padding: 50px boven/onder).
   Zelfde full-bleed-formule als de generieke `.cms-row:has(> .cms-block-banner)` (globals.css) - hier
   bespoke toegepast omdat een nieuws-blok geen bannerblok is en dat generieke mechanisme dus niet raakt.
   .cms-block-news is geen DIRECT kind van .cms-row (zit zelf al binnen een wrapper), dus `:has()` zonder
   `>` i.p.v. de generieke `:has(> ...)`. */
.cms-row:has(.cms-block-news) {
  width: 100vw; position: relative; left: 50%; right: 50%; margin-left: -50vw; margin-right: -50vw;
  background-color: #f2f4f7;
  padding: 50px 0;
  /* Gemeten op live: de grijze band staat FLUSH tegen het blok erboven (0px lucht), niet de generieke
     .cms-page{gap:var(--space-4)} tussenruimte - margin-top:0 zou die flex-gap van de OUDER niet
     raken (zelfde valkuil als de header-strip eerder), dus de gap hier expliciet wegtrekken. */
  margin-top: calc(-1 * var(--space-4));
}
/* Horizontale re-centering staat op de KINDEREN, niet op de rij zelf: padding-percentages rekenen
   tegen de breedte van de CONTAINING BLOCK (de ouder, .cms-page - nog steeds ~1138px), niet tegen
   het element se eigen net-gezette 100vw - calc(50% - 585px) op de rij zelf gaf zo een negatieve
   (dus geclampte 0px) waarde. De advies-tegel deed dit wel goed OMDAT die zelf al een kind is van een
   AL-100vw rij (dezelfde generieke bannerregel) - zelfde formule hier dus een niveau dieper toegepast. */
.cms-row:has(.cms-block-news) > .cms-block-news,
.cms-row:has(.cms-block-news) > .cms-block-link {
  padding-left: calc(50% - 585px);
  padding-right: calc(50% - 585px);
}

/* "Meer nieuws" (het LINKS-blok direct na de nieuws-teaser): HERMETEN op live (eerdere meting
   "lichtgrijze balk-knop" bleek niet meer te kloppen, of was een verkeerd element - live toont nu
   een kale tekstlink (transparant, geen padding, #38a4dd), met een dunne lijn die de rest van de
   rij vult - geen knopvlak. Dit link_block heeft geen enkele bespoke-vlag (header_link_block/
   move_to_banner/fixed_sidebar_links zijn alle false) - het is dus generiek ".cms-links" zonder
   onderscheidende class, vandaar de sibling-selector i.p.v. een variant-class. */
.cms-block-news + .cms-block-link .cms-links a {
  display: flex; align-items: center; gap: var(--space-3); background: none; color: #38a4dd;
  font-size: 16px; font-family: var(--font-heading); font-weight: 700; padding: 0;
}
/* Gemeten op live: geen dunne grijze lijn maar een 4px dikke WITTE lijn (border-bottom:4px solid #fff
   op de li - hier direct als background op de ::after, simpeler equivalent). Was nog een oude
   ongemeten aanname (var(--color-border), 1px) sinds vóór de grijze achtergrondband er was; tegen die
   #f2f4f7-achtergrond viel de grijze lijn ineens te donker/zwart op. */
.cms-block-news + .cms-block-link .cms-links a::after { content: ""; flex: 1 1 auto; height: 4px; background: #fff; }
/* CORRECTIE: zelfde live-regel als bij "Lees meer" hierboven (a:hover{color:#60ccff !important}) -
   dus wel een lichtere blauwtint bij hover, geen onderstreping. */
.cms-block-news + .cms-block-link .cms-links a:hover { color: #60ccff; text-decoration: none; }
/* Gemeten op live: ~125px lucht tussen "Meer nieuws" en de advies-band eronder (niet de generieke
   .cms-row block-gap van 16px). Sibling-chain-selector (.cms-block-news + .cms-block-link +
   .cms-block-banner) matchte niet: er zit nog een verborgen (cms-hide-xs/sm/md/lg) banner-blok
   tussenin, dus :has() op de advies-tile zelf i.p.v. aan te nemen dat hij direct na de links staat. */
.cms-block-banner:has(.cms-banner-tile--advice) { margin-top: 56px; }

/* "Offerte aanvragen" (GOOL-66/67). Deze twee regels stonden tot 2026-08-15 in globals.css, met daar
   zelf de erkenning "effectief bespoke ondanks dat dit bestand generiek is" - waardoor elke nieuwe
   klant met een offerteknop Van Gools magenta erfde. Ze horen hier.
   Gemeten op live (.price-onreq-btn): de knop is EXACT dezelfde magenta als de prijzen (#941680,
   --vg-price), geen los paars. De hover zet alleen icoon/tekst lichter (#60ccff), niet de achtergrond.
   Selectorvorm bewust gelijk aan de generieke (element + 2 classes): de knop rendert onder twee
   verschillende wrappers (.buy-row op de tegel, .buy-panel op de PDP), en een regel die aan één
   wrapper hangt verliest in de andere context. */
a.btn.btn-quote-request { background: #941680; color: #fff; }
a.btn.btn-quote-request:hover:not(:disabled) { background: #941680; color: #60ccff; }

/* Topbar: donkerblauw met licht-grijze tekst. Die twee kleuren stonden hier met de hand, maar ze
   STAAN AL in ucm_settings: topbar_backgr_col #002A65 en topbar_font_col #D4D7DF, letterlijk dezelfde
   waarden. Sinds 2026-08-15 leest de generieke .shell-usp die kolommen (--color-topbar-bg /
   --color-topbar-fg), dus hier hoefde alleen de rand nog uit. De kindregel eronder kon ook weg:
   .shell-usp-right a en button.shell-logout lezen dezelfde variabele, en .shell-toggle/.shell-lang
   zetten zelf geen kleur en erven hem van .shell-usp. Nagemeten voor en na: #002A65 / #D4D7DF, gelijk.
   De hover blijft WEL bespoke - generiek is dat een wit vlak, hier een lichte wash op donkerblauw. */
.shell-usp { border-bottom: none; }
.shell-usp-right a:hover, .shell-usp-right button.shell-logout:hover { background: rgba(255,255,255,.12); color: var(--color-topbar-fg); }

/* Menubalk: wit met navy items in 12px MontserratBold en een "/"-scheider ACHTER elk item
   (gemeten op live: li::after = "/", link 12px MontserratBold #002a65). */
.shell-nav { background: #fff; border-bottom: 1px solid #d0d3d5; }
/* De generieke .shell-nav-list a heeft padding: 12px 16px (bedoeld voor een hover-achtergrond/
   border-bottom highlight-stijl) - dat maakte elk item 29px breder dan live, x7 items ~210px extra
   totale breedte, wat de hele navrij zichtbaar verder naar rechts/uit elkaar liet lopen ondanks dat
   de "/"-scheider-marges zelf al vrijwel exact klopten (27-28px). Live's items hebben geen padding,
   alleen de marge van de "/"-scheider zorgt voor ruimte. */
.shell-nav-list a { padding: 0; color: #002a65; font-family: var(--font-heading); font-weight: 700; font-size: 14px; }
/* Live toont GEEN dropdown-pijltje bij Producten/Over ons/Diensten (geverifieerd via zoom-screenshot
   tegen vangool.nl) - alleen platte tekst. Het extra glyph+spatie maakte elk item breder, wat als
   "opties staan te ver uit elkaar" werd ervaren ondanks dat de kale tekst-naar-tekst afstand (27-28px)
   al vrijwel exact gelijk was. Alleen hier verbergen (span, niet de tekst zelf) - Deponti/ALU toont
   de pijl wel echt op live (zie MegaMenu.tsx's eigen comment), dus dit blijft generiek zichtbaar. */
.mega-menu-caret { display: none; }
/* Gemeten op live (.dropdown-menu): ruimere padding (25px 30px, niet de generieke 12px 16px) en een
   zachtere, verder uitwaaierende schaduw (rgba(90,90,90,.075) 0 5px 5px, geen zichtbare rand). */
.mega-menu-panel { padding: 25px 30px; border: none; box-shadow: 0 5px 5px rgba(90, 90, 90, .075); }
/* Live's "Producten"-dropdown (.dropdown-menu) is één enkele kolom van 9 items (alle even ver van
   links, top loopt gewoon door van 166 naar 372px) - de generieke .mega-menu-panel--categories
   split altijd in 2 kolommen (columns:2), wat hier een 5/4-split maakte die live niet heeft. */
.mega-menu-panel--categories ul { columns: 1; }
/* Gemeten op live (.dropdown-menu a): line-height 20px + margin-bottom 5px per item (~26px
   regelafstand) - de generieke padding:var(--space-1) 0 zonder marge gaf hier maar ~22px. */
.mega-menu-panel a { padding: 0; margin: 0 0 5px; line-height: 20px; }
/* Zelfde magenta chevron als de categorieën-sidebar (.cat-sidebar a::before hierboven) - Wesley wil
   dit icoon consistent op ELKE dropdown (Producten's --categories-variant EN de --simple-variant van
   Over ons/Diensten/Onze merken - MegaMenu.tsx zet beide op `.mega-menu-panel`, alleen het tweede
   suffix verschilt per item.isMega), niet alleen in de sidebar. Geen live-meting nodig (dit is dezelfde
   bewuste bespoke-toevoeging, niet een live-overname). */
.mega-menu-panel a {
  display: flex; align-items: center; gap: var(--space-2);
}
.mega-menu-panel a::before {
  content: "";
  flex: none; width: 7px; height: 11px;
  background: url("/bespoke/vangool/fa-chevron-right-magenta.svg") center/contain no-repeat;
}
/* CORRECTIE (Wesley, echte muis-hover in eigen browser op vangool.nl/?language=nl): het menu-item
   wordt WEL lichtblauw (#38a4dd) bij hover - mijn eerdere "blijft navy"-meting was een artefact van
   de synthetische hover in de tooling (CDP-mouse-events triggeren hier kennelijk niet dezelfde
   JS/CSS-hoverstate als een echte muisbeweging). Geen underline bij hover. */
.shell-nav-list a:hover { color: #38a4dd; text-decoration: none; }
/* .mega-menu-item:hover .mega-menu-row a (globals.css, 3 classes + element - het opent ook de
   dropdown-panel-hover) won hiervan (2 classes + element) voor elk nav-item MET een dropdown
   (Diensten/Onze merken/Producten) - dezelfde specificiteitsval als steeds. Zelfde selector-vorm
   met bespoke kleur om 'm hier te winnen. */
.mega-menu-item:hover .mega-menu-row a { color: #38a4dd; background: transparent; }
/* Wesley: de "huidige pagina"-indicator (blauw+underline op bv. Home) bestaat NIET in legacy - daar
   is qua kleur geen enkel visueel verschil tussen de actieve en niet-actieve TOP-LEVEL nav-items.
   Generieke regel (globals.css: `.shell-nav-list a[aria-current="page"]`) hier voor VanGool
   geannuleerd - maar ALLEEN voor de top-level rij (.mega-menu-row), niet via de kale
   `.shell-nav-list a`-descendant-vorm: die matchte ook de submenu-links in `.mega-menu-panel`
   (een sibling van `.mega-menu-row`, niet erin genest) en annuleerde zo per ongeluk ook de
   dropdown's EIGEN, wél-bestaande actieve-subpagina-highlight (zie hieronder) - zelfde
   specificiteitsval-patroon als elders in dit bestand. */
.mega-menu-row a[aria-current="page"], .mega-menu-row a.mega-menu-parent-active { color: #002a65; border-bottom-color: transparent; }
/* Same "no active-page indicator" rule as above, for the OTHER underline mechanism
   (globals.css's `.mega-menu-row:has(> a[aria-current="page"], > a.mega-menu-parent-active)::after`,
   added later than the border-bottom rule above and never suppressed here too - a 3px ::after
   bar, not a border, so the border-bottom-color:transparent above doesn't touch it). Both
   conditions need suppressing: aria-current="page" for a leaf item like Home, .mega-menu-parent-
   active for a parent whose CHILD page is active (e.g. Producten while browsing a category under
   it - reported 2026-08-08, first fix only covered the aria-current case and missed this one). */
.mega-menu-row:has(> a[aria-current="page"], > a.mega-menu-parent-active)::after { content: none; }
/* Wesley: het generieke bolletje-vinkje voor de actieve submenu-link (globals.css, toegevoegd voor
   Deponti - daar is body_link_color toevallig gelijk aan de inktkleur, dus die kleursignaal alleen
   was onzichtbaar) hoort niet bij VanGool. VanGool heeft de kleurregel hierboven (regel ~316/492)
   AL als zichtbaar "je bent hier"-signaal (gemeten op live, #38a4dd tegen #002a65) - het bolletje was
   hier gewoon een overbodige tweede indicator die niet in de brief/meting voorkomt.
   Niet zomaar content:none - dezelfde ::before draagt hierboven (regel ~293) ook de magenta chevron
   voor ELK dropdown-item; zonder de geometrie hier terug te zetten zou de actieve regel als enige
   zijn chevron missen (of, als alleen content herbruikt wordt zonder position/width te resetten,
   scheef staan door de position:absolute/left:0/top:50% van de bolletje-regel die anders blijft
   hangen - zelfde-specificiteit cascadet per property, niet per regel). */
.mega-menu-panel a[aria-current="page"]::before {
  position: static;
  left: auto; top: auto; margin-top: 0;
  width: 7px; height: 11px;
  border-radius: 0;
  background: url("/bespoke/vangool/fa-chevron-right-magenta.svg") center/contain no-repeat;
}
.mega-menu-row a[aria-current="page"]:hover { color: #38a4dd; }
.shell-nav-list > li { display: flex; align-items: center; }
/* Gemeten op live: het "/"-scheidingsteken is lichtblauw (#38a4dd), niet grijs. */
.shell-nav-list > li::after { content: "/"; color: #38a4dd; margin: 0 var(--space-3); font-size: 12px; }
.shell-nav-list > li:last-child::after { content: none; }

/* Productcards: wit, 1px border, 2px radius, hover-schaduw; titel navy SemiBold; prijs magenta */
.product-card { border: 1px solid #d0d3d5; border-radius: 2px; box-shadow: none; transition: box-shadow .15s ease; }
.product-card:hover { box-shadow: 0 2px 12px rgba(0,42,101,.18); }
.product-title-link { color: #002a65; font-family: var(--font-heading); font-weight: 600; font-size: 15px; }
/* De generieke .product-card h3 (color:var(--color-ink) grijs; font-size:0.95rem) matcht de <h3> zelf
   direct - een expliciete regel op een element wint altijd van een op de OUDER (.product-title-link)
   gezette, overgeërfde waarde, ongeacht specificiteit. Titel bleef daardoor grijs/klein ondanks de
   regel hierboven. Zelfde eigenschappen, nu direct op de h3 met genoeg specificiteit (2 classes + 1
   element) om de generieke regel (1 class + 1 element) te verslaan. Groter+donkerblauw, zoals gevraagd. */
.product-card .product-title-link h3 { color: #002a65; font-family: var(--font-heading); font-weight: 700; font-size: 17px; }
/* uws_settings.prod_show_subtitle=1 in vangool_full, dus dit is data-gedreven (niet een generieke
   bug) - maar diezelfde vlag stuurt ZOWEL de PDP als de catalogus-tegel (ProductCard/ProductDetail-
   Client delen showSubtitle). Gemeten (screenshot Wesley): live's CATALOGUS-TEGEL toont de lange
   technische specs-tekst niet, alleen titel + prijs + knop - vermoedelijk toont live 'm alleen op de
   losse productpagina. Kan niet zelf op live geverifieerd worden (webshop vereist login), dus
   bespoke i.p.v. de generieke showSubtitle-vlag/data aan te passen (zou ook de PDP kunnen raken, en
   voor Deponti niet te verifiëren is of die dezelfde live-conventie aanhoudt). */
.product-card .product-subtitle { display: none; }
/* "Prijs vanaf" boven de prijs - alleen voor groeperingsproducten (product.variantKey, zie
   ProductCard.tsx). CORRECTIE 2026-08-08: was een vaste NL CSS ::before-tekst (bleef altijd
   Nederlands, ook in andere talen - de vertaaltabel-key PORTAL_LABEL_PRICE_FROM bestond al en
   wordt elders (ProductGroupMatrix.tsx, ProductDetailClient.tsx) prima gebruikt). Nu een echte
   vertaalde <span> naast de prijs in ProductCard.tsx, net als die twee - .product-price-label
   hieronder is al display:block, dus geen aparte flex-direction:column-truc meer nodig. */
.product-price { color: var(--vg-price); font-size: 19px; font-weight: 700; }
.product-price .muted { font-size: 12px; font-weight: 400; }
/* `.product-list .product-price` (globals.css, 2 classes - the forced mobile list view) outweighs
   the plain `.product-price` above (1 class) regardless of load order, so on phone the price fell
   back to the generic list font-size (16px) instead of VanGool's own. Wesley wants it a bit larger
   than the desktop 19px here specifically: 20px. */
@media (max-width: 560px) {
  .product-list .product-price { font-size: 20px; }
}
/* Detail-pagina prijs: generieke .detail-info .product-price (2 classes, globals.css) zet navy
   (var(--color-deep)) - hier optrekken naar dezelfde magenta als de catalogus-tegels. Het "Prijs
   vanaf"-label is hier een echte (vertaalde) span i.p.v. de tegel's CSS-::before-injectie.
   Font-size/weight gemeten op live (.ph-product-price .default span): 40px MontserratSemibold
   (zelfde 700-conventie als elders in dit bestand voor Semibold). */
.detail-info .product-price { color: var(--vg-price); font-size: 40px; font-weight: 700; font-family: var(--font-heading); }
/* "Excl. BTW"-label naast de prijs: gemeten op live (.ex-vat-label span) 15px MontserratSemibold
   #555 - andere waarden dan de generieke .product-price .muted (bedoeld voor de catalogus-tegel). */
.detail-info .product-price .muted { font-size: 15px; font-weight: 700; color: #555; font-family: var(--font-heading); }
.product-price-label { display: block; font-size: 12px; }

/* Detail-pagina titel/artikelcode/subtekst - gemeten op live (uc_product_details_elastic):
   h1 40px MontserratBold #46525b, margin 15px 0 25px; artikelcode 14px MontserratBold #46525b;
   prod-desc-2 (onze .product-subtitle) 16px MontserratSemibold #46525b, line-height 1.2. */
.detail-info h1 { font-family: var(--font-heading); font-weight: 700; font-size: 40px; color: #46525b; margin: 15px 0 25px; }
.detail-info .product-code { font-family: var(--font-heading); font-weight: 700; font-size: 14px; color: #46525b; }
.detail-info .product-subtitle { font-family: var(--font-heading); font-weight: 700; font-size: 16px; color: #46525b; line-height: 1.2; }
/* Tabs (Omschrijving/Product specificaties/Documenten) - gemeten op live (de actieve tab):
   13px MontserratSemibold #002a65. Zelfde grootte/lettertype voor alle tabs, kleur alleen op actief
   (niet-actieve kleur niet apart gemeten, generieke var(--color-text-muted) blijft staan). */
/* .product-tab is a <button>, so the generic button-regel hierboven (navy vlak, witte tekst,
   flex-column-opmaak) bleef zichtbaar ondanks de :not(.product-tab)-uitsluiting daar (die neemt
   alleen de pijl-::after/flex-column weg, niet zelf achtergrond/kleur/padding) - hier expliciet
   leeggemaakt tot platte tekst, geen onderstreping op geen enkele tab (ook niet actief): inactieve
   tabs lichtblauw #38a4dd, actieve tab navy #002a65 - hover lichter blauw #60ccff (zelfde
   opklaring-conventie als news-list-more/mega-menu). Extra ruimte onder de tab-rij vóór de
   lijn eronder (was 0, oogde te krap). */
.product-tab { background: none; border: none; padding: 0 0 var(--space-2); color: #38a4dd; font-family: var(--font-heading); font-weight: 700; font-size: 13px; }
/* border:none herhaald - de generieke `.product-tab:hover { border-bottom: 2px solid ... }`
   (globals.css) heeft hier meer specificiteit dan de kale `.product-tab { border:none }` hierboven
   (die zelf geen :hover-variant heeft), dus zonder deze regel verschijnt er bij hoveren (ook meteen
   na een klik, terwijl de cursor nog op de knop staat) alsnog een 2px rand - die maakt de hele
   tabrij 2px hoger, en daarmee schuift de scheidingslijn eronder zichtbaar mee naar onder. */
.product-tab:hover:not(:disabled) { background: none; filter: none; color: #60ccff; text-decoration: none; border: none; }
.product-tab.active { color: #002a65; font-weight: 700; text-decoration: none; }
.product-tab.active:hover { color: #002a65; }
.product-tabs-list { padding-bottom: var(--space-1); }
.product-tab.active:hover { color: #002a65; }

/* Gemeten op live (.utlz-col-md-5.column-left / .utlz-col-md-7.column-right): 365.6px/511.9px -
   ondanks de klassenaam is dit NIET Bootstrap's eigen col-md (hard bij 992px) - rechtstreeks
   gemeten op vangool.nl: nog een echte 313px-kolom bij 768px, pas volledige breedte bij 767px.
   CORRECTIE 2026-08-08: kort naar min-width:992 gezet (analoog aan de andere grids in deze audit),
   maar dat was mis - deze utlz-col-md-5/7 gedraagt zich als Bootstrap's sm-tier (768), niet md
   (992). min-width:768px is de echt gemeten grens - zonder deze grens won deze regel (zelfde
   specificiteit, later geladen) ook op mobiel van de generieke
   `@media(max-width:767px){.detail-top{grid-template-columns:1fr}}` (globals.css), wat de foto tot
   136px en de titelkolom tot 190px kneep op een 375px-scherm. */
@media (min-width: 768px) {
  .detail-top { grid-template-columns: 5fr 7fr; }
}

/* "Prijs vanaf" toont live NIET op een gewone (bestelbare) productdetailpagina - alleen het bedrag
   zelf. Het label bestaat wél echt op live, maar alleen voor "hoofdgroepering"-producten (shp_grp
   gevuld, eigen grp_val1/grp_val2 leeg - zie ProductGroupMatrix.tsx), waar het de minimumprijs over
   de hele groep aankondigt. Dus: standaard verborgen, expliciet teruggezet voor die ene situatie
   via .product-price-row--group hieronder. */
.detail-info .product-price-label { display: none; }
.detail-info .product-price-row--group .product-price-label { display: inline; }

/* "Hoofdgroepering"-dropdowns (Werklast/Hijshoogte, ProductGroupMatrix.tsx) - gemeten op live
   (.cmp-product-group): GEEN gearceerd vak/icoon/"Kies een uitvoering"-kopje (dat is Deponti-eigen
   maatwerk, .variant-chooser in globals.css) - hier alleen een label per select, naast elkaar.
   Label 14px Open Sans bold #002a65, select 12px MontserratSemiBold #46525b, 1px grijze rand. */
.group-matrix { display: flex; gap: var(--space-4); margin: var(--space-3) 0; }
.group-matrix-property { display: flex; flex-direction: column; gap: 5px; }
.group-matrix-property .select-label { font-family: var(--font-sans); font-weight: 700; font-size: 14px; color: #002a65; }
/* Breedte gemeten op live (.cmp-product-group select): 211px, niet de browser-default smalle
   auto-breedte die eerder hier stond. */
.group-matrix-property select { font-family: var(--font-heading); font-weight: 400; font-size: 12px; color: #46525b; border: 1px solid #d0d3d5; padding: 0 6px; height: 35px; width: 211px; }
/* Live's 211px is a desktop measurement - two of them side by side (.group-matrix has no wrap) add
   up to 422px+gap, well past a phone's content width, overflowing the row (reported: "Hijshoogte
   (m)" cut off on the right). flex:1 with min-width:0 lets each property shrink to share the row's
   actual width instead of forcing its own fixed 211px. */
@media (max-width: 480px) {
  .group-matrix { flex-wrap: wrap; }
  .group-matrix-property { flex: 1 1 140px; min-width: 0; }
  .group-matrix-property select { width: 100%; }
}

/* Hoofd-bestelknop (buy-row-inline se "In winkelwagen"): gemeten op live (.add-to-cart-btn) - een
   rij (niet de generieke kolom+pijltje-onder), navy achtergrond, WITTE "+"-tekst voor de labeltekst
   i.p.v. een pijl-icoon erna, 14px, 140x50px, radius 2px. Cancelt de generieke button-regel
   (globals.css: flex-column + font-weight:700 + SVG-pijl-::after) specifiek voor deze knop via de
   .btn-order-main-class (zie ProductDetailClient.tsx). Live's font-weight meet als 400, maar dat is
   omdat de tekst daar via het eigen MontserratSemiBold-lettertypebestand loopt (het gewicht zit al
   ín het font-bestand); onze --font-heading is één enkel gewicht, dus 400 zou hier als dun/regulier
   ogen i.p.v. semibold - font-weight:700 gebruikt om hetzelfde vette effect visueel na te bootsen. */
.btn-order-main {
  display: flex; flex-direction: row; align-items: center; justify-content: center;
  background: #002a65; color: #fff; font-family: var(--font-heading); font-weight: 700; font-size: 14px;
  padding: 0 25px; height: 50px; width: 140px; border-radius: 2px; gap: 0;
}
/* :not(.btn-added) - the "already in cart" label ("✓ In winkelwagen", ProductDetailClient.tsx)
   already carries its own checkmark; without this exclusion the "+" rendered anyway, and since that
   longer label wraps to 2 lines inside the fixed 140px width, the "+" visually detached from the
   wrapped text instead of sitting next to it - the "messy floating +" look. */
.btn-order-main:not(.btn-added)::before { content: "+"; margin-right: 5px; }
.btn-order-main::after { content: none; }
/* Opmerkingveld op een EIGEN regel (verzoek 2026-08-12). Generiek staan stepper, opmerking en
   bestelknop bewust op één rij met `flex-wrap: nowrap` - dat staat daar met de toelichting "Wesley:
   het moet naast elkaar". Bij Van Gool past dat niet: gemeten in het koopblok van 464px zijn de drie
   samen 476px breed (stepper 142 + veld 178 + knop 140 + 2x8 tussenruimte), dus het veld werd
   platgeknepen en de placeholder viel weg. Vandaar hier wél wrappen; Kobout houdt zijn eigen
   nowrap-regel en blijft dus ongemoeid.
   Het veld staat BOVEN de rij (`order: -1`) en niet eronder. Dat is geen smaak: de opmerking wordt
   MEEGESTUURD door de bestelknop (zie ProductDetailClient's addMany(..., comment)), dus een veld
   onder die knop wordt te laat ingevuld en de notitie gaat verloren. Onder de knop zetten is één
   waarde omzetten (`order: 1`).
   Zelfde selectorvorm als de generieke regels, anders wint de generieke op specificiteit. */
.buy-row-inline:has(input.order-comment) { flex-wrap: wrap; }
.buy-row-inline input.order-comment { flex: 1 1 100%; order: -1; }
/* De stepper stond op 38px hoog naast een knop van 50 - een verschil van 8px in een rij van twee
   dingen. De generieke 38px komt uit `.buy-panel .qty-stepper`; met auto rekt hij mee door de
   `align-items: stretch` die de rij toch al heeft, dus hij volgt automatisch de knop. */
.buy-panel .qty-stepper { height: auto; }
/* .btn-added itself is already generically green (globals.css .buy-row-inline .btn-added) - only
   the sizing needs a bespoke fix here: "✓ In winkelwagen" doesn't fit the "+ Bestellen"-measured
   140px on one line. Grow to fit instead of wrapping, keeping the same minimum width/height so the
   button doesn't shrink for the (removed) shorter "+"-less label either. */
.btn-order-main.btn-added { width: auto; min-width: 140px; padding: 0 18px; white-space: nowrap; }

/* Bestelknoppen: #4379bd (legacy add-to-cart), hover donkerder. Deze regel zette alleen de
   achtergrond, niet de tekstkleur - de generieke .btn-secondary { color: var(--color-ink) } (donker-
   grijs, bedoeld voor EEN WITTE achtergrond) bleef daardoor staan op de nieuwe blauwe achtergrond:
   bijna onleesbaar contrast (gemeten: #46525b tekst op #4379bd - PDP's eigen "In winkelwagen"-knop
   (kale <button>, geen .btn-secondary) had dit niet, want die valt terug op de generieke
   button{color:#fff}). Expliciete color:#fff hersteld voor consistentie tussen alle bestelknoppen. */
.buy-row .btn, .buy-row button.btn { background: #4379bd; border-color: #4379bd; color: #fff; }
.buy-row .btn:hover, .buy-row button.btn:hover { background: #002a65; border-color: #002a65; color: #fff; }
/* .buy-btn (catalogus-tegel "in winkelwagen"-knop, ProductCard.tsx): gemeten op live
   (a.order-button.button.theme-primary, DevTools) - #4379bd, 75x40px, 0 20px padding, GEEN vast
   vierkant icoon-only formaat zoals de generieke `.buy-btn { width:34px }` hierboven aanneemt. De
   knop bleef daarvoor navy (#002a65, generieke button-kleur) en te klein/vierkant, want `.buy-btn`
   is een kaal <button> zonder `.btn`-klasse en matchte dus geen van de regels hierboven. */
.buy-btn { background: #4379bd; width: auto; height: 40px; padding: 0 20px; }
.buy-btn:hover:not(:disabled) { background: #002a65; filter: none; }
/* Catalogus-tegel qty-stepper: de generieke compacte maat (22px knoppen, 28px veld, 30px hoog -
   globals.css .buy-row .qty-stepper) oogde te krap naast de nu 40px hoge .buy-btn hierboven en had
   geen matchende hoogte. Breder + zelfde 40px hoogte als de bestelknop ernaast. */
.buy-row .qty-stepper { height: 40px; }
.buy-row .qty-stepper button { width: 32px; font-size: 1.1rem; }
.buy-row .qty-stepper input { width: 36px; }
/* Deze maat geldt hier ook in de RIJweergave. globals.css maakt de stepper daar ruimer (44px knoppen,
   76px veld) omdat Kobout verpakkingsaantallen van drie en vier cijfers heeft; bij Van Gool is
   sale_unit voor élk product leeg, dus staat er nooit meer dan een paar cijfers in en zou dat veld
   alleen maar leeg ogen. De regels hierboven wegen te licht om die generieke te verslaan
   (.buy-row .qty-stepper = 2 klassen tegen .product-list .buy-row .qty-stepper = 3), vandaar deze
   herhaling met .product-list ervoor. */
.product-list .buy-row .qty-stepper { height: 40px; }
.product-list .buy-row .qty-stepper button { width: 32px; font-size: 1.1rem; }
.product-list .buy-row .qty-stepper input { width: 36px; font-size: 1rem; padding: var(--space-1) 0; }
/* De "grouped"-tegel (variant-bundel zonder vaste prijs) toont een volle-breedte "Bestellen"-tekst-
   knop (generiek .buy-row-single { flex:1 }). Gemeten via screenshot (Wesley leverde de referentie-
   afbeelding aan): live toont hier hetzelfde compacte icoon-formaat als de directe-bestel-knop, met
   HETZELFDE winkelwagen+plus-icoon (zelfde SVG-paden als ProductCard's .buy-btn inline-SVG, hier als
   los wit SVG-bestand omdat een <a>-tag geen React-children kan krijgen via pure CSS). Tekst blijft
   in de HTML staan (toegankelijkheid), visueel verborgen via font-size:0.
   :not(.btn-quote-request) toegevoegd: ProductCard.tsx geeft de "Offerte aanvragen"-knop (GOOL-66/67,
   prijs €0,00) DEZELFDE .buy-row-single-klasse als de grouped-tegel (allebei "volle breedte, geen
   qty-stepper ernaast"), maar dat is een andere knop met eigen zichtbare tekst+icoon - gemeten op
   live (.price-onreq-btn op de catalogus-tegel): 40px hoog, GEEN vast breed vierkant, icoon + tekst
   allebei zichtbaar naast elkaar (niet icon-only zoals hier). Zonder deze uitsluiting werd de
   offerte-knop ook tot een leeg icoon-vierkant samengeknepen (font-size:0 verborg de eigen tekst).
   CORRECTIE: breedte was hardcoded 40px (vierkant), maar .buy-btn (de directe-bestel-knop op de
   buurtegel) is intussen zelf 60px breed (0 20px padding, zie hierboven) - de twee moeten hetzelfde
   "cart-knop"-uiterlijk hebben, dus width:40px vervangen door dezelfde 0 20px padding i.p.v. een
   eigen vaste breedte, zodat ze altijd gelijk blijven ook als .buy-btn's breedte ooit weer verandert. */
.buy-row-single:not(.btn-quote-request) { flex: none; width: auto; height: 40px; padding: 0 20px; font-size: 0; overflow: hidden; display: flex; align-items: center; justify-content: center; }
.buy-row-single:not(.btn-quote-request)::after {
  content: ""; display: block; width: 18px; height: 18px;
  background: url("/bespoke/vangool/fa-cart-add-white.svg") center/contain no-repeat;
}

/* .btn-quote-request breedte/hoogte: gemeten op live (.price-onreq-btn), TWEE verschillende
   contexten. Catalogus-tegel (.buy-row): 40px hoog, 0 15px padding, margin-top:52px (leeft de
   plek in van de prijsregel eronder, die hier ontbreekt). PDP (.buy-panel): 50px hoog, 0 25px
   padding, margin-top:30px. Beide inhoud-breed (inline-flex), NIET volle breedte - de generieke
   `.buy-row-single { flex:1 }` (ProductCard) en `.buy-panel.card { align-items:stretch }` (PDP)
   rekken 'm anders allebei tot de volledige containerbreedte uit. Font: live's span gebruikt
   MontserratSemiBold (--font-heading) - de generieke a.btn.btn-quote-request-regel (globals.css)
   heeft geen eigen font-family, dus die viel terug op de site-brede Open Sans/--font-ui. */
/* font-weight:700 nodig ondanks de generieke bold-knopregel (globals.css h.o.g. hierboven, .btn:not(
   ...):not(:has(svg))...): die :not(:has(svg)) is bedoeld voor ECHTE icoon-only knoppen (zoekveld,
   hamburger) - deze knop heeft ook een icoon (btn-quote-request-icon), dus viel er ten onrechte ook
   onder en bleef dun (400) i.p.v. de bold-look van elke andere CTA. */
.btn-quote-request { font-family: var(--font-heading); font-weight: 700; }
/* CORRECTIE (2x): eerst content-breed (159px), toen smaller getrokken (140px) - allebei nog
   duidelijk smaller dan de buurtegels se qty-stepper+cart-knop-rij (334.6px, gemeten: .buy-row
   breedte = kaart-breedte minus padding). Wesley wil 'm exact even breed als DIE volledige rij,
   niet alleen even zwaar als de losse cart-knop - dus hier volle breedte i.p.v. content-breed. */
.buy-row .btn-quote-request.buy-row-single {
  flex: 1; width: 100%; display: inline-flex; align-items: center; justify-content: center;
  height: 40px; padding: 0 10px; margin-top: 52px; font-size: 12px;
}
/* margin-top:52px above deliberately left room for the "Prijs vanaf" label that used to render
   above this button - never shown for isQuoteOnly tiles (ProductCard.tsx only renders the label
   when there's a real price), so that gap is just dead air. On mobile specifically, Wesley wants
   the button pulled up into that now-empty spot and narrower (content-width, left-aligned) instead
   of stretched full-row-width. */
@media (max-width: 560px) {
  .buy-row .btn-quote-request.buy-row-single {
    flex: none; width: auto; align-self: flex-start; margin-top: var(--space-2); padding: 0 var(--space-3);
  }
}
.buy-panel .btn-quote-request {
  align-self: flex-start; display: inline-flex; align-items: center; justify-content: center;
  height: 50px; padding: 0 25px; margin-top: 30px;
}

/* Sale-badge groen (legacy .3ddc97) */
.product-sale-badge, .sale-badge { background: var(--vg-sale); color: #fff; }

/* Generieke footer-tekstkleuren (globals.css .shell-footer-col h2 / .shell-footer a) gaan uit van
   een DONKERE footer-achtergrond (zoals Deponti's) en zetten koppen/links op wit. VanGool's footer
   is wit - zonder deze override was elke koptekst en link wit-op-wit, dus onzichtbaar. Zelfde
   patroon als de tegel- en header-strip-kleurbotsingen hierboven, nu bevestigd via Chrome devtools
   computed style (h2 color: rgb(255,255,255) op een witte achtergrond). */
.shell-footer { background: #fff; color: #46525b; }
.shell-footer-col h2 { color: #002a65; }
/* "Sinds 1984 een vertrouwd adres" is een <h2> BINNEN een raw .cms-text WYSIWYG-blok naast de
   certificatielogo's - géén sectietitel (die renderen als losstaande <h2> buiten .cms-text, zie
   .shell-footer-col h2 hierboven). Gemeten op live: grijs #46525b, 20px - de regel hierboven ving dit
   per ongeluk ook (navy, en zonder expliciete font-size viel het terug op een kleinere geërfde maat).
   Live breekt na "een" (regel 1 "Sinds 1984 een", regel 2 "vertrouwd adres" - geen <br> in de HTML,
   puur natuurlijke wrap). Onze generieke Montserrat-cut is smaller dan live's echte MontserratBold-
   bestand (zelfde bekende font-metriek-verschil als elders), dus "vertrouwd" past bij ons nog wél op
   regel 1 (270px < 285px kolombreedte) - canvas-meting: "Sinds 1984 een"=155px, "...vertrouwd"=270px.
   max-width tussen die twee waarden forceert dezelfde regelbreuk als live. */
.shell-footer .cms-text h2 { color: #46525b; font-size: 20px; font-weight: 700; max-width: 200px; }
.shell-footer a { color: #38a4dd; }
.shell-footer a:hover { color: #002a65; }
/* Nieuwsbrief-band: volledige breedte met legacy's eigen achtergrond (Bespoke/Assets/Images/
   footer_bg.jpg, geverifieerd via Chrome devtools tegen vangool.nl - dezelfde driehoek-graphic als de
   "leer ons kennen"-fototegels). Rendert nu als aparte child van <footer> (zie Footer.tsx), dus een
   gewone volledige-breedte achtergrond volstaat - geen grid-cel-uitbraak-hack meer nodig. */
/* Gemeten op live: band-hoogte 330px (huidige 226px was te laag) - vergroot verticale padding zodat
   de bredere input+knop-combinatie evenveel ademruimte krijgt als live. */
.shell-footer-newsletter-band {
  background: url("/bespoke/vangool/footer_bg.jpg") center/cover no-repeat;
  padding: 68px var(--space-4);
}
/* 1.3rem was bedoeld als 20.8px (16px root), maar het generieke design system zet html font-size op
   :root's --font-size-base = 13px (niet 16px) - dus 1.3rem rekende hier ineens naar 16.9px. Expliciete
   px i.p.v. rem, gemeten op live: 20px. */
.shell-footer-newsletter-band .newsletter-signup label { font-size: 20px; font-family: var(--font-heading); font-weight: 700; }
/* De generieke .newsletter-signup (globals.css) is `display:inline-flex` zonder eigen breedte, dus
   shrink-to-fit op zijn content - `width:100%` op de row-kind hieronder heeft dan geen effect (100%
   van een shrink-wrap-ouder blijft shrink-wrap). Het FORM zelf moet dus expliciet breed worden. */
.shell-footer-newsletter-band .newsletter-signup { width: 100%; max-width: 730px; }
/* Live stapelt invoerveld en knop (niet naast elkaar): input volle breedte, knop gecentreerd eronder.
   max-width was eerder een ongemeten aanname van 460px - live's input is zelf 730px breed (gemeten op
   vangool.nl, .form-group), dus de rij mag veel breder worden dan de oude aanname. */
.shell-footer-newsletter-band .newsletter-signup-row { flex-direction: column; max-width: 730px; width: 100%; }
/* De generieke .newsletter-signup-row input { flex: 1 1 0% } is bedoeld voor de standaard naast-
   elkaar-rij (flex-basis 0% groeit dan in de breedte) - zodra de rij hierboven op column staat
   (legacy stapelt input/knop), is de main axis verticaal en bepaalt diezelfde flex-basis:0% ineens
   de HOOGTE via flex-grow i.p.v. de expliciete height:44px hieronder, wat het veld liet inklappen
   tot ~17.6px (font-based intrinsieke hoogte). flex:none herstelt dat de height gewoon telt. */
.shell-footer-newsletter-band .newsletter-signup-row input {
  flex: none; border: 0.8px solid #002a64; height: 50px; padding: 0 var(--space-4); width: 100%;
  text-align: center; font-family: var(--font-heading);
}
/* Placeholder viel terug op het generieke body-font (font-sans) i.p.v. het Montserrat-lettertype
   dat de rest van dit blok (label + knop) al gebruikt - font-family hierboven lost de tekst zelf op,
   maar ::placeholder erft niet automatisch dezelfde text-align in elke browser. */
.shell-footer-newsletter-band .newsletter-signup-row input::placeholder {
  text-align: center; font-family: inherit;
}
/* Knop gemeten op live: 185px breed, 72px hoog, gecentreerd ONDER de volle-breedte input (niet zelf
   even breed) - de column-flex row hierboven stretcht kinderen standaard, dus align-self:center +
   width:auto nodig om de knop zijn eigen (intrinsieke) breedte te laten behouden. Tekst en pijl staan
   ONDER elkaar (niet naast elkaar - flex-direction:column, niet de default row), gecentreerd. */
.shell-footer-newsletter-band .newsletter-signup-row button {
  background: #002a65; color: #fff; border: none; border-radius: 2px;
  height: 72px; width: 185px; font-family: var(--font-heading); font-weight: 700;
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-1);
  align-self: center; padding: 0 var(--space-5);
}
/* Live gebruikt GEEN tekst-pijl (geen "→" Unicode-glyph) maar een SVG-achtergrondafbeelding -
   hetzelfde bestand (fa-arrow-right-blue.svg, blauw #4379bd, 12.3x12px) dat ook op de tegel-CTA's
   hierboven gebruikt wordt. Bron: `background-image` op de <input type=submit> zelf op live. */
.shell-footer-newsletter-band .newsletter-signup-row button::after {
  content: ""; width: 12px; height: 12px;
  background: url("/bespoke/vangool/fa-arrow-right-blue.svg") center/contain no-repeat;
}

/* fixed_sidebar_links floating tab: magenta, matching live's "Contact" side-tab. */
/* Gemeten op live (.fixed-sidebar-links): de tab is smal (45px) en laat "Contact" per letter
   wrappen i.p.v. op één regel (geen vertical writing-mode nodig, gewoon een nauwe breedte). Het
   logo-item eronder (bevat een <img>, geen tekst-<span>) is WIT, niet magenta - alleen de tekst-tab
   krijgt de magenta achtergrond. */
/* Live roteert deze tab 90° (transform: matrix(0,-1,1,0,0,0) - een 280x45 horizontale tab gedraaid
   tot een smalle verticale strook) i.p.v. "Contact" in een 45px-brede box te proppen, wat het woord
   doormidden brak ("Cont/act"). writing-mode geeft hetzelfde verticale resultaat zonder transform-
   positioneringsrekenwerk. */
/* Renderde eerder binnen .cms-page (per-pagina CMS-blocks), nu globaal via FixedSidebarLinks.tsx in
   app/layout.tsx (zie backend CmsRepository.GetFixedSidebarLinks) - GEEN .cms-page-voorouder meer,
   dus die prefix uit de selector gehaald. .cms-links.cms-links--sidebar (2 classes) volstaat hier:
   de concurrerende generieke lichtblauwe linkkleur is zelf ook op .cms-page geschoold, dus buiten
   die context speelt die specificiteitsval niet meer. writing-mode staat op de <span> (niet op de
   <a> zelf) zodat de <a> een gewone flex-column kan zijn met het pijltje-icoon eronder, net als de
   "Aanmelden"-knop hierboven - anders zou het pijltje meegeroteerd worden door dezelfde
   writing-mode/transform als de tekst. */
.cms-links.cms-links--sidebar a {
  background: #941680; color: #fff; width: 45px; box-sizing: border-box;
  padding: var(--space-4) var(--space-2); white-space: nowrap;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-2);
}
.cms-links.cms-links--sidebar a span {
  writing-mode: vertical-rl; text-orientation: mixed; transform: rotate(180deg); font-weight: 700;
}
.cms-links--sidebar a:hover { background: #7a1169; }
/* Zelfde specificiteit nodig als de regel hierboven (.cms-links.cms-links--sidebar a, 2 classes) -
   de oude `.cms-links--sidebar a:has(img)` (1 class + :has) verloor stilletjes, dus de EKH-tab bleef
   magenta i.p.v. wit. */
.cms-links.cms-links--sidebar a:has(img) { background: #fff; padding: var(--space-2); }
/* Het bron-logo (EKH35px.jpg, checksum-identiek aan live) staat zelf ~9° naar links scheef getekend
   - ook zichtbaar op vangool.nl, maar Wesley wil dit hier bewust rechtzetten (geen live-verschil om
   te matchen, een gewenste correctie). rotate(9deg) compenseert. */
.cms-links--sidebar .cms-link-logo { transform: rotate(9deg); }
/* Beide tabs tegen elkaar (geen tussenruimte) - overschrijft de generieke .cms-links { gap } uit
   globals.css (zelfde 1-class specificiteit, bronvolgorde beslist: bespoke laadt na generiek). */
.cms-links--sidebar { gap: 0; }
/* Pijltje onder zowel de "Contact"-tekst als het EKH-logo (zelfde SVG als de "Aanmelden"-knop
   hierboven, maar donkerblauw #002a65 i.p.v. het middenblauw #4379bd - gevraagd door Wesley). */
.cms-links--sidebar a::after {
  content: ""; width: 12px; height: 12px; flex: none;
  background: url("/bespoke/vangool/fa-arrow-right-navy.svg") center/contain no-repeat;
}
/* Live toont geen "Powered by"-regel voor VanGool (geverifieerd: footer eindigt op Privacybeleid +
   adresgegevens, geen attributietekst) - tenant-scoped verborgen i.p.v. de generieke component aan
   te passen, zodat andere tenants (waar dit wel zichtbaar hoort) ongewijzigd blijven. */
.shell-footer-bar { display: none; }
/* VERWIJDERD (2026-08-13): de hardgecodeerde 25/75 voor de bovenste footer-rij. Die stond hier omdat
   de generieke footer elke rij in GELIJKE stukken verdeelde (`repeat(auto-fit, minmax(160px,1fr))`)
   en `ucm_footer_blocks.block_layout` nergens gelezen werd. Die kolom bestaat op alle drie de tenants
   en is gevuld: bij Van Gool staat het tekstblok op 3 en het bannerblok op 9 - precies de 25/75 die
   hier met de hand stond. De footer is nu een echt 12-koloms raster dat die waarden volgt, dus dit is
   geen bespoke-afwijking meer maar gewoon de data. Stapelen onder de tabletgrens doet de generieke
   regel ook (max-width: 991px), dus de tweede override hieronder kon mee weg.
   Verandert er iets aan deze rij? Dan is het beheerscherm de plek: footer > Breedte. */
/* Zelfde meting: de generieke `.cms-banner-grid` 991px-stackregel (globals.css) is voor de grote
   hero-tegels (die op tablet WEL naar 1 volle-breedte-tegel per rij moeten), maar deze klasse wordt
   hier hergebruikt voor de 4 kleine certificatielogo's - die moeten NOOIT naar 1 kolom stacken.
   Live wrapt ze i.p.v. dat: 4 naast elkaar vanaf tablet (965px), 2x2 op telefoon (390px, elk logo
   dan zijn eigen natuurlijke breedte ~150-220px). auto-fit/minmax herhaalt exact dat gedrag zonder
   een vaste kolomtelling die op een van beide breedtes fout zou zitten. */
@media (max-width: 991px) {
  .shell-footer-row:has(.cms-banner-grid) .cms-banner-grid {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  }
}
/* Onderste footer-rij (legal links / adres+telefoon+email / social-iconen): live toont dit NIET als
   een grid met 3 gelijke kolommen, maar als een flex-rij met content-breedte kolommen (col-md-4 is
   hier geen 33%-breedte, gemeten `flex: 0 1 auto`) - de social-iconen-kolom is te smal om nog op
   dezelfde regel te passen (links-blok + adres-blok vullen samen al ~1015px van de 1170px-container)
   en wrapt daardoor naar een eigen regel, links uitgelijnd onder het links-blok. Een 1fr-grid gaf hier
   3 gelijke kolommen op één regel - zichtbaar anders dan live. Elk item toont zijn links horizontaal
   doorlopend met een "/"-scheidingsteken ertussen (gemeten op live: kleur #352480, 13px, margin 0 5px). */
/* column-gap 155px (niet de generieke --space-6/~40px) - gemeten op live: de links-kolom eindigt op
   x=528, de adres-kolom begint op x=683 (viewport 1280px), een gat van 155px. Zonder dit stopt de
   adreskolom veel eerder (content-sized breedte, flex:0 1 auto) en blijft er rechts een leeg gat over
   tot de containerrand - met de bredere gap begint (en eindigt) de adreskolom net als op live vrijwel
   tot de rand van de rij. */
/* Gemeten op live: de onderste footer-rij zelf (niet .shell-footer-inner) heeft een lichtgrijze
   achtergrond #f1f5f8 - subtiel maar duidelijk zichtbaar t.o.v. de witte footer erboven. */
.shell-footer-row:has(+ .shell-footer-bar) { background: #f1f5f8; }
/* row-gap 25px (niet de generieke --space-2/8px) - gemeten op live: 25px tussen de tekst-regel
   (EKH-links/Disclaimer/Privacybeleid) en de social-iconen eronder. */
.shell-footer-row:has(+ .shell-footer-bar) .shell-footer-inner {
  display: flex; flex-flow: row wrap; align-items: center; justify-content: flex-start;
  column-gap: 155px; row-gap: 25px; text-align: left; padding: var(--space-4) var(--space-4);
}
.shell-footer-row:has(+ .shell-footer-bar) .shell-footer-col { flex: 0 1 auto; }
/* Live forceert de social-iconen altijd naar een eigen regel onder het links-blok (via een vreemde
   margin-right:155px op de eerste kolom - vermoedelijk een bootstrap-artefact, geen bewust ontwerp),
   ook al past de iconen-kolom qua breedte nog wel op regel 1 in een gewone flex-wrap. flex-basis:100%
   op de iconen-kolom zelf geeft hetzelfde zichtbare resultaat zonder die magic-number-hack over te nemen. */
.shell-footer-row:has(+ .shell-footer-bar) .shell-footer-col:has(.cms-links--icons) { flex-basis: 100%; }
.shell-footer-row:has(+ .shell-footer-bar) .cms-links,
.shell-footer-row:has(+ .shell-footer-bar) .cms-text ul {
  display: flex; flex-flow: row wrap; align-items: center; list-style: none; margin: 0; padding: 0; gap: 0;
}
.shell-footer-row:has(+ .shell-footer-bar) .cms-links li,
.shell-footer-row:has(+ .shell-footer-bar) .cms-text ul li {
  color: #555; font-size: 13px; line-height: 18px;
}
.shell-footer-row:has(+ .shell-footer-bar) .cms-links li:not(:last-child)::after,
.shell-footer-row:has(+ .shell-footer-bar) .cms-text ul li:not(:last-child)::after {
  /* Gemeten op live: 18px (niet 13px zoals de omringende linktekst - het scheidingsteken is bewust
     groter/hoger dan de tekst). line-height hierboven staat expliciet op dezelfde 18px voor ELKE li
     (met of zonder scheidingsteken) - zonder dat kreeg een li MET het grotere scheidingsteken een
     hogere regel-hoogte dan de laatste li (zonder ::after), waardoor "Privacybeleid"/"info@vangool.nl"
     zichtbaar hoger kwamen te staan dan hun buren in dezelfde rij. */
  content: "/"; margin: 0 5px; color: #352480; font-size: 18px; line-height: 18px;
}
/* Social-iconen (.cms-links--icons) zijn GEEN tekstlinks - live toont geen "/"-scheidingsteken
   ertussen, alleen de iconen zelf op een rijtje. De regel hierboven raakt elke .cms-links in deze
   rij; zonder :not(:last-child) had deze override een LAGERE specificiteit (3 classes) dan die regel
   (4 classes, door zijn eigen :not()), dus verloor hij stilletjes - zelfde structuur nodig om te winnen. */
.shell-footer-row:has(+ .shell-footer-bar) .cms-links--icons li:not(:last-child)::after { content: none; }
/* Generieke .shell-footer .cms-link-logo (globals.css: width:auto, alleen height:18px vast) behoudt
   de intrinsieke aspect-ratio per icoon-bestand - bij VanGool's social-iconen geeft dat een grote
   breedte-spreiding (11-27px, bv. YouTube veel breder dan Facebook). Live's eigen iconen variëren ook
   iets in breedte, maar veel minder (10-18px) - vast vierkant + object-fit:contain geeft hier een
   consistenter, rustiger resultaat dan de generieke aspect-ratio-behoudende regel. */
.shell-footer .cms-links--icons .cms-link-logo { width: 18px; height: 18px; object-fit: contain; }
/* De generieke gap:0 hierboven (bedoeld voor de tekst-links, waar de "/"-scheider zelf al ruimte
   geeft) liet de social-iconen zonder enige tussenruimte tegen elkaar aan staan - gemeten op live:
   20px consistente gap tussen elk icoon. Zelfde specificiteit (3 classes) als de gap:0-regel, dus
   bronvolgorde (deze regel staat later) beslist. */
.shell-footer-row:has(+ .shell-footer-bar) .cms-links--icons { gap: 20px; }
@media (max-width: 860px) {
  .shell-footer-row:has(+ .shell-footer-bar) .shell-footer-inner { flex-direction: column; align-items: flex-start; text-align: left; }
  .shell-footer-row:has(+ .shell-footer-bar) .shell-footer-col { flex-basis: 100%; }
}

/* Navy background-image rows (Over ons: "Kijk mee met Edwin", "Wij komen met onze keurmeesters"):
   Extend to viewport edges by negating the parent container's left/right positioning.
   Container is ~1250px centered on 1280px viewport = ~15px margin per side.
   BUG (gevonden na screenshot van een echte browser op een andere breedte dan getest): deze regel
   miste `position: relative; left: 50%; right: 50%` - zonder dat blijft de rij op zijn statische
   positie binnen de ~1170px-container staan, en trekt margin:-50vw de box dan vanaf DIE positie naar
   links, niet vanaf het midden van de viewport. Resultaat: de rij schoof honderden pixels naar links
   uit beeld (tekst liep off-screen) en het navy-vlak eindigde ruim voor de rechterrand. Dit is exact
   dezelfde full-bleed-truc als de banner-rij hierboven (regel ~1384) - die heeft `left/right:50%`
   wél, en werkte daardoor altijd correct; deze regel was gewoon incompleet. */
.cms-row[style*="background-image"] {
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
  /* Gemeten op live (.row-breakout.block_breakout): padding: 50px 163.5px - de 50px verticaal
     ontbrak hier helemaal, dus de tekst/video stonden zonder enige lucht plat tegen de boven- en
     onderkant van het navy-vlak aan.
     Horizontaal: EERST stond hier padding:50vw (zoals de margin hierboven) - dat leek te werken
     voor de 6+6-grid-rij ("Kijk mee met Edwin"), want een aparte override compenseerde daar
     specifiek. Maar op de single-column variant ("Lastmeetapparatuur kalibreren", block_layout=12,
     gewoon .cms-row zonder --grid) is er geen enkele kind-override - padding:50vw op een 1512px-
     viewport = 756px links+756px rechts = 0px content-box over, dus de tekst kromp naar
     letter-voor-letter-wrap (bijna onleesbaar, "echt bagger"). calc(50vw - 585px) rekent (anders dan
     de eerder geprobeerde calc(50% - ...), zie git-historie) tegen de VIEWPORT, niet de containing
     block, en werkt daardoor identiek voor zowel de grid- als de single-column-variant - geen aparte
     override per geval meer nodig. */
  padding: 50px calc(50vw - 585px);
  width: 100vw;
  /* Gemeten op live: background-size:cover (wij hadden geen background-size gezet, dus browser-
     default "auto" - de foto (1368x428 nativ) rendert dan op zijn eigen pixelformaat i.p.v. de rij te
     vullen. Onder de 1368px viewport onzichtbaar (de rij is dan smaller dan de foto), maar op een
     breed scherm (bv. 1920px) bleef rechts van de foto een kale witte/transparante rand over. */
  background-size: cover;
}
/* Mobiel: calc(50vw - 585px) wordt negatief onder ~1170px viewport en clamped naar 0px
   horizontaal (padding kan niet negatief) - tekst/video stonden daardoor plat tegen de navy-
   randen aan. Losse override zet zowel wat lucht links/rechts terug als de 50px verticaal
   omlaag (te veel witruimte op een smal scherm t.o.v. de korte tekstregels). */
@media (max-width: 560px) {
  .cms-row[style*="background-image"] {
    padding: 24px var(--space-4);
  }
}
/* Tablet gap (2026-08-08, over-ons audit): the base rule's calc(50vw - 585px) is only positive
   above ~1170px viewport - the mobile override above only covers <=560px, leaving 561-1169px
   (iPad-ish widths) with 0px horizontal padding (text flush against the navy edges, reported at
   918px on /pagina/over-ons). 1169 is the formula's own natural cutoff (50vw-585px hits 0 exactly
   at 1170px), not an arbitrary Bootstrap tier - matches the underlying math, not a guess. */
@media (min-width: 561px) and (max-width: 1169px) {
  .cms-row[style*="background-image"] {
    padding: 50px var(--space-6);
  }
}
/* Gemeten op live: twee opeenvolgende navy-rijen ("Kijk mee met Edwin" + "Lastmeetapparatuur
   kalibreren") staan FLUSH tegen elkaar (0px), maar .cms-page's flex-gap (var(--space-4), 16px)
   zette hier een witte streep tussen. BUG (gevonden op Jung Heftechniek: banner-carousel gevolgd
   door ÉÉN navy-rij, geen tweede): de vorige versie van deze regel zat op de basisselector
   hierboven (elke background-image-rij trekt ALTIJD 16px omhoog), dus trok ook de gap weg tussen
   een GEWONE rij (hier: een banner-carousel, geen background-image) en de eerste navy-rij die erop
   volgt - precies het omgekeerde probleem: geen witruimte waar die wél moet blijven staan.
   Scope daarom met de adjacent-sibling-combinator: alleen wegtrekken als de VOORGAANDE rij zélf ook
   een background-image-rij is (elke instantie moet zijn eigen gap naar zo'n buur wegtrekken, niet
   de gap naar een niet-navy-rij ervoor). */
.cms-row[style*="background-image"] + .cms-row[style*="background-image"] {
  margin-top: calc(-1 * var(--space-4));
}
/* BUG: ".cms-text h2[style*=center]" (hierboven, geschreven voor de losse "header-light"
   adviestekst - MontserratLight, grijs) matcht ook deze navy-koppen ("Lastmeetapparatuur
   kalibreren") puur omdat ze óók een inline text-align:center hebben - toevallige structurele
   overlap, geen inhoudelijke. Live is deze kop 24px MontserratBold (dus fontWeight 700), niet de
   300 van de adviestekst - de span regelt al de witte kleur (zie DB: <span style="color:#FFFFFF">),
   dit hoeft alleen het gewicht terug te zetten. Hogere specificiteit (extra attribuutselector) wint
   ongeacht bronvolgorde. */
.cms-row[style*="background-image"] .cms-text h2[style*="center"],
.cms-row[style*="background-image"] .cms-text h3[style*="center"],
.cms-row[style*="background-image"] .cms-text h4[style*="center"] {
  font-weight: 700;
}
/* De CMS-rich-text hier gebruikt lege <p>&nbsp;</p>/<h1>&nbsp;</h1> regels als handmatige witruimte
   tussen "Kijk mee met Edwin" en "Wij komen met onze keurmeesters" (2 lege p's + 1 lege h1, vóór de
   2e h1) - bedoeld om die 2e kop ongeveer gelijk te laten starten met de 2e video ernaast. Bij ons
   renderden die spacer-regels op hun kale line-height (~12px margin-bottom elk), 90px te weinig om
   de 2e kop op gelijke hoogte met video 2 te krijgen (gemeten: kop stond 90px te vroeg t.o.v. het
   begin van video 2). Echte content-paragrafen zijn altijd in een <span style=color:...> gewikkeld
   (WYSIWYG-output); de spacers hebben geen span-kind - dat onderscheidt ze zonder een class te hoeven
   toevoegen aan de content zelf. +30px per spacer-regel (x3 = +90px) legt de 2e kop gelijk met video 2.
   Alleen relevant zolang de twee blokken (video + tekst) naast elkaar staan (grid-column: span 6)
   - onder 992px stapelt de grid naar span 12 (zie hoger), dus is er niks meer om mee gelijk te
   leggen.
   BUG (2026-08-08, iPad audit): deze regel stond op `min-width: 561px` - dat was juist toen de
   stack-breakpoint nog op 560px zat, maar is sindsdien naar 991px verhoogd (zie .cms-row--grid
   hoger in dit bestand). Tussen 561-991px kregen de spacer-regels dus nog steeds +42px i.p.v. +12px
   TERWIJL de blokken al gestapeld waren - precies de 90px onnodige witruimte tussen "Kijk mee met
   Edwin" en "Wij komen met onze keurmeesters" die op 918-965px werd gerapporteerd. Grens verhoogd
   naar 992px zodat 'm exact matcht met de kolom-stack-breakpoint. */
@media (min-width: 992px) {
  .cms-row--grid[style*="background-image"] .cms-text > :is(p, h1, h2, h3, h4):not(:has(span)) {
    margin-bottom: 42px;
  }
}

/* Pijl-knoppen zoals live ("Bekijk assortiment →") - ALLEEN op de tegel- en strip-varianten.
   Niet generiek op .cms-links: dat plakte ook pijlen achter social-icons, footerlinks en het
   Contact-tabje (zichtbaar in de side-by-side van 29-07). */
.cms-links--tiles a::after, .cms-links--header-strip a::after {
  content: "";
  display: inline-block;
  width: 12px; height: 12px; margin-left: 6px;
  background: url("/bespoke/vangool/fa-arrow-right-blue.svg") center/contain no-repeat;
}

/* De 4 hero-tegels (Verkoop/Verhuur/Kalibratiecentrum/Testen & Keuren): gemeten op live, deze rij
   heeft GEEN gap tussen de tegels (edge-to-edge, elk 316px in een 1265px-viewport) - de generieke
   `.cms-banner-grid { gap: var(--space-4) }` (16px) gaf hier zichtbare witruimte tussen de tegels die
   live niet heeft. Gescoped op `:has(.cms-banner-tile--overlay)` zodat andere banner-grids (bv. de
   footer-certificatielogo's, die wél 30px gap hebben) ongemoeid blijven. */
.cms-banner-grid:has(.cms-banner-tile--overlay) { gap: 0; }

/* Bespoke banner-flags (ucm_banner_blocks.portrait_overlay/full_width_landscape/advice_banner) -
   structurele mechanica staat generiek in globals.css, dit is puur de VanGool-look erbovenop. */
.cms-banner-slide-overlay {
  background: linear-gradient(to top, rgba(0,42,101,.85), rgba(0,42,101,0));
  color: #fff;
}
/* Gemeten op live (.static-banner): de tegel-KOLOM zelf heeft 15px links/rechts padding (transparant)
   - de foto (en overlay/tekst erover) is dus maar 286px breed, gecentreerd binnen de 316px kolom. De
   generieke gap:0 (hierboven) klopt qua GRID (kolommen raken elkaar echt zonder CSS-gap), maar zonder
   deze padding liep onze foto edge-to-edge tot de kolomrand, dus ontbrak de zichtbare witruimte
   (2x 15px = 30px witte pagina-achtergrond) tussen elke foto die live wél toont. box-sizing:border-box
   houdt de kolombreedte zelf ongewijzigd (316-ish px), alleen de foto/overlay/tekst erbinnen krimpen. */
.cms-banner-tile--overlay {
  padding: 0 15px;
  box-sizing: border-box;
}
/* Gemeten op live (.banner_block_hover): de blauwe overlay is een gradient over de VOLLEDIGE
   foto-hoogte (transparant boven -> volledig dekkend #002a65 onder), niet alleen achter het
   tekst-label - dat gaf bij ons een veel te kleine/lichte waas (gradient zat alleen op het krappe
   label-vlak, met max 0.85 opacity i.p.v. volledig dekkend). ::before dekt de foto af binnen dezelfde
   15px-marge als hierboven (inset:0 alleen zou de PADDING-box vullen, dus ook over de witruimte-marge
   heen lopen) - het label zelf blijft transparant en komt er als DOM-kind vanzelf bovenop te liggen. */
.cms-banner-tile--overlay::before {
  content: ""; position: absolute; inset: 0 15px;
  background: linear-gradient(to top, rgba(0,42,101,1) 0%, rgba(0,42,101,0) 100%);
  pointer-events: none;
}
/* Tegel-label ligt OVER de foto: wit, 20px MontserratBold, GECENTREERD (gemeten op live: zowel de
   titel als de CTA-regel staan text-align:center, niet links zoals de generieke .cms-banner-tile-label
   aanneemt) met de CTA-regel eronder in 14px. left/right:15px i.p.v. de generieke 0/0, zodat de tekst
   ook binnen dezelfde foto-breedte blijft (niet over de witruimte-marge heen). */
.cms-banner-tile--overlay .cms-banner-tile-label {
  color: #fff;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 20px;
  line-height: 1.25;
  padding: var(--space-5) var(--space-4) var(--space-4);
  text-align: center;
  left: 15px;
  right: 15px;
}
.cms-banner-tile--overlay .cms-banner-tile-cta {
  color: #fff; font-family: var(--font-heading); font-weight: 700;
  font-size: 14px; opacity: 1; margin-top: var(--space-1); padding-bottom: var(--space-4);
}
/* CORRECTIE: het pijltje bestaat wél op live - eerder ten onrechte verwijderd op basis van een
   onvolledige meting (alleen .banner_button_link's eigen ::after gecheckt, content:"" zonder icoon).
   Het echte pijltje zit op de OUDER-div (.banner_button, niet de link zelf): FontAwesome fa-arrow-
   right (codepoint U+F061), wit, ~15px vanaf de onderkant van de tegel, gecentreerd. Hier als gewone
   in-flow ::after i.p.v. FontAwesome's absolute positionering na te bouwen - text-align:center op de
   ouder centreert 'm al, en de padding-bottom hierboven geeft de tegel dezelfde "lucht" onder de CTA
   als live, ongeacht de tekstlengte per tegel (varieert: "Bekijk assortiment" vs "Zo helpen wij u").
   Was ooit een Unicode "→"-teken (dunne font-rendering, oogde te licht t.o.v. live's dikkere
   FontAwesome-glyph, gemeld 2026-08-08) - vervangen door dezelfde witte SVG-pijl als de advies-knop
   en de nieuwsbrief-knop elders in dit bestand, voor een consistent dikke pijl overal. */
.cms-banner-tile--overlay .cms-banner-tile-cta::after {
  content: "";
  display: block;
  width: 14px;
  height: 14px;
  margin: var(--space-2) auto 0;
  background: url("/bespoke/vangool/fa-arrow-right-white.svg") center/contain no-repeat;
}
/* ---- row_under_header: de banner strak onder de kopbalk, over de volle breedte -----------------
 * ucm_structure_blocks.row_under_header staat bij Van Gool op 13 BANNER-blokken (Home, Over ons,
 * Downloads, Maatwerk & advies, Op locatie, Levering, zes merkpagina's, Kalibratiecentrum). Legacy
 * zet zo'n blok BUITEN de 1170-container: gemeten op vangool.nl/nl/1/diensten/levering.aspx staat er
 * `div.static-banner.col-md-12.banner_background` op x=-15 w=1568 h=553 in een venster van 1538 -
 * dus van rand tot rand, met de foto als `background-size: cover`.
 *
 * Bij ons leunde dat op de vlag van de RIJ (block_breakout -> .cms-row--breakout). Dat klopte op 8
 * van de 13 pagina's toevallig; op Levering, Op locatie, Maatwerk & advies en Kalibratiecentrum staat
 * de rij op 0, en op Downloads hangt het blok niet eens in een rij. Daar bleef de banner in de
 * container van 1138 steken (gemeld op /pagina/levering). De vlag van het BLOK is dus de juiste haak,
 * net als bij de advies-banner verderop in dit bestand.
 *
 * `calc(50% - 50vw)` is met opzet zo geschreven: staat het blok tóch al in een breakout-rij (die 8
 * pagina's), dan is 50% van die rij precies 50vw en komt er 0 uit - dan verandert deze regel niets.
 *
 * De foto moet ook echt meeschalen: `showroom website.png` is 1250 breed, dus met alleen
 * max-width:100% zou hij op een breder venster opnieuw een witte strook laten (zie de gelijksoortige
 * regel voor .cms-banner-grid--full-width in globals.css). Live komt op dezelfde maat uit: 1250 ->
 * 1538 is 1.23x, en 553 (de gemeten hoogte daar) is precies 1.23x de eigen hoogte. */
/* Op de RIJ en niet op het blok zelf. Eerst stond dit op het blok, en dat ging mis op een pagina waar
   de banner maar een HALVE rij breed is: /pagina/maatwerk--advies heeft een banner van 6/12 met de
   tekst ernaast, en die banner schoof toen naar de linkerrand terwijl de tekst bleef staan - dus dwars
   over elkaar heen. Live trekt daar de hele RIJ open en houdt de 50/50-verdeling: gemeten op
   maatwerk--advies.aspx staat de banner op x=-15 w=784 en de tekstkolom op x=769 w=784, allebei buiten
   de 1170-container. Met de rij als drager klopt allebei: een span-12 banner (Levering) wordt 100vw,
   een span-6 banner de helft daarvan. */
.cms-page .cms-row:has(> .cms-block--under-header) {
  width: 100vw;
  /* Stond de rij zelf al op `block_breakout`, dan heeft globals.css er de andere full-bleed-truc op
     staan: position:relative + left/right:50% + margin:-50vw. Die twee door elkaar heen leverden een
     rij op x=569 met een horizontale schuifbalk (gemeten op /pagina/over-ons, scrollWidth 2107 in een
     venster van 1538). Hier dus expliciet terug naar static, zodat alleen de marge hieronder telt -
     dat werkt zowel op een rij mét als zonder die vlag. */
  position: static;
  left: auto;
  right: auto;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}
.cms-page .cms-block--under-header .cms-banner-tile img { width: 100%; }
/* In een float-rij hebben de blokken 12px zijpadding (globals.css), en daarmee bleef er links van de
   foto een witte strook van 12px staan terwijl de rij zelf wél tot de rand liep. Live lost dat op
   door het blok 15px verder naar links te trekken dan de rij (x=-15 tegen 0); hetzelfde effect,
   minder omweg: alleen de LINKER padding weg, de rechter blijft staan als naad naar de tekstkolom. */
.cms-page .cms-row--float > .cms-block--under-header { padding-left: 0; }
/* Zelfde uitzondering als bij de advies-banner: in de categoriekolom en in de blok-editor is de
   container niet symmetrisch gecentreerd, dus daar zou deze truc de rij het venster uit schuiven. */
.category-main .cms-row:has(> .cms-block--under-header),
.category-sidebar-col .cms-row:has(> .cms-block--under-header),
.admin-block-body .cms-row:has(> .cms-block--under-header) {
  width: auto;
  margin-left: 0;
  margin-right: 0;
}

/* Full-width hero (Home/Over ons e.d.): gemeten op live (.banner_title h2 / .banner_subtitle p) -
   dit is een ANDER teksttype dan de 316px-grid-tegels hierboven (die zijn wél correct op 20px), dus
   niet dezelfde class-instantie hergebruiken zonder override. Live: h2 32px MontserratBold met
   margin-bottom 30px, p 24px MontserratSemiBold, beide gecentreerd binnen een VASTE 1170px container
   (Bootstrap .container, niet-fluid - blijft 1170px ongeacht viewport, ook op 1920px gemeten) - dus
   max-width+auto-margin i.p.v. left/right:15px. `.cms-banner-grid--full-width` staat op de OUDER
   (zie CmsBannerGrid.tsx), dus scopen daarop i.p.v. op --overlay zelf om de grid-tegels ongemoeid
   te laten.
   BELANGRIJK verschil met de grid-tegels: de FOTO zelf is op live edge-to-edge (100% van de rij,
   .static-banner heeft geen max-width/padding) - de 15px-padding en ::before-gradient hierboven zijn
   ALLEEN gemeten op de kleine 316px-tegels en horen niet bij de full-width hero. Live heeft hier
   zelfs HELEMAAL geen donkere overlay (.banner_block_hover/_inner zijn transparant, geverifieerd via
   getComputedStyle - de foto zelf is al donker genoeg voor wit tekstcontrast). Vandaar de resets
   hieronder: padding:0 (geen witruimte-marge) en ::before uitgeschakeld (geen extra donkere waas). */
.cms-banner-grid--full-width .cms-banner-tile--overlay {
  padding: 0;
}
.cms-banner-grid--full-width .cms-banner-tile--overlay::before {
  display: none;
}
.cms-banner-grid--full-width .cms-banner-tile-label {
  font-size: 32px;
  line-height: 1.2;
  max-width: var(--container-max);
  /* Live wrapt de titel op 877px i.p.v. de volle 1170px container (h2 is display:inline-block,
     geen eigen max-width) - dus geen greedy fill-tot-de-rand maar gebalanceerde regels. Zonder dit
     zette onze versie bijna de hele zin op regel 1 (alleen het laatste woord op regel 2), veel
     breder dan live. text-wrap:balance repliceert dat gedrag zonder een gokwaarde als max-width. */
  text-wrap: balance;
  left: 0; right: 0;
  margin: 0 auto;
  padding: var(--space-5) var(--space-4) 40px;
}
.cms-banner-grid--full-width .cms-banner-tile-sub {
  display: block;
  font-size: 24px;
  font-weight: 600;
  opacity: 1;
  margin-top: 30px; /* gemeten op live: h2's margin-bottom, niet --space-2 (8px) */
}
/* Mobiel: gemeten op live (.static-banner op vangool.nl/nl/1/over-ons/onze-visie.aspx, 375px
   viewport) - de foto-tegel staat daar op een VASTE 500px hoogte met background-size:cover (fors
   hoger dan zijn eigen 1366x604-aspect zou geven op 375px breed: dat is maar ~166px, veel te
   "smal/laag" - de foto wordt op live juist ingezoomd/uitgesneden tot een portretachtige verhouding).
   Onze <img>+object-fit-aanpak i.p.v. legacy's background-image levert hetzelfde optisch resultaat
   met dezelfde vaste hoogte + cover-crop. Titel 24px/line-height 1.2, subtitel 13px (ook live-gemeten
   op dezelfde pagina) - ruim kleiner dan de 32px/24px desktop-meting hierboven, die anders op een
   343px-brede telefoon naar 3-4 regels wrapt en het label (absoluut gepositioneerd, bottom:0, geen
   top - globals.css) hoger maakt dan de tegel, waardoor de titel-tekst omhoog het beeld uit schuift
   en overlapt met de vorige alinea erboven (zag eruit als "kapotte"/spookerige tekst - was geen
   renderbug maar deze overflow). */
/* 720 -> 991 (2026-08-08, iPad audit): this block assumed "mobile" only ever meant <=720px, but
   .cms-banner-grid now stacks to one column up to 991px (same Bootstrap col-md-* root cause as
   elsewhere in this audit) - without this move, a hero photo at e.g. 878px got the DESKTOP crop
   (measured for a wide multi-column tile) squeezed into the new single-column width instead,
   which reads as an extreme, wrong zoom into the image (reported 2026-08-08). */
@media (max-width: 991px) {
  /* Default voor ELKE volle-breedte hero op mobiel: eigen aspect-ratio, geen crop. Klopt voor alle
     "pure foto, geen teksttitel erover"-banners (Werken bij Van Gool 1920x379, Kalibratiecentrum
     1920x380, ...) - gemeten op live dat legacy die net zo ongecropt toont (height:auto). Deze
     banners zijn brede panoramafoto's; een vaste hoogte zou 80%+ van de breedte wegsnijden tot een
     onherkenbaar detail. */
  .cms-banner-grid--full-width .cms-banner-tile--overlay img {
    height: auto;
    object-fit: fill;
  }
  /* Uitzondering: banners MET een titel/subtitel-overlay (bv. "Onze gecertificeerde EKH-
     keurmeesters..." op Over ons/Onze visie, hero.jpg 1366x604 = 2.26:1) hebben wél ruimte nodig
     voor die tekst en worden op live juist WEL uitgesneden tot een portretachtige 500px-hoogte
     (gemeten op vangool.nl/nl/1/over-ons/onze-visie.aspx). :has(.cms-banner-tile-label) onderscheidt
     dit correct zonder een eigen data-vlag nodig te hebben - portraitOverlay/fullWidthLandscape zijn
     voor beide bannertypes identiek true, maar alleen het teksttype heeft ook echt een label-kind. */
  .cms-banner-grid--full-width .cms-banner-tile--overlay:has(.cms-banner-tile-label) img {
    height: 500px;
    object-fit: cover;
  }
  .cms-banner-grid--full-width .cms-banner-tile-label {
    font-size: 24px;
    line-height: 1.2;
    /* Groter padding-bottom dan padding-top: het label is bottom:0 verankerd (globals.css) zonder
       top, dus meer padding-bottom duwt de HELE tekstblok (titel + subtitel) omhoog weg van de
       onderrand van de foto, i.p.v. alleen ruimte na de subtitel toe te voegen. Wesley: stond te
       plat tegen de onderkant aan. */
    padding: var(--space-3) var(--space-3) 28px;
  }
  .cms-banner-grid--full-width .cms-banner-tile-sub {
    font-size: 13px;
    /* Wesley: eerst per ongeluk te ver dichtgetrokken (-4px, zag er dan weer te krap uit) -
       var(--space-3) (12px) geeft duidelijke maar niet overdreven lucht tussen titel en subtitel. */
    margin-top: var(--space-3);
  }
}
/* Gemeten op live MOBIEL (.static-banner/.banner_block_hover, dezelfde 4 hero-tegels als hierboven,
   maar nu gestapeld i.p.v. naast elkaar): elke tegel 200px hoog met ~20px witruimte ertussen - op
   onze site erfden ze tot nu toe alleen de DESKTOP-meting (geen vaste hoogte, dus de foto's eigen
   aspect-ratio bepaalde de hoogte), wat op smalle schermen veel te hoge tegels gaf (~450px, geen
   gap). object-fit:cover houdt de bestaande CMS-foto's (niet per-breakpoint gecropt) toch op een
   consistente hoogte zonder uitrekken. body:has(.shell-header--vangool) scoped dit op VanGool - de
   gedeelde .cms-banner-tile--overlay-klasse wordt ook door Deponti gebruikt, zonder deze meting. */
@media (max-width: 991px) {
  body:has(.shell-header--vangool) .cms-banner-grid:has(.cms-banner-tile--overlay) { gap: 20px; }
  /* :not(.cms-banner-grid--full-width) - deze 200px/cover-crop is gemeten op de 4 KLEINE hero-tegels
     (Verkoop/Verhuur/Kalibratiecentrum/Testen & Keuren), maar .cms-banner-tile--overlay wordt ook
     gezet op de volle-breedte hero (bv. "Onze gecertificeerde EKH-keurmeesters..." op Over ons/Onze
     visie - zie CmsBannerGrid.tsx: fullWidthLandscape zet ook --overlay). Zonder deze uitsluiting
     kneep dezelfde 200px-crop ook die hero-foto in, wat de bovenste tekstregel (in de foto zelf
     gebakken) wegsneed - de tekst was niet "afgebroken" door een layoutbug maar door een crop die
     voor een heel ander, vierkanter beeldformaat was gemeten. */
  /* `width: 100%` hoort hier ONLOSMAKELIJK bij de vaste hoogte. Zonder die breedte gaf `object-fit:
     cover` niets te croppen: de generieke regel is `max-width: 100%; height: auto`, dus op desktop
     rekt de foto zich in het grid uit tot de kolombreedte (gemeten 330px) en volgt de hoogte uit de
     verhouding. Zet je alleen de HOOGTE vast, dan is de breedte niet langer `auto`-uitrekbaar maar
     volgt hij de beeldverhouding - en dan wordt een portretfoto van 1066x1392 op 200px hoog precies
     153px breed. Gemeten op localhost 375px: foto 15..168 in een tegel van 375, dus de rechterhelft
     was kale gradient. Live zet ze allebei: `width: 345px; height: 200px; object-fit: cover` (345 =
     375 - 2x15 padding), dus vult de foto de contentbox en doet cover het werk. */
  body:has(.shell-header--vangool) .cms-banner-grid:not(.cms-banner-grid--full-width) .cms-banner-tile--overlay img { width: 100%; height: 200px; object-fit: cover; }
  /* Wesley: het team-rondje in het "Advies nodig"-adviesblok mag op telefoon weg - alleen de tekst +
     CTA-knop blijven over. display:none op de <img> alleen liet de 2-koloms grid hieronder intact
     (.cms-banner-tile-body: 1fr minmax(0,234px)) - de foto-kolom bleef zo 234px reserveren voor een
     lege cel, wat de tekstkolom op een 343px-breed scherm tot maar 109px kneep (titel brak woord voor
     woord: "Advies"/"nodig bij"/"uw"/"keuze?"). grid-template-columns:1fr laat de tekst de volle
     breedte gebruiken nu de foto er sowieso niet meer staat - geldt op elke pagina die dit CMS-blok
     rendert (homepage, categoriepagina's, ...), niet alleen de homepage. */
  body:has(.shell-header--vangool) .cms-banner-tile--advice img { display: none; }
  body:has(.shell-header--vangool) .cms-banner-tile--advice > .cms-banner-tile-body { grid-template-columns: 1fr; }
  /* .shell-footer .cms-text h2's max-width:200px (hierboven, buiten een media query) forceert
     dezelfde regelbreuk als live's DESKTOP 25%-tekstkolom (~292px) - nu die kolom op mobiel de volle
     rijbreedte heeft (zie de .shell-footer-row:has(.cms-banner-grid)-fix hierboven), diende die
     kunstmatige 200px-cap geen doel meer en brak de titel juist onnodig midden in woorden. */
  body:has(.shell-header--vangool) .shell-footer .cms-text h2 { max-width: none; }
  /* The 4 certification badges (metaalunie/DNV ISO9001/DNV VCA**/EKH) are each a different width -
     fine in live's horizontal desktop row, but left-aligned in a single stacked mobile column they
     read as a ragged, unintentional list. Centering each gives the stack a calm, deliberate spine
     instead of a jagged left edge. */
  body:has(.shell-header--vangool) .shell-footer .cms-banner-tile { text-align: center; }
  body:has(.shell-header--vangool) .shell-footer .cms-banner-tile img { margin: 0 auto; }
}
/* Wesley: het Van Gool-team is ~40 mensen in een 4-koloms grid (elk blok span 3 van 12) - de
   generieke mobiele stack-regel (globals.css: elk blok naar span 12 !important) maakt dat op
   telefoon 40 losse volle-breedte rijen. 2 naast elkaar (span 6) houdt de pagina scanbaar zonder
   een apart layout-mechanisme te bouwen. Scoped op data-page-key zodat andere --grid-rijen (bv.
   Kijk-mee-met-Edwin's foto+tekst-paar, die WEL 1-per-rij moet blijven op mobiel) ongemoeid blijven.
   !important nodig om de even specifieke globals-regel te verslaan (specificiteit is gelijk, maar
   !important wint sowieso onafhankelijk van bronvolgorde). */
@media (max-width: 560px) {
  body:has(.shell-header--vangool) .cms-page[data-page-key="van-gool-team"] .cms-row--grid > .cms-block,
  body:has(.shell-header--vangool) .cms-page[data-page-key="erkenningen"] .cms-row--grid > .cms-block {
    grid-column: span 6 !important;
  }
}
/* Tablet (2026-08-08, iPad audit): gemeten op live (768/899/965px) - deze grid blijft daar gewoon
   op de volle 4-koloms desktop-layout staan (auto-fit, geen harde Bootstrap-breakpoint zoals de
   andere grids in dit bestand), en collapt pas onder ~560px naar 2. De generieke tablet-stackregel
   (globals.css, max-width:991px -> span 12) gaf hier dus 1 foto per rij i.p.v. 4 - specifiek
   gerapporteerd op 899px. Zonder deze override viel het tablet-bereik (561-991px) tussen de twee
   bestaande regels door. */
@media (min-width: 561px) and (max-width: 991px) {
  body:has(.shell-header--vangool) .cms-page[data-page-key="van-gool-team"] .cms-row--grid > .cms-block,
  body:has(.shell-header--vangool) .cms-page[data-page-key="erkenningen"] .cms-row--grid > .cms-block {
    grid-column: span 3 !important;
  }
}
.cms-banner-slide-overlay strong { font-family: var(--font-heading); font-size: 1.1rem; }
.cms-banner-slide-overlay span { font-size: .9rem; opacity: .9; }

/* advice_banner: live is een grijze band met de tekst LINKS (titel + banner_subdesc + knop uit
   banner_button) en de ronde teamfoto RECHTS. De tegel-markup is <img> + <span class=label>, dus we
   draaien de volgorde om met grid-order i.p.v. extra DOM. */
/* Op een categorie-pagina MET producten (leaf, geen subcategorieën) stopt live's sidebar al bij de
   product-listing (gemeten: sidebar-onderrand op y=716) - dit advies-blok staat daar ver onder
   (y=4494) en gebruikt dan gewoon de volle paginabreedte (1265px), niet de main-kolom-breedte. Onze
   CSS-Grid (.category-page: sidebar+main als gelijke-hoogte kolommen) houdt de kolombreedte echter
   over de HELE hoogte vast, dus de generieke "cancel full-bleed in .category-main" regel (globals.css)
   knijpt dit specifieke blok te veel af. Alleen voor de advies-tile de viewport-full-bleed weer
   aanzetten (hogere/gelijke specificiteit + latere bronvolgorde wint van de generieke cancel-regel) -
   andere banners in .category-main (bv. de smalle sidebar-eigen banner uit de generieke regel's eigen
   comment) blijven wel ingeperkt.
   De standaard left:50%/margin-left:-50vw-truc gaat uit van een SYMMETRISCH gecentreerde container
   (evenveel ruimte links als rechts in de viewport) - .category-main is dat niet (sidebar duwt 'm
   alleen naar rechts), dus die truc gaf hier een zichtbare verschuiving (eerste poging: 124.5px te
   ver naar rechts). I.p.v. daarvan: expliciet berekende margin-left op basis van de bekende, vaste
   structuur (paginacentrering + 16px padding + 240px sidebar + 24px kolom-gap, alle vier gemeten) -
   met width:100vw als vaste breedte heeft margin-right geen effect meer op de eigen positie (de
   rechterrand ligt dan automatisch op linkerrand+100vw), dus die hoeft niet apart berekend. */
/* min-width:992px (moved from 861 on 2026-08-08, iPad audit - NOT the same 1099/1100 nav-hamburger
   threshold used elsewhere in this audit, a different system with its own correct value) - the
   280px offset assumes the sidebar layout (16px padding + 240px sidebar + 24px gap) that
   .category-page only has above 991px now (see globals.css's own sidebar-collapse breakpoint,
   itself just moved from 860 - same Bootstrap col-md-* root cause as .cms-banner-grid/.cms-row--
   grid elsewhere in this audit); below that .category-page is already a single 1fr column with no
   sidebar to offset against, so this same calc pushed the whole row off-screen to the left instead
   (reported: the advice block appearing as a narrow, clipped sliver, most of it shifted past the
   left edge of the viewport - recurred 2026-08-08 at iPad width once the sidebar breakpoint moved
   out from under this pair). */
@media (min-width: 992px) {
  .category-main .cms-row:has(.cms-banner-tile--advice) {
    width: 100vw;
    margin-left: calc(-1 * (max(0px, (100vw - var(--container-max)) / 2) + 280px));
  }
}
/* Below the sidebar breakpoint, .category-main is centered/symmetric again (no sidebar pushing it
   off-center), so the plain full-bleed trick applies directly - the grey advice band should still
   break out of the page's normal content gutter into a true edge-to-edge band on phone, same intent
   as the desktop rule above, just without its sidebar-offset math. */
@media (max-width: 991px) {
  .category-main .cms-row:has(.cms-banner-tile--advice) {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
  }
}
/* Op elke ANDERE pagina (home, faq, /pagina/*) stond hierboven niets, en dat werkte alleen zolang de
   rij waarin het blok viel toevallig `block_breakout` had staan - dan trok .cms-row--breakout (globals.
   css) de hele rij al naar 100vw en liftte de band mee. Die samenloop is weg: Van Gools redacteuren
   hebben de advies-banner opnieuw geplaatst (nieuw blokrecord 0000001917) in rij 0000001023, en die
   rij heeft `block_breakout = 0`. Uitkomst: de grijze band was 1138 breed in plaats van 1440, en de
   padding hieronder (calc(50% - 585px), bedoeld om de inhoud vanuit een 100vw-band terug in de
   1170-container te zetten) rekende zich negatief en verdween, dus de tekst plakte tegen de bandrand.
   Op de band zelf leunen en niet op de vlag van de rij, want legacy doet dat ook niet: gemeten op
   vangool.nl/ zit deze banner helemaal niet in de blokkenstroom van de pagina maar in de footer, in
   zijn EIGEN wrapper (`div.col-md-12.uc_banner_block.advice-banner-wrapper` > `div.row.advice-banner
   .reset`, 1440 breed op x=0, met 135px padding op de kolom erbinnen). De volle breedte hoort dus bij
   de advies-vlag, niet bij de rij eromheen.
   Op het BLOK en niet op de rij: dezelfde rij kan nog een andere banner naast zich hebben (op de home
   staan de Verhuur/Testen-tegels in dezelfde rij 0000001023), en die horen wél in de container. */
.cms-block-banner:has(.cms-banner-tile--advice) {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}
/* In de categoriekolom, de zijbalk en de blok-editor doet de RIJ-regel hierboven het werk - die heeft
   zijn eigen offset voor de asymmetrische container. Deze blok-regel zou daar nog eens 50vw bovenop
   schuiven, precies de "smalle strook die links het venster uit loopt" waar die rij-regels ooit voor
   geschreven zijn. Alleen de zijwaartse uitbraak terugdraaien, niet de marge erboven (regel ~290). */
.category-main .cms-block-banner:has(.cms-banner-tile--advice),
.category-sidebar-col .cms-block-banner:has(.cms-banner-tile--advice),
.admin-block-body .cms-block-banner:has(.cms-banner-tile--advice) {
  width: auto;
  margin-left: 0;
  margin-right: 0;
}

/* De tegel is <div class=tile><div class=cms-banner-tile-body><img> + <span class=label>...
   <a class=cta></span></div></div> - de band zit op de buitenste div, het 2-koloms grid op
   .cms-banner-tile-body (alleen de CTA erin is nog een echte link, zie hieronder). */
.cms-banner-tile--advice {
  max-width: none;
  margin: 0;
  padding: var(--space-6) calc(50% - 585px);
  background: #f2f4f7;
  box-shadow: none;
  /* De generieke .cms-banner-tile--advice (globals.css) zet ook text-align:center (bedoeld voor zijn
     eigen max-width:260px kaart-look) - mijn override zette max-width/margin al terug maar miste
     text-align, dus die bleef staan en centreerde titel/subtekst/knop i.p.v. links uitgelijnd zoals
     live. */
  text-align: left;
}
/* Gemeten op live: foto 234x234 (niet 300), direct tegen de tekstkolom aan (gap 0, niet
   var(--space-6)/40px - de tekstkolom eindigt exact waar de foto begint). */
.cms-banner-tile--advice > .cms-banner-tile-body {
  display: grid;
  grid-template-columns: 1fr minmax(0, 234px);
  align-items: center;
  gap: 0;
}
.cms-banner-tile--advice img { order: 2; border-radius: 50%; aspect-ratio: 1 / 1; object-fit: cover; }
/* Gemeten op live: grijs #46525b (niet navy), 20px, MontserratBold (font-weight zelf rapporteert 400
   omdat "MontserratBold" een apart lettertypebestand is, geen weight-variant). */
.cms-banner-tile--advice .cms-banner-tile-label {
  order: 1; margin: 0; color: #46525b;
  font-family: var(--font-heading); font-weight: 700; font-size: 20px;
}
.cms-banner-tile--advice .cms-banner-tile-sub { color: #46525b; font-size: 14px; margin-top: var(--space-2); }
/* banner_button als echte knop, zoals live ("Ik heb advies nodig"). Zelfde gecentreerde
   tekst+pijl-onder-elkaar-patroon als de nieuwsbrief-knop hierboven (.newsletter-signup-row button) -
   align-items:center, niet flex-start (die eerdere versie stond links uitgelijnd i.p.v. gecentreerd). */
/* .cms-page a:not(.btn):not(.btn-secondary) (3 classes + element, zie hierboven) wint van deze regel
   nu de CTA zelf een <a> is (was een kale <small> binnen de tegel-link, matchte dat selector niet) -
   dezelfde specificiteitsval als steeds. Extra .cms-page-gekwalificeerde variant met a. erbij om
   dezelfde 3 classes + element te halen (zie ook .category-sibling-pill hieronder voor hetzelfde
   patroon). */
.cms-banner-tile--advice .cms-banner-tile-cta,
.cms-page .cms-banner-tile--advice a.cms-banner-tile-cta {
  margin-top: var(--space-4); background: #4379bd; color: #fff;
  padding: var(--space-3) var(--space-4); font-size: 14px; font-weight: 700; opacity: 1;
  width: fit-content; border-radius: 2px; text-align: center;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-1);
}
/* Witte SVG-pijl (zelfde bestand als de nieuwsbrief-knop en de generieke knop-regel hierboven),
   i.p.v. een Unicode "→"-teken - anders oogde deze knop's pijltje net ietsje anders dan de rest. */
.cms-banner-tile--advice .cms-banner-tile-cta::after {
  content: ""; display: block; width: 12px; height: 12px;
  background: url("/bespoke/vangool/fa-arrow-right-white.svg") center/contain no-repeat;
}
/* Gevraagd door Wesley: alleen de knop mag klikbaar zijn, niet de hele tegel - CmsBannerGrid.tsx
   rendert titel/subtekst voor adviceBanner-tegels daarom als kale tekst in een gewone <div> (geen
   omhullende <a>/<Link> meer), en de CTA is nu zelf de enige link in de tegel. Eerdere versies
   (hele tegel als link) hadden hier een underline-op-hover-fix nodig omdat titel/subtekst per
   ongeluk meeliftten op de link se hover-underline - dat probleem bestaat nu niet meer, maar de
   knop zelf moet nog steeds geen onderstreping tonen (solide CTA, cursor+achtergrond volstaan). */
/* Gemeten op live: TWEE regels raken deze knop tegelijk bij hover - de generieke .btn-u:hover
   (achtergrond donkerder: rgb(40,82,141)) en een advice-banner-specifieke regel (tekst naar 75%
   wit-opacity, niet knalwit meer). Allebei toegepast voor hetzelfde "iets donkerder"-effect.
   Zelfde specificiteitsval als steeds: de RUST-regel heeft een .cms-page-gekwalificeerde tak
   (.cms-page .cms-banner-tile--advice a.cms-banner-tile-cta, 3 classes+element) die zwaarder weegt
   dan een kale :hover-override zonder die tak - dus hier dezelfde tak herhaald, anders wint de
   rust-kleur gewoon door tijdens hover (bevestigd: eerste versie deed precies dat, geen hover-effect
   zichtbaar in een echte screenshot). */
.cms-banner-tile--advice .cms-banner-tile-cta:hover,
.cms-page .cms-banner-tile--advice a.cms-banner-tile-cta:hover {
  background: #28528d; color: rgba(255, 255, 255, .75); text-decoration: none;
}
/* 860 -> 991 (2026-08-08, iPad audit): the outer full-bleed width:100vw treatment above already
   moved to 991 in lockstep with .category-page's sidebar breakpoint - this inner padding rule was
   left behind at the old 860, so 861-991px got an edge-to-edge band with NO internal padding
   (text flush against the viewport edge, reported 2026-08-08). */
/* Horizontal padding widened space-4 (16px) -> space-6 (32px), 2026-08-08: the full-bleed
   width:100vw trick above (`calc(50% - 50vw)`) has a known Windows scrollbar-width sub-pixel
   drift (documented elsewhere in this file for other full-bleed rows) that shifts this row ~24px
   left of the true viewport edge - with only 16px of padding that ate almost the whole gutter,
   leaving the text nearly flush against the edge (reported 2026-08-08 on a category page at
   918px). 32px comfortably absorbs that drift with a real gap left over. */
@media (max-width: 991px) { .cms-banner-tile--advice { grid-template-columns: 1fr; padding: var(--space-5) var(--space-6); } .cms-banner-tile--advice img { order: 1; max-width: 240px; } }

/* Categorie-tegels (Producten-overzicht, .category-tile/.category-grid uit CategoryTile.tsx):
   generiek is een "logo-tegel" (witte kaart, image contain op 88%, titel eronder) - live
   (vangool.nl/nl/webshop/product_list.aspx, .category-item) is een foto-tegel: vierkant, foto vult
   de hele tegel, een blauwe (#4379bd - dezelfde kleur als onze bestelknop) labelbalk overlapt de
   onderkant met witte 14px bold tekst. Gemeten via computed style + margin-top:-40px overlay-trick
   op live (image 262.5x262.5, label 40px hoog, 30px gap tussen tegels, geen kaartrand/schaduw). */
.category-tile {
  border: none; box-shadow: none; padding: 0; border-radius: 0;
  position: relative; overflow: hidden;
}
.category-tile:hover { box-shadow: none; border: none; transform: none; }
.category-tile-media { aspect-ratio: 1 / 1; border-radius: 0; background: none; }
.category-tile-media img { max-width: 100%; max-height: 100%; object-fit: cover; }
/* De twee KLEUREN stonden hier hardgecodeerd (#4379bd op #fff) en dat waren letterlijk Van Gools
   eigen uws_settings.cat_tiles_backgr_col / cat_tiles_font_col - precies het patroon "een
   hardgecodeerde kleur in bespoke is een kolom die niet is aangesloten". Sinds die kolommen via
   /api/cms/theme binnenkomen zijn ze weg; gemeten voor en na, beide #4379bd / #fff. De PLAATSING
   (als strook over de onderkant van de foto) blijft hier, want dat is layout en geen instelling. */
.category-tile-title {
  position: absolute; left: 0; right: 0; bottom: 0; margin: 0;
  font-family: var(--font-sans); font-weight: 700; font-size: 14px;
  padding: var(--space-2) var(--space-3); text-align: center;
}
.category-grid { gap: 30px; }

/* Categorieën-sidebar (.cat-sidebar, CategorySidebar.tsx - de linkerkolom op /catalog/category/* EN
   nu ook op /catalog zelf): live's ruwe DOM (.col-md-3 op takels-lieren.aspx, volledig gedumpt en
   nagekeken tegen alle geladen stylesheets) bevat GEEN icoon-element en GEEN CSS content/background-
   image op de link - de magenta chevron is dus een bewuste toevoeging, geen 1:1-overname van een
   bestaand live-icoon. Wel bevestigd via computed style: linktekst is MontserratSemibold (niet Open
   Sans), 14px, navy #002a65 - dat gebruiken we hier via var(--font-heading) (Montserrat next/font).
   Chevron als echte SVG i.p.v. een "›"-teken, zelfde opzet als fa-arrow-right-blue.svg elders in dit
   bestand voor consistentie. Kaart-look (rand/schaduw/padding) van de generieke .cat-sidebar
   weggehaald: live's sidebar is een kale lijst op de witte pagina-achtergrond, geen paneel. */
.cat-sidebar { background: none; border: none; box-shadow: none; padding: 0; }
.cat-sidebar h2 { font-family: var(--font-heading); font-weight: 700; font-size: 1rem; color: #002a65; }
/* Generieke .cat-sidebar > ul > li margin-bottom (--space-1) + a padding (--space-1 0) stapelden op
   tot ~12px extra lucht per rij bovenop de line-height - te ruim, teruggebracht naar een compacte
   lijst (geen live-meting, want live heeft geen vergelijkbare sidebar-look - zie hierboven). */
.cat-sidebar > ul > li { margin-bottom: 0; }
/* Op een categorie-subpagina wrapt BlockRenderer de sidebar in .cms-page (via de CATEGORIES-slot) -
   daar wint .cms-page a:not(.btn):not(.btn-secondary) (3 classes + element, globals.css) alsnog van
   een simpele .cat-sidebar a (1 class): dezelfde specificiteitsval als de breadcrumb hierboven, nu
   pas zichtbaar omdat de root-/catalog-pagina deze sidebar NIET in .cms-page wrapt (geen CMS-template
   match daar) en dus toevallig wel klopte. Beide selectors nodig: de kale voor de root-pagina (geen
   .cms-page-ouder daar), de opgetrokken (3 classes + element) voor de subpagina's - LET OP DOM-
   volgorde: .category-sidebar-col zit BUITEN .cms-page (BlockRenderer nest 'm erin), niet andersom -
   dat had de eerste versie van deze selector fout (matchte daardoor nooit). */
.cat-sidebar a, .category-sidebar-col .cms-page .cat-sidebar a {
  display: flex; align-items: center; gap: var(--space-2);
  font-family: var(--font-heading); font-weight: 700; font-size: 14px;
  color: #002a65; padding: 3px 0;
}
.cat-sidebar a::before {
  content: "";
  flex: none; width: 7px; height: 11px;
  background: url("/bespoke/vangool/fa-chevron-right-magenta.svg") center/contain no-repeat;
}

/* Categoriepagina-titel (CategoryPageClient.tsx: kale <h1>{categorienaam}</h1>, gewrapt in een
   generieke .cms-block-content - dus GEEN direct kind van .category-main, wel de enige andere h1
   daarbinnen naast .category-hero's geneste "Lees meer"-tagline-<h1>. Die laatste heeft al zijn
   eigen, specifiekere `.category-hero .read-more-body h1`-regel (2 classes) hieronder, die van deze
   bredere `.category-main h1` (1 class) blijft winnen op specificiteit - geen :not() nodig.
   Gemeten op live (.category-text h1, ook op mobiel): 40px MontserratBold, kleur #46525b (niet de
   generieke navy h1-kleur), margin 5px 0 20px - de generieke `h1 {font-size:25px}` (globals.css)
   liet deze titel duidelijk kleiner/minder dominant ogen dan live. */
.category-main h1 { font-size: 40px; font-weight: 700; color: #46525b; margin: 5px 0 20px; }
/* Live heeft TWEE verschillende titel-groottes naar categorietype: een overzichtspagina met
   subcategorie-tegels (.uc_categories_overview.advanced h1, bv. "Takels & Lieren") toont 20px, een
   bladpagina met producten (.category-text h1, bv. "Elektrische takels") toont 40px (de regel
   hierboven). CategoryPageClient.tsx rendert altijd dezelfde kale <h1>, maar rendert de
   subcategorie-tegels alleen in een `.category-section`-sibling wanneer detail.children.length>0 -
   dat onderscheid gebruiken als hetzelfde signaal. :has() geeft deze regel 1 class-punt meer dan de
   40px-regel hierboven (2 vs 1), dus wint hier altijd, ongeacht bronvolgorde. */
.category-main:has(.category-section) h1 { font-size: 20px; margin: 0 0 5px; }
/* Productdetailpagina's (ProductDetailClient.tsx) renderen ook binnen dezelfde .category-main-
   wrapper - de titel daar is een DERDE, eigen legacy-maat: live's .product-details-column h1 toont
   25px (margin 15px 0 25px), niet de 40px van de categorie-bladpagina hierboven. .detail-top bestaat
   alleen op een productpagina, dus :has(.detail-top) is hier het onderscheidende signaal (2
   class-punten, wint van de 40px-regel). */
.category-main:has(.detail-top) h1 { font-size: 25px; font-weight: 700; margin: 15px 0 25px; }
/* "Lees meer"-knop (.category-hero-toggle, ReadMore.tsx "hero"-variant): generiek is dit een kaal
   <button>, dat de globale navy-knop-stijl (bedoeld voor echte CTA's) erft. Gemeten op live
   (.read-more): wit met grijze rand (1px #ddd), lichtblauwe tekst #38a4dd, gecentreerd (niet links
   uitgelijnd zoals eerder aangenomen op basis van een screenshot - bounding-rect-meting bevestigt
   centrering: gelijke marge links/rechts binnen de kaart). Live's horizontale lijn: .cat-text zelf
   heeft border-bottom:1px #ccc, en .cat-buttons (de knop) is position:absolute erover heen
   geschoven (gemeten: knop-top ligt 20px BOVEN de tekst-onderrand) - de knop's eigen witte
   achtergrond "knipt" de lijn optisch door. Zelfde effect hier met negative margin-top i.p.v.
   absolute positionering (geen aparte DOM-laag nodig, .read-more-body en .category-hero-toggle
   zijn al gewone flow-siblings binnen .category-hero). */
.category-hero .read-more-body { border-bottom: 1px solid #ccc; padding-bottom: var(--space-3); }
.category-hero-toggle {
  display: block; position: relative; z-index: 1;
  margin: -12px auto 0; padding: 0 10px;
  background: #fff; border: 1px solid #ddd; color: #38a4dd;
  font-family: var(--font-sans); font-size: 14px;
}
/* De generieke button:hover:where(:not(:disabled)) (globals.css) zet ook filter:brightness(0.85) -
   mijn background-override cancelde alleen de kleur zelf, niet die filter, dus de hele knop
   (incl. de lichtblauwe tekst/pijl) doofde alsnog uit tot een grauw donker geheel.
   CORRECTIE: Wesley wil wél hover-feedback, alleen geen donkere - tekst/pijl naar een lichtere
   tint (#60ccff, zelfde patroon als "Lees meer"/"Meer nieuws" elders op de site). */
.category-hero-toggle:hover { background: #fff; filter: none; color: #60ccff; }

/* "Lees meer"-knop op de productdetailpagina (.read-more-toggle-inline, ReadMore.tsx "inline"-
   variant - live's .collapse-button op de Omschrijving-tab): plat, links uitgelijnd, GEEN kader/
   achtergrond, navy tekst+pijl 13px bold Open Sans - gemeten op live (.collapse-button span/i,
   .cmp-elastic-product-details.aspx). Live heeft hier geen apart hover-effect (geen :hover-regel
   voor .collapse-button gevonden), dus geen kleurverandering bij hover - wel de generieke
   button:hover filter:brightness(0.85) expliciet weggehaald, anders doofde de navy tekst toch uit. */
.read-more-toggle-inline { color: #002a65; font-family: var(--font-sans); font-weight: 700; font-size: 13px; justify-content: flex-start; }
.read-more-toggle-inline:hover { background: none; filter: none; color: #002a65; }

/* Documenten-tab pillen (.product-documents, ProductDetailClient.tsx) - gemeten op live
   (.cmp-product-documents): witte pil, lichtgrijze rand #eee, navy link-kleur op de <a> zelf, maar
   icoon+tekst er zelf lichtblauw #38a4dd overheen (live's eigen `!important`-regel) - geen
   hover-kleurverandering (geen :hover-regel gevonden voor .text-link binnen deze context).
   .cms-page-uitsluiting: de productdetailpagina rendert deze tab binnen `.cms-page` (het generieke
   category-page-layout), en die pagina's eigen `.cms-page a:not(.btn):not(.btn-secondary)`-regel
   (1 klasse + 2 :not()-klassen + 1 element = specificity 0,3,1) is zwaarder dan een simpele
   `.cms-page .product-documents a` (2 klassen + 1 element = 0,2,1, nog steeds te licht) - vandaar
   hier dezelfde :not()-vorm herhaald om minstens gelijk te wegen (zelfde patroon als eerder bij de
   advies-banner-CTA, zie skill "CSS specificity traps"). */
.product-documents a, .cms-page .product-documents a:not(.btn):not(.btn-secondary) { color: #002a65; border-color: #eee; font-family: var(--font-sans); font-size: 13px; }
.product-documents a:hover, .cms-page .product-documents a:not(.btn):not(.btn-secondary):hover { color: #002a65; background: none; filter: none; }

/* "Vergelijkbare producten"/"Ook bestellen?"-koppen (.related-section h2, ProductCarousel.tsx) -
   gemeten op live (.cmp-product-carousel h2): 20px MontserratBold #46525b, niet de generieke
   navy 24px van het gedeelde h2-lettertype. font-weight:700 om hetzelfde vette effect visueel na
   te bootsen (zelfde reden als eerder bij .btn-order-main: live's font-weight meet als 400 omdat
   het al een los Bold-lettertypebestand is, --font-heading is één enkel gewicht). Navigatiepijl:
   gemeten op live (.nav-control i): #4379bd. */
.related-section h2 { color: #46525b; font-size: 20px; font-weight: 700; }
.product-carousel-nav { color: #4379bd; }
.product-document-icon, .product-documents a span { color: #38a4dd; }

/* Breadcrumb (CatalogPageClient.tsx + CategoryPageClient.tsx, .breadcrumb-*-classes): gemeten op live
   (product_list.aspx, ul.breadcrumb-v5): "Home" medium blauw #4379bd, elke volgende stap navy #002a65,
   beide MontserratSemiBold 700 13px, gescheiden door een "/" (::before op elke stap, geen los
   scheider-element) - i.p.v. de generieke ›-scheider. Generiek genoeg voor N stappen (root-catalogus
   heeft er 1, een diepe subcategorie meerdere) - .breadcrumb-step vervangt zowel de oude losse
   .breadcrumb-current als een aparte regel per stap. */
/* .cms-page a:not(.btn):not(.btn-secondary) (3 classes + element, zie globals.css) telt zwaarder dan
   een kale .breadcrumb-home (1 class) - de bekende specificiteitsval, hier voor de 3e keer. Selector
   optrekken naar dezelfde vorm (3 classes + element), bronvolgorde (bespoke laadt na globals.css)
   beslist dan in ons voordeel. CmsBreadcrumb (BlockRenderer.tsx, /pagina/* content pages) reuses
   these same classes but isn't always a .cms-page descendant - CmsPageView renders it as a SIBLING
   above <BlockRenderer>, outside .cms-page entirely, so the specificity fight above doesn't apply
   there and a plain `.breadcrumb a.breadcrumb-home` is enough - kept as a separate selector rather
   than folded into one, since the two contexts need different specificity for different reasons. */
.cms-page .breadcrumb a.breadcrumb-home, .breadcrumb a.breadcrumb-home { color: #4379bd; font-family: var(--font-heading); font-weight: 700; font-size: 13px; }
.breadcrumb-sep { display: none; }
.breadcrumb-step {
  color: #002a65; font-family: var(--font-heading); font-weight: 700; font-size: 13px;
}
.breadcrumb-step::before { content: "/"; margin-right: var(--space-1); color: #002a65; }
/* Root-catalogus-pagina: generieke fallback-tekst is "Catalogus", live noemt deze stap "Webshop" -
   tekstvervanging via font-size:0 + ::before content, want de fallback-tekst wordt door meerdere
   tenants gedeeld en een per-tenant i18n-laag bestaat nog niet - dit is de kleinste scoped ingreep
   die andere tenants niet raakt. */
.breadcrumb-root { font-size: 0; }
.breadcrumb-root::before { content: "/ Webshop"; font-size: 13px; }

/* Sidebar-categorieboom: het uitgeklapte item (heeft een geneste <ul> erna, ongeacht of het ook het
   "current"-item is) krijgt dezelfde chevron omlaag i.p.v. rechts - :has(+ ul) is state-onafhankelijk,
   werkt dus ook wanneer een dieper kind (niet de root zelf) de "current" pagina is. */
.cat-sidebar > ul > li > a:has(+ ul)::before { transform: rotate(90deg); }

/* header_link_block: de vier categorie-snelkoppelingen direct onder de hoofdnav. Live is een DUNNE
   WITTE strip met kleine blauwe tekst en "/"-scheidingstekens (geen donkerblauwe band). */
.cms-links--header-strip { background: #fff; border-bottom: 1px solid #d0d3d5; justify-content: flex-start; align-items: center; min-height: 40px; padding: 0 calc(50% - 585px); }
.cms-links--header-strip li { flex: 0 0 auto; }
.cms-links--header-strip li::before { content: "/"; color: #9aa3ad; margin: 0 var(--space-2); font-weight: 400; }
/* gemeten op live: 12px MontserratBold in navy #002a65 (niet lichtblauw).
   Selector bevat .cms-page omdat de generieke link-kleurregel hierboven (.cms-page a:not(.btn)...)
   anders specifieker is en het lichtblauw zou blijven overschrijven. */
.cms-page .cms-links.cms-links--header-strip a { display: inline-block; color: #002a65; font-family: var(--font-heading); font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .02em; padding: 0; }
/* Wesley (echte muis-hover): blauw blijft #38a4dd, maar zonder underline - de generieke
   a:hover{text-decoration:underline} (globals.css) moet hier expliciet geannuleerd worden. */
.cms-page .cms-links.cms-links--header-strip a:hover { color: #38a4dd; text-decoration: none; }
.cms-links--header-strip a:hover { color: #002a65; background: none; text-decoration: none; }
/* geen pijl op deze strip - live heeft alleen de "/"-scheiders */
.cms-links--header-strip a::after { content: none; }

/* Logo staat live direct op de witte header-rij, niet in een wit blok op donkerblauw. De witte band
   zelf stond hier met de hand terwijl ucm_settings.centerbar_backgr_col al #FFFFFF is; sinds
   2026-08-15 leest .shell-header-main die kolom via --color-header-bg, dus de regel kon weg. */
.shell-header-main .shell-logo, .shell-header-main a:has(img) { background: none; padding: 0; }

/* VanGool-header (components/bespoke/vangool/Header.tsx): zoekveld in de topbalk, hoofdnav NAAST het
   logo op de witte rij - zoals live. De generieke shell zet zoeken op de logo-rij en nav eronder. */
/* Gemeten op live @1400px: topbalk 45px hoog, logo-rij 96px, logo 233x48, zoekveld 175x35 (niet
   uitgerekt), topbalk-links 13px MontserratSemibold #d4d7df. */
.shell-header--vangool .shell-usp { padding: 0; }
.shell-header--vangool .shell-usp-inner { display: flex; align-items: center; gap: var(--space-5); min-height: 45px; padding-top: 0; padding-bottom: 0; }
/* Nav-utility (Downloads/Nieuws/FAQ) en vg-utility-links (Webshop/Registratie) horen visueel bij
   elkaar - kleine gap, zelfde afstand als binnen één lijst, niet de grote gap tussen groepen. */
/* shell-usp-inner's generieke justify-content:space-between duwt deze groep en shell-usp-right naar
   de twee uiteinden - live plakt de linkjes juist direct tegen de NL-switch aan, met de lege ruimte
   links. margin-left:auto absorbeert die ruimte vóór deze groep i.p.v. die te verdelen. */
.vg-utility-group { display: flex; align-items: center; gap: 0; margin-left: auto; }
/* De mobiele topbalk staat NIET hier maar bij de andere mobiele headerregels, na het
   @media (max-width: 1099px)-blok - die zet flex-wrap expliciet op nowrap en zou een blok hier
   verslaan op bronvolgorde. Zoek op "Topbalk ingelogd op een telefoon". */
.shell-header--vangool .shell-header-main { min-height: 96px; }
.shell-header--vangool .shell-header-main img { max-height: 48px; width: auto; }
/* De "grijzige achtergrond" onder de categorie-strip is geen background-color op de strip zelf (drie
   keer nagekeken, telkens transparant) - het is een box-shadow op de HELE <header> (live: .header-v5
   { box-shadow: 0 18px 8px rgba(0,0,0,.16) }), die over de content eronder valt. Op VanGool staat de
   categorie-strip direct na de header, dus de schaduw landt daar precies overheen. */
/* `sticky_header` in ucm_settings (bit, =1 voor deze klant) is een ECHTE website-instelling, geen
   VanGool-eigenaardigheid (gemeten: ook bij Deponti's aludep_full =1) - dus de aan/uit-knop komt uit
   de generieke --header-position var (lib/cms/theme.ts, app/globals.css), niet uit een lokale hack.
   Wat WEL bespoke is: live's exacte multi-tier opstelling (header + categorie-strip beide "vast",
   strip er precies onder) en de kleur/schaduw-styling daarvan. */
.shell-header--vangool { position: var(--header-position, relative); top: 0; z-index: 999; box-shadow: 0 18px 8px rgba(0, 0, 0, 0.16); }
/* Live pint topbar+nav+categorie-strip samen vast (`.uc_header_v6.sticky-desktop { position:fixed }`).
   Met position:sticky (i.p.v. fixed) hoeft de weggehaalde flow-hoogte niet met een aparte padding-top
   gecompenseerd te worden: een sticky element houdt gewoon zijn eigen plek in de flow tot je voorbij
   scrollt. Elke laag "plakt" op zijn eigen top-offset (141px = hoogte topbar+nav) - hetzelfde patroon
   als een sticky tabelheader + sticky subheader. Het strip-blok bestaat sowieso alleen op de homepage
   (header_link_block), dus dit scoped zichzelf al - geen extra :has(body ...) nodig. */
.cms-block-link:has(.cms-links--header-strip) { position: var(--header-position, static); top: 141px; z-index: 998; }
/* Live's header-strip blok zit flush tegen de nav (0px gat) - de generieke main-padding (24px) gaf
   hier een ongewenste kloof. */
body:has(.cms-links--header-strip) main { padding-top: 0; }
/* De generieke .cms-banner-grid margin-top (12px) duwde de eerste tegel-rij los van de strip - live
   staat die rij daar wél flush tegenaan (met een zachte schaduw-overgang, zie de box-shadow hierboven). */
.cms-row:has(.cms-links--header-strip) .cms-banner-grid { margin-top: 0; }
/* margin-top:0 op de grid zelf loste de zichtbare 16px lucht niet op - die kwam niet van de grid's
   eigen margin, maar van de generieke .cms-row { gap: var(--space-4) } flex-gap TUSSEN de header-strip
   en de banner-grid (beide zijn losse child-blocks van dezelfde flex-column .cms-row). Gemeten op
   live: de tegel-rij staat direct tegen de strip aan, dus de gap van de OUDER moet ook naar 0. */
.cms-row:has(.cms-links--header-strip) { gap: 0; }
/* Utility-nav in de topbalk (Downloads/Nieuws/FAQ): witte 12px-links, geen band, geen mobiel-toggle
   en geen "/"-scheiders - dat is de hoofdnav-look, niet deze. */
.shell-nav--utility { background: none; border: none; flex: 0 0 auto; }
.shell-nav--utility .shell-nav-toggle { display: none; }
/* Op mobiel (≤1099px, zie globals.css se eigen hamburger-drempel sinds de 2026-08-08 iPad-audit)
   heeft deze nav geen eigen hamburger (regel hierboven) en zou zijn lijst dus nergens bereikbaar
   zijn - Header.tsx geeft de hoofdnav daarom ongefilterd door zodat Downloads/Nieuws/FAQ daar
   meedoen in het ENE hamburgermenu (zoals legacy). Hier dus volledig verbergen om geen dode
   restruimte over te houden. */
@media (max-width: 1099px) {
  .shell-nav--utility { display: none; }
}
/* .shell-nav-list (generiek) heeft padding:0 var(--space-4) (16px links/rechts) bedoeld voor de
   HOOFDnav-rij tegen de paginacontainer - deze utility-nav (Downloads/Nieuws/FAQ) hergebruikt
   dezelfde class en erfde die padding mee, wat "FAQ" 16px extra ruimte gaf t.o.v. "Webshop" ernaast
   (welke geen padding heeft) - vandaar de zichtbaar ongelijke tussenruimte. */
.shell-nav--utility .shell-nav-list { gap: 0; padding: 0; max-width: none; margin: 0; }
.shell-nav--utility .shell-nav-list > li::after { content: none; }
/* .shell-usp li::before zet een ✓ op ELKE li in de topbalk (bedoeld voor de USP-strip) - die mag niet
   voor deze menu-items komen. */
.shell-nav--utility .shell-nav-list > li::before { content: none; }
.shell-nav--utility .shell-nav-list > li { padding-left: 0; }
/* Hover, gemeten op live (.uc_header_v6 .account-handler li:hover a): alleen een donkere
   achtergrond-highlight, tekstkleur blijft ONGEWIJZIGD (legacy forceert dat zelfs met !important). */
.shell-nav--utility .shell-nav-list a { display: inline-flex; align-items: center; color: #d4d7df; font-family: var(--font-heading); font-weight: 600; font-size: 13px; padding: var(--space-2); }
.shell-nav--utility .shell-nav-list a:hover { color: #d4d7df; }
/* De highlight hoort op de RIJ (.mega-menu-row) en niet op de link. Reden: globals.css zet daar op
   hover `background: #fff` - bedoeld voor de lichte hoofdnav, want de rij is de gedeelde ouder van de
   link en de chevron (zie de opmerking daar). Op deze DONKERE balk is dat wit, en het zat er dus
   altijd al: de rij sprong per direct op wit terwijl de link zijn eigen navy in 150ms invaagde
   (`transition: background .15s` uit de generieke .shell-nav-list a). Gemeten tijdens de hover:
   0ms transparant -> 234ms rij WIT met de link nog op alpha 0, en pas op ~400ms navy over de volle
   breedte. Dat is de witte flits die Wesley zag, en waarom hij er nooit een screenshot van kreeg.
   Dus: de rij krijgt de navy (die overschrijft het wit) en de link zelf houdt geen eigen achtergrond
   meer - twee lagen met verschillende timing is precies het probleem. De transition gaat mee naar de
   rij, zodat het invagen blijft zoals het bedoeld was. */
.shell-nav--utility .mega-menu-item:hover .mega-menu-row {
  background: #00023d;
  transition: background .15s ease;
}
/* width:175px paste alleen bij een kaal zoekveld (search_type 1/2) - zodra de Webshop/Website-
   toggle verschijnt (search_type 3) heeft de rij meer ruimte nodig, vandaar min-width i.p.v. een
   vaste breedte die de radio's zou wegknellen/laten overlappen. */
/* De generieke .shell-search (globals.css) heeft zelf al een witte achtergrond + radius + overflow:
   hidden, maar zonder vaste hoogte vulde dat de volle 47px topbar ("het witte vlak valt eroverheen").
   Hier: wel wit/afgerond houden (Webshop/Website horen IN dezelfde witte balk te staan, niet los op
   navy - anders onleesbaar), maar met een vaste hoogte zodat het een ingebed vak blijft i.p.v. een
   balk die de hele topbar-hoogte vult. */
.shell-header--vangool .shell-usp .shell-search {
  flex: 0 0 auto; min-width: 175px; height: 35px; align-items: center;
  background: #fff; border-radius: var(--radius); overflow: hidden;
}
/* Uitzondering zodra de suggestielijst open staat: die mag niet afgeknipt worden. De regel hierboven
   zet overflow: hidden (voor de ronde hoeken van dat ingebedde vak) plus een vaste hoogte van 35px, en
   samen knippen die het uitklaplijstje weg. Gemeten in de browser: de lijst stond met acht regels in de
   DOM, maar zijn rechthoek was 359x47 in plaats van 359x380 - dus hij was er wel en je zag hem niet.
   De generieke uitzondering in globals.css (.shell-search:has(.shell-search-suggest)) verliest hier op
   specificiteit: die weegt 0,2,0 en de regel hierboven 0,3,0. Vandaar dezelfde uitzondering, hier één
   klasse zwaarder. */
.shell-header--vangool .shell-usp .shell-search:has(.shell-search-suggest) { overflow: visible; }
/* input[type=search] (niet gewoon "input"!) - anders matcht dit ook de radiobuttons in
   .shell-search-scope, die daardoor elk 175px breed werden gerekt i.p.v. ~13px. */
/* Gemeten op live: het zoekveld gebruikt MontserratSemibold (14px), niet de generieke Open Sans
   body-stack - anders viel het zichtbaar uit de toon met de rest van de (Montserrat) header. */
.shell-header--vangool .shell-usp .shell-search input[type="search"] { background: none; border: none; height: 35px; width: 175px; padding: 0 var(--space-3); font-size: 14px; font-family: var(--font-heading); }
/* Gevraagd door Wesley (afwijking van live's navy zoek-knop): wit, zelfde achtergrond als de rest
   van de zoekbalk - navy icoon i.p.v. wit, anders onzichtbaar op wit. */
/* button[type="submit"] en niet elke button: sinds er een suggestielijst ONDER het zoekveld hangt,
   staan daar ook knoppen in (aantal +/- en "Bestellen"). Die werden door dit blok alle drie in een
   vakje van 35x35 geperst - gemeten: de bestelknop was 35px breed en het woord viel er buiten. Deze
   regel is geschreven toen de zoekknop de enige knop in de balk was; die is de submit-knop. */
.shell-header--vangool .shell-usp .shell-search button[type="submit"] {
  height: 35px; width: 35px; padding: 0; background: #fff; color: #002a65; flex: none;
  display: flex; align-items: center; justify-content: center;
}
/* Zoekbereik (Webshop/Website) als segmented control i.p.v. twee losse radio+label-paren - die
   waren op mobiel te klein om nog te kunnen raken en lazen niet als "kies één van deze twee".
   :has() (al eerder gebruikt in dit bestand, zie .mega-menu-item hierboven) stuurt de actieve
   look aan zonder JS - de radio blijft functioneel/focusbaar, alleen visueel verborgen. */
.shell-header--vangool .shell-usp .shell-search-scope {
  display: flex; gap: 2px; background: #eef1f6; border-radius: 999px; padding: 2px;
  height: 31px; font-size: 12px;
}
.shell-header--vangool .shell-usp .shell-search-scope label {
  display: flex; align-items: center; justify-content: center; flex: 1 1 auto;
  padding: 0 var(--space-3); border-radius: 999px; color: #46525b; font-weight: 700;
  white-space: nowrap; cursor: pointer; transition: background .15s ease, color .15s ease;
}
.shell-header--vangool .shell-usp .shell-search-scope input[type="radio"] {
  position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none;
}
.shell-header--vangool .shell-usp .shell-search-scope label[data-active] { background: #002a65; color: #fff; }
.shell-header--vangool .shell-usp .shell-search-scope label:has(input:focus-visible) { outline: 2px solid #002a65; outline-offset: 1px; }

/* Webshop/Registratie: zelfde look als de utility-nav-links ernaast, geen apart mechanisme nodig.
   Zelfde valkuil als de utility-nav hierboven: .shell-usp li::before zet een ✓ op ELKE li in de
   topbalk (bedoeld voor de USP-strip) - moet ook hier onderdrukt worden. */
/* .shell-usp ul (class+element, globals.css) is specifieker dan een kale class-selector en zou
   gap:0 anders overschrijven met var(--space-5) - vandaar .shell-usp ervoor. */
.shell-usp .vg-utility-links { display: flex; gap: 0; list-style: none; margin: 0; padding: 0; }
.vg-utility-links li::before { content: none; }
.vg-utility-links li { padding-left: 0; }
.vg-utility-links a { display: inline-flex; align-items: center; color: #d4d7df; font-family: var(--font-heading); font-weight: 600; font-size: 13px; padding: var(--space-2); }
.vg-utility-links a:hover { color: #d4d7df; background-color: #00023d; }
/* Logged in: AccountMenu ("Mijn account"/"Uitloggen") renders straight into this same list in place
   of the anonymous Webshop/Registratie links (see Header.tsx) - .shell-usp-right button.shell-logout
   (globals.css) no longer applies once it's moved out of that container, so it needs its own match
   for the link style right above instead of falling back to an unstyled default button. */
.vg-utility-links button.shell-logout { display: inline-flex; align-items: center; background: none; border: none; margin: 0; cursor: pointer; color: #d4d7df; font-family: var(--font-heading); font-weight: 600; font-size: 13px; padding: var(--space-2); }
.vg-utility-links button.shell-logout:hover { color: #d4d7df; background-color: #00023d; }
/* Webshop/Registratie (anoniem) op mobiel uit de topbalk - ze komen terug onderaan de ene
   hamburger (extraLinks op de hoofdnav, zie Header.tsx), zoals legacy. Ingelogd blijft
   "Mijn account"/"Uitloggen" hier gewoon staan - dat heeft geen ander bereikbaar plekje. */
@media (max-width: 1099px) {
  /* .shell-usp .vg-utility-links (hierboven) is specifieker (2 classes) dan een kale
     .vg-utility-links--guest zou zijn - vandaar dezelfde opbouw hier, anders verliest deze regel
     ondanks de latere media query. */
  .shell-usp .vg-utility-links--guest { display: none; }
}

/* Taalknop: pil met dunne rand, zoals live ("NL ▾" in een kader) i.p.v. de generieke platte tekst. */
.shell-header--vangool .shell-lang-trigger {
  border: 1px solid #1a4075; border-radius: 2px; background: none;
  color: #d4d7df; font-size: 13px; height: 35px; padding: 0 var(--space-3);
}

/* Cart/offerte-icoon: de generieke kleur (globals.css) is wit, voor een donkere headerbalk (Deponti).
   VanGool's shell-header-main is wit (zie hierboven), dus wit-op-wit was volledig onzichtbaar. */
.shell-header--vangool .shell-header-actions a,
.shell-header--vangool .shell-header-actions .shell-icon-link { color: #002a65; }
/* fa-shopping-cart is op live rood (#ff1f1f gemeten) - eigen accent, niet navy.
   Selector moet minstens zo specifiek zijn als de navy-regel hierboven (die telt 3 classes via
   .shell-header-actions .shell-icon-link) - anders wint die alsnog ondanks latere volgorde. */
/* Eerder gemeten als rood (fa-shopping-cart #ff1f1f), maar door de gebruiker herbevestigd tegen een
   verse screenshot van live: het icoon is navy, zelfde kleur als de rest van de nav-iconen. */
.shell-header--vangool .shell-header-actions a.shell-cart { color: #002a65; }
/* Live toont het aantal als gewone grijze tekst NAAST het icoon (span.cart_total_quantity), geen
   rode cirkel overlappend op het icoon - dus hier de generieke absolute-positioned badge
   terugbrengen naar inline tekst, in dezelfde grijstint als de body-tekst. */
.shell-header--vangool .shell-cart { gap: var(--space-1); }
.shell-header--vangool .shell-cart-badge {
  position: static; background: none; color: #46525b; min-width: 0; height: auto; padding: 0;
  font-family: var(--font-heading); font-weight: 700; font-size: 14px;
}
.shell-header--vangool .shell-header-main {
  display: flex; align-items: center; gap: var(--space-5);
  max-width: var(--container-max); margin: 0 auto; padding: var(--space-3) var(--space-4);
}
.shell-header--vangool .shell-header-main .shell-nav { flex: 1 1 auto; background: none; border: none; }
.shell-header--vangool .shell-header-main .shell-nav-list { justify-content: flex-end; }
.shell-header--vangool .shell-header-actions { flex: 0 0 auto; }
/* Deze nav krijgt sinds kort geen exclude meer (nodig zodat Downloads/Nieuws/FAQ op mobiel in het
   ene hamburgermenu meedoen, zie Header.tsx) - op desktop staan die 3 al in de topbalk-utility-nav
   erboven, dus hier de dubbele tabs verbergen. */
@media (min-width: 1100px) {
  .shell-header--vangool .shell-header-main .shell-nav-list > li:has(a[href$="/pagina/downloads"]),
  .shell-header--vangool .shell-header-main .shell-nav-list > li:has(a[href$="/nieuws"]),
  .shell-header--vangool .shell-header-main .shell-nav-list > li:has(a[href$="/pagina/faq"]) {
    display: none;
  }
  /* Webshop/Registratie staan op desktop al zichtbaar in de topbalk (.vg-utility-links) - de
     extraLinks-rij op de hoofdnav (Header.tsx) is puur voor de mobiele hamburger. */
  .shell-header--vangool .shell-header-main .shell-nav-extra { display: none; }
}
@media (max-width: 860px) {
  .shell-header--vangool .shell-usp-inner { flex-wrap: wrap; }
  .shell-header--vangool .shell-header-main { flex-wrap: wrap; }
  /* Zoekveld nam op smalle schermen zijn min-width (175px) + de Webshop/Website-toggle mee, samen
     breder dan de beschikbare topbar-ruimte na het wrappen van de utility-links erboven - dat gaf
     overlappende/uitlopende styling. Eigen volle-breedte rij, met de toggle er dan weer los onder. */
  .shell-header--vangool .shell-usp .shell-search { flex: 1 1 100%; min-width: 0; }
  .shell-header--vangool .shell-usp .shell-search input[type="search"] { width: 100%; }
  .shell-header--vangool .shell-usp .shell-search-scope { flex-wrap: wrap; }
}
@media (max-width: 1099px) {
  /* Compactere topbalk: Webshop/Registratie staan hier niet meer tussen (zie hierboven), dus past
     NL-vlag + zoekbalk weer op één regel - geen geforceerde 2e regel/hoogte meer nodig. */
  .shell-header--vangool .shell-usp-inner { flex-wrap: nowrap; gap: var(--space-2); padding: var(--space-2) var(--space-3); min-height: 0; }
  /* Gemeld: het zoekveld viel links buiten de balk. Oorzaak: .shell-usp-right (generiek, geen
     breedtebeperking) nam als flex-item van shell-usp-inner zijn automatische minimumbreedte van
     de VOLLEDIGE inhoud van zijn kinderen (NL-knop + zoekbalk-op-natuurlijke-breedte) - het
     min-width:0 op .shell-search zelf (regel hieronder) helpt dan niet, want de OUDER-schakel in
     de flex-keten (.shell-usp-right) kreeg zelf nooit de vrijheid om onder die inhoud te krimpen.
     Elke laag in een geneste flex-keten moet min-width:0 krijgen, niet alleen het uiteindelijke
     element - vandaar hier ook. */
  .shell-header--vangool .shell-usp-right { min-width: 0; flex: 1 1 auto; }
  .shell-header--vangool .shell-usp .shell-search { min-width: 0; flex: 1 1 auto; }
  .shell-header--vangool .shell-usp .shell-search input[type="search"] { width: auto; flex: 1 1 auto; min-width: 0; }
  .shell-header--vangool .shell-usp .shell-search-scope { flex: 0 0 auto; flex-wrap: nowrap; }
  .shell-header--vangool .shell-lang-trigger { padding: 0 var(--space-2); font-size: 12px; flex: 0 0 auto; }
  /* Gevraagd: cart links van de hamburger, hamburger uiterst rechts - zelfde 3 flex-children als
     desktop (logo/nav/actions), alleen de volgorde staat hier om (desktop heeft de nav juist
     MIDDEN tussen logo en cart/offerte nodig). gap:0 + margin-left:auto op de logo (i.p.v. de
     generieke space-between) houdt cart en hamburger tegen elkaar aan i.p.v. gelijk verdeeld over
     de resterende ruimte - dat gaf zichtbaar een groot gat tussen cart en hamburger. */
  /* .shell-header--vangool .shell-header-main (verderop, buiten een media query) zet zelf al
     gap:var(--space-5) + justify-content:space-between met dezelfde 2-classes-specificiteit - een
     kale .shell-header-main hieronder zou die dus NOOIT verslaan, ondanks latere bron-volgorde en
     een matchende media query (specificiteit gaat voor bronvolgorde). Vandaar hier ook
     .shell-header--vangool ervoor. */
  /* flex-wrap:nowrap overrides the generic .shell-header-main{flex-wrap:wrap} (globals.css) - logo
     + cart + hamburger fit within a couple px of the available width, so close that the hamburger
     was falling to its own row on real phone widths (Wesley: moet op dezelfde regel als winkelwagen)
     even though the generic wrap rule was only ever meant for a plain 2-item logo/toggle row. */
  .shell-header--vangool .shell-header-main { gap: 0; justify-content: flex-start; flex-wrap: nowrap; }
  .shell-header--vangool .shell-header-main .shell-logo { order: 1; margin-right: auto; }
  .shell-header--vangool .shell-header-main .shell-header-actions { order: 2; margin-right: var(--space-2); }
  /* flex:1 1 auto (verderop, ongeconditioneerd) laat de nav op desktop de middenruimte tussen logo
     en cart vullen (voor de horizontale tab-balk) - op mobiel is de nav alleen nog een hamburger-
     knop, dus die groei-regel hier uitzetten. Zonder dit "won" de nav zelf alle resterende ruimte
     ondanks margin-right:auto op de logo hierboven - de KNOP bleef even ver rechts staan, maar dat
     was gewoon zijn eigen (te brede) doos die door text-align:right rechts uitkwam, geen echte
     gap-verkleining. */
  .shell-header--vangool .shell-header-main .shell-nav { order: 3; flex: 0 0 auto; }
  /* Logo iets kleiner op telefoon (Wesley) - de basisregel (buiten media query) zet 48px, bedoeld
     voor desktop; op mobiel is er minder breedte te verdelen tussen logo/cart/hamburger. */
  .shell-header--vangool .shell-header-main img { max-height: 36px; }
  /* Wesley (afwijking van live, die daar een los ongekaderd fa-angle-down-icoontje toont): een
     ronde grijze pil-knop rond het pijltje i.p.v. de generieke 48x44-box+scheidingslijn
     (globals.css, bedoeld voor Deponti). */
  .shell-header--vangool .mega-menu-chevron {
    width: 32px; height: 32px; border-left: none; padding: 0; margin: 0 0 0 var(--space-3);
    border-radius: 50%; background: var(--color-muted); color: #941680;
    /* .mega-menu-row's align-items:stretch (desktop, unconditional) has no effect on an item with
       an explicit height like this 32px circle - it degrades to flex-start (top-aligned) instead,
       leaving the circle stuck at the top of the now-taller 10px/25px-padded row. align-self:center
       overrides just this item back to vertically centered against the row's own text baseline. */
    align-self: center;
  }
  .shell-header--vangool .mega-menu-chevron[aria-expanded="true"] { background: var(--color-muted); color: #941680; }
  /* Live (.dropdown-button.fa-angle-down): color:#941680 !important, font-size:15px - dezelfde
     magenta al gebruikt voor prijzen/"prijs op aanvraag" (--vg-price), en dunner dan de generieke
     chevron-icoon-stijl (strokeWidth 2, bedoeld als duidelijk klikbaar icoon) - stroke-width hier
     verdunnen benadert dat zonder de gedeelde MegaMenu.tsx-SVG (alle tenants) aan te passen. */
  .shell-header--vangool .mega-menu-chevron svg { width: 15px; height: 15px; }
  .shell-header--vangool .mega-menu-chevron svg path { stroke-width: 3; }
  /* Gemeten op live (mobiel uitgeklapt hamburgermenu): hoofditems 20px MontserratBold, maar
     Downloads/Nieuws/FAQ (dezelfde 3 die op desktop al in de topbalk staan, zie UTILITY_SLUGS in
     Header.tsx) EN Webshop/Registratie (extraLinks) zijn daar zichtbaar kleiner/lichter: 16px
     MontserratSemiBold - live's eigen "topbar-links"-klasse. Geen datasignaal om ze te
     onderscheiden binnen de hoofdlijst (zelfde reden als de UTILITY_SLUGS-comment elders), dus
     href-matching op dezelfde 3 slugs; Webshop/Registratie zijn al apart via .shell-nav-extra. */
  /* Gemeten op live (.navbar-nav>li>a): padding 10px 25px - VanGool's eigen `.shell-nav-list a
     {padding:0}` (hierboven, desktop) liet elk item hier zonder eigen ademruimte, alleen de
     lijst-brede 16px (globals.css) als linker-inset. */
  .shell-header--vangool .mega-menu-row a { font-size: 20px; font-weight: 700; padding: 10px 25px; }
  .shell-header--vangool .mega-menu-row a[href*="/downloads"],
  .shell-header--vangool .mega-menu-row a[href*="/nieuws"],
  .shell-header--vangool .mega-menu-row a[href*="/faq"],
  .shell-header--vangool .shell-nav-extra a {
    font-size: 16px; font-weight: 600;
  }
  /* Het "/"-scheidingsteken (hierboven, buiten een media query) is de desktop-tabrij-styling (zie
     .shell-nav-list > li::after) - in de gestapelde mobiele kolom-layout landt dat teken op zijn
     eigen regel ONDER elk item i.p.v. ertussen, wat als een rare onderstreep+teken oogde. De
     generieke rij-scheiding (.mega-menu-item border-bottom, globals.css) ook weg: Wesley wil hier
     kale rijen zonder scheiding, zoals live's eigen mobiele menu. */
  .shell-header--vangool .shell-nav-list > li::after { content: none; }
  .shell-header--vangool .mega-menu-item { border-bottom: none; }
  /* `.shell-nav-list > li {align-items:center}` (hierboven, desktop tabrij) is een child-selector
     die ook hier matcht en dezelfde specificiteit heeft als de generieke mobiele
     `.shell-nav-list li {align-items:stretch}` (globals.css) - wint via bronvolgorde. Zonder deze
     reset kreeg .mega-menu-panel (geen eigen width, in tegenstelling tot .mega-menu-row dat wél
     width:100% heeft) shrink-to-content + gecentreerd i.p.v. de volle breedte, wat de submenu-
     pijltjes/tekst een stuk verder naar rechts/onder de rand liet beginnen dan "Producten" zelf. */
  .shell-header--vangool .shell-nav-list > li { align-items: stretch; }
  /* Gemeten op live: de uitgeklapte rij blijft gewoon wit, geen tint - de generieke navy-tint
     (globals.css, toegevoegd zonder live-referentie om open/dicht "cohesiever" te laten ogen) hier
     voor VanGool uitgezet. */
  .shell-header--vangool .mega-menu-item:has(.mega-menu-chevron[aria-expanded="true"]) .mega-menu-row,
  .shell-header--vangool .mega-menu-item:has(.mega-menu-chevron[aria-expanded="true"]) .mega-menu-row a {
    background: transparent;
  }
  /* Gemeten op live (mobiel, .dropdown-menu): transparante achtergrond, geen rand - de desktop-
     regel hierboven (.mega-menu-panel, buiten een media query: padding 25px 30px, gemeten op de
     FLOATING desktop-dropdown) heeft op mobiel exact dezelfde specificiteit (1 class) en wint hier
     anders alsnog via bronvolgorde over de generieke mobiele padding (globals.css) - vandaar hier
     expliciet resetten. De navy-tint/linker-accentbalk (globals.css, generieke toevoeging zonder
     live-referentie) ook weg: live's mobiele paneel is gewoon wit/transparant. */
  .shell-header--vangool .mega-menu-panel { padding: 0; background: transparent; border-left: none; }
  /* Gemeten op live (.dropdown-menu a): padding 5px 15px 5px 25px, font-weight 400 (normaal, niet
     bold) - VanGool's eigen `.shell-nav-list a` (hierboven, desktop: font-weight 700, padding 0) is
     een DESCENDANT-selector die deze submenu-links ook raakt (ze zitten genest onder .shell-nav-list),
     dus zonder deze regel bleven ze vet en zonder eigen tik-ruimte. margin:0 i.p.v. de generieke
     margin-bottom:5px - de eigen padding hierboven geeft nu al genoeg ademruimte tussen items. */
  /* justify-content:flex-start overrides de generieke `.shell-nav-list a {justify-content:space-
     between}` (globals.css, mobiel) - ook een descendant-treffer op deze submenu-links (::before
     chevron + tekst tellen dan als 2 flex-children), die de chevron en tekst tegen elkaars uiteinden
     van de rij duwde i.p.v. vlak naast elkaar links. */
  .shell-header--vangool .mega-menu-panel a { font-weight: 400; padding: 5px 15px 5px 25px; margin: 0; justify-content: flex-start; }
  /* Live's cirkel is 24x24 (border-radius 12px), niet de 32x32 die hierboven voor de TOP-level rijen
     is gezet. */
  .shell-header--vangool .mega-menu-chevron { width: 24px; height: 24px; }
  .shell-header--vangool .mega-menu-chevron svg { width: 12px; height: 12px; }
}

/* Topbalk ingelogd op een telefoon. Het blok hierboven zet bij ≤1099px bewust één rij met
   `flex-wrap: nowrap`, en dat klopt voor de UITGELOGDE balk: daar staan alleen Webshop/Registratie
   plus taal en zoeken, en die passen. Ingelogd staan er "Mijn account" en "Uitloggen", en dan niet.
   Gemeten op 375px met het ingelogde antwoord nagebootst (de echte componenten, alleen /api/auth/me
   onderschept): de inhoud liep door tot x=603 in een venster van 375 - de taalknop half buiten beeld,
   het zoekveld met zijn Webshop/Website-schakelaar volledig onbereikbaar - en "Mijn account" werd tot
   zijn minimumbreedte geknepen en brak over DRIE regels, wat de balk op 74px bracht.
   Eén rij is hier ook niet te redden: de vier onderdelen vragen samen ruim 490px waar 351px is. Dus
   krijgt de rechterhelft (prijzen-schakelaar, taal, zoeken) zijn eigen regel en houdt de linkerhelft
   de account-links. Niets valt weg en niets staat buiten beeld.
   Voor de volledigheid: live doet op 375px iets anders - daar staan ALLEEN de taalkiezer en het
   zoekveld in de balk (45px, één rij) en zitten de utility-links in het hamburgermenu. Dat naspelen
   vraagt een wijziging in Header.tsx (links doorgeven aan de mobiele nav), geen opmaak - apart
   besluit, want het verplaatst functionaliteit. */
@media (max-width: 767px) {
  .shell-header--vangool .shell-usp-inner { flex-wrap: wrap; row-gap: var(--space-2); }
  /* margin-left:auto duwde deze groep naar de rechterrand; op twee regels hoort hij links te beginnen.
     flex: 0 0 auto zodat hij niet meer onder zijn eigen tekst geperst wordt - dat was de woordafbreking. */
  .shell-header--vangool .vg-utility-group { margin-left: 0; flex: 0 0 auto; }
  /* De taalkiezer mee naar de EERSTE regel, zodat het zoekveld de tweede regel bijna alleen heeft
     (verzoek). Dat kan alleen als de drie kinderen van .shell-usp-right zelf flex-items van de balk
     worden - vandaar `display: contents`: die laat het tussenliggende kadertje verdwijnen zonder de
     opmaak van de kinderen te raken. De volgorde staat daarna met `order`, want in de HTML komt de
     prijzen-schakelaar vóór de taalkiezer.
     De regelovergang komt uit de breedtes zelf: account-links (188) + taal (76) vullen de eerste
     regel, de schakelaar past er niet meer bij en begint dus een nieuwe - nagemeten op 375 en 320px. */
  .shell-header--vangool .shell-usp-right { display: contents; }
  .shell-header--vangool .shell-usp .shell-lang { order: 1; }
  .shell-header--vangool .shell-usp .shell-toggle { order: 2; }
  /* flex-basis 0 en niet auto: met auto rekent de browser bij het afbreken met de eigen contentbreedte
     van het zoekveld (~250px), en dan past het niet meer naast de prijzen-schakelaar en kwam het op
     een DERDE regel - balk van 132px. Met basis 0 blijft het op dezelfde regel en groeit het daarna
     naar wat er over is: 215px op een venster van 375, vergelijkbaar met live's 212px. */
  .shell-header--vangool .shell-usp .shell-search { order: 3; flex: 1 1 0; min-width: 0; }
  /* Geen woordafbreking in de topbalk-links: "Mijn account" hoort op één regel. */
  .shell-header--vangool .shell-usp a,
  .shell-header--vangool .shell-usp button { white-space: nowrap; }
  /* De Webshop/Website-keuze uit het zoekveld verdwijnt op een telefoon. Niet om ruimte te winnen
     omdat het moet: gemeten op live op 375px staat er in die balk uitsluitend een zoekveld met een
     loep, zonder die keuze - terwijl vangool_full `search_type = 3` heeft en de keuze op desktop dus
     wel toont. Samen waren die twee labels 143px in een regel die er 131 over had, dus zonder deze
     regel liep de balk alsnog 65px buiten beeld. Het formulier houdt de aangevinkte stand, dus er
     verandert niets aan waar een zoekopdracht heen gaat. */
  .shell-header--vangool .shell-usp .shell-search-scope { display: none; }
}

/* Footer-logo's: alleen de afbeeldingen, geen banner_desc-label eronder (live toont die niet). */
.shell-footer .cms-banner-tile-label { display: none; }
/* Certificatie-logo's: gemeten op live 182px breed (niet 100% van de grid-cel) met 30px gap - de
   generieke .cms-banner-tile img{width:100%} rekt ze anders uit tot de smallere gelijke-kolombreedte
   (127px, 16px gap) van een 4-koloms grid. */
.shell-footer .cms-banner-grid { gap: 30px; justify-content: start; }
.shell-footer .cms-banner-tile { width: auto; min-height: 60px; }
/* min-height op de tile: zonder gereserveerde hoogte klapt de tile (en de <img loading="lazy"> erin)
   in tot 0x0 vóórdat de afbeelding geladen is - een 0-grootte element triggert de browser's native
   lazy-load intersection-check niet betrouwbaar, dus de echte fetch bleef soms helemaal uit (gezien:
   img.complete=true, naturalWidth=0, geen network request). Een vaste minimumhoogte voorkomt die
   deadlock, ongeacht laadvolgorde. */
/* De 182px is een BOVENgrens, niet een breedte: `min(182px, 100%)` laat het logo op desktop op zijn
   op live gemeten maat staan en krimpen zodra de cel smaller is. Zonder dat tweede deel bleef het
   182 in een cel van 156,5 (375px, twee kolommen van een rooster van 343 met 30px gap) en stak elk
   logo 25px buiten zijn cel; het rechtse eindigde op 384 in een venster van 375. Dat waren de 9px
   waarmee ELKE pagina op een telefoon horizontaal te scrollen was - op de winkelwagen gemeld, maar
   het zat in de footer en gold dus overal. Op 1099px hetzelfde met cellen van 177,5 (8px over). */
.shell-footer .cms-banner-tile img { width: auto; max-width: min(182px, 100%); max-height: 130px; }

/* move_to_banner: tegel-look voor tekstlinks (bv. "Ons assortiment" / "Testen & Keuren"), lichtblauw
   met witte tekst, subtekst uit de <small>-caption iets transparanter. */
/* Zelfde specificiteits-val als de header-strip (zie hierboven): de generieke link-kleurregel
   (.cms-page a:not(.btn):not(.btn-secondary)) telt 3 classes en won van deze 1-class selector, dus
   de tekst kreeg dezelfde blauwe kleur als de achtergrond - onzichtbaar. .cms-page toegevoegd om
   gelijk te trekken (nu vastgesteld, niet alleen aangenomen: computed style bevestigde identieke
   kleuren op zowel <a> als de achtergrond). */
.cms-page .cms-links.cms-links--tiles a { background: #38a4dd; color: #fff; }
.cms-page .cms-links.cms-links--tiles a:hover { background: #002a65; }
.cms-links--tiles a span { font-family: var(--font-heading); font-weight: 600; font-size: 15px; }

/* "Weergave"-label vóór de grid/lijst-icoontjes (ViewToggle.tsx): gemeten op live (.sort-options-wrapper
   label): MontserratSemiBold 14px grijs #46525b - generiek had dit label niet eens (alleen een
   onzichtbare aria-label), nu toegevoegd als zichtbare tekst (zie ViewToggle.tsx .view-toggle-label). */
.view-toggle-label { font-family: var(--font-heading); font-weight: 600; font-size: 14px; color: #46525b; }
/* Actieve/inactieve icoon-knop-kleuren, gemeten op live (.button.active.theme-primary / .button):
   actief = navy achtergrond wit icoon, inactief = wit met grijze rand donkere tekst - de generieke
   .view-toggle button[aria-pressed=true] gebruikt var(--color-accent) (lichtblauw #38a4dd hier), live
   gebruikt de navy merkkleur voor de actieve staat. */
/* `color: #fff` hoorde hier vanaf het begin bij - de meting hierboven zegt "wit icoon", maar deze
   regel zette alleen de achtergrond. Het icoon bleef daardoor de generieke donkere tekstkleur en
   stond donker op navy, praktisch onzichtbaar. */
.view-toggle button[aria-pressed="true"] { background: #002a65; border-color: #002a65; color: #fff; }

/* Sibling-categorie-pillen (leaf-categoriepagina): gemeten op live (.outline-btn): 1px navy rand
   #002a65, navy tekst, 700 gewicht Montserrat, geen achtergrond, hover = gevulde navy achtergrond
   met witte tekst (standaard outline-button-hover-patroon).
   .cms-page a:not(.btn):not(.btn-secondary) (3 classes + element) wint van een kale
   .category-sibling-pill (1 class) - dezelfde specificiteitsval als steeds. Optrekken naar dezelfde
   3 classes + element (.cms-page + .category-sibling-pills + .category-sibling-pill + a). */
.category-sibling-pill, .cms-page .category-sibling-pills a.category-sibling-pill {
  border-color: #002a65; color: #002a65;
  font-family: var(--font-heading); font-weight: 700; font-size: 14px;
}
.category-sibling-pill:hover, .cms-page .category-sibling-pills a.category-sibling-pill:hover {
  background: #002a65; color: #fff;
}

/* ---- /account dashboard: narrow option-sidebar + wide welcome/content column ---- */
/* Confirmed with Wesley (2026-08-05, CMS admin screenshots): Van Gool's account_template
   ("Default Account Pagina") is genuinely a single FULL-width zone - there's no second CMS zone/
   column to hold a sidebar. Live's narrow left column of plain option links next to the welcome
   text + team photo is therefore Van Gool's OWN bespoke CSS on top of the same generic
   uc_account_block markup our .account-dash already mirrors (icons/descriptions/wide layout =
   the generic Deponti-style tile treatment, see globals.css) - not a page-template/CMS-config
   difference, so it's implemented here as pure CSS repositioning of the existing DOM.
   main:has(.account-dash) scopes this to the dashboard index page only (not /account/profile etc,
   which don't render .account-dash) without needing a route-specific class. */
/* Measured directly on live via DevTools (2026-08-05, Wesley's own inspector screenshots):
   .col-md-3/.col-md-9 (Bootstrap, true 25%/75% proportional split, not a fixed sidebar width) -
   heading h2.heading-sm is 18px MontserratSemibold #002A65, margin 5px 0 10px; each option link is
   13px MontserratSemibold #002A65 (SAME font/color as the heading, only smaller - not the body/
   Open Sans font a first pass here had used). Montserrat only has 300/400/700 cuts loaded
   (app/layout.tsx) - no 600/Semibold cut exists to render, so 700 is the closest available weight,
   same substitution already used for every other "SemiBold" navy heading in this file. */
main:has(.account-dash) {
  display: grid;
  grid-template-columns: 3fr 9fr;
  grid-template-areas: "sidebar intro";
  align-items: start;
  gap: var(--space-6);
}
/* min-width: 0 op beide vakken. Zonder dit valt de automatische minimumbreedte van een grid-item
   terug op zijn min-content, en die wordt bepaald door het breedste kind - bij de welkomsttekst een
   CMS-afbeelding met een vaste inline breedte van 750px. Het 9fr-vak rekte daarmee tot 750px, `main`
   liep buiten het venster en `body { max-width: 100vw }` kapte de tekst rechts af. Vierde keer dat
   dit patroon in dit project toeslaat (zie de theming-skill), dus hier meteen op allebei de vakken. */
.account-intro, .account-dash { min-width: 0; }
.account-intro { grid-area: intro; }
/* Same content-heading convention already measured on live twice elsewhere in this file
   (.cms-text h1-h4 and .detail-info h1: MontserratBold, #46525b grey - NOT navy). The generic base
   rule (globals.css: h1,h2,h3,h4 { font-weight:400; color:var(--color-deep) }) left this specific
   h1 at the un-bolded navy default since nothing had overridden it here yet. */
.account-intro h1 { font-weight: 700; color: #46525b; }
.account-dash { grid-area: sidebar; margin-top: 0; }
/* Live: plain heading + plain link list per group, no icon, no sub-description, no divider rule -
   just vertical spacing between groups (see uc_account_block.ascx's col-md-3/col-md-9 split,
   condensed here into one narrow column instead of the generic wide icon+description layout). */
.account-dash-group { display: block; grid-template-columns: none; padding: var(--space-3) 0; border-top: none; gap: 0; }
.account-dash-group-head { border-bottom: none; padding-bottom: 0; }
.account-dash-icon { display: none; }
.account-dash-group-head h2 { font-size: 18px; font-family: var(--font-heading); font-weight: 700; color: #002a65; margin: 5px 0 10px; }
/* Live indents every option link one step in from its own group heading (measured on Wesley's
   reference screenshot: ~16px) - globals.css's own .account-dash-options rule zeroes the browser's
   default ~40px marker-gutter padding (a real generic bug fix, kept), but Van Gool's compact sidebar
   still wants a small DELIBERATE indent of its own on top of that zero, not none at all. */
.account-dash-options { padding-left: var(--space-4); }
.account-dash-option { padding: 2px 0; border-bottom: none; }
.account-dash-option a { font-weight: 700; font-size: 13px; font-family: var(--font-heading); color: #002a65; }
.account-dash-option a:hover { color: #4379bd; }
/* Description sits in a plain <div className="muted"> (app/account/page.tsx), not a <p> - a `p`
   selector here matches nothing and silently hides zero descriptions. */
.account-dash-option .muted { display: none; }
/* "Wachtwoord wijzigen" (GROUPS's own separate last group, app/account/page.tsx) has exactly one
   option whose label repeats its own heading title - in this compact sidebar that reads as an
   awkward duplicate line. Live's account.aspx shows it as the plain last item under "Mijn account"
   instead, with no section of its own. Its option href isn't gated by any module flag, so it's
   ALWAYS the last rendered .account-dash-group - hiding just this group's own heading (no border/
   gap between groups here already) makes its single link fall right in with "Mijn account"'s list
   above it, without touching the generic GROUPS data (Deponti's wide tile view still gets its own
   dedicated password box, matching uc_account_block.ascx's separate service-box-v2 for it). */
.account-dash-group:last-child .account-dash-group-head { display: none; }
.account-dash-group:last-child { padding-top: 0; }
@media (max-width: 860px) {
  main:has(.account-dash) { grid-template-columns: 1fr; grid-template-areas: "intro" "sidebar"; }
}

/* ---- Snel bestellen (order entry): compact autocomplete suggestions ---- */
/* Excluding .order-entry-suggest-btn from the generic bare-button rule above already restores the
   normal flex-ROW layout (code + description side by side, not stacked/centered/bold) - this just
   tightens it further per Wesley's "compact maken" request: smaller gap/padding, and the
   description no longer wraps to a second line (many are longer than the dropdown is wide, which
   is what made each row 2-3 lines tall) - it truncates with an ellipsis instead. */
.order-entry-suggest button { gap: var(--space-2); padding: 6px var(--space-3); }
.order-entry-suggest button span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.order-entry-suggest .order-entry-code { font-size: 13px; }

/*----------------------------------------
    Regelweergave: vaste kolommen
----------------------------------------*/
/* De regel is een flexrij waarin ELK onderdeel op `flex: 0 1 auto` staat - dus inhoudsbreed, en niets
   groeit. Gemeten op /category/takels-%26-lieren/elektrische-takels bij 1440px, vier regels:
     artikelcode  x=544 vast, maar 46..56 breed -> titel begon op 606, 607, 613 en 616
     prijs        x=984..1072, 124..146 breed; bij 124 brak "excl. btw" naar een tweede regel
     knop         x=1212 bij drie regels, maar x=1146 bij de vierde - een sprong van 66px
   De titel groeit niet mee, dus een regel met een korte titel vult de rij niet en trekt prijs en knop
   naar links. Vandaar hier vaste breedtes voor de twee smalle kolommen en groei op de titel: dan
   staan code, prijs en knop op elke regel op dezelfde x.
   Alleen binnen .product-list, dus de tegelweergave blijft zoals hij is. */
.product-list .product-code { flex: 0 0 120px; }
.product-list .product-title-link { flex: 1 1 auto; min-width: 0; }
/* Rechts uitgelijnd tegen de knop aan, met de "Prijs vanaf"-regel erboven (die staat via
   .product-price-label al op display:block). 180px is de breedste regel plus lucht: "€ 2.463,00
   excl. btw" meet 146 zonder afbreken. */
.product-list .product-price-slot { flex: 0 0 180px; justify-content: flex-end; text-align: right; }
/* Het bedrag en "excl. btw" horen bij elkaar op één regel - dat afbreken was het lelijkste aan de
   huidige rij. */
.product-list .product-price-row { white-space: nowrap; }
.product-list .buy-row { flex: 0 0 auto; }

/* ---------------------------------------------------------------------------------------------
   WINKELWAGEN / CHECKOUT: gevulde grijze vlakken worden witte kaarten met een dunne rand.
   Besluit Wesley 2026-08-14, op zijn melding "die achtergronden enzo zo lelijk" - en bewust ALLEEN
   hier en niet generiek, want het draait twee gedocumenteerde generieke keuzes om (`.checkout-box`
   en `.cart-line-comment` vullen met --color-muted, bij die laatste met de expliciete onderbouwing
   dat een optionele notitie niet als een echt formulierveld mag lezen). Elke andere tenant houdt dus
   wat hij had.
   Er is GEEN live-referentie: de winkelwagen van vangool.nl zit achter de dealerlogin. Daarom geen
   enkele nieuwe kleur verzonnen - alles komt uit de tokens die op de publieke pagina's van deze site
   al gemeten zijn (zie bovenaan dit bestand): rand #d0d3d5 (--color-border, dezelfde als de selects),
   radius 2px, tekst #46525B, koppen #002A65.
   Gemeten vóór deze wijziging op localhost:3002/cart (1440px, gevulde wagen): .checkout-box
   561x140 en 1138x69 in #f2f4f7 met een rand van #eee - een rand die op een gevuld vlak niets doet en
   op wit onzichtbaar is, vandaar dat de vulling het enige was dat de vakken begrensde.
   --------------------------------------------------------------------------------------------- */
body:has(.shell-header--vangool) .checkout-box {
  background: #fff;
  border-color: var(--color-border);
}
/* Het opmerkingveld per regel: drie grijze balkjes van 360x25 onder elkaar waren precies wat de
   regels rommelig maakte. Als gewoon veld leest het rustiger, en de focus-toestand hoeft dan niet
   meer van kleur te wisselen (generiek springt hij van grijs naar wit) - alleen de rand kleurt bij. */
body:has(.shell-header--vangool) .cart-line-comment {
  background: #fff;
  border-color: var(--color-border);
}
body:has(.shell-header--vangool) .cart-line-comment:focus { border-color: var(--color-deep); }
/* De totalenkaart stond al op wit met een rand van #eee en een schaduw. Op een pagina die nu overal
   witte kaarten met een #d0d3d5-rand heeft, is die ene lichtere rand het buitenbeentje - gelijk
   getrokken, schaduw eraf zodat de kaarten onderling hetzelfde wegen. */
body:has(.shell-header--vangool) .cart-summary {
  border-color: var(--color-border);
  box-shadow: none;
}

/* ---- Zoeksuggesties op een telefoon ------------------------------------------------------------
 * Gemeten op 375px: elke regel was 102px hoog, dus er pasten er vier in het paneel van 400. Dat kwam
 * door de derde regel per suggestie - een aantalkiezer van 104px plus de bestelknop, onder de tekst.
 * Elke suggestie las daardoor als een kaartje in plaats van als een regel in een lijst, en juist het
 * antwoord op wat je typt (welke takel is dit?) kreeg de minste ruimte.
 *
 * Wat deze regels doen, in volgorde van belang:
 *   1. De aantalkiezer gaat weg. Op 375px kost hij een derde van de breedte voor iets wat je hier
 *      zelden instelt; het aantal wijzig je in de wagen. De bestelknop blijft, dus de actie zelf
 *      verdwijnt niet - alleen de fijnregeling.
 *   2. De knop schuift mee naar dezelfde regel als de tekst, verticaal gecentreerd rechts. Daarmee is
 *      elke suggestie precies twee tekstregels hoog en zijn alle regels even hoog: een lijst om langs
 *      te scannen, niet acht blokjes.
 *   3. De foto komt terug (generiek wordt hij hier verborgen). In deze catalogus verschillen de namen
 *      onderling minimaal - "KITO Elektrische Takel type ER2S / EQS / ED1" - en dan is het plaatje het
 *      snelste onderscheid dat er is. 40px, precies de hoogte van de twee tekstregels.
 * Uitkomst gemeten: regelhoogte 102 -> 62px, zes suggesties in beeld in plaats van vier. */
@media (max-width: 560px) {
  body:has(.shell-header--vangool) .shell-search-suggest li {
    grid-template-columns: 40px minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
  }
  /* De link als FLEX-rij in plaats van een subgrid over kolom 1-2. Met het subgrid stond de foto
     namelijk 2px van de tekst af: de <img> rendert 10px ná het begin van zijn eigen kolom (gemeten:
     kolom 31..71, afbeelding 41..81), dus de 12px kolomruimte werd voor het overgrote deel links van
     de foto opgesoupeerd in plaats van rechts ervan. Met flex bepaalt de gap de afstand die je ook
     echt ziet: 14px tussen foto en tekst. De knop zit in de derde kolom van de <li> zelf en blijft
     dus gewoon uitgelijnd over alle regels. */
  body:has(.shell-header--vangool) .shell-search-suggest-link {
    grid-column: 1 / 3;
    display: flex;
    align-items: center;
    gap: 14px;
  }
  body:has(.shell-header--vangool) .shell-search-suggest-thumb {
    display: block;
    width: 40px;
    height: 40px;
  }
  body:has(.shell-header--vangool) .shell-search-suggest-buy > .qty-stepper { display: none; }
  /* De knop is nu het enige kind van de koopregel en staat in de derde kolom, dus die regel hoeft
     zelf geen ruimte meer te claimen. 32px hoog: klein genoeg voor een lijst, groot genoeg om met
     een duim te raken zonder de regel op te rekken. */
  body:has(.shell-header--vangool) .shell-search-suggest-buy { grid-column: 3; }
  body:has(.shell-header--vangool) .shell-search .shell-search-suggest-buy > button {
    padding: 6px 12px;
    font-size: 12px;
    line-height: 1.4;
    min-height: 32px;
  }
  /* Codeblok en naam: de code is een label (klein, grijs, gespatieerd), de naam draagt de regel en
     staat in de navy van de huisstijl. Eén regel met ellipsis, zodat elke suggestie even hoog is. */
  body:has(.shell-header--vangool) .shell-search-suggest-code { font-size: 11px; letter-spacing: .06em; }
  body:has(.shell-header--vangool) .shell-search-suggest-desc { font-size: 14px; color: #002a65; }
  /* Twee regels voor de naam, en dat is de belangrijkste keuze van dit blok. Met een enkele regel
     eindigde ELKE suggestie op "KITO Elektrische Takel..." - acht identieke regels, want het
     onderscheid ("type ER2S 125KG", "type EQS 0,5-1T") valt precies achter de afkapping. Een lijst
     die je niet kunt lezen is geen lijst. Kosten: de regel wordt ~80 in plaats van 65px hoog, dus
     vijf suggesties in beeld in plaats van zes. Dat is het waard - je zoekt hier welke takel je
     hebt, niet hoeveel regels er passen. */
  body:has(.shell-header--vangool) .shell-search-suggest-desc {
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    line-height: 1.3;
  }
}

/* ---- Productlijst op een telefoon: prijs en knop op EEN lijn ------------------------------------
 * Verzoek Wesley: "prijs en vanaf-tekst meer naar links, op dezelfde lijn als de winkelwagenknop".
 * Wat er stond, gemeten op 375px: het prijsblok was rechts uitgelijnd en 63px hoog omdat het over
 * drie regels brak - "Prijs vanaf" op een eigen regel (de label-span is display:block), daaronder het
 * bedrag van 20px met "excl. btw" erachter. De knop stond bodemgelijk in de derde kolom en kwam
 * daardoor ONDER die stapel uit te zien in plaats van ernaast.
 *
 * Nu: het prijsblok is een enkele regel die links begint (bij de tekstkolom, niet rechts uitgelijnd),
 * en krijgt dezelfde hoogte als de knop met verticaal gecentreerde inhoud. Twee blokken van gelijke
 * hoogte, allebei op de onderrand van de kaart, dus ze staan per definitie op dezelfde lijn.
 * De maten gaan omlaag (label/btw 11px, bedrag 15px i.p.v. 20px) omdat de tekstkolom op 375px 195px
 * breed is; met de oude 20px past "Prijs vanaf € 2.463,00 excl. btw" er niet op een regel. Op de
 * PRODUCTPAGINA blijft de prijs zijn eigen (grote) maat houden - dit geldt alleen in de lijst. */
@media (max-width: 560px) {
  body:has(.shell-header--vangool) :is(.product-list, .product-grid) .product-price-slot {
    justify-content: flex-start;
    align-items: center;
    min-height: 40px;
  }
  body:has(.shell-header--vangool) :is(.product-list, .product-grid) .product-price-row {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    column-gap: 5px;
    row-gap: 0;
    margin: 0;
  }
  body:has(.shell-header--vangool) :is(.product-list, .product-grid) .product-price-label { font-size: 11px; }
  body:has(.shell-header--vangool) :is(.product-list, .product-grid) .product-price { font-size: 15px; white-space: nowrap; }
  body:has(.shell-header--vangool) :is(.product-list, .product-grid) .product-price-vat { font-size: 11px; }
}

/* De zwevende Contact/EKH-tab hoort niet op een telefoon. Gemeten op 375px: hij staat vast tegen de
 * rechterrand (x=330..375, z-index 40) en legt zich precies over de bestelknoppen van het
 * productoverzicht heen - je kunt er niet omheen tikken. Live doet dit niet: op vangool.nl is er bij
 * 375px geen enkele fixed tab met "Contact" in de DOM, die verschijnt pas op een breed scherm.
 * Zelfde grens als de rest van dit blok (560px), dus op tablet en desktop blijft hij staan. */
@media (max-width: 560px) {
  body:has(.shell-header--vangool) .cms-links.cms-links--sidebar { display: none; }
}
