/* ══════════════════════════════════════════════════════════════════════
   THEMA — het ontwerpsysteem van Frontrun.

   Dit blad wordt NA de eigen stijl van elk scherm geladen en gebruikt
   dezelfde selectoren. De laadvolgorde is het enige wat het werk doet;
   er staat vrijwel nergens !important. Daardoor kan het hele ontwerp hier
   wonen zonder dat er in twaalf bestanden geknipt hoeft te worden, en
   zonder dat er één klassenaam, één element of één functie verandert.

   ── waar dit blad vandaan komt ──────────────────────────────────────

   Het begon als palet-override: elk scherm droeg zijn eigen kamerkleur,
   en die zijn hier vervangen door twee paletten. Donker is de boorvloer
   (warm bijna-zwart, amber), licht is de slijperij (noorderlicht,
   grafiet). De kamers bleven bestaan als indeling en als naam boven het
   scherm — alleen niet meer als kleur.

   Nu draagt het meer. Het systeem was technisch netjes maar visueel
   plat: één laag, één rand, één schaduw. Wat erbij komt is diepte, en
   die diepte is niet decoratie maar de metafoor zelf.

   ── het dragende idee: van ruw naar geslepen ────────────────────────

   De vier kamers zijn een keten: boren, wassen, slijpen, etaleren. Dat
   verloop zit nu in de vorm. Een kaart op de boorvloer heeft 3px hoeken
   en 3,8% korrel; in de etalage 12px hoeken en nul korrel. Niemand ziet
   dat per scherm. Het werkt alleen cumulatief, over een sessie. Als je
   het ziet is het te veel — daarom zijn de sprongen zo klein.

   ── waarom grafiet als accent in licht ──────────────────────────────

   Op een lichte ondergrond beoordeel je kleur en stof, en dan mag de
   interface zelf geen kleur bijdragen. Amber blijft wél bestaan, maar
   alleen in zijn ene betekenis: waarde. Statuskleuren (goed, fout, let
   op, wacht) verschuiven niet.

   Gevolg dat je makkelijk over het hoofd ziet: een "gloed" in grafiet
   bestaat niet — grijs licht is geen licht. Daarom staat er nergens in
   dit blad een glow. De amberstip krijgt in plaats daarvan een specular
   puntje van 1,2px linksboven: een steentje dat licht vangt, geen LED.
   Dat werkt in beide thema's zonder truc.

   ── de volgorde in dit bestand ──────────────────────────────────────

    1. tokens — donker
    2. tokens — licht (media en expliciet)
    3. de kamerlaag: het dichtheidsverloop
    4. de korrellaag
    5. schermwissel
    6. de kaartlaag: één rand die verloopt
    7. tabellen en het cursorlicht
    8. meters, banen en sporen
    9. knoppen, pillen, chips
   10. lege staten en laadstaten
   11. drijvende dingen
   12. de zijrail en de bovenbalk
   13. de boorkern-strip en de kernlade
   14. de kamers in de vorm
   15. getalrollen
   16. eigendom van beweging (.mv)
   17. minder beweging
   18. projectkiezer (bestond al)
   ══════════════════════════════════════════════════════════════════ */

/* ══ 1. DONKER — de boorvloer ═══════════════════════════════════════ */
:root,
:root[data-theme="dark"] {
  color-scheme: dark;

  --vlak-diep:#131110; --vlak:#1B1815; --vlak-op:#232019;
  --vlak-hoog:#2C281F; --vlak-put:#100E0D;

  --inkt:#F2EFE8; --inkt-zacht:#ADA79C; --inkt-vaag:#968F83; --inkt-om:#16120B;
  --rand-zacht:#2A251F; --rand:#362F27; --rand-sterk:#4A4137;

  --accent:#F0A93B; --accent-hoog:#FFC469; --accent-diep:#B87A1C;
  --accent-zacht:#F0A93B26; --accent-inkt:#1A1206;

  --goed:#86BE84; --goed-zacht:#86BE8422;
  --fout:#E2735F; --fout-zacht:#E2735F22;
  --let:#E5B94E;  --let-zacht:#E5B94E1F;
  --koel:#93B8CE; --koel-zacht:#93B8CE22;
  --klem:#8B7CE0; --klem-zacht:#8B7CE022;

  /* de waardekleur: hier zit iets, hier zát iets in */
  --amber:#F0A93B;

  /* de lichtbak blijft neutraal grijs, ook in donker. Dat vlak ligt
     onder beeld, en een warme zweem eronder liegt over de kleur van
     het kledingstuk. Dit is het enige dat níet meeschakelt. */
  --lichtbak:#313131; --lichtbak-diep:#262626;
  --lichtbak-rand:#454545; --passepartout:#3C3C3C;

  /* ── hoogte ──────────────────────────────────────────────────────
     Twee offsets per trede: één korte harde voor het contact met de
     ondergrond, één lange zachte voor de hoogte. Dat is wat één
     `0 10px 30px -8px` niet kan — die zweeft zonder ergens te staan.
     De verhouding donker : licht is ongeveer 5 : 1 in alfa, bij
     dezelfde geometrie. Meer wit op licht is onzichtbaar; meer zwart
     op donker is een vlek. */
  --hoog-1: 0 1px 2px rgb(0 0 0 / .30), 0 0 0 1px rgb(0 0 0 / .16);
  --hoog-2: 0 2px 4px rgb(0 0 0 / .26), 0 8px 20px -8px rgb(0 0 0 / .46);
  --hoog-3: 0 4px 8px rgb(0 0 0 / .30), 0 18px 44px -14px rgb(0 0 0 / .62);

  --schaduw-op:inset 0 1px 0 rgb(255 255 255 / .045);
  --schaduw-zweef:var(--hoog-3);      /* de oude naam blijft werken */
  --ring:0 0 0 3px var(--accent-zacht);

  /* ── glans ───────────────────────────────────────────────────────
     In donker is glans wit. In licht is glans een schaduw — zie het
     lichte blok. Een token dat die omslag niet maakt, breekt. */
  --glans: rgb(255 255 255 / .055);
  --glans-sterk: rgb(255 255 255 / .11);
  --glans-rij: rgb(255 255 255 / .042);

  /* ── de rand die verloopt ────────────────────────────────────────
     Van 12% inkt linksboven naar --rand-zacht rechtsonder. Dat leest
     als een gebogen oppervlak in plaats van een uitgeknipte rechthoek.
     Toegepast via background-clip, niet border-image — die negeert
     border-radius. */
  --rand-glans: linear-gradient(158deg,
    color-mix(in srgb, var(--inkt) 11%, transparent) 0%,
    var(--rand) 46%, var(--rand-zacht) 100%);
  --rand-glans-op: linear-gradient(158deg,
    color-mix(in srgb, var(--inkt) 20%, transparent) 0%,
    var(--rand-sterk) 46%, var(--rand) 100%);
  --rand-glans-aan: linear-gradient(158deg,
    color-mix(in srgb, var(--accent) 72%, transparent) 0%,
    color-mix(in srgb, var(--accent) 38%, transparent) 60%,
    color-mix(in srgb, var(--accent) 22%, transparent) 100%);

  /* ── grafieken hebben hun eigen laag ─────────────────────────────
     --vlak-put droeg drie betekenissen tegelijk: het spoor van een
     meter, de achtergrond van een invoerveld, en de achtergrond van
     een uitklaprij. Verander er één en er breekt iets elders. */
  --graf-spoor: #171412;
  --graf-raster: color-mix(in srgb, var(--inkt) 9%, transparent);
  --graf-lijn: var(--accent);
  --graf-kruis: color-mix(in srgb, var(--inkt) 34%, transparent);
  --graf-leeg: repeating-linear-gradient(90deg,
    var(--rand-sterk) 0 2px, transparent 2px 6px);

  /* ── korrel ──────────────────────────────────────────────────────
     Grijswaarde, nooit amber-getint. Eén vaste laag over het hele
     document — ruis per kaart is een paint-ramp bij tweehonderd
     tegels. De waarde wordt door de kamerlaag hieronder verschoven. */
  --korrel: .022;
  --korrel-meng: overlay;

  /* de ader die door een lege staat loopt: één hoofdader, twee zijtakken */
  --ader: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 200" preserveAspectRatio="none"><path d="M-10 168 C 60 150 88 120 132 112 S 214 104 258 78 S 330 44 412 30" fill="none" stroke="%23fff" stroke-width="1.4" stroke-linecap="round"/><path d="M132 112 C 150 128 168 140 176 162" fill="none" stroke="%23fff" stroke-width="1" stroke-linecap="round"/><path d="M258 78 C 276 70 288 56 292 38" fill="none" stroke="%23fff" stroke-width="1" stroke-linecap="round"/></svg>');

  /* ── maat en tijd ────────────────────────────────────────────────
     --soepel is een expo-out: uitstekend voor binnenkomst, ongeschikt
     voor vertrek. Iets dat traag begint met wegvallen leest als
     aarzeling. Daarvoor is --weg. */
  --rond-xl: 16px;
  --rond-kaart: 8px;
  --duur-0: 80ms;
  --duur-4: 380ms;
  --duur-5: 560ms;
  --weg: cubic-bezier(.4, 0, 1, 1);
  --gelijk: linear;
  --spot-rij: 420px;
}

/* ══ 2. LICHT — de slijperij ════════════════════════════════════════ */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;

    --vlak-diep:#E8E9EA; --vlak:#F2F3F4; --vlak-op:#FBFBFC;
    --vlak-hoog:#FFFFFF; --vlak-put:#E4E6E7;

    --inkt:#16181A; --inkt-zacht:#4C5257; --inkt-vaag:#5F666A; --inkt-om:#FFFFFF;
    --rand-zacht:#DEE0E2; --rand:#CBCFD2; --rand-sterk:#A8AEB3;

    --accent:#2F3A40; --accent-hoog:#1E262B; --accent-diep:#646E74;
    --accent-zacht:#2F3A401A; --accent-inkt:#FFFFFF;

    --goed:#356A38; --goed-zacht:#356A3818;
    --fout:#A63B29; --fout-zacht:#A63B2918;
    --let:#7E5A0E;  --let-zacht:#7E5A0E18;
    --koel:#3D6B87; --koel-zacht:#3D6B8718;
    --klem:#5B4FA8; --klem-zacht:#5B4FA818;

    --amber:#875609;

    --lichtbak:#C9C9C7; --lichtbak-diep:#B9B9B7;
    --lichtbak-rand:#A8A8A6; --passepartout:#FBFAF8;

    --hoog-1: 0 1px 2px rgb(30 40 48 / .06), 0 0 0 1px rgb(30 40 48 / .04);
    --hoog-2: 0 2px 4px rgb(30 40 48 / .07), 0 8px 20px -8px rgb(30 40 48 / .13);
    --hoog-3: 0 4px 8px rgb(30 40 48 / .08), 0 18px 44px -14px rgb(30 40 48 / .20);

    --schaduw-op:inset 0 1px 0 rgb(255 255 255 / .7);
    --schaduw-zweef:var(--hoog-3);
    --ring:0 0 0 3px var(--accent-zacht);

    /* de omslag: glans is hier een schaduw, geen licht */
    --glans: rgb(255 255 255 / .72);
    --glans-sterk: rgb(255 255 255 / .95);
    --glans-rij: rgb(30 40 48 / .035);

    --rand-glans: linear-gradient(158deg,
      color-mix(in srgb, var(--inkt) 14%, transparent) 0%,
      var(--rand) 46%, var(--rand-zacht) 100%);
    --rand-glans-op: linear-gradient(158deg,
      color-mix(in srgb, var(--inkt) 26%, transparent) 0%,
      var(--rand-sterk) 46%, var(--rand) 100%);
    --rand-glans-aan: linear-gradient(158deg,
      color-mix(in srgb, var(--accent) 62%, transparent) 0%,
      color-mix(in srgb, var(--accent) 32%, transparent) 60%,
      color-mix(in srgb, var(--accent) 18%, transparent) 100%);

    --graf-spoor: #DFE2E4;
    --graf-raster: color-mix(in srgb, var(--inkt) 12%, transparent);
    --graf-kruis: color-mix(in srgb, var(--inkt) 40%, transparent);

    /* korrel op een lichte ondergrond leest als vuil of als een
       slechte scan. Een derde van de donkere waarde, en vermenigvuldigd
       in plaats van overlay — anders wordt de ruis wit. */
    --korrel: .008;
    --korrel-meng: multiply;
  }
}

:root[data-theme="light"] {
  color-scheme: light;

  --vlak-diep:#E8E9EA; --vlak:#F2F3F4; --vlak-op:#FBFBFC;
  --vlak-hoog:#FFFFFF; --vlak-put:#E4E6E7;

  --inkt:#16181A; --inkt-zacht:#4C5257; --inkt-vaag:#5F666A; --inkt-om:#FFFFFF;
  --rand-zacht:#DEE0E2; --rand:#CBCFD2; --rand-sterk:#A8AEB3;

  --accent:#2F3A40; --accent-hoog:#1E262B; --accent-diep:#646E74;
  --accent-zacht:#2F3A401A; --accent-inkt:#FFFFFF;

  --goed:#356A38; --goed-zacht:#356A3818;
  --fout:#A63B29; --fout-zacht:#A63B2918;
  --let:#7E5A0E;  --let-zacht:#7E5A0E18;
  --koel:#3D6B87; --koel-zacht:#3D6B8718;
  --klem:#5B4FA8; --klem-zacht:#5B4FA818;

  --amber:#875609;

  --lichtbak:#C9C9C7; --lichtbak-diep:#B9B9B7;
  --lichtbak-rand:#A8A8A6; --passepartout:#FBFAF8;

  --hoog-1: 0 1px 2px rgb(30 40 48 / .06), 0 0 0 1px rgb(30 40 48 / .04);
  --hoog-2: 0 2px 4px rgb(30 40 48 / .07), 0 8px 20px -8px rgb(30 40 48 / .13);
  --hoog-3: 0 4px 8px rgb(30 40 48 / .08), 0 18px 44px -14px rgb(30 40 48 / .20);

  --schaduw-op:inset 0 1px 0 rgb(255 255 255 / .7);
  --schaduw-zweef:var(--hoog-3);
  --ring:0 0 0 3px var(--accent-zacht);

  --glans: rgb(255 255 255 / .72);
  --glans-sterk: rgb(255 255 255 / .95);
  --glans-rij: rgb(30 40 48 / .035);

  --rand-glans: linear-gradient(158deg,
    color-mix(in srgb, var(--inkt) 14%, transparent) 0%,
    var(--rand) 46%, var(--rand-zacht) 100%);
  --rand-glans-op: linear-gradient(158deg,
    color-mix(in srgb, var(--inkt) 26%, transparent) 0%,
    var(--rand-sterk) 46%, var(--rand) 100%);
  --rand-glans-aan: linear-gradient(158deg,
    color-mix(in srgb, var(--accent) 62%, transparent) 0%,
    color-mix(in srgb, var(--accent) 32%, transparent) 60%,
    color-mix(in srgb, var(--accent) 18%, transparent) 100%);

  --graf-spoor: #DFE2E4;
  --graf-raster: color-mix(in srgb, var(--inkt) 12%, transparent);
  --graf-kruis: color-mix(in srgb, var(--inkt) 40%, transparent);

  --korrel: .008;
  --korrel-meng: multiply;
}

/* ══ 3. DE KAMERLAAG — het dichtheidsverloop ════════════════════════
   Gezet op <html> door kern.js. Een kaart wordt hoekiger en korreliger
   naarmate je verder terug in de keten staat: ruw materiaal links,
   geslepen steen rechts. De sprongen zijn 3 → 5 → 8 → 12px en
   3,8% → 2,2% → 0,8% → 0%.

   Schermen zonder kamer (kansen, vloot, instellingen) houden de
   standaardwaarde uit het tokenblok. Dat is opzet: die schermen staan
   naast de keten, niet erin. */
:root[data-kamer="boorvloer"] { --korrel:.038; --rond-kaart:3px }
:root[data-kamer="wasplaats"] { --korrel:.022; --rond-kaart:5px }
:root[data-kamer="slijperij"] { --korrel:.008; --rond-kaart:8px }
:root[data-kamer="etalage"]   { --korrel:0;    --rond-kaart:12px }

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"])[data-kamer="boorvloer"] { --korrel:.013 }
  :root:not([data-theme="dark"])[data-kamer="wasplaats"] { --korrel:.008 }
  :root:not([data-theme="dark"])[data-kamer="slijperij"] { --korrel:.003 }
}
:root[data-theme="light"][data-kamer="boorvloer"] { --korrel:.013 }
:root[data-theme="light"][data-kamer="wasplaats"] { --korrel:.008 }
:root[data-theme="light"][data-kamer="slijperij"] { --korrel:.003 }

/* ══ 4. DE KORRELLAAG ═══════════════════════════════════════════════
   Eén vaste laag, position:fixed, onder alle tekst en boven niets wat
   data draagt. --vlak-diep is een groot volstrekt egaal vlak; op een
   groot scherm zie je banding in elk verloop dat je erop legt. Een paar
   procent ruis dooft dat, en geeft het bijna-zwart korrel.

   Fixed en niet meescrollend: bewegende korrel is misselijkmakend en
   kost een herteking per frame. */
body::before {
  content:""; position:fixed; inset:0; z-index:0; pointer-events:none;
  opacity: var(--korrel);
  mix-blend-mode: var(--korrel-meng);
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="180" height="180"><filter id="k"><feTurbulence type="fractalNoise" baseFrequency="0.82" numOctaves="3" stitchTiles="stitch"/><feColorMatrix type="saturate" values="0"/></filter><rect width="180" height="180" filter="url(%23k)"/></svg>');
  background-size: 180px 180px;
}

/* ══ 5. SCHERMWISSEL ════════════════════════════════════════════════
   Elf losse HTML-bestanden voelden als elf websites. De zijrail en de
   bovenbalk staan op elk scherm op dezelfde plek; als die blijven staan
   terwijl alleen het podium wisselt, wordt het één applicatie.

   Kort gehouden (180ms). Een scherm als maken.html is zwaar; de browser
   houdt de oude pagina vast tot de nieuwe kan tekenen, en een lange
   transitie leest dan als vastlopen. */
@view-transition { navigation: auto }

.rail   { view-transition-name: rail }
.balk   { view-transition-name: balk }
.kern   { view-transition-name: kern }
.podium { view-transition-name: podium }

::view-transition-old(rail),
::view-transition-new(rail),
::view-transition-old(balk),
::view-transition-new(balk),
::view-transition-old(kern),
::view-transition-new(kern) { animation: none; mix-blend-mode: normal }

::view-transition-old(podium) { animation: podiumuit 120ms var(--weg) both }
::view-transition-new(podium) { animation: podiumin  180ms var(--soepel) both }
@keyframes podiumuit { to { opacity:0 } }
@keyframes podiumin  { from { opacity:0; transform:translateY(4px) } }

/* ══ 6. DE KAARTLAAG — één rand die verloopt ════════════════════════
   De belangrijkste verandering in dit blad, en de goedkoopste: één
   regelblok dat elf schermen raakt zonder één HTML-wijziging.

   Techniek: twee achtergrondlagen. De eerste is het vlak zelf, geknipt
   op de padding-box. De tweede is het verloop, geknipt op de border-box.
   De rand zelf is doorzichtig, dus het verloop komt eruit als een
   haarlijn die met de hoek meebuigt. border-image kan dit niet — die
   negeert border-radius.

   --kaartvlak is het aanknopingspunt: een kaart met een andere vulling
   (ingedrukt, geselecteerd) zet alleen dat token om en houdt de rand.

   Let op de hover: die verandert de rand, niet de border-color. Zou een
   scherm bij hover een echte border-color zetten, dan schildert die
   over het verloop heen — vandaar dat de hover hier expliciet op
   transparent blijft.

   .paneel staat hier NIET in, en dat is geen vergetelheid. In kiezen,
   maken, vinden-lijsten, winkelkeuze en platform-demo is .paneel de
   <section> van een hele tabbladinhoud — vijf schermen waar het element
   alleen `[hidden]{display:none}` droeg en verder geen vlak had. Als
   die de kaartlaag krijgt, ligt er een ondoorzichtige plaat van 1142 bij
   2710 met een schaduw eromheen onder álles, en liggen de echte kaarten
   erin op precies dezelfde toon: het verschil tussen kaart en ondergrond
   valt weg. Een paneel is een indeling, geen kaart. */
.kaart, .tegel, .kand, .klaarkaart, .winkelkop,
.fase, .loep, .venster, .melding, .afdruk {
  --kaartvlak: var(--vlak-op);
  border-color: transparent;
  border-radius: var(--rond-kaart);
  background-image:
    linear-gradient(var(--kaartvlak), var(--kaartvlak)),
    var(--rand-glans);
  background-origin: border-box;
  background-clip: padding-box, border-box;
  background-repeat: no-repeat;
  box-shadow: var(--hoog-1);
}

.kaart:hover, .tegel:hover, .kand:hover,
.klaarkaart:hover, .fase:hover, .afdruk:hover {
  border-color: transparent;
  background-image:
    linear-gradient(var(--kaartvlak), var(--kaartvlak)),
    var(--rand-glans-op);
}

/* Aangewezen, gekozen, in de cursor: de rand wordt amber in plaats van
   dat er een gekleurd vlak onder schuift. Kleur op de rand kost geen
   leesbaarheid van de inhoud. */
.tegel[aria-pressed="true"], .tegel[data-cursor],
.fase[aria-pressed="true"], .kaart[aria-current="true"] {
  border-color: transparent;
  background-image:
    linear-gradient(var(--kaartvlak), var(--kaartvlak)),
    var(--rand-glans-aan);
}
.fase[aria-pressed="true"] { --kaartvlak: var(--accent-zacht) }

/* Twee standen die hun betekenis in de rand dragen en die de kaartlaag
   anders wegschildert. Afgekeurd en afgewezen zijn de enige plekken waar
   de rand méér zegt dan "hier houdt de kaart op". */
.afdruk--afgekeurd {
  background-image:
    linear-gradient(var(--kaartvlak), var(--kaartvlak)),
    linear-gradient(color-mix(in srgb, var(--fout) 45%, transparent),
                    color-mix(in srgb, var(--fout) 45%, transparent));
}
.tegel[data-stand="afgewezen"] {
  background-image: linear-gradient(var(--kaartvlak), var(--kaartvlak));
  background-clip: padding-box;
  border-color: var(--rand-sterk);
}

/* Drijvende dingen staan hoger en krijgen bovenop een lichtlijn. */
/* .loep zweeft; .venster is in de slijperij het werkvlak zelf en staat
   gewoon in de stroom. Dialooghoogte op iets dat nergens boven ligt
   maakt de pagina wattig. */
.loep    { box-shadow: var(--hoog-3), inset 0 1px 0 var(--glans) }
.venster { box-shadow: var(--hoog-1) }
.melding        { box-shadow: var(--hoog-2), inset 0 1px 0 var(--glans) }

/* Een melding zweeft, en wat zweeft ligt op --vlak-hoog. maken.html en
   slijperij.html zetten dat zelf al zo ("zweeft, dus hoogte in plaats van
   rand"), en de kaartlaag schilderde daar --vlak-op overheen: de toast
   zakte een trede terug naar de toon van de kaarten eronder. Het token
   omzetten herstelt dat en trekt de vierde melding (wasplaats) mee naar
   dezelfde hoogte. De ingekleurde melding van instellingen.html raakt dit
   niet — die zet `background` als korte notatie en wint. */
.melding { --kaartvlak: var(--vlak-hoog) }

/* Grote drijvende panelen mogen de grovere straal. Werkschermen niet:
   16px op een kaart met 8px binnenmarge ziet eruit als een kussen.

   Daarom staat .venster hier niet meer bij: dat is in slijperij.html
   geen drijvend paneel maar het werkvlak zelf, 1142 bij 1067 in de
   stroom, met .venster__kop erin op var(--r3) var(--r4). Precies het
   kussen uit de zin hierboven. Hij volgt nu --rond-kaart, en dat is in
   de slijperij 8px. */
dialog { border-radius: var(--rond-xl) }

/* ══ 7. TABELLEN EN HET CURSORLICHT ═════════════════════════════════
   Bij twintig kolommen weet je met een vlakke hoverkleur nog steeds
   niet waar je horizontaal zit. Een lichtvlek die met de muis meeschuift
   is een tweede as informatie, en hij kost niets: beweging.js zet één
   custom property op de tbody, niet per rij.

   Het licht ligt in een ::after met pointer-events:none, dus het vangt
   geen kliks af en het staat onder de tekst. */
tbody { --mx: 50% }
tbody tr:hover {
  background-image: radial-gradient(var(--spot-rij) 140% at var(--mx) 50%,
                    var(--glans-rij), transparent 72%);
  background-repeat: no-repeat;
}

/* De sorteerpijl blijft ruimte innemen als hij weg is, anders verspringt
   de kolombreedte bij elke klik. Die vondst stond in één bestand. */
.sorteer__pijl[hidden] { display: inline-block; visibility: hidden }

/* De vervagende rand op een schuivende tabel stond hier, en is weg: CSS
   kan niet zien of een tabel daadwerkelijk overloopt, dus vervaagde hij
   ook de eerste en laatste kolom van tabellen die keurig passen. Een
   aanwijzing die net zo vaak liegt als klopt is geen aanwijzing.
   Terug te zetten zodra iets een klasse zet op `scrollWidth >
   clientWidth`. */

/* Kolomkoppen dragen het UI-font. Mono is gereserveerd voor gemeten
   waarden, en een kolomkop is geen meting. */
thead th { font-family: var(--font-ui) }

/* ══ 8. METERS, BANEN EN SPOREN ═════════════════════════════════════
   Een leeg spoor haalt tegen zijn kaart 1,3:1 in donker en 1,1:1 in
   licht. Dat is in beide gevallen te weinig om als vorm te lezen — je
   ziet geen lege balk, je ziet niets. Eén inzet-haarlijn lost dat op.
   .baan deed dit al goed; .meter en .spoor niet.

   Let op het :not(): "niets gemeten = geen balk" is een bestaande en
   juiste regel — een balk op 0% liegt over wat er gebeurt. Dit blad
   laadt later en zou die uitzondering anders overschrijven. */
.meter:not(.meter--leeg), .baan:not(.baan--leeg),
.spoor:not(.spoor--leeg), .spreiding__spoor {
  background: var(--graf-spoor);
  box-shadow: inset 0 0 0 1px var(--rand-sterk);
}
/* .ring__spoor is een SVG-cirkel: background en box-shadow landen daar
   niet. Die heeft een stroke nodig. */
.ring__spoor { stroke: var(--graf-spoor) }

/* De boorkop. Er stond al een 2px dwarsstreepje op de vulgrens van de
   dieptemeter op de boorvloer — het enige stukje mijnbouwvorm in het
   systeem dat al bestond en al iets deed. Nu draagt elke meter hem, en
   is elke balk herkenbaar als van dit systeem.

   Hij verschijnt niet op een lege of ongemeten balk: daar is geen grens
   om te markeren. Een maatverdeling op iets dat niet gemeten is, is
   precies de leugen die dit systeem bestrijdt. */
.meter > i, .baan > i, .spoor > i {
  background-image: linear-gradient(to left, var(--accent-hoog) 0 2px, transparent 2px);
}
.meter--leeg > i, .baan--leeg > i { background-image: none }


/* ══ 9. KNOPPEN, PILLEN, CHIPS ══════════════════════════════════════ */

/* Elk scherm heeft precies één handeling die er echt toe doet. Die knop
   krijgt bij hover een smalle geschuinde veeg. Als drie knoppen
   schitteren, schittert er geen — dus .knop, .knop--stil en
   .knop--klein krijgen dit niet. */
.knop--primair {
  position: relative; overflow: hidden;
  background-image: linear-gradient(105deg, transparent 38%,
    var(--glans-sterk) 50%, transparent 62%);
  background-size: 280% 100%;
  background-position: 190% 0;
  background-repeat: no-repeat;
  transition: background-position var(--duur-5) var(--soepel),
              background-color var(--duur-1) var(--soepel);
}
.knop--primair:hover { background-position: -90% 0 }

/* De keycap. Twee schaduwlagen maken een indrukbaar oppervlak; een
   dikkere onderrand maakt alleen een dikkere onderrand. Dit platform
   leunt zwaar op sneltoetsen, dus die caps zijn geen decoratie. */
.toets {
  border-bottom-width: 1px;
  box-shadow: inset 0 1px 0 var(--glans),
              0 1px 0 var(--rand-sterk),
              0 2px 0 color-mix(in srgb, var(--vlak-put) 55%, #000);
  transition: transform var(--duur-0) var(--soepel),
              box-shadow var(--duur-0) var(--soepel);
}
.toets:active, .knop:active .toets {
  transform: translateY(1px);
  box-shadow: inset 0 1px 0 var(--glans), 0 1px 0 var(--rand-sterk);
}

/* Een echte border vreet bij 11px tekst van de binnenruimte. Een
   inzet-ring niet: de pil wordt twee pixels compacter bij gelijk
   uiterlijk. In tabelcellen telt dat. */
.pil {
  border-width: 0;
  border-color: transparent;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 26%, transparent);
  background-color: color-mix(in srgb, currentColor 9%, transparent);
}
.pil--geen, .pil--vlak {
  box-shadow: inset 0 0 0 1px var(--rand);
  background-color: transparent;
}

/* ══ 10. LEGE STATEN EN LAADSTATEN ══════════════════════════════════
   Een stippelrand zegt "hier is niets". Een vervaagd raster van
   tabelregels zegt "hier komen straks rijen" — en dat is wat je wilt
   weten. De ader die er diagonaal doorheen loopt is amber: hier is nu
   niets, maar deze plek is niet dood. Dat is exact het verschil dat de
   gegevens overal al maken tussen "—" en "0".

   Eén ader, geen netwerk. Geen animatie. Nooit onder de tekst door. */
.staat {
  position: relative; overflow: hidden;
  border-style: solid; border-color: transparent;
  border-radius: var(--rond-kaart);
  background-image:
    linear-gradient(var(--vlak-op), var(--vlak-op)),
    var(--rand-glans);
  background-origin: border-box;
  background-clip: padding-box, border-box;
}
.staat::before {
  content:""; position:absolute; inset:0; pointer-events:none; z-index:0;
  background-image: repeating-linear-gradient(0deg,
    var(--rand-zacht) 0 1px, transparent 1px 34px);
  -webkit-mask-image: radial-gradient(ellipse 78% 68% at 50% 42%, #000, transparent 74%);
  mask-image: radial-gradient(ellipse 78% 68% at 50% 42%, #000, transparent 74%);
  opacity: .55;
}
.staat::after {
  content:""; position:absolute; inset:0; pointer-events:none; z-index:0;
  /* De ader is een masker, geen plaatje. Stond de kleur in de SVG, dan
     bleef hij in het lichte thema op donker-amber staan terwijl --amber
     daar naar #875609 schuift — en op bijna-wit is dat een vlek in
     plaats van een ader. Nu draagt background de kleur en knipt het
     masker de vorm. */
  background: var(--amber);
  opacity: .16;
  -webkit-mask-image: var(--ader); mask-image: var(--ader);
  -webkit-mask-size: 100% 100%; mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
.staat > * { position: relative; z-index: 1 }

/* De ader hoort niet in een foutstaat. Een kapotte plek is iets anders
   dan een lege plek. */
.staat--fout::after, .staat[data-fout]::after { display: none }

/* Het skelet houdt de vórm van wat er komt, zodat de indeling niet
   schokt bij binnenkomst. De veeg stopt zodra de gegevens er zijn — dit
   is een van de twee animaties in dit systeem die mogen herhalen, en
   alleen zolang er gewacht wordt. */
.skelet {
  background-image: linear-gradient(90deg,
    var(--graf-spoor) 0%, var(--vlak-hoog) 42%, var(--graf-spoor) 84%);
  background-size: 280% 100%;
  animation: veeg 1.4s var(--gelijk) infinite;
  border-radius: var(--rond-s);
}
@keyframes veeg { to { background-position: -180% 0 } }

/* ══ 11. DRIJVENDE DINGEN ═══════════════════════════════════════════
   backdrop-filter dwingt een eigen laag per element. Bij tweehonderd
   tegels zakt het scrollen in. Daarom staat hij alleen op wat écht
   boven iets anders zweeft — nooit op een kaart in de stroom. */
.balk, .bank {
  box-shadow: inset 0 1px 0 var(--glans);
}
.bank { box-shadow: inset 0 1px 0 var(--glans), 0 -12px 30px -18px rgb(0 0 0 / .55) }

dialog::backdrop {
  background: color-mix(in srgb, var(--vlak-put) 62%, transparent);
  backdrop-filter: blur(6px);
}

/* Hier stond een aftelstreep onder de melding, die zou tonen hoeveel
   tijd je nog hebt om terug te draaien. Weg, om twee redenen.

   .melding is niet één ding. In de wasplaats, de slijperij en maken is
   het een toast die vanzelf verdwijnt; in instellingen is het een vast
   notitieblok dat blijft staan. Een aftelbalk op dat tweede liegt over
   de tijd. En er is geen haak in de opmaak om ze uit elkaar te houden —
   het verschil zit in `position: fixed`, en daar kun je niet op
   selecteren.

   De `overflow: hidden` die de streep nodig had ging mee weg: die kon
   de focusring van een knop ín de melding afknippen.

   Terug te zetten zodra de schermen hun toasts van een eigen haak
   voorzien; dan is het een goed idee. Nu is het een halve waarheid. */
.melding { position: relative }

/* ══ 12. DE ZIJRAIL EN DE BOVENBALK ═════════════════════════════════
   De rail heeft vier groepen en veertien rijen. Een gevuld blok per
   actieve rij is zwaar; een staaf plus een lichte was leest sneller als
   "je bent hier" en laat de tekst met rust. */
.nav[aria-current="page"] {
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  position: relative;
}
.nav[aria-current="page"]::before {
  content:""; position:absolute; left:0; top:18%; bottom:18%;
  width:2px; border-radius:1px; background: var(--accent);
}

/* ── randtokens dragen geen tekst ─────────────────────────────────
   --rand-sterk is gemaakt om een vlak af te bakenen tegen een ander
   vlak, en haalt als tekstkleur 1,8:1. Drie plekken gebruikten hem als
   letterkleur: de pijltjes tussen de kamers, de scheidingspunt in de
   bronnenstrook, en de bandpijl. Allemaal klein, allemaal onleesbaar. */
.kamer__pijl, .bron__punt, .band__pijl { color: var(--inkt-vaag) }

/* Dekking op tekst die al gedempt is, dempt twee keer: --inkt-zacht op
   .7 komt uit op 2,7 tot 4,4:1. Het gedempte effect hoort in de kleur
   te zitten, niet in een tweede laag eroverheen. */
.chip__tel { opacity: 1; color: var(--inkt-vaag) }

/* Op de getinte was van een actieve rij of kamer zakt --inkt-vaag naar
   2,6:1. Daar één trede omhoog. */
.nav[aria-current="page"] .nav__tel,
.nav[aria-current="page"] .nav__tel-eigen,
.kamer[data-nu] .nav__tel { color: var(--inkt-zacht) }

/* De blokjes in de kamerstrip droegen elk hun eigen kamerkleur. Die
   kleuren bestaan niet meer, dus volgen ze nu gewoon de tekst: de kamer
   waar je bent licht op in het accent, de rest is gedempt. */
.kamer i { background: currentColor !important }

/* ── de themakiezer ─────────────────────────────────────────────────
   Eén keuzelijst voor beide assen: donker, licht in drie temperaturen,
   of volg het systeem. thema.js zet hem in de balk, op de plek van de
   oude knop.

   Die knop blijft in de DOM staan en gaat alleen uit het zicht. Elk
   scherm bindt er zelf een click-handler aan, ongeguard; verdwijnt het
   element, dan struikelt dat scherm op null.addEventListener en werkt
   daarna geen enkele knop meer op die pagina. Dit is dus geen restje
   maar een steunbalk. */
.knop--thema { min-width: 5.5rem }
#themaknop { display: none }

.kiezer--thema { min-width: 9.5rem }

/* De voortgangslijn onder de balk. Alleen op schermen die langer zijn
   dan twee schermhoogtes — beweging.js beslist dat en maakt het element
   pas dan aan. Hij loopt op een scroll-tijdlijn, dus buiten de hoofddraad. */
.balk__voortgang {
  position: absolute; left:0; right:0; bottom:-1px; height:2px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  pointer-events: none;
}

/* ══ 13. DE BOORKERN-STRIP EN DE KERNLADE ═══════════════════════════
   Het signatuurelement. De keten is 460 winkels → 12 gekozen → 240
   producten → 18 klaargezet, en dat is geen trechter: bij stap 3 gaat
   het getal omhóóg, want de eenheid wisselt. Winkels worden producten.
   Elke taps toelopende vorm zou beweren dat 240 een deelverzameling van
   12 is.

   Vandaar: vier gelijke segmenten, en een zichtbare breuk waar de
   eenheid wisselt. De segmenten zijn NIET proportioneel — 12 naast 460
   geeft een segment van 2,6% breed, en het zou bovendien beweren dat de
   vier getallen in één schaal staan.

   Geen ronding, geen glans, geen verloop binnen een segment. Een kern
   is een cilinder gesteente, geen voortgangsbalk. Hij loopt nooit vol;
   hij toont een verhouding. */
.kern {
  position: sticky; top: var(--balk, 3.25rem); z-index: 29;
  display: grid;
  /* vier gelijke segmenten, met de eenheidswissel als eigen spoor.
     Grid kent geen gap per voeg, dus de breuk moet een track zijn. */
  grid-template-columns: 1fr 1fr 3px 1fr 1fr;
  column-gap: 1px; height: 6px; width: 100%; padding: 0; border: 0;
  /* De voeg tussen de segmenten is de containerachtergrond die door de
     gap heen komt. Hij stond op --rand-zacht en haalde 1,1:1 tegen de
     segmenten — onzichtbaar, dus leunden vier segmenten volledig op
     kleur. Nu is het de paginakleur: de segmenten liggen als vier losse
     staven op de ondergrond in plaats van als één balk met naden.
     Gemeten het beste van vijf kandidaten (minimum 1,61 donker / 1,44
     licht, tegen 1,17 en 1,14 voor --rand-sterk).

     Dat haalt de 3:1 van WCAG voor grafische objecten niet, en dat is
     hier verdedigbaar: elk segment draagt zijn getal in een `title`, de
     strip draagt alle vier in zijn aria-label, en de lade zet ze eronder
     in tekst. De kleur bevestigt wat er in woorden staat; hij is niet de
     enige drager. Een strook van zes pixels kan vier niveaus niet op
     3:1 uit elkaar houden zonder een tweede kleur, en een tweede kleur
     is precies wat dit systeem niet heeft. */
  background: var(--vlak-diep);
  cursor: pointer;
}
/* Vier segmenten, één kleur, oplopende concentratie. Eerst stonden hier
   drie tokens naast elkaar — en in het donkere thema zijn --accent en
   --amber exact dezelfde waarde (#F0A93B), dus toonde de strip vier
   segmenten in twee kleuren. Segment 2 en 4 waren niet te onderscheiden.

   Dit is bovendien de betere vorm. Amber betekent waarde, en de keten
   loopt van ruw naar geslepen: hoe verder naar rechts, hoe hoger de
   concentratie. Eén kleur die aanslibt zegt dat; drie kleuren naast
   elkaar zeggen alleen "drie dingen". */
.kern__deel { min-width: 0; background: color-mix(in srgb, var(--amber) 30%, var(--graf-spoor)) }
.kern__deel[data-stap="gekozen"]   { background: color-mix(in srgb, var(--amber) 48%, var(--graf-spoor)) }
.kern__deel[data-stap="producten"] { background: color-mix(in srgb, var(--amber) 74%, var(--graf-spoor)) }
.kern__deel[data-stap="klaar"]     { background: var(--amber) }
/* Drie standen. Niet geteld is streepjes: onbekend. Geteld en nul is een
   lege bak: bekend, en er staat niets. Alleen een gevuld segment beweert
   dat er waarde zit — en dat is wat amber betekent. */
.kern__deel--leeg {
  background-color: var(--graf-spoor);
  background-image: var(--graf-leeg);
}
.kern__deel--nul, .kern__deel--nul[data-stap] {
  background-color: var(--graf-spoor);
  background-image: none;
}
/* de breuk zelf is de kleur van de pagina eronder: geen lijn, een gat.
   Hier houdt de ene eenheid op en begint de andere. */
.kern__breuk { background: var(--rand-sterk) }

/* --ring is een zachte was van 10 tot 15 procent en haalt als focus
   1,2:1 — onbruikbaar. En de strip is 6px hoog met de balk erboven op
   een hogere laag, dus de bovenste helft van een naar buiten stekende
   ring werd ook nog overschilderd. Een echte outline, naar binnen
   verschoven, en even boven de balk uit. */
.kern:focus-visible {
  outline: 2px solid var(--accent); outline-offset: -2px;
  box-shadow: none; z-index: 31;
}
/* De strip blijft op elke breedte staan. Hij zou onder 1120px wijken
   voor de kamerstrip in de bovenbalk — maar die verdwijnt daar zelf ook
   (op sommige schermen al bij 1180px), en dan zijn de vier ketengetallen
   nergens meer te zien. De strip kost zes pixels over de volle breedte
   en heeft die ruimte niet nodig van iets anders. */

.kernlade {
  position: sticky; top: calc(var(--balk, 3.25rem) + 6px); z-index: 28;
  display: grid; grid-auto-flow: column; align-items: center;
  gap: var(--r4); padding: var(--r3) var(--r5);
  background: color-mix(in srgb, var(--vlak) 94%, transparent);
  backdrop-filter: blur(14px) saturate(1.15);
  border-bottom: 1px solid var(--rand);
  overflow-x: auto;
}
.kernlade[hidden] { display: none }
.kernlade__vak { min-width: 0 }
/* 11px functionele tekst draagt --inkt-zacht, niet --inkt-vaag. Die
   regel staat in de kop van etalage.html en gold overal behalve, tot
   net, in dit blad zelf. */
.kernlade__lab {
  font: 600 var(--t-2xs)/1.2 var(--font-ui);
  letter-spacing: var(--spoor-wijd); text-transform: uppercase;
  color: var(--inkt-zacht); margin: 0;
}
.kernlade__w {
  font: 650 var(--t-xl)/1.1 var(--font-kop);
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -.02em; margin: 2px 0 0;
}
.kernlade__w.leeg { color: var(--inkt-vaag); font-weight: 600 }
.kernlade__k {
  font: var(--t-2xs)/1.4 var(--font-ui); color: var(--inkt-zacht);
  margin: 2px 0 0;
}
.kernlade__val {
  font: var(--t-2xs)/1.4 var(--font-mono);
  font-variant-numeric: tabular-nums; color: var(--inkt-zacht);
  white-space: nowrap;
}
.kernlade__wissel {
  padding-left: var(--r4);
  border-left: 1px solid var(--rand-zacht);
}
/* De lade schuift horizontaal in plaats van te verdwijnen. Vijf vakken
   naast elkaar passen niet op een smal scherm, maar wegnemen is erger
   dan schuiven. */
@media (max-width: 1120px) {
  .kernlade { gap: var(--r3); padding: var(--r2) var(--r4) }
}

/* ══ 14. DE KAMERS IN DE VORM ═══════════════════════════════════════
   Vier ingrepen, één per kamer, en elk moet de weghaal-toets doorstaan:
   haal hem weg en kijk of het scherm slechter werkt. Blijft het even
   goed werken, dan was het decoratie.

   Wat hier NIET staat, en met opzet: geen pikhouweel, geen helm, geen
   lantaarn, geen ruitvormige opsommingstekens, geen briljantslijp-
   loader, geen gesteentefoto onder de bovenbalk. Zodra een boor-icoon
   in de interface staat is de metafoor van de chrome naar de inhoud
   gelekt. De vorm draagt het thema; de woorden dragen de betekenis. */

/* ── het zeefraster: geschrapt, en de reden hoort hier te staan ────
   Hier stond een raster van haarlijnen op 14px maas achter de tegelmuur
   in de wasplaats — de zeef waar het gewassen materiaal doorheen valt.
   Het zag er goed uit en het is er niet meer.

   De weghaal-toets uit het contract: haal het idee weg en kijk of het
   scherm slechter werkt. Dat deed het niet. Mijn verdediging was dat je
   bij een half gevulde laatste rij zou zien waar het raster ophoudt en
   dus hoeveel er nog kon staan — maar de tegels laten dat al zien door
   er niet te zijn. Het raster voegde niets toe wat er niet stond.

   Een raster van haarlijnen achter een kaartraster is bovendien precies
   de vorm die je moet bewaren voor een oppervlak dat écht een maatveld
   is: een kaart, een tijdlijn, een tekenvlak. Ergens anders is het
   behang met een verhaal erbij. Eén ingreep minder, en de metafoor
   draagt nog steeds — via de dichtheid, het facet, de ader en de kern. */

/* ── de etalage: de kaart is geen kaart ────────────────────────────
   .kaart heet in etalage.html hetzelfde als overal, maar het is er iets
   anders: `.kaart{min-width:0}` en verder niets. Geen vlak, geen rand,
   geen straal, geen schaduw. Het dragende vlak is .kaart__doek — de
   lichtbak waar het kledingstuk op staat — en daaromheen hoort de
   pagina te liggen, niet een tweede paneel.

   De kaartlaag maakte er een ondoorzichtige plaat van --vlak-op onder,
   met --hoog-1 eromheen. Dat is precies wat het contract voor deze kamer
   verbiedt: op een lichte ondergrond beoordeel je kleur en stof, en dan
   mag de interface geen extra vlak naast het doek zetten. Bovendien is
   de rand hier nul breed, dus het verloop dat de kaartlaag komt brengen
   is er niet eens — er blijft alleen de fout over.

   Uitgesloten dus, en alleen hier: op de tien andere schermen is .kaart
   wél een kaart. */
:root[data-kamer="etalage"] .kaart {
  background-image: none;
  box-shadow: none;
}

/* ── de amberstip vangt licht ──────────────────────────────────────
   Bij honderden tegels moet "deze zit boven de drempel" perifeer
   detecteerbaar zijn zonder te lezen. Een stip is een stip; een stip
   met een specular puntje leest als een steentje.

   1,2px, linksboven op 32%/30% — dezelfde lichtbron als --schaduw-op,
   die ook van boven komt. Geen ring, geen halo, geen box-shadow met
   spreiding: dat zou een LED zijn, en amber is een inclusie. In licht
   is de highlight zwakker, anders wordt het een vuiltje. */
.tegel__waarde, .kaart__waarde {
  background-image: radial-gradient(circle at 32% 30%,
    rgb(255 255 255 / .55) 0 1.2px, transparent 1.2px);
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .tegel__waarde,
  :root:not([data-theme="dark"]) .kaart__waarde {
    background-image: radial-gradient(circle at 32% 30%,
      rgb(255 255 255 / .34) 0 1.2px, transparent 1.2px);
  }
}
:root[data-theme="light"] .tegel__waarde,
:root[data-theme="light"] .kaart__waarde {
  background-image: radial-gradient(circle at 32% 30%,
    rgb(255 255 255 / .34) 0 1.2px, transparent 1.2px);
}

/* ── de slijperij: één facet ───────────────────────────────────────
   Eén afgesneden hoek rechtsboven, 9px. Eén, niet vier — en alleen in
   deze kamer, want dit is de kamer waar geslepen wordt. Een facet op
   een tegel in de wasplaats zou beweren dat die tegel al bewerkt is.

   Bij afgekeurd verdwijnt het facet weer: afgekeurd is teruggezet naar
   ruw. Dat is de hele reden dat dit de weghaal-toets doorstaat — de
   vorm zegt iets dat de kleur niet zegt.

   De cursorring wordt hier een inzet-ring. Een box-shadow buiten het
   element wordt door clip-path afgesneden, en dan verdwijnt de
   focusaanduiding. Dat is een toegankelijkheidsfout, geen smaakkwestie. */
:root[data-kamer="slijperij"] .afdruk {
  clip-path: polygon(0 0, calc(100% - 9px) 0, 100% 9px, 100% 100%, 0 100%);
}
:root[data-kamer="slijperij"] .afdruk--afgekeurd { clip-path: none }
/* Dit hing alleen aan [data-cursor] — de roving cursor van de
   pijltjestoetsen. Wie met Tab op een afdruk landt kreeg niets, want de
   gewone focus-outline ligt buiten de border-box en wordt door de
   clip-path weggeknipt. Beide staten, dezelfde ring. */
:root[data-kamer="slijperij"] .afdruk[data-cursor],
:root[data-kamer="slijperij"] .afdruk:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--accent);
}

/* ── de laagbreuk ──────────────────────────────────────────────────
   Een sectiegrens was één haarlijn. Twee haarlijnen met 2px lucht
   ertussen lezen als een breuk tussen twee lagen in plaats van als een
   streep. Twee, nooit drie — drie is een sierrand.

   Alleen op sectiegrenzen, nooit tussen tabelrijen. Daar is een enkele
   lijn juist wat je wilt: rijen horen bij elkaar. Dát is wat de dubbele
   lijn codeert: een sectiegrens is iets anders dan een rijgrens, en op
   een dicht scherm komen ze allebei voor.

   Dit is géén rasterveld, ook al lijkt het er in de code op. Let op
   `background-repeat: no-repeat` en `background-size: 100% 1px`: er
   worden precies twee lijnen getekend, op twee vaste posities. Geen
   tegel, geen pixelcel, geen herhaling. Functioneel is het een
   `border-top` met een tweede haarlijn 3px eronder.

   Het echte rasterveld dat hier ooit stond — het zeefraster achter de
   tegelmuur — is geschrapt; zie de noot bovenaan deze sectie. */
.sectie__kop, .periode, .rail__voet {
  border-top-color: transparent;
  background-image:
    linear-gradient(var(--rand) 0 1px, transparent 1px),
    linear-gradient(var(--rand-zacht) 0 1px, transparent 1px);
  background-position: top, 0 3px;
  background-repeat: no-repeat;
  background-size: 100% 1px, 100% 1px;
}

/* ══ 15. GETALROLLEN ════════════════════════════════════════════════
   Er stonden vier verschillende maten voor de rol "het grote getal",
   verspreid over vier bestanden. Dat zijn er nu drie, met vaste
   betekenis: antwoord (maximaal één per scherm), teller, cel. */
.getal, .stat__g, .dek__deel, .fase__tel, .geld__w, .veld__w,
.bank__g, .tbank__g, .gat__getal, .kernlade__w {
  font-variant-numeric: tabular-nums lining-nums;
}
.gat__getal { letter-spacing: -.03em }
.dek__deel, .fase__tel, .geld__w, .stat__g { letter-spacing: -.02em }

/* Mono is gereserveerd voor gemeten waarden. Uitleg draagt het UI-font. */
.detail--woord, .sub--woord { font-family: var(--font-ui) }

/* Een dalende plek is grijs, niet rood. Rood blijft voor negatieve
   marge en voor ingrijpen — precies één betekenis per kleur, zoals
   amber. De richting staat altijd in de glyph, nooit alleen in de kleur. */
.delta--omlaag { color: var(--inkt-zacht) }
.delta--gelijk { color: var(--inkt-vaag) }

/* ══ 16. EIGENDOM VAN BEWEGING ══════════════════════════════════════
   Een element dat door de bewegingslaag wordt aangestuurd, mag geen
   eigen CSS-transitie op dezelfde eigenschap hebben. Anders vechten
   twee systemen: de WAAPI-animatie ligt boven de computed style, en op
   het moment dat hij eindigt ziet CSS een sprong en start zijn eigen
   transitie. Je krijgt de beweging dan twee keer, de tweede keer traag
   en verkeerd.

   beweging.js zet deze klassen vlak vóór het animeren en haalt ze er
   daarna weer af.

   De klasse staat er dubbel in de selector. Dat is geen typefout: het
   maakt de specificiteit (0,2,0), en dat is precies wat nodig is. Een
   enkele .mv (0,1,0) verliest van `.uitklapknop .tik` (0,2,0) in
   instellingen.html en vinden-lijsten.html, en van `.spoor i` en
   `.keur__balk > i` (0,1,1). Die zouden hun transitie stilletjes houden
   terwijl je denkt dat hij weg is — je ziet het pas als de pijl dubbel
   draait. Geen !important nodig: de reduced-motion-blokken zetten
   transition-DURATION, en dit is transition-PROPERTY. Ze bijten elkaar
   niet.

   Drie treden, want niet elke helper schrijft evenveel:
   · .mv       druk() schrijft alleen transform — achtergrond mag zacht
   · .mv--vol  golf(), verhuis(), markeer(): niets meer over CSS
   · .mv--stil een element dat al een eigen entree-keyframe heeft. Daar
               helpt het intrekken van een transitie niet, want het
               probleem is een tweede animatie. */
.mv.mv {
  transition-property: background, border-color, color, box-shadow;
}
.mv--vol.mv--vol {
  transition-property: none;
}
.mv--stil.mv--stil {
  animation: none;
}

/* ══ 17. MINDER BEWEGING ════════════════════════════════════════════
   De bestaande vangnetten in de schermen zetten animation-duration en
   transition-duration op 1ms. Dat dekt CSS af, maar niet de
   bewegingslaag — die draait op WAAPI en glipt er dwars doorheen.
   beweging.js zet daarom MotionGlobalConfig.instantAnimations om.

   Wat hier staat is het deel dat níet getimed is maar positioneel: het
   cursorlicht, de veeg over de primaire knop, de korrellaag. Die kun je
   niet korter maken, alleen weglaten. */
@media (prefers-reduced-motion: reduce) {
  tbody tr:hover { background-image: none }
  .knop--primair { background-image: none }
  .melding::after { animation: none; transform: scaleX(0) }
  .skelet { animation: none; background-position: 0 0 }
  body::before { opacity: calc(var(--korrel) * .5) }
  @view-transition { navigation: none }

  /* ── de gaten dichten ──────────────────────────────────────────────
     De schermen zetten hun animaties netjes op 1ms, maar drie plekken
     verliezen daarmee informatie in plaats van alleen sier. De regel
     hoort te zijn: vervang de beweging door een statische drager, zet
     hem niet alleen uit. boorvloer.html en wasplaats.html doen dat al
     goed; deze drie deden het niet.

     1. Een vers kernwoord was alleen te herkennen aan een flits die
        naar de ruststand terugvalt. In 1ms is die eindstand de
        ruststand — het verse kernwoord is dan niet meer te
        onderscheiden van de rest. Er gaat dus gegevens verloren. */
  .kw--vers {
    border-color: color-mix(in srgb, var(--accent) 55%, transparent);
    color: var(--accent);
  }

  /* Wat hier NIET staat: een gekleurde rand langs de linkerkant van de
     loep en de melding. Dat was mijn eerste oplossing voor twee dingen
     die zonder beweging onaangekondigd verschijnen, en hij was fout om
     twee redenen.

     De eerste staat in dit project zelf opgeschreven, in de kop van
     platform-demo.html: geen gekleurde linkerrand, want kleur is nooit
     de enige code. De tweede is dat het probleem er geen was. De loep
     hangt aan de cursor, dus je weet waar hij vandaan komt. En de
     melding kondigt zichzelf aan — drie van de vier schermen zetten er
     `aria-live` op. Het vierde was wasplaats.html, uitgerekend het
     scherm waar de melding de vervanger ís van de spoelanimatie. Dát
     was het echte gat, en dat is daar gerepareerd in plaats van hier
     met een streep overgeschilderd. */
}

/* ══ 18. PROJECTKIEZER ══════════════════════════════════════════════
   Zat in de eerste opzet linksboven en is bij de kamers nooit
   meegekomen. rail.js zet hem op elk scherm terug, gevuld uit
   data/project.json. */
.proj{position:relative;width:100%;text-align:left;color:inherit;font:inherit;
  background:var(--vlak-op);border:1px solid var(--rand);border-radius:var(--rond-m);
  padding:var(--r3);margin-bottom:var(--r4);cursor:pointer;
  transition:border-color 120ms cubic-bezier(.16,1,.3,1),
             background 120ms cubic-bezier(.16,1,.3,1)}
.proj:hover{border-color:var(--rand-sterk);background:var(--vlak-hoog)}
.proj__lab{display:block;font:600 var(--t-2xs)/1.2 var(--font-ui);
  letter-spacing:var(--spoor-wijd);text-transform:uppercase;color:var(--inkt-vaag)}
.proj__naam{display:block;font:600 var(--t-s)/1.3 var(--font-ui);margin-top:var(--r1)}
.proj__meta{display:block;font:var(--t-2xs)/1.4 var(--font-ui);color:var(--inkt-vaag);
  margin-top:2px}
.proj__pijl{position:absolute;right:var(--r3);top:var(--r3);color:var(--inkt-vaag);
  font-size:var(--t-2xs)}
.projmenu{border:1px solid var(--rand);border-radius:var(--rond-m);
  background:var(--vlak-op);padding:var(--r1);margin:calc(var(--r4) * -1 + var(--r1)) 0 var(--r4)}
.projmenu[hidden]{display:none}
.projmenu button{display:block;width:100%;text-align:left;border:0;background:none;
  color:var(--inkt);padding:var(--r2) var(--r3);border-radius:var(--rond-s);
  font:var(--t-s)/1.3 var(--font-ui);cursor:pointer}
.projmenu button:hover{background:var(--vlak-hoog)}
.projmenu button[aria-current="true"]{color:var(--accent);font-weight:600}
.projmenu button:disabled{opacity:.42;cursor:not-allowed}
.projmenu .projmenu__noot{font:var(--t-2xs)/1.45 var(--font-ui);color:var(--inkt-vaag);
  padding:var(--r2) var(--r3);margin:0;border-top:1px solid var(--rand-zacht)}

/* Wisselen en bijstellen zijn twee handelingen, dus twee knoppen naast
   elkaar. Tot 25-08-2026 lagen ze op dezelfde klik: de rij markeerde het
   huidige project met aria-current en opende bij klikken het formulier.
   Dat leest als een kiezer en is er geen, en de eigenaar klikte er precies
   zo op. De rij is nu de kiezer; bijstellen staat ernaast.

   Bijstellen krijgt geen accent en geen rand: het is de tweede handeling van
   de twee, en twee even luide knoppen op één regel is weer dezelfde
   verwarring in een andere vorm. Hij is stiller, niet zwakker — hij staat er
   altijd, want op een aanraakscherm bestaat hover niet en met de tab-toets
   moet je kunnen zien waar je heen tabt.

   STILLER MAG NIET ONLEESBAAR WORDEN. Hier stond eerst `opacity:.62` op
   --inkt-vaag; gemeten in de donkere stand gaf dat 2,81:1 op 11px, ver onder
   de 4,5:1 die kleine tekst nodig heeft. Nu doet de KLEUR het werk en niet de
   doorzichtigheid: --inkt-vaag is precies het niveau dat de metaregel en de
   noot hiernaast ook gebruiken, dus stiller dan de naam ernaast en toch
   leesbaar. Hover en focus tillen hem naar --inkt. */
.projmenu__rij{display:flex;align-items:stretch;gap:2px;border-radius:var(--rond-s)}
.projmenu__rij:hover{background:var(--vlak-hoog)}
.projmenu .projmenu__kies{flex:1 1 auto;min-width:0}
.projmenu .projmenu__kies:hover{background:none}
.projmenu__naam{display:block;overflow-wrap:anywhere}
.projmenu__meta{display:block;font:var(--t-2xs)/1.35 var(--font-ui);
  color:var(--inkt-vaag);margin-top:1px}
.projmenu .projmenu__kies[aria-current="true"] .projmenu__meta{color:inherit;opacity:.72}
.projmenu .projmenu__stel{flex:0 0 auto;width:auto;align-self:center;
  padding:var(--r1) var(--r2);font:600 var(--t-2xs)/1.3 var(--font-ui);
  color:var(--inkt-vaag);white-space:nowrap;
  transition:color var(--duur-1,120ms) var(--soepel,ease),
             background var(--duur-1,120ms) var(--soepel,ease)}
.projmenu__rij:hover .projmenu__stel{color:var(--inkt-zacht)}
.projmenu .projmenu__stel:hover,
.projmenu .projmenu__stel:focus-visible{color:var(--inkt);background:var(--vlak-op)}

/* De regel die meetelt terwijl er gewisseld wordt. Hij staat ONDER de noot
   en niet in de plaats ervan: de noot legt uit wat de twee knoppen doen, en
   die uitleg is juist tijdens het wachten niet minder waar. */
.projmenu__bezig{color:var(--inkt-zacht)}
.projmenu__bezig--fout{color:var(--fout)}

/* ── winkelprojecten (13-10-2026) ──────────────────────────────────
   De kaart is nu de website; de keywordlijsten (Seizoen, Mannen, Vrouwen)
   staan er direct onder als schakelaar. Dichter op de kaart dan het menu,
   want ze horen erbij: de kaart zegt wélke website, de schakelaar welke
   lijst daarvan. Het menu schuift ertussen als het opengaat. */
.proj.proj--lijst{margin-bottom:var(--r2)}
.proj--lijst + .projmenu{margin-top:0}
.projlijst{margin:0 0 var(--r4)}
.projlijst[hidden]{display:none}
.projlijst__lab{display:block;font:600 var(--t-2xs)/1.2 var(--font-ui);
  letter-spacing:var(--spoor-wijd);text-transform:uppercase;color:var(--inkt-vaag);
  margin:0 0 var(--r1) 2px}
.projlijst__knoppen{display:flex;flex-wrap:wrap;gap:2px;padding:2px;
  border:1px solid var(--rand);border-radius:var(--rond-m);background:var(--vlak-op)}
.projlijst__knop{flex:1 1 auto;min-width:0;border:0;background:none;color:var(--inkt-zacht);
  font:500 var(--t-xs)/1.3 var(--font-ui);padding:var(--r1) var(--r2);
  border-radius:var(--rond-s);cursor:pointer;overflow-wrap:anywhere}
.projlijst__knop:hover{background:var(--vlak-hoog);color:var(--inkt)}
.projlijst__knop:focus-visible{outline:none;box-shadow:var(--ring)}
.projlijst__knop[aria-pressed="true"]{background:var(--accent-zacht);color:var(--accent);
  font-weight:600;cursor:default}
/* Gepauzeerd: gedempt door kleur en cursief, niet door doorzichtigheid —
   zie de contrastmeting bij .projmenu__stel hierboven. */
.projlijst__knop--pauze{color:var(--inkt-vaag);font-style:italic}
.projlijst__knop:disabled{opacity:.42;cursor:not-allowed}
.projlijst__leeg,
.projlijst .projmenu__noot{font:var(--t-2xs)/1.45 var(--font-ui);color:var(--inkt-vaag);
  margin:var(--r1) 0 0;padding:0 2px}
.projlijst .projmenu__bezig{color:var(--inkt-zacht)}
.projlijst .projmenu__bezig--fout{color:var(--fout)}

/* In het menu: per website een groep, met de lijsten eronder ingesprongen. */
.projmenu__groep + .projmenu__groep{border-top:1px solid var(--rand-zacht);
  margin-top:var(--r1);padding-top:var(--r1)}
.projmenu__lijsten{padding:0 0 var(--r1) var(--r3)}
.projmenu__lijst{display:flex;align-items:center;gap:var(--r2);
  font:var(--t-2xs)/1.35 var(--font-ui);color:var(--inkt-zacht);padding-left:var(--r3)}
.projmenu__lijst > span{flex:1 1 auto;min-width:0;overflow-wrap:anywhere}
.projmenu .projmenu__erbij{display:block;margin-left:var(--r1)}
