/* ==========================================================================
   QualiMundi — beheeromgeving
   Zelfde familie als de site, maar dichter en functioneler. Werken boven tonen.
   ========================================================================== */

/*
 * Deze namen zijn nu een aliaslaag boven assets/css/tokens.css (fase 0.1),
 * die vóór dit bestand geladen wordt op elke pagina die admin.css gebruikt.
 * Geen enkele regel verderop in dit bestand hoefde daarvoor te veranderen —
 * ze verwijzen nog altijd naar --a-*, alleen de bron is verplaatst.
 *
 * Drie namen die tot fase 0 hier ontbraken maar wel gebruikt werden,
 * --a-accent-zacht, --a-vlak-accent en --a-vlak-zacht, stonden daardoor
 * zonder definitie en vielen terug op een per-ongeluk-groene of
 * Tailwind-blauwe kleur (zie bevinding 2 van het plan). Ze staan nu wél
 * gedefinieerd, uit dezelfde tokenbron als de rest.
 */
:root {
  --a-ink:      var(--qm-ink);
  --a-ink-2:    var(--qm-ink-2);
  --a-ink-3:    var(--qm-ink-3);
  --a-paper:    var(--qm-paper);
  --a-vlak:     var(--qm-vlak);
  --a-rand:     var(--qm-rand);
  --a-rand-zacht: var(--qm-rand-zacht);
  /* Alleen voor de omtrek van iets waar je in kunt typen of kiezen; zie
     tokens.css. Overal elders blijft --a-rand de rand. */
  --a-rand-veld: var(--qm-rand-veld);
  --a-diep:     var(--qm-deep);
  --a-diep-2:   var(--qm-deep-2);
  --a-accent:   var(--qm-accent);
  --a-accent-licht: var(--qm-accent-licht);
  --a-accent-zacht: var(--qm-accent-licht);
  --a-goed:     var(--qm-goed);
  --a-goed-licht: var(--qm-goed-licht);
  --a-fout:     var(--qm-fout);
  --a-fout-licht: var(--qm-fout-licht);
  --a-blauw:    var(--qm-blauw);
  --a-blauw-licht: var(--qm-blauw-licht);
  --a-vlak-accent: rgba(158, 95, 40, .06);
  --a-vlak-zacht:  var(--qm-rand-zacht);

  /*
   * De achtergrond van een rij of een regel waar je met de muis op staat.
   *
   * Stond op --a-rand-zacht (#EFEBE3). Daar haalt --a-ink-3 (#736B60) — de
   * kleur van elke hint, elke datum, elke kolomnaam in de kaartweergave —
   * nog 4,41:1, en dat is onder de 4,5 die gewone tekst nodig heeft. Het
   * effect is klein maar precies verkeerd om: de tekst wordt moeilijker
   * leesbaar op de rij die je aan het lezen bent.
   *
   * #F2EFE8 haalt 4,57:1 en staat nog altijd 1,15:1 van wit af — het verschil
   * met #EFEBE3 (1,19:1) zie je niet, de leesbaarheid wel.
   */
  --a-vlak-aanwijs: #F2EFE8;

  --a-serif: var(--qm-serif);
  --a-sans:  var(--qm-sans);
  --a-mono:  var(--qm-mono);

  --a-zij: 264px;
  --a-radius: var(--qm-radius);
  --a-ease: var(--qm-ease);
}

* , *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--a-paper);
  color: var(--a-ink);
  font-family: var(--a-sans);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }

h1, h2, h3, h4 { margin: 0; font-weight: 500; line-height: 1.25; letter-spacing: -.012em; }
h1 { font-size: 1.6rem; }
h2 { font-size: 1.2rem; }
h3 { font-size: 1rem; }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

:focus-visible { outline: 2px solid var(--a-blauw); outline-offset: 2px; border-radius: 3px; }

.vh {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/*
 * De sprong naar de inhoud.
 *
 * Die stond eerst op .vh, en .vh verbergt permanent: er is geen :focus-regel
 * die hem terughaalt. Wie enkel een toetsenbord heeft kreeg dus wel de link
 * onder de eerste Tab, maar zag nergens dat hij daar stond — en tabde dan
 * maar door de veertig menulinks van de zijbalk heen. Dit is hetzelfde
 * patroon als .skip op de publieke site (qualimundi.css): buiten beeld
 * geparkeerd, en bij focus terug naar links boven.
 */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--a-diep); color: var(--a-paper); padding: 1rem 1.5rem;
}
.skip:focus { left: 0; }

/* --- Losse schermen: inloggen, installatie ------------------------------- */

body.admin-kaal {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: var(--a-diep);
  padding: 2rem 1rem;
}

.kaal-kaart {
  width: 100%;
  max-width: 460px;
  background: var(--a-vlak);
  border-radius: 10px;
  padding: clamp(2rem, 5vw, 3rem);
  box-shadow: 0 24px 60px rgba(0,0,0,.28);
}
.kaal-kaart .logo-plek { margin-bottom: 2rem; }
.kaal-kaart .logo-plek img { height: 40px; width: auto; }
.kaal-kaart h1 { font-family: var(--a-serif); font-weight: 300; font-size: 2rem; margin-bottom: .5rem; }
.kaal-kaart .onder-titel { color: var(--a-ink-3); margin-bottom: 2rem; }
.kaal-form { display: grid; gap: 1.25rem; }
.kaal-noot { margin-top: 1.5rem; font-size: .85rem; color: var(--a-ink-3); }

/* --- Rooster -------------------------------------------------------------- */

.admin {
  display: grid;
  grid-template-columns: var(--a-zij) minmax(0, 1fr);
  min-height: 100vh;
}

/* --- Zijbalk -------------------------------------------------------------- */

.zijbalk {
  background: var(--a-diep);
  color: rgba(252,250,246,.75);
  padding: 1.5rem 0 2rem;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}
.zijbalk__merk { padding: 0 1.5rem 1.75rem; }
.zijbalk__merk img { height: 34px; width: auto; }
/*
 * De dekking van deze twee stille labels stond op 40% en 35% wit. Op
 * --a-diep (#152231) levert dat 3,62 en 3,09 op, en beide zijn kleine
 * hoofdletters van elf pixels: precies de tekst die 4,5 het hardst nodig
 * heeft. Op 52% wordt het 5,15 - nog altijd duidelijk stiller dan de
 * menulinks zelf, die op 78% staan en 9,84 halen.
 */
.zijbalk__merk .rol {
  display: block; margin-top: .75rem;
  font-size: .68rem; letter-spacing: .22em; text-transform: uppercase;
  color: rgba(252,250,246,.52);
}

.zijbalk nav { display: grid; gap: 2px; padding: 0 .75rem; }
.zijbalk__groep {
  font-size: .65rem; letter-spacing: .2em; text-transform: uppercase;
  /* Zie de noot bij .zijbalk__merk .rol: 35% wit gaf 3,09 op de donkere balk. */
  color: rgba(252,250,246,.52);
  padding: 1.5rem .75rem .5rem;
}
/*
 * Veertig menulinks van 42,73 px. Net onder de 44 die een vinger nodig heeft,
 * en dat op élk beheerscherm, want de zijbalk staat overal.
 *
 * Het onzichtbare klikvlak van .admin-voet a zou hier ook kunnen: de links
 * staan met 2 px ertussen, dus de steek is 44,73 en een vlak van 44 past er
 * net in. Toch niet gedaan. In deze balk is de achtergrond van hover en van
 * .is-actief de aanwijzing waar je bent; een klikvlak dat groter is dan die
 * achtergrond laat je raken waar niets oplicht. Hier groeit de link zelf.
 *
 * De prijs is gemeten en valt mee: veertig links van 42,73 naar 44 is 51 px
 * op een kolom die met 2479 px toch al scrolt. Geen 156, zoals gevreesd,
 * want er ontbrak maar 1,27 px per link.
 */
.zijbalk a {
  display: flex; align-items: center; gap: .75rem;
  padding: .6rem .75rem;
  min-height: 44px;
  border-radius: var(--a-radius);
  color: rgba(252,250,246,.78);
  font-size: .92rem;
  transition: background .2s var(--a-ease), color .2s var(--a-ease);
}
.zijbalk a:hover { background: rgba(252,250,246,.07); color: #fff; }
.zijbalk a.is-actief { background: rgba(252,250,246,.12); color: #fff; font-weight: 450; }
.zijbalk a .ic { width: 17px; flex: none; opacity: .8; }
.zijbalk a .telling {
  margin-left: auto; font-size: .72rem; background: var(--a-accent); color: #fff;
  padding: .1rem .45rem; border-radius: 999px; font-weight: 500;
}
/* Er staat iets tussen dat over tijd is. Het getal blijft zeggen hoeveel er
   openstaat; alleen de kleur zegt dat er haast bij is. */
.zijbalk a .telling--laat { background: var(--a-fout); }

.zijbalk__voet {
  margin-top: auto; padding: 1.5rem 1.5rem 0;
  border-top: 1px solid rgba(252,250,246,.12);
  font-size: .82rem; color: rgba(252,250,246,.5);
}
/* Website bekijken, Mijn gegevens en Uitloggen. Ze staan in dezelfde kolom
   als het menu erboven, dus horen ze ook even goed te raken te zijn: de
   menu-items meten 43 pixels, deze drie maten er 35 met .15rem ertussen.
   Het onderste is Uitloggen — dat wil je niet per ongeluk aantikken. */
.zijbalk__voetlinks { display: grid; gap: .15rem; }
.zijbalk__voet a {
  padding: .35rem 0;
  color: rgba(252,250,246,.6);
  display: flex;
  align-items: center;
  min-height: 44px;
}
@media (max-width: 700px) { .zijbalk__voetlinks { gap: .4rem; } }
.zijbalk__voet a:hover { background: none; color: #fff; }

/*
 * De focusring in de zijbalk moet wit zijn, niet blauw.
 *
 * De algemene regel bovenaan tekent een ring in --a-blauw (#3D6E9E). Op de
 * donkere zijbalk (--a-diep, #152231) haalt die net 3:1 en zakt hij daar
 * onder zodra er een lichter vlak achter zit: het actieve menu-item heeft een
 * eigen achtergrond van 12% wit, en daar blijft van de ring bijna niets over.
 * Wit tegen dezelfde donkere balk is niet twijfelachtig.
 */
.zijbalk a:focus-visible,
.zijbalk button:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* --- Hoofdgebied ---------------------------------------------------------- */

.hoofd { display: flex; flex-direction: column; min-width: 0; }

.kopbalk {
  position: sticky; top: 0; z-index: 20;
  background: rgba(252,250,246,.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--a-rand);
  padding: 1.1rem clamp(1.25rem, 3vw, 2.25rem);
  display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;
}
.kopbalk h1 { font-size: 1.35rem; }
.kopbalk__kruimel { font-size: .78rem; color: var(--a-ink-3); margin-bottom: .2rem; }
.kopbalk__acties { margin-left: auto; display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
/* Zonder deze regel neemt het zoekveld zijn browserbreedte (ruim 200 px) en
   kan het niet krimpen, waardoor het op een telefoon een eigen regel claimt
   en de plakkende kopbalk het halve scherm inneemt. */
.kopbalk__zoeken { flex: 1 1 8rem; min-width: 0; display: flex; }
.kopbalk__zoeken input { width: 100%; min-width: 0; }
/*
 * De knop met het vergrootglas en de bel ernaast, nu op elke breedte.
 *
 * Onder 900 px stonden ze allebei al op 44; daarboven mat het
 * vergrootglas 36,6 bij 30 en de bel 39,2 bij 32. Dat zijn de twee
 * bedieningen die op alle 21 beheerschermen rechtsboven staan: de weg
 * naar de interne zoekmachine en de weg naar wat er ondertussen gebeurd
 * is. Een beheerder gebruikt ze de hele dag, ook met een muis, en 36 bij
 * 30 is ook met een muis een klein doel.
 *
 * Echt groter en niet met een onzichtbaar vlak: het zijn knoppen. De bel
 * heeft een hover-achtergrond die dan mee hoort te groeien, en het
 * vergrootglas hoort even hoog te zijn als het zoekveld waar het aan
 * vastzit; een knop van 30 naast een veld van 44 ziet er verkeerd uit.
 *
 * De prijs staat in de kopbalk zelf: die was 68,2 px hoog op een scherm
 * zonder kruimelpad en wordt 79,2. Op een scherm met kruimelpad was ze al
 * 80,2 en verandert er niets. De kopbalk plakt bovenaan, dus die elf
 * pixels kosten elf pixels beeld: op een venster van 900 is dat 1,2%.
 */
.kopbalk__zoeken input,
.kopbalk__zoeken button { min-height: 44px; }
.kopbalk__zoeken button { min-width: 44px; }

.notificaties { position: relative; margin-left: auto; }
.kopbalk__acties + .notificaties,
.notificaties + .kopbalk__acties { margin-left: 0; }
.notificaties__knop {
  position: relative; border: none; background: none; cursor: pointer;
  font-size: 1.2rem; line-height: 1; padding: .4rem; border-radius: 999px;
  color: var(--a-ink-2);
}
.notificaties__knop:hover { background: var(--a-rand-zacht); }
/* Zie de uitleg bij .kopbalk__zoeken hierboven. inline-flex met centreren
   in plaats van meer vulling: het belletje is een emoji van 1,2rem en die
   hoort in het midden van zijn ronde vlak te staan, niet linksboven. */
.notificaties__knop {
  min-height: 44px; min-width: 44px;
  display: inline-flex; align-items: center; justify-content: center;
}
.notificaties__knop .telling {
  position: absolute; top: 0; right: 0; font-size: .68rem; background: var(--a-accent);
  color: #fff; padding: .05rem .4rem; border-radius: 999px; font-weight: 500;
}
.notificaties__paneel {
  position: absolute; top: calc(100% + .5rem); right: 0; width: min(340px, 90vw);
  background: #fff; border: 1px solid var(--a-rand); border-radius: .6rem;
  box-shadow: 0 12px 32px rgba(0,0,0,.14); z-index: 30; overflow: hidden;
}
.notificaties__kop {
  display: flex; align-items: center; justify-content: space-between;
  padding: .7rem .9rem; border-bottom: 1px solid var(--a-rand); font-weight: 500;
}
.notificaties__kop button { border: none; background: none; color: var(--a-accent); font-size: .8rem; cursor: pointer; }
.notificaties__lijst { max-height: 60vh; overflow-y: auto; }
.notificaties__leeg { padding: 1.2rem .9rem; color: var(--a-ink-3); font-size: .88rem; text-align: center; }
/* Een notificatie zonder link was een <div> met een klikafhandelaar: met de
   muis werkte dat, met het toetsenbord kon je er niet komen en Enter deed
   niets. Ze is nu een echte knop (admin-notificaties.js). De vier regels
   width/border/background/font-text-align halen het knopuiterlijk eraf zodat
   het paneel er hetzelfde uitziet als voorheen; ze staan op de basisklasse en
   niet op button.notificaties__item, want dan zouden ze zwaarder wegen dan
   .notificaties__item--ongelezen verderop en verloor een ongelezen melding
   zonder link haar kleur. Op een <a> veranderen ze niets. */
.notificaties__item {
  display: block; padding: .65rem .9rem; border-bottom: 1px solid var(--a-rand-zacht);
  border-left: 0; border-right: 0; border-top: 0;
  width: 100%;
  background: none;
  font: inherit;
  text-align: left;
  text-decoration: none; color: inherit; cursor: pointer;
}
.notificaties__item:last-child { border-bottom: none; }
/* Het paneel snijdt af (overflow: hidden hierboven), dus een ring buiten de
   rand valt links en rechts weg. Vandaar naar binnen. */
.notificaties__item:focus-visible {
  outline: 2px solid var(--a-blauw);
  outline-offset: -2px;
}
.notificaties__item:hover { background: var(--a-vlak-aanwijs); }
.notificaties__item--ongelezen { background: var(--a-accent-zacht); }
.notificaties__item-titel { font-size: .88rem; font-weight: 500; }
.notificaties__item-tekst { font-size: .82rem; color: var(--a-ink-2); margin-top: .15rem; }
.notificaties__item-moment { font-size: .74rem; color: var(--a-ink-3); margin-top: .25rem; }

.inhoud { padding: clamp(1.25rem, 3vw, 2.25rem); flex: 1; }
.inhoud--smal { max-width: 940px; }

/* --- Knoppen -------------------------------------------------------------- */

.knop {
  display: inline-flex; align-items: center; gap: .5rem;
  /* Een knop kwam op 42,7 pixels uit, net onder de 44 die een vinger nodig
     heeft. De hoogte staat hier als ondergrens en niet als vaste maat, zodat
     een knop met twee regels tekst gewoon meegroeit. */
  min-height: 44px;
  padding: .58rem 1.1rem;
  border: 1px solid var(--a-rand);
  background: var(--a-vlak);
  color: var(--a-ink);
  border-radius: var(--a-radius);
  font-size: .88rem; font-weight: 450;
  cursor: pointer; white-space: nowrap;
  transition: background .2s var(--a-ease), border-color .2s var(--a-ease), color .2s var(--a-ease);
}
.knop:hover { border-color: var(--a-ink-3); background: #fff; }
.knop--primair { background: var(--a-ink); border-color: var(--a-ink); color: #fff; }
.knop--primair:hover { background: var(--a-accent); border-color: var(--a-accent); color: #fff; }
.knop--publiceer { background: var(--a-goed); border-color: var(--a-goed); color: #fff; }
.knop--publiceer:hover { background: var(--qm-goed-hover); border-color: var(--qm-goed-hover); color: #fff; }
.knop--gevaar { color: var(--a-fout); border-color: var(--qm-fout-rand); }
.knop--gevaar:hover { background: var(--a-fout); border-color: var(--a-fout); color: #fff; }
.knop--klein { padding: .35rem .7rem; font-size: .8rem; }

/* Een tabel waarin je de volgende regel meteen kan intypen. Zonder deze
   toon leest de laatste rij als een gewone rij met lege vakjes, en dan is
   niet te zien dat je er iets aan toevoegt. */
/* --a-vlak-aanwijs en niet --a-vlak-zacht: op dat laatste haalt --a-ink-3
   een contrast van 4,41 en dat is onder de 4,5 die leesbaar heet. De kop van
   de kolom en de hint in deze rij zijn klein en grijs, dus juist daar telt
   het. Het verschil tussen de twee vlakken is met het oog niet te zien. */
.tabel__invulrij > td { background: var(--a-vlak-aanwijs); vertical-align: middle; }
.tabel__invulrij input,
.tabel__invulrij select { width: 100%; min-width: 6rem; margin: 0; }
.knop--kaal { border-color: transparent; background: transparent; }
.knop--kaal:hover { background: var(--a-rand-zacht); border-color: transparent; }
.knop[disabled] { opacity: .45; pointer-events: none; }

/* --- Meldingen ------------------------------------------------------------ */

.melding {
  padding: .8rem 1.1rem;
  border-radius: var(--a-radius);
  border: 1px solid var(--a-rand);
  background: var(--a-vlak);
  margin-bottom: 1rem;
  font-size: .9rem;
}
.melding--goed { background: var(--a-goed-licht); border-color: var(--qm-goed-rand); color: var(--qm-goed-donker); }
.melding--fout { background: var(--a-fout-licht); border-color: var(--qm-fout-rand); color: var(--qm-fout-donker); }
.melding--let-op { background: var(--a-accent-licht); border-color: var(--qm-accent-rand); color: var(--qm-accent-donker); }

/*
 * De melding blijft onder de kopbalk hangen zolang ze er staat.
 *
 * Anders leest een handeling die je onderaan een lange tab uitvoert als
 * niets: je wordt naar boven gegooid voor de bevestiging, of je landt bij
 * je rij en ziet de bevestiging nooit. Leeg is dit vakje nul pixels hoog,
 * dus het staat er zonder iets te doen tot er echt iets te melden valt.
 *
 * Beide variabelen komen uit assets/js/kopmaat.js. De hoogte van de balk is
 * geen vast getal: de beheerkopbalk breekt op smalle schermen over meerdere
 * regels, en de portaalbalk wisselt onder 900 px bewust van sticky naar
 * static. Dit blad wordt ook door de drie portalen geladen.
 *
 * Zonder dat script blijft --a-melding-vast op static staan en gedraagt de
 * melding zich zoals vroeger. Dat is met opzet: een vaste melding met een
 * verkeerde afstand zou achter de balk van dat scherm schuiven, en dan is de
 * bevestiging helemaal onleesbaar in plaats van alleen slecht geplaatst.
 */
.melding-gebied {
  position: var(--a-melding-vast, static);
  top: calc(var(--a-kop-h, 0px) + .6rem);
  z-index: 15;
}
.melding-gebied .melding { box-shadow: 0 6px 18px rgba(31,26,20,.10); }

@media (prefers-reduced-motion: no-preference) {
  .melding-gebied .melding { animation: melding-binnen .18s ease-out; }
  @keyframes melding-binnen { from { opacity: 0; transform: translateY(-.35rem); } to { opacity: 1; transform: none; } }
}

/* --- Kaarten en panelen --------------------------------------------------- */

.kaart {
  background: var(--a-vlak);
  border: 1px solid var(--a-rand);
  border-radius: 8px;
  padding: clamp(1.1rem, 2vw, 1.6rem);
  /*
   * Kaarten tonen tekst die van buiten komt: componenttitels uit een
   * DMC-document, leveranciersreferenties, links. Eén woord zonder spaties duwt
   * anders de hele beheeromgeving zijwaarts, menubalk inbegrepen. Erft naar alle
   * tekst in de kaart, dus dit hoeft nergens herhaald te worden.
   */
  overflow-wrap: break-word;
}
.kaart + .kaart { margin-top: 1rem; }
/*
 * Wikkelen, want een badge naast een kop kan niet krimpen.
 *
 * De kop van een kaart draagt vaak een label naast de titel ("A — QMTEST
 * Namib Trails" op het tabblad Reisprogramma). Dat label staat op
 * white-space: nowrap, en de rij stond op nowrap, dus op een smal scherm
 * schoof het label gewoon de kaart uit: gemeten op 375 px werd de
 * layoutviewport 444 px breed en schoof de hele pagina mee opzij.
 *
 * Wikkelen verandert niets zolang alles past, en zet het label op een
 * eigen regel zodra dat niet meer zo is.
 */
.kaart__kop { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; margin-bottom: 1.1rem; }
.kaart__kop h2 { font-size: 1.05rem; }
.kaart__kop .knop { margin-left: auto; }

.raster { display: grid; gap: 1rem; }
.raster--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/*
 * Drag-and-drop-dropzone voor documentupload (admin/dossier.php, tab
 * documenten). Puur visueel — de logica zit in assets/js/document-dropzone.js.
 * Ook zonder JS blijft dit een klikbaar <label> rond een verborgen
 * <input type="file">, dus werkt de klassieke bestandskiezer altijd nog.
 */
.document-dropzone {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 90px;
  padding: 1rem;
  border: 2px dashed var(--a-rand);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease;
}
.document-dropzone:hover,
.document-dropzone:focus-within {
  border-color: var(--a-accent);
}
.document-dropzone--over {
  border-color: var(--a-accent);
  background: var(--a-vlak-accent, rgba(37, 99, 235, .06));
}
.document-dropzone__link { text-decoration: underline; }
/* Het echte bestandsveld blijft functioneel bereikbaar (toetsenbord, screen
   readers) maar visueel verborgen achter de dropzone-tekst — niet display:none,
   dat zou het ook uit de tab-volgorde halen. */
.document-dropzone__input {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
}
.document-dropzone__lijst {
  list-style: none;
  margin: .6rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}
.document-dropzone__lijst:empty { margin: 0; }
.document-dropzone__lijst li {
  display: flex;
  justify-content: space-between;
  gap: .6rem;
  font-size: .85rem;
  padding: .3rem .5rem;
  border-radius: 6px;
  background: var(--a-vlak-zacht, rgba(0,0,0,.03));
}
.document-dropzone__lijst li[data-status="fout"] { color: var(--a-fout); }
.raster--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.raster--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/*
 * Overal minmax(0, 1fr) en nooit een kale 1fr. Een kolom van 1fr mag namelijk
 * groeien tot de breedste inhoud erin past — staat er een tabel in die niet
 * mag afbreken, dan rekt de hele kaart mee tot buiten het scherm. Met een
 * ondergrens van 0 blijft de kolom binnen het raster en gaat de tabel zelf
 * scrollen, zoals bedoeld.
 */
@media (max-width: 1100px) { .raster--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 900px)  { .raster--2, .raster--3 { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 620px)  { .raster--4 { grid-template-columns: minmax(0, 1fr); } }

/* --- Kerncijfers ---------------------------------------------------------- */

.cijfer { background: var(--a-vlak); border: 1px solid var(--a-rand); border-radius: 8px; padding: 1.25rem; }
.cijfer b { display: block; font-family: var(--a-serif); font-size: 2.4rem; font-weight: 300; line-height: 1; }
.cijfer span { display: block; margin-top: .5rem; font-size: .82rem; color: var(--a-ink-3); }

/* Kopje boven een groep knoppen binnen een kaart. */
.a-groepje {
  font-size: .68rem; font-weight: 500; letter-spacing: .14em;
  text-transform: uppercase; color: var(--a-ink-3);
  margin: 0 0 .55rem;
}

/* --- Tabellen ------------------------------------------------------------- */

.tabel { width: 100%; border-collapse: collapse; font-size: .9rem; }
.tabel th {
  text-align: left; font-weight: 500; font-size: .72rem;
  letter-spacing: .12em; text-transform: uppercase; color: var(--a-ink-3);
  padding: .6rem .75rem; border-bottom: 1px solid var(--a-rand);
}
.tabel td { padding: .75rem; border-bottom: 1px solid var(--a-rand-zacht); vertical-align: middle; }
/*
 * Een hele zin in een tabelkop is geen kolomkop.
 *
 * .tabel th zet alles in hoofdletters met wijde letterafstand, en dat werkt
 * voor een kopje van één woord. In een tfoot staat er soms een zin: "de
 * schijven tellen niet op tot 100 %", of de waarschuwing dat een
 * annuleringstrede goedkoper is dan de vorige. Die kwam als een regel
 * geschreeuwde hoofdletters op het scherm, precies op het moment dat iemand
 * rustig moet lezen wat er mis is.
 *
 * Alleen de genestelde vorm: een th die zélf de klasse draagt is nog altijd
 * een kop en blijft dus wél in hoofdletters staan.
 */
.tabel th .a-hint, .tabel th .a-hint--82, .tabel th .a-hint--78 {
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
}
/*
 * Eén waarde zonder spaties trekt anders de hele beheeromgeving scheef: een
 * tabelcel groeit mee met haar inhoud, de tabel duwt de kaart uit, en op een
 * telefoon schuift het volledige scherm zijwaarts — ook de menubalk en de
 * andere kaarten. Dat hoeft geen rare invoer te zijn: een leveranciersreferentie
 * of een lange link uit een DMC-document heeft vaak geen enkele spatie.
 * `anywhere` breekt alleen af waar het écht moet, dus gewone tekst blijft
 * ongemoeid.
 *
 * Alleen op td, en dat is het verschil met hoe deze regel hier stond.
 * Een th bevat nooit invoer van iemand anders: het is altijd een label
 * dat wij zelf in een taalbestand geschreven hebben. Daar levert
 * `anywhere` dus geen bescherming op, alleen schade. In een smalle kolom
 * brak Chrome het Engelse kopje QUANTITY af tot QUANTIT / Y, midden in
 * het woord. Een kop die je moet ontcijferen is erger dan een kop die
 * een halve millimeter buiten zijn kolom staat.
 */
.tabel td { overflow-wrap: anywhere; }
.tabel tr:last-child td { border-bottom: 0; }
.tabel tbody tr { transition: background .15s; }
.tabel tbody tr:hover { background: var(--a-vlak-aanwijs); }
.tabel .rechts { text-align: right; }

/*
 * Een tabel waarvan de cel zélf de link is.
 *
 * In een cijfertabel staat er per cel één link en niets anders — de trechter
 * op het managementdashboard, de paginalijst en de niet-gevonden adressen in
 * de statistiek. De link was daar negentien pixels hoog terwijl de cel
 * eromheen ruim veertig was: je moest op de letters mikken.
 *
 * De negatieve marge neemt de celopvulling over en de opvulling zet ze weer
 * terug, zodat de link de hele cel vult zonder dat de rij hoger wordt.
 * min-height tilt hem over de drempel van 44 pixels; zonder die regel komt
 * hij op 43 uit bij de huidige regelhoogte.
 *
 * Bewust een modifier en geen regel over .tabel td a: een brede regel zou de
 * rijhoogte veranderen in elke lijst van het beheer, ook waar de cel naast de
 * link nog tekst of een label draagt.
 */
.tabel--raakbaar td > a {
    display: block;
    box-sizing: border-box;
    min-height: 44px;
    margin: -.75rem;
    padding: .75rem;
}
/*
 * Een rij knoppen is een rij.
 *
 * Deze klasse had alleen binnen .tabel een regel. Daarbuiten - op acht
 * pagineringsbalken en op de zoekbalk van de dossierlijst - was ze een gewoon
 * blok, en deden de justify-content en align-self die daar geschreven staan
 * niets. Het zag er goed uit omdat .knop inline-block is; dat is geen ontwerp
 * maar geluk, en het breekt zodra een knoptekst langer wordt.
 *
 * div.knoppen en niet .knoppen: <span class="knoppen"> in de navigatie- en
 * veldenbouwer zit in een kop die admin-editor.css zelf al uitlijnt.
 */
div.knoppen { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; }
.tabel .knoppen { display: flex; gap: .4rem; justify-content: flex-end; }
.tabel a.titel { font-weight: 500; }
.tabel a.titel:hover { color: var(--a-accent); }

/*
 * De kolomnaam binnen een cel, alleen zichtbaar in de kaartweergave hieronder.
 *
 * Op een breed scherm staat de naam waar hij hoort, in de tabelkop, en zou een
 * tweede kopie in elke cel de tabel verdubbelen. display:none haalt hem ook uit
 * de toegankelijkheidsboom, dus een schermlezer hoort hem daar evenmin dubbel:
 * daar doet de <th> het werk.
 */
.tabel__kop { display: none; }

/*
 * Op een smal scherm past een tabel met vier of vijf kolommen niet. Laat
 * hem dan binnen zijn eigen kaart schuiven in plaats van de hele pagina
 * breder te maken — anders moet je het volledige beheer heen en weer
 * schuiven om één knop te bereiken.
 */
@media (max-width: 860px) {
  .kaart .tabel {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
  }
  .kaart .tabel td { vertical-align: top; }

  /*
   * Zeggen dat er meer staat dan er past.
   *
   * De tabel hierboven schuift, maar niets op het scherm zegt dat. Gemeten op
   * /en/reiskantoor/kantoor bij 768 px: de collegatabel is 1076 px breed in
   * een kaart van 670, dus 406 px valt weg aan de rechterkant. De laatste
   * kolom heet "Actie" en draagt de knop waarmee je iemand de toegang
   * intrekt. Op een tablet is de schuifbalk zelf onzichtbaar, dus er is geen
   * enkel spoor dat die kolom bestaat.
   *
   * Dezelfde vier verlopen als op de tabbalk hieronder en op de
   * portaalnavigatie: twee die de rand afdekken en meeschuiven
   * (background-attachment local), twee die als sluier blijven staan zolang er
   * iets buiten beeld is. Staat de tabel helemaal links, dan dekt de linkse
   * dekking haar eigen sluier af; schuif je naar rechts, dan schuift die
   * dekking weg en verschijnt de sluier. Aan het einde gebeurt hetzelfde
   * rechts, omgekeerd. Een tabel die wél past toont dus niets.
   *
   * Een tabel staat altijd in een kaart, en die is wit in het beheer én in de
   * portalen, dus de dekkleur is --a-vlak.
   */
  .kaart .tabel {
    background-image:
      linear-gradient(to right, var(--a-vlak), transparent),
      linear-gradient(to left,  var(--a-vlak), transparent),
      linear-gradient(to right, rgba(26, 24, 20, .20), transparent),
      linear-gradient(to left,  rgba(26, 24, 20, .20), transparent);
    background-position: left center, right center, left center, right center;
    background-repeat: no-repeat;
    background-size: 2.2rem 100%, 2.2rem 100%, .9rem 100%, .9rem 100%;
    background-attachment: local, local, scroll, scroll;
  }
  /*
   * Een rij die je aanwijst krijgt een dekkende achtergrond, en die zou de
   * sluier erachter wegnemen: precies op de rij waar je met de muis staat
   * verdwijnt dan de rand. Half doorschijnend blijft de aanwijzing zichtbaar
   * en de rand ook. Alleen in deze band, want boven 860 px schuift er niets.
   */
  .kaart .tabel tbody tr:hover { background: rgba(242, 239, 232, .72); }
}

/*
 * Onder de 700 pixels houdt schuiven op te werken: je veegt de tabel heen en
 * weer om bij de knop rechts te komen en raakt onderweg kwijt op welke rij
 * je zat. Elke rij wordt daarom een kaart, met de kolomnaam links en de
 * waarde rechts. De namen zet het script in admin/onderdelen/voet.php erbij;
 * die geeft de tabel ook pas dan de klasse hieronder, zodat er zonder
 * JavaScript niets verandert.
 */
@media (max-width: 700px) {
  .tabel--kaarten,
  .kaart > .tabel--kaarten,
  .kaart > form > .tabel--kaarten {
    display: block;
    overflow-x: visible;
    white-space: normal;
  }
  .tabel--kaarten thead { display: none; }
  .tabel--kaarten tbody,
  .tabel--kaarten tr,
  .tabel--kaarten td { display: block; width: auto; }

  .tabel--kaarten tbody tr {
    border: 1px solid var(--a-rand);
    border-radius: 10px;
    padding: .35rem .2rem;
    margin-bottom: .7rem;
    background: var(--a-vlak);
  }
  /* Hieronder is een rij een kaart met een eigen witte achtergrond, en dan is
     aanwijzen geen aanwijzing meer. De tweede selector houdt de schuifsluier
     uit het blok van 860 px hiervoor tegen: die maakt de aanwijskleur half
     doorschijnend, wat hoort bij een tabel die schuift, niet bij een kaart. */
  .tabel--kaarten tbody tr:hover,
  .kaart .tabel--kaarten tbody tr:hover { background: var(--a-vlak); }
  .tabel--kaarten tbody tr:last-child { margin-bottom: 0; }

  .tabel--kaarten td {
    padding: .5rem .75rem;
    border-bottom: 1px solid var(--a-rand-zacht);
    text-align: left;
  }
  .tabel--kaarten tr td:last-child { border-bottom: 0; }

  /*
   * De kolomnaam boven de waarde, als echte tekst.
   *
   * Dit stond hier eerst als ::before met content: attr(data-kop). Dat is
   * generated content, en die staat niet in de DOM. Op iOS leest VoiceOver
   * haar niet voor: de kaart klonk daar als vier losse waarden zonder dat er
   * ooit gezegd werd waar ze bij hoorden - een annuleringsladder van een
   * lokale agent las als "30", "60", "90". En juist op een telefoon is de
   * kaartweergave de enige weergave die er is.
   *
   * Het script in de voet zet nu een echte <span class="tabel__kop"> vóór de
   * waarde in de cel. Het beheer en de drie portalen doen dat alle vier, dus
   * de ::before-regel had geen gebruiker meer en is weg. Boven de kaartgrens
   * zet .tabel__kop zichzelf op display: none en doet de <th> het werk.
   *
   * Boven de waarde en niet ernaast: naast elkaar oogt compacter, maar dan
   * vechten een lange omschrijving en een smal scherm om dezelfde ruimte, en
   * wint de omschrijving, die dan buiten beeld steekt.
   */
  .tabel--kaarten td > .tabel__kop {
    display: block;
    margin-bottom: .15rem;
    font-size: .68rem;
    font-weight: 500;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--a-ink-3);
  }

  /* Een lege cel met alleen een label is ruis. */
  .tabel--kaarten td:empty { display: none; }

  .tabel--kaarten td .knoppen { flex-wrap: wrap; justify-content: flex-start; }
  .tabel--kaarten .rechts { text-align: left; }

  /*
   * .knop--klein is bedoeld voor een dichte desktoptabel, waar een muis
   * precies kan klikken. In de kaartweergave tik je met een vinger, en dan
   * is 34px (de hoogte die de compacte padding oplevert) te krap — vandaar
   * hier, alleen binnen de kaartweergave, een ruimere maat.
   */
  .tabel--kaarten .knop--klein {
    padding: .6rem 1rem;
    min-height: 44px;
  }

}

/* --- Labels --------------------------------------------------------------- */

.label {
  display: inline-flex; align-items: center; gap: .35rem; white-space: nowrap;
  font-size: .72rem; font-weight: 500; letter-spacing: .04em;
  padding: .18rem .55rem; border-radius: 999px;
  background: var(--a-rand-zacht); color: var(--a-ink-2);
}
.label--concept { background: var(--a-accent-licht); color: var(--qm-accent-donker); }
.label--live    { background: var(--a-goed-licht); color: var(--qm-goed-donker); }
/* --qm-uit-tekst is --qm-ink-3, en dat haalt op --qm-uit-vlak maar 4,41 - te
   weinig voor een label van .72rem. --a-ink-2 haalt 7,60. De token zelf blijft
   staan: die leeft in tokens.css en draagt ook de publieke site. */
.label--uit     { background: var(--qm-uit-vlak); color: var(--a-ink-2); }
.label--land    { background: var(--a-blauw-licht); color: var(--qm-blauw-donker); }
.label--goed    { background: var(--a-goed-licht); color: var(--qm-goed-donker); }
.label--fout    { background: var(--a-fout-licht); color: var(--qm-fout-donker); }
.label--let-op  { background: var(--a-accent-licht); color: var(--qm-accent-donker); }
.label--info    { background: var(--a-blauw-licht); color: var(--qm-blauw-donker); }
.label--neutraal { background: var(--a-rand-zacht); color: var(--a-ink-2); }

/* --- Lege staat ------------------------------------------------------------
   Onderdeel van de componentenbibliotheek (fase 0.5). Eén vaste vorm voor
   "hier staat nog niets" — tabellen, zoekresultaten, dossieroverzichten —
   in plaats van dat elk scherm zijn eigen lege-tekst uitvindt. */
.lege-staat {
  text-align: center;
  padding: clamp(1.8rem, 4vw, 3rem) 1.2rem;
  color: var(--a-ink-3);
}
.lege-staat__icoon { font-size: 1.8rem; line-height: 1; margin-bottom: .5rem; opacity: .6; }
.lege-staat__titel { font-size: .95rem; font-weight: 500; color: var(--a-ink-2); margin-bottom: .3rem; }
.lege-staat__tekst { font-size: .85rem; max-width: 32rem; margin: 0 auto; }
.lege-staat .knop { margin-top: 1rem; }

/* --- Skeletons (fase 0.5) ---------------------------------------------------
   Alleen voor de drie echt-asynchrone schermen genoemd in het plan: chatpolling,
   AI-documentextractie, jobqueue. Blijft herkenbaar bij verminderde beweging
   (tokens.css zet animatieduur dan al bijna op nul, maar de vorm blijft staan
   als signaal — zie de toelichting bij --qm-staat-bezig-duur in tokens.css). */
.skeleton {
  display: block;
  border-radius: var(--a-radius);
  background: linear-gradient(90deg, var(--a-rand-zacht) 25%, var(--a-rand) 37%, var(--a-rand-zacht) 63%);
  background-size: 400% 100%;
  animation: qm-skeleton-schuif var(--qm-staat-bezig-duur, .9s) ease-in-out infinite;
}
.skeleton--regel { height: .9rem; width: 100%; margin-bottom: .5rem; }
.skeleton--regel:last-child { width: 70%; margin-bottom: 0; }
.skeleton--kaart { height: 6rem; width: 100%; }
.skeleton--cirkel { height: 2.2rem; width: 2.2rem; border-radius: 50%; }
@keyframes qm-skeleton-schuif {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

/* --- Bezig-toestand op knoppen (fase 0.5) -----------------------------------
   .knop[aria-busy="true"]: tekst blijft leesbaar (geen tekstvervanging door
   een spinner-icoon, dat verbergt precies het enige signaal wat er loopt bij
   verminderde beweging), spinner ernaast. */
.knop[aria-busy="true"] { pointer-events: none; opacity: .75; position: relative; padding-right: 2.2rem; }
.knop[aria-busy="true"]::after {
  content: "";
  position: absolute; right: .7rem; top: 50%;
  width: .85rem; height: .85rem; margin-top: -.425rem;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%;
  animation: qm-draai var(--qm-staat-bezig-duur, .9s) linear infinite;
}
@keyframes qm-draai { to { transform: rotate(360deg); } }

/* --- Geselecteerd (fase 0.5) -------------------------------------------------
   Gedeelde staat voor kaart/rij/tabblad die aangevinkt of gekozen is —
   gebruikt de statustokens uit tokens.css zodat dit niet per component
   opnieuw wordt uitgevonden (zie bevinding 2 van het plan). */
.is-geselecteerd {
  background: var(--qm-staat-geselecteerd-vlak) !important;
  border-color: var(--qm-staat-geselecteerd-rand) !important;
}

/* --- Dialoog / modaal (fase 0.5) --------------------------------------------
   Native <dialog>, geen eigen open/dicht-boekhouding nodig — .showModal()/
   .close() plus ::backdrop doen het zware werk. */
.dialoog {
  border: 1px solid var(--a-rand);
  border-radius: var(--a-radius);
  padding: 0;
  width: min(32rem, 92vw);
  color: var(--a-ink);
  background: var(--a-vlak);
  box-shadow: 0 12px 40px rgba(0, 0, 0, .18);
}
.dialoog::backdrop { background: rgba(21, 34, 49, .45); }
.dialoog__kop {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 1rem 1.2rem; border-bottom: 1px solid var(--a-rand-zacht);
}
.dialoog__kop h2 { font-size: 1.05rem; margin: 0; }
.dialoog__sluit { border: 0; background: none; font-size: 1.2rem; line-height: 1; cursor: pointer; color: var(--a-ink-3); }
.dialoog__sluit:hover { color: var(--a-ink); }
.dialoog__inhoud { padding: 1.2rem; }
.dialoog__voet { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .6rem; padding: 1rem 1.2rem; border-top: 1px solid var(--a-rand-zacht); }

/* --- Beoordeling (fase 0.75) -------------------------------------------------
   Bron naast voorstel, met de confidence-badge en de twee acties die op de
   drie bestaande beoordelingsschermen (DMC-voorstel, documentextractie,
   DNA-conflict) al voorkwamen maar telkens los opgebouwd waren. */
.beoordeling {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  border: 1px solid var(--a-rand);
  border-radius: var(--a-radius);
  padding: 1rem;
  margin-bottom: 1rem;
}
@media (max-width: 640px) {
  .beoordeling { grid-template-columns: 1fr; }
}
.beoordeling__bron { border-right: 1px solid var(--a-rand-zacht); padding-right: 1rem; }
@media (max-width: 640px) {
  .beoordeling__bron { border-right: 0; border-bottom: 1px solid var(--a-rand-zacht); padding-right: 0; padding-bottom: 1rem; }
}
.beoordeling__label {
  display: flex; align-items: center; gap: .5rem;
  font-size: .72rem; font-weight: 500; text-transform: uppercase; letter-spacing: .04em;
  color: var(--a-ink-3); margin-bottom: .4rem;
}
.beoordeling__tekst { font-size: .88rem; color: var(--a-ink-2); }
.beoordeling__acties { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: .6rem; margin-top: .8rem; }

/* --- Tabbalk (statusfilters e.d.) ------------------------------------------ */

.tabbalk {
  display: flex; gap: .3rem; flex-wrap: wrap;
  margin-bottom: 1.2rem; border-bottom: 1px solid var(--a-rand-zacht); padding-bottom: .1rem;
}
.tabbalk a {
  display: flex; align-items: center; gap: .4rem;
  padding: .55rem .3rem; margin-bottom: -1px;
  font-size: .88rem; color: var(--a-ink-3);
  border-bottom: 2px solid transparent;
}
.tabbalk a:hover { color: var(--a-ink); }
.tabbalk a.is-actief { color: var(--a-ink); border-bottom-color: var(--a-accent); font-weight: 500; }
/* --a-ink-3 op --a-rand-zacht is 4,41 en dit is tekst van elf pixels; met
   --a-ink-2 wordt het 7,60, binnen dezelfde inktfamilie. */
.tabbalk a .telling {
  font-size: .72rem; background: var(--a-rand-zacht); color: var(--a-ink-2);
  padding: .05rem .4rem; border-radius: 999px; font-weight: 500;
}
.tabbalk a.is-actief .telling { background: var(--a-accent); color: #fff; }

/*
 * De inklapbare filterbalk van de dossierlijst.
 *
 * Vijftien tabs die wrappen worden op een telefoon vier regels hoog, en het
 * eerste dossier staat dan onder de vouw. Boven 900 px verandert er niets:
 * de samenvatting verdwijnt en de balk staat gewoon open, precies zoals ze
 * altijd stond. Zie C7 in OPEN-VRAGEN.md.
 */
.filterinklap > summary {
  display: flex; align-items: center; gap: .5rem;
  min-height: 44px; padding: .35rem .1rem;
  margin-bottom: .6rem;
  border-bottom: 1px solid var(--a-rand-zacht);
  font-size: .88rem; cursor: pointer;
  list-style: none;
}
.filterinklap > summary::-webkit-details-marker { display: none; }
/* Het driehoekje zelf, want de standaardmarkering hierboven is weggehaald:
   die staat in elke browser ergens anders en neemt de kleur van de tekst
   niet over. */
.filterinklap > summary::after {
  content: ""; margin-left: auto;
  width: .5rem; height: .5rem;
  border-right: 2px solid var(--a-ink-3); border-bottom: 2px solid var(--a-ink-3);
  transform: rotate(45deg) translate(-2px, -2px);
}
.filterinklap[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.filterinklap__wat { color: var(--a-ink-3); }
.filterinklap__nu {
  display: flex; align-items: center; gap: .4rem;
  color: var(--a-ink); font-weight: 500;
}
/* Boven 900 px bestaat de inklapper niet: geen samenvatting, geen rand, en
   het script laat <details> daar open staan. */
@media (min-width: 900px) {
  .filterinklap > summary { display: none; }
}

/* Tabbalk bínnen een kaart — bv. de vier chatkanalen. Kleiner en met minder
   lucht eronder, zodat hij niet concurreert met de hoofdtabbalk erboven. */
.tabbalk--onder { margin-bottom: .7rem; gap: .1rem; }
.tabbalk--onder a { font-size: .82rem; padding: .4rem .55rem; }

/* Tweede laag van de dossiertabbalk: de onderdelen binnen de gekozen groep.
   Geen eigen onderrand, anders staan er twee lijnen onder elkaar; pillen in
   plaats van onderstrepingen, zodat de twee lagen niet op elkaar lijken. */
.tabbalk--tweede {
  border-bottom: 0; gap: .15rem;
  margin-top: -.85rem; margin-bottom: 1.3rem;
}
.tabbalk--tweede a {
  font-size: .82rem; padding: .3rem .6rem; margin-bottom: 0;
  border-bottom: 0; border-radius: 999px;
}
.tabbalk--tweede a.is-actief { background: var(--a-vlak-accent); color: var(--a-ink); }

/*
 * De tabbalk mat 42,1 px op een breed scherm: acht-tiende vulling boven
 * en onder een regel van .88rem. Onder 900 px stond er al min-height 44
 * (zie de mediaregel verderop); boven de 900 ontbrak hij, en dat is de
 * balk waarlangs je op de dossierlijst, de takenlijst, de DMC-lijst, de
 * agentaanvragen en de statistiek de hele dag van filter wisselt.
 *
 * 1,9 px per tab, en de balk zelf wordt 1,9 px hoger. Verder verschuift
 * er niets: de tabs staan in een flexrij en de tekst blijft waar hij is.
 *
 * Nadrukkelijk niet .tabbalk--onder en .tabbalk--tweede. Dat zijn de
 * pillen binnen een kaart (de vier chatkanalen) en de tweede laag van de
 * dossiertabbalk. Die zijn met opzet klein en compact op een breed
 * scherm; onder 900 px krijgen ze hun 44 al van de mediaregels verderop,
 * waar het om vingers gaat en niet om een muis.
 */
/* min-width erbij, en dus ook centreren: een tab met alleen het woord
   "Alle" erin meet 34 px en haalt zijn hoogte wel maar zijn breedte
   niet. Centreren raakt alleen die smalle tabs; elke bredere tab is al
   even breed als zijn inhoud en verschuift geen pixel. */
.tabbalk:not(.tabbalk--onder):not(.tabbalk--tweede) > a {
  min-height: 44px; min-width: 44px; justify-content: center;
}

/*
 * De vouwregels van admin/rollen.php.
 *
 * Negentien stuks, en alleen daar: vier keer "Tonen" in de rechterkolom
 * van de rollentabel (21,8 px) en vijftien groepskoppen van de
 * rechtencatalogus (24 px). Onder 900 px staat er al summary { min-height:
 * 44px } voor alles; daarboven niet.
 *
 * Die regel hierheen halen zou elke <summary> in het beheer en in de drie
 * portalen raken, en dat zijn er tientallen op schermen waar niets mis
 * mee is. Gemeten over 21 beheerschermen is dit de enige plek waar een
 * summary onder de 44 blijft, dus krijgt hij een eigen klasse.
 *
 * Echt groter en geen onzichtbaar vlak: de vijftien groepskoppen staan
 * met .4rem tussenruimte onder elkaar, dus 30,4 px van hart tot hart. Een
 * onzichtbaar vlak van 44 zou daar veertien pixels over zijn buurman
 * heen liggen en precies de fout maken die het moest voorkomen.
 *
 * Prijs: admin/rollen.php gaat van 1720 naar ongeveer 2100 px lang.
 *
 * Vulling en min-height, geen flexbox. Een <summary> die op display:flex
 * gezet wordt verliest in een aantal browsers zijn driehoekje, en dat
 * driehoekje is het enige dat zegt dat er iets open kan. Dezelfde reden
 * staat verderop bij .fasestappen__vouw > summary.
 */
.rechtenvouw > summary { min-height: 44px; padding-block: .6rem; }

/* --- Formuliervelden ------------------------------------------------------ */

.veld { display: block; margin-bottom: 1.1rem; }
.veld > span,
.veld > .veld-label {
  display: block; font-size: .82rem; font-weight: 500; margin-bottom: .35rem;
}
.veld small { display: block; margin-top: .35rem; font-size: .78rem; color: var(--a-ink-3); line-height: 1.5; }

/*
 * "verplicht" achter het label van een verplicht veld.
 *
 * Hier stond zesentachtig keer een kaal sterretje, en op geen enkel scherm
 * een zin die zei wat dat sterretje betekent. Dezelfde keuze als bij het
 * aanvraagformulier van de reiziger: het woord in plaats van het teken, want
 * dan is er geen legende meer nodig. Zie .lbl-nodig in aanvraag.css.
 *
 * Dezelfde kleur en grootte als .veld small hierboven, zodat het bij het
 * label hoort en er niet bovenuit komt. Het draagt aria-hidden - het veld
 * zelf zegt required, en een schermlezer hoort het anders twee keer.
 */
.veld-nodig { font-size: .78rem; font-weight: 400; color: var(--a-ink-3); }

/* Een datumveld hoorde er niet bij, en dat zag je meteen: het viel terug op
   de browserstandaard van 29 pixels hoog met een lichtgrijze rand, naast een
   tekstveld van 43 met de projectrand. Op het scherm met de reisgegevens
   staan er zevenendertig van. Zoeken, tijd, maand en bestand zaten in
   hetzelfde schuitje. */
.veld input[type=text], .veld input[type=email], .veld input[type=tel],
.veld input[type=password], .veld input[type=number], .veld input[type=url],
.veld input[type=date], .veld input[type=datetime-local], .veld input[type=time],
.veld input[type=month], .veld input[type=search], .veld input[type=file],
.veld select, .veld textarea, .invoer {
  width: 100%;
  padding: .55rem .7rem;
  /* De donkerdere randkleur, niet --a-rand: op wit was het veld praktisch
     onzichtbaar. Zie de toelichting bij --qm-rand-veld in tokens.css. */
  border: 1px solid var(--a-rand-veld);
  border-radius: var(--a-radius);
  background: var(--a-vlak);
  font-size: .92rem;
  transition: border-color .2s var(--a-ease), box-shadow .2s var(--a-ease);
}
.veld input:focus, .veld select:focus, .veld textarea:focus, .invoer:focus {
  outline: none; border-color: var(--a-blauw); box-shadow: 0 0 0 3px rgba(61,110,158,.12);
}
/*
 * Diezelfde velden, maar dan met de focus van het toetsenbord.
 *
 * De regel hierboven zet de outline weg voor élke focus. Wat overblijft is een
 * randje dat van grijs naar blauw gaat plus een gloed van 12% dekking — genoeg
 * als je zelf net geklikt hebt en dus weet waar je bent, te weinig als je met
 * Tab door een formulier van veertig velden loopt en moet zien waar je terecht
 * kwam. :focus-visible zet de ring alleen terug wanneer de browser zegt dat de
 * focus van het toetsenbord komt; met de muis blijft het rustige beeld staan.
 */
.veld input:focus-visible, .veld select:focus-visible,
.veld textarea:focus-visible, .invoer:focus-visible {
  outline: 2px solid var(--a-blauw);
  outline-offset: 2px;
}
/*
 * Het veld dat de vorige verzending deed struikelen.
 *
 * aria-invalid vertelt een schermlezer welk veld het is; deze regel vertelt
 * het aan wie kijkt. Zonder haar leest iemand bovenaan "Het bedrag is geen
 * getal" en mag hij op een scherm met dertig velden zelf gaan zoeken welk
 * bedrag. Zie qm_veldfout() in includes/functions.php voor waar het attribuut
 * vandaan komt.
 *
 * Kleur alleen zou te weinig zijn: wie rood van grijs niet onderscheidt ziet
 * dan niets. Vandaar ook de dikkere rand en de gloed eromheen, dezelfde vorm
 * als de focusgloed hierboven maar in de foutkleur — drie signalen die niet
 * van elkaar afhangen.
 *
 * De selector staat niet meer binnen .veld. Die inperking leek netjes tot de
 * schermen erbij kwamen waar de invoer in een tabelcel staat en niet in een
 * veldblok: de betaalmijlpalen en de annuleringsladder van de lokale agent
 * zetten hun invoer in een <td>, en die velden droegen het attribuut wel maar
 * bleven er precies hetzelfde uitzien. Een element dat zichzelf ongeldig
 * noemt, hoort er ongeldig uit te zien, waar het ook staat.
 */
input[aria-invalid="true"], select[aria-invalid="true"],
textarea[aria-invalid="true"], .invoer[aria-invalid="true"] {
  border-color: var(--qm-fout-rand);
  border-width: 2px;
  box-shadow: 0 0 0 3px var(--a-fout-licht);
}
input[aria-invalid="true"]:focus, select[aria-invalid="true"]:focus,
textarea[aria-invalid="true"]:focus, .invoer[aria-invalid="true"]:focus {
  border-color: var(--qm-fout-rand);
  box-shadow: 0 0 0 3px var(--a-fout-licht);
}
/*
 * Een vinkje heeft geen rand die de browser laat kleuren, en een schaduw
 * eromheen valt weg achter het vakje zelf. Een omlijning ligt erbuiten en
 * werkt wel, ook op het akkoordvinkje waar een reiskantoor namens zijn klant
 * voor tekent — het enige veld op dat formulier dat niets van tekst is en
 * toch geweigerd kan worden.
 */
input[type="checkbox"][aria-invalid="true"], input[type="radio"][aria-invalid="true"] {
  outline: 2px solid var(--qm-fout);
  outline-offset: 2px;
  box-shadow: none;
}

.veld textarea { min-height: 6rem; resize: vertical; line-height: 1.6; font-family: inherit; }
.veld textarea.groot { min-height: 11rem; }

/*
 * Twee dingen die op een aanraakscherm te klein blijven.
 *
 * Eén: een zoekveld dat niet in een .veld staat. De regels hierboven maken elk
 * veld binnen een label 43 pixels hoog, maar de zoekbalk bovenaan een lijst
 * staat kaal in een knoppenrij en valt dus terug op de browserstandaard van
 * 29. Gemeten op de dossierlijst; hetzelfde geldt voor de zoekvelden op
 * contacten, taken, gebruikers, media en de andere lijsten. Sommige daarvan
 * dragen wél .invoer, en die zijn hier ongemoeid: 44 is niet lager dan 43.
 *
 * Twee: de links in de voettekst. Die staan op élk beheerscherm en zijn 18
 * pixels hoog. Ze worden zelden gebruikt, en dat is precies waarom ze moeten
 * kloppen: wie er één nodig heeft, heeft hem nodig.
 *
 * 900 en niet 700, om dezelfde reden als de aanraakblokken in portaal.css: een
 * tablet in staande stand is 768 of 810 px breed, en daar wordt getikt.
 */
@media (max-width: 900px) {
  input[type=search], input[type=text], input[type=email], input[type=tel],
  input[type=number], input[type=url], input[type=date], input[type=time],
  input[type=datetime-local], input[type=month], input[type=password],
  select {
    min-height: 44px;
  }

  /*
   * De kleurkiezers, en waarom hier de breedte meetelt.
   *
   * Elk ander veld hierboven strekt zich over de volle regel uit; alleen een
   * input[type=color] houdt de maat die de browser hem geeft. Op
   * admin/instellingen.php staan er drie naast elkaar - de huisstijlkleuren
   * van het aanspreekpunt en die van het deelbeeld. Gemeten bij 375 px breed:
   * 34 bij 44, op x 52..86, 92..126 en 131..165. Zes pixels ertussen, hart tot
   * hart veertig: je tikt de tweede kleur open terwijl je de eerste bedoelde,
   * en je ziet pas welke het was als de kiezer al openstaat.
   *
   * Met 44 staan ze op 52..96, 102..146 en 151..195 - nog altijd ruim binnen
   * de 298 px die de kolom breed is.
   */
  input[type=color] { min-width: 44px; min-height: 44px; }

  /* De tabbalk meet 42 px: acht-tiende padding boven en onder een regel van
     .88rem. Het blok op 700 px hierboven zet .tabbalk--tweede a wel op 44 en
     deze niet — een vergetelheid, want het commentaar daar noemt 44 als de
     maat. Twee pixels, op de balk waarmee je op elk dossierscherm van tab
     wisselt. */
  .tabbalk a { min-height: 44px; }

  /* De springlijst. inline-block en padding, geen flexbox: een label als
     "Gewenst of maximaal budget" moet over twee regels kunnen breken, en dat
     doet een flexregel niet vanzelf. De extra tussenruimte hoort erbij — met
     alleen padding raken twee doelen van 44 px elkaar en tik je de regel
     ernaast aan. */
  .sprongen > li > a {
    display: inline-block;
    padding-block: .7rem;
    min-height: 44px;
  }
  .sprongen > li + li { margin-top: .3rem; }

  /* Een <summary> is een knop: hij klapt een blok open. Hij ziet er alleen
     niet uit als een knop, en meet daardoor de hoogte van zijn tekstregel —
     24 px op de kwalificatietab.
     display:flex haalt in Chrome het driehoekje weg — elk ander display dan
     list-item doet dat — dus padding in plaats van uitlijning. */
  summary { min-height: 44px; padding-block: .5rem; }

  /* Een kleurveld valt terug op de browserstandaard van 34 bij 26. */
  input[type=color] { min-height: 44px; }

  /*
   * Een vinkje is 13 bij 13, en dat blijft zo: groter zetten maakt van een
   * vinkje een blokje. Het label eromheen is het doel, en dat meet 22 px. Het
   * label krijgt dus de ruimte, niet het vinkje.
   *
   * Padding en geen min-height met flexbox: op het instellingenscherm hoort
   * bij een vinkje een uitleg van drie regels, en dat label is 115 px hoog.
   * Met align-items:center zakt het vinkje dan naar het midden van die drie
   * regels, ver van de zin waar het bij hoort. Padding laat het vinkje staan
   * waar het staat en maakt alleen het doel groter.
   *
   * :has() is hier het enige dat werkt — er is geen klasse op deze labels en
   * ze staan door het hele beheer. Een browser die :has() niet kent slaat de
   * regel over en houdt wat er vandaag staat; niets breekt.
   */
  label:has(> input[type=checkbox]),
  label:has(> input[type=radio]) { padding-block: .7rem; }

  /*
   * Een hint die uit niets anders bestaat dan een link is geen hint maar een
   * knop in tekstvorm: "De eerste lege instelling invullen →". Op het
   * gezondheidsscherm staan er zestien, elk 18 px hoog, en ze zijn daar de
   * enige weg naar het scherm dat het probleem oplost. :only-child houdt de
   * regel weg bij een hint waar de link middenin een zin staat — die hoort
   * klein te blijven, anders breekt het lezen.
   */
  .a-hint--82 > a:only-child { display: inline-block; padding-block: .75rem; }

  /*
   * Een e-mailadres en een telefoonnummer zijn op een telefoon geen tekst maar
   * twee knoppen: tikken belt, tikken opent de mail. Op de overzichtstab van
   * een dossier staan ze onder elkaar in het contactblok, elk 18 px hoog.
   * inline-block met padding en geen onzichtbaar vlak: ze staan met een
   * regelafbreking onder elkaar, en een vlak van 44 px zou de regel eronder
   * overlappen. Padding duwt de regels uit elkaar in plaats van eroverheen.
   */
  a[href^="mailto:"], a[href^="tel:"] {
    display: inline-block;
    padding-block: .65rem;
  }

  /*
   * "ga erheen" achter de eerstvolgende stap. Dit staat middenin een zin, en
   * de regel is dat een link in lopende tekst klein blijft — anders breekt het
   * lezen. Hier maak ik één uitzondering: deze zin ís de eerstvolgende stap
   * die het systeem voorstelt, en de link is de enige manier om hem te volgen.
   * Hij staat achteraan de laatste regel van de alinea, dus de padding duwt
   * alleen die regel wat verder open en overlapt niets.
   */
  .fasestappen__volgende a { display: inline-block; padding-block: .72rem; }

  /*
   * En om dezelfde reden de bronlink van een afgeleide stap.
   *
   * "Het systeem leidt dit af uit het dossier — bekijken." Die link is het
   * enige wat je op zo'n regel kan aanraken, en hij is de manier om te zien
   * waaróp het systeem zich baseert. Gemeten op 375 px: 45 bij 16 px, op
   * elk tabblad vijf keer. Hij staat achteraan de zin, dus de padding duwt
   * alleen die laatste regel open.
   */
  .fasestappen__bron a { display: inline-block; padding-block: .5rem; }

  /*
   * De kolomkoppen van een tabel zijn links: erop tikken sorteert. Bij 768 px
   * meet zo'n kop 16 px. Onder de 700 telt dit niet meer mee — daar wordt de
   * tabel een kaart en verdwijnt de kop helemaal — dus dit gaat zuiver over
   * de strook tussen 701 en 900, de tablet in staande stand.
   */
  .tabel th a { display: inline-block; padding-block: .8rem; }

  /*
   * De kruimel boven de titel is de weg terug naar de lijst, en hij meet 42
   * bij 16. Groter zetten mag niet: een kruimel hoort klein en rustig te zijn
   * boven de titel waar het om gaat. Dus krijgt hij een onzichtbaar vlak, net
   * als de taalknop en de voettekstlink. Hij staat alleen in zijn eigen blok,
   * dus er is niets waarmee dat vlak kan overlappen.
   */
  .kopbalk__kruimel a { position: relative; display: inline-block; }
  .kopbalk__kruimel a::after {
    content: "";
    position: absolute;
    top: 50%; left: 0; right: 0;
    height: 44px;
    transform: translateY(-50%);
  }

  /* De wegwijzer op het instellingenscherm stond hier; die 44 geldt sinds
     de tweede ronde kliksdoelen op elke breedte, zie .instelzoek__groepen
     verderop in dit bestand. */

  /*
   * Vijf maten die tot nu toe achter 700 px stonden. Bij 768 px meet de
   * notificatiebel 32 px, en die staat op élk scherm rechtsboven.
   *
   * .dagsprong staat op de takenlijst en houdt zijn min-width erbij: dat zijn
   * de dagkoppen, en die zijn breder dan hoog te raken.
   */
  /* De notificatiebel stond in deze rij en staat sinds de tweede ronde
     kliksdoelen op 44 bij 44 op elke breedte, zie .notificaties__knop
     eerder in dit bestand. */
  .dagsprong a,
  .tabbalk--tweede a,
  .knop--klein,
  .dialoog__sluit {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  /* Deze regel verloor van `.dagsprong a { min-width: 1.7rem }` verderop in
     dit bestand — gelijk gewicht, latere plek. Ze staat daarom nóg eens ná
     .dagsprong, onderaan bij "De sprongbalk op een telefoon". */
  .dagsprong a { min-width: 44px; }

  /*
   * De titel in een tabelrij: het dossiernummer, de naam van het contact, de
   * titel van de pagina. Dat is niet één van de handelingen op de rij, dat is
   * dé handeling — en het is precies wat het kleinst is. Op de dossierlijst
   * meet ik er vijftig van 19 px, op contacten zevenendertig.
   *
   * Groter zetten mag niet; de tekstgrootte is de leesbaarheid van de rij. Dus
   * wordt de link een blok van 44 px met de tekst in het midden. Dat maakt een
   * rij ongeveer 25 px langer, een kleine 5 procent — goedkoop voor de enige
   * weg naar binnen.
   *
   * inline-flex en niet block: een titel die over twee regels loopt moet zijn
   * eigen breedte houden, anders vangt de link de lege ruimte rechts op en
   * open je een dossier door naast de tekst te tikken.
   */
  /* Niet alleen in een tabel: op admin/mails.php, automatisering.php en
     rollen.php staan de rijen als kaarten in divs, en daar gold deze regel
     niet. Gemeten op 375 px: een mailrij is 66 px hoog en de titel erin was
     183 bij 20 px — de rest van de rij deed niets. De reden hierboven is
     dezelfde, of de rij nu een <tr> of een <div> is. */
  a.titel {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    /* Een bestemming heet ook wel eens "Chili" of "Servie": vijftien
       titels op admin/bestemmingen.php bleven onder de 44 px breed,
       terwijl ze wel 44 hoog waren. Onzichtbaar, want een titel heeft
       geen achtergrond en geen rand; rechts ernaast staat lege cel. */
    min-width: 44px;
  }

  /*
   * Twee plekken waar dezelfde titel geen a.titel heet.
   *
   * De regel hierboven werkt op een klasse, en twee schermen zetten die
   * klasse niet. Het gaat om precies hetzelfde soort link: het dossiernummer,
   * de enige weg van de lijst naar het dossier.
   *
   *   - admin/control-tower.php zet het nummer als <h3> boven elke kaart.
   *     Gemeten bij 375 px breed: 161 bij 20 px.
   *   - admin/taken.php zet het in de dossierkolom van de takenlijst, die op
   *     een telefoon een kaartrij wordt. Gemeten bij 375 px: 131 bij 16 px.
   *
   * De cel op taken staat vol: het kolomkopje als <span>, de link, en na een
   * <br> de bestemming. :only-child helpt daar dus niet. Wat wél onderscheidt
   * is het aantal links in de cel: op admin/rollen.php staan er honderdvier-
   * endertig rolnamen als komma-lijst in dezelfde soort cel, en dat zijn
   * tekstlinks in een zin - die horen klein te blijven en horen elkaar niet te
   * overlappen. :not(:has(a ~ a)) laat precies die met rust: gemeten raakt de
   * regel op rollen alleen de cellen met één rol erin, en de pagina wordt daar
   * geen pixel langer (2174 px voor en na).
   */
  .kaart h3 > a,
  td.a-hint:not(:has(a ~ a)) > a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    min-width: 44px;
  }

  /*
   * De tweede kolom van admin/bestemmingen.php: 85 keer "Inhoud
   * bewerken". Op een breed scherm breekt die tekst over twee regels en
   * haalt hij zijn hoogte; op 375 px staat hij op een regel van 16 px in
   * een cel van 58,5 px. De ruimte is er dus, de link gebruikt hem niet.
   *
   * Onzichtbaar vlak en niet groter maken: de cellen staan op een
   * telefoon onder elkaar met hun kolomkopje erboven, en een link die
   * zelf 44 px wordt duwt elke rij 28 px langer. 85 rijen, ruim
   * tweeduizend pixels op een lijst die al 36.928 px lang is.
   */
  .tabel td.a-hint--zonder-kleur > a { position: relative; display: inline-block; }
  .tabel td.a-hint--zonder-kleur > a::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 44px;
    min-width: 44px;
    transform: translateY(-50%);
    z-index: -1;
  }
}

/*
 * De titel in een rij, nu ook op een breed scherm.
 *
 * Hierboven, onder 900 px, wordt a.titel zelf een blok van 44 px. Boven de
 * 900 mag dat niet: daar is de tabel dicht en zou elke rij 26 px langer
 * worden. Op de dossierlijst zijn dat vijftig rijen, op bestemmingen
 * vijfentachtig. Gemeten is de link daar 17 px hoog, terwijl de rij eromheen
 * 69 px meet (contacten), 95 (mails) of 119 (bestemmingen): de ruimte is er
 * al, alleen de link gebruikt hem niet.
 *
 * Dus hetzelfde onzichtbare vlak als bij .admin-voet a. De kortste afstand
 * tussen twee opeenvolgende titels die gemeten is, is 58,5 px op contacten,
 * en dat is ruim boven de 44: de vlakken van twee rijen raken elkaar niet, en
 * je kan dus niet per ongeluk de rij erboven openen.
 *
 * inline-block en niet inline: een absoluut geplaatst ::after heeft een
 * blokvormig anker nodig. De titel blijft gewoon afbreken over meerdere
 * regels, want een inline-block wikkelt zijn eigen tekst.
 */
@media (min-width: 901px) {
  a.titel { position: relative; display: inline-block; }
  a.titel::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 44px;
    /* left en right en min-width samen: de doos is overbepaald, dus wint
       left en groeit het vlak naar rechts. Een titel als "Kroatie" is
       33 px breed en stond daarmee nog altijd onder de 44; rechts naast
       een titel in de eerste kolom staat niets anders dan lege cel. */
    min-width: 44px;
    transform: translateY(-50%);
    /*
     * z-index: -1 en dat is geen detail.
     *
     * Zonder deze regel ligt het vlak bovenop wat eronder staat. Op
     * admin/rollen.php staan de rollen als kaartrijen onder elkaar en steekt
     * het vlak van "Redacteur" 1 px over de knop Bijtrekken van de rij
     * eronder. Eén pixel, maar het is wél de bovenste rand van een knop, en
     * wie daar tikt zou een rol openen in plaats van een recht bij te
     * trekken. Met z-index -1 zakt het vlak onder de echte knoppen: het vangt
     * nog steeds elke tik die anders naast de titel viel, maar het wint het
     * nooit van een knop die er echt staat. Nagemeten op negen schermen:
     * klikvlak blijft 44 tot 71 px, overgenomen tikken 0 (was 2).
     */
    z-index: -1;
  }
}

/*
 * Dezelfde titel, maar zonder de klasse .titel.
 *
 * Op admin/paginas.php (98 rijen) en admin/financien.php (35 rijen) is de
 * eerste cel van elke rij een link: de paginanaam, het dossiernummer. Die
 * link heeft daar nooit class="titel" gekregen. Gemeten 17 px hoog, op
 * beide breedtes, in een rij van 119 px (paginas) of 71 px (financien).
 * Het is precies dezelfde link met precies hetzelfde werk als een .titel
 * elders, alleen zonder de klasse.
 *
 * De klasse alsnog in de php zetten kan niet zonder het beeld te
 * veranderen: .tabel a.titel is font-weight 500 en die rijen zouden
 * zwaarder gaan staan. Dus hetzelfde onzichtbare vlak, maar via de plaats
 * in de rij in plaats van via een klasse.
 *
 * Op elke breedte, niet alleen boven 900. Bij .titel groeit de link onder
 * 900 px zelf tot 44 en worden de rijen langer; hier zou dat op
 * paginas.php 98 rijen raken. De ruimte is er al: op 375 px meet de cel
 * 80,8 px en staat de link er alleen in, met een kolomkopje erboven en
 * een grijze omschrijving eronder, allebei tekst en geen bediening. De
 * kortste afstand tussen twee opeenvolgende van deze links is 285,8 px.
 *
 * :not(.titel), anders overschrijft deze regel (0,2,2) de inline-flex die
 * a.titel (0,1,1) onder 900 px krijgt.
 */
.tabel td:first-child > a:not(.titel) { position: relative; display: inline-block; }
.tabel td:first-child > a:not(.titel)::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 44px;
  min-width: 44px;
  transform: translateY(-50%);
  /* Zie de uitleg bij a.titel::after hierboven: zonder dit ligt het vlak
     bovenop de knoppen van de rij ernaast. */
  z-index: -1;
}
/*
 * minmax(0, 1fr) en niet 1fr: een 1fr-kolom mag standaard niet kleiner worden
 * dan de breedste onbreekbare inhoud erin. Op het profielscherm staat naast de
 * tweestapsverificatie een tabel met browsergegevens van elke sessie, en die
 * duwde de rechterkolom naar 1048px — waarna het volledige beheerscherm op een
 * tablet zijwaarts schoof. Met een ondergrens van nul mag de kolom krimpen en
 * wikkelt de inhoud zoals bedoeld.
 */
.veld--rij { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
@media (max-width: 700px) { .veld--rij { grid-template-columns: 1fr; } }
/*
 * LET OP voor wie hier iets aan toevoegt: .veld--rij is een RASTER.
 *
 * Op vijftien plaatsen in admin/ en includes/ staat op een kind van deze rij
 * nog een inline style="flex:1", style="flex:0 0 auto" of
 * style="flex-wrap:wrap". Dat is dode code: flex-eigenschappen doen niets in
 * een grid-container. Ze zijn overgebleven uit de tijd dat .veld--rij een
 * flexrij was, en ze verklaren waarom een veld dat "de volle breedte" moest
 * krijgen dat nooit kreeg. (align-items en align-self werken wél: die zijn van
 * de box-alignment-specificatie en gelden in beide.)
 *
 * Wat je in plaats daarvan gebruikt:
 *
 *   flex: 1 1 100%      ->  class="veld veld--vol"   (de hele rij breed)
 *   flex: 1             ->  niets; een rastercel vult haar kolom al
 *   flex: 0 0 auto      ->  niets, of justify-self: start op het element
 *   flex-wrap: wrap     ->  niets; het raster wikkelt zelf op 700px
 *
 * .veld--vol werkt in elk raster met twee of drie kolommen, dus ook in
 * .veld--rij3 hieronder.
 */
.veld--vol { grid-column: 1 / -1; }
/*
 * Een knop die rechtstreeks in zo'n raster staat, is een knop en geen veld.
 *
 * Een grid-cel rekt haar inhoud standaard op. Een submitknop die als directe
 * dochter van .veld--rij staat werd daardoor een witte balk van vijfhonderd
 * pixels breed met een woord erin, op dezelfde hoogte en met dezelfde rand als
 * de invoervelden ernaast. Op het reisprogramma las "Opslaan" zo als een leeg
 * tekstveld. Deze regel geeft de knop haar eigen breedte terug en zet ze op de
 * onderlijn van de rij, waar ze naast het laatste veld hoort.
 */
.veld--rij > .knop { justify-self: start; align-self: end; }
/*
 * Een rij van drie: veld, vergelijking, waarde.
 *
 * Dit stond als inline stijl op de voorwaardenrij van een automatiseringsregel,
 * en een inline stijl kent geen mediaquery. Op een telefoon werden de drie
 * kolommen elk ruim tachtig pixels breed, waarin geen enkele keuze nog leesbaar
 * was. Onder de zeven honderd stapelen ze nu, net als .veld--rij hierboven.
 */
.rij-drie { display: grid; grid-template-columns: 1fr 1fr 1.4fr; gap: .5rem; align-items: end; }
@media (max-width: 700px) { .rij-drie { grid-template-columns: 1fr; } }


.veld-fout { color: var(--a-fout); font-size: .82rem; margin-top: .35rem; }
/* Een bedrag onder nul in een tabel vol bedragen. Zonder dit leest een marge
   van -620,00 als elk ander getal in de kolom. De td-variant staat erbij omdat
   de optieregel ook .a-hint--82 draagt, en die zet verderop in dit bestand een
   eigen kleur; een losse klasse alleen zou daar verliezen. */
.bedrag-min, td.bedrag-min { color: var(--a-fout); }

.vink { display: flex; align-items: flex-start; gap: .6rem; font-size: .9rem; margin-bottom: .5rem; }
.vink input { margin-top: .25rem; flex: none; }

/*
 * Een groep vinkjes of keuzerondjes met een naam erboven.
 *
 * Een <fieldset> is het enige element dat een schermlezer laat zeggen bij welke
 * vraag een rondje hoort; zonder hoor je zestig losse vinkjes zonder groep. De
 * browser geeft hem alleen een rand, een merkwaardige binnenmarge en een
 * legenda die over die rand heen valt - dit haalt dat allemaal weg, zodat een
 * .veldgroep er precies zo uitziet als de .veld eromheen.
 *
 * min-inline-size: 0 is geen sier: een fieldset heeft een ingebakken
 * min-width: min-content die niet uit te schakelen is met width, en die duwt
 * een raster met een lange optieregel erin breder dan het scherm.
 */
fieldset.veldgroep {
  border: 0;
  padding: 0;
  margin: 0 0 1.1rem;
  min-inline-size: 0;
}
fieldset.veldgroep > legend {
  display: block;
  padding: 0;
  font-size: .82rem;
  font-weight: 500;
  margin-bottom: .35rem;
}

/* --- Rechtenmatrix (rollen) ------------------------------------------------ */

/* .rechten-groep is sinds admin/rol.php een <fieldset>: de zestig vinkjes
   erbinnen hoorden bij een groepsnaam die alleen visueel bestond. De reset
   hierboven bij .veldgroep geldt ook hier. */
.rechten-groep { padding: 1.1rem 0; border-top: 1px solid var(--a-rand-zacht); }
.rechten-groep:first-of-type { padding-top: 0; border-top: 0; }
.rechten-groep > legend { display: block; padding: 0; width: 100%; }
.rechten-groep h3 {
  font-family: var(--a-sans); font-size: .72rem; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--a-ink-3); margin: 0 0 .8rem;
}
.rechten-lijst { display: grid; grid-template-columns: repeat(2, 1fr); gap: .3rem 1.5rem; }
@media (max-width: 780px) { .rechten-lijst { grid-template-columns: 1fr; } }
.vink--recht {
  align-items: flex-start; padding: .5rem .6rem; border-radius: var(--a-radius);
  margin-bottom: 0; transition: background .15s var(--a-ease);
}
.vink--recht:hover { background: var(--a-rand-zacht); }
.vink--recht span { display: block; }
.vink--recht small { display: block; color: var(--a-ink-3); font-size: .78rem; margin-top: .1rem; line-height: 1.4; }

/* --- Rijkaart (regels, e.d. buiten een tabel) ------------------------------ */

.rijkaart {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .85rem 0; border-top: 1px solid var(--a-rand-zacht);
}
.rijkaart:first-of-type { border-top: 0; }
.rijkaart .rechts { display: flex; align-items: center; gap: .6rem; flex: none; }

/* Op een telefoon past de naam plus de knoppen niet naast elkaar; dan gaan
   ze onder elkaar staan in plaats van de pagina breder te maken. */
@media (max-width: 700px) {
  .rijkaart { flex-wrap: wrap; gap: .6rem; }
  .rijkaart .rechts { flex-wrap: wrap; }
}

/*
 * Telefoon: de balken mogen het scherm niet opeten.
 *
 * De dossiertabbalk stapelde tot drie rijen boven élke inhoud, en de
 * dagsprongbalk plakte daar nog eens onder de kopbalk bij. Samen bleef er een
 * derde van een telefoon over om in te werken. De portaalnavigatie loste dit
 * al op met horizontaal schuiven; hier hetzelfde recept.
 *
 * De minimumhoogtes eronder zijn dezelfde 44 pixels die de kaartweergave
 * hierboven al aanhoudt: kleiner is met een vinger niet te raken.
 */
@media (max-width: 700px) {
  .tabbalk {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  /*
   * flex: none, en dat is het verschil tussen leesbaar en onleesbaar.
   *
   * Een tab in deze balk is een flexitem, en een flexitem mag krimpen. Wat
   * hem normaal tegenhoudt is min-width: auto — de browser laat een flexitem
   * niet kleiner worden dan zijn inhoud. Die rem is verderop weggenomen:
   * `.tabbalk:not(--onder):not(--tweede) > a` zet min-width: 44px, en dat
   * verving de auto. Vanaf dat moment kón elke tab wél krimpen, tot precies
   * die 44 pixels. Met white-space: nowrap erbij loopt de tekst gewoon door
   * buiten zijn eigen doos.
   *
   * Gemeten op admin/dossier.php?id=269 bij 375 px breed: alle acht de tabs
   * exact 44 px breed, terwijl ze samen 736 px inhoud hebben. Ze stonden dus
   * over elkaar heen gedrukt — het scherm las "DossieReizigeGesprekPartners"
   * en er was geen enkele manier om te zien welk tabblad je aanraakte. De
   * schuifbalk was er wel (scrollWidth 425 tegen clientWidth 335), maar
   * schoof langs een stapel overlappende woorden.
   *
   * flex: none haalt zowel het krimpen als het groeien weg. De tabs krijgen
   * hun echte breedte terug (70 tot 142 px), de balk schuift over 736 px, en
   * de pagina zelf blijft op 0 px zijwaartse overloop staan.
   */
  .tabbalk a { white-space: nowrap; padding-left: .6rem; padding-right: .6rem; flex: none; }
  /* De tabbalk schuift hier horizontaal (overflow-x hierboven), en een
     overflow-container snijdt af in beide richtingen. Een ring 2px búiten de
     tab valt daardoor weg bij de eerste en de laatste tab. Naar binnen blijft
     hij heel. */
  .tabbalk a:focus-visible { outline-offset: -2px; }
  /* De positie is een layoutkeuze en hoort hier. De maten die hier stonden
     zijn verhuisd naar de mediaregel op 900 px verderop in dit bestand: ze
     gaan over vingers, niet over opbouw, en tussen 701 en 900 px viel er
     niets terug.

     Deze regel verloor van `position: sticky` bij .dagsprong verderop in dit
     bestand: gelijk gewicht, latere plek. Ze staat daarom nóg eens ná
     .dagsprong, onderaan bij "De sprongbalk op een telefoon". */
  .dagsprong { position: static; }

  /*
   * De tabbalk schuift hier, maar zei nergens dát hij schoof.
   *
   * Op het dossierscherm staat ongeveer 697 pixels aan tabs in een container
   * van 335: vijf van de acht groepen lopen dus buiten beeld, en tot je bij
   * toeval zijwaarts veegt lijkt de balk gewoon afgelopen. Twee paar
   * achtergronden lossen dat op zonder een pixel opmaak of een regel script:
   *
   *   - het dekkende paar (background-attachment: local) schuift mee met de
   *     inhoud en dekt de schaduw af zolang je aan die kant al bent;
   *   - het schaduwpaar (scroll) blijft op de rand van de balk staan.
   *
   * Zit je helemaal links, dan ligt het dekkende vlak precies over de linker
   * schaduw en zie je er maar één - rechts. Schuif je naar het midden, dan
   * verschijnen ze allebei. Het is de enige oplossing die weet hoevéél er nog
   * komt zonder dat er iets meet.
   *
   * De dekkleur verschilt per plek: de hoofdtabbalk staat op het papier van de
   * pagina, de tabbalk binnen een kaart op het wit van die kaart.
   */
  .tabbalk {
    --tabbalk-vlak: var(--a-paper);
    background-image:
      linear-gradient(to right, var(--tabbalk-vlak), transparent),
      linear-gradient(to left,  var(--tabbalk-vlak), transparent),
      linear-gradient(to right, rgba(26, 24, 20, .20), transparent),
      linear-gradient(to left,  rgba(26, 24, 20, .20), transparent);
    background-position: left center, right center, left center, right center;
    background-repeat: no-repeat;
    background-size: 2.2rem 100%, 2.2rem 100%, .9rem 100%, .9rem 100%;
    background-attachment: local, local, scroll, scroll;
  }
  .kaart .tabbalk { --tabbalk-vlak: var(--a-vlak); }
  /* De portalen zetten een ander papier onder de pagina (--a-vlak-zacht). Ze
     gebruiken vandaag geen .tabbalk, maar als dat verandert hoort de dekkleur
     mee te veranderen, anders staat er een lichte veeg op de rand. */
  body.portaal .tabbalk { --tabbalk-vlak: var(--a-vlak-zacht); }

  /*
   * De plakkende kopbalk op een telefoon.
   *
   * Met 1,1rem lucht boven en onder, 1,5rem tussen de onderdelen en vijf
   * blokken die elk hun eigen breedte houden, brak ze op 375 pixels over drie
   * of vier regels: hamburger, titel, zoekveld, bel en knoppen elk apart. Dat
   * is ruim tweehonderd pixels die blijven staan terwijl je scrolt - een kwart
   * van het scherm, boven élke pagina.
   *
   * Het wordt hier één afspraak: de eerste regel draagt de hamburger, de titel
   * en de bel, de tweede het zoeken en de knoppen. De titel is het enige blok
   * dat mag krimpen; zonder min-width:0 duwt een lange dossiernaam de bel van
   * de regel af. De kruimel blijft staan - daar zit vaak de enige link terug
   * naar het dossier.
   */
  .kopbalk {
    padding: .55rem 1rem;
    gap: .45rem .6rem;
  }
  .kopbalk h1 { font-size: 1.08rem; }
  .kopbalk__kruimel { font-size: .72rem; margin-bottom: .1rem; }
  .kopbalk > div:first-of-type { flex: 1 1 6rem; min-width: 0; }
  .notificaties { margin-left: 0; }
  .kopbalk__zoeken { order: 5; flex: 1 1 55%; }
  .kopbalk__acties { order: 6; margin-left: 0; flex: 1 1 auto; justify-content: flex-end; }

  /*
   * Het aanraakvlak van de taalkiezer.
   *
   * De knop meet 28 bij 19 pixels. De 44px-regel in portaal.css noemt de bel,
   * de paginering en de sprongbalk, maar niet dit: de taalkiezer hangt in
   * admin.css omdat hij ook op de aanmeldschermen staat, waar portaal.css niet
   * geladen wordt. Groter máken mag niet - twee letters naast twee letters
   * horen klein - dus krijgt hij een onzichtbaar vlak van 44 pixels hoog en
   * een halve tussenruimte breed aan elke kant. De tussenruimte gaat daarvoor
   * van .1rem naar 1.2rem: elk vlak claimt precies zijn eigen helft, zodat NL
   * en FR elkaar niet overlappen en je nooit de verkeerde taal aantikt.
   *
   * Alleen de knop, niet .portaal-taal__nu: dat is de taal waar je al staat,
   * een <span> zonder handeling erachter.
   */
  /* Het vlak zelf én de tussenruimte staan verderop bij elkaar, in een eigen
     mediaregel op 900 px. Ze stonden hier op 700, en dat was twee keer fout.

     Eén: de tussenruimte verloor. Beide regels wegen even zwaar (één klasse),
     dus won de laatste in het bestand — .1rem. De twee vlakken van 44 pixels
     overlapten daardoor ruim zeventien pixels en je tikte de verkeerde taal
     aan, precies wat het vlak moest voorkomen.

     Twee: 700 is de verkeerde grens. Boven de 700 verdween het vlak, en dan
     blijft er een doel van 19 bij 30 over. Op een tablet in staande stand
     (768 of 810 breed) wordt er getikt en niet geklikt. Zie de mediaregel op
     900 px verderop in dit bestand. */

  /*
   * Het zoekvak van de kopbalk, en de vouwregel van de fasestappen.
   *
   * Drie bedieningen die op élk beheerscherm staan en alle drie te klein om
   * op een telefoon te raken: het zoekvak meet 29 pixels hoog, de knop met
   * het vergrootglas ernaast 36 bij 29, en de regel "Alle stappen van deze
   * fase" 20. De knoppen van dit beheer staan op 44 (.knop), maar geen van
   * deze drie is een .knop, dus geen van drieën kreeg die maat mee.
   *
   * Het zoekvak weegt het zwaarst. Op een telefoon is het de enige weg naar
   * iets dat niet toevallig op het scherm staat, en het was met 29 pixels
   * het kleinste vlak van de hele kopbalk.
   *
   * De vouwregel groeit met vulling en niet met een hoogte: een <summary>
   * die op flex gezet wordt verliest in een aantal browsers zijn driehoekje,
   * en dat driehoekje is het enige dat zegt dat er iets open kan.
   */
  /* Het zoekvak en de knop met het vergrootglas staan sinds de tweede ronde
     kliksdoelen op elke breedte op 44, zie .kopbalk__zoeken vooraan in dit
     bestand. Wat hier overblijft is de vouwregel. */
  .fasestappen__vouw > summary { padding: .75rem 0; }
}

/* --- Voet van het beheer -------------------------------------------------- *
 * Er was geen enkel <footer>-landmerk in het beheer: wie met een schermlezer
 * van landmerk naar landmerk springt kwam na <main> op niets meer uit, en had
 * dus geen manier om te horen dat de pagina daar ophield. Klein gehouden - dit
 * is werkgereedschap, geen website - met de enige link die op een scherm van
 * tweehonderd rijen echt helpt.
 */
.admin-voet {
  padding: 1rem clamp(1.25rem, 3vw, 2.25rem) 1.6rem;
  border-top: 1px solid var(--a-rand-zacht);
  font-size: .78rem;
  color: var(--a-ink-2);
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
}
.admin-voet p { margin: 0; }
.admin-voet a { text-decoration: underline; text-underline-offset: .18em; }
/*
 * Het onzichtbare vlak steekt boven en onder de link uit in plaats van de
 * link zelf te vergroten: de voettekst is een regel van .78rem, en die
 * hoogte hoort ze te houden. De links staan met 1rem tussenruimte naast
 * elkaar, dus horizontaal raken de vlakken elkaar niet.
 *
 * Deze regel stond achter een mediaregel op 900 px en staat nu vooraan.
 * "Terug naar boven" is op een breed scherm net zo goed 15 px hoog als op
 * een telefoon, en op een lijst van tweehonderd rijen is het de enige weg
 * terug naar de kop. Het vlak past ruim binnen de vulling van de voet
 * (1rem boven, 1,6rem onder), dus de pagina wordt er geen pixel langer
 * van.
 */
.admin-voet a { position: relative; display: inline-block; }
.admin-voet a::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 44px;
  min-width: 44px;
  transform: translateY(-50%);
  z-index: -1;
}

/* --- Springlijsten -------------------------------------------------------- */

/*
 * Een lijst van gegevens die nog ontbreken, waarbij elke regel een link is
 * naar het veld waar dat gegeven ingevuld wordt. Staat op de kwalificatietab
 * van een dossier (daar tot tweeënveertig regels lang) en op het
 * instellingenscherm.
 *
 * Dit is de enige lijst in het beheer waar aanklikken het werk zelf is: ze
 * bestaat om leeg te raken. Vandaar dat de link hier meer ruimte krijgt dan
 * een link in een lopende zin, en op een aanraakscherm de volle 44 pixels.
 */
.sprongen { margin: .2rem 0 0; padding-left: 1.1rem; }
.sprongen > li { font-size: .9rem; }
.sprongen > li + li { margin-top: .15rem; }
.sprongen__hard {
  font-size: .75rem;
  color: var(--qm-fout-donker);
  white-space: nowrap;
}
.sprongen__vouw { cursor: pointer; }
.sprongen__groep {
  font-size: .8rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--a-ink-3);
}

/* --- Lege staat ----------------------------------------------------------- */

.leeg {
  text-align: center; padding: 3.5rem 1.5rem;
  color: var(--a-ink-3);
  border: 1px dashed var(--a-rand);
  border-radius: 8px;
  background: var(--a-vlak);
}
.leeg h2, .leeg h3 { font-family: var(--a-serif); font-size: 1.4rem; font-weight: 300; color: var(--a-ink); margin-bottom: .5rem; }

/* --- Mobiel --------------------------------------------------------------- */

.zij-knop { display: none; }

@media (max-width: 900px) {
  .admin { grid-template-columns: 1fr; }
  .zijbalk {
    position: fixed; inset: 0 auto 0 0; width: min(280px, 85vw); z-index: 60;
    transform: translateX(-100%);
    box-shadow: 0 0 50px rgba(0,0,0,.3);
    /* Weggeschoven is niet hetzelfde als weg. Met alleen translateX blijft elke
       menulink in de tabvolgorde staan: op een telefoon liep de eerste Tab dus
       door dertig links buiten beeld voor je bij de pagina zelf was, zonder dat
       er iets te zien was. visibility haalt ze er echt uit, en omdat ze
       meeloopt in de overgang gebeurt dat pas nadat de balk uit beeld geschoven
       is. */
    visibility: hidden;
    transition: transform .3s var(--a-ease), visibility .3s var(--a-ease);
  }
  /* Eigen transition, zonder visibility: anders staat de balk op het moment
     dat de klasse erbij komt nog op hidden, en doet de focus() in
     admin/onderdelen/voet.php niets. Bij het sluiten geldt de regel
     hierboven weer, en daar hoort de vertraging wel. */
  body.menu-open .zijbalk {
    transform: none; visibility: visible;
    transition: transform .3s var(--a-ease);
  }
  body.menu-open::after {
    content: ""; position: fixed; inset: 0; background: rgba(10,14,20,.5); z-index: 50;
  }
  .zij-knop {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; border: 1px solid var(--a-rand);
    background: var(--a-vlak); border-radius: var(--a-radius); cursor: pointer;
  }
}

/* --- Bezoekcijfers --------------------------------------------------------- */

.kengetal {
  display: grid; gap: .25rem; align-content: start;
  padding: 1rem 1.1rem;
  border: 1px solid var(--a-rand-zacht);
  border-radius: var(--a-radius);
  background: var(--a-vlak);
}
.kengetal__label { font-size: .78rem; color: var(--a-ink-3); letter-spacing: .02em; }
.kengetal__getal { font-size: 1.9rem; font-weight: 500; line-height: 1.1; color: var(--a-ink); }
.kengetal__bij   { font-size: .78rem; color: var(--a-ink-3); }

/* De trechter van de intake. */
.trechter { display: grid; gap: .35rem; }
.trechter__rij {
  display: grid;
  grid-template-columns: minmax(0, 22rem) minmax(0, 1fr) 4.5rem 4rem;
  align-items: center; gap: .9rem;
}
.trechter__naam {
  font-size: .84rem; color: var(--a-ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.trechter__balk {
  display: block; height: 1.4rem; border-radius: 3px;
  background: var(--a-rand-zacht); overflow: hidden;
}
.trechter__vul {
  display: block; height: 100%; border-radius: 3px;
  background: var(--a-accent); transition: width .3s ease;
}
.trechter__vul--let-op { background: var(--qm-waarschuwing-sterk); }
.trechter__getal   { text-align: right; font-variant-numeric: tabular-nums; font-size: .86rem; }
.trechter__verlies { text-align: right; font-variant-numeric: tabular-nums; font-size: .78rem; color: var(--a-ink-3); }
.trechter__verlies.is-let-op { color: var(--qm-waarschuwing-sterk); font-weight: 500; }

/* Bezoekers per dag. */
.dagbalken {
  display: flex; align-items: flex-end; gap: 2px;
  height: 120px; overflow-x: auto; padding-bottom: 2px;
}
.dagbalk {
  display: flex; align-items: flex-end; flex: 1 0 6px; min-width: 6px; height: 100%;
}
.dagbalk > span {
  display: block; width: 100%; border-radius: 2px 2px 0 0;
  background: var(--a-accent); opacity: .75;
}
.dagbalk:hover > span { opacity: 1; }

@media (max-width: 860px) {
  .trechter__rij { grid-template-columns: minmax(0, 1fr) 3.5rem 3.5rem; }
  .trechter__balk { grid-column: 1 / -1; order: 2; }
  .trechter__naam { white-space: normal; }
}

/* --- Zoekbalk in de mediabibliotheek --------------------------------------- */

.mediazoek {
  margin-left: auto;
  display: flex; align-items: center; flex-wrap: wrap; gap: .5rem;
  min-width: 0;                 /* mag krimpen, anders duwt hij de kaart open */
}
.mediazoek input[type="search"],
.mediazoek select {
  padding: .45rem .7rem;
  border: 1px solid var(--a-rand);
  border-radius: 6px;
  font-size: .86rem;
  min-width: 0;
}
.mediazoek input[type="search"] { flex: 1 1 12rem; }

@media (max-width: 620px) {
  .mediazoek { margin-left: 0; flex: 1 1 100%; }
  .mediazoek input[type="search"] { flex: 1 1 100%; }
}

/* --- Zeer smalle telefoons (320 px en minder) ------------------------------ */

/*
 * Knoppen mogen normaal niet afbreken: een knoptekst over twee regels leest
 * rommelig. Op een scherm van 320 px is dat de verkeerde afweging — daar duwt
 * een lange knoptekst als "Teksten van een pagina aanpassen" de hele pagina
 * voorbij de rand, en dan is afbreken duidelijk het kleinere kwaad.
 */
@media (max-width: 440px) {
  .knop { white-space: normal; text-align: left; }
  .kopbalk__acties .knop { flex: 1 1 auto; justify-content: center; text-align: center; }
}

/* --- Mediadetail: losse blokken onder elkaar ------------------------------- */

.mediablok {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--a-rand);
}
.mediablok h3 { font-size: .88rem; margin-bottom: .5rem; }
.mediablok__uitleg { font-size: .85rem; color: var(--a-ink-3); margin: .6rem 0 0; }
.mediablok__lijst { font-size: .85rem; padding-left: 1.1rem; margin: 0; }
.mediablok__form { margin-top: 1rem; }
.tabel--dicht td, .tabel--dicht th { padding-top: .35rem; padding-bottom: .35rem; font-size: .84rem; }

/* ==========================================================================
   Hulpklassen — vervangen herhaalde inline style="" op de admin-schermen
   (fase 4, opkuis). Dit zijn geen algemene utility-klassen voor overal:
   alleen deze paar patronen kwamen tientallen keren identiek terug.
   Écht dynamische waarden (breedte/hoogte op basis van een cijfer) blijven
   terecht inline staan.
   ========================================================================== */
.a-dempen { color: var(--a-ink-3); }
.a-leeg { color: var(--a-ink-3); margin: 0; }
.a-hint { color: var(--a-ink-3); font-size: .85rem; }
.a-hint--82 { color: var(--a-ink-3); font-size: .82rem; }
.a-hint--78 { color: var(--a-ink-3); font-size: .78rem; }
.a-hint--mt { margin-top: 1rem; }
.a-intro { color: var(--a-ink-3); margin: -.4rem 0 1.2rem; max-width: 64ch; }
.a-intro--kort { color: var(--a-ink-3); margin: 0 0 1.2rem; max-width: 62ch; }
.a-verborgen { display: none; }
.a-mt-1 { margin-top: 1rem; }
.a-mt-2 { margin-top: 1.2rem; }
.a-mt-3 { margin-top: 1.5rem; }
.a-mb-2 { margin-bottom: 1.2rem; }
.a-mb-3 { margin-bottom: 1.5rem; }
.a-breed { max-width: 52ch; }
.a-hint--zonder-kleur { font-size: .85rem; }
.a-normaal { font-weight: 400; }
.a-intro--zonder-breedte { color: var(--a-ink-3); margin: -.4rem 0 1.2rem; }
.a-leeg--breed { color: var(--a-ink-3); margin: 0; max-width: 66ch; }
.a-hint--mt1 { color: var(--a-ink-3); font-size: .85rem; margin-top: 1rem; }

/* Fasebalk (fase 2, ux-ui-masterplan-ontwerp.md deel G): promoot de huidige
   ux_fase van een dossier zonder de bestaande tabbladen te verbergen. */
.fasebalk {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem;
  margin: 0 0 .8rem;
}
.fasebalk__stap {
  padding: .3rem .7rem;
  border-radius: 999px;
  font-size: .78rem;
  font-weight: 600;
  background: var(--a-paper);
  color: var(--a-ink-3);
  border: 1px solid var(--a-rand);
}
.fasebalk__stap.is-voorbij {
  background: var(--a-vlak);
  color: var(--a-ink-2);
}
.fasebalk__stap.is-huidig {
  background: var(--a-accent);
  color: var(--a-paper);
  border-color: var(--a-accent);
}

/* Fasestappen: de checkpoints binnen de huidige fase. De fasebalk zegt waar
   je staat, deze lijst zegt wat er nog moet gebeuren voor je verder mag.
   Bewust een lijst en geen balk: het aantal stappen verschilt per fase. */
.fasestappen {
  margin: 0 0 1rem;
}
.fasestappen__kop {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
}
.fasestappen__kop h2 {
  margin: 0;
  font-size: 1rem;
}
.fasestappen__telling {
  font-size: .78rem;
  color: var(--a-ink-3);
  font-variant-numeric: tabular-nums;
}
.fasestappen__volgende {
  margin: .6rem 0 0;
  padding: .55rem .8rem;
  border-radius: var(--a-radius);
  background: var(--a-accent-zacht, #eef2ff);
  border-left: 3px solid var(--a-accent);
  font-size: .88rem;
}
.fasestappen__volgende.is-klaar {
  background: var(--a-goed-licht);
  border-left-color: var(--a-goed);
}
.fasestappen__lijst {
  list-style: none;
  margin: .8rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}
.fasestappen__stap {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  padding: .45rem .6rem;
  border-radius: var(--a-radius);
  background: var(--a-vlak-zacht);
  border: 1px solid var(--a-rand-zacht);
}
.fasestappen__stap.is-afgevinkt {
  background: var(--a-goed-licht);
  border-color: var(--a-goed-licht);
}
.fasestappen__stap.is-nvt {
  opacity: .6;
}
.fasestappen__stap.is-blokkeert {
  border-color: var(--a-accent);
}
.fasestappen__vink {
  flex: 0 0 auto;
  width: 1.1rem;
  text-align: center;
  font-size: .95rem;
  line-height: 1.5;
  color: var(--a-ink-3);
}
.fasestappen__stap.is-afgevinkt .fasestappen__vink {
  color: var(--a-goed);
}
.fasestappen__tekst {
  flex: 1 1 auto;
  font-size: .88rem;
  min-width: 0;
}
.fasestappen__tekst small {
  display: block;
  color: var(--a-ink-3);
  font-size: .76rem;
}
.fasestappen__los {
  margin-left: .4rem;
  font-size: .72rem;
  font-style: normal;
  color: var(--a-ink-3);
}
/* De wegwijzer boven de instellingen. */
.instelzoek input[type="search"] {
  width: 100%;
  max-width: 34rem;
}
.instelzoek__leeg {
  margin: .6rem 0 0;
  font-size: .85rem;
  color: var(--a-ink-3);
}
.instelzoek__groepen {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem;
  margin-top: .9rem;
}
/*
 * De groepenlijst bovenaan admin/instellingen.php mat 29 px. Onder 900 px
 * stond er al 44 (zie de mediaregel eerder in dit bestand); daarboven
 * niet, en het is de enige manier om in een scherm van 18.957 px lang
 * ergens te komen zonder te scrollen.
 *
 * Echt groter: het zijn omkaderde knopjes met een eigen achtergrond, en
 * een onzichtbaar vlak eromheen zou groter zijn dan wat je ziet. Ze staan
 * in een flexrij met tussenruimte, dus twee buren raken elkaar niet.
 */
.instelzoek__groepen a {
  min-height: 44px; display: inline-flex; align-items: center;
  font-size: .78rem;
  padding: .22rem .6rem;
  border: 1px solid var(--a-rand);
  border-radius: 999px;
  color: var(--a-ink-2);
  text-decoration: none;
  white-space: nowrap;
}
.instelzoek__groepen a:hover,
.instelzoek__groepen a:focus-visible {
  border-color: var(--a-accent);
  color: var(--a-accent);
}
/* Het veld waar een link je naartoe stuurde. Zonder markering scrollt de
   browser wel naar de juiste plek, maar zie je niet welk veld bedoeld is. */
.instelling-anker.is-gezocht {
  outline: 2px solid var(--a-accent);
  outline-offset: 6px;
  border-radius: var(--a-radius);
}
/* De stappenlijst zelf, dicht op een werktab en open op Overzicht. De regel
   moet leesbaar zijn als knop, niet als kopje: hij is het enige wat er op tien
   tabbladen van de lijst overblijft. */
.fasestappen__vouw > summary {
  cursor: pointer;
  margin-top: .8rem;
  font-size: .8rem;
  color: var(--a-accent);
}
.fasestappen__vouw > summary:hover {
  text-decoration: underline;
}
.fasestappen__vouw[open] > summary {
  color: var(--a-ink-3);
}

.fasestappen__uitleg {
  margin: .8rem 0 0;
  font-size: .78rem;
  color: var(--a-ink-3);
  max-width: 70ch;
}
/* De stand van de stap, als eigen kolom. Zonder deze kolom staat er in de
   rechterhoek van een afgeleide stap alleen een randloze knop, en die leest
   dan als de status van de rij in plaats van als een handeling. */
.fasestappen__staat,
.controlelijst__staat {
  flex: 0 0 auto;
  align-self: flex-start;
  white-space: nowrap;
}
.fasestappen__knoppen {
  flex: 0 1 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .25rem;
  max-width: 24rem;
}
/* Het notitieveld bij een stap. Het krimpt mee en wipt onder de knoppen zodra
   de rij te smal wordt, in plaats van de knoppen weg te duwen. */
.fasestappen__notitie {
  flex: 1 1 9rem;
  min-width: 7rem;
  font-size: .8rem;
  padding: .22rem .45rem;
}
/* Het vak is met opzet smal: op een breed scherm staat het op één regel
   naast Afvinken en Overslaan. Op een telefoon staan die knoppen toch
   onder elkaar, dus mag het vak daar gewoon te raken zijn.

   Deze regel hoort ná de regel hierboven en niet bij de andere mobiele
   regels bovenaan: ze wegen allebei even zwaar, dus wint de laatste in
   het bestand. Boven gezet doet ze niets. */
@media (max-width: 700px) {
  .fasestappen__notitie { padding: .6rem .7rem; }
}
.fasestappen__notitie-tekst {
  color: var(--a-ink-2);
  font-style: italic;
}
/* Zoekveld boven een lange keuzelijst. Het wordt door assets/js/keuzefilter.js
   gemaakt en bestaat dus alleen waar dat bestand geladen is; zonder JavaScript
   staat er enkel de gewone keuzelijst. */
.keuzefilter {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-bottom: .4rem;
}
.keuzefilter__veld {
  flex: 1 1 auto;
  min-width: 0;
  font-size: .88rem;
  padding: .35rem .55rem;
}
.keuzefilter__telling {
  flex: 0 0 auto;
  white-space: nowrap;
  font-size: .78rem;
}
/* Een kale knop is elders bewust onopvallend, maar in deze twee lijsten
   staat ze naast een statuslabel. Zonder rand zijn het twee stukjes tekst
   naast elkaar en is niet te zien welk van de twee je kan aanklikken. */
.fasestappen__knoppen .knop--kaal,
.controlelijst__knoppen .knop--kaal {
  border-color: var(--a-rand);
}
@media (max-width: 640px) {
  .fasestappen__stap {
    flex-wrap: wrap;
  }
  .fasestappen__knoppen {
    flex-basis: 100%;
    padding-left: 1.7rem;
  }
}
/* Een instelling waar vanuit een melding rechtstreeks naar verwezen wordt.
   Zonder markering land je wel op de juiste plek maar zie je niet welk van
   de zestig velden bedoeld is. */
.instelling-anker:target {
  scroll-margin-top: 5rem;
  background: var(--a-accent-zacht, #eef2ff);
  box-shadow: 0 0 0 .35rem var(--a-accent-zacht, #eef2ff);
  border-radius: 6px;
}

/* Hetzelfde principe voor de kwalificatiegraad, die per ontbrekend gegeven
   naar het veld verwijst waar het ingevuld wordt. Dat veld kan een kaart
   zijn, een blok in een formulier of een enkele invoer, vandaar de drie
   vormen. Zonder markering sta je wel op de juiste hoogte, maar zie je in
   een formulier van veertig velden niet welk veld je zocht. */
.a-doelveld:target,
.kaart:target,
input:target, select:target, textarea:target {
  scroll-margin-top: 6rem;
  outline: .16rem solid var(--a-accent, #4f46e5);
  outline-offset: .3rem;
  border-radius: 6px;
}

/*
 * Een blok binnen een kaart, voor een reeks gelijkaardige eenheden die elk hun
 * eigen tabel en knoppen hebben — vandaag de offerte van één DMC naast die van
 * een andere. Zonder rand lopen die in elkaar over en is niet te zien waar de
 * ene ophoudt.
 */
.a-blok { border: 1px solid var(--a-rand); border-radius: 8px; padding: .9rem 1rem; }
.a-blok + .a-blok { margin-top: 1rem; }
/* Interne controle op een voorstelversie. Zelfde vorm als .fasestappen, want
   het is dezelfde soort lijst: punten die af moeten voor er iets naar buiten
   mag. Eigen naam omdat ze per voorstelversie staat en niet per fase, en
   omdat de twee naast elkaar op één scherm kunnen staan. */
.controlelijst {
  margin: 1rem 0 0;
  padding: .9rem 1rem;
  border: 1px solid var(--a-rand);
  border-radius: var(--a-radius);
  background: var(--a-vlak-zacht);
}
.controlelijst__kop {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
  margin: 0;
  font-size: .95rem;
}
.controlelijst__teller {
  font-size: .78rem;
  font-weight: 400;
  color: var(--a-ink-3);
  font-variant-numeric: tabular-nums;
}
.controlelijst__lijst {
  list-style: none;
  margin: .7rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}
.controlelijst__punt {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  padding: .45rem .6rem;
  border-radius: var(--a-radius);
  background: var(--a-vlak);
  border: 1px solid var(--a-rand-zacht);
}
.controlelijst__punt.is-akkoord {
  background: var(--a-goed-licht);
  border-color: var(--a-goed-licht);
}
.controlelijst__punt.is-nvt {
  opacity: .6;
}
.controlelijst__punt.is-blokkeert {
  border-color: var(--a-accent);
}
.controlelijst__vink {
  flex: 0 0 auto;
  width: 1.1rem;
  text-align: center;
  font-size: .95rem;
  line-height: 1.5;
  color: var(--a-ink-3);
}
.controlelijst__punt.is-akkoord .controlelijst__vink {
  color: var(--a-goed);
}
.controlelijst__tekst {
  flex: 1 1 auto;
  font-size: .88rem;
  min-width: 0;
}
.controlelijst__uitleg {
  display: block;
  color: var(--a-ink-3);
  font-size: .76rem;
}
.controlelijst__knoppen {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: .25rem;
}
@media (max-width: 640px) {
  .controlelijst__punt {
    flex-wrap: wrap;
  }
  .controlelijst__knoppen {
    flex-basis: 100%;
    padding-left: 1.7rem;
  }
}
/* De offertebouwer: twee kolommen naast elkaar, links wat de lokale agent
   aanleverde en rechts wat de klant leest. Onder de 1000 pixels vallen ze
   onder elkaar — naast elkaar zetten op een smal scherm levert twee kolommen
   op die geen van beide leesbaar zijn. */
.bouwer {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.2rem;
  align-items: start;
}
.bouwer__kop {
  margin: 0 0 .6rem;
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--a-ink-3);
}
/* De voorwaarden van de agent staan onder zijn regels, in dezelfde kaart.
   Kleiner gezet dan de tabellen aan de klantzijde: het is meelezen, niet
   invullen. */
.bouwer__subkop {
  margin: .9rem 0 .3rem;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--a-ink-3);
}
.tabel--klein th,
.tabel--klein td { padding: .3rem .45rem; font-size: .84rem; }

.bouwer__regels {
  list-style: none;
  margin: .6rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .4rem;
}
.bouwer__regel {
  display: flex;
  align-items: flex-start;
  gap: .7rem;
  padding: .55rem .7rem;
  border: 1px solid var(--a-rand-zacht);
  border-radius: var(--a-radius);
  background: var(--a-vlak);
}
.bouwer__regel.is-overgenomen {
  background: var(--a-goed-licht);
  border-color: var(--a-goed-licht);
}
.bouwer__regeltekst {
  flex: 1 1 auto;
  min-width: 0;
  font-size: .88rem;
}
.bouwer__regeltekst small {
  display: block;
  color: var(--a-ink-3);
  font-size: .76rem;
}
.bouwer__optie {
  margin-left: .35rem;
  font-size: .72rem;
  font-style: normal;
  color: var(--a-ink-3);
}
.bouwer__regelknoppen,
.bouwer__blokknoppen {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
  flex: 0 0 auto;
}
.bouwer__blokknoppen {
  margin-top: .6rem;
}
/* Een intern onderdeel staat niet op het blad van de klant. Dat moet je zien
   zonder het etiket te lezen, want het is precies het soort verschil dat
   iemand over het hoofd ziet op het moment dat het ertoe doet. */
.bouwer__blok.is-intern {
  border-left: 3px solid var(--a-accent);
}
.bouwer__leestekst {
  margin: .4rem 0 0;
  font-size: .9rem;
  white-space: normal;
}
.bouwer__feedback {
  list-style: none;
  margin: .8rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .4rem;
}
.bouwer__opmerking {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: .7rem;
  padding: .6rem .7rem;
  border: 1px solid var(--a-rand-zacht);
  border-radius: var(--a-radius);
  background: var(--a-vlak);
  font-size: .88rem;
}
.bouwer__opmerking.is-verwerkt {
  opacity: .6;
}
.bouwer__opmerking p {
  margin: .3rem 0 0;
}
.bouwer__opmerking small {
  display: block;
  color: var(--a-ink-3);
  font-size: .76rem;
}
@media (max-width: 1000px) {
  .bouwer {
    grid-template-columns: minmax(0, 1fr);
  }
}
@media (max-width: 640px) {
  .bouwer__regel,
  .bouwer__opmerking {
    flex-wrap: wrap;
  }
}

/* --- De taalkiezer van de portalen ---------------------------------------
   Twee of drie letters naast elkaar, met de huidige taal als vaste tekst en
   de andere als link. Bewust geen uitklapmenu: bij drie talen kost een menu
   een klik meer en verbergt het precies wat iemand zoekt.

   De kleuren hier gelden op een lichte achtergrond, dus op de aanmeldschermen.
   In de donkere portaalbalk worden ze overschreven in portaal.css. */

/* De taalkiezer op de kale beheerschermen (inloggen, wachtwoord kiezen,
   wachtwoord vergeten). Hij staat binnen de kaart en niet erboven: het vlak
   van body.admin-kaal is --a-diep, en de kleuren van .portaal-taal hieronder
   gelden op een licht vlak. Binnen de kaart klopt dat, erboven niet.

   Rechts uitgelijnd en met een negatieve bovenmarge, zodat hij op de hoogte
   van het logo komt te staan in plaats van er een regel onder. */
.kaal-taal {
  display: flex;
  justify-content: flex-end;
  margin: -3.4rem 0 2rem;
}

.portaal-taalbalk {
  display: flex;
  justify-content: flex-end;
  max-width: 26rem;
  margin: 1.4rem auto -2.6rem;
  padding: 0 1rem;
}

.portaal-taal {
  display: inline-flex;
  align-items: center;
  gap: .1rem;
  font-size: .74rem;
  letter-spacing: .06em;
}

/*
 * Het aanraakvlak van de taalkiezer, en de ruimte die het nodig heeft.
 *
 * De knop meet 28 bij 19 pixels. Groter máken mag niet — twee letters naast
 * twee letters horen klein — dus krijgt hij een onzichtbaar vlak van 44 pixels
 * hoog dat .6rem buiten de letters uitsteekt. De tussenruimte moet dan mee van
 * .1rem naar 1.2rem: zonder dat raken de twee vlakken elkaar en tik je de
 * verkeerde taal aan.
 *
 * Alleen de knop, niet .portaal-taal__nu: dat is de taal waar je al staat, een
 * <span> zonder handeling erachter, en die hoort dus geen doel te zijn.
 *
 * 900 en niet 700, net als het aanraakblok van portaal.css. Boven de 700 viel
 * dit weg en bleef er een doel van 19 bij 30 px met 1,6 px ertussen over.
 * Gemeten bij 768 px, in alle drie de portalen. Een tablet in staande stand is
 * 768 of 810 breed en er wordt op getikt.
 *
 * Deze twee regels staan hier en niet in de mediaregel hierboven, en dat is de
 * hele reden dat de tussenruimte werkt: ze weegt even zwaar als de basisregel
 * van .portaal-taal, dus ze moet er ná staan. Verplaats ze niet naar boven.
 */
@media (max-width: 900px) {
  .portaal-taal { gap: 1.2rem; }
  .portaal-taal__knop { position: relative; }
  .portaal-taal__knop::after {
    content: "";
    position: absolute;
    top: 50%;
    left: -.6rem;
    right: -.6rem;
    height: 44px;
    transform: translateY(-50%);
  }
}

.portaal-taal__nu,
.portaal-taal__knop {
  padding: .22rem .42rem;
  border-radius: var(--a-radius, 6px);
  line-height: 1;
}

.portaal-taal__nu {
  font-weight: 600;
  color: var(--a-ink-1, #152231);
  background: rgba(21, 34, 49, .08);
}

.portaal-taal__knop {
  color: var(--a-ink-3, #5a6b7d);
  text-decoration: none;
  transition: background .2s ease, color .2s ease;
}

.portaal-taal__knop:hover,
.portaal-taal__knop:focus-visible {
  color: var(--a-ink-1, #152231);
  background: rgba(21, 34, 49, .08);
}

/*
 * De inhoudsopgave boven een reisprogramma van meer dan drie dagen.
 *
 * Ze plakt aan de bovenkant zodra je scrolt, want anders is ze precies dan weg
 * wanneer je ze nodig hebt: bij dag twaalf. Kleine vierkantjes met enkel het
 * dagnummer erin — de titel hangt in het title-attribuut, want vijftien titels
 * naast elkaar leest als een tweede programma en niet als een balk.
 */
.dagsprong {
  position: sticky;
  top: var(--a-kopbalk-hoogte, 5.5rem);
  z-index: 3;
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
  align-items: center;
  margin-bottom: 1rem;
  padding: .5rem .7rem;
  background: var(--a-paper);
  border: 1px solid var(--a-rand);
  border-radius: 8px;
}

.dagsprong > span {
  margin-right: .3rem;
}

.dagsprong a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.7rem;
  padding: .15rem .35rem;
  font-size: .8rem;
  font-variant-numeric: tabular-nums;
  color: var(--a-ink-2);
  text-decoration: none;
  background: var(--a-vlak);
  border: 1px solid var(--a-rand-zacht);
  border-radius: 5px;
}

.dagsprong a:hover,
.dagsprong a:focus-visible {
  color: var(--a-paper);
  background: var(--a-accent);
  border-color: var(--a-accent);
}

/* De kaart mag niet half onder de plakbalk beginnen wanneer je erheen springt.
   Twee balken staan boven de kaart: de kopbalk van het beheer en de sprongbalk
   zelf. Beide meten zichzelf op, want beide mogen afbreken op een smal scherm;
   de terugvalwaarden gelden alleen zolang die meting nog niet gebeurd is. */
.kaart[id^="dag-"],
.kaart[id^="dnacat-"] {
  scroll-margin-top: calc(var(--a-kopbalk-hoogte, 5.5rem) + var(--a-sprongbalk-hoogte, 3rem) + .8rem);
}

/* --- De sprongbalk op een telefoon ---------------------------------------- *
 *
 * Twee regels die al in dit bestand stonden en geen van beide aankwamen. Ze
 * stonden vóór de opmaak van .dagsprong hierboven, en bij gelijk gewicht wint
 * de laatste regel in het bestand — precies de val die bij de taalkiezer al
 * eens toesloeg. Een mediaregel weegt niets extra mee; alleen de plek telt.
 * Ze staan hier dus opnieuw, ná .dagsprong, met dezelfde bedoeling als op hun
 * oude plek (zie de mediaregels op 900 en 700 px eerder in dit bestand).
 *
 * Eén: de breedte van een dagnummer. `.dagsprong a { min-width: 44px }` stond
 * op 900 px, maar `.dagsprong a { min-width: 1.7rem }` hieronder won. Gemeten
 * op admin/dossier.php?id=269&tab=reisprogramma bij 375 px breed: zestien
 * vierkantjes van 27 bij 44, met 4,8 px ertussen. Hart tot hart is dat 32
 * pixels, en een vingertop is er ruim dertig breed: je tikt dag 5 aan terwijl
 * je dag 4 bedoelde. Met 44 wordt de balk drie regels in plaats van twee
 * (110 px werd 159), en dat is de goede ruil — zie punt twee.
 *
 * Twee: de balk plakte. `.dagsprong { position: static }` stond op 700 px en
 * verloor van `position: sticky` hierboven, dus bleef ze op een telefoon
 * hangen ónder de kopbalk. Samen 114 + 110 = 224 van de 812 px, permanent, op
 * het scherm waar je een reisprogramma van zestien dagen zit te schrijven.
 * Nu schuift ze gewoon mee: de drie regels kosten je één veeg, niet een kwart
 * van je scherm.
 *
 * De sprongbalkhoogte gaat mee op nul zolang ze niet plakt. voet.php meet
 * offsetHeight en weet niet of het ding vastzit; zonder deze regel houdt de
 * kaart onder een anker 159 px lucht vrij voor een balk die er niet meer staat.
 */
@media (max-width: 900px) {
  .dagsprong a { min-width: 44px; }
}
@media (max-width: 700px) {
  .dagsprong { position: static; }
  .kaart[id^="dag-"],
  .kaart[id^="dnacat-"] { --a-sprongbalk-hoogte: 0px; }
}


/* --- Hoog contrast (forced-colors) --------------------------------------- *
 * Windows-hoogcontrast en de leesstand van sommige browsers gooien elke kleur
 * weg en zetten er hun eigen paar voor terug. Alles wat wij met kleur alleen
 * zeggen, verdwijnt dan: de actieve tab (een gekleurde onderrand), het actieve
 * menu-item (een vlak van 12% wit), de rand van een kaart, de omtrek van een
 * knop en de vulling van een label. Wat overblijft is een pagina waarop niets
 * meer opvalt.
 *
 * Deze regels zeggen niets nieuws; ze vertalen wat de kleuren al zeiden naar
 * de twee dingen die in hoogcontrast wél overleven: een rand en het
 * systeemkleurenpaar. prefers-reduced-motion staat al in tokens.css en hoort
 * hier dus niet nog eens.
 */
@media (forced-colors: active) {
  /* Een knop moet als knop te zien blijven, ook als hij "kaal" is. */
  .knop,
  .knop--kaal { border: 1px solid ButtonBorder; }
  .knop[disabled] { opacity: 1; color: GrayText; border-color: GrayText; }

  /* De actieve tab hangt aan border-bottom-color, en kleur is precies wat hier
     wegvalt. Een dikkere rand overleeft wel. */
  .tabbalk a.is-actief { border-bottom-width: 3px; border-bottom-color: Highlight; }
  .tabbalk--tweede a.is-actief { outline: 2px solid Highlight; outline-offset: -2px; }

  /* Het actieve menu-item is enkel een lichter vlak; dat vlak bestaat niet
     meer. De schuine streep ervoor is geen sier maar de enige aanwijzing die
     overblijft. */
  .zijbalk a.is-actief { outline: 2px solid Highlight; outline-offset: -2px; }

  /* Kaarten, tabellen en meldingen leunen op een zachte rand die in
     hoogcontrast tot niets vervaagt. */
  .kaart,
  .melding,
  .lege-staat,
  .notificaties__paneel { border: 1px solid CanvasText; }
  .tabel th,
  .tabel td { border-bottom-color: CanvasText; }

  /* Een label is een gekleurd vlakje met tekst erin; zonder vlak is het los
     woord in de zin ernaast niet meer te onderscheiden. */
  .label { border: 1px solid CanvasText; }

  /* De telling op een menu-item en op een tab is wit op accent: twee kleuren
     die allebei verdwijnen. */
  .zijbalk a .telling,
  .tabbalk a .telling,
  .notificaties__knop .telling,
  .portaal-nav__badge { border: 1px solid CanvasText; }

  /* De schuifaanwijzing op de tabbalk is een verloop, en verlopen tekent
     hoogcontrast niet. Zonder deze regel blijft er een grijze veeg staan die
     niets meer betekent. */
  .tabbalk { background-image: none; }

  /* Het skeleton is puur beweging in grijstinten: in hoogcontrast een blok
     dat als inhoud leest terwijl er niets staat. */
  .skeleton { border: 1px dashed GrayText; background: Canvas; }
}
