/* De opmaak van ScreenWatch.
 *
 * Het merk is paars. Het logo in statisch/ is daarvoor omgekleurd vanuit het
 * blauw-groene origineel in merk/, zodat logo en paneel bij elkaar horen.
 *
 * Indeling zoals de grote pakketten in dit vak: een donkere zijbalk met de
 * klantkiezer bovenin, een lichte werkvloer, een balk met zoekveld en één
 * duidelijke knop rechtsboven. De maatvoering komt van shadcn/ui: hsl-waarden
 * als losse getallen, radius van 0.5rem, randen in plaats van schaduwen.
 * Met de hand geschreven, zodat er geen npm en geen bouwstap in de uitrol komt.
 *
 * Eén kleur bepaalt het merk: --accent hieronder. Verander die regel en het
 * hele paneel gaat mee.
 */

:root {
  /* 65 procent en niet 66. Audit 5 oktober 2026, F10: witte tekst op het oude
     paars haalde 4,30 : 1 en normale tekst vraagt 4,5. Eén procentpunt donkerder
     brengt het op precies 4,50 -- met het oog niet te zien, en de hele knop,
     het merk en de iconen blijven dezelfde kleur. Gemeten met de som uit
     WCAG 2.1 op #895bf5 tegen wit (4,30) en #8656f5 tegen wit (4,50). */
  --accent: 258 89% 65%;
  --accent-tekst: 0 0% 100%;

  --achtergrond: 240 20% 98%;
  --voorgrond: 240 10% 3.9%;
  --kaart: 0 0% 100%;
  --gedempt: 240 5% 96%;
  --gedempte-tekst: 240 4% 46%;
  --rand: 240 6% 90%;
  --ring: var(--accent);
  --gevaar: 0 72% 51%;
  /* Donkerder dan het groen van een stip: dit is TEKST op een lichte
     achtergrond, en op 45 procent haalde dat maar 2,30 : 1 (F10). Op 30 procent
     is het 4,83. De vlakken eronder gebruiken dezelfde kleur met .1 doorzicht,
     dus die blijven licht; alleen de letters worden leesbaar. In de donkere
     stand blijft het lichter -- zie de regel verderop. */
  --goed: 142 71% 30%;
  /* Tussen goed en gevaar in: "dit klopt, maar kijk er even naar" -- een box
     die achterloopt, een versie die vastgezet is. Stond drie keer los in een
     sjabloon als hsl(32 90% 38%) en was in de donkere stand niet te lezen. */
  --let-op: 32 90% 38%;
  --radius: 0.5rem;
  /* Hoogte van alles wat je aanraakt. John, 26 september 2026: "allemaal even
     hoog maken en dat overal doen. Maar hoe komt de interface zo inconsistent?"
     In één rij op Media stonden drie hoogtes: een keuzelijst van 2,6 rem, een
     knop van 2,1 en twee weergaveknopjes van 2,4 -- elk op een andere plek in
     dit bestand gezet, en nooit met elkaar vergeleken. Precies de ziekte van de
     23 tekstmaten uit ONTWERP.md, nu in hoogtes. Drie maten, verder geen. */
  --hoog: 2.6rem;
  --hoog-klein: 2.1rem;
  --hoog-groot: 3rem;

  /* De zijbalk is altijd donker, ook in de lichte stand: dat geeft het paneel
     zijn vorm en houdt de aandacht op de werkvloer. */
  --zij: 258 30% 11%;
  --zij-tekst: 260 20% 96%;
  --zij-gedempt: 258 12% 65%;
  --zij-rand: 258 20% 20%;
}

@media (prefers-color-scheme: dark) {
  :root {
    --achtergrond: 258 18% 7%;
    --voorgrond: 0 0% 98%;
    --kaart: 258 18% 10%;
    --gedempt: 258 14% 16%;
    --gedempte-tekst: 258 10% 65%;
    --rand: 258 14% 18%;
    --zij: 258 22% 8%;
    --zij-rand: 258 16% 16%;
    --goed: 142 60% 45%;
    --let-op: 38 92% 60%;
  }
}

* { box-sizing: border-box; }
/* Wat verborgen is, blijft verborgen: anders wint .knop of .melding met hun
   eigen display, en staat er "Verwijderen" bij een blok dat nog niet bestaat. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: hsl(var(--achtergrond));
  color: hsl(var(--voorgrond));
  /* Een paneel dat op een groot beeldscherm wordt gebruikt mag ruimer staan
     dan een webpagina. Vandaar 16 in plaats van de gebruikelijke 14, en overal
     wat meer lucht. */
  font: 16px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; }
svg { flex: none; }

/* ------------------------------------------------------------------ opbouw */

.schil { display: flex; min-height: 100vh; }

.zijkant {
  width: 16.5rem; flex: none; position: sticky; top: 0; height: 100vh;
  background: hsl(var(--zij)); color: hsl(var(--zij-tekst));
  padding: .875rem .75rem; display: flex; flex-direction: column; gap: .125rem;
}

.merk {
  display: flex; align-items: center; gap: .625rem;
  font-weight: 600; font-size: 17px; padding: .5rem 0 1.25rem;
  letter-spacing: -.015em; text-decoration: none;
}
/* Het vak voor het logo is precies 240 x 60 (John, 22 september 2026). De
   zijbalk is 16,5rem met .75rem padding, dus 240 px is exact de volle breedte.
   object-fit: contain -- een logo dat niet precies past wordt passend
   geschaald en nooit bijgesneden; links uitgelijnd, want daar begint alles in
   deze balk. Die maat staat ook op Instellingen -> Logo, zodat je weet waar je
   je beeld op moet maken. */
.merk .woordmerk {
  width: 240px; height: 60px; max-width: 100%;
  object-fit: contain; object-position: left center;
}
.poortlogo { display: block; width: 20rem; max-width: 80vw; margin: 0 auto 2rem; }
/* Hetzelfde vak, op ware grootte, op Instellingen -> Logo. Het moet er precies
   zo uitzien als in de zijbalk, dus dezelfde 240 x 60 op dezelfde donkere
   ondergrond -- en niet meebewegen met de breedte van de kaart. */
.logovoorbeeld { width: max-content; padding: .75rem; border-radius: var(--radius);
  background: hsl(var(--zij)); }
.logovoorbeeld img { display: block; width: 240px; height: 60px;
  object-fit: contain; object-position: left center; }

/* De klantkiezer: bovenin, als vak, zodat altijd zichtbaar is bij wie je werkt. */
.kiezer {
  background: hsl(0 0% 100% / .06); border: 1px solid hsl(var(--zij-rand));
  border-radius: calc(var(--radius) - 2px); padding: .4rem .55rem;
  margin-bottom: .875rem;
}
.kiezer span { display: block; font-size: 12px; color: hsl(var(--zij-gedempt)); }
.kiezer select {
  width: 100%; height: auto; padding: 0; margin: 0; border: 0; background: transparent;
  color: hsl(var(--zij-tekst)); font: inherit; font-weight: 500; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, hsl(var(--zij-gedempt)) 50%),
                    linear-gradient(135deg, hsl(var(--zij-gedempt)) 50%, transparent 50%);
  background-position: right .3rem center, right 0 center;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
  padding-right: 1rem;
}
.kiezer select option { color: #111; }
.kiezer .vast { font-weight: 500; }

.zijkant a.punt {
  display: flex; align-items: center; gap: .7rem;
  padding: .6rem .7rem; border-radius: calc(var(--radius) - 2px);
  color: hsl(var(--zij-gedempt)); text-decoration: none; font-weight: 500;
  font-size: 15px;
}
.zijkant a.punt:hover { background: hsl(0 0% 100% / .07); color: hsl(var(--zij-tekst)); }
.zijkant a.punt.hier {
  background: hsl(var(--accent)); color: hsl(var(--accent-tekst));
}
.zijkant .duw { margin-top: auto; }

.wie {
  display: flex; align-items: center; gap: .625rem; padding: .5rem;
  border-top: 1px solid hsl(var(--zij-rand)); margin-top: .5rem;
  color: hsl(var(--zij-tekst)); text-decoration: none;
}
.wie .bol {
  width: 2rem; height: 2rem; border-radius: 999px; flex: none; display: grid;
  place-items: center; background: hsl(var(--accent)); color: hsl(var(--accent-tekst));
  font-weight: 600; text-transform: uppercase;
}
.wie div { min-width: 0; }
.wie b { display: block; font-weight: 500; }
.wie small { color: hsl(var(--zij-gedempt)); font-size: 12px;
             display: block; overflow: hidden; text-overflow: ellipsis; }

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

.kop {
  display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap;
  padding: 1.05rem 2rem; border-bottom: 1px solid hsl(var(--rand));
  background: hsl(var(--kaart)); position: sticky; top: 0; z-index: 5;
}
.kop h1 { margin: 0; font-size: 24px; font-weight: 600; letter-spacing: -.02em;
          white-space: nowrap; }
/* De kop is op elke pagina hetzelfde opgebouwd: links terug-link, titel en
   onderkop onder elkaar; rechts de knoppen, altijd tegen de rechterrand. */
/* flex-basis 22rem met groei: past de knoppenrij er niet meer naast, dan gaat
   zij naar de tweede regel in plaats van de titel tot een sliver te persen. */
.koptekst { flex: 1 1 22rem; min-width: 0; display: flex; flex-direction: column; gap: .15rem; }
.titelrij { display: flex; align-items: center; gap: 1.25rem; min-width: 0; }
.titelrij h1 { overflow: hidden; text-overflow: ellipsis; }
.terug a { display: inline-flex; align-items: center; gap: .3rem; font-size: 13px;
           color: hsl(var(--gedempte-tekst)); text-decoration: none; }
.terug a:hover { color: hsl(var(--voorgrond)); }
.onderkop { margin: 0; font-size: 13px; color: hsl(var(--gedempte-tekst)); line-height: 1.4; }
.onderkop a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.onderkop b { color: hsl(var(--voorgrond)); font-weight: 600; }
/* flex: none stond hier tot 1.90.2, en dat kon de knoppenrij niet laten
   krimpen: tussen 768 en ~1100 px staat de menubalk nog op 264 px, en dan paste
   "Verzend naar schermen" er met de twee knoppen ernaast niet meer naast de
   titel. De hele PAGINA schoof dan 61 px zijwaarts (gemeten op /afspeellijsten
   bij 900 px). Met 0 1 auto en min-width: 0 wikkelt hij naar een tweede regel
   in plaats van uit te steken; de knoppen zelf worden niet smaller, want de
   min-content van een wikkelende flexrij is zijn breedste kind. */
.kopknoppen { margin-left: auto; flex: 0 1 auto; min-width: 0;
              display: flex; align-items: center; gap: .5rem;
              flex-wrap: wrap; justify-content: flex-end; }
.kopknoppen form { margin: 0; }

/* Bij welke klant je kijkt, naast de titel. Zonder dat staat er een lijst op
   je scherm waarvan je niet ziet van wie hij is, en dat is precies het soort
   twijfel dat je bij klantgegevens niet wilt. */
.bijklant {
  flex: none; padding: .2rem .7rem; border-radius: 999px; font-size: 13px;
  font-weight: 500; color: hsl(var(--gedempte-tekst));
  border: 1px solid hsl(var(--rand)); background: hsl(var(--gedempt) / .6);
  white-space: nowrap; margin-left: -.5rem;
}

.zoek { flex: 1; position: relative; max-width: 52rem; }
.zoek svg { position: absolute; left: .7rem; top: 50%; transform: translateY(-50%);
            color: hsl(var(--gedempte-tekst)); }
/* staat verderop nog eens, want de algemene invoerregel komt later */

.inhoud { padding: 1.75rem 2rem; display: flex; flex-direction: column; gap: 1.5rem; }
.inhoud > p.duiding { margin: -.5rem 0 0; color: hsl(var(--gedempte-tekst)); }

.rooster { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); }

/* --------------------------------------------------------------- onderdelen */

.kaart {
  background: hsl(var(--kaart)); border: 1px solid hsl(var(--rand));
  border-radius: var(--radius); overflow: hidden;
}
/* Kop, romp en voet mogen ook in een formulier in de kaart zitten. Dat is
   bijna altijd zo, en zonder die tweede regel plakken de velden tegen de rand. */
.kaart > header, .kaart > form > header { padding: 1.25rem 1.5rem .875rem; }
.kaart > header h2, .kaart > form > header h2 { margin: 0; font-size: 17px; font-weight: 600; }
.kaart > header p, .kaart > form > header p { margin: .3rem 0 0; font-size: 15px; color: hsl(var(--gedempte-tekst)); }
.kaart > .romp, .kaart > form > .romp { padding: 0 1.5rem 1.5rem; display: flex; flex-direction: column; gap: .875rem; }
/* Een romp zonder kopje erboven: dan mist de ruimte die die kop normaal geeft
   en plakt het eerste label tegen de bovenrand. Dat gebeurde overal waar een
   kaart meteen met velden begint. */
.kaart > .romp:first-child, .kaart > form > .romp:first-child,
.kaart > form > input[type="hidden"] + .romp { padding-top: 1.25rem; }
/* Zo'n zelfde gat onderaan: een uitleg onder een veld hoort niet tegen de
   scheidingslijn of de voet aan te lopen. */
.kaart > .romp:last-child, .kaart > form > .romp:last-child { padding-bottom: 1.5rem; }
/* De opslaanvoet staat VRIJ in de kaart: een grijs vak met een eigen rand en
   ronde hoeken, met wit eromheen. Niet tegen de onderrand aan.
   John, 27 september 2026: "zie de grijze balk met paarse button bij
   afspeellijsten, deze staat vrij in het witte kader, dit vind ik mooi -- maar
   dit is de enige plek." Dat klopte: een kaart met .invakken zette zijn voet zo
   neer, elke andere kaart plakte hem tegen de rand. Hij heeft het meerdere
   keren gezegd; het stond in twee losse regels en ik heb er telkens één
   aangepast. Nu geldt de vorm voor ELKE voet, ook eentje die er later bij
   komt. */
.kaart > footer, .kaart > form > footer {
  padding: .875rem 1.25rem; margin: 1rem 1.25rem 1.25rem;
  border: 1px solid hsl(var(--rand)); border-radius: var(--radius);
  background: hsl(var(--gedempt) / .5);
  display: flex; gap: .5rem; align-items: center; justify-content: flex-end;
}

.knop {
  display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  height: var(--hoog); padding: 0 1.1rem; border-radius: calc(var(--radius) - 2px);
  border: 1px solid transparent; background: hsl(var(--accent));
  color: hsl(var(--accent-tekst)); font: inherit; font-weight: 500;
  cursor: pointer; text-decoration: none; white-space: nowrap;
}
.knop:hover { filter: brightness(1.08); }
.knop.stil { background: hsl(var(--kaart)); border-color: hsl(var(--rand)); color: hsl(var(--voorgrond)); }
/* Het icoon op een stille knop is PAARS, de tekst blijft zwart. John, 4 oktober
   2026, voor de derde keer: "een mooi vlak met paars icoon net zoals overal."
   Gemeten voor ik het schreef: er was nergens in het paneel een paars icoon --
   op een stille knop was hij zwart, en de enige paarse stonden in de ontwerper
   omdat ik ze daar zelf had bedacht. "Zoals overal" was dus nergens waar.
   Deze ene regel maakt het overal waar, in plaats van op één pagina. */
.knop.stil svg { color: hsl(var(--accent)); }
/* Behalve als de knop zelf al een kleur draagt: een knop die iets ingrijpends
   doet is rood, en een rood vlak met een paars icoon erin is geen stijl. */
.knop.stil.ingrijpend svg, .knop.weg svg { color: inherit; }
.knop.stil:hover { background: hsl(var(--gedempt)); filter: none; }
/* Een stille knop die AAN staat: het soortfilter bij Media. Precies wat
   .standen a.hier al doet -- .knop.stil draagt de rand en de tekstkleur al,
   dus alleen de achtergrond verschilt. Geen nieuwe knopsoort, alleen de
   bestaande .hier-afspraak op een knop (ONTWERP.md punt 26). */
.knop.stil.hier { background: hsl(var(--gedempt)); }
/* Weghalen ziet eruit als een knop: een kader met een zacht rood vlak erin
   (John, 25 september 2026: "de prullebak ook in een kader zetten met een
   pastel background" -- en daarna: "overal"). Dus niet alleen de prullenbak in
   een rij, maar elke weg-knop, op de telefoon en op het bureaublad. Zacht
   genoeg om niet te schreeuwen, duidelijk genoeg om een knop te zijn; de
   betekenis van --gevaar blijft "dit draai je niet terug". */
.knop.weg {
  background: hsl(var(--gevaar) / .08); border-color: hsl(var(--gevaar) / .3);
  color: hsl(var(--gevaar));
}
.knop.weg:hover { background: hsl(var(--gevaar) / .16); border-color: hsl(var(--gevaar) / .5); filter: none; }
.knop.klein { height: var(--hoog-klein); padding: 0 .75rem; font-size: 14px; }
.knop.groot { height: var(--hoog-groot); padding: 0 1.5rem; font-size: 17px; }

/* Niet alleen op een <label>: een veld waarin een rij knoppen staat (de dagen,
   de draaiing) kan geen label zijn -- dan klikt het label de eerste knop aan. */
.veld { display: flex; flex-direction: column; gap: .375rem; font-weight: 500; }
.veld > span { font-size: 14px; }
.veld em { font-style: normal; font-weight: 400; color: hsl(var(--gedempte-tekst));
           font-size: 12px; line-height: 1.45; margin-top: .1rem; }

/* Alles behalve de vinkjes en de bestandskiezer. Bewust niet opsommen welke
   soorten wel: een veld zonder type-attribuut is gewoon een tekstveld, maar
   valt buiten input[type=text] en houdt dan de maat van de browser. */
input:where(:not([type=checkbox], [type=radio], [type=file], [type=submit])),
select, textarea {
  height: var(--hoog); padding: 0 .75rem; font: inherit;
  background: hsl(var(--kaart)); color: hsl(var(--voorgrond));
  border: 1px solid hsl(var(--rand)); border-radius: calc(var(--radius) - 2px);
  width: 100%;
}
input:where(:not([type=checkbox], [type=radio])):focus-visible,
select:focus-visible, textarea:focus-visible {
  outline: 2px solid hsl(var(--ring) / .5); outline-offset: 1px;
  border-color: hsl(var(--accent));
}
input[type=file] { font: inherit; }
/* Na de algemene invoerregel, anders wint die en loopt het vergrootglas
   dwars door de tekst. */
.zoek input[type=search] { padding-left: 2.2rem; }
select {
  appearance: none; padding-right: 1.75rem;
  background-image: linear-gradient(45deg, transparent 50%, hsl(var(--gedempte-tekst)) 50%),
                    linear-gradient(135deg, hsl(var(--gedempte-tekst)) 50%, transparent 50%);
  background-position: right 1rem center, right .7rem center;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}

/* Onderlangs uitgelijnd, zodat een knop naast een invulveld op dezelfde lijn
   staat. Hebben de velden een uitleg eronder van verschillende lengte, dan
   springt daardoor het bovenste label omhoog: zet er dan .boven bij. */
.rij { display: flex; gap: .625rem; align-items: flex-end; flex-wrap: wrap; }
.rij.boven { align-items: flex-start; }
.rij > * { flex: 1; min-width: 8rem; }
.rij > .vast { flex: none; min-width: 0; }

table { width: 100%; border-collapse: collapse; font-size: 15px; }
th {
  text-align: left; font-weight: 500; font-size: 12px; text-transform: uppercase;
  letter-spacing: .04em; color: hsl(var(--gedempte-tekst));
  padding: .8rem 1.5rem; border-bottom: 1px solid hsl(var(--rand));
}
td { padding: .95rem 1.5rem; border-bottom: 1px solid hsl(var(--rand)); vertical-align: middle; }
tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: hsl(var(--gedempt) / .6); }

.merkje {
  display: inline-flex; align-items: center; gap: .375rem;
  padding: .125rem .5rem; border-radius: 999px; font-size: 12px; font-weight: 500;
  border: 1px solid hsl(var(--rand)); color: hsl(var(--gedempte-tekst));
  white-space: nowrap;
}
.merkje.leeft { color: hsl(var(--goed)); border-color: hsl(var(--goed) / .35); background: hsl(var(--goed) / .1); }
.merkje.stil { color: hsl(var(--gevaar)); border-color: hsl(var(--gevaar) / .35); background: hsl(var(--gevaar) / .08); }
/* Tijdelijk uitgezet: geen storing, dus geen rood. Grijs en rustig. */
.merkje.hold { color: hsl(var(--gedempte-tekst)); background: hsl(var(--gedempt));
               border-color: hsl(var(--rand)); }
tr.rust td { opacity: .65; }

/* Slepen tussen "in bedrijf" en "tijdelijk uit". Een rij die je kunt oppakken
   hoort dat te laten zien voordat je hem oppakt, anders ontdekt niemand het. */
tr[draggable="true"] { cursor: grab; }
body.sleept tr[draggable="true"] { cursor: grabbing; }
/* Twee bakken die duidelijk verschillen. Ze zagen er allebei uit als een
   gewone witte kaart, en dan lijkt het onderste vak een mededeling in plaats
   van een plek waar iets in ligt. De rustbak is grijs en gestippeld.

   Dezelfde stippellijn als het sleepvlak bij Media (2 px): dat is in dit
   paneel de vorm die "hier kun je iets in laten vallen" betekent, en dan hoeft
   niemand twee vormen te leren. De dikke streep links is eruit -- die zei
   niets en trok het vak scheef (John, 27 september 2026: "Tijdelijk uit heeft
   links nog een dikke rand, de stippellijn eromheen mag iets dikker zodat je
   ook ziet dat je een scherm erin kunt slepen"). */
/* De twee bakken staan samen in één blok dat zichzelf ververst, dus de gap van
   .inhoud geldt er niet: zonder deze regel plakt "Tijdelijk uit" tegen de kaart
   erboven. */
#schermvak { display: flex; flex-direction: column; gap: 1.5rem; }
.werkvak > header h2, .rustvak > header h2,
.kanaalvak > header h2 { display: flex; align-items: center; gap: .5rem; }
.rustvak {
  border: 2px dashed hsl(var(--rand));
  background: hsl(var(--gedempt) / .7);
  transition: border-color .15s, background .15s;
}
.rustvak > header p { max-width: 46rem; }
.rustvak table { background: hsl(var(--kaart)); border-radius: calc(var(--radius) - 2px); }
/* De rustbak heeft geen kolomkoppen; dan hoort de eerste rij niet tegen de
   bovenrand te plakken. */
.rustvak tbody tr:first-child td { padding-top: 1rem; }
[data-vak].raak { outline: 2px solid hsl(var(--accent)); outline-offset: 2px;
                  background: hsl(var(--accent) / .06); }
.stip { width: .5rem; height: .5rem; border-radius: 999px; background: currentColor; }

.gedempt { color: hsl(var(--gedempte-tekst)); }
.klein { font-size: 14px; }
.letop { color: hsl(var(--let-op)); }
.getal { font-variant-numeric: tabular-nums; }
/* Een lange waarde in een feittegel (een versienummer, een modelnaam) mag een
   stap kleiner dan de 17px van .feit b, anders breekt hij de tegel. */
.feit b.lang { font-size: 15px; }

.gelukt {
  padding: .75rem 1rem; border-radius: calc(var(--radius) - 2px); font-size: 14px;
  border: 1px solid hsl(var(--goed) / .4); background: hsl(var(--goed) / .1);
  color: hsl(var(--goed));
}
.kaart > form > header.scheiding, .kaart > header.scheiding {
  border-top: 1px solid hsl(var(--rand)); margin-top: .25rem;
}

.melding {
  padding: .75rem 1rem; border-radius: calc(var(--radius) - 2px);
  border: 1px solid hsl(var(--gevaar) / .4); background: hsl(var(--gevaar) / .08);
  color: hsl(var(--gevaar)); font-size: 13px;
}

/* Waarom dit scherm niet speelt: het eerste dat je leest, met de knop naar de
   plek waar je het repareert ernaast. Rood als er iets misgaat, rustig als het
   scherm zwart hoort te zijn (op hold, buiten de openingstijden, zwart volgens
   de agenda) -- dat is geen storing en hoort niet te alarmeren. */
.waarom {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  margin-bottom: 1rem; padding: .75rem 1rem; font-size: 15px;
  border-radius: calc(var(--radius) - 2px);
  border: 1px solid hsl(var(--gevaar) / .4); background: hsl(var(--gevaar) / .08);
  color: hsl(var(--gevaar));
}
.waarom > span { flex: 1 1 20rem; }
.waarom.verwacht {
  border-color: hsl(var(--rand)); background: hsl(var(--gedempt) / .6);
  color: hsl(var(--voorgrond));
}
.leeg { padding: 3rem 1.25rem; text-align: center; color: hsl(var(--gedempte-tekst)); }
/* De ene zin die zo'n leeg vlak uitlegt, in gewone tekstkleur. */
.leeg .leegkop { font-size: 17px; font-weight: 500; color: hsl(var(--voorgrond)); }

/* --------------------------------------------------------- de lege begintoon */

.welkom { padding: 3.5rem 1rem; text-align: center; }
.welkom > h2 { margin: 0 0 2.25rem; font-size: 24px; font-weight: 400; }
.welkom > h2 b { font-weight: 600; }
.keuzes { display: flex; gap: 1.25rem; justify-content: center; flex-wrap: wrap; }
.keuze {
  width: 26rem; max-width: 100%; text-align: left; border-radius: 14px;
  padding: 2rem; display: flex; flex-direction: column; gap: .75rem;
}
.keuze h3 { margin: 0; font-size: 20px; font-weight: 600; }
.keuze p { margin: 0; font-size: 15px; opacity: .85; line-height: 1.6; }
.keuze .duw { margin-top: auto; padding-top: .5rem; }
.keuze.donker { background: hsl(258 25% 14%); color: #fff; }
.keuze.donker .knop { background: hsl(var(--accent)); }
.keuze.kleur { background: linear-gradient(135deg, hsl(var(--accent)), hsl(275 80% 58%)); color: #fff; }
.keuze.kleur .knop { background: #fff; color: hsl(258 30% 15%); }

/* ------------------------------------------------------ media en afspeellijst */

.tegel { display: flex; flex-direction: column; }
.tegel .beeld {
  aspect-ratio: 16/9; background: hsl(var(--gedempt));
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.tegel .beeld img { width: 100%; height: 100%; object-fit: cover; }
.tegel .onder { padding: .75rem .875rem; display: flex; flex-direction: column; gap: .25rem; }
.tegel .naam { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.dia { display: flex; gap: .875rem; align-items: center; padding: .75rem 1.25rem;
       border-bottom: 1px solid hsl(var(--rand)); }
.dia:last-of-type { border-bottom: 0; }
.dia .grijp { cursor: grab; color: hsl(var(--gedempte-tekst)); user-select: none; }
.dia iframe.voor { border: 0; pointer-events: none; }
.dia .voor { width: 5rem; aspect-ratio: 16/9; border-radius: 4px; background: hsl(var(--gedempt));
             object-fit: cover; flex: none; }
.dia .midden { flex: 1; min-width: 0; }
.dia input[type=number] { width: 5rem; }
/* De prullenbak staat op dezelfde onderlijn als de velden ernaast en is even
   hoog. Zonder dit hing hij 18 px hoger (hij werd gecentreerd tegen het blok
   label+veld) en was hij 34 px tegen 42 (John, 25 september 2026: "icon lijnt
   weer niet met de rest"). */
.dia .knop.weg { align-self: flex-end; height: var(--hoog); }
.dia select { width: 9.5rem; }

/* ------------------------------------------------------------------- inloggen */

.poort { min-height: 100vh; display: grid; place-items: center; padding: 1.5rem;
         background: hsl(var(--zij)); }
.poort .kaart { width: 23rem; max-width: 100%; }
.poort .merk { justify-content: center; color: hsl(var(--zij-tekst)); }

/* ------------------------------------------------------------------ vensters
 *
 * Met het <dialog> van de browser zelf: die regelt de laag erboven, het
 * sluiten met escape en de aandacht in het venster. Scheelt een bibliotheek.
 */

dialog {
  border: 0; padding: 0; border-radius: 14px; max-width: 46rem; width: calc(100% - 2rem);
  background: hsl(var(--kaart)); color: hsl(var(--voorgrond));
  box-shadow: 0 24px 60px hsl(240 10% 4% / .35);
}
dialog::backdrop { background: hsl(240 10% 4% / .55); }
dialog header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1.25rem 1.5rem; border-bottom: 1px solid hsl(var(--rand));
}
dialog header h2 { margin: 0; font-size: 20px; font-weight: 600; }
dialog .sluit {
  background: none; border: 0; cursor: pointer; color: hsl(var(--gedempte-tekst));
  font-size: 24px; line-height: 1; padding: .25rem .5rem; border-radius: 6px;
}
dialog .sluit:hover { background: hsl(var(--gedempt)); }
dialog .romp { padding: 1.5rem; display: flex; flex-direction: column; gap: 1rem; }
dialog footer {
  padding: 1rem 1.5rem; border-top: 1px solid hsl(var(--rand));
  display: flex; gap: .75rem; justify-content: flex-end; align-items: center;
}

/* Het koppelvenster: een donker vlak met één groot veld, zoals het scherm
   waar de code op staat. Zo hoort het bij elkaar. */
.koppelvlak {
  background: hsl(258 25% 12%); color: #fff; border-radius: 12px;
  padding: 2.5rem 2rem; text-align: center;
}
.koppelvlak h3 { margin: 0 0 1.75rem; font-size: 20px; font-weight: 500; }
.koppelvlak input {
  background: transparent; border: 0; border-bottom: 3px solid hsl(var(--accent));
  border-radius: 0; color: #fff; text-align: center; height: 4rem;
  font-size: 44px; font-weight: 600; letter-spacing: .3em; text-indent: .3em;
  font-variant-numeric: tabular-nums; max-width: 22rem; margin: 0 auto;
}
.koppelvlak input:focus-visible { outline: 0; border-bottom-color: #fff; }
.koppelvlak p { margin: 1.75rem 0 0; font-size: 14px; opacity: .6; }

/* ---------------------------------------------------------- media als lijst */

.balkje { display: flex; align-items: center; gap: .5rem; justify-content: space-between;
          padding: 0 .25rem; }
/* De twee weergaveknopjes horen naast elkaar, niet onder elkaar: het zijn twee
   standen van hetzelfde, geen twee losse knoppen. */
.standen { display: inline-flex; gap: .25rem; flex: none; white-space: nowrap; }
.standen a {
  display: grid; place-items: center; width: var(--hoog); height: var(--hoog);
  border-radius: calc(var(--radius) - 2px); color: hsl(var(--gedempte-tekst));
  text-decoration: none; border: 1px solid transparent;
}
.standen a.hier { background: hsl(var(--gedempt)); color: hsl(var(--voorgrond));
                  border-color: hsl(var(--rand)); }
.mini { width: 3.5rem; height: 2.2rem; object-fit: cover; border-radius: 5px;
        background: hsl(var(--gedempt)); flex: none; }
td .met-beeld { display: flex; align-items: center; gap: .875rem; }

/* --------------------------------------------------------------- de kiezer */

.kiesrij {
  display: flex; align-items: center; gap: .875rem; padding: .7rem 1rem;
  border-bottom: 1px solid hsl(var(--rand)); cursor: pointer;
}
.kiesrij:hover { background: hsl(var(--gedempt) / .6); }
.kiesrij input { width: 1.1rem; height: 1.1rem; flex: none; accent-color: hsl(var(--accent)); }
.kieslijst { max-height: 24rem; overflow: auto; border: 1px solid hsl(var(--rand));
             border-radius: var(--radius); }

/* ------------------------------------------------------------ binnenkort */

.binnenkort { display: flex; flex-direction: column; align-items: center; gap: 1rem;
              padding: 4rem 1rem; text-align: center; color: hsl(var(--gedempte-tekst)); }
.binnenkort h2 { margin: 0; font-size: 20px; color: hsl(var(--voorgrond)); }
.binnenkort p { margin: 0; max-width: 32rem; }

/* ----------------------------------------------------------- twee kolommen */

/* Links het beeld met de knoppen, rechts het werk: instellingen, logboek,
   gespeeld. Die rechterkolom stond op 24 rem en dat is voor een formulier met
   twintig velden een koker -- alles kwam onder elkaar in een strookje. Nu deelt
   hij de ruimte, met een ondergrens zodat twee velden naast elkaar passen.

   Er staat ook een bovengrens op de rechterkolom. Zonder die grens rekt een
   formulier op een breed scherm mee tot een naamveld van duizend pixels breed,
   met de vinkjes verloren in het wit. Een formulier wordt niet beter van meer
   breedte; een voorbeeldbeeld wel. De ruimte die overblijft gaat dus naar
   links, naar het beeld. */
/* De linkerkolom heeft een ONDERGRENS. Met minmax(0, 1fr) pakte de
   rechterkolom eerst zijn 46 rem en hield links soms 48 px over -- tussen
   ongeveer 1000 en 1250 px was het voorbeeldbeeld daarmee een streepje. Dat
   viel hier nooit op omdat we altijd op een breed venster kijken; het nameten
   (hulp/paneel-meten.js) zag het meteen. Nu krimpt rechts eerst. */
/* Het VOORBEELD krijgt wat er over is, en het formulier houdt een bovengrens.
   John, 4 oktober 2026: "kan de preview groter?" Gemeten op 1600 px: het
   formulier nam zijn maximum van 46 rem (736 px) en voor het beeld bleef 512
   px over. Een formulier wordt niet beter van meer breedte, een beeld wel --
   dezelfde reden als in september, nu met een scherpere grens: 36 rem is nog
   ruim genoeg voor een label met een veld eronder, en het beeld wint 64 px. */
.werkblad { display: grid; grid-template-columns: minmax(16rem, 1fr) minmax(22rem, 36rem);
            gap: 1.5rem; align-items: start; }
/* Breed: voor een scherm waar RECHTS het werk zit in plaats van links. Een
   menukaart heeft een tabel met acht kolommen, en die past niet in 46 rem
   (John, 3 oktober 2026: "de rechterkolom waar de app in staat is te klein").
   Het voorbeeld links blijft groot genoeg om iets aan te zien. */
.werkblad.breed { grid-template-columns: minmax(14rem, 22rem) minmax(32rem, 1fr); }
@media (max-width: 62rem) { .werkblad, .werkblad.breed { grid-template-columns: 1fr; } }

/* Tabbladen, voor apparaat naast instellingen. */
.tabs { display: flex; border-bottom: 1px solid hsl(var(--rand)); }
.tabs a {
  /* min-width: 0 erbij, anders is flex-basis 0 maar blijft de minimumbreedte
     die van het woord zelf: "INSTELLINGEN" werd dan breder dan "GESPEELD" en
     stonden de vier tabs ongelijk. */
  flex: 1 1 0; min-width: 0; white-space: nowrap; text-align: center; padding: .875rem .5rem; text-decoration: none;
  font-weight: 500; font-size: 13px; letter-spacing: .04em; text-transform: uppercase;
  color: hsl(var(--gedempte-tekst)); border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tabs a.hier { color: hsl(var(--voorgrond)); border-bottom-color: hsl(var(--accent)); }

/* Kleine feitjes over het apparaat, twee op een rij. */
/* John, 26 september 2026: "4 graag". Twee kolommen lieten de halve breedte
   leeg staan. Een vast getal en geen auto-fill: op een breed venster zouden dat
   er zes of zeven worden, en dan staan er drie woorden per tegel. */
.feiten { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; }
@media (min-width: 62rem) { .feiten { grid-template-columns: repeat(4, 1fr); } }
.feit {
  border: 1px solid hsl(var(--rand)); border-radius: calc(var(--radius) - 2px);
  padding: .75rem .875rem; min-width: 0;
}
.feit span { display: block; font-size: 12px; color: hsl(var(--gedempte-tekst));
             display: flex; gap: .375rem; align-items: center; }
.feit b { display: block; font-size: 17px; font-weight: 600; margin-top: .25rem;
          overflow-wrap: anywhere; }
.feit.breed { grid-column: 1 / -1; }

/* De feiten van een apparaat in groepen (schermpagina, tab Apparaat). */
.feitgroepen { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr)); gap: 1rem; }
.feitgroep { border: 1px solid hsl(var(--rand)); border-radius: var(--radius); padding: .9rem 1rem 1rem;
             background: hsl(var(--kaart)); min-width: 0; }
.feitgroep h3 { display: flex; align-items: center; gap: .45rem; margin: 0 0 .7rem; font-size: 12px;
                font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: hsl(var(--gedempte-tekst)); }
.feitgroep h3 svg { color: hsl(var(--accent)); }
dl.feitjes { margin: 0; display: grid; grid-template-columns: 7.75rem minmax(0, 1fr); gap: .55rem .9rem; font-size: 14px; }
dl.feitjes dt { color: hsl(var(--gedempte-tekst)); }
dl.feitjes dd { margin: 0; overflow-wrap: anywhere; line-height: 1.45; }
dl.feitjes dd code { font-size: 13px; }
dl.feitjes dd .klein { display: block; margin-top: .15rem; }
@media (max-width: 520px) { dl.feitjes { grid-template-columns: 1fr; gap: .1rem .9rem; } dl.feitjes dd { margin-bottom: .45rem; } }
dl.regels { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: .5rem .875rem;
            font-size: 14px; align-items: baseline; }
dl.regels dt { color: hsl(var(--gedempte-tekst)); white-space: nowrap; }
dl.regels dd { margin: 0; text-align: right; overflow-wrap: anywhere;
               font-variant-numeric: tabular-nums; }

/* Wat er nu speelt: het beeld met een randje eromheen. */
.nuspeelt { background: #0b0a10; border-radius: calc(var(--radius) - 2px);
            aspect-ratio: 16/9; display: grid; place-items: center; overflow: hidden; }
.nuspeelt img { width: 100%; height: 100%; object-fit: contain; }
.nuspeelt .niets { color: hsl(var(--gedempte-tekst)); font-size: 13px; }

/* Het voorbeeld: een echte speler in een lijstje. */
.voorbeeldvlak {
  background: #000; border-radius: var(--radius); overflow: hidden;
  border: 1px solid hsl(var(--rand)); aspect-ratio: 16/9; position: relative;
}
.voorbeeldvlak iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
/* Waarom er staat wat er staat. Onder het vlak, klein en gedempt: het is een
   bijschrift bij het beeld, niet het beeld zelf. */
.voorbeeldbijschrift {
  margin: .6rem 0 0; text-align: center; font-size: 13px; color: hsl(var(--gedempte-tekst));
}

/* De keuze 0/90/180/270 als een rij knoppen. */
.keuzerij { display: flex; gap: .375rem; }
.keuzerij label { flex: 1; }
.keuzerij input { position: absolute; opacity: 0; pointer-events: none; }
.keuzerij span {
  display: block; text-align: center; padding: .55rem .25rem; cursor: pointer;
  border: 1px solid hsl(var(--rand)); border-radius: calc(var(--radius) - 2px);
  font-weight: 500; font-size: 14px;
}
.keuzerij input:checked + span {
  background: hsl(var(--accent)); color: hsl(var(--accent-tekst));
  border-color: hsl(var(--accent));
}
.keuzerij input:focus-visible + span { outline: 2px solid hsl(var(--ring) / .5); }

/* --------------------------------------------------------------- uploaden */

.sleepvlak {
  border: 2px dashed hsl(var(--rand)); border-radius: var(--radius);
  padding: 2.5rem 1.5rem; text-align: center; display: flex; flex-direction: column;
  align-items: center; gap: .75rem; background: hsl(var(--gedempt) / .4);
  transition: border-color .15s, background .15s;
}
.sleepvlak.erboven { border-color: hsl(var(--accent)); background: hsl(var(--accent) / .07); }
.sleepvlak h3 { margin: 0; font-size: 17px; font-weight: 600; }
.sleepvlak p { margin: 0; font-size: 14px; color: hsl(var(--gedempte-tekst)); }
.sleepvlak .plaatjes { display: flex; gap: .5rem; opacity: .5; }
.sleepvlak input[type=file] { display: none; }
.gekozen { display: flex; flex-direction: column; gap: .375rem; width: 100%;
           max-height: 12rem; overflow: auto; text-align: left; }
.gekozen div { display: flex; justify-content: space-between; gap: 1rem;
               font-size: 14px; padding: .375rem .625rem; border-radius: 6px;
               background: hsl(var(--kaart)); border: 1px solid hsl(var(--rand)); }

/* --------------------------------------------------------------- mappen */

.mapbalk { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }
.mapbalk a {
  display: inline-flex; align-items: center; gap: .5rem; padding: .45rem .8rem;
  border: 1px solid hsl(var(--rand)); border-radius: 999px; text-decoration: none;
  font-size: 14px; font-weight: 500; background: hsl(var(--kaart));
}
.mapbalk a.hier { background: hsl(var(--accent)); color: hsl(var(--accent-tekst));
                  border-color: hsl(var(--accent)); }
.mapbalk a small { opacity: .6; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ agenda
 *
 * Een week in zeven kolommen. De uren staan links; een blok wordt met de muis
 * versleept en aan de onderrand langer gemaakt. Alles in gewone css-raster,
 * geen kalenderbibliotheek: dit is een tabel met blokjes erin.
 */

.agenda { border: 1px solid hsl(var(--rand)); border-radius: var(--radius);
          overflow: hidden; background: hsl(var(--kaart)); }
.agendakop, .agendalijf { display: grid; grid-template-columns: 3.5rem repeat(7, 1fr); }
.agendakop {
  border-bottom: 1px solid hsl(var(--rand)); position: sticky; top: 0; z-index: 3;
  background: hsl(var(--kaart));
}
.agendakop div { padding: .7rem .5rem; text-align: center; font-weight: 600; font-size: 14px; }
.agendakop div + div { border-left: 1px solid hsl(var(--rand)); }
.agendakop div.vandaag { color: hsl(var(--accent)); }

/* Zo hoog als er ruimte is, met een bodem zodat hij op een laptop niet
   ineenschrompelt. Op een grote monitor bleef de onderkant anders leeg.
   De 35rem (was 32) laat ruimte voor de groene meldingsbalk die na het opslaan
   van een blok bovenin verschijnt; zonder die marge werd de pagina hoger dan
   het scherm en moest je scrollen. */
.agendarol { height: clamp(20rem, calc(100vh - 35rem), 64rem);
             overflow: auto; position: relative; }
.uren { border-right: 1px solid hsl(var(--rand)); }
.uren span {
  display: block; height: 3rem; font-size: 12px; color: hsl(var(--gedempte-tekst));
  text-align: right; padding-right: .5rem; transform: translateY(-.55em);
}
.dagkolom { position: relative; border-left: 1px solid hsl(var(--rand)); }
.dagkolom .uurlijn { height: 3rem; border-bottom: 1px solid hsl(var(--rand) / .6); }
.dagkolom .uurlijn:nth-child(2n) { background: hsl(var(--gedempt) / .35); }

.blok {
  position: absolute; left: 3px; right: 3px; border-radius: 6px; overflow: hidden;
  background: var(--blokkleur, hsl(var(--accent))); color: #fff;
  border: 1px solid var(--blokkleur, hsl(var(--accent))); cursor: grab; user-select: none;
  padding: .25rem .45rem; font-size: 12px; line-height: 1.25; z-index: 2;
  box-shadow: 0 1px 3px hsl(240 10% 4% / .25);
}
.blok.sleept { cursor: grabbing; opacity: .85; z-index: 4; }
.blok b { display: block; font-weight: 600; overflow: hidden; text-overflow: ellipsis;
          white-space: nowrap; }
.blok small { display: block; opacity: .85; font-variant-numeric: tabular-nums;
              white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.blok .rekker {
  position: absolute; left: 0; right: 0; bottom: 0; height: 8px; cursor: ns-resize;
}
.blok .rekker::after {
  content: ""; position: absolute; left: 50%; bottom: 2px; width: 1.5rem; height: 2px;
  transform: translateX(-50%); background: currentColor; opacity: .5; border-radius: 2px;
}
.blok.kort { padding-top: .1rem; font-size: 12px; }
.blok.kort small { display: none; }
/* Een blok dat op meer dagen terugkomt, draagt het teken van herhalen. */
.blok.reeks b::before { content: "↻"; margin-right: .3em; font-weight: 400; opacity: .9; }
/* Een blok met datums: een uitzondering op het weekpatroon. Het staat naast
   het blok waar het overheen gaat, niet erop — anders lijkt het één blok en
   denk je dat je planning weg is. */
.blok .periode { display: block; opacity: .85; font-variant-numeric: tabular-nums; }
.blok .periode::before { content: "▸ "; opacity: .8; }
.blok.metdatum { box-shadow: 0 1px 3px hsl(240 10% 4% / .25), inset 0 0 0 2px hsl(0 0% 100% / .55); }
.blok.kort .periode { display: none; }

/* Op welke dagen een blok staat: zeven knoppen, met snelkeuzes eronder. */
.dagkeus { display: flex; gap: .375rem; flex-wrap: wrap; }
.dagkeus label { position: relative; }
.dagkeus input { position: absolute; opacity: 0; pointer-events: none; }
.dagkeus span {
  display: inline-flex; align-items: center; justify-content: center;
  width: 3rem; height: var(--hoog); border: 1px solid hsl(var(--rand));
  border-radius: calc(var(--radius) - 2px); cursor: pointer; font-weight: 500; font-size: 15px;
}
.dagkeus input:checked + span {
  background: hsl(var(--accent)); border-color: hsl(var(--accent)); color: hsl(var(--accent-tekst));
}
.dagkeus input:focus-visible + span { outline: 2px solid hsl(var(--ring) / .5); outline-offset: 1px; }
.dagkeus span.hier { box-shadow: inset 0 -3px 0 hsl(var(--voorgrond) / .35); }
/* Een dag die in de gekozen periode helemaal niet voorkomt: uit te sluiten,
   niet stilletjes een rij laten opleveren die nooit speelt. */
.dagkeus span.kanniet { opacity: .35; cursor: not-allowed;
                        background: hsl(var(--gedempt)); }
.snelkeus { display: flex; gap: .375rem; flex-wrap: wrap; }

/* Een korte vraag met drie antwoorden, zoals "alleen deze dag of alle dagen". */
dialog.vraag { max-width: 34rem; }
dialog.vraag h2 { margin: 0 0 .25rem; font-size: 20px; font-weight: 600; }
dialog.vraag p { margin: 0; color: hsl(var(--gedempte-tekst)); line-height: 1.5; }

.agendauitleg { display: flex; gap: 1rem; flex-wrap: wrap; align-items: center;
                font-size: 14px; color: hsl(var(--gedempte-tekst)); }


/* Tussen twee blokken in één kaart: een lijn en weer lucht.

   Met dezelfde soort selector als de romp zelf, anders wint
   ".kaart > form > .romp" met zijn padding-top van 0 en plakt het eerste label
   tegen de scheidingslijn. Dat was precies wat er bij Draaiing, Aan vanaf,
   Updates en Plaats te zien was. */
.kaart .scheiding { border-top: 1px solid hsl(var(--rand)); }
.kaart > .scheiding, .kaart > form > .scheiding,
.kaart > .romp.scheiding, .kaart > form > .romp.scheiding { padding-top: 1.5rem; }

/* Wat er nu speelt, in de verhouding van het kanaal zelf. */
.nuspeelt.opmaat { max-height: 30rem; margin: 0 auto; width: 100%; position: relative; }
/* Het beeld over het hele vak leggen, anders neemt het zijn eigen verhouding
   mee, snijdt de rand het af, en lijkt 'passend' ineens 'zoom'. Dan liegt
   het voorbeeld over wat er op het scherm staat. */
.nuspeelt.opmaat img, .nuspeelt.opmaat video {
  position: absolute; inset: 0; width: 100%; height: 100%;
}
.nuspeelt .passend { object-fit: contain; }
.nuspeelt .uitgerekt { object-fit: fill; }
.nuspeelt .geen { object-fit: none; object-position: center; }
.nuspeelt .zoom { object-fit: cover; object-position: center; }
.nuspeelt img, .nuspeelt video { object-position: left top; }
/* De afdruk van een box is het hele hdmi-beeld; die ligt op schaal
   linksboven en steekt uit het vak (overflow: hidden snijdt hem af). */
.nuspeelt.opmaat img.hdmi { inset: auto; left: 0; top: 0; height: auto; object-fit: unset; }

/* Keuze tussen twee dingen, als twee grote knoppen naast elkaar. */
.tweekeus { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; }
.tweekeus label { position: relative; }
.tweekeus input { position: absolute; opacity: 0; pointer-events: none; }
.tweekeus span {
  display: flex; flex-direction: column; gap: .15rem; padding: .75rem .875rem;
  border: 1px solid hsl(var(--rand)); border-radius: calc(var(--radius) - 2px);
  cursor: pointer; font-weight: 500;
}
.tweekeus span small { font-weight: 400; color: hsl(var(--gedempte-tekst)); font-size: 13px; }
.tweekeus input:checked + span { border-color: hsl(var(--accent));
  box-shadow: 0 0 0 1px hsl(var(--accent)); background: hsl(var(--accent) / .06); }
.tweekeus input:focus-visible + span { outline: 2px solid hsl(var(--ring) / .5); }

/* Schermen aan een kanaal hangen: een lijst met vinkjes. */
.vinklijst { display: flex; flex-direction: column; border: 1px solid hsl(var(--rand));
             border-radius: calc(var(--radius) - 2px); }
.vinklijst label { display: flex; align-items: center; gap: .75rem; padding: .7rem .875rem;
                   cursor: pointer; }
.vinklijst label + label { border-top: 1px solid hsl(var(--rand)); }
.vinklijst input { width: 1.25rem; height: 1.25rem; accent-color: hsl(var(--accent)); flex: none; }
/* Vinkjes in een tabel (media): groot genoeg om te raken, ook op een tablet. */
table input[type="checkbox"] { width: 1.35rem; height: 1.35rem; accent-color: hsl(var(--accent));
                               cursor: pointer; vertical-align: middle; }
.vinklijst .rechts { margin-left: auto; font-size: 13px; color: hsl(var(--gedempte-tekst)); }

.opdrachtlog { display: flex; flex-direction: column; gap: .2rem; margin-top: .75rem;
               padding-top: .75rem; border-top: 1px solid hsl(var(--rand)); }

/* ------------------------------------------------------- toezicht op afstand */

/* Hoe het met een scherm gaat, in een paar vakjes met een gekleurde rand. */
.gezondheid { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); }
.gezondheid .staat {
  border: 1px solid hsl(var(--rand)); border-left: 4px solid hsl(var(--goed));
  border-radius: calc(var(--radius) - 2px); padding: .7rem .9rem;
  display: flex; flex-direction: column; gap: .15rem;
}
.gezondheid .staat b { font-weight: 600; }
.gezondheid .staat span { font-size: 13px; color: hsl(var(--gedempte-tekst)); }
.gezondheid .staat.let { border-left-color: hsl(38 92% 50%); }
.gezondheid .staat.fout { border-left-color: hsl(var(--gevaar)); }

/* Een kaart die dicht begint: één regel die zegt wat erin zit, de rest op een klik. */
details.uitklap > summary { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap;
                            padding: 1rem 1.25rem; cursor: pointer; list-style: none; font-size: 15px; }
details.uitklap > summary::-webkit-details-marker { display: none; }
details.uitklap > summary h2 { margin: 0; font-size: 17px; font-weight: 600; }
details.uitklap > summary span { font-size: 13px; color: hsl(var(--gedempte-tekst)); }
details.uitklap > summary::after { content: "+"; margin-left: auto; color: hsl(var(--gedempte-tekst)); }
details.uitklap[open] > summary::after { content: "\2212"; }
details.uitklap[open] > summary { border-bottom: 1px solid hsl(var(--rand)); }

/* ------------------------------------------------ de lijst op de versiepagina

   John, 19 september 2026: "alles staat niet gelijnd, het ziet er rommelig uit."
   Een tabel belooft dat elke cel gevuld is, en dat was hier nooit zo: de helft
   van de kolommen stond leeg en de rest vulde zich met losse tekstlinks. Dit is
   één lijst met vaste kolommen, een kop erboven, en per regel steeds hetzelfde
   op dezelfde plek. Alles links uitgelijnd, ook de koppen. */

.lijst { border-top: 1px solid hsl(var(--rand)); }
.lijst > * { border-bottom: 1px solid hsl(var(--rand)); }
.lijst > *:last-child { border-bottom: 0; }

/* minmax(0, 1fr) en niet 1fr: een 1fr-kolom wordt anders zo breed als zijn
   langste onafgebroken regel, en dan schuift één rij met een lange uitleg alle
   kolommen erachter opzij. Precies wat er in de oude tabel ook misging. */
.regel { display: grid; grid-template-columns: 1.5rem minmax(0, 1fr) 6rem 8.5rem 9.5rem;
         align-items: center; gap: 1rem; padding: .9rem 1.5rem; }
.regel > svg { justify-self: center; }
.regel .naam { font-weight: 600; color: inherit; text-decoration: none; }
.regel a.naam:hover { text-decoration: underline; }
.regel .waar { display: block; font-size: 13px; color: hsl(var(--gedempte-tekst));
               margin-top: .1rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.regel .versie { font-variant-numeric: tabular-nums; white-space: nowrap; }
.regel .gebruik, .regel .doen { display: flex; gap: .4rem; }
.regel .gebruik .knop { white-space: nowrap; }

/* De koprij: de opmaak van een <th>, maar dan in hetzelfde raster. */
.regel.kop { padding-top: .8rem; padding-bottom: .8rem; font-size: 12px;
             text-transform: uppercase; letter-spacing: .04em; font-weight: 500;
             color: hsl(var(--gedempte-tekst)); }

/* Een regel die meer te vertellen heeft klapt zichzelf open, in hetzelfde
   raster: de versies en de knoppen blijven op hun streep staan. */
details.regelblok > summary { list-style: none; cursor: pointer; }
details.regelblok > summary::-webkit-details-marker { display: none; }
details.regelblok > summary:hover { background: hsl(var(--gedempt) / .6); }
details.regelblok > summary .naam::after { content: " \203A"; color: hsl(var(--gedempte-tekst)); }
details.regelblok[open] > summary .naam::after { content: " \2304"; }
details.regelblok[open] > summary { background: hsl(var(--gedempt) / .6); }
.uitklap-inhoud { padding: .25rem 1.5rem 1.25rem 4rem; background: hsl(var(--gedempt) / .35); }

/* De lagen boven de lijst: waar de onderdelen zich tot elkaar verhouden. */
.lagen { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-top: .9rem; }
.lagen .laag { border: 1px solid hsl(var(--rand)); border-radius: var(--radius);
               padding: .45rem .7rem; font-size: 13px; }
.lagen .laag b { display: block; font-size: 14px; }
.lagen .laag span { color: hsl(var(--gedempte-tekst)); }
.lagen .pijl { color: hsl(var(--gedempte-tekst)); }

/* Wat er te doen is staat onder de lijst, weg zodra het gedaan is. Een kolom
   ervoor zou bij alle andere regels leeg staan.

   Elk punt is een EIGEN vak, met dezelfde vorm als een opslaanvoet: grijs, een
   eigen rand, ronde hoeken, lucht eromheen. Eerst deelden ze het raster van de
   lijst (class="regel") zodat de knop in de kolom Downloaden viel; dat gaf drie
   grijze regels die aan elkaar plakten en samen geen vak waren. John,
   27 september 2026: "dit mag 1 veld zijn maar het mogen er ook 2 losse zijn."
   Losse vakken dus, en wat bij elkaar hoort in hetzelfde vak. */
.tedoen {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  margin: 1rem 1.25rem; padding: .875rem 1.25rem; font-size: 14px;
  background: hsl(var(--gedempt) / .5);
  border: 1px solid hsl(var(--rand)); border-radius: var(--radius);
}
.tedoen:last-child { margin-bottom: 1.25rem; }
.tedoen .tekst { display: flex; flex-direction: column; gap: .4rem; }
.tedoen p { margin: 0; }
.tedoen form { margin: 0; }
.tedoen .knop { white-space: nowrap; }
@media (max-width: 48rem) {
  .tedoen { flex-direction: column; align-items: stretch; }
  .tedoen .knop { width: 100%; }
}

/* De boxen: dezelfde regel, met klant en staat erbij. */
.regel.box { grid-template-columns: 1.5rem minmax(0, 1fr) 6rem 5.5rem 7.5rem auto; }
.regel.box .wachtwoord .knop { margin-left: .3rem; padding: .05rem .4rem; font-size: 12px; }
/* Met het wachtwoord erbij past de regel niet meer op één regel; dan mag hij 
   afbreken. Dat is precies het moment dat je hem staat te lezen. */
.regel.box.toont .waar { white-space: normal; }
.regel.box .doen form { display: inline-block; }
.regel.box .klant { color: hsl(var(--gedempte-tekst)); font-size: 14px; }
.regel.box .doen { justify-content: flex-end; }
.regel.box .knop.aan { border-color: hsl(var(--accent)); color: hsl(var(--accent)); }

.kleinetabel { font-size: 14px; width: auto; }
.kleinetabel td, .kleinetabel th { padding: .3rem 1.25rem .3rem 0; border: 0; white-space: nowrap; }
.kleinetabel th { padding-bottom: .5rem; }
.kleinetabel tr + tr td { border-top: 1px solid hsl(var(--rand)); }

/* In een smal venster passen zes kolommen niet. Dan geen raster maar een regel
   die vouwt: naam links, versie en knoppen erachter. De koprij gaat weg, want
   een kop boven een gevouwen regel wijst nergens meer naar. */
@media (max-width: 56rem) {
  .regel { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1rem; }
  .regel > span:nth-of-type(1) { flex: 1 1 12rem; }
  .regel .versie { margin-left: auto; }
  .regel .gebruik, .regel .doen, .regel.box .klant, .regel.box .staat { flex: none; }
  .regel.kop { display: none; }
  .uitklap-inhoud { padding-left: 1.5rem; }
}

/* Het venster achter "in gebruik": wie draait wat, met een link erheen. */
dialog.gebruikvenster { max-width: 34rem; }
dialog.gebruikvenster table { font-size: 14px; }
dialog.gebruikvenster td { padding: .5rem 1rem .5rem 0; border: 0; white-space: nowrap; }
dialog.gebruikvenster tr + tr td { border-top: 1px solid hsl(var(--rand)); }

/* De stip op de verzendknop: er wacht werk. Wit op paars, want op die knop is
   elke andere kleur een tweede boodschap. */
.knop .wachtstip { display: inline-block; width: .5rem; height: .5rem; border-radius: 999px;
                   background: currentColor; margin-left: .5rem; vertical-align: middle; }

.teller { display: inline-grid; place-items: center; min-width: 1.35rem; height: 1.35rem;
          padding: 0 .35rem; border-radius: 999px; font-size: 12px; font-weight: 600;
          background: hsl(var(--gedempt)); }
.teller.fout { background: hsl(var(--gevaar)); color: #fff; }

.niveau { display: inline-block; padding: .1rem .5rem; border-radius: 999px; font-size: 12px;
          font-weight: 600; text-transform: lowercase; background: hsl(var(--gedempt));
          color: hsl(var(--gedempte-tekst)); }
.niveau.fout { background: hsl(var(--gevaar) / .12); color: hsl(var(--gevaar)); }
.niveau.waarschuwing { background: hsl(38 92% 50% / .15); color: hsl(32 90% 38%); }
.logtabel td { vertical-align: top; }

/* Logboek en Gespeeld: één regel per melding, niet een tabel zo breed als de
   pagina. Alleen een fout krijgt kleur; een logboek waarin alles opvalt is een
   logboek waarin niets opvalt. Hij rolt in zichzelf, zodat honderdvijftig
   regels de pagina niet eindeloos maken. */
.logboek { list-style: none; margin: 0; padding: 0; max-height: 30rem; overflow-y: auto; }
.logboek li { display: flex; gap: .75rem; align-items: baseline;
              padding: .45rem .25rem .45rem .6rem; border-bottom: 1px solid hsl(var(--rand) / .5);
              font-size: 13px; border-left: 3px solid transparent; }
.logboek li:last-child { border-bottom: none; }
.logboek time { flex: none; width: 8.5ch; color: hsl(var(--gedempte-tekst)); font-size: 12px; }
.logboek .wat { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.logboek .wat small { display: block; color: hsl(var(--gedempte-tekst)); font-size: 12px; }
.logboek li.fout { border-left-color: hsl(var(--gevaar)); }
.logboek li.fout .wat { color: hsl(var(--gevaar)); }
.logboek li.waarschuwing { border-left-color: hsl(38 92% 50%); }
.logboek.gespeeld li { border-left: none; padding-left: .25rem; }

/* Tabellen die breder kunnen worden dan het scherm: zelf zijwaarts scrollen. */
.rolbaar { overflow-x: auto; }

/* Grote getallen bovenaan een rapport. */
.tellers { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); }
.tellers .kaart { padding: 1rem 1.25rem; display: flex; flex-direction: column; gap: .2rem; }
.tellers span { font-size: 14px; color: hsl(var(--gedempte-tekst)); }
.tellers b { font-size: 28px; font-weight: 650; letter-spacing: -.02em; }
.tellers small { font-size: 12px; color: hsl(var(--gedempte-tekst)); }

/* Een keuze tussen een paar standen, als één strook knoppen. */
.segment { display: inline-flex; align-self: flex-start; gap: .2rem; padding: .2rem;
           background: hsl(var(--gedempt)); border-radius: calc(var(--radius) - 1px); }
.segment a { padding: .35rem .85rem; border-radius: calc(var(--radius) - 3px); font-size: 14px;
             font-weight: 500; text-decoration: none; color: hsl(var(--gedempte-tekst)); }
.segment a.hier { background: hsl(var(--kaart)); color: hsl(var(--voorgrond));
                  box-shadow: 0 1px 2px hsl(240 10% 4% / .12); }

/* Een tekstvak met meer regels groeit mee; de algemene veldregel zet anders
   alles op één regel hoog. */
textarea { height: auto; min-height: 5rem; padding: .6rem .75rem; resize: vertical; line-height: 1.5; }

/* Een melding dat iets gelukt is: dezelfde vorm, andere kleur. */
.melding.goed { border-color: hsl(var(--goed) / .45); background: hsl(var(--goed) / .08);
                color: hsl(142 60% 28%); }

/* Eén losse aan/uit-keuze met uitleg ernaast. */
.vinkje { display: flex; align-items: center; gap: .65rem; cursor: pointer; font-size: 15px; }
.vinkje input { width: 1.1rem; height: 1.1rem; accent-color: hsl(var(--accent)); flex: none; }
/* Een vinkje met uitleg. John, 26 september 2026: "kan dit iets duidelijker
   worden uitgelegd?" De uitleg stond tussen haakjes ACHTER de tekst en liep op
   een tweede regel door tot onder het vakje; dan lees je niet meer waar de ene
   regel ophoudt. Nu de keuze op zijn eigen regel en de uitleg eronder, met de
   tekst netjes naast het vakje uitgelijnd -- zoals bij elke knop op de
   schermpagina (ONTWERP.md, punt 6). */
.vinkje.metuitleg { align-items: flex-start; }
.vinkje.metuitleg input { margin-top: .15rem; }
.vinkje.metuitleg > span { display: flex; flex-direction: column; gap: .15rem; }
.vinkje.metuitleg small { font-size: 13px; color: hsl(var(--gedempte-tekst)); line-height: 1.45; }

/* De tabbladen van Instellingen: een strook boven de pagina. */
.instellingtabs { padding: 0 .75rem; }

/* Rechten: de keuze kleurt mee, zodat je ziet wat afgeschermd is. */
.rechtentabel td { vertical-align: middle; }
.rechtentabel select { min-width: 15rem; }
.rechtentabel select.geen { color: hsl(var(--gevaar)); border-color: hsl(var(--gevaar) / .35); }
/* background-color, niet background: dat laatste gooit het pijltje van de keuzelijst weg. */
.rechtentabel select.wijzigen { border-color: hsl(var(--accent) / .6);
                                background-color: hsl(var(--accent) / .06); }

/* Een groepje velden dat bij één keuze hoort. */
.groep { display: flex; flex-direction: column; gap: .875rem; }

/* Aan de slag: wat er nog moet gebeuren voordat een scherm iets laat zien.
   Geen wizard maar een lijstje dat verdwijnt zodra het af is. */
.stappenlijst { list-style: none; margin: 0; padding: 0; display: flex;
                flex-direction: column; gap: .25rem; }
.stappenlijst li { display: flex; align-items: center; gap: .75rem;
                   padding: .6rem .7rem; border-radius: var(--radius);
                   border: 1px solid transparent; }
.stappenlijst li.nu { border-color: hsl(var(--accent) / .35);
                      background: hsl(var(--accent) / .06); }
.stappenlijst .vinkje { flex: none; display: inline-grid; place-items: center;
                        width: 1.6rem; height: 1.6rem; border-radius: 999px;
                        font-size: 13px; font-weight: 600;
                        border: 1px solid hsl(var(--rand));
                        color: hsl(var(--gedempte-tekst)); }
.stappenlijst li.klaar .vinkje { border-color: hsl(var(--goed) / .4);
                                 background: hsl(var(--goed) / .12);
                                 color: hsl(var(--goed)); }
.stappenlijst li.nu .vinkje { border-color: hsl(var(--accent) / .5);
                              background: hsl(var(--accent) / .12);
                              color: hsl(var(--accent)); }
.stappenlijst .wat { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.stappenlijst .wat small { font-size: 13px; }
/* --gedempte-tekst, niet --gedempt: dat laatste is een achtergrondtint, en
   daarmee was de titel van een afgevinkte stap zo goed als onzichtbaar. */
.stappenlijst li.klaar .wat b { color: hsl(var(--gedempte-tekst)); font-weight: 500; }

/* Kiezen in een kolom in plaats van in een uitklaplijst: één klik, en je ziet
   wat er nog meer is. Onder de 640 px wordt het een strook die opzij schuift. */
.metkolom { display: grid; grid-template-columns: 15rem minmax(0, 1fr); gap: 1rem;
            align-items: start; }
/* Valt er niets te kiezen (een klant met één kanaal of één lijst), dan laat
   keuzekolom.html de kolom weg. Zonder deze regel bleef de pagina in tweeën
   verdeeld en stond alle inhoud in de smalle kolom van 15 rem (Edge Eindhoven,
   18 september 2026; bij Questo viel het nooit op, daar is altijd keus). */
.metkolom:not(:has(> .keuzekolom)) { grid-template-columns: minmax(0, 1fr); }
.keuzekolom { display: flex; flex-direction: column; gap: .15rem;
              background: hsl(var(--kaart)); border: 1px solid hsl(var(--rand));
              border-radius: var(--radius); padding: .5rem; position: sticky; top: 1rem; }
.keuzekolom .kolomkop { font-size: 12px; font-weight: 600; letter-spacing: .04em;
                        text-transform: uppercase; color: hsl(var(--gedempte-tekst));
                        padding: .45rem .6rem .3rem; }
.keuzekolom a { display: flex; flex-direction: column; gap: .1rem;
                padding: .5rem .6rem; border-radius: calc(var(--radius) - 2px);
                text-decoration: none; color: inherit; }
.keuzekolom a:hover { background: hsl(var(--gedempt)); }
.keuzekolom a.hier { background: hsl(var(--accent)); color: #fff; }
.keuzekolom a b { font-weight: 600; font-size: 14px; }
.keuzekolom a small { font-size: 12px; color: hsl(var(--gedempte-tekst)); }
.keuzekolom a.hier small { color: hsl(0 0% 100% / .75); }

/* 62rem en niet 640px (1.90.2). De hoofdmenubalk blijft tot 48rem staan op
   264 px; een tweede kolom van 264 px ernaast liet op een venster van 900 px
   nog 277 px over voor het werk zelf, en daar past "Tweestapsverificatie
   instellen" niet eens in. 62rem is dezelfde grens als bij .werkblad, zodat er
   één breedte is waarop een pagina van twee kolommen naar één gaat. */
@media (max-width: 62rem) {
  .metkolom { grid-template-columns: minmax(0, 1fr); }
  .keuzekolom { flex-direction: row; overflow-x: auto; position: static;
                gap: .35rem; }
  .keuzekolom .kolomkop { display: none; }
  .keuzekolom a { flex: none; }
}

/* De hamburger en de waas horen alleen op smalle schermen; op de desktop staat
   de zijbalk gewoon vast. */
.menuknop { display: none; }
.menu-waas { display: none; }
/* Telefoon/kleine tablet: de zijbalk schuift als lade in, en een knop in de kop
   opent hem. Zo is het paneel ook op een telefoon te bedienen. Volledige
   navigatie herlaadt de pagina, dus de lade sluit vanzelf bij het klikken. */
@media (max-width: 48rem) {
  .menuknop { display: inline-flex; align-items: center; justify-content: center;
              width: var(--hoog); height: var(--hoog); flex: none; cursor: pointer;
              border: 1px solid hsl(var(--rand)); border-radius: calc(var(--radius) - 2px);
              background: hsl(var(--kaart)); color: hsl(var(--voorgrond)); }
  .zijkant { position: fixed; top: 0; left: 0; height: 100vh; z-index: 60;
             transform: translateX(-100%); transition: transform .25s ease;
             box-shadow: 0 0 40px hsl(0 0% 0% / .45); }
  body.menu-open .zijkant { transform: translateX(0); }
  body.menu-open .menu-waas { display: block; position: fixed; inset: 0; z-index: 55;
             background: hsl(0 0% 0% / .5); }
  .kop { padding: .85rem 1rem; gap: .6rem; flex-wrap: wrap; }
  .kop h1 { font-size: 20px; }
  .inhoud { padding: 1rem; }
}

/* "Verzend naar schermen": wijzigingen vasthouden tot je klaar bent. Wacht er
   werk, dan valt de balk op; anders blijft hij rustig. */
.uitstuurbalk { border-color: hsl(var(--rand)); }
.uitstuurbalk.wacht { border-color: hsl(var(--accent) / .45);
                      background: hsl(var(--accent) / .04); }
/* Een rij, geen kolom: .kaart > .romp staat standaard op kolom. */
.uitstuurbalk .romp { padding-top: .8rem; padding-bottom: .8rem;
                      flex-direction: row; align-items: center; gap: 1rem;
                      flex-wrap: wrap; }
.uitstuurbalk .romp > form { margin: 0; }
.uitstuurbalk .uitleg { flex: 1 1 14rem; }

/* De kolomkant van een pagina met keuzekolom: dezelfde ruimte tussen de kaarten
   als anders, anders plakt de uitstuurbalk tegen het blok eronder. */
.metkolom > div:last-child { display: flex; flex-direction: column; gap: 1.5rem; }

/* De vaste lijst naast de twee keuzeblokken: even hoog, niet een half veldje. */
.buitenrij { align-items: stretch; }
.buitenrij > .veld { display: flex; flex-direction: column; }
.buitenrij > .veld select { flex: 1; }

/* Kleur kiezen voor een blok in de agenda: vaste kleuren als bolletjes. */
.kleurkeus { display: flex; gap: .5rem; flex-wrap: wrap; }
.kleurkeus input { position: absolute; opacity: 0; pointer-events: none; }
.kleurkeus span { display: block; width: 1.6rem; height: 1.6rem; border-radius: 999px;
                  background: hsl(var(--accent)); cursor: pointer;
                  border: 2px solid hsl(var(--kaart));
                  box-shadow: 0 0 0 1px hsl(var(--rand)); }
.kleurkeus input:checked + span { box-shadow: 0 0 0 2px hsl(var(--voorgrond)); }
.kleurkeus input:focus-visible + span { box-shadow: 0 0 0 3px hsl(var(--ring) / .6); }

/* Wat er buiten de agendablokken speelt: één regel, want het is één keuze. */
.buitenregel { flex-direction: row !important; align-items: center; gap: .75rem;
               flex-wrap: wrap; padding-top: 1rem !important;
               padding-bottom: 1rem !important; }
.buitenregel select { max-width: 16rem; }
.buitenregel .keus { display: inline-flex; align-items: center; gap: .4rem;
                     font-size: 14px; cursor: pointer; }
.buitenregel .keus input { flex: none; }
.buitenregel select.gedempt { color: hsl(var(--gedempte-tekst)); }

/* Een schakelaar: één keuze met twee standen. Het vinkje zelf schuiven we weg
   maar laten we bereikbaar, zodat tabben en de spatiebalk gewoon werken. */
.schakelaar { display: inline-flex; align-items: center; gap: .5rem; cursor: pointer; }
.schakelaar input { position: absolute; opacity: 0; width: 0; height: 0; }
.schakelaar .wip { flex: none; width: 2.45rem; height: 1.4rem; border-radius: 999px;
                   background: hsl(var(--rand)); position: relative;
                   transition: background .15s ease; }
.schakelaar .wip::after { content: ""; position: absolute; top: 2px; left: 2px;
                          width: calc(1.4rem - 4px); height: calc(1.4rem - 4px);
                          border-radius: 999px; background: #fff;
                          box-shadow: 0 1px 2px hsl(0 0% 0% / .25);
                          transition: transform .15s ease; }
.schakelaar input:checked + .wip { background: hsl(var(--accent)); }
.schakelaar input:checked + .wip::after { transform: translateX(1.05rem); }
.schakelaar input:focus-visible + .wip { outline: 2px solid hsl(var(--ring) / .6);
                                         outline-offset: 2px; }
.schakelaar input:disabled + .wip { opacity: .5; }
.schakelaar .wat { min-width: 7rem; }

/* De week die je bekijkt, met pijlen ernaast. Blokken zonder datum horen bij
   elke week; met een datum alleen bij hun eigen weken. */
.weekbalk { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.weekbalk b { font-size: 15px; }
.weekbalk .naardatum { display: inline-flex; align-items: center; gap: .35rem; }
.weekbalk .naardatum input { font-size: 13px; padding: .2rem .4rem; width: auto; }
.agendakop div span.klein { display: block; font-weight: 400; }

/* ------------------------------------------------------------- tags */

/* Vrije woorden bij een scherm. De tint komt uit het woord zelf (tags.py)
   en staat als --tint op het element, dus er is geen klasse per kleur en er
   hoeft nooit iemand een kleur te kiezen.

   Pastel en niet vol: rood en groen betekenen in dit paneel al "stuk" en
   "speelt". Een tag dat om aandacht schreeuwt maakt die twee minder waard. */
.tags { display: flex; flex-wrap: wrap; gap: .25rem; margin: .3rem 0 .1rem; }
.tag {
  font-size: 12px; font-weight: 500; line-height: 1.4;
  padding: .1rem .5rem; border-radius: 999px;
  color: hsl(var(--tint) 45% 32%);
  background: hsl(var(--tint) 70% 93%);
  border: 1px solid hsl(var(--tint) 55% 84%);
}

/* De instellingen: een kolom links, het werk rechts. Het waren acht tabs in
   een rij en dat werd een strook om doorheen te schuiven. In een kolom passen
   ze onder elkaar, met kopjes erboven, en kan er zonder verbouwing een negende
   bij. Iets breder dan de kolom bij de agenda, want hier staan woorden als
   "Installatiestick" in. */
.metkolom:has(> .instelkolom) { grid-template-columns: 16.5rem minmax(0, 1fr); }
/* Op een telefoon moet die kolom wél wijken. Deze regel staat NA de mediaquery
   hierboven en is specifieker (:has telt mee), dus zonder deze herhaling hield
   de instellingenkolom 264 van de 375 pixels en bleef er 63 over voor het werk
   -- gemeten op 24 september 2026, en precies waar John over viel. */
@media (max-width: 62rem) {
  .metkolom:has(> .instelkolom) { grid-template-columns: minmax(0, 1fr); }
}
.instelwerk { display: flex; flex-direction: column; gap: 1.5rem; min-width: 0; }
/* Eén regel per punt, geen tweede regel eronder zoals bij de agenda. */
.instelkolom a { flex-direction: row; align-items: center; }
.instelkolom .kolomkop + a { margin-top: 0; }

/* Iconen in de instellingenkolom: ze maken de kolom scanbaar zonder te lezen.
   Gedempt, want ze zijn een hulpje bij het woord en niet het woord zelf. */
.instelkolom a { gap: .6rem; }
.instelkolom a svg { color: hsl(var(--gedempte-tekst)); }
.instelkolom a.hier svg { color: #fff; }

/* De knoppenrij onder het voorbeeldbeeld. Ze deden allemaal iets anders en
   zagen er allemaal hetzelfde uit; nu zegt de vorm waar je op drukt. */
.opdrachtknoppen { display: flex; flex-wrap: wrap; gap: .5rem; }
.knop.klein svg { width: 14px; height: 14px; }
/* Wat het beeld even onderbreekt of het kastje raakt: niet hetzelfde als
   "laten zien". */
.knop.stil.ingrijpend { color: hsl(var(--gevaar)); border-color: hsl(var(--gevaar) / .3); }
.knop.stil.ingrijpend:hover { background: hsl(var(--gevaar) / .07); }

/* Schermen als tegels. De schermafdruk staat erop, dus je ziet in één blik wat
   er waar speelt in plaats van het te moeten lezen. De lijst blijft bestaan
   voor wie wil vergelijken op kanaal of speler. */
.schermtegels { display: grid; gap: 1rem;
                grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); }
.schermtegel { overflow: hidden; }
.schermtegel .beeld {
  display: block; aspect-ratio: 16/10; background: #000; position: relative;
  display: grid; place-items: center;
}
.schermtegel .beeld img { width: 100%; height: 100%; object-fit: contain; }
/* Tegel zonder schermafdruk: een rustig, laag vlak met een beeldscherm-icoon in
   plaats van een zwart gat of een verouderde afbeelding. Geen 16:10 meer -- een
   klein icoon in een groot vlak oogt leeg; een compacte band is genoeg. */
.schermtegel .beeld.leeg { aspect-ratio: auto; height: 5.5rem;
                           background: hsl(var(--achtergrond)); color: hsl(var(--gedempte-tekst)); }
/* Nog nooit een afdruk: een zwart vlak met een streepje leest als een kapot
   scherm. Dit zegt wat er aan de hand is. */
.schermtegel .geenbeeld { color: hsl(var(--gedempte-tekst)); font-size: 13px; }
.schermtegel .onder { padding: .75rem .875rem; display: flex; flex-direction: column; gap: .4rem; }
.schermtegel .naam a { font-weight: 600; text-decoration: none; }
.schermtegel .naam a:hover { text-decoration: underline; }

/* Hoe oud de schermafdruk op een tegel is. Klein en in de hoek: het is een
   voorbehoud bij het beeld, niet het beeld zelf. */
.schermtegel .beeld { position: relative; }
.schermtegel .ouderdom {
  position: absolute; right: .4rem; bottom: .4rem;
  background: hsl(0 0% 0% / .6); color: #fff;
  font-size: 12px; padding: .1rem .4rem; border-radius: 999px;
}

/* --------------------------------------------------------- kanalen als tegels
   Een kanaal is twee dingen tegelijk: een VORM (het doek) en wat erop staat.
   De tegel toont ze allebei -- de eerste dia van wat er nu speelt, getekend in
   het vlak van het kanaal zelf. Een strook van 1154x512 ziet er dan ook uit
   als een strook, en een staand vlak van 768x960 als een staand vlak; dat is
   precies het verschil dat je op een lijstregel niet ziet.

   De band eromheen is bij elke tegel even groot. Zonder die vaste band krijgt
   een rij tegels twee hoogtes zodra er een staand kanaal tussen staat, en dat
   is de fout die hulp/paneel-meten.js het vaakst vindt.

   Alles binnenin heeft een EIGEN naam (kanaalbeeld, kanaalnaam, kanaalonder):
   .beeld en .naam bestaan al bij andere tegels, en een generieke naam in een
   component pakt vroeg of laat de regels van een ander component op -- de les
   van 1.89.6. */
.kanaaltegels { display: grid; gap: 1rem;
                grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr)); }
.kanaaltegel { overflow: hidden; }
.kanaaltegel .kanaalbeeld {
  display: grid; place-items: center; height: 8.5rem; padding: .75rem;
  background: hsl(var(--achtergrond)); border-bottom: 1px solid hsl(var(--rand));
}
.kanaaltegel .kanaalonder { padding: .75rem .875rem; display: flex; flex-direction: column; gap: .3rem; }
.kanaaltegel .kanaalnaam a { font-weight: 600; text-decoration: none; color: inherit; }
.kanaaltegel .kanaalnaam a:hover { text-decoration: underline; }

/* Het vlak zelf, in de vorm van het kanaal (--b en --h staan in het sjabloon).
   De breedte is min(alles wat er is, de breedte die bij de bandhoogte hoort),
   en de hoogte volgt uit de verhouding. Dezelfde som als bij "Nu op dit
   scherm" (scherm_nu.html), en om dezelfde reden: met alleen max-width knijpt
   de browser wél de breedte maar niet de hoogte, en dan wordt een strook van
   1152x160 een blok. Gezien op 28 september 2026, vóór het uitrollen. */
.kanaalvlak {
  display: grid; place-items: center; overflow: hidden;
  aspect-ratio: var(--b) / var(--h); background: #000; border-radius: 3px;
  color: hsl(var(--gedempte-tekst));
}
.kanaaltegel .kanaalvlak { width: min(100%, calc(7rem * var(--b) / var(--h))); }
.kanaalvlak img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Dezelfde miniatuur in de lijstweergave, in een bak van vaste maat: zonder
   die maat zou elke regel de hoogte krijgen van de vorm van dat ene kanaal. */
td.kanaalmini { width: 4.5rem; }
td.kanaalmini .minibeeld { display: grid; place-items: center; width: 4.5rem; height: 2.5rem; }
td.kanaalmini .kanaalvlak { width: min(4.5rem, calc(2.5rem * var(--b) / var(--h))); }

/* ------------------------------------------------------- een ontwerp uit Canva
   Staat het ontwerp hier al, dan is de vraag niet "halen of niet" maar "is het
   nog bij". Die ene regel krijgt daarom de accentkleur zodra Canva een nieuwere
   versie heeft; de rest blijft rustig. */
.teverversen { color: hsl(var(--accent)); font-weight: 500; }

/* De ontwerpen van een klant lopen van een staande poster tot een brede
   banner. Zonder een band van vaste hoogte krijgt elke tegel zijn eigen maat
   en staat geen enkele knop op één lijn -- dat was precies wat John op 28
   september zag. De voet wordt naar de onderkant geduwd, dus binnen een rij
   staan alle knoppen gelijk. */
.canvategel { display: flex; flex-direction: column; }
.canvategel > form:first-of-type { display: flex; flex-direction: column; flex: 1; }
.canvategel > form:first-of-type > .romp { flex: 1; }
.canvabeeld {
  display: grid; place-items: center; height: 9rem; overflow: hidden;
  background: hsl(var(--achtergrond)); border-radius: calc(var(--radius) - 2px);
  color: hsl(var(--gedempte-tekst));
}
/* contain en geen cover: je kiest hier op wat je ziet, dus er mag niets af. */
.canvabeeld img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
/* Twee regels en dan afbreken: "Minimal Health Consultant Personal Logo" mag
   de tegel niet een regel hoger maken dan zijn buren. */
/* Een bestandsnaam heeft vaak geen spatie ("Max_vs_100__SI202609160490.jpg") en
   kan dus nergens afbreken; op een telefoon duwde die ene naam de mediatabel 31
   px buiten zijn kaart (gemeten 28 september 2026 op 375 px). Een naam mag
   overal breken -- het is geen commando dat je moet kunnen kopiëren. */
.bestandsnaam { overflow-wrap: anywhere; }

.canvanaam {
  margin-top: .6rem; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Een knop met alleen een icoon: even hoog als de knop ernaast, maar zo smal
   dat er twee naast elkaar passen in de voet van een tegel. Alleen voor een
   handeling die zichzelf uitlegt in de vraag die erop volgt; wat hij doet
   staat in title en aria-label. */
/* Een knop met alleen een icoon is overal even breed als hoog. Hij stond
   alleen onder een kaartvoet, en dat is geen eigenschap van die plek maar van
   de knop -- John, 4 oktober 2026, over het kruisje om een afbeelding weg te
   halen: "mag ook kruis zijn met pastel achtergrond net zoals overal, en dan
   komen we weer op het stijlblad." Een regel die "overal" heet hoort niet
   achter één selector te zitten. */
.knop.alleenicoon {
  padding: 0; width: var(--hoog); min-width: var(--hoog); flex: none;
}
.knop.alleenicoon.klein, .kaart > footer .knop.alleenicoon,
.kaart > form > footer .knop.alleenicoon {
  width: var(--hoog-klein); min-width: var(--hoog-klein);
}

/* Herstelcodes en de QR-code op de accountpagina (tweestapsverificatie). */
pre.codes { font-size: 17px; line-height: 1.7; letter-spacing: .04em; margin: 0;
  padding: .75rem 1rem; background: var(--vlak, #f4f4f5); border-radius: .5rem;
  user-select: all; }
img.qr { background: #fff; border-radius: .5rem; padding: .5rem; width: 200px; height: 200px; }

/* Een pictogram vóór een woord, op de lijn: bij Downloaden (server, Android,
   pc, Pi) zodat je in één blik ziet welke regel welke speler is. */
.metpictogram { display: inline-flex; align-items: center; gap: .5rem; }
.metpictogram svg { flex: none; }

/* De helppagina: de keten als vijf stappen naast elkaar, en de vragen als
   uitklapregels. Simpel, want dit is de pagina die je leest als je vastzit. */
.keten { list-style: none; margin: 0; padding: 0; display: grid;
         grid-template-columns: repeat(5, minmax(0, 1fr)); gap: .75rem; counter-reset: stap; }
.keten li { position: relative; padding: 1rem; border: 1px solid hsl(var(--rand));
            border-radius: var(--radius); background: hsl(var(--gedempt) / .35);
            display: flex; flex-direction: column; gap: .5rem; font-size: 13px;
            color: hsl(var(--gedempte-tekst)); }
.keten li::before { counter-increment: stap; content: counter(stap); position: absolute;
                    top: .6rem; right: .7rem; font-size: 12px; font-weight: 600;
                    color: hsl(var(--gedempte-tekst)); }
.keten li a { display: inline-flex; align-items: center; gap: .5rem; color: hsl(var(--voorgrond));
              text-decoration: none; font-size: 15px; }
.keten li a svg { color: hsl(var(--accent)); }
.keten li + li::after { content: "\2192"; position: absolute; left: -.85rem; top: 1rem;
                        color: hsl(var(--gedempte-tekst)); font-size: 14px; }
@media (max-width: 900px) { .keten { grid-template-columns: 1fr; } .keten li + li::after { content: none; } }
.vragen details { border-top: 1px solid hsl(var(--rand)); padding: .6rem 0; }
.vragen details:first-child { border-top: 0; }
.vragen summary { cursor: pointer; font-weight: 500; font-size: 14px; }
.vragen details p { margin: .5rem 0 0 1.1rem; font-size: 14px; color: hsl(var(--gedempte-tekst)); line-height: 1.5; }
.vragen details p b, .vragen details p a { color: hsl(var(--voorgrond)); }
/* Help, de onderdelen: dezelfde uitklapregels als de vragen, met het icoon van
   het menu ervoor, in één woord waar het voor is, en de handelingen als lijst. */
.onderdelen summary { display: flex; align-items: center; gap: .55rem; font-size: 15px; list-style: none; }
.onderdelen summary::-webkit-details-marker { display: none; }
.onderdelen summary svg { color: hsl(var(--accent)); flex: none; }
.onderdelen summary span { font-weight: 400; font-size: 13px; color: hsl(var(--gedempte-tekst)); }
.onderdelen summary::after { content: "+"; margin-left: auto; color: hsl(var(--gedempte-tekst)); font-weight: 400; }
.onderdelen details[open] summary::after { content: "\2212"; }
.onderdelen details ul { margin: .65rem 0 .35rem 1.7rem; padding: 0; display: grid; gap: .45rem;
  font-size: 14px; line-height: 1.5; color: hsl(var(--gedempte-tekst)); max-width: 62rem; }
.onderdelen details li b, .onderdelen details li a { color: hsl(var(--voorgrond)); }

/* De indeling in vakken: de beginstand als rij knopjes, daaronder links een
   compacte tekening op de verhouding van het kanaal en rechts de tabel met
   de vakken in pixels. Zelfde velden, knoppen en kopjes als de rest. */
.beginstand { display: flex; flex-wrap: wrap; align-items: flex-start; gap: .6rem; margin-bottom: 1.5rem; }
.beginstand > span { width: 100%; }
/* Een beginstand is een plaatje van de verdeling met de naam eronder: het
   hoofdvak in de accentkleur, de bijvakken licht. */
.beginkeus { display: flex; flex-direction: column; align-items: center; gap: .4rem; width: 7rem;
  padding: .55rem .5rem .5rem; border: 1px solid hsl(var(--rand)); border-radius: var(--radius);
  background: hsl(var(--kaart)); color: inherit; font: inherit; font-size: 12px; line-height: 1.25;
  text-align: center; cursor: pointer; }
.beginkeus:hover { border-color: hsl(var(--accent) / .6); background: hsl(var(--accent) / .05); }
.beginkeus:focus-visible { outline: 2px solid hsl(var(--accent)); outline-offset: 2px; }
.beginkeus svg { width: 100%; height: 3.25rem; display: block; }
.beginkeus svg rect { stroke: hsl(var(--kaart)); stroke-width: 2; }
.beginkeus svg rect.hoofd { fill: hsl(var(--accent)); }
.beginkeus svg rect.bij { fill: hsl(var(--accent) / .28); }
/* De tekening groot bovenaan, de velden eronder: naast elkaar bleef de
   tekening een postzegel (John, 18 september 2026). */
.indeling { display: flex; flex-direction: column; gap: 1.5rem; }
.indeling .tekening { display: flex; flex-direction: column; gap: .5rem; align-items: flex-start; max-width: 46rem; }
.indeling .tekening svg { width: 100%; max-height: 26rem; height: auto; display: block;
                          border-radius: calc(var(--radius) - 2px); border: 1px solid hsl(var(--rand));
                          background: #0b0a10; }
.indeling .tekening svg text { pointer-events: none; user-select: none; }
table.vakken tr.vast td { background: hsl(var(--accent) / .08); }
.vakkenblok { min-width: 0; }
/* width: auto: over de hele kaart uitgerekt stonden x, y en de maat een
   handbreedte uit elkaar (John, 18 september 2026). */
table.vakken { font-size: 14px; width: auto; }
table.vakken th { padding: .35rem .75rem .6rem 0; }
table.vakken td { padding: .35rem .75rem .35rem 0; border-bottom: 1px solid hsl(var(--rand)); white-space: nowrap; }
table.vakken th:last-child, table.vakken td:last-child { padding-right: 0; }
table.vakken tr:last-child td { border-bottom: 0; }
table.vakken input, table.vakken select { height: var(--hoog-klein); padding: 0 .55rem; font-size: 14px; }
table.vakken input.naam { width: 9rem; }
table.vakken .paar { display: flex; gap: .35rem; align-items: center; flex-wrap: nowrap; }
table.vakken .paar input { width: 4.75rem; }
table.vakken select { width: 20rem; max-width: 100%; text-overflow: ellipsis; padding-right: 2rem; }
/* Geluid en weghalen: knoppen van dezelfde maat als de velden, met een icoon. */
.geluidkeus { display: inline-flex; cursor: pointer; }
.geluidkeus input { position: absolute; opacity: 0; width: 0; height: 0; }
/* var(--hoog-klein) en geen eigen 2,25rem: deze knopjes staan in dezelfde rij
   als de velden ernaast, en die zijn ook --hoog-klein. Met 2,25rem stond er
   36 px naast 34 (audit 5 oktober 2026, F11). Drie hoogtes, en geen vierde. */
.geluidkeus span, .vakweg { display: inline-grid; place-items: center;
                            width: var(--hoog-klein); height: var(--hoog-klein);
  border: 1px solid hsl(var(--rand)); border-radius: var(--radius); background: hsl(var(--kaart));
  color: hsl(var(--gedempte-tekst)); cursor: pointer; padding: 0; }
.geluidkeus span:hover { border-color: hsl(var(--accent) / .6); }
.geluidkeus input:checked + span { background: hsl(var(--accent)); border-color: hsl(var(--accent)); color: hsl(var(--accent-tekst)); }
.geluidkeus input:focus-visible + span, .vakweg:focus-visible { outline: 2px solid hsl(var(--accent)); outline-offset: 2px; }
.geluidkeus input:disabled + span { opacity: .5; cursor: default; }
.vakweg:hover { border-color: hsl(var(--gevaar) / .5); background: hsl(var(--gevaar) / .08); color: hsl(var(--gevaar)); }
.vakkenvoet { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem; margin-top: .75rem; }


/* De knoppen bij een scherm: één TEGEL per opdracht.
   John, 28 september 2026, met een uitsnede van Help erbij: "kunnen we de
   knoppen bij schermen meer in de stijl van help maken... maar per tegel een
   lijn eromheen." Dus dezelfde vorm als de tegels van "Zo komt iets op een
   scherm": icoon in de accentkleur, naam ernaast, uitleg eronder, een lijn
   rondom.

   Wat hiervoor stond was een raster van knopjes met de uitleg in een tweede
   kolom. Dat was een kadertje in een kadertje -- precies waar hij de hele
   week vanaf wilde -- en de uitleg werd op deze kaart vier regels hoog.

   De hele tegel IS de knop. Een knopje in een tegel zou het kadertje
   terugbrengen; en alles wat iets kost heeft een bevestigingsvraag, dus een
   misklik is niet erger dan een vraag wegklikken. */
.kaart > footer.opdrachtlijst { display: block; }
.opdrachtgroep { margin-top: 1.1rem; }
.opdrachtgroep:first-of-type { margin-top: 0; }
.opdrachtgroep h4 {
  margin: 0 0 .5rem; font-size: 12px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .05em; color: hsl(var(--gedempte-tekst));
}
/* auto-fit meet de breedte van het RASTER, dus van deze kaart -- en die staat
   naast het voorbeeldbeeld en is op een breed venster juist smal. Daarom geen
   vensterquery: past er twee naast elkaar, dan twee; anders één. */
/* min(100%, 16rem) en niet 16rem: zonder die min kan een spoor niet onder
   zijn minimum krimpen, en dan steekt een tegel 43 px buiten de kaart zodra
   de kolom smaller is dan 16 rem -- gemeten op 900 en 1200 px. Dezelfde val
   als bij .feitgroepen. */
.opdrachttegels { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
                  gap: .625rem; }
.opdrachttegels form { display: contents; }
.opdrachttegel {
  display: block; width: 100%; text-align: left; box-sizing: border-box;
  padding: .75rem .875rem; font: inherit; cursor: pointer;
  border: 1px solid hsl(var(--rand)); border-radius: var(--radius);
  background: hsl(var(--kaart)); color: hsl(var(--voorgrond));
  transition: border-color .12s, background .12s;
}
.opdrachttegel:hover { border-color: hsl(var(--accent) / .55); background: hsl(var(--accent) / .05); }
.opdrachttegel:focus-visible { outline: 2px solid hsl(var(--accent)); outline-offset: 2px; }
/* tegelkop en niet kop: .kop is de PAGINAKOP -- wit, sticky, met een eigen
   opvulling. Die sloeg hier toe en zette een wit strookje boven in elke tegel
   (John, 28 september 2026). Dezelfde val als input.kleurkeus in 1.87.2: een
   algemene naam binnen een component pakt de opmaak van iets heel anders. */
.opdrachttegel .tegelkop { display: flex; align-items: center; gap: .5rem; font-size: 15px; font-weight: 500; }
.opdrachttegel .tegelkop svg { color: hsl(var(--accent)); flex: none; }
/* Een pijl en niet het plusje van Help: daar betekent het teken "dit klapt
   open", hier "dit gebeurt er als je drukt". */
.opdrachttegel .tegelkop::after { content: "\2192"; margin-left: auto;
  color: hsl(var(--gedempte-tekst)); font-weight: 400; }
/* tegeluitleg en niet uitleg, om dezelfde reden als tegelkop hierboven:
   `.kaart > footer .uitleg` is specifieker dan `.opdrachttegel .uitleg` en zet
   de marge op nul, dus de uitleg plakte tegen de naam. */
.opdrachttegel .tegeluitleg { display: block; margin-top: .3rem; font-size: 13px;
  line-height: 1.45; color: hsl(var(--gedempte-tekst)); }
/* Ingrijpend: alleen de naam en het icoon rood, geen rode rand (John,
   28 september 2026). Een rood kader om drie van de negen tegels maakte het
   blok onrustig; de rode tekst zegt genoeg, en de vraag "weet je het zeker?"
   is de echte grendel. */
.opdrachttegel.ingrijpend .tegelkop { color: hsl(var(--gevaar)); }
.opdrachttegel.ingrijpend .tegelkop svg { color: hsl(var(--gevaar)); }
.opdrachttegel.ingrijpend:hover { border-color: hsl(var(--gevaar) / .5); background: hsl(var(--gevaar) / .04); }
.opdrachtuitslag { display: block; margin-top: .75rem; font-size: 13px; }


/* ---------------------------------------------------------------- telefoon
   John, 24 september 2026: "responsive gaat het nog niet goed op een mobiele
   telefoon". Gemeten op 375 px, en dit kwam eruit:

   - een tabel in een kaart was 844 px breed en werd afgeknipt: de kolommen
     rechts waren niet te bereiken, ook niet met vegen (/schermen, /klanten,
     Instellingen -> Versies);
   - een lange opdracht in <code> stak buiten het scherm (Installatiestick);
   - de instellingenkolom hield 264 van de 375 px (hierboven opgelost).

   Alles hieronder is opmaak en niets anders: geen route, geen sjabloon, geen
   logica. Zo kan het platform er niet van omvallen. ONTWERP.md, punt 8: een
   brede tabel mag over de rand, maar dan in zijn eigen vak met een schuifbalk,
   nooit de pagina zelf. */
@media (max-width: 48rem) {
  /* De tabel wordt zélf het schuifvak (display: block), en niet de romp
     eromheen: op Instellingen -> Rechten zit de tabel in een formulier en niet
     rechtstreeks in de romp, en dan greep een regel op de romp er niet op --
     gemeten op 24 september 2026, de kolommen rechts bleven afgeknipt. Zo
     werkt het ongeacht hoe het sjabloon eromheen is opgebouwd.
     -webkit-overflow-scrolling voor de vaart op iOS. */
  .kaart table {
    display: block; overflow-x: auto; -webkit-overflow-scrolling: touch;
    max-width: 100%; width: max-content; min-width: 100%;
  }
  /* Een tabel met een koprij wordt een rijtje kaartjes: elke rij onder elkaar,
     met het kopje van de kolom vóór de waarde. Zijwaarts vegen loste het niet
     op -- dan lees je één kolom tegelijk zonder te weten waar hij bij hoort, en
     een e-mailadres brak per letter af (John, 24 september 2026).
     De class komt van het script in basis.html; blijft die weg, dan is het
     gewoon de schuifbare tabel hierboven. */
  .kaart table.stapel { display: block; width: 100%; min-width: 0; overflow-x: visible; }
  .kaart table.stapel thead { display: none; }
  .kaart table.stapel tbody, .kaart table.stapel tr, .kaart table.stapel td { display: block; width: auto; }
  .kaart table.stapel tr { padding: .5rem 0; border-bottom: 1px solid hsl(var(--rand)); }
  .kaart table.stapel tr:last-child { border-bottom: 0; }
  .kaart table.stapel td {
    display: grid; grid-template-columns: 7rem minmax(0, 1fr);
    gap: .75rem; align-items: baseline; padding: .25rem 0; border: 0;
  }
  .kaart table.stapel td::before {
    content: attr(data-kop); font-size: 12px; font-weight: 600;
    text-transform: uppercase; letter-spacing: .05em;
    color: hsl(var(--gedempte-tekst));
  }
  /* Een cel zonder kopje (de knop achteraan) krijgt de hele breedte. */
  .kaart table.stapel td[data-kop=""] { grid-template-columns: minmax(0, 1fr); }
  .kaart table.stapel td[data-kop=""]::before { content: none; }
  /* Nooit per letter afbreken: liever een woord dat doorloopt. */
  .kaart table.stapel td { overflow-wrap: break-word; }

  /* Een opdracht om over te typen mag afbreken in plaats van uitsteken. */
  code, .kaart pre { max-width: 100%; overflow-x: auto; overflow-wrap: anywhere; }

  /* De knoppen in de kop mogen op een tweede regel: "Verzend naar schermen"
     viel anders half buiten het scherm. */
  .kopknoppen { margin-left: 0; flex-wrap: wrap; }
  /* De dagkolommen in de agenda krijgen een leesbare breedte; de week schuift
     dan binnen zijn eigen vak in plaats van in elkaar gedrukt te staan. */
  .agendarol { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  /* Dezelfde keus voor de tabstrook van een scherm. Vier gelijke vakken van
     75 px op een telefoon konden APPARAAT, LOGBOEK, GESPEELD en INSTELLINGEN
     niet houden: het woord liep uit zijn vakje en de kaart werd 12 px te breed.
     Nu houdt elke tab zijn eigen breedte en schuift de STROOK, niet de kaart. */
  .tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .tabs a { flex: 0 0 auto; min-width: auto; }
  /* Een stap in "Aan de slag" wordt een blokje in plaats van drie kolommen
     waarvan de middelste vier woorden breed is. */
  .stappenlijst li { flex-wrap: wrap; }
  .stappenlijst .wat { flex: 1 1 100%; }
}


/* ------------------------------------------------ maatvoering voor vingers
   John, 25 september 2026: "buttons te dicht op elkaar, buttons te breed,
   blokken op elkaar zonder ruimtes. Graag geen aannames maar onderbouwing."

   De norm is niet van mij. Apple houdt 44 x 44 pt aan voor elk bedienbaar
   ding, Material 48 x 48 dp, en allebei minstens 8 dp ruimte tussen twee
   dingen die je aanraakt. Gemeten op 390 px vóór deze regels: van de 17
   knoppen op Kanalen waren er 15 lager dan 44 px en stonden 9 paren dichter
   dan 8 px op elkaar; op de afspeellijst overlapten twee teksten elkaar.

   Alles hieronder geldt alleen op een telefoon en is opmaak: de knoppen en de
   velden worden groter en krijgen lucht, en rijen die op een breed scherm
   naast elkaar passen gaan onder elkaar. */
@media (max-width: 48rem) {
  /* 44 px is het minimum; een knop die je vaak gebruikt mag groter. */
  .knop, .knop.klein, .knop.stil { min-height: 44px; }
  .knop.klein { padding: 0 1rem; }
  input, select, textarea { min-height: 44px; }
  /* De lijst/tegel-schakelaar is een link, dus hij viel buiten de regel
     hierboven: op /media stond hij op 42 px naast een keuzelijst van 44.
     Een duim ziet dat verschil niet, het oog wel. */
  .standen a { min-height: 44px; }
  input[type="checkbox"], input[type="radio"] { width: 1.5rem; height: 1.5rem; }
  /* Acht pixel is het minimum tussen twee dingen die je aanraakt; wij houden
     twaalf aan, want een duim is geen muis. */
  .kopknoppen, .kop .rij, .romp .rij, .vakkenvoet { gap: .75rem; }
  .kaart > footer, .kaart > form > footer { gap: .75rem; flex-wrap: wrap; }

  /* De gestapelde tabel: elke rij wordt een LOSSE TEGEL met een rand eromheen
     en ruimte ertussen, net als op een breed scherm (John, 25 september 2026:
     "elk scherm moet op een losse tegel"). En met binnenruimte, want de tekst
     stond tegen de linkerrand van de kaart: een tabel staat vaak rechtstreeks
     in de kaart, zonder de romp die die ruimte normaal geeft. */
  /* Alleen als de tabel rechtstreeks in de kaart staat: zit hij in een romp,
     dan geeft die de ruimte al en zou dit dubbel tellen (gemeten op
     Instellingen -> Rechten: de tabel begon 25 px binnen de kaart). */
  .kaart > table.stapel, .kaart > form > table.stapel { padding: .875rem; }
  .kaart table.stapel tr {
    padding: .875rem 1rem; border: 1px solid hsl(var(--rand));
    border-radius: var(--radius); background: hsl(var(--kaart));
    margin-bottom: .75rem;
  }
  .kaart table.stapel tr:last-child { margin-bottom: 0; }
  .kaart table.stapel td { padding: .3rem 0; grid-template-columns: minmax(0, 6.5rem) minmax(0, 1fr); }
  /* Een lang kopje ("KLANTBEHEERDER") past niet in 6,5 rem en liep over de
     waarde heen. Het mag afbreken; de kolom mag krimpen. */
  .kaart table.stapel td::before { overflow-wrap: anywhere; }
  /* Een cel met een keuzelijst of een veld erin: het kopje erboven en het veld
     over de volle breedte eronder. Naast elkaar hield het veld maar 240 van de
     358 px over (gemeten op Instellingen -> Rechten). */
  .kaart table.stapel td:has(select), .kaart table.stapel td:has(input:not([type="hidden"])) {
    grid-template-columns: minmax(0, 1fr); gap: .25rem;
  }
  .kaart table.stapel td[data-kop=""] {
    display: flex; flex-wrap: wrap; gap: .75rem; margin-top: .75rem;
  }
  .kaart table.stapel td[data-kop=""] .knop { flex: 0 1 auto; }
  .kaart table.stapel td[data-kop=""] form { margin: 0; }

  /* Een dia in een afspeellijst is op een breed scherm één regel: greep,
     voorbeeld, naam, seconden, weergave. Op een telefoon liepen die over
     elkaar heen (gemeten: twee overlappende teksten). Nu twee regels. */
  .dia { flex-wrap: wrap; row-gap: .75rem; padding: 1rem 1.25rem; }
  .dia .midden { flex: 1 1 8rem; }
  .dia .veld.vast { flex: 1 1 7rem; }
  .dia input[type="number"], .dia select { width: 100%; }

  /* De keuzestrook boven een pagina (kanalen, afspeellijsten, mappen) is op
     een telefoon een rij om doorheen te vegen; die knoppen moeten ook 44 px
     hoog zijn en uit elkaar staan. */
  .keuzekolom a { min-height: 44px; }
  .keuzekolom { gap: .5rem; padding-bottom: .5rem; }

  /* De knop waarmee het menu opengaat is het eerste wat je aanraakt. */
  .menuknop { width: 44px; height: 44px; }

  /* Een uitklapregel (Help, de onderdelen, de oudere versies) is ook iets wat
     je aanraakt: gemeten 40 px, dus net te laag. */
  summary { min-height: 44px; display: flex; align-items: center; }

  /* De knoppen in de kop kregen een eigen regel, maar bleven op één rij staan
     en staken 24 px buiten het scherm (gemeten op 390 px: de pagina zelf was
     414 breed). flex:none hield ze tegen.
     Ze zijn ook allemaal even breed: "Verzend naar schermen" was smaller dan
     "Agendablok toevoegen" en dat staat slordig onder elkaar. */
  .kopknoppen { flex: 1 1 100%; min-width: 0; flex-direction: column; align-items: stretch; }
  .kopknoppen .knop, .kopknoppen form { width: 100%; }
  .kopknoppen .knop { justify-content: center; }

  /* De week in de agenda is zeven kolommen; op 390 px is dat 48 px per dag en
     dan valt "08:00" over de rand van zijn blok heen (gemeten: acht
     overlappende teksten). Met een leesbare minimumbreedte schuift de week
     binnen zijn eigen vak, zoals een tabel. */
  .agendakop, .agendalijf { grid-template-columns: 3rem repeat(7, minmax(5.5rem, 1fr)); }
  .agendarol { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .agendakop div { padding: .6rem .25rem; font-size: 13px; }
}

/* De keuzelijst met mappen naast "Aangevinkt verplaatsen naar". Stond op een
   vaste 12rem en paste daarmee op een telefoon niet naast de tekst; dat was
   het zijwaarts schuiven op Media (John, 25 september 2026). */
.mapkeuze { width: 12rem; }
/* Het filter op soort houdt zijn eigen breedte op een breed scherm; de maat
   stond als inline stijl in het sjabloon en won daarmee van elke regel
   hieronder (ONTWERP.md: geen maat in een sjabloon). */
/* Drie velden met een eigen maat. Die stond als inline stijl in het sjabloon
   en won daarmee van elke regel voor de telefoon; nu staat hij hier, zodat de
   telefoonregel hem kan overrulen (ONTWERP.md, punt 1). */
.rolkeuze { width: 11rem; }
/* De keuzelijst midden in een zin. De opvulling RECHTS moet blijven staan:
   select tekent zijn pijl op "right 1rem" en een smallere opvulling zet die
   pijl dwars door de tekst heen. John, 4 oktober 2026: "pijl door de tekst" --
   bij "een gewoon scherm (16:9)" stond de pijl op de 9. */
.maatkeus { display: inline; width: auto; padding: .1rem 1.6rem .1rem .5rem; }
/* LET OP: input.kleurkeus en niet .kleurkeus. Twee dingen dragen die naam --
   het kleurvakje op de schermpagina (een input) en de rij kleurbolletjes in
   de agenda (een div). Toen deze maat hier kwam te staan werd die rij 72 px
   breed en vielen de bolletjes in twee kolommen (John, 26 september 2026:
   "kleuren staan verticaal"). Een class die twee dingen betekent is een val;
   een selector op het soort element houdt ze uit elkaar. */
input.kleurkeus { width: 4.5rem; padding: .2rem; }
@media (max-width: 48rem) {
  /* De balk op Media wordt een kolom: elk kopje boven zijn eigen keuzelijst,
     en elke keuzelijst even breed. Vouwen alleen was niet genoeg -- de ene
     lijst werd 345 px en de andere 275, en dat lijnt niet (John, 25 september
     2026: "deze mappen en pulldowns lijnen niet, maak ze anders even breed of
     naast elkaar"). */
  .balkje, .balkje > span {
    display: flex; flex-direction: column; align-items: stretch;
    width: 100%; row-gap: .5rem;
  }
  .balkje select, .balkje .knop { width: 100%; }
  .mapkeuze { width: 100%; flex: none; min-width: 0; }
  /* Alleen de knopjes lijst/tegels blijven naast elkaar: dat is één keuze. */
  .balkje .standen { flex-direction: row; align-self: flex-start; width: auto; }
}


/* Op een breed scherm bestaat de groep niet: de velden staan gewoon in de rij. */
.diaknoppen { display: contents; }

/* ------------------------------------------------- alles gelijkgetrokken (telefoon)
   John, 25 september 2026: "maak alle knoppen als ze alleen staan net zo breed
   als het scherm, dit geldt ook voor de pulldowns (...) probeer aub alles
   gelijk te trekken."

   Eén regel voor het hele paneel: op een telefoon vult een keuzelijst of een
   veld de breedte, en een knop die alleen staat ook. Twee knoppen naast elkaar
   delen de breedte. Zo staat overal hetzelfde, in plaats van per pagina iets
   anders. */
@media (max-width: 48rem) {
  select, input[type="text"], input[type="email"], input[type="password"],
  input[type="number"], input[type="date"], input[type="time"], input[type="search"],
  input[type="url"], textarea { width: 100%; }
  /* Een veld met een eigen maat (de duur van een dia) houdt die niet vast. */
  .veld.vast, .veld { width: auto; }

  /* Een knop die als enige in een formulier of rij staat, vult de breedte. */
  form > .knop:only-child, .romp > .knop:only-child,
  .kaart > footer > form:only-child > .knop:only-child { width: 100%; }

  /* De prullenbak is een knop waar je met je duim op mikt. */
  .knop.prullenbak { min-width: 44px; padding: 0 .75rem; }
  .knop.prullenbak svg { width: 20px; height: 20px; }

  /* De dia: naam op de eerste regel over de volle breedte, daaronder
     seconden en weergave naast elkaar met de prullenbak erachter. De naam
     liep eerst onder "Seconden" door. */
  .dia { align-items: start; }
  .dia .midden { flex: 1 1 8rem; }
  .diaknoppen {
    display: flex; flex: 1 1 100%; gap: .75rem; align-items: flex-end;
  }
  .diaknoppen .veld { flex: 1 1 6rem; }
  .diaknoppen .knop.prullenbak { flex: none; }

  /* De weekpijlen van de agenda: de ene links, de andere rechts, met het
     weeknummer ertussen. De datums en de rest zakken naar een eigen regel --
     anders past de tweede pijl er niet meer bij en gaat hij naar beneden
     (gemeten: de pijlen stonden 56 px uit elkaar in hoogte). */
  .weekbalk { flex-wrap: wrap; gap: .75rem; align-items: center; }
  .weekbalk > a.knop:nth-of-type(1) { order: 1; }
  .weekbalk > b { order: 2; flex: 1 1 auto; text-align: center; }
  .weekbalk > a.knop:nth-of-type(2) { order: 3; }
  .weekbalk > span, .weekbalk > a.knop:nth-of-type(3) { order: 4; flex: 1 1 100%; margin: 0; }
  .weekbalk .naardatum { order: 5; flex: 1 1 100%; }

  /* Een voorbeeldje in een lijst mag groter: op een telefoon is 5 rem te klein
     om te zien wat het is. */
  .dia .voor, .kaart table.stapel img, .kaart table.stapel .voor { width: 7rem; }
}

/* ------------------------------------------------------------------ vakken
   John, 26 september 2026: "kun je alles in een aparte box zetten met een
   border-radius net zoals bij het hoofdscherm, en dan ook de buttons in de
   box, wel op die grijze achtergrond. Dit dan overal toepassen!"

   Een lange kaart met haarlijnen ertussen leest als één brok: je ziet niet
   welke knop bij welk stuk hoort, en de knoppenstrook loopt van rand tot rand
   alsof hij bij de hele pagina hoort.

   De eerste opzet zette de ruimte als marge OP de vakken. Dat ging mis bij
   alles wat geen .romp of footer is -- een kopje, een melding, een tabstrook --
   want dat kreeg niets en plakte tegen de buren. John zag het op drie plekken
   tegelijk en vroeg terecht "waarom kan dat niet allemaal in één keer?".
   Daarom nu de ruimte van de OUDER: één kolom met een gap, dus elk kind krijgt
   hem, ook een kind dat er later bij komt. */
.kaart.invakken {
  display: flex; flex-direction: column; gap: 1rem; padding: 1.25rem;
}
.kaart.invakken > form { display: flex; flex-direction: column; gap: 1rem; }
.kaart.invakken > .romp, .kaart.invakken > form > .romp,
.kaart.invakken > footer, .kaart.invakken > form > footer {
  border: 1px solid hsl(var(--rand)); border-radius: var(--radius); margin: 0;
}
.kaart.invakken > .romp, .kaart.invakken > form > .romp {
  padding: 1.25rem; background: hsl(var(--kaart));
}
/* De haarlijn die stukken scheidde is nu de rand van het vak zelf. */
.kaart.invakken .scheiding { border-top: 0; }
.kaart.invakken > .romp.scheiding, .kaart.invakken > form > .romp.scheiding { padding-top: 1.25rem; }
/* De voet staat VRIJ in de kaart, als eigen vak met ronde hoeken -- niet
   vastgeplakt aan het stuk erboven. In 1.87.2 zat hij er nog aan vast ("samen
   één kader"); John koos op 27 september 2026 de andere vorm, die op de
   afspeellijstpagina toevallig al zo stond: "deze staat vrij in het witte
   kader, dit vind ik mooi". De ruimte komt van de gap van de ouder, dus hier
   staat alleen de opvulling. */
.kaart.invakken > footer, .kaart.invakken > form > footer {
  padding: .875rem 1.25rem;
}
/* Een tabstrook of kop hoort bij de hele kaart en loopt dus van rand tot rand. */
.kaart.invakken > nav.tabs, .kaart.invakken > header:first-child {
  margin: -1.25rem -1.25rem 0;
}
/* Een kop verderop in de kaart is een tussenkop en hoort gewoon in de kolom. */
.kaart.invakken > header:not(:first-child) { padding: 0; }
.kaart.invakken > nav.tabs { padding-left: 1.25rem; padding-right: 1.25rem; }

/* Een stuk dat zelf al uit vakjes bestaat (de tegels op tab Apparaat) krijgt
   geen kader eromheen: dan zit er een lijn te veel omheen. John, 26 september
   2026: "apparaat zit een kader te veel in, moet hetzelfde zijn als bij
   instellingen". */
.kaart.invakken > .romp.geenvak, .kaart.invakken > form > .romp.geenvak {
  border: 0; border-radius: 0; margin: 0; padding: 0; background: none;
}
/* Een formulier in een rij stapelt zijn veld en zijn knop op elkaar, zonder
   ruimte ertussen: de knop plakte tegen het invoervak en tegen de onderrand van
   het vak (John, 26 september 2026: "buttons staan tegen de rand"). Eén gap
   hier zet ze overal los, en zet meteen de knoppen van twee formulieren naast
   elkaar op dezelfde hoogte. */
.rij > form { display: flex; flex-direction: column; gap: .625rem; align-items: flex-start; }
.rij > form > .knop { flex: none; }

/* Een melding in een kaart stond met een inline marge zonder onderkant, dus hij
   plakte tegen wat eronder kwam (John, 26 september 2026: "groene balk zit
   tegen onderkant aan"). Eén regel, aan alle kanten. */
.kaart > .melding, .kaart > form > .melding { margin: 1.25rem 1.5rem; }
.kaart.invakken > .melding, .kaart.invakken > form > .melding { margin: 0; }

/* In één rij één hoogte. Los van elkaar kloppen een knop van 2,1 rem en een
   keuzelijst van 2,6 allebei, naast elkaar nooit.

   Deze regel is op 26 september 2026 één keer verdwenen doordat ik er een blok
   overheen herschreef, en dat viel pas op bij het nameten (hulp/paneel-meten.js).
   Daarom staat hij nu ook in test_ontwerp.py: verdwijnt hij, dan valt de ronde om
   in plaats van dat John het op een schermafdruk ziet. */
.balkje .knop, .balkje select, .balkje .standen a,
.balkje input:not([type="checkbox"]):not([type="radio"]):not([type="color"]),
.rij .knop, .rij select,
.rij input:not([type="checkbox"]):not([type="radio"]):not([type="color"]) {
  height: var(--hoog);
}

/* Een kleurveld is ook een bedieningsvak. De regel hierboven slaat hem over
   omdat hij geen tekst draagt en dus niet mee hoort te rekken -- maar zijn
   HOOGTE hoort wel bij de rij te passen, en de browser geeft hem uit zichzelf
   een eigen maat. John, 4 oktober 2026: "vlak niet even groot". Dat was dit:
   naast een knop van 44 px stond een kleurvakje van 23 px.

   Hij staat hier en niet in een sjabloon of een plugin, want het paneel
   gebruikt hem op drie plekken (scherm, app, ontwerper) en drie kopieën van
   dezelfde maat lopen uit elkaar. */
input[type="color"] {
  flex: none; width: 3.25rem; height: var(--hoog); padding: .25rem;
  border: 1px solid hsl(var(--rand)); border-radius: calc(var(--radius) - 2px);
  background: hsl(var(--kaart)); cursor: pointer;
}
.rij input[type="color"], .balkje input[type="color"] { height: var(--hoog); }
input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
input[type="color"]::-webkit-color-swatch { border: 1px solid hsl(var(--rand) / .7); border-radius: 3px; }
input[type="color"]::-moz-color-swatch { border: 1px solid hsl(var(--rand) / .7); border-radius: 3px; }

/* Een lange opdracht schuift in zijn EIGEN vak, nooit de pagina (ONTWERP.md
   punt 10). Op de stickpagina duwde één curl-regel van 750 px de hele kaart
   203 px uit zijn vel. */
code { max-width: 100%; overflow-x: auto; vertical-align: bottom; }
code.klein, .romp > code, li > code { display: inline-block; }

/* Een knop met een lange naam mag afbreken in plaats van zijn kolom uit te
   duwen: op de schermpagina stak "Meetbeeld tonen" 87 px buiten de kaart. */
.opdrachtraster .knop { white-space: normal; max-width: 100%; height: auto; min-height: var(--hoog-klein); }

/* Een brede tabel schuift in zijn EIGEN vak, op elke breedte. Deze regel stond
   alleen in de telefoonquery (onder 48 rem), en daardoor duwde een tabel
   tussen ongeveer 770 en 1100 px zijn kaart uit het vel -- op Schermen 298 px,
   op Klanten 187, op Versies 206. Dat heeft niemand ooit gezien omdat we altijd
   op een breed venster kijken; het nameten (hulp/paneel-meten.js) vond het
   meteen. ONTWERP.md punt 10: de PAGINA schuift nooit zijwaarts, wat te breed
   is schuift in zijn eigen vak.

   Het schuifvak zit om de tabel HEEN en niet OP de tabel: display: block op
   een <table> haalt de tabelopmaak van zijn eigen doos af, en dan krimpen de
   rijen naar hun inhoud terwijl de kaart breed blijft. Op Kanalen bleef zo
   747 van de 1470 px over en stond de halve kaart leeg -- John, 27 september
   2026: "nu de lijstweergaves, die zijn te smal". Met :has() grijpt het
   ongeacht hoe het sjabloon eromheen is opgebouwd; dat was de reden dat het
   op de tabel zelf stond. */
@media (min-width: 48.0625rem) {
  .kaart:has(> table), .kaart *:has(> table) {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
  }
  /* De lijst is een raster en geen tabel; die krijgt zijn eigen schuifvak. */
  .kaart > .lijst { overflow-x: auto; }
}

/* Een cel in een regel mag krimpen. Zonder min-width: 0 houdt een grid-item
   zijn min-content-breedte, en dan duwt de kolom Downloaden ("Download" plus
   "niet gebouwd") de hele lijst 205 px buiten zijn kaart -- zichtbaar tussen
   ongeveer 900 en 1100 px. Gevonden met hulp/paneel-meten.js, 26 september 2026. */
.regel > * { min-width: 0; }
.regel .doen, .regel .gebruik { overflow: hidden; }

/* Een kolom in een raster mag krimpen. Zonder dit neemt hij de breedte van zijn
   INHOUD (min-content) en schuift de rest van de pagina opzij -- dezelfde val
   als bij `1fr` voor een naamkolom, die in ONTWERP.md punt 11 al staat. Op
   Versies duwde de lijst zijn kaart daardoor 206 px uit het vel tussen 900 en
   1100 px. Gevonden met hulp/paneel-meten.js. */
.metkolom > *, .werkblad > * { min-width: 0; }

/* Een regel die LOS in de kaart staat (de strook "wat er te doen is") heeft
   dezelfde vaste kolommen als de lijst, maar niet de schuifbak van die lijst.
   In een smalle kolom -- Versies naast de instellingenkolom is 292 px --
   duwde hij de kaart 206 px uit zijn vel. Hij schuift nu zelf. */
.kaart > .regel { overflow-x: auto; }

/* Een vak waarvan de INHOUD zijn eigen opvulling al meebrengt: een lijst met
   rijen. Wel een kader, geen dubbele rand van binnen. De ronding moet klippen,
   anders steekt de eerste rij door de hoek heen. */
.kaart.invakken > .romp.vullend, .kaart.invakken > form > .romp.vullend {
  padding: 0; overflow: hidden;
}

/* De voet staat links de uitleg en rechts de knop. Was hij alleen een knop,
   dan bleef die uitleg weg; met space-between valt de knop vanzelf rechts en
   een losse knop ook. John, 26 september 2026: "overal waar de knop opslaan
   staat moet net zoals deze worden, ook bij instellingen." */
.kaart > footer, .kaart > form > footer { justify-content: space-between; gap: 1rem; }
.kaart > footer > .knop:only-child, .kaart > form > footer > .knop:only-child,
.kaart > footer > form:only-child, .kaart > form > footer > form:only-child { margin-left: auto; }
.kaart > footer .uitleg, .kaart > form > footer .uitleg {
  font-size: 13px; color: hsl(var(--gedempte-tekst)); margin: 0;
}
/* Twee knoppen in één voet horen naast elkaar aan de rechterkant. Zonder deze
   groep verdeelt space-between drie kinderen over de hele breedte en staat de
   eerste knop midden in de voet, los van de tweede (John, 28 september 2026,
   Instellingen -> Canva). */
.kaart > footer .voetknoppen, .kaart > form > footer .voetknoppen {
  display: flex; gap: .5rem; align-items: center; flex-wrap: wrap;
  justify-content: flex-end;
}

/* Een knop met een lange naam in een voet mag afbreken in plaats van zijn kaart
   uit te duwen: "Overal afmelden, behalve hier" is 280 px en stak op een smal
   venster 13 px buiten de kaart. De hoogte blijft de token-hoogte zolang het op
   één regel past. */
.kaart > footer .knop, .kaart > form > footer .knop {
  max-width: 100%; white-space: normal; height: auto;
  min-height: var(--hoog); padding-top: .4rem; padding-bottom: .4rem;
}


/* --------------------------------------------- een afbeelding groot bekijken

   John, 27 september 2026: "bij media moet je op een afbeelding kunnen drukken
   en dat hij dan groot wordt." Het venster is zo groot als het beeld toelaat en
   nooit groter dan het scherm; de achtergrond is donker, zodat je ziet waar het
   beeld ophoudt -- bij een ontwerp met een witte rand is dat het halve punt. */
dialog.grootbeeld {
  /* fit-content en niet auto: een dialog met width:auto wordt zo breed als de
     browser hem gunt, en dan zweeft een liggend beeld in een veel te breed
     kader. Met fit-content sluit het kader om het beeld. */
  max-width: min(96vw, 1600px); max-height: 92vh; width: fit-content;
  padding: .75rem; border: 0; border-radius: var(--radius);
  background: hsl(var(--kaart)); color: hsl(var(--voorgrond));
  box-shadow: 0 24px 60px hsl(0 0% 0% / .35);
}
dialog.grootbeeld::backdrop { background: hsl(0 0% 0% / .6); }
dialog.grootbeeld img {
  display: block; max-width: 100%; max-height: calc(92vh - 4rem);
  margin: 0 auto; border-radius: calc(var(--radius) - 4px);
  background: repeating-conic-gradient(hsl(var(--gedempt)) 0% 25%, transparent 0% 50%) 0 0 / 18px 18px;
}
dialog.grootbeeld #grootbeeldnaam { margin-top: .5rem; text-align: center; }
.sluitkruis { position: absolute; top: .4rem; right: .4rem; line-height: 1;
              padding: 0 .5rem; font-size: 20px; }
/* Een miniatuur die je kunt aanklikken hoort dat te laten zien. */
img[data-groot] { cursor: zoom-in; }

/* ------------------------------------------- de recepten op de stickpagina

   John, 2 oktober 2026: "maak er een mooie tegel van met een icon, dus
   BrightSign apart en Android apart". Zes recepten onder elkaar was een pagina
   om doorheen te scrollen; dit is één blik. De tegel is een knop, geen link:
   hij opent een venster en gaat nergens heen. */

.receptegels { display: grid; gap: .75rem;
               grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }

.receptegel {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .15rem .85rem;
  align-items: start; text-align: left; cursor: pointer;
  padding: .9rem 1rem; background: hsl(var(--kaart)); color: inherit;
  border: 1px solid hsl(var(--rand)); border-radius: var(--radius);
  font: inherit; min-height: 44px;
}
.receptegel:hover { background: hsl(var(--gedempt) / .6); }
.receptegel:focus-visible { outline: 2px solid hsl(var(--accent)); outline-offset: 2px; }
.receptegel .beeldje { grid-row: 1 / span 2; display: grid; place-items: center;
                       width: 2.5rem; height: 2.5rem; border-radius: var(--radius);
                       background: hsl(var(--gedempt)); }
.receptegel .naam { font-weight: 600; }
.receptegel .wat { font-size: 13px; color: hsl(var(--gedempte-tekst)); }

/* Het venster erachter leest als een korte handleiding, dus iets meer ruimte
   dan een formuliervenster. */
dialog.recept { max-width: 44rem; }
dialog.recept .romp ol, dialog.recept .romp ul { padding-left: 1.2rem; line-height: 1.9; }

/* -------------------------------------------------- de regels van een menukaart

   John, 3 oktober 2026: "een app om menukaarten te maken". Eén rij per
   gerecht, net als in de kaart die je overtikt. Smalle velden voor prijs en
   categorie, brede voor naam en omschrijving -- anders typ je een omschrijving
   in een vakje van drie centimeter. */

table.menuregels { width: 100%; border-collapse: collapse; }
table.menuregels th { text-align: left; font-size: 12px; text-transform: uppercase;
                      letter-spacing: .04em; font-weight: 500;
                      color: hsl(var(--gedempte-tekst)); padding: .35rem .4rem; }
table.menuregels td { padding: .25rem .4rem; vertical-align: middle; }
table.menuregels input[type="text"], table.menuregels select { width: 100%; }
/* Een ondergrens per kolom, en een ondergrens voor de hele tabel. Zonder dat
   perst de browser acht kolommen in de beschikbare breedte en staat er "4." in
   een prijsveld en "BRO" in een categorie -- gemeten op 3 oktober 2026 op een
   venster van 1600 px. Past het niet, dan hoort .rolbaar te schuiven; dat is
   het verschil tussen "te smal" en "onleesbaar". */
table.menuregels { min-width: 54rem; }
table.menuregels td:nth-child(2) { min-width: 11rem; }
table.menuregels td:nth-child(3) { min-width: 15rem; }
table.menuregels td:nth-child(4) { min-width: 5rem; }
table.menuregels td:nth-child(5) { min-width: 8rem; }
table.menuregels td:nth-child(6) { min-width: 8rem; }
table.menuregels td.midden { text-align: center; }
table.menuregels td.pak { cursor: grab; color: hsl(var(--gedempte-tekst)); user-select: none;
                          width: 1.5rem; text-align: center; }
table.menuregels tr.sleept { opacity: .5; }


/* De keuze "begin met" hoort alleen bij een menukaart, en dat regelen we met
   CSS en niet met javascript. John, 3 oktober 2026: "ik zie de Menukaart
   Lunchroom nergens staan" -- de apps-pagina laadt namelijk helemaal geen
   script, dus het blok bleef verborgen en je kreeg een lege kaart terwijl je
   dacht dat je Lunchroom had gekozen. Een regel die van javascript afhangt op
   een pagina zonder javascript is geen regel. */
#kaartkeus { display: none; }
.tweekeus:has(input[value="menukaart"]:checked) + #kaartkeus { display: block; }

/* Welke apps een klant mag maken (1.90.69). Een lijst met een vinkje, de naam
   en waar de app voor is: zonder die uitleg moet je tien namen uit je hoofd
   kennen om te kunnen kiezen. */
dialog.appsvenster .romp { max-width: 34rem; }
.appskeus { display: grid; gap: .55rem; margin-top: .75rem; }
.appskeus .vinkje { align-items: flex-start; gap: .55rem; }
.appskeus .vinkje span { display: block; line-height: 1.35; }
.appskeus .vinkje small { display: block; color: hsl(var(--gedempte-tekst)); font-size: 12px; }
.appskeus .vinkje em { font-style: normal; font-size: 12px; }

/* Wat er bij het weerbericht staat: vijf vinkjes naast elkaar als het past,
   eronder als het niet past. Vijf losse schakelaars onder elkaar maakten het
   formulier twee keer zo lang. */
.weerkeus { display: flex; flex-wrap: wrap; gap: .35rem 1.2rem; margin-top: .4rem; }

/* Alle seconden in één keer (1.90.70). Eén regel boven de dia's: veld, knop,
   en ernaast één zin wat hij doet -- dezelfde vorm als elke andere knop in dit
   paneel (ONTWERP.md). */
/* LET OP de selector: `.kaart > form > .romp` zet elke romp op een KOLOM en
   weegt zwaarder dan een losse klasse. Gemeten op 4 oktober 2026: het veld,
   de knop en de uitleg stonden alle drie onder elkaar rechts in beeld. */
.kaart > form > .romp.allesduur, .kaart > .romp.allesduur {
  flex-direction: row; align-items: flex-end; gap: .75rem; flex-wrap: wrap;
  padding-bottom: 1rem; border-bottom: 1px solid hsl(var(--rand)); }
.allesduur .uitleg { flex: 1; min-width: 12rem; padding-bottom: .4rem; }

