:root{
  --bg:#0B0B0C; --panel:#131315; --panel2:#18181B; --row:#1C1C1F; --rowhi:#232327;
  --line:#28282D; --linesoft:#212125;
  /* Rand van iets dat je bedient. Een haarlijn van #28282D haalt 1,3:1 tegen de
     pagina, en dan is de grens die zegt "hier kun je typen" vrijwel onzichtbaar.
     WCAG 1.4.11 vraagt 3:1 voor de omtrek van een bedieningselement; deze haalt
     3,1:1. Alleen op input, select, textarea en .btn — de haarlijnen tussen rijen
     en om kaarten dragen geen informatie en blijven zoals ze waren. */
  --line-ctl:#626267;
  /* --tx3 was #6C6C75 en haalde 3,0 tot 3,8:1: onder de 4,5:1 van WCAG AA, en dit
     is de kleur van elke kolomkop, elk tijdstip en elke legenda. #8A8A93 haalt
     4,6:1 op het lichtste vlak en blijft duidelijk gedempt naast --tx2. */
  --tx:#EFEFF1; --tx2:#A2A2A9; --tx3:#8A8A93;
  --ac:#E8973C; --ac-bg:rgba(232,151,60,.13); --ac-dim:#B2701F;
  --ok:#74BE92; --ok-bg:rgba(116,190,146,.13);
  --wa:#E0A94A; --wa-bg:rgba(224,169,74,.13);
  --er:#D8736B; --er-bg:rgba(216,115,107,.13);
  /* Randkleur voor iets dat weggaat of stuk is: verwijderknop, foutbalk. Stond op
     vier plekken als losse rgba-waarde. */
  --er-line:rgba(216,115,107,.35);
  /* Lichtere tint van dezelfde twee kleuren, voor de naam van een aandachtssoort binnen
     zijn groep. Ze moeten leesbaar zijn als gewone tekst en tegelijk zeggen in welke groep
     je zit, dus zitten ze tussen --tx2 (#A2A2A9) en de volle kleur in: 6,5:1 en 6,9:1 tegen
     het paneel, waar de volle --er 4,9:1 haalt. Een kop is tekst en geen waarschuwing —
     acht koppen in de volle kleur maakte het blok één lap rood. De lijn ernaast is dezelfde
     kleur op 22%, net genoeg om de groep aan te wijzen zonder een streep te trekken. */
  --er-licht:#E8A9A3; --wa-licht:#EBCB92;
  --er-lijn:rgba(216,115,107,.22); --wa-lijn:rgba(224,169,74,.22);
  /* De twee rusttoestanden van het 24-uursstaafje. Stonden zowel hier als in de
     legenda in portaal.js, dus konden ze uit elkaar lopen — en een legenda die de
     verkeerde kleur toont is erger dan geen legenda. --hb-ok haalt 3,0:1 tegen het
     paneel (was 2,6 en dat is te weinig voor iets dat informatie draagt). */
  --hb-ok:#58645D; --hb-none:#26262A;
  --r:7px; --f:'Instrument Sans','DM Sans',system-ui,-apple-system,sans-serif;
  /* Hoogte van de plakkende topbalk. Staat hier omdat twee plekken hem nodig hebben:
     .top zelf en de scrollruimte hieronder. Liepen die uit elkaar, dan is de fix stuk. */
  --top-h:53px;
}
*{box-sizing:border-box}
/*
    Scrollbalken in de stijl van het portaal.

    De standaardbalk van Windows is licht grijs met een witte baan, en die stond in elk
    scrollvlak: de groepskeuze bij uitrol en koppelen, de tabellen, de pop-ups. Op een donker
    paneel is dat het helderste vlak op het scherm — het trekt meer aandacht dan de inhoud
    waar het langs schuift, en het is het laatste stuk Windows dat nog in beeld kwam.

    Portaalbreed en niet per vlak: een scrollbalk is geen onderdeel van één component maar van
    de manier waarop dit portaal eruitziet, en een halve toepassing zou betekenen dat je bij
    het ene lijstje een grijze balk hebt en bij het andere niet.

    Twee schrijfwijzen, want ze dekken verschillende browsers: scrollbar-color is de standaard
    (Firefox, en Chrome 121+), ::-webkit-scrollbar is wat oudere Chrome en Edge begrijpen. De
    duim gebruikt --line-ctl, dezelfde kleur als de rand van een knop of invoerveld: het is
    iets wat je kunt bedienen, en dan hoort het die kleur te hebben.
*/
*{scrollbar-width:thin;scrollbar-color:var(--line-ctl) transparent}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--line-ctl);border-radius:5px;
  border:2px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover{background:#7A7A80;border:2px solid transparent;
  background-clip:content-box}
::-webkit-scrollbar-corner{background:transparent}
/*
    Ruimte bovenaan voor alles wat de browser zelf in beeld schuift.

    Waarom dit nodig is: na een navigatie krijgt #view de focus (portaal.js, zodat Tab
    niet weer bovenaan de zijbalk begint). Chrome legt bij zo'n focuswissel de bovenrand
    van #view gelijk met de bovenrand van het venster — scrollY sprong van 0 naar 53 — en
    daarmee schoof de paginakop onder de plakkende topbalk. Gemeten: h1 op y=22 terwijl
    .top 0 tot 53 beslaat, dus de kop was helemaal weg en je moest een stukje omhoog
    scrollen.

    scroll-padding-top op de scroller lost alle vier de plekken tegelijk op: de focus na
    navigatie, de sprong naar de inhoud, een tabblad dat met de pijltjes focus krijgt, en
    de knop die na het sluiten van een dialoog zijn focus terugkrijgt. preventScroll of
    scroll-margin-top op #view repareren alleen de eerste twee.
*/
html{scroll-padding-top:var(--top-h)}
/* Een eigen display-regel (.kv is een grid) verslaat de standaardregel voor
   [hidden]. Zonder dit blijft een verborgen tabblad staan. */
[hidden]{display:none!important}
html,body{margin:0;padding:0}
body{background:var(--bg);color:var(--tx);font-family:var(--f);font-size:14px;line-height:1.55;-webkit-font-smoothing:antialiased;letter-spacing:-.005em}
h1,h2,h3{margin:0;font-weight:600;letter-spacing:-.02em}
h1{font-size:23px}h2{font-size:18px}h3{font-size:14.5px}
a{color:var(--ac);text-decoration:none}a:hover{text-decoration:underline}
.num{font-variant-numeric:tabular-nums;letter-spacing:0}

/* Wachtscherm tot /auth/me antwoord heeft gegeven; zie #boot in index.html. */
#boot{min-height:100vh;display:grid;place-items:center;color:var(--tx3);font-size:13.5px}
#boot.uit{display:none}
/* Standaard uit: pas aan als vaststaat dat er geen sessie is. */
#login{min-height:100vh;display:none;grid-template-columns:1fr 1fr}
#login.on{display:grid}
/* Het merkpaneel stond met alles bovenaan en een lege onderhelft. De inhoud staat nu
   op ooghoogte; alleen de voetregel blijft onderaan hangen. */
.brand{background:var(--panel);border-right:1px solid var(--line);padding:56px 60px;display:flex;flex-direction:column}
/* margin-block:auto op het eerste blok, niet justify-content: dan verdeelt de vrije
   ruimte zich boven én onder het merk en blijft de voetregel onderaan staan. */
.brand>div:first-child{margin-block:auto}
/* Het logo. Eén bestand — kroon en woordmerk in één stuk, zoals het merkbestand ze
   levert (assets/merk/dk-logo.png). Het woordmerk was hiervoor nagemaakt in de
   huisstijlletter met een icoon ervoor; dat leek erop maar was het niet. De hoogte
   bepaalt de maat, de breedte volgt uit de verhouding van het bestand zelf. */
.merk{display:block;height:26px;width:auto}
.merk-lg{height:34px;margin-bottom:4px}
.merkrij{display:flex;flex-direction:column;align-items:flex-start;gap:6px;min-width:0}
.merksub{font-size:12px;color:var(--tx3);font-weight:500;line-height:1.2}
/* Stonden als inline stijlen in index.html; maten horen in de stylesheet, anders
   is de typografie van het loginscherm niet te overzien vanuit één bestand. */
.pitch{margin:44px 0 0}
.pitch h1{font-size:26px;max-width:20ch;line-height:1.25}
.pitch p{color:var(--tx2);max-width:42ch;margin-top:12px;font-size:14.5px}
.brandfoot{font-size:12.5px;color:var(--tx3)}
.fc .lead{color:var(--tx2);margin:6px 0 22px;font-size:13.5px}
.remrij{display:flex;align-items:center;justify-content:space-between;margin:6px 0 18px;font-size:13.5px}
.remlabel{display:flex;align-items:center;gap:9px;color:var(--tx2)}
.ini-ac{background:var(--ac-bg);color:var(--ac)}
.formwrap{display:flex;align-items:center;justify-content:center;padding:40px}
.fc{width:100%;max-width:352px}
label{display:block;font-size:12.5px;color:var(--tx2);font-weight:500;margin:0 0 6px}
input,select,textarea{width:100%;height:39px;background:var(--bg);border:1px solid var(--line-ctl);color:var(--tx);border-radius:var(--r);padding:0 11px;font-family:var(--f);font-size:14px;outline:none}
textarea{height:auto}
input:focus,select:focus{border-color:var(--ac-dim);box-shadow:0 0 0 3px var(--ac-bg)}
.field{margin-bottom:14px}
.btn{height:36px;border:1px solid var(--line-ctl);background:var(--panel2);color:var(--tx);border-radius:var(--r);padding:0 14px;font-family:var(--f);font-size:13.5px;font-weight:500;cursor:pointer;display:inline-flex;align-items:center;gap:7px;letter-spacing:-.01em}
/* Een knop hoort te laten merken dat hij de druk voelt: 0.97 op :active, en een korte
   ease-out zodat het terugveren niet nasleept. Kleur krijgt een eigen, iets tragere
   overgang - dat is een toestandswijziging en geen reactie op een aanraking.
   Alleen transform en kleuren, want die slaan layout en paint over. */
.btn{transition:transform 160ms cubic-bezier(.23,1,.32,1),background-color 120ms ease,border-color 120ms ease}
.btn:active{transform:scale(.97)}
.btn[disabled]:active{transform:none}
.btn:hover{background:var(--rowhi);border-color:#7A7A80}
.btn[disabled]{opacity:.5;cursor:not-allowed}
.btn[disabled]:hover{background:var(--panel2);border-color:var(--line-ctl)}
.btn:focus-visible{outline:2px solid var(--ac);outline-offset:2px}

/*
    De actiebalk van een paneel: blijft in beeld terwijl je door de inhoud scrollt.

    Waarom dit er komt: de opslaanknop stond ónder de instellingen. Bij een groep met
    twintig sleutels stond hij honderden pixels lager dan het veld dat je net wijzigde,
    en dan lijkt hij weg. Je wijzigt iets, je zoekt de knop, je scrollt - en de kans dat
    je wegklikt zonder op te slaan is groter dan de kans dat je hem vindt.

    Sticky en niet fixed: hij hoort bij dit paneel en niet bij het scherm, dus hij
    verschijnt en verdwijnt met het paneel zelf. De negatieve marges laten hem tot de
    rand van de kaart lopen, zodat er niets langs de zijkanten onderdoor schuift.
*/
.actiebalk{position:sticky;bottom:0;z-index:3;display:flex;gap:12px;align-items:center;
  flex-wrap:wrap;margin:18px -15px -15px;padding:12px 15px;background:var(--panel);
  border-top:1px solid var(--line)}
/* Wat er nog niet opgeslagen is, naast de knop die dat doet. */
.actiebalk .stand{font-size:12.5px;color:var(--tx3)}
.actiebalk .rechts{margin-left:auto}
.btn i{font-size:16px}
.btn-p{background:var(--ac);border-color:var(--ac);color:#17120A}
.btn-p:hover{background:#F0A551;border-color:#F0A551}
.btn-g{background:transparent;border-color:transparent;color:var(--tx2)}
.btn-g:hover{background:var(--row);color:var(--tx)}
.btn-w{width:100%;justify-content:center;height:39px}
.btn-sm{height:31px;font-size:13px;padding:0 11px}
.sep{display:flex;align-items:center;gap:12px;color:var(--tx3);font-size:12.5px;margin:18px 0}
.sep:before,.sep:after{content:"";flex:1;height:1px;background:var(--linesoft)}

#app{display:none;min-height:100vh;grid-template-columns:230px 1fr}
#app.on{display:grid}
/* Alleen zichtbaar voor een schermlezer. Voor een label dat visueel al naast het
   element staat, of dat in de smalle zijbalk wegvalt. */
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:9px;top:-44px;z-index:20;background:var(--panel2);
  color:var(--tx);border:1px solid var(--line-ctl);border-radius:var(--r);
  padding:8px 13px;font-size:13.5px;transition:top .12s}
.skip:focus{top:9px;text-decoration:none}
#view:focus{outline:none}
.side{background:var(--panel);border-right:1px solid var(--line);display:flex;flex-direction:column;position:sticky;top:0;height:100vh;overflow-y:auto}
.stop{padding:17px 17px 14px;border-bottom:1px solid var(--linesoft)}
.tenant{margin-top:13px;background:var(--bg);border:1px solid var(--line);border-radius:var(--r);padding:8px 10px;display:flex;align-items:center;gap:9px;cursor:pointer}
.tenant:hover{border-color:#33333A}
.ini{border-radius:5px;display:grid;place-items:center;font-size:12px;font-weight:600;flex:none}
.tenant .ini{width:27px;height:27px}
.tenant .nm{font-size:13px;font-weight:500;line-height:1.25}
.tenant .sub{font-size:12px;color:var(--tx3);line-height:1.25}
.tenant i.ti-selector{margin-left:auto;color:var(--tx3);font-size:16px}
.navgrp{padding:13px 11px 0}
.navgrp>span{display:block;font-size:12px;color:var(--tx3);font-weight:500;padding:0 9px 7px}
.nav{display:flex;align-items:center;gap:10px;padding:7px 9px;border-radius:var(--r);color:var(--tx2);cursor:pointer;font-size:13.5px}
.nav i{font-size:16px;width:17px;text-align:center;color:var(--tx3)}
.nav:hover{background:var(--row);color:var(--tx)}.nav:hover i{color:var(--tx2)}
.nav.act{background:var(--rowhi);color:var(--tx);font-weight:500}
.nav.act i{color:var(--ac)}
.nav .cnt{margin-left:auto;font-size:12px;color:var(--tx3)}
.nav:focus-visible,.tenant:focus-visible,.site:focus-visible,.tab:focus-visible,
tbody tr:focus-visible,.row-s[data-hash]:focus-visible,.tog:focus-visible,
th button:focus-visible{outline:2px solid var(--ac);outline-offset:2px}
tbody tr:focus-visible{outline-offset:-2px}
.sfoot{margin-top:auto;padding:14px 17px;border-top:1px solid var(--linesoft);font-size:12px;color:var(--tx3)}

.main{min-width:0;display:flex;flex-direction:column}
.top{height:var(--top-h);border-bottom:1px solid var(--line);display:flex;align-items:center;gap:13px;padding:0 22px;background:var(--panel);position:sticky;top:0;z-index:5}
.crumb{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--tx3)}
.crumb b{color:var(--tx);font-weight:500}.crumb i{font-size:16px}
/* Het logo van de site in het kruimelspoor. 18 px: het moet te herkennen zijn en niet
   concurreren met het woordmerk van Datakings een paar centimeter naar links. */
.kruimelmerk{width:18px;height:18px;object-fit:contain;border-radius:5px;flex:none;
  margin-right:2px}
.search{margin-left:auto;position:relative}
.search input{height:32px;width:224px;padding-left:32px;font-size:13px}
.search i{position:absolute;left:10px;top:8px;color:var(--tx3);font-size:16px}
.me{display:flex;align-items:center;gap:9px;padding-left:13px;border-left:1px solid var(--linesoft);cursor:pointer}
.me .av{width:28px;height:28px;border-radius:50%;background:var(--ac-bg);color:var(--ac);display:grid;place-items:center;font-size:12px;font-weight:600}
.me .nm{font-size:13px;line-height:1.2}.me .rl{font-size:12px;color:var(--tx3);line-height:1.2}
/* Gecentreerd, want op een 2560px-monitor kleefde alles links met een lege strook
   ernaast. Onder 1500px verandert er niets. */
.body{padding:22px;flex:1;width:100%;max-width:1500px;margin-inline:auto}
.phead{display:flex;align-items:flex-start;gap:16px;margin-bottom:18px;flex-wrap:wrap}
.phead p{margin:3px 0 0;color:var(--tx2);font-size:13.5px;max-width:66ch}
/* Het logo naast de schermtitel. 2px naar beneden zodat het optisch op de bovenlijn van
   de letters uitkomt in plaats van op de regelhoogte. */
.ptitel{display:flex;align-items:flex-start;gap:13px;min-width:0}
.ptitel .ini{margin-top:2px}
/* Een aangeleverd logo mag niet aangesneden worden: contain, met de vrije ruimte om het
   plaatje heen in plaats van een uitsnede. Geen achtergrondkleur, want een logo met een
   transparante rand hoort in het donker gewoon donker te zijn. */
img.merk-site,.ini.merk-site img{object-fit:contain;border-radius:5px;background:transparent}
.ini.merk-site{background:transparent;overflow:hidden}
.ini.merk-site img{width:100%;height:100%;display:block}
.pacts{margin-left:auto;display:flex;gap:8px;flex-wrap:wrap;align-items:center}

.card{background:var(--panel);border:1px solid var(--line);border-radius:10px}
.card>header{padding:12px 15px;border-bottom:1px solid var(--linesoft);display:flex;align-items:center;gap:10px}
.card>header h3{flex:1}
.card>.in{padding:15px}
.grid{display:grid;gap:14px}
.two{display:grid;grid-template-columns:1.55fr 1fr;gap:14px;align-items:start}
.three{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:12px;margin-bottom:16px}
.kpi{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:14px 15px}
.kpi .lb{font-size:12.5px;color:var(--tx2);display:flex;align-items:center;gap:7px}
.kpi .lb i{font-size:16px;color:var(--tx3)}
.kpi .vl,.kerncijfer{font-size:26px;font-weight:600;line-height:1.3;letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.kpi .vl{margin-top:5px}
.kpi .dl{font-size:12.5px;color:var(--tx3)}
.kpi.wa{border-color:rgba(224,169,74,.35)}.kpi.er{border-color:var(--er-line)}

table{width:100%;border-collapse:collapse}
/* Vaste kolombreedtes uit de colgroup van de tabel zelf. Zonder dit bepaalt de
   inhoud de breedte, en dan duwt één lange groepsnaam of serienummer de tabel
   breder dan zijn kaart — precies waar de horizontale schuifbalk vandaan kwam. */
table.fx{table-layout:fixed}
/* text-overflow erbij: een kolomkop die niet past werd hard afgesneden zonder enig
   teken. Dat gebeurde meteen zodra een kolom smaller werd gezet. */
th{text-align:left;font-size:12px;color:var(--tx3);font-weight:500;padding:10px 13px;border-bottom:1px solid var(--line);white-space:nowrap;background:var(--panel2);overflow:hidden;text-overflow:ellipsis}
/* Een sorteerkop is een knop, niet een klikbare div: zo werkt hij met het
   toetsenbord en kan aria-sort de richting melden. */
th button{background:none;border:0;padding:0;margin:0;font:inherit;color:inherit;
  cursor:pointer;display:inline-flex;align-items:center;gap:5px}
th button:hover{color:var(--tx)}
th[aria-sort] button{color:var(--tx)}
th .pijl{font-size:12px;color:var(--ac)}
td{padding:10px 13px;border-bottom:1px solid var(--linesoft);font-size:13.5px;vertical-align:middle}
tbody tr{cursor:pointer}tbody tr:hover{background:var(--row)}
tbody tr:last-child td{border-bottom:none}
.tbl{border:1px solid var(--line);border-radius:10px;background:var(--panel);overflow:hidden}
/*
    Een tabel past binnen zijn kaart en schuift niet horizontaal.

    Dertien kolommen naast elkaar pasten niet, en de schuifbalk betekende dat je
    de helft van een toestel alleen zag door te slepen: batterij, uitrolstatus en
    laatste contact stonden rechts buiten beeld terwijl je naar de naam keek. Wat
    kolommen waren, staat nu als tweede regel in de cel waar het bij hoort —
    serienummer onder de naam, model onder de groep. Niets is weggelaten, en
    sorteren op elk veld kan nog steeds (kolomkop of de keuzelijst 'Sorteren op').

    Een cel breekt nooit af over twee regels: te lange tekst kapt af met een
    tooltip. "BH-SCAN-01" over drie regels als BH- / SCAN- / 01 is onleesbaar,
    en dat is waarom hier nowrap staat en niet word-wrap.
*/
/*
    Een lijst die niet oneindig doorloopt. Geldt voor élke lijst, niet voor een handjevol.

    Bij veel regels werd de pagina zo lang dat de kop, de filters en de knoppen ver boven beeld
    verdwenen en je met de schuifbalk van het venster door honderden rijen moest — terwijl je
    meestal de bovenste tien wil zien. Met een eigen schuifgebied blijft de pagina even lang,
    of er nu tien of vierhonderd regels in staan.

    Dit stond eerst als `.scr-hoog` op vier lijsten en op de andere acht niet, en dat is precies
    hoe zoiets uit elkaar loopt: wie er een lijst bij bouwt weet niet dat hij een extra klasse
    moet meenemen. Nu hoort het bij het schuifgebied zelf en kan niemand het vergeten.

    De koprij blijft staan (position: sticky), anders scrol je binnen twintig rijen weg van de
    betekenis van de kolommen. 62vh: hoog genoeg om een lijst als lijst te lezen, laag genoeg
    dat wat eronder staat nog zichtbaar is en je weet dat de pagina doorloopt.
*/
.scr{min-width:0;max-height:62vh;overflow-y:auto;overscroll-behavior:contain}
.scr thead th{position:sticky;top:0;z-index:1}

/*
    Twee signalen dat een lijst verder gaat.

    1. De onderste regels lopen weg in een vervaging. Een lijst die in zichzelf scrolt houdt de
       pagina kort, maar hij verzwijgt ook dat er meer is: de onderste rij loopt tegen de rand
       aan en je moet gokken. De klasse `kanmeer` wordt in code gezet en verdwijnt zodra je
       onderaan bent — zo zegt hij ook wanneer je er wél bent. Een lijst die helemaal past
       krijgt hem nooit, want een vervaging zonder inhoud eronder is een leugen.

       mask-image en niet een gradiënt eroverheen: een overlay moet de achtergrondkleur van
       precies dat blok raden, en die verschilt per kaart. Een masker werkt op wat er getekend
       is en heeft die kleur niet nodig.

    2. Een schuifbalk die altijd staat in plaats van pas bij muisbeweging. De vervaging zegt
       "er is meer", de balk zegt hoeveel en waar je bent. Smal en in de lijnkleur, zodat hij
       niet met de inhoud concurreert.
*/
.scr.kanmeer{
  -webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 38px),transparent);
  mask-image:linear-gradient(to bottom,#000 calc(100% - 38px),transparent)
}
.scr{scrollbar-width:thin;scrollbar-color:var(--lijn) transparent}
.scr::-webkit-scrollbar{width:10px;height:10px}
.scr::-webkit-scrollbar-track{background:transparent}
/* Radius 7, zoals alle bediening (DESIGN.md). De duim is 4px breed, dus hij is sowieso rond;
   een derde radius invoeren voor iets wat je niet eens kunt zien is er een te veel. */
.scr::-webkit-scrollbar-thumb{
  background:var(--lijn);border-radius:7px;
  border:3px solid transparent;background-clip:content-box
}
.scr:hover::-webkit-scrollbar-thumb{background:var(--tx3);background-clip:content-box}

/*
    Behalve in een dialoog. Die heeft zijn eigen schuifgebied (.dialoog .in) en twee
    schuifbalken in elkaar is precies één te veel: je pakt de verkeerde en er lijkt niets
    te gebeuren.
*/
.dialoog .scr{max-height:none;overflow-y:visible}

/* Blijft bestaan voor bestaande markup; doet nu hetzelfde als .scr. */
.scr-hoog{max-height:62vh;overflow-y:auto;overscroll-behavior:contain}
.scr-hoog thead th{position:sticky;top:0;z-index:1}
.cel{display:flex;flex-direction:column;gap:1px;min-width:0}
.cel .a,.cel .b{display:block;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cel .a{line-height:1.4}
.cel .b{font-size:12px;color:var(--tx3);line-height:1.35}
/*
    Namen mogen over twee regels; meetwaarden nooit.

    Waarom opt-in en niet globaal: de meeste cellen in dit portaal zijn meetwaarden, en
    die laten doorlopen geeft drie regressies op alleen al de devicelijst — "100% ⚡"
    schuift onder het batterijbalkje, "3 uur geleden" valt uiteen in twee regels, en de
    pil "In reparatie" breekt. Namen zijn de uitzondering, dus krijgen namen de klasse.

    Waarom precies twee regels en niet vrij doorlopen: white-space:normal breekt ook na
    een koppelteken, dus "BH-SCAN-01" kan in een smalle kolom als BH- / SCAN- / 01
    uiteenvallen — de klacht die dit portaal al één keer heeft gehad. Met line-clamp is
    een derde regel structureel onmogelijk in plaats van toevallig afwezig, en blijft de
    rijhoogte op de devicelijst rond 90px in plaats van 160. Wat na twee regels niet past
    staat in de tooltip.
*/
.cel .a.wr,.cel .b.wr,.cel .rij>.tr.wr{white-space:normal;overflow-wrap:break-word;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
/* Een regel met een bolletje, een balkje of een pil ervoor: de tekst ernaast is
   wat afkapt, niet het element zelf. Ook buiten een cel te gebruiken, voor een
   avatar of initialen die naast beide regels staat. */
.rij{display:flex;align-items:center;gap:9px;min-width:0}
.rij>.tr,.rij>.cel{min-width:0}
/* Deze twee moeten .cel .a en .cel .b verslaan (die zetten display:block, en dan
   doet gap niets en plakt een bolletje tegen de naam). Vandaar drie klassen. */
.cel .a.rij,.cel .b.rij{display:flex;align-items:center;gap:8px}
.cel .rij>.tr{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}

/*
    Een groep kiezen: rijen met echte radio's in plaats van een <select>.

    Een keuzelijst kan een lange naam niet laten doorlopen, kapt de dichtgeklapte keuze
    hard af zonder ellipsis of tooltip, en de open lijst is vormgeving van het
    besturingssysteem — dat blauwe balkje hoort niet bij dit portaal. Zelf afkappen loste
    dat niet op: dan is de lengte van een naam nog steeds de reden dat het scherm er niet
    uitziet.
*/
.keuze{border:1px solid var(--line);border-radius:var(--r);background:var(--bg);overflow:hidden}
.keuzerij{display:flex;align-items:flex-start;gap:11px;padding:11px 13px;cursor:pointer;
  border-bottom:1px solid var(--linesoft);margin:0;min-height:48px;align-items:center}
.keuzerij:last-child{border-bottom:none}
.keuzerij:hover{background:var(--row)}
.keuzerij input{position:absolute;width:1px;height:1px;opacity:0}
.keuzerij .stip{width:17px;height:17px;border-radius:50%;border:1px solid var(--line-ctl);
  flex:none;display:grid;place-items:center}
.keuzerij input:checked+.stip{border-color:var(--ac);border-width:2px}
.keuzerij input:checked+.stip:after{content:"";width:9px;height:9px;border-radius:50%;
  background:var(--ac)}
.keuzerij input:focus-visible+.stip{outline:2px solid var(--ac);outline-offset:2px}
.keuzerij .nm{flex:1;min-width:0;font-size:13.5px;line-height:1.35}
.keuzerij .nm .sub{display:block;font-size:12px;color:var(--tx3);line-height:1.35}
.keuzerij .mt{font-size:12.5px;color:var(--tx3);white-space:nowrap}
.keuzerij .mt.leeg{color:var(--wa)}
.keuzerij.aan{background:var(--row)}
.keuzerij.aan .nm{font-weight:500}
.keuzeleeg{padding:13px;font-size:13px;color:var(--tx3)}
/* Vanaf negen groepen: zoekveld erboven en een eigen schuifgebied van vier rijen hoog,
   zodat de knoppen eronder in beeld blijven. */
.keuze-veel{max-height:248px;overflow-y:auto}
.keuzezoek{position:sticky;top:0;background:var(--panel);padding:9px 13px;
  border-bottom:1px solid var(--line);z-index:1}
.keuzezoek input{height:36px;font-size:13px}
/* Behalve in een leeg-toestand: dat is een zin, geen meetwaarde. */
.scr .empty,.scr .empty p,.scr .empty b{white-space:normal}
/* De vier tegels met de stand van nu op het devicescherm. Label boven de waarde,
   want een icoon alleen zegt niet welk getal je ziet. */
.tegels{display:grid;grid-template-columns:1fr 1fr;gap:11px;margin-bottom:15px}
.tegel{background:var(--row);border-radius:var(--r);padding:11px 13px;display:grid;
  grid-template-columns:auto 1fr;grid-template-rows:auto auto;gap:0 9px;align-items:center}
.tegel i{grid-row:1 / span 2;font-size:20px;color:var(--tx3)}
.tegel .lb{font-size:12px;color:var(--tx3);line-height:1.3}
.tegel .vl{font-size:13.5px;line-height:1.3}

/*
    De sprong naar de devicelijst achter een aandachtssoort ("in de lijst").

    Hier stonden ook .aplijst, .apgroep, .apkop, .aprij, .apsites, .apsite en .apmeer: de
    opmaak van twee eerdere vormen van het aandachtsblok, waarin eerst de sites per soort en
    daarna de toestellen bij naam stonden. Beide zijn vervangen door één regel per soort met
    een telling (.ernstblok en .apwarij hieronder), en die 33 regels css hoorden bij niets
    meer. Een selector die nergens meer bij hoort is erger dan geen selector: de volgende die
    hier iets aanpast weet niet of hij iets stuk maakt.
*/
.apnaar{margin-left:12px;font-size:12.5px}
/* De licentie-uitzonderingen op het dashboard: reden links, sites rechts, één regel per
   reden. De labels lijnen uit omdat het één grid is en niet drie losse regels. */
.letlijst{display:grid;grid-template-columns:auto minmax(0,1fr);gap:3px 14px;margin-bottom:5px}
.letlijst b{font-weight:500;white-space:nowrap}
.letlijst span{color:var(--tx2)}
@media(max-width:900px){.letlijst{grid-template-columns:1fr;gap:0 0}
  .letlijst span{margin-bottom:5px}}
/*
    Een bestand kiezen: slepen, klikken of plakken. Zie valvak() in portaal.js.

    Waarom dit bestaat: een <input type="file"> tekent de browser zelf — een grijze knop met
    "geen bestand geselecteerd" ernaast in de opmaak van Windows. Dat was het enige onderdeel
    van dit portaal dat er niet uitzag als dit portaal. De bestandsdialoog van Windows zelf
    blijft zoals hij is; daar mag geen enkele website aan komen. Maar met slepen en plakken
    heb je hem niet meer nodig.

    De echte input staat er nog wel (code die .files leest blijft werken) maar is onzichtbaar
    en niet bereikbaar met Tab: het vak zelf is de bediening, met een rol en focus.
*/
.valvak{position:relative;border:1px dashed var(--line-ctl);border-radius:var(--r);
  background:var(--bg);padding:16px 14px;cursor:pointer;transition:border-color .12s,
  background .12s}
.valvak:hover{border-color:#7A7A80;background:var(--panel2)}
.valvak:focus-visible{outline:2px solid var(--ac);outline-offset:2px}
/* Tijdens het slepen: doorlopende rand in de accentkleur, zodat je ziet dat je op de goede
   plek bent voordat je loslaat. */
.valvak.over{border-style:solid;border-color:var(--ac);background:var(--ac-bg)}
.valvak-echt{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.valvak-leeg{display:flex;flex-direction:column;align-items:center;gap:5px;text-align:center}
.valvak-leeg i{font-size:20px;color:var(--tx3)}
.valvak.over .valvak-leeg i{color:var(--ac)}
.valvak-leeg .tx{font-size:13px;color:var(--tx2)}
.valvak-leeg .of{font-size:12px;color:var(--ac);text-decoration:underline;
  text-underline-offset:3px}
/* Gekozen: wat het is, hoe groot, en een uitweg. */
.valvak-vol{display:flex;align-items:center;gap:12px;min-width:0}
.valvak-vol .voor{width:38px;height:38px;flex:none;display:grid;place-items:center;
  background:var(--rowhi);border-radius:5px;overflow:hidden}
.valvak-vol .voor img{width:100%;height:100%;object-fit:contain;display:block}
/* Geen plaatje: de extensie als kenmerk. Een icoon van een blaadje zegt niets over wat er
   in zit; ".APK" wel. */
.valvak-vol .ext{font-size:12px;font-weight:500;letter-spacing:.04em;color:var(--tx2)}
.valvak-vol .wat{min-width:0;display:flex;flex-direction:column;gap:1px}
.valvak-vol .wat b{font-weight:500;font-size:13px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.valvak-vol .maat{font-size:12px;color:var(--tx3);font-variant-numeric:tabular-nums}
.valvak-vol .btn{margin-left:auto;flex:none}

/* Het logoveld: links wat er nu staat, daaronder het valvak om het te vervangen. */
.logoveld{display:grid;gap:11px}
.logoveld .nu{display:flex;align-items:center;gap:12px}
.logoveld .nu .voor{width:44px;height:44px;flex:none}
.logoveld .nu .voor img{width:44px;height:44px;object-fit:contain;border-radius:5px;
  display:block}
.logoveld .nu .voor .ini{font-size:15px}
.logoveld .d{font-size:12px;color:var(--tx3)}
/*
    De koppeldialoog: twee wegen naast elkaar, scannen of intikken.

    Waarom naast elkaar en niet onder elkaar met een keuze ertussen: het zijn geen twee
    instellingen waar je tussen kiest maar twee manieren om hetzelfde te doen, en welke werkt
    hangt af van waar je staat. Beide in beeld betekent dat niemand hoeft te zoeken.
*/
/* Vaste breedte voor de kolom met de QR. Met `auto` kneep het raster die kolom samen zodra
   de tekst ernaast ruimte vroeg, terwijl de svg zijn eigen maat uit zijn attributen houdt —
   dan loopt de code buiten zijn witte vlak en over de uitleg eronder. */
.koppelweg{display:grid;grid-template-columns:196px 1fr;gap:22px;margin-top:16px;
  align-items:start}
.kw-kop{font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--tx3);
  margin-bottom:9px}
/* Wit vlak om de code heen: een QR op een donkere achtergrond leest geen enkele scanner. De
   stille zone zit in de svg zelf (zie qr.js), dit is de rand die je met je oog ziet. */
.qr{background:#FFFFFF;padding:8px;border-radius:5px;display:block;line-height:0;
  width:196px;height:196px}
/* De maat komt uit de css en niet uit de attributen van de svg, zodat er één plek is die hem
   bepaalt. 180px op een scherm is ruim genoeg voor de imager van een TC20 op leesafstand. */
.qr svg{display:block;width:180px;height:180px}
.qr-mislukt{width:180px;font-size:12.5px;color:var(--er);line-height:1.5}
.kw-uitleg{font-size:12px;color:var(--tx3);margin-top:9px;max-width:30ch;line-height:1.5}
.kw-uitleg b{color:var(--tx2);font-weight:500}
/* De pincode is om over te typen op een toestel dat je in je andere hand houdt: groot, met
   een spatie in het midden zodat je niet je plek verliest. */
.pincode{font-size:26px;font-weight:500;letter-spacing:.1em;line-height:1.15}
/* De eerste app op een kaal toestel. Niet ingeklapt zoals de oude weg hieronder: dit is de enige
   weg die werkt als er nog geen agent op staat, en dat is de normale situatie bij een nieuwe
   klant. Wel eronder, want bij verreweg de meeste koppelingen staat de app er al. */
.kw-boot{margin-top:20px;padding-top:14px;border-top:1px solid var(--linesoft)}
.boot-rij{display:grid;grid-template-columns:196px 1fr;gap:22px;align-items:start}
/* Een adres van tachtig tekens moet kunnen afbreken zonder het venster te verbreden, en het moet
   te selecteren zijn om over te typen of te kopiëren. */
.boot-adres{font-size:13px;line-height:1.5;color:var(--tx);background:var(--rowhi);
  padding:8px 10px;border-radius:5px;word-break:break-all;user-select:all}
@media(max-width:640px){.boot-rij{grid-template-columns:1fr}}

/* De oude weg staat ingeklapt: hij moet er zijn zolang de app niet kan scannen, maar hij mag
   niet de eerste zijn die je ziet. */
.oudeweg{margin-top:20px;padding-top:14px;border-top:1px solid var(--linesoft)}
.oudeweg summary{font-size:12.5px;color:var(--tx2);cursor:pointer}
.oudeweg summary:hover{color:var(--tx)}
.oudeweg p{font-size:12px;color:var(--tx3);line-height:1.6;margin:10px 0 12px}
.oudeweg code{font-family:var(--f);font-size:12px;background:var(--rowhi);padding:1px 4px;
  border-radius:5px}
.knoprij{display:flex;gap:8px;flex-wrap:wrap}
@media(max-width:640px){.koppelweg{grid-template-columns:1fr}}
/* Een site als chip met zijn logo ervoor: bij Gebruikers in de kolom "Ziet". Zelfde maat en
   radius als de chips op het dashboard, zodat een site er overal hetzelfde uitziet. */
.sitechip{display:inline-flex;align-items:center;gap:6px;background:var(--rowhi);
  border-radius:5px;padding:3px 8px;font-size:12.5px;color:var(--tx2);max-width:100%;
  min-width:0}
.sitechip-rest{background:transparent;color:var(--tx3);padding-left:2px}
/* Wat er met één toestel aan de hand is, bovenaan het devicescherm. Zelfde twee kleuren en
   zelfde woorden als op de dashboards; alleen de bol en de soortnamen dragen kleur, want een
   gevuld vlak bovenaan een scherm dat verder rustig is schreeuwt. */
.devaandacht{display:grid;gap:7px;margin:-4px 0 16px}
.devaandacht .rij{display:flex;align-items:baseline;gap:10px;font-size:13.5px}
.devaandacht .bol{width:7px;height:7px;border-radius:50%;flex:none;position:relative;top:-2px}
.devaandacht .rij.er .bol{background:var(--er)}
.devaandacht .rij.wa .bol{background:var(--wa)}
.devaandacht b{font-weight:500;min-width:64px}
.devaandacht .rij.er .wat{color:var(--er-licht)}
.devaandacht .rij.wa .wat{color:var(--wa-licht)}
/* Een meetwaarde die door zijn drempel is. Dezelfde tinten als de soortnamen, zodat "1450"
   in de lijst dezelfde kleur heeft als "Buffer loopt op" erboven. */
.v-er{color:var(--er-licht)}
.v-wa{color:var(--wa-licht)}
/* De twee vinkvelden in de werkbalk van de devicelijst. Ze staan in één omhulsel met een
   rand eromheen, want het zijn twee delen van één vraag ("wat vraagt aandacht") en niet twee
   losse instellingen tussen de keuzelijsten. Een bolletje in de kleur van de groep, zodat
   het vinkje dezelfde taal spreekt als de chips op het dashboard waar je vandaan komt. */
.vinkfilters{display:flex;align-items:center;gap:2px;border:1px solid var(--line-ctl);
  border-radius:var(--r);padding:2px 4px}
.vinkfilters .vink{font-size:13px;gap:7px;padding:4px 7px;border-radius:5px;margin:0;
  white-space:nowrap}
.vinkfilters .vink:hover{background:var(--rowhi)}
.vinkfilters .bol{width:7px;height:7px;border-radius:50%;flex:none}
.vinkfilters .bol.er{background:var(--er)}
.vinkfilters .bol.wa{background:var(--wa)}
/* Twee ernstgroepen op het sitedashboard: Storing en Aandacht, elk met zijn eigen kleur.
   Zie sitePunten() voor waarom een storing namen krijgt en aandacht een telling. */
.ernstblok+.ernstblok{margin-top:20px;padding-top:16px;border-top:1px solid var(--linesoft)}
.ernstkop{display:flex;align-items:center;gap:9px;margin-bottom:11px}
.ernstkop .bol{width:8px;height:8px;border-radius:50%;flex:none}
.ernstblok.er .bol{background:var(--er)}
.ernstblok.wa .bol{background:var(--wa)}
.ernstkop b{font-size:14px;font-weight:500}
/* De naam van de soort in een lichtere tint van de groep waar hij in staat, en de rand
   links in dezelfde kleur. Zonder dat verschil stonden acht koppen in hetzelfde grijs en
   moest je terugzoeken onder welke groep je zat. De reden en de groepsnaam achter een
   toestel blijven grijs: die dragen geen ernst. */
.ernstblok.er .apwarij b{color:var(--er-licht)}
.ernstblok.er .apwarij{border-top-color:var(--er-lijn)}
.ernstblok.wa .apwarij b{color:var(--wa-licht)}
.ernstblok.wa .apwarij{border-top-color:var(--wa-lijn)}
.ernstkop .num{font-size:12.5px;color:var(--tx2)}
.ernstkop .ui{margin-left:auto;font-size:12.5px;color:var(--tx3);text-align:right}
/* Zelfde inspringing als de soortkoppen onder Storing (.apgroep heeft 2px rand + 13px),
   zodat de namen van alle acht soorten op één lijn staan. */
.apwarij{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:0 9px;
  align-items:center;padding:9px 0;border-top:1px solid var(--linesoft);font-size:14px}
.apwarij b{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.apwarij .num{font-size:12.5px;color:var(--tx3)}
@media(max-width:760px){.ernstkop .ui{display:none}}

/* De legenda bij de 24-uursreeks in een lijst: een gekleurd staafje in een tabel
   hoort uitgelegd te worden op hetzelfde scherm, niet alleen in een tooltip. */
.hblegrij{padding:9px 13px;border-top:1px solid var(--linesoft)}
.hblegrij .hbleg{margin-top:0}
.tools{display:flex;align-items:center;gap:8px;padding:11px 13px;border-bottom:1px solid var(--linesoft);flex-wrap:wrap}
.tools select,.tools input{height:32px;width:auto;font-size:13px}
.tools .rt{margin-left:auto;display:flex;gap:8px}
/* Het zoekveld is het enige dat mag krimpen: een keuzelijst die smaller wordt kapt zijn
   optie af, en dan sta je te lezen wat er ook alweer aanstond. Het zoekveld verliest
   alleen wat plaatshouder. Daarmee past de rij tot ver onder 1280 px op één regel; er
   stond een tweede regel met één keuzelijst erop en dat las als een tweede werkbalk. */
.tools>input[id="f-zoek"]{flex:1 1 120px;min-width:92px;max-width:240px}
/* Een keuzelijst wordt door de browser zo breed als zijn langste optie. Met een groep die
   "Magazijn Rotterdam stelling 12" heet duwde dat de rij op 1280 px naar twee regels. De
   gekozen waarde is bijna altijd kort ("Alle groepen"), dus 190 px is ruim; wie een lange
   groep kiest ziet hem afgekapt in de lijst maar volledig in de kolom Groep. */
.tools>select{flex:0 1 auto;min-width:0;max-width:162px;text-overflow:ellipsis}
.tools .vinkfilters{flex:none}
.tfoot{padding:10px 13px;border-top:1px solid var(--linesoft);display:flex;align-items:center;color:var(--tx3);font-size:13px}

/*
    De tweede regel in een kolomkop: het veld dat in de cel eronder staat, met zijn eigen
    sorteerknop. Kleiner en gedempt, zodat het hoofdveld de kop blijft — dezelfde verhouding als
    tussen de eerste en tweede regel van de cel.
*/
th button.kop-onder{display:block;margin-top:2px;font-size:12px;color:var(--tx3);
  letter-spacing:0;font-weight:400}
th button.kop-onder:hover{color:var(--tx2)}
th button.sorteert{color:var(--tx)}
.pill{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:500;padding:2px 9px;border-radius:20px;white-space:nowrap}
.p-ok{background:var(--ok-bg);color:var(--ok)}
.p-wa{background:var(--wa-bg);color:var(--wa)}
.p-er{background:var(--er-bg);color:var(--er)}
.p-ac{background:var(--ac-bg);color:var(--ac)}
.p-nu{background:var(--rowhi);color:var(--tx2)}
.dotr{width:7px;height:7px;border-radius:50%;display:inline-block;flex:none}
.d-ok{background:var(--ok)}.d-wa{background:var(--wa)}.d-er{background:var(--er)}.d-of{background:var(--tx3)}
.live{animation:bt 2.4s ease-in-out infinite}
@keyframes bt{0%,100%{opacity:.4}50%{opacity:1}}
.hb{display:inline-flex;gap:2px;align-items:flex-end;height:18px}
.hb i{display:block;width:3px;border-radius:1px}
.hb i.g{background:var(--hb-ok)}.hb i.a{background:var(--wa)}.hb i.r{background:var(--er)}.hb i.o{background:var(--hb-none)}
/*
    De fijne reeks: 96 blokken van een kwartier, alleen op het toestelscherm (DESIGN.md).

    Hij loopt over de volle breedte van zijn kolom, dus tot onder de laatste tegel. Eerst stonden
    de staafjes op een vaste 1,5 px met 1 px ertussen: samen ±240 px, en dat was de helft van het
    kader eromheen. Ward, 5 augustus 2026: *"ik zie dat dit maar tot de helft gaat van het kader
    waar het inzit. Je kan dit ook doortrekken tot aan het eind van 'nog te verzenden' voor een
    beter beeld."* Terecht — een reeks die maar half zo breed is als de kaart leest als een reeks
    die halverwege ophoudt.

    Daarom flex in plaats van een vaste maat: de staafjes verdelen de ruimte die er is. Op een
    kolom van 480 px worden ze ~4 px, op 320 px ~2,3 px, en het beeld blijft in verhouding. Een
    vaste maat zou bij elke schermbreedte een andere fout maken.
*/
/*
    De fijne reeks is een rij van 24 uurblokjes met vier kwartieren erin. De ruimte tússen de uren
    (5px) is groter dan die binnen een uur (1px): daardoor telt je oog uren in plaats van 96 losse
    streepjes. Binnen een uurblokje verdeelt een raster de breedte — met flex rondde de browser elke
    staaf af op hele beeldpunten en verdween de tussenruimte op willekeurige plekken, waardoor
    staafjes aan elkaar plakten (Ward, 6 augustus 2026).
*/
.hb-fijn{display:flex;gap:5px;width:100%;height:18px}
.hbuur{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;
  align-items:flex-end;flex:1 1 0;min-width:0;height:18px}
.hb-fijn i{width:auto;min-width:0}
/* Waar je nu naar wijst. Lichter in plaats van een rand: een contour om een staaf van 4px maakt
   hem breder dan zijn buren en dan lijkt de meting anders. */
.hb-fijn i.hb-aan{filter:brightness(1.75)}
.hb-fijn:focus{outline:2px solid var(--ac);outline-offset:3px;border-radius:3px}

/* De tijdas onder de reeks: vier tijdstippen op gelijke afstand en "nu" aan het eind. */
.hbas{display:flex;margin-top:5px;font-size:12px;color:var(--tx3);letter-spacing:.2px}
.hbas span{flex:1 1 0}
.hbas span.nu{flex:0 0 auto;color:var(--tx2)}

/*
    De uitleesregel. Staat er altijd — met een samenvatting zolang je nergens op wijst — en
    verandert terwijl je over de reeks beweegt. Vaste hoogte, anders springt alles eronder mee.
*/
.hblees{margin-top:7px;font-size:12.5px;color:var(--tx2);min-height:19px}
/* Legenda onder de reeks: hetzelfde staafje, één keer gedefinieerd. */
.hbleg{display:flex;flex-wrap:wrap;gap:12px;margin-top:8px;font-size:12px;color:var(--tx3)}
.hbleg span{display:inline-flex;align-items:center;gap:5px}
.hbleg b{display:block;width:3px;height:11px;border-radius:1px}
.hbleg b.g{background:var(--hb-ok)}.hbleg b.a{background:var(--wa)}
.hbleg b.r{background:var(--er)}.hbleg b.o{background:var(--hb-none)}
.bar{height:6px;background:var(--rowhi);border-radius:3px;overflow:hidden}
.bar b{display:block;height:100%;background:var(--tx2);border-radius:3px}
.bar b.ac{background:var(--ac)}.bar b.ok{background:var(--ok)}.bar b.wa{background:var(--wa)}.bar b.er{background:var(--er)}

.tabs{display:flex;gap:3px;border-bottom:1px solid var(--line);margin-bottom:16px;overflow-x:auto}
.tab{padding:9px 14px;font-size:13.5px;color:var(--tx2);cursor:pointer;border-bottom:2px solid transparent;white-space:nowrap}
.tab:hover{color:var(--tx)}
.tab.act{color:var(--tx);border-bottom-color:var(--ac);font-weight:500}
.kv{display:grid;grid-template-columns:158px 1fr;gap:10px 14px;font-size:13.5px;margin:0}
.kv dt{color:var(--tx3)}.kv dd{margin:0}
.chip{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;background:var(--rowhi);color:var(--tx2);border-radius:5px;padding:2px 8px}
.tog{width:35px;height:20px;border-radius:11px;background:var(--rowhi);position:relative;cursor:pointer;flex:none}
.tog b{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--tx3);transition:.15s}
.tog.on{background:var(--ac-dim)}.tog.on b{left:17px;background:#fff}
.row-s{display:flex;align-items:center;gap:12px;padding:11px 0;border-bottom:1px solid var(--linesoft)}
.row-s:last-child{border-bottom:none;padding-bottom:0}
.row-s .tx{flex:1}.row-s .tx .t{font-size:13.5px}.row-s .tx .d{font-size:12.5px;color:var(--tx3)}
.note{background:var(--row);border:1px solid var(--line);border-radius:var(--r);padding:11px 13px;font-size:13.5px;display:flex;gap:11px;align-items:flex-start}
.note i{font-size:16px;flex:none;margin-top:1px;color:var(--tx2)}
.note.w{background:var(--wa-bg);border-color:rgba(224,169,74,.3)}.note.w i{color:var(--wa)}
/* Rood, voor een melding waar echt iets aan moet gebeuren. Zelfde vorm als .note.w; alleen de
   kleur verschilt, en de glyph staat er los bij - kleur mag nooit het enige signaal zijn. */
.note.er{background:var(--er-bg);border-color:var(--er-line)}.note.er i{color:var(--er)}
.tl{position:relative;padding-left:19px}
.tl:before{content:"";position:absolute;left:4px;top:6px;bottom:6px;width:1px;background:var(--line)}
.tl .it{position:relative;padding:0 0 14px}
.tl .it:last-child{padding-bottom:0}
.tl .it:before{content:"";position:absolute;left:-19px;top:5px;width:9px;height:9px;border-radius:50%;background:var(--panel);border:2px solid var(--tx3)}
.tl .it.al:before{border-color:var(--wa)}.tl .it.er:before{border-color:var(--er)}
.tl .tt{font-size:13.5px}.tl .tm{font-size:12.5px;color:var(--tx3);font-variant-numeric:tabular-nums}
.sites{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}
.site{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:14px;cursor:pointer}
.site:hover{border-color:#33333A;background:var(--panel2)}
.site .hd{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.site .ini{width:31px;height:31px;font-size:12px}
.site .mt{display:flex;gap:16px;font-size:12.5px;color:var(--tx3);margin-top:10px}
.site .mt b{color:var(--tx);font-weight:500;font-variant-numeric:tabular-nums}
@media(max-width:1080px){
  .two,.three{grid-template-columns:1fr}
  #app.on{grid-template-columns:62px 1fr}
  .navgrp>span,.nav span:not(.cnt){display:none}
  /* Het logo is één stuk en gaat niet in een zijbalk van 62px: op de 46px die
     overblijft is het 8px hoog en dan is het een vlekje. Het merk komt terug zodra
     de zijbalk weer breed genoeg is; de sitewisselaar was in deze breedte toch al
     weg, dus de hele kop verdwijnt en de menu-iconen beginnen bovenaan. */
  .stop{display:none}
  .navgrp:first-child{padding-top:17px}
  .nav{justify-content:center}
  /* Het aantal verdwijnt hier: naast een icoon van 16px ging het zwevend naast de
     rand hangen en las het als los cijfer. Het staat nog in de titel en het
     aria-label, dus voor toetsenbord en schermlezer gaat er niets verloren. */
  .nav .cnt{display:none}
  .navgrp{padding:13px 6px 0}
}
@media(max-width:760px){#login{grid-template-columns:1fr}.brand{display:none}}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* ------------------------------------------------------------------
   Toevoegingen op de mockup (frontend-doc §7). De variabelen en
   componentklassen hierboven zijn ongewijzigd; hieronder alleen wat de
   mockup nog niet had: laden, leeg, fout en een enkel formulierdetail.
   ------------------------------------------------------------------ */

/* Laden. Een tabel die op data wacht laat de vorm zien, geen leeg vlak. */
.skel{display:block;height:11px;border-radius:3px;background:linear-gradient(90deg,var(--row) 25%,var(--rowhi) 37%,var(--row) 63%);background-size:400% 100%;animation:sk 1.3s ease infinite}
@keyframes sk{0%{background-position:100% 50%}100%{background-position:0 50%}}
.skel.w1{width:34%}.skel.w2{width:58%}.skel.w3{width:76%}
.loading{display:flex;align-items:center;gap:9px;color:var(--tx3);font-size:13px;padding:15px}
.loading i{animation:sp 1s linear infinite;font-size:16px}
@keyframes sp{to{transform:rotate(360deg)}}

/* Leeg. Een nieuwe site zonder devices is geen fout, dus geen rode tekst. */
.empty{padding:34px 22px;text-align:center;color:var(--tx3)}
.empty i{font-size:26px;color:var(--tx3);display:block;margin-bottom:9px}
.empty b{display:block;color:var(--tx2);font-weight:500;font-size:13.5px;margin-bottom:3px}
.empty p{margin:0 auto;max-width:44ch;font-size:13px}
.empty .btn{margin-top:14px}

/* Fout. Bovenaan de pagina, blijft staan tot het gelukt is. */
.bar-er{background:var(--er-bg);border:1px solid var(--er-line);border-radius:var(--r);padding:11px 13px;font-size:13.5px;display:flex;gap:11px;align-items:flex-start;margin-bottom:16px}
.bar-er i{font-size:16px;color:var(--er);flex:none;margin-top:1px}
.bar-er .btn{margin-left:auto}

/*
    Formulieren zijn een dialoog, geen paneel in de pagina.

    Ze schoven eerst als kaart bóven de paginatitel: je klikte rechtsboven op
    "Groep toevoegen" en de hele pagina schoof naar beneden, met één invoerveld
    uitgerekt over 860 px en een schakelaar 1400 px van zijn label. Nu staat het
    formulier boven de pagina, op de breedte die bij het aantal velden past.
*/
/*
    Een bevestiging staat bóven de dialoog waarin je op de knop drukte: annuleren betekent "ik wilde
    dat venster nog". Zelfde vorm, één laag hoger, en een iets diepere waas zodat je ziet dat er iets
    overheen staat.
*/
#dialoogwaas,#dialoogwaas-boven{position:fixed;inset:0;z-index:60;background:rgba(6,6,7,.66);
  display:flex;align-items:flex-start;justify-content:center;padding:48px 22px;overflow-y:auto;
  animation:dw .12s ease}
@keyframes dw{from{opacity:0}to{opacity:1}}
/* De bovenste laag: één hoger, en een iets lichtere waas zodat de dialoog eronder zichtbaar blijft
   staan. Deze regel staat ná de gedeelde regel, anders wint z-index 60 alsnog. */
#dialoogwaas-boven{z-index:61;background:rgba(6,6,7,.45)}
/*
    Binnenkomen met een ease-out en niet met de ingebouwde `ease`: een element dat verschijnt
    hoort meteen te bewegen, want dat is het moment waarop je kijkt. De ingebouwde curves
    beginnen te traag en dan voelt 160 ms langzamer dan het is.

    Geen scale(0) maar een verschuiving van 8 px met opacity: niets in het echt verschijnt uit
    het niets. Het middelpunt blijft het middelpunt — een dialoog hangt niet aan een knop maar
    staat midden op het scherm, dus transform-origin hoort hier niet verlegd te worden.
*/
/*
    De dialoog is een kolom: kop vast, inhoud scrollt, voet vast.

    Eerst plakte de voet met `position: sticky`. Dat hield de knop wel in beeld, maar de inhoud
    schoof eronder door — en dan kun je een vinkje aanzetten dat half achter de opslaanknop
    ligt. Een knop die over je formulier heen hangt is geen oplossing maar een tweede probleem.

    Nu heeft de dialoog een hoogte die op het scherm past en scrollt alleen het middenstuk. De
    voet is weer een gewone voet: hij staat onderaan de dialoog, niet erbovenop, en er ligt
    nooit iets onder. Dat is ook waarom de waas eromheen niet meer hoeft te scrollen.
*/
.dialoog{width:100%;max-width:520px;background:var(--panel);border:1px solid var(--line);
  border-radius:10px;box-shadow:0 18px 48px rgba(0,0,0,.55);
  animation:dz .16s cubic-bezier(.23,1,.32,1);
  display:flex;flex-direction:column;max-height:calc(100vh - 96px)}
/*
    Een brede dialoog is 960px en niet 860px. Reden: op het instellingenscherm staat rechts een
    waardeveld van 320px met een Weg-knop erachter, en dan blijft er links te weinig over voor een
    keuzelijst die "Distributiecentrum — labels aan een order koppelen" heet. Die kapte af, en juist
    de gekozen waarde is wat je wil kunnen lezen (Ward, 6 augustus 2026). Boven 1040px viewport past
    dit; daaronder krimpt hij mee met width:100%.
*/
.dialoog-breed{max-width:960px}
@keyframes dz{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
.dialoog>header{flex:0 0 auto;padding:14px 17px;border-bottom:1px solid var(--linesoft);display:flex;
  align-items:center;gap:10px}
.dialoog>header h3{flex:1;font-size:15px}
/* Het enige deel dat schuift. overscroll-behavior houdt het scrollen binnen de dialoog:
   aan het einde van de lijst gaat de pagina eronder niet ineens mee. */
.dialoog .in{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:17px}
/* Twee kolommen velden, maar alleen als er genoeg velden zijn (zie formulier()). */
.dialoog .velden{display:grid;gap:0 18px}
.dialoog-breed .velden{grid-template-columns:1fr 1fr}
.dialoog .velden .breed{grid-column:1 / -1}
/* Vast onderaan de kolom. Geen sticky: er ligt nooit inhoud onder, dus hij hoeft nergens
   overheen te hangen. Zie de uitleg bij .dialoog. */
.dialoog .voet{flex:0 0 auto;display:flex;gap:8px;align-items:center;padding:13px 17px;
  border-top:1px solid var(--linesoft);background:var(--panel2);border-radius:0 0 10px 10px}
.dialoog .voet .rechts{margin-left:auto;display:flex;gap:8px}

/* Eigen vinkje. Het browservinkje kwam in Chrome-blauw op een donker paneel binnen. */
.vink{display:flex;align-items:center;gap:8px;cursor:pointer;font-size:13px;color:var(--tx);margin:0}
.vink input{position:absolute;width:1px;height:1px;opacity:0}
/* 5px is de chip-radius uit DESIGN.md; een eigen waarde erbij verzinnen voor één doosje
   maakt de reeks radii onbetrouwbaar. */
.vink .doos{width:17px;height:17px;border-radius:5px;border:1px solid var(--line-ctl);
  background:var(--bg);flex:none;display:grid;place-items:center;color:transparent;font-size:12px}
.vink input:checked+.doos{background:var(--ac);border-color:var(--ac);color:#17120A}
.vink input:focus-visible+.doos{outline:2px solid var(--ac);outline-offset:2px}

/*
    De instellingen van een devicegroep: twee kolommen instellingen, en binnen een
    instelling de naam met uitleg links en de bediening rechts op een vaste breedte.

    Ze stonden als .row-s in de smalle kolom van een .two: labels over drie regels, elk
    waardeveld op een andere plek. Dit is het enige scherm waar het zendvermogen van een
    hele groep scanners wordt gezet; dan moet je kunnen zien wat je verandert.
*/
/* Velden met de knop die erbij hoort op één regel; de knop lijnt uit op de velden en
   niet op hun labels, vandaar de eigen uitlijning van de laatste kolom. */
.kopvelden{display:grid;grid-template-columns:1.2fr 1fr 1fr auto;gap:12px;align-items:end}
.kopvelden>div:last-child{padding-bottom:2px}
@media(max-width:1080px){.kopvelden{grid-template-columns:1fr 1fr}}

.insts{display:grid;grid-template-columns:1fr 1fr;gap:0 30px}
.inst{display:grid;grid-template-columns:1fr 184px;gap:3px 14px;align-items:center;
  padding:12px 0;border-bottom:1px solid var(--linesoft);min-width:0}
.inst>.tx{min-width:0}
.inst>.tx .t{font-size:13.5px}
.inst>.tx .d{font-size:12px;color:var(--tx3);line-height:1.45}
/* Bediening links uitgelijnd in een kolom van vaste breedte: dan begint elk waardeveld
   op dezelfde plek en staat de eenheid er netjes achter in plaats van eronder. */
.inst>.bediening{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  font-size:12px;color:var(--tx3)}
.inst>.bediening input.val{width:92px;min-width:92px;text-align:right}
/* Een adres of een naam heeft de volle celbreedte nodig; 168px leest niet. */
.inst-breed{grid-template-columns:1fr}
.inst-breed>.bediening input.val{flex:1 1 0;width:auto;min-width:0;max-width:none;text-align:left}
/* Een keuzelijst krijgt dezelfde volle breedte, maar moet kunnen krimpen: staat er een knop naast,
   dan viel die anders op een eigen regel onder de lijst. */
.inst-breed>.bediening select.val{width:auto;flex:1 1 0;min-width:0}
/* De knop om een sleutel weg te halen: naast het veld en niet eronder. Zonder deze regels viel
   hij in de smalle kolom (184px) op een eigen regel, en dan lijkt hij bij de vólgende instelling
   te horen. Vandaar ook een pictogram in plaats van het woord "Weg": naast een veld, een eenheid
   en een knop is 184px te krap voor nog een woord. flex:0 0 auto houdt de knop heel; het veld
   krimpt een paar pixels. */
.inst>.bediening>[data-grweg],.inst>.bediening>.inst-wegknop{flex:0 0 auto;margin-left:auto}
.inst>.bediening>[data-grweg]{padding:0 7px}
.inst-weg:not(.inst-breed)>.bediening input.val{width:78px;min-width:0}
/* De lijst met vinkjes staat onder elkaar en niet op één regel met de eenheid. */
.inst>.bediening>[data-lijst]{width:100%}
.instkop{display:flex;align-items:baseline;gap:9px;margin:20px 0 2px;grid-column:1 / -1}
.instkop .t{font-size:12.5px;color:var(--tx2);font-weight:500}
.instkop .d{font-size:12px;color:var(--tx3)}
@media(max-width:1080px){.insts{grid-template-columns:1fr}}
/*
    Instellingen in de groepdialoog staan onder elkaar en niet in twee kolommen.

    Twee kolommen werkt in een paneel over de volle breedte; in een dialoog blijft er per kolom
    ~200px over voor naam én uitleg, en dan wordt een uitleg van twee regels een kolom van tien.
    Dat was precies wat er misstond: "de layout klopt niet". Eén kolom geeft de uitleg de ruimte
    en houdt het waardeveld rechts uitgelijnd op dezelfde plek.
*/
.insts-lijst{grid-template-columns:1fr}
/*
    Ook in één kolom blijft het waardeveld rechts staan, op twee breedtes: 184px voor een getal of
    een schakelaar, 320px voor een keuzelijst of een tekst. Een keuzelijst met twee opties over de
    volle 780px oogt als een zoekveld, en dan is niet te zien welke kolom de waarde is.
*/
/*
    Eén kolom voor de waarde, en elk veld begint op dezelfde plek — een getal, een keuzelijst en een
    schakelaar allemaal op dezelfde linkerlijn. Dat was het tweede dat misstond: een 900 op 1019px,
    een keuzelijst op 881 en een schakelaar helemaal rechts, en dan "lijkt het alsof er maar wat
    staat" (Ward, 5 augustus 2026). De breedte van het veld zelf verschilt nog wél: een getal in een
    vak van 320px suggereert dat er een zin in past.
*/
/*
    De waardekolom is breed genoeg voor het veld én de knop ernaast: 320px veld plus de Weg-knop.
    Die knop viel eerst op een eigen regel onder het veld — flex-wrap deed zijn werk in een kolom
    die te smal was — en dan lijkt hij bij de vólgende instelling te horen.
*/
.insts-lijst .inst,
.insts-lijst .inst-breed{grid-template-columns:1fr minmax(320px, 490px)}
.insts-lijst .inst>.bediening{flex-wrap:nowrap}
.insts-lijst .inst>.bediening{justify-content:flex-start}
.insts-lijst .inst>.bediening input.val{width:104px;min-width:104px}
.insts-lijst .inst-breed>.bediening input.val{flex:1 1 320px;width:auto;min-width:0;max-width:320px}
/*
    Een keuzelijst mag de hele kolom hebben. Een tekstveld niet: dat is een invoerveld en 320px
    leest prettig. Bij een keuzelijst gaat het om wat er ín staat — "Distributiecentrum — labels aan
    een order koppelen" kapte af op 320px, en dan staat er precies niet wat je wilde controleren.
*/
.insts-lijst .inst>.bediening select.val{flex:1 1 auto;width:auto;min-width:0;max-width:none}
/* De knop houdt zijn maat; het veld geeft mee. Andersom kapt de knoptekst af. */
.insts-lijst .inst>.bediening>.inst-wegknop{flex:0 0 auto}
/*
    "Twee groepen wijken hiervan af." Amber, want het gaat over jouw handeling: wat je hier zet
    komt bij die toestellen niet aan. Geen pil en geen icoon — het is een voetnoot bij de uitleg,
    geen tweede status naast de pil op de naamregel.
*/
.afwijking{color:var(--wa)}

/* De knop om terug te zetten of weg te halen blijft aan het einde van de kolom staan. */
.insts-lijst .inst>.bediening>[data-volg],
.insts-lijst .inst>.bediening>[data-grweg],
.insts-lijst .inst>.bediening>.inst-wegknop{margin-left:auto}
/*
    Een instellingenlijst in een dialoog mag rustiger staan.

    Ward, 5 augustus 2026, over de standaardinstellingen van een applicatie: *"ik wil dat je
    duidelijk en meer spacing gebruikt, nu zit standaard en globaal direct naast elkaar, en de knop
    weg valt niet op"*. Drie dingen dus: meer lucht per regel, en verderop in dit blok een Weg-knop
    die eruitziet als iets wat iets weghaalt.
*/
.insts-lijst .inst{padding:15px 0;gap:5px 14px}
.insts-lijst .inst>.tx .t{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.insts-lijst .inst>.tx .d{margin-top:1px}
/*
    De knop die een instelling weghaalt: woord én pictogram, in de kleur van iets onomkeerbaars.

    Hij was een grijs knopje met "Weg" erin, en in een rij met een veld en een pil zag je hem niet.
    Rode tekst op een rode rand van 35% is dezelfde vorm als "Uitrol annuleren" en "Verwijderen" bij
    een sitelogo — één taal voor "dit haalt iets weg". De vulling blijft leeg: een volledig rode knop
    zou het zwaarste element op het scherm zijn en het is niet de hoofdactie.
*/
.inst-wegknop{color:var(--er);border-color:var(--er-line)}
.inst-wegknop:hover{color:var(--er);border-color:var(--er);background:rgba(216,115,107,.10)}
/* In de lijstvariant is er ruimte, dus het veld hoeft niet te krimpen voor een knop. */
.insts-lijst .inst-weg:not(.inst-breed)>.bediening input.val{width:104px;min-width:104px}

/*
    De tekst in een bevestigingsdialoog. Iets groter dan gewone tekst en met ruimte eronder: dit is
    de enige inhoud van dat venster, en je leest hem op het moment dat je iets onomkeerbaars doet.
*/
.bevestig{font-size:14px;line-height:1.55;color:var(--tx)}
.bevestig b{font-weight:500}
.bevestig .er{color:var(--er)}
/*
    Een hoofdknop die iets weghaalt. Zelfde vorm als de primaire knop — het is de hoofdactie van dat
    venster — maar rood in plaats van amber, zodat "Verwijderen" er niet uitziet als "Opslaan".
*/
.btn-gevaar{background:var(--er);border-color:var(--er);color:#17120A;font-weight:500}
.btn-gevaar:hover{background:#E59B95;border-color:#E59B95}

/* Melding na een actie. Verdwijnt zelf; geen knop om weg te klikken. */
#toast{position:fixed;right:20px;bottom:20px;z-index:50;display:flex;flex-direction:column;gap:8px}
#toast div{background:var(--panel2);border:1px solid var(--line);border-radius:var(--r);padding:11px 14px;font-size:13.5px;box-shadow:0 8px 24px rgba(0,0,0,.4);display:flex;gap:9px;align-items:center;animation:ts .2s ease}
#toast div.ok i{color:var(--ok)}#toast div.er i{color:var(--er)}
@keyframes ts{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

/* Verversen. Het bolletje pulseert zolang er een verzoek loopt. */
.stale{color:var(--tx3);font-size:12.5px;display:flex;align-items:center;gap:7px}

/* Instellingen bewerken: het waardeveld naast de sleutel. */
.row-s input.val{width:auto;min-width:140px;max-width:230px;height:31px;font-size:13px;text-align:right}
.row-s .val.mono{font-variant-numeric:tabular-nums}
.kv dd input{height:31px;font-size:13px}
.dirty{color:var(--ac)}

/* Het loginscherm meldt fouten onder de knop, niet in een dialoog. */
#loginerr,#vergetenmelding,#nieuwmelding{margin-top:13px;font-size:13px;color:var(--er);display:none}
#loginerr.on,#vergetenmelding.on,#nieuwmelding.on{display:block}
/* Gelukt is geen fout: dezelfde plek, andere kleur. */
#loginerr.ok,#vergetenmelding.ok,#nieuwmelding.ok{color:var(--tx2)}

/*
    Een tekstknop die als link leest. Op het inlogscherm is "Wachtwoord vergeten?" geen actie
    naast inloggen maar een uitweg eronder, en die hoort niet als tweede knop even zwaar te wegen.
    Het is wel een <button>: er wordt niets genavigeerd, er wordt een formulier gewisseld.
*/
.lnk{background:none;border:0;padding:0;font:inherit;font-size:13px;color:var(--tx2);
  cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.lnk:hover{color:var(--tx)}
/* 3 px en niet 2: 2 stond in geen enkele schaal van DESIGN.md, 3 wel (de balkjes).
   Op een focusring om lopende tekst is het verschil onzichtbaar, en één waarde minder
   buiten het systeem is er één. */
.lnk:focus-visible{outline:2px solid var(--ac);outline-offset:2px;border-radius:3px}
.fcvoet{margin-top:16px;text-align:center}

/*
    Bediening op slot: de instellingen van een devicegroep voor iemand die ze mag zien maar niet
    mag wijzigen. Niet verbergen — wat een groep voorschrijft is juist wat je wil nakijken als een
    scanner zich vreemd gedraagt. Wel duidelijk maken dat er niets te doen is.

    pointer-events uit is hier genoeg: de server weigert de wijziging toch (Auth/Vereist.cs), dus
    dit is vormgeving en geen slot.
*/
.bediening[data-opslot]{opacity:.55;pointer-events:none}

/*
    Twee wegen naar hetzelfde doel, als kaarten onder elkaar in plaats van twee knoppen naast
    elkaar. Gebruikt bij het regelen van een wachtwoord voor iemand anders: herstellink of zelf
    zetten. Twee knoppen met alleen een label zouden de keuze verzwijgen, en het verschil zit
    juist in het gevolg — bij de een ken je daarna het wachtwoord van een collega, bij de ander
    niet. Dus staat de reden op de kaart.
*/
.keuzeweg{display:flex;flex-direction:column;gap:10px}
.wegkaart{display:flex;flex-direction:column;gap:5px;text-align:left;width:100%;
  padding:14px 15px;background:var(--panel2);border:1px solid var(--line-ctl);border-radius:var(--r);
  cursor:pointer;font-family:var(--f);font-size:14px;color:var(--tx);
  transition:border-color .12s,background .12s}
.wegkaart:hover{border-color:var(--ac);background:var(--rowhi)}
.wegkaart:focus-visible{outline:2px solid var(--ac);outline-offset:2px}
.wegkaart[disabled]{opacity:.55;cursor:default}
.wegkop{display:flex;align-items:center;gap:8px;font-size:13.5px;font-weight:500}
.wegkop .ti{color:var(--tx3)}
.wegtekst{font-size:12.5px;color:var(--tx2);line-height:1.5}

/*
    Een link die je moet doorsturen. Breekt op elk teken af: een herstellink is ruim honderd
    tekens en mag niet buiten de dialoog vallen of horizontaal laten scrollen.
*/
/*
    Een kopje binnen een formulier, en schakelaars in twee kolommen.

    Nodig geworden bij de rechten van een gebruiker: elf schakelaars onder elkaar maken een
    dialoog waar je in moet scrollen om de opslaanknop te vinden, en zonder kopje is "wie is
    dit" niet te scheiden van "wat mag hij".
*/
.veldkop{grid-column:1/-1;display:flex;flex-direction:column;gap:2px;
  margin:20px 0 4px;padding-top:15px;border-top:1px solid var(--linesoft)}
.veldkop b{font-size:13.5px;font-weight:600;letter-spacing:-.01em}
.veldkop span{font-size:12.5px;color:var(--tx2);line-height:1.5}
.veldkop:first-child{margin-top:0;padding-top:0;border-top:0}
.schakelrij{display:grid;grid-template-columns:1fr 1fr;gap:0 26px}
/* Onder 620px past een tweede kolom niet meer; de dialoog is dan zelf de breedte van het venster. */
@media (max-width:620px){.schakelrij{grid-template-columns:1fr}}

/* Een recht dat deze beheerder zelf niet heeft, en dus niet kan weggeven. */
.row-s-opslot{opacity:.5}
.row-s-opslot .tog{cursor:default}

.linkvak{padding:11px 12px;background:var(--bg);border:1px solid var(--line-ctl);
  border-radius:var(--r)}
.linkvak code{font-family:var(--f);font-size:12px;line-height:1.6;color:var(--tx);
  word-break:break-all;user-select:all}

/*
    Per site wat er aan de hand is: één telling per soort, elk een sprong naar de
    devicelijst van die site met dat filter aan. Dit verving acht blokken met sitechips —
    twee lijsten van hetzelfde in een andere sortering, en met twintig sites een scherm
    zonder handeling erin.
*/
.wat{display:flex;flex-wrap:wrap;gap:6px}
.watchip{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;padding:3px 9px;
  border-radius:5px;background:var(--rowhi);color:var(--tx2);text-decoration:none;
  border:1px solid transparent}
.watchip:hover{text-decoration:none;color:var(--tx);border-color:var(--line-hover)}
/* Alleen het bolletje en het getal dragen kleur, niet het hele vlakje. Met een gevulde
   achtergrond per ernst werden twintig rijen één lap rood en amber — "teveel van het
   goede" — en dan valt de site die het écht nodig heeft niet meer op. */
.watchip .bol{width:7px;height:7px;border-radius:50%;flex:none}
.watchip b{font-weight:500;font-variant-numeric:tabular-nums}
.watchip.er .bol{background:var(--er)}
.watchip.er b{color:var(--er)}
.watchip.wa .bol{background:var(--wa)}
.watchip.wa b{color:var(--wa)}
/* De chiprij is een flexvlak en geen tekstregel: .cel .a zet nowrap met een ellips, en
   dan zag je vier soorten en een puntje in plaats van alle soorten. */
.cel .a.wat{display:flex;white-space:normal;overflow:visible;text-overflow:clip}

/*
    Het vinkje "globaal" bij een instelling in het applicatiescherm.

    Onder de naam en de uitleg, niet ernaast: de bediening rechts is het waardeveld, en een
    vinkje daartussen leest als een tweede waarde. Hier hoort het bij de beschrijving, want dat
    is wat het is — een eigenschap van de sleutel en niet van zijn waarde.
*/
.glob{display:inline-flex;align-items:center;gap:7px;margin-top:6px;cursor:pointer;
  font-size:12.5px;color:var(--tx2)}
.glob input{width:15px;height:15px;margin:0;accent-color:var(--ac);cursor:pointer}
.glob span{user-select:none}
