/* work.css - ronde 5: de work-index (/our-work/) en het case-sjabloon.
 *
 * Apart bestand, net als forms.css, services.css en about.css: styles.css blijft
 * daarmee dicht bij de goedgekeurde bron en een fout hier kan nooit de homepage
 * raken. Binnenkomen doet dit via de `styles`-prop op BaseLayout.
 *
 * Alleen tokens uit DESIGN.md §1. Geen losse hex, geen losse ease, radii uit de
 * gesloten set (2/3/4/8/10/999). Op PAPER staat het accentrood op --red-deep:
 * --red haalt daar 3,56:1 en dat is onder de 4,5:1 van §8 (gemeten in ronde 3,
 * en het is de reden dat .hub-num daar ook op --red-deep staat).
 */

/* ============================================================
   1. De kop (ink)
   ============================================================ */

.work-head {
  background: var(--ink);
  color: var(--paper);
  padding: calc(var(--nav-h) + clamp(46px, 7vw, 96px)) 0 clamp(46px, 6vw, 86px);
}

/* --grey en niet --grey-2: die haalt op ink 3,37:1 bij 11,5px. Dit is de
   huisregel die elke donkere sectie in styles.css al volgt (DESIGN.md
   wijzigingslog 2026-07-30). */
.work-head .kicker { color: var(--grey); }

.work-lead {
  color: var(--grey);
  max-width: 46ch;
  margin-top: 20px;
  font-size: 1.02rem;
}

/* Het raster van .news-inner: cijfers in de smalle kolom, beeld in de brede.
   Zelfde vorm als de kop van de services-hub, zodat de site een hand blijft. */
.work-head-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 2fr);
  gap: clamp(30px, 5vw, 76px);
  align-items: end;
  margin-top: clamp(34px, 5vw, 64px);
}

.work-facts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(18px, 2.2vw, 28px);
}

.work-fact {
  display: grid;
  gap: 8px;
}

.work-fact-figure {
  font-stretch: 63%;
  font-weight: 840;
  letter-spacing: 0.002em;
  line-height: 0.98;
  font-size: clamp(2.1rem, 3.4vw, 3.1rem);
  color: var(--white);
}

.work-fact-lab {
  display: block;
  border-top: 1px solid var(--line-w);
  padding-top: 8px;
}

.work-fact-label {
  font-family: var(--font-mono);
  font-size: 1.00rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--grey);
}

/* Vaste verhouding: een vervangen beeld verschuift de layout nooit (§4). */
.work-head-media {
  aspect-ratio: 3 / 2;
  overflow: hidden;
  border-radius: 4px;
}
/* Het anker eromheen moet de doos VULLEN, anders resolvet height:100% op de img
   tegen een auto-hoge <a> en valt het beeld terug op zijn eigen hoogte. */
.work-head-media .beeld-open {
  display: block;
  height: 100%;
}
.work-head-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ============================================================
   2. De ledger (paper)
   ============================================================ */

.work-ledger {
  background: var(--paper);
  color: var(--ink);
  padding: clamp(56px, 7vw, 104px) 0 clamp(56px, 7vw, 104px);
}

.work-ledger-inner {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 2fr);
  gap: clamp(30px, 5vw, 76px);
  align-items: start;
}

/* De rail plakt. DESIGN.md §6b: sticky is apparatuur en geen eis, dus dit mag
   alleen als de rail aantoonbaar in het venster past. Hij draagt kicker, kop,
   acht filterpillen en een teller; check-work.mjs meet zijn hoogte tegen de
   beschikbare ruimte op meerdere venstergroottes, precies zoals de expertiserail
   van een persoonspagina bewaakt wordt. */
/* PLAKKEN MAG ALLEEN ALS DE RAIL PAST (DESIGN.md §6b: sticky is apparatuur en
   geen eis). Een sticky element scrollt niet intern, dus wat onder de vouw
   uitsteekt is PERMANENT onzichtbaar, niet even weg.

   Gemeten door check-work.mjs, met de rail onvoorwaardelijk sticky: hij is
   717px op 1440px breed en 663px op 1024px (kicker, kop, acht filterpillen en
   de teller). De beschikbare ruimte is innerHeight min de top van 98px
   (--nav-h + 26px), dus op een venster van 700px hoog bleef er 602px over en
   stond 115px permanent buiten beeld: de teller en de onderste rij pillen.
   Dat is exact de fout waarvoor §6b is opgeschreven, en de rail is precies het
   element dat de filter bedient.

   717 + 98 = 815, dus vanaf 830px vensterhoogte past hij met marge. Daaronder
   scrollt de rail gewoon mee en is alles bereikbaar. Dit is GEEN dode query:
   een veelgebruikte laptop staat rond 700 tot 800px viewporthoogte, dus hij
   staat op echte schermen daadwerkelijk uit.

   HERMETEN 2026-08-29, na het vergroten van de type-schaal: de filterpillen en
   de teller dragen .mono, dat van 0,72rem naar 0,82rem ging, en de rail werd
   daarmee 717px -> 739px op 1440px breed. 739 + 98 = 837, dus de oude drempel
   van 830px liet hem plakken terwijl hij NIET meer paste: op een venster van
   830 tot 837px hoog stond de teller er weer buiten. Drempel mee omhoog naar
   850px, met dezelfde marge van ongeveer 15px als de oorspronkelijke redenering.
   Toets 7 van check-work.mjs meet dit bij elke run opnieuw.

   HERMETEN 2026-08-29 (ronde 2), met .mono op 1rem: de rail is 739 -> 778px op
   1440px breed. 778 + 98 = 876, dus de drempel van 850 liet hem opnieuw plakken
   terwijl hij niet meer paste. Naar 890, met dezelfde marge van ongeveer 14px
   als beide vorige keren. Dit is de tweede keer dat deze drempel meeschuift met
   de labelmaat, en dat is geen toeval: de rail bestaat UIT labels. Wie de schaal
   nog eens aanraakt, meet deze drempel opnieuw. */
.work-rail {
  align-self: start;
}
@media (min-height: 890px) {
  .work-rail {
    position: sticky;
    top: calc(var(--nav-h) + 26px);
  }
}

/* De huismaat voor een kop in een smalle kolom, overgenomen van
   .news-rail .section-title. Geen nieuwe token. */
.work-rail .section-title {
  font-size: clamp(2.3rem, 4.2vw, 3.7rem);
  margin-bottom: 22px;
}

/* --- de filter (verrijking) --- */

/* Zonder JS bestaat er geen filter: de pillen staan wel in de DOM maar zijn
   onzichtbaar en uit de tabvolgorde, zodat er nooit een knop staat die niets
   doet. Het script zet .is-enhanced op <html>. */
.work-filter { display: none; }
.is-enhanced .work-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
}

.work-pill {
  font-family: var(--font-mono);
  font-size: 1.00rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--line-k);
  border-radius: 999px;
  /* 44px tikdoel (§8), gehaald via de REGELHOOGTE en niet via meer horizontale
     padding. Rekensom: 11,5px x 1,3 = 15px, plus 2x14px padding en 2x1px rand =
     45px. Met 14px padding rondom kwam dit op 42px, en dat meldde
     check-page-floor.mjs terecht als te klein. Bredere pillen zouden het ook
     oplossen, maar die wrappen naar meer rijen en maken de rail hoger, en dat
     kostte de pagina gemeten een procentpunt breedtebenutting: op de banden
     waar alleen een pil staat reikt de sectie maar 21%. */
  padding: 14px 16px;
  line-height: 1.3;
  cursor: pointer;
  transition: background 0.3s var(--ease-out), color 0.3s var(--ease-out), border-color 0.3s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .work-pill:hover { border-color: var(--ink); }
}
.work-pill.is-on {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.work-pill:focus-visible {
  outline: 2px solid var(--red-deep);
  outline-offset: 2px;
}

.work-count {
  color: var(--grey-2);
  margin: 0;
}
/* Zonder JS verandert dit getal nooit en zegt "23 of 23" niets; dan is de teller
   ruis. Hij hoort bij de filter en verschijnt met de filter. */
.work-count { display: none; }
.is-enhanced .work-count { display: block; }

/* --- de rijen --- */

.work-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line-k);
}

.work-row {
  position: relative;
  border-bottom: 1px solid var(--line-k);
  overflow: hidden;
  transition: background 0.35s var(--ease-out);
}

/* De rode randstreep die bij hover uitschuift: exact wat .news-row doet, alleen
   op paper. Op ::after en niet op een extra element, net als daar. */
.work-row::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--red);
  transform: scaleY(0);
  transform-origin: top center;
  transition: transform 0.35s var(--ease-out);
  z-index: 1;
}

/* DE DIENSTLABELS LOPEN OVER DE NAAM- EN DE UITKOMSTKOLOM, en dat is geen
   smaakkeuze maar de reparatie van de §6b-fout. `.about-row` in about.css draagt
   sinds ronde 4 exact dit commentaar en exact deze rasterindeling, en deze rij is
   in ronde 5 toch weer met de labels IN de smalle middenkolom gebouwd.

   Gemeten op 2026-07-31, 1440px, met de rij zoals hij was: de middenkolom is
   196px breed in een rij van 723px. Zestien van de 23 klantnamen wrapten daarin
   naar twee of meer regels (First Graphene naar VIER), en de labelband reikte tot
   73% van --wrap terwijl de uitkomst ernaast op 95% staat. De ledger kwam
   daardoor op 78% en de pagina op 79%, onder de 80% van de ondergrens.
   Met de labels op een eigen rasterrij: ledger 81%, pagina 81%.

   De vaste kolommaten zijn die van de huisgrammatica en geen nieuwe waarden:
   46px indexkolom en gap clamp(14px, 2vw, 28px) uit `.about-row`, en de
   uitkomstkolom minmax(146px, 210px) uit `.news-row` (styles.css r.897). Dat
   geeft de klantnaam 239px in plaats van 196px.

   DE CLIPKOLOM IS 136px EN GEEN PIXEL MEER, en dat is gemeten en geen smaak. De
   rij heeft geen speling: elke pixel die de clip erbij krijgt, gaat van de
   naamkolom af. Gemeten op 1440px, aantal klantnamen dat over twee of meer
   regels valt: 120px -> 11, 136px -> 11, 140px -> 13, 148px -> 14, 152px -> 15
   en dan valt de langste naam op vier regels. Die 16px zijn dus gratis en de
   volgende vier niet. Boven 136px keert precies de regressie terug die ronde 5
   met de rasterindeling van .news-row had gerepareerd. */
.work-row-link {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 46px 136px minmax(0, 1fr) minmax(146px, 210px);
  grid-template-areas:
    "num clip client out"
    "num clip svcs   svcs";
  gap: 6px clamp(14px, 2vw, 28px);
  align-items: center;
  padding: clamp(20px, 2.4vw, 30px) 12px;
  text-decoration: none;
  color: inherit;
}
.work-row-link:focus-visible {
  outline: 2px solid var(--red-deep);
  outline-offset: -2px;
}

/* De indexCEL draagt twee dingen: het volgnummer en het jaar eronder. Zij is de
   rastercel; .work-num en .work-year zijn haar kinderen en hebben zelf geen
   grid-area meer. Zo blijft "num" een gebied in alle drie de rasters hieronder
   zonder dat elk van hen twee gebieden moet noemen. */
.work-num-cel {
  grid-area: num;
  align-self: start;
  padding-top: 6px;
}
.work-num {
  display: block;
  color: var(--grey-2);
}
/* Het jaar op 0,82rem: de indexkolom is 46px en .mono staat sinds de
   type-schaal op 1rem, waarmee vier cijfers met 0,14em tracking ~47px vragen en
   dus niet passen. Dit is de uitzondering van DESIGN.md §1a-2 (een dichte reeks
   labels in een smalle kolom), dezelfde als de persoonsrail en het
   About-register, en geen nieuwe maat.

   DE KLEUR IS --grey-2 EN ERFT DUS DIE VAN HET VOLGNUMMER, met opzet. Hier stond
   eerst --grey-3, overgenomen van .news-date die precies dezelfde rol speelt in
   de newswire-rij. Nagemeten op --paper: --grey-3 haalt 2,94:1 en --grey-2 5,38:1,
   en de drempel van DESIGN.md §8 is 4,5:1. .news-date staat op INK, waar dezelfde
   hex ruim voldoet. Een token overnemen van een sectie met de andere toon is
   daarmee altijd een meting waard; het onderscheid tussen nummer en jaar draagt
   hier de MAAT (16px tegen 13,12px) en niet de kleur. */
.work-year {
  display: block;
  margin-top: 4px;
  font-size: 0.82rem;
  letter-spacing: 0.08em;
  color: var(--grey-2);
  font-variant-numeric: tabular-nums;
}

/* De achtergrond hangt aan .has-shot en niet aan .work-clip zelf. Drie cases
   hebben geen bruikbaar beeld (spec §1.5), en een leeg grijs vlak in hun rij
   leest als een beeld dat niet geladen is in plaats van als een rij zonder
   beeld. De cel blijft wel bestaan, want de kolom staat in het raster: de andere
   twintig rijen mogen niet verschuiven. */
/* GEEN VASTE ASPECT-RATIO MEER. Die stond op 4/3 landschap terwijl elf van de 21
   bronnen staand zijn (801x1024), en sneed ze met object-fit cover terug tot 59%
   zichtbaar: hoofden eraf, krantenkoppen doormidden. De KOLOM houdt een vaste
   breedte, dus het raster lijnt nog steeds uit; alleen de hoogte volgt de bron.
   De layout blijft stabiel bij een vervangen beeld omdat width, height en
   aspect-ratio uit de asset-metadata op het element staan. Zie DESIGN.md §4. */
.work-clip {
  grid-area: clip;
  display: block;
  overflow: hidden;
  border-radius: 3px;
  align-self: start;
  /* KRIMP OM HET BEELD HEEN. De cel is 136px breed maar een staande clip vult
     daar maar 81px van, en de --paper-2-achtergrond stond dan als grijze
     rechthoek NAAST het beeld: precies het "beeld dat niet geladen is" dat die
     achtergrond juist moest voorkomen. Met fit-content houdt de KOLOM zijn
     136px, dus het raster lijnt uit, en krimpt alleen het vlak. */
  width: fit-content;
}
.work-clip.has-shot { background: var(--paper-2); }
/* DE HOOGTE IS BEGRENSD OP 104px, en dat is de 4/3 van de 136px-kolom. Niet om
   te snijden (dat doet max-height met width:auto niet) maar omdat een rij een
   horizontale band is: zonder grens werd een staande clip 153px hoog, hoger dan
   de tekst ernaast, en ontstonden er meetbanden waarin ALLEEN de clip staat. Die
   reiken tot 19% van --wrap en trokken de ledger van 84% naar 79%, onder de
   ondergrens van §6c. Gemeten tekstblok van een rij: 58 tot 126px, mediaan 80px.

   Waarom 104 en niet de hoogste score uit de reeks: de meting bemonstert per
   40px en is op deze schaal onrustig. Gemeten paginabenutting bij max-height
   72/80/88/96/104px: 85/84/83/79/82%. Die 79% bij 96px valt uit de reeks en is
   bemonsteringsruis, geen signaal, dus afstemmen op het maximum zou op ruis
   afstemmen zijn. 104px is de waarde die uit de kolombreedte volgt, staat twee
   procentpunt boven de ondergrens en meet stabiel over herhaalde runs.

   Uitkomst per bron, alle 21 op 100% zichtbaar (was 59% tot 88%):
   staand 801x1024 -> 81x104 · vierkant 1500 -> 104x104 · landschap 994x657 ->
   136x90, dus BREDER dan de 120x90 van voor deze reparatie. */
.work-clip img {
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 104px;
  display: block;
  /* De huisbehandeling van .case-scan: grijstinten die bij hover oplossen. Dat
     maakt van de zwakke bronresolutie een bewuste vorm in plaats van een gebrek
     (ontwerp §2.3). */
  filter: grayscale(1) contrast(1.04);
  transition: filter 0.45s var(--ease-out), transform 0.6s var(--ease-out);
}

/* Het kop-recept (§2): smal en zwaar, uppercase. */
.work-client {
  grid-area: client;
  min-width: 0;
  display: block;
  font-stretch: 64%;
  font-weight: 780;
  text-transform: uppercase;
  font-size: clamp(1.45rem, 2.6vw, 2.3rem);
  text-wrap: pretty;
  line-height: 1.02;
  transition: transform 0.4s var(--ease-out);
}

.work-svcs {
  grid-area: svcs;
  min-width: 0;
  display: block;
  color: var(--grey-2);
  /* 4px bovenop de 6px rijgap van het raster: samen de 10px die de labels
     hiervoor als losse margin van 9px hadden. */
  margin-top: 4px;
  /* De labels mogen afbreken; de echte spaties in de markup zijn de
     afbreekkansen (DESIGN.md §4). */
  line-height: 1.5;
}
.work-svcs .sep { color: var(--red-deep); }

.work-out {
  grid-area: out;
  justify-self: end;
  text-align: right;
  min-width: 0;
}

.work-fig {
  display: block;
  font-stretch: 63%;
  font-weight: 840;
  letter-spacing: 0.002em;
  line-height: 0.98;
  font-size: clamp(1.6rem, 2.8vw, 2.4rem);
}

.work-lab {
  display: block;
  color: var(--grey-2);
  margin-top: 6px;
}
/* Drie cases dragen geen cijfer en daar staat het label alleen. Zonder deze
   regel houdt het de marge die onder een cijfer hoort en hangt het los in de
   rij, alsof er een cijfer weggevallen is. */
.work-out > .work-lab:first-child { margin-top: 0; }

@media (hover: hover) and (pointer: fine) {
  .work-row:hover { background: rgba(10, 10, 12, 0.03); }
  .work-row:hover::after { transform: scaleY(1); }
  .work-row:hover .work-client { transform: translateX(7px); }
  .work-row:hover .work-clip img { filter: grayscale(0) contrast(1); transform: scale(1.03); }
}
/* Toetsenbord krijgt dezelfde behandeling als de muis: anders is de actieve rij
   voor wie tabt onzichtbaar. */
.work-row:focus-within::after { transform: scaleY(1); }
.work-row:focus-within .work-clip img { filter: grayscale(0) contrast(1); }

/* ============================================================
   3. Smallere vensters
   ============================================================ */

/* Onder 1000px klappen beide rasters naar een kolom, net als elk ander
   twee-koloms patroon in styles.css. De rail plakt dan niet meer: boven de
   rijen hangen zou de halve eerste schermvulling opeten. */
@media (max-width: 1000px) {
  .work-head-grid,
  .work-ledger-inner {
    grid-template-columns: 1fr;
  }
  .work-rail {
    position: static;
    margin-bottom: clamp(24px, 4vw, 40px);
  }
}

/* De band 640-900px: de clipping blijft, maar de uitkomst gaat onder de naam
   staan in plaats van aan de rechterrand. Met vier kolommen wordt de naamkolom
   daar smaller dan de klantnaam op zijn eigen maat. */
@media (max-width: 900px) {
  .work-row-link {
    grid-template-columns: 44px 92px minmax(0, 1fr);
    grid-template-areas:
      "num clip client"
      "num clip svcs"
      "num clip out";
    align-items: start;
  }
  .work-out {
    justify-self: start;
    text-align: left;
    margin-top: 12px;
  }
  .work-fig { font-size: clamp(1.5rem, 5vw, 2rem); }
}

/* Onder 560px valt de clipping weg. Op die breedte is 92px beeld naast een
   klantnaam op display-formaat geen informatie meer maar ruis, en het cijfer is
   wat de rij moet dragen. */
@media (max-width: 560px) {
  .work-row-link {
    grid-template-columns: 38px minmax(0, 1fr);
    grid-template-areas:
      "num client"
      "num svcs"
      "num out";
  }
  .work-clip { display: none; }
}

/* ============================================================
   4. Het case-sjabloon
   ============================================================ */

.case-hero {
  background: var(--ink);
  color: var(--paper);
  padding: calc(var(--nav-h) + clamp(46px, 7vw, 96px)) 0 clamp(34px, 4vw, 56px);
}
.case-hero .kicker { color: var(--grey); }

/* Twee zones vanaf de eerste regel: naam links, dossier rechts. Zelfde
   verhouding als .news-inner, zodat de site een hand blijft. */
.case-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(30px, 5vw, 76px);
  align-items: end;
}

/* Het projectdossier: mono-label boven de waarde, met een haarlijn per rij.
   Dezelfde opbouw als de feitenrail op About. */
.case-dossier {
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(14px, 1.8vw, 22px);
}
.case-dossier-row {
  border-top: 1px solid var(--line-w);
  padding-top: 10px;
}
.case-dossier-lab {
  display: block;
  color: var(--grey);
  margin: 0 0 6px;
}
.case-dossier-val {
  display: block;
  margin: 0;
  color: var(--white);
  font-size: clamp(1rem, 1.5vw, 1.18rem);
  line-height: 1.35;
}

/* Het beeld draagt de verhouding van zijn bronbestand; de aspect-ratio komt uit
   de asset-metadata en staat inline op het element. Hier alleen de begrenzing,
   zodat een staand knipsel van 801x1024 de hero niet drie schermen hoog maakt. */
.case-hero-media {
  margin-top: clamp(28px, 4vw, 48px);
}
/* NOOIT OPSCHALEN, NOOIT SNIJDEN. Hier stond width:100% met max-height en
   object-fit cover. Die drie samen deden precies wat het comment hierboven
   verbood: width:100% blies een bron van 801px op naar 1128px (1,41x), en
   max-height plus cover sneed er tot 54% af. Gemeten over de 20 hero's: 14
   opgeschaald, 17 onder de 95% zichtbaar, negen op 46%.

   width:auto laat de browser op de NATUURLIJKE maat beginnen; max-width en
   max-height begrenzen dan zonder te snijden, want zonder cover schaalt de
   browser het hele kader mee. Zie DESIGN.md §4. */
.case-hero-media img {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 74vh;
  margin-inline: auto;
  border-radius: 4px;
}

/* Staand of vierkant beeld draagt de TWEEDE ZONE (DESIGN.md §6b) in plaats van
   een band eronder half leeg te laten. Dat is 14 van de 20 cases, dus dit is de
   hoofdvorm en niet de uitzondering. Het dossier zakt onder de kop mee. */
.case-hero.is-naast .case-hero-grid {
  align-items: start;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
}
.case-hero.is-naast .case-hero-media { margin-top: 0; }
.case-hero.is-naast .case-hero-media img { max-height: 76vh; }
.case-hero.is-naast .case-dossier { margin-top: clamp(28px, 4vw, 44px); }

/* Onder 1000px klapt het naar een kolom, zoals elk twee-zone-raster op deze
   site. Dit MOET hier staan: de bestaande media query verderop richt zich op
   `.case-hero-grid` (specificiteit 0,1,0) en verliest van de regel hierboven
   (0,3,1), dus zonder deze override bleef de hero tweekoloms tot 0px. Gemeten op
   390px zonder deze regel: het beeld werd 143px breed en het dossier wrapte op
   vier regels. */
@media (max-width: 1000px) {
  .case-hero.is-naast .case-hero-grid { grid-template-columns: 1fr; }
  .case-hero.is-naast .case-hero-media img { max-height: 62vh; }
}

/* --- de body (paper) --- */

.case-body {
  background: var(--paper);
  color: var(--ink);
  padding: clamp(56px, 7vw, 104px) 0;
}

.case-body-inner {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 2fr);
  gap: clamp(30px, 5vw, 76px);
  align-items: start;
}
/* De stroom staat EERST in de DOM (tabvolgorde en mobiele leesvolgorde) en
   wordt hier naar rechts geplaatst. */
.case-flow { grid-column: 2; grid-row: 1; }
.case-rail {
  grid-column: 1;
  grid-row: 1;
  position: sticky;
  top: calc(var(--nav-h) + 26px);
  align-self: start;
}

.case-block + .case-block { margin-top: clamp(38px, 5vw, 64px); }

/* De sectiekop is een mono-label met de rode punt: het kicker-patroon van §4.
   Geen display-kop, want deze pagina heeft er al een in de hero en vier
   statement-koppen op een rij zouden de brief wegdrukken. */
.case-h {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 clamp(14px, 1.8vw, 20px);
  color: var(--grey-2);
  font-weight: 500;
}
.case-h .dot {
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--red);
  flex: none;
}

.case-prose p {
  margin: 0 0 1em;
  max-width: 62ch;
  font-size: clamp(1rem, 1.3vw, 1.1rem);
  line-height: 1.62;
}
.case-prose p:last-child { margin-bottom: 0; }

.case-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
}
.case-list li {
  position: relative;
  padding-left: 22px;
  max-width: 66ch;
  line-height: 1.52;
  border-bottom: 1px solid var(--line-k);
  padding-bottom: 10px;
}
.case-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 7px;
  height: 1px;
  background: var(--red-deep);
}
.case-list li:last-child { border-bottom: 0; }

/* De clippings. Elk beeld op zijn eigen verhouding, in een raster dat zich vult
   naar wat er is: negen bij FutureEnergy, een bij de meeste. */
.case-shots {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* auto-FIT en niet auto-fill. auto-fill houdt lege kolommen aan, dus een enkele
     clipping vulde een derde van de kolom: gemeten stond een bron van 2000x1333
     op 228px (0,11x) en een diagram van 2048x771 op 228x86, onleesbaar. auto-fit
     klapt de lege tracks dicht en 1fr verdeelt de ruimte over wat er staat.
     De BOVENGRENS per cel staat inline op de li en komt uit de asset-metadata,
     want zonder die grens is "vul de kolom" een opschaalregel: gemeten blies dat
     een knipsel van 235px op naar 4,8x. Zie DESIGN.md §4. */
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: clamp(16px, 2vw, 26px);
  align-items: start;
  justify-items: start;
}

/* De gallery over de VOLLE BREEDTE wanneer het materiaal die draagt
   (imageFit.besteplaatsing, berekend op buildmoment). Dit is een eigen band
   NAAST het twee-zone-raster en geen tweede rasterrij: een sticky rasteritem
   wordt niet door zijn rij begrensd, en de rail liep gemeten 153px over de
   gallery heen. De reden staat voluit in CaseBody.astro. */
.case-shots-band { margin-top: clamp(38px, 5vw, 64px); }
.case-shot img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 3px;
  /* De huisbehandeling: grijstinten die bij hover oplossen, zoals .case-scan.
     Zo wordt de zwakke bronresolutie een bewuste vorm (ontwerp §2.3). */
  filter: grayscale(1) contrast(1.04);
  transition: filter 0.45s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .case-shot img:hover { filter: grayscale(0) contrast(1); }
}

/* --- de rail --- */

.case-metric {
  border-top: 2px solid var(--ink);
  padding-top: 12px;
  margin-bottom: clamp(26px, 3.4vw, 38px);
}
.case-metric-fig {
  display: block;
  font-stretch: 63%;
  font-weight: 840;
  letter-spacing: 0.002em;
  line-height: 0.98;
  font-size: clamp(2.4rem, 4.4vw, 3.6rem);
}
.case-metric-lab {
  display: block;
  color: var(--grey-2);
  margin-top: 8px;
  max-width: 22ch;
}

.case-rail-block { margin-bottom: clamp(22px, 3vw, 30px); }
.case-rail-h {
  color: var(--grey-2);
  font-weight: 500;
  margin: 0 0 10px;
}
.case-rail-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 2px;
}
.case-rail-list a {
  display: block;
  /* WCAG 2.5.8 vraagt 24px voor een inline link in een tekstblok; hier 25px,
     dezelfde maat als de rail op een persoonspagina. */
  padding: 5px 0;
  min-height: 25px;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--line-k);
  transition: color 0.3s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .case-rail-list a:hover { color: var(--red-deep); }
}

.case-rail-back { margin: 0; }
.case-back {
  display: inline-flex;
  align-items: center;
  /* 44px tikdoel (§8). */
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid var(--line-k);
  border-radius: 999px;
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: 1.00rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: background 0.3s var(--ease-out), color 0.3s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .case-back:hover { background: var(--ink); color: var(--paper); }
}

@media (max-width: 1000px) {
  .case-hero-grid,
  .case-body-inner {
    grid-template-columns: 1fr;
  }
  /* Een kolom: de DOM-orde geldt, dus de stroom staat boven en de rail eronder.
     Het kopcijfer hoort dan juist wel vooraan, want het is de samenvatting; het
     verhuist naar de stroom door de rail-grid-rij te laten vallen. */
  .case-flow { grid-column: 1; grid-row: 2; }
  .case-rail {
    grid-column: 1;
    grid-row: 1;
    position: static;
    margin-bottom: clamp(26px, 4vw, 40px);
  }
  .case-hero-media img { max-height: 62vh; }
}

/* ============================================================
   5. Het beeld op ware grootte (ronde 5, taak 5)
   ============================================================ */

/* HET ANKER IS BLOCK, en dat is geen nettigheid. Een inline <a> om een <img>
   heen zet baseline-ruimte onder het beeld en verschuift daarmee elke cel van
   de gallery en de hero-band. De maten die taak 2 t/m 4 hebben vastgezet zijn
   precies wat de poort meet, dus dit anker mag er niets aan veranderen. */
.beeld-open {
  display: block;
  text-decoration: none;
  color: inherit;
}
/* Alleen wanneer het script draait wijst de cursor op vergroten. Zonder JS is
   het een gewone link naar het bestand, en dan is zoom-in een belofte die de
   pagina niet doet. */
html.heeft-lichtbak .beeld-open { cursor: zoom-in; }
/* Focus op ink (de hero) en op paper (de gallery): dezelfde twee roden als de
   rest van de site, want --red haalt op paper maar 3,56:1 (DESIGN.md §6c). */
.case-hero-media .beeld-open:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 3px;
}
.case-shot .beeld-open:focus-visible {
  outline: 2px solid var(--red-deep);
  outline-offset: 3px;
}

/* De lichtbak zelf. GEEN display in deze regel: een <dialog> is dicht
   display:none, en wie hier `display: grid` neerzet laat de overlay permanent
   openstaan over de hele pagina. Daarom staat de display op [open]. */
.lb {
  position: fixed;
  inset: 0;
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: clamp(16px, 3vw, 40px);
  border: 0;
  background: transparent;
  overflow: hidden;
}
/* FLEX EN GEEN GRID, en dat is een gemeten verschil en geen smaak. Met
   `display: grid; place-items: center` zit het beeld in een auto-hoge rijtrack,
   en een percentage-max-height tegen een auto-hoge parent is circulair: de
   browser negeert hem. Gemeten op 1440x900: een bron van 801x1024 werd 801x1024
   getoond en liep 204px onder de vensterrand uit, zonder scrollmogelijkheid,
   want de dialog staat op overflow:hidden. Precies de klacht die deze taak moest
   oplossen. Flex geeft het beeld een containing block met een definiete hoogte
   (de dialog is fixed inset:0), dus daar werkt max-height wel. Dit is bovendien
   wat de bestaande video-modal doet (styles.css r.1623). */
.lb[open] {
  display: flex;
  align-items: center;
  justify-content: center;
}
/* De token en niet een nieuwe rgba: opacity op de backdrop is een eigen laag,
   dus dit maakt alleen de achtergrond doorzichtig (DESIGN.md §1). Dichter dan
   de 0,92 van de video-modal: op de opname van 0,94 was de paginatekst achter
   het beeld nog leesbaar, en bij een lichtbak is het beeld de hele inhoud. */
.lb::backdrop {
  background: var(--ink);
  opacity: 0.97;
}

/* NOOIT OPGESCHAALD, ook hier niet. width/height auto laat de browser op de
   natuurlijke maat beginnen (die staat als attribuut op het element), max-width
   en max-height begrenzen zonder te snijden. Dezelfde regel als in de pagina,
   en dat is precies de bedoeling: dit is het beeld, niet een tweede weergave. */
.lb-img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  border-radius: 4px;
}

.lb-close {
  position: absolute;
  top: clamp(12px, 2vw, 24px);
  right: clamp(12px, 2vw, 24px);
  z-index: 1;
  background: var(--ink-3);
}

/* De overgang volgt de video-modal uit script.js r.797: autoAlpha in 0,3s. Bij
   prefers-reduced-motion draait er niets, want de hele blok staat achter
   no-preference in plaats van dat hij hem terugdraait. */
@media (prefers-reduced-motion: no-preference) {
  .lb[open] { animation: lb-in 0.3s var(--ease-out); }
  .lb[open]::backdrop { animation: lb-bg 0.3s var(--ease-out); }
}
@keyframes lb-in {
  from { opacity: 0; transform: scale(0.985); }
}
@keyframes lb-bg {
  from { opacity: 0; }
}

/* De video van een campagne. Alleen zichtbaar als er een videoUrl staat: een
   still van een speler zonder speler erachter is het defect dat deze ronde
   vond, niet de oplossing ervan. Zie de noot in CaseBody.astro over waarom dit
   een link is en geen ingebedde speler. */
.case-video {
  display: inline-block;
  max-width: min(100%, 720px);
  text-decoration: none;
  color: inherit;
}
.case-video img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 3px;
}
.case-video-lab {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  /* 44px tikdoel (§8), zoals .case-back. */
  min-height: 44px;
  margin-top: 12px;
  padding: 0 18px;
  border: 1px solid var(--line-k);
  border-radius: 999px;
  color: var(--ink);
  transition: background 0.3s var(--ease-out), color 0.3s var(--ease-out);
}
.case-video-lab::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--red);
  flex: none;
}
@media (hover: hover) and (pointer: fine) {
  .case-video:hover .case-video-lab { background: var(--ink); color: var(--paper); }
}
.case-video:focus-visible {
  outline: 2px solid var(--red-deep);
  outline-offset: 3px;
}

/* ============================================================
   5. Het work-blok op een dienstpagina (ronde 5 taak 14)
   ============================================================ */

/* De kruislink heen: elke dienstpagina toont de cases die deze dienst gebruikt
   hebben. Er staat hier bijna geen CSS, en dat is het punt: het blok gebruikt
   .work-ledger-inner, .work-rail, .work-rows en .work-row uit dit bestand, plus
   .case-back voor de knop. Alle maten, de rasterindeling, de drie breekpunten en
   het 44px-tikdoel gelden daarmee automatisch. Een tweede kopie van die
   grammatica in services.css zou stil verouderen, en dat is precies hoe de
   §6b-fout twee rondes op rij ontstond.

   PAPER-2 EN NIET PAPER, want de sectie erboven (.service-body) is al paper en
   twee gelijk gekleurde banden lezen als een sectie. Gemeten contrast op
   #eceae4: --grey-2 4,87:1 en --red-deep 4,79:1, dus de labels en het
   scheidingsteken uit de rij blijven boven de 4,5:1 van §8. Op --paper zijn die
   5,38 en 5,28. Dit is de eerste sectie van de site die --paper-2 als
   achtergrond gebruikt; de token stond in styles.css r.11 en werd verder alleen
   als vlak achter een clipping ingezet.

   Gevolg dat je moet kennen: .work-clip.has-shot zet ook --paper-2, dus het
   vlakje achter een clipping valt hier weg tegen de sectie. Dat is goed. Dat
   vlak bestaat om een staande clip een kader te geven op --paper; op --paper-2
   zou het een onzichtbare rechthoek zijn. */
.svc-work {
  background: var(--paper-2);
  color: var(--ink);
  padding: clamp(56px, 7vw, 96px) 0;
}

/* De rail draagt alleen de kicker en de kop; teller en knop staan onder de
   rijen (.svc-work-foot). Twee eerdere vormen zijn met check-page-floor.mjs
   verworpen en de metingen staan in ServiceRelatedWork.astro: de rail met
   teller en knop erin werd 280px terwijl een enkele rij 165px is (secties 45%
   en 56%), en volle-breedte rijen maakten het erger omdat de klantnaam niet
   meerekt (media-pr 81% -> 70%).

   Deze override haalt de knop en de teller uit de rail-hoogte, meer niet. De
   maat van .work-rail .section-title en het plakken erven mee van .work-rail. */
.svc-work-rail .section-title { margin-bottom: 0; }

/* De voet: knop links, teller aan de rechterrand van de stroomkolom. Die
   rechterrand is de rand van de wrap, dus deze band reikt even ver als een rij
   en houdt de sectie op breedte, ook bij een lijst van een. */
.svc-work-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px clamp(16px, 2vw, 28px);
  margin-top: clamp(22px, 2.6vw, 32px);
}
.svc-work-count {
  color: var(--grey-2);
  margin: 0;
  text-align: right;
}
