/*
 * ITdocu.
 *
 * ── Waar het ontwerp vandaan komt ────────────────────────────────────────────
 *
 * Dit systeem stelt één vraag: klopt dit nog? Apparatuur in een rack antwoordt
 * die vraag met een lampje -- groen is goed, oranje vraagt aandacht, rood is
 * stuk, donker is uit. Dat is de taal die deze schermen spreken.
 *
 * Daarom:
 *
 *   De zijbalk is een **rackpaneel**: donker, met fijne scheidingslijnen zoals
 *   tussen units, en per regel een lampje in plaats van een pictogram.
 *
 *   Elke rij in een lijst heeft links een **statusstreep** met dezelfde drie
 *   kleuren. Je leest een lijst van vijftig onderdelen dan op kleur en niet op
 *   tekst -- en dat is precies hoe je naar een rack kijkt.
 *
 *   Getallen die iets betekenen -- IP-adressen, serienummers, poorten -- staan
 *   in een **mono met tabelcijfers**. Een IP-adres in een proportioneel
 *   lettertype is een woord; in mono is het een adres dat je kunt vergelijken.
 *
 * De drie signaalkleuren zijn er alléén voor status. Niet voor knoppen, niet
 * voor koppen, niet voor accenten -- want dan betekenen ze niets meer. Dat is
 * de enige regel in dit bestand die je niet mag buigen.
 *
 * Archivo voor de tekst (iets vierkant, industrieel, leest goed klein) en
 * IBM Plex Mono voor gegevens. Bewust niet de gebruikelijke keuzes: dit hoort
 * eruit te zien als gereedschap, niet als een dashboard.
 */

/* De lettertypes worden in index.html geladen: een @import hier zou het
 * tekenen van de pagina ophouden tot het stylesheet binnen is. */

:root {
  /* ── Grond en oppervlak ──
   *
   * Warm en niet zwart. Een bijna-zwart paneel is streng: het leest als een
   * terminal, en dit is een scherm waar iemand een hele dag naar kijkt. Een
   * diep indigo doet hetzelfde werk -- de lampjes komen eruit, tekst blijft
   * leesbaar -- maar het is niet hard.
   *
   * De vloer is een warm gebroken wit en geen koel grijs. Dat verschil van een
   * paar procent geel is precies wat een scherm van "netjes" naar "aangenaam"
   * brengt, en het valt niemand op. Dat is de bedoeling.
   */
  --grond:      #F4F2EE;
  --vlak:       #FFFFFF;
  --paneel:     #33414C;   /* gedempt leisteen */
  --paneel-op:  #43535F;   /* de gemerkte unit, en de knop bij aanwijzen */
  --paneel-lijn:rgba(238, 243, 245, .13);
  --paneel-tekst: #EEF3F5;
  --paneel-poort: #4A5B68; /* een poort die bestaat */
  --paneel-gat:   #1E2831; /* een poort waar niets van bekend is */

  /* ── Inkt ── */
  --inkt:       #1F2A31;
  --inkt-zacht: #41525E;
  --stil:       #667681;
  --flauw:      #9AA7B0;

  /* ── Lijnen ── */
  --lijn:       #E0DCD5;
  --lijn-fijn:  #EDEAE4;
  --hover:      #FAF8F5;

  /* ── De drie lampjes. Alleen voor status. ──
   *
   * Iets warmer dan de gebruikelijke signaalkleuren, zodat ze bij het indigo
   * horen in plaats van erop te liggen. Ze blijven wel signaal: dit zijn de
   * enige drie kleuren in het hele bestand die iets betekenen.
   */
  --led-goed:   #34C07A;
  --led-let:    #EFA02E;
  --led-fout:   #E85C50;
  --led-uit:    #C6C1D0;

  --goed-vlak:  #E8F7EF;
  --goed-inkt:  #16704A;
  --goed-lijn:  #BFE7D2;
  --let-vlak:   #FDF3E4;
  --let-inkt:   #8A5A12;
  --let-lijn:   #F4DEBC;
  --fout-vlak:  #FCECEA;
  --fout-inkt:  #A63A31;
  --fout-lijn:  #F5CDC9;

  /* ── Het merk. Nergens als status. ── */
  --merk:       #2FA8A0;

  /* ── Wat omklapt bij een donkere stand ──
   *
   * Een knop gebruikte --inkt als achtergrond met witte tekst erop. In het
   * donker is --inkt bijna wit, en dan staat er witte tekst op een witte knop.
   * Vandaar eigen tokens: de kleur van een knop is niet de kleur van tekst, ook
   * al zijn ze in de lichte stand hetzelfde.
   */
  --knop-vlak:  #1F2A31;
  --knop-tekst: #FFFFFF;
  --gekozen-vlak: #33414C;
  --gekozen-tekst: #EEF3F5;
  --gekozen-naam: rgba(238, 243, 245, .62);
  --gekozen-lijn: #1F2A31;

  /* De tinten van de tegels in de lichte stand: pastel vlak, donkere letter.
     De kleurtoon zelf staat per soort bij .t-* -- zie de uitleg daar. */
  --tint-vs: 42%; --tint-vl: 87%; --tint-is: 45%; --tint-il: 27%;
  --uit-vlak:   #F1F0EE;   /* de grijze stand van een uitgefaseerd onderdeel */
  --zoekkop:    #FBFAF8;   /* de kop van een tabel */
  /* De balk boven het werkvlak. Doorschijnend, want er zit blur achter: hij
     hoort te laten zien dat er iets onder hem doorschuift. */
  --balk:       rgba(239, 242, 241, .9);

  --rond: 11px;
  --schaduw: 0 1px 2px rgba(31, 42, 49, .05), 0 6px 18px rgba(31, 42, 49, .06);
}

/*
 * ── De donkere stand ──
 *
 * Drie standen en niet twee: licht, donker, en "volg het toestel". Die derde is
 * de standaard, want iemand die zijn Mac 's avonds op donker zet, bedoelt dat
 * ook hier.
 *
 * Vandaar tweemaal dezelfde lijst. De eerste geldt als het toestel op donker
 * staat en er hier niets is gekozen -- `:not([data-thema="licht"])` zorgt dat
 * een uitdrukkelijke keuze voor licht die van het toestel verslaat. De tweede
 * geldt als hier donker is gekozen, ongeacht wat het toestel doet.
 *
 * Dat kan met `light-dark()` in één lijst, maar dan valt de pagina in een
 * oudere browser terug op géén kleur in plaats van op de lichte stand. Twee
 * blokken die uit elkaar kunnen lopen is een risico dat ik kan overzien; een
 * onleesbare pagina bij een klant is dat niet.
 *
 * Alleen de tokens staan hier. Geen enkele regel hieronder in dit bestand mag
 * een kleur rechtstreeks zetten -- dat is de afspraak die maakt dat dit werkt.
 */
@media (prefers-color-scheme: dark) {
  :root:not([data-thema="licht"]) {
  /* Grond en oppervlak */
  --grond:      #14191D;
  --vlak:       #1D242A;
  --hover:      #252E35;
  --paneel:     #0E1317;
  --paneel-op:  #1B242B;
  --paneel-lijn:rgba(238, 243, 245, .10);
  --paneel-poort: #2C3841;
  --paneel-gat:   #080C0F;

  /* Inkt. Niet zuiver wit: 100% wit op een donkere grond geeft een harde
     rand om elke letter, en daar ga je van knijpen. */
  --inkt:       #E4E9EC;
  --inkt-zacht: #BDC7CD;
  --stil:       #8D9AA3;
  --flauw:      #66727B;

  /* Lijnen */
  --lijn:       #303A42;
  --lijn-fijn:  #262E35;

  /* De lampjes blijven wat ze zijn: dit zijn de enige kleuren met een
     betekenis, en die betekenis verandert niet met de stand van het licht.
     Alleen "uit" mag lichter, anders verdwijnt hij in de grond. */
  --led-uit:    #4E5A63;

  /* De meldingsvlakken: een donkere tint van dezelfde kleur, met lichte
     letters erop. Niet de lichte vlakken laten staan -- dat geeft drie
     lichtbakken midden op een donker scherm. */
  --goed-vlak:  #12301F;
  --goed-inkt:  #79D8A2;
  --goed-lijn:  #1E4A31;
  --let-vlak:   #322510;
  --let-inkt:   #EEBE76;
  --let-lijn:   #4C3915;
  --fout-vlak:  #351B18;
  --fout-inkt:  #F1A29A;
  --fout-lijn:  #4E2723;

  /* Het merk iets lichter: #2FA8A0 op een donkere grond is net te gedempt om
     als aanwijzing te werken. */
  --merk:       #3BBDB4;

  --knop-vlak:  #E4E9EC;
  --knop-tekst: #14191D;

  /* De tinten van de tegels: dezelfde kleurtonen, vlak diep en letter licht. */
  --tint-vs: 30%; --tint-vl: 18%; --tint-is: 42%; --tint-il: 70%;
  --gekozen-vlak: #313C45;
  --gekozen-tekst: #F2F6F8;
  --gekozen-naam: rgba(242, 246, 248, .70);
  --gekozen-lijn: #5A6A76;
  --uit-vlak:   #22292F;
  --zoekkop:    #171D22;
  --balk:       rgba(20, 25, 29, .86);

  /* Een schaduw doet in het donker niets; een dunne lichte bovenrand doet wat
     een schaduw in het licht doet -- zeggen dat iets bovenop iets anders ligt. */
  --schaduw: 0 1px 2px rgba(0, 0, 0, .5), 0 6px 18px rgba(0, 0, 0, .35);
  }
}

:root[data-thema="donker"] {
  /* Grond en oppervlak */
  --grond:      #14191D;
  --vlak:       #1D242A;
  --hover:      #252E35;
  --paneel:     #0E1317;
  --paneel-op:  #1B242B;
  --paneel-lijn:rgba(238, 243, 245, .10);
  --paneel-poort: #2C3841;
  --paneel-gat:   #080C0F;

  /* Inkt. Niet zuiver wit: 100% wit op een donkere grond geeft een harde
     rand om elke letter, en daar ga je van knijpen. */
  --inkt:       #E4E9EC;
  --inkt-zacht: #BDC7CD;
  --stil:       #8D9AA3;
  --flauw:      #66727B;

  /* Lijnen */
  --lijn:       #303A42;
  --lijn-fijn:  #262E35;

  /* De lampjes blijven wat ze zijn: dit zijn de enige kleuren met een
     betekenis, en die betekenis verandert niet met de stand van het licht.
     Alleen "uit" mag lichter, anders verdwijnt hij in de grond. */
  --led-uit:    #4E5A63;

  /* De meldingsvlakken: een donkere tint van dezelfde kleur, met lichte
     letters erop. Niet de lichte vlakken laten staan -- dat geeft drie
     lichtbakken midden op een donker scherm. */
  --goed-vlak:  #12301F;
  --goed-inkt:  #79D8A2;
  --goed-lijn:  #1E4A31;
  --let-vlak:   #322510;
  --let-inkt:   #EEBE76;
  --let-lijn:   #4C3915;
  --fout-vlak:  #351B18;
  --fout-inkt:  #F1A29A;
  --fout-lijn:  #4E2723;

  /* Het merk iets lichter: #2FA8A0 op een donkere grond is net te gedempt om
     als aanwijzing te werken. */
  --merk:       #3BBDB4;

  --knop-vlak:  #E4E9EC;
  --knop-tekst: #14191D;

  /* De tinten van de tegels: dezelfde kleurtonen, vlak diep en letter licht. */
  --tint-vs: 30%; --tint-vl: 18%; --tint-is: 42%; --tint-il: 70%;
  --gekozen-vlak: #313C45;
  --gekozen-tekst: #F2F6F8;
  --gekozen-naam: rgba(242, 246, 248, .70);
  --gekozen-lijn: #5A6A76;
  --uit-vlak:   #22292F;
  --zoekkop:    #171D22;
  --balk:       rgba(20, 25, 29, .86);

  /* Een schaduw doet in het donker niets; een dunne lichte bovenrand doet wat
     een schaduw in het licht doet -- zeggen dat iets bovenop iets anders ligt. */
  --schaduw: 0 1px 2px rgba(0, 0, 0, .5), 0 6px 18px rgba(0, 0, 0, .35);
}

/* De browser laten weten wat we kunnen, zodat de rolbalken en de invoervelden
 * meegaan. Zonder dit blijft een tekstvak wit in een donkere pagina. */
:root { color-scheme: light; }
:root[data-thema="donker"] { color-scheme: dark; }
@media (prefers-color-scheme: dark) {
  :root:not([data-thema="licht"]) { color-scheme: dark; }
}

* { box-sizing: border-box; }
html, body { height: 100%; }

body {
  margin: 0;
  font-family: Archivo, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 14.5px; line-height: 1.5;
  color: var(--inkt); background: var(--grond);
  -webkit-font-smoothing: antialiased;
  font-feature-settings: "ss01";
}

.mono, .num, code, kbd {
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-variant-numeric: tabular-nums;
}

a { color: var(--inkt); }
.wacht { padding: 60px; text-align: center; color: var(--stil); }

/* ── De indeling ─────────────────────────────────────────────────────────────
 *
 * Welke kant het menu op staat, staat hier -- en alleen hier. In de html staat
 * het werkvlak eerst en het menu daarna; met een grid maakt die volgorde niets
 * uit. Omdraaien is deze drie regels en niets in de JavaScript.
 */

.raam { display: grid; grid-template-columns: 248px 1fr; min-height: 100vh; align-items: start; }
.zij      { grid-column: 1; grid-row: 1; }
.werkkant { grid-column: 2; grid-row: 1; min-width: 0; }

/* ── Het rackpaneel ─────────────────────────────────────────────────────── */

.zij {
  background: var(--paneel); color: var(--paneel-tekst);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
  /* Een haarlijn licht bovenaan, zoals de bovenrand van een paneel dat licht
   * vangt. Zonder zo'n rand is een donker vlak een gat in het scherm. */
  box-shadow: inset -1px 0 0 rgba(0, 0, 0, .3), inset 0 1px 0 rgba(238, 243, 245, .07);
}

.zij .merk { display: flex; align-items: center; gap: 11px; padding: 19px 18px 17px;
             cursor: pointer; background: none; border: 0; color: inherit;
             font: inherit; text-align: left; border-bottom: 1px solid var(--paneel-lijn); }
.zij .merk img { width: 30px; height: 30px; display: block; }
.zij .merk b { font-size: 18.5px; letter-spacing: -.35px; font-weight: 700; }
.zij .merk b span { font-weight: 400; opacity: .62; }

.zij nav { padding: 6px 0; display: flex; flex-direction: column; }
.zij .kopje { padding: 16px 20px 7px; font-size: 10px; text-transform: uppercase;
              letter-spacing: 1.4px; color: rgba(238, 243, 245, .38); font-weight: 600; }

/*
 * Elk menu-item is een unit in het rack: een lampje links, de naam, en rechts
 * het aantal. De fijne lijn eronder is de naad tussen twee units.
 */
.zij nav button {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 11px 20px; border: 0; border-radius: 0; cursor: pointer;
  background: none; color: rgba(238, 243, 245, .78);
  font: inherit; font-size: 14.5px; position: relative;
}
.zij nav button::after {
  content: ''; position: absolute; left: 20px; right: 20px; bottom: 0;
  border-bottom: 1px solid var(--paneel-lijn);
}
.zij nav button:hover { background: rgba(238, 243, 245, .05); color: #fff; }

/* De actieve unit: lichter, en met een streep aan de kant waar het paneel
 * begint -- zoals de gemerkte unit in een rack. */
.zij nav button.aan {
  background: var(--paneel-op); color: #fff; font-weight: 600;
  box-shadow: inset 3px 0 0 var(--merk);
}

/*
 * Het teken vóór de naam.
 *
 * Vaste breedte en gecentreerd, en dat is de hele reden dat deze regel bestaat.
 * De tekens komen uit verschillende hoeken van de tekenset -- ▤ is een blok, ⌫
 * een pijl, ⚿ een sleutel, ⚙ een tandwiel -- en die zijn allemaal net anders
 * breed: gemeten liep dat van 8,7 tot 14,5 pixels. Zonder vaste breedte begint
 * elke naam dus op een andere plek, met bijna zes pixels verschil tussen de
 * eerste en de laatste. Dat is te weinig om aan te wijzen en genoeg om te zien
 * dat de lijst scheef hangt.
 *
 * Een vaste regelhoogte hoort erbij: deze tekens hebben ook verschillende
 * hoogtes, en zonder line-height zakt de naam per regel een pixel mee.
 */
.zij nav .teken {
  flex: 0 0 18px; width: 18px;
  text-align: center; font-size: 14px; line-height: 1;
  color: rgba(238, 243, 245, .45);
  /* Sommige van deze tekens hebben een emoji-variant; die zou als plaatje in
     kleur verschijnen en dan is hij weer een andere breedte. */
  font-variant-emoji: text;
}
.zij nav button:hover .teken { color: rgba(238, 243, 245, .8); }
.zij nav button.aan .teken { color: var(--merk); }
.zij nav button.let .teken { color: var(--led-let); }

.zij nav .led { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 7px;
                background: var(--led-uit); box-shadow: 0 0 0 0 transparent; }
.zij nav button.aan .led { background: var(--merk); box-shadow: 0 0 8px rgba(47, 168, 160, .7); }
.zij nav button.let .led { background: var(--led-let); box-shadow: 0 0 8px rgba(239, 160, 46, .65); }

.zij nav .aantal { margin-left: auto; font-family: "IBM Plex Mono", monospace;
                   font-size: 12px; font-variant-numeric: tabular-nums;
                   color: rgba(238, 243, 245, .45); }
.zij nav button.let .aantal { color: var(--led-let); font-weight: 500; }

.zij .onder { margin-top: auto; padding: 15px 20px 18px; border-top: 1px solid var(--paneel-lijn); }
.zij .onder b { display: block; font-size: 14px; }
.zij .onder .rol { display: block; font-size: 11px; text-transform: uppercase;
                   letter-spacing: 1px; color: rgba(238, 243, 245, .42); margin-top: 1px; }
/* Afmelden en de stand van het licht naast elkaar: twee dingen die je zelden
 * doet, en dan hoort de een de ander niet naar beneden te duwen. */
.zij .onderrij { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.zij .onder button { display: block; margin-top: 11px; background: none; border: 0; padding: 0;
                     cursor: pointer; color: rgba(238, 243, 245, .55); font: inherit;
                     font-size: 12.5px; text-align: left; }
.themaknop { display: inline-flex !important; align-items: center; gap: 6px; }
/* Het teken iets groter en met een vaste breedte: zon, maan en halve maan zijn
 * niet even breed, en dan verspringt het woord ernaast bij elke klik. */
.themaknop .teken { font-size: 13px; width: 1.1em; text-align: center; }
.zij .onder button:hover { color: var(--paneel-tekst); }
/* De uitgave. Klein, in mono, en altijd op dezelfde plek -- dan kun je iemand
 * vragen "wat staat er linksonder" zonder uit te leggen waar hij moet kijken. */
.zij .onder .uitgave { display: block; margin-top: 12px;
                       font-family: "IBM Plex Mono", monospace; font-size: 10.5px;
                       letter-spacing: .3px; color: rgba(238, 243, 245, .32); }

/* ── De balk boven het werkvlak ─────────────────────────────────────────── */

.werkbalk { position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 12px;
            padding: 13px 28px; background: var(--balk);
            border-bottom: 1px solid var(--lijn); backdrop-filter: blur(10px); }

.zoekvak { flex: 1 1 auto; max-width: 660px; position: relative; }
.zoekvak input { width: 100%; padding: 10px 14px 10px 40px; border: 1px solid var(--lijn);
                 border-radius: 9px; background: var(--vlak); font-size: 15px; }
.zoekvak input::placeholder { color: var(--flauw); }
.zoekvak .loep { position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
                 color: var(--stil); pointer-events: none; font-size: 15px; }
.zoekvak .tip { position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
                font-family: "IBM Plex Mono", monospace; font-size: 11px; color: var(--stil);
                border: 1px solid var(--lijn); border-radius: 5px; padding: 1px 6px;
                pointer-events: none; background: var(--grond); }

.zijknop { display: none; background: none; border: 1px solid var(--lijn); border-radius: 8px;
           padding: 7px 11px; cursor: pointer; font-size: 15px; line-height: 1; color: var(--inkt); }

@media (max-width: 880px) {
  .raam { grid-template-columns: 1fr; }
  .zij, .werkkant { grid-column: 1; }
  .zij { position: fixed; left: 0; top: 0; bottom: 0; width: 248px; z-index: 50;
         height: 100vh; transform: translateX(-100%); transition: transform .18s ease; }
  .zij.open { transform: none; box-shadow: 8px 0 40px rgba(31, 42, 49, .35); }
  .zijknop { display: block; margin-right: auto; order: -1; }
  /* De sneltoets-hint weg: op een aanraakscherm is er geen toetsenbord, en hij
   * ligt over de zoektekst heen. */
  .zoekvak .tip { display: none; }
  .zoekvak input { padding-right: 14px; }
  /* Iets ruimer aan te tikken; een vinger is geen muis. */
  .knop { padding: 11px 16px; }
  .knop.klein { padding: 8px 12px; }
  .zij nav button { padding: 13px 20px; }
}

/* ── Bladzijde ───────────────────────────────────────────────────────────── */

/* In het midden en niet tegen het menu aan geplakt.
 *
 * Er stond alleen een max-width. Op een venster van 1920 is het werkvlak dan
 * 1220 breed met vierhonderdvijftig pixels leegte áán één kant, en dan lijkt
 * de app scheef te hangen. Met `margin: 0 auto` staat die ruimte aan beide
 * kanten en leest het als een bladzijde. */
.blad { max-width: 1220px; margin: 0 auto; padding: 26px 28px 90px; }

h1 { font-size: 26px; font-weight: 700; letter-spacing: -.6px; margin: 0 0 3px; }
h2 { font-size: 10.5px; text-transform: uppercase; letter-spacing: 1.4px;
     color: var(--stil); margin: 30px 0 11px; font-weight: 600;
     display: flex; align-items: center; gap: 10px; }
/* Een lijn die de rest van de breedte vult, zoals een gravure op een paneel. */
h2::after { content: ''; flex: 1 1 auto; border-bottom: 1px solid var(--lijn); }
.sub { color: var(--stil); margin: 0 0 22px; max-width: 82ch; }

.kaart { background: var(--vlak); border: 1px solid var(--lijn); border-radius: var(--rond);
         box-shadow: var(--schaduw); overflow: hidden; }

/* Een kaart met een tabel erin mag opzij schuiven.
 *
 * `overflow: hidden` hierboven is er voor de ronde hoeken, en dat had een
 * bijwerking die je pas ziet op een smaller scherm: een tabel die breder is
 * dan de kaart werd afgekapt, zonder schuifbalk. De kolommen rechts -- bij
 * servers zijn dat "waarvoor" en "nagekeken" -- waren dan niet weg maar
 * ónbereikbaar, en dat is erger, want niets zegt dat er meer is.
 *
 * overflow-x: auto naast overflow-y: hidden mag: de hoeken blijven rond en de
 * tabel schuift. */
.kaart:has(> table) { overflow-x: auto; overflow-y: hidden; }
.kaart + .kaart { margin-top: 14px; }
.leeg { padding: 30px; text-align: center; color: var(--stil); }

/* ── De statusstrook ─────────────────────────────────────────────────────────
 *
 * Het voorpaneel van een rack, samengevat: één blokje per onderdeel, gekleurd
 * naar hoe oud het is. Dit is het eerste wat je ziet en het enige dat je in één
 * oogopslag leest -- of alles groen staat, of er oranje tussen zit.
 */
.strook { display: flex; flex-wrap: wrap; gap: 3px; padding: 16px 18px;
          background: var(--paneel); border-radius: var(--rond); margin-bottom: 20px;
          box-shadow: inset 0 1px 0 rgba(238, 243, 245, .07); }
.strook .blokje { width: 10px; height: 26px; border-radius: 2px; background: var(--led-uit);
                  opacity: .85; }
.strook .blokje.goed { background: var(--led-goed); }
.strook .blokje.let  { background: var(--led-let); }
.strook .blokje.fout { background: var(--led-fout); }
.strook .uitleg { flex: 1 1 100%; display: flex; gap: 18px; margin-top: 12px;
                  font-size: 11.5px; color: rgba(238, 243, 245, .55);
                  text-transform: uppercase; letter-spacing: 1px; }
.strook .uitleg span { display: flex; align-items: center; gap: 6px; }
.strook .uitleg i { width: 8px; height: 8px; border-radius: 2px; display: block; }

/* ── Tabellen ────────────────────────────────────────────────────────────── */

table { width: 100%; border-collapse: collapse; }
th { text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: 1.2px;
     color: var(--stil); font-weight: 600; padding: 11px 14px;
     border-bottom: 1px solid var(--lijn); background: var(--zoekkop); }
td { padding: 12px 14px; border-bottom: 1px solid var(--lijn-fijn); vertical-align: top; }
tr:last-child td { border-bottom: 0; }
tbody tr.klik { cursor: pointer; }
tbody tr.klik:hover { background: var(--hover); }
td.r, th.r { text-align: right; }
/* Een IP-adres, een poortnummer of een VLAN dat over twee regels wordt
 * afgebroken is geen gegeven meer maar twee halve. */
td.mono, td.num { white-space: nowrap; }

/* De statusstreep vooraan een rij. Een randje en geen kolom: het hoort bij de
 * rij en niet in de tabelindeling. */
tbody tr[data-stand] > td:first-child { box-shadow: inset 3px 0 0 var(--led-uit); }
tbody tr[data-stand="goed"] > td:first-child { box-shadow: inset 3px 0 0 var(--led-goed); }
tbody tr[data-stand="let"]  > td:first-child { box-shadow: inset 3px 0 0 var(--led-let); }
tbody tr[data-stand="fout"] > td:first-child { box-shadow: inset 3px 0 0 var(--led-fout); }

/* ── Status in tekst ─────────────────────────────────────────────────────────
 *
 * Een lampje met een woord erachter, en geen gekleurde pil. Een rij vol pillen
 * wordt een rij vol kleurvlakken, en dan valt niets meer op -- terwijl juist
 * het opvallen het hele punt is.
 */
.stand { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
         color: var(--stil); white-space: nowrap; }
.stand i { width: 7px; height: 7px; border-radius: 50%; background: var(--led-uit);
           flex: 0 0 7px; display: block; }
.stand.goed i { background: var(--led-goed); }
.stand.let  i { background: var(--led-let); }
.stand.fout i { background: var(--led-fout); }
.stand.let  { color: var(--let-inkt); }
.stand.fout { color: var(--fout-inkt); font-weight: 500; }

.merkje { display: inline-block; padding: 2px 8px; border-radius: 5px;
          font-size: 11px; font-weight: 600; white-space: nowrap;
          text-transform: uppercase; letter-spacing: .6px;
          background: var(--grond); color: var(--stil); border: 1px solid var(--lijn); }
.merkje.goed { background: var(--goed-vlak); color: var(--goed-inkt); border-color: var(--goed-lijn); }
.merkje.let  { background: var(--let-vlak); color: var(--let-inkt); border-color: var(--let-lijn); }
.merkje.fout { background: var(--fout-vlak); color: var(--fout-inkt); border-color: var(--fout-lijn); }

/* ── Knoppen ─────────────────────────────────────────────────────────────── */

.knop { display: inline-flex; align-items: center; gap: 8px; padding: 9px 16px;
        border: 1px solid var(--knop-vlak); border-radius: 8px; background: var(--knop-vlak);
        color: var(--knop-tekst); font: inherit; font-size: 14px; font-weight: 600;
        cursor: pointer;
        letter-spacing: .1px; }
.knop:hover { background: var(--paneel-op); }
.knop:disabled { background: var(--lijn); border-color: var(--lijn); color: var(--stil); cursor: default; }
.knop.stil { background: var(--vlak); color: var(--inkt); border-color: var(--lijn); font-weight: 500; }
.knop.stil:hover { background: var(--hover); border-color: var(--flauw); }
.knop.klein { padding: 5px 11px; font-size: 12.5px; }
.knop.gevaar { background: var(--vlak); color: var(--fout-inkt); border-color: var(--fout-lijn); }
.knop.gevaar:hover { background: var(--fout-vlak); }
/*
 * Een knop die eigenlijk een link is.
 *
 * De knop naar een apparaat in de RMM móet een <a> zijn: hij gaat in een nieuw
 * tabblad open, en dat hoort de browser te doen en niet javascript. Maar `a`
 * krijgt hierboven zijn eigen kleur en de underline van de browser, en dan is
 * het een zwart onderstreept blokje op een zwarte knop.
 */
a.knop { text-decoration: none; }
a.knop:not(.stil):not(.gevaar) { color: var(--knop-tekst); }
.rij-knoppen { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/*
 * Een rij dingen naast elkaar.
 *
 * Deze klasse werd op drie plekken gebruikt en bestond hier niet -- alleen
 * `.rij-knoppen`. Het gevolg valt alleen op waar er iets anders dan een knop in
 * staat: twee knoppen zijn `inline-flex` en gaan toch al naast elkaar, maar een
 * invoerveld is een blok en dan viel de knop erachter op de volgende regel. Zo
 * stond het zoekveld van de vloot boven zijn eigen knop.
 *
 * Dezelfde regel als in het beheerpaneel, waar hij wél stond.
 */
.rij { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* ── Velden ──────────────────────────────────────────────────────────────── */

/*
 * Een label bij een invulveld, en geen tabelkop.
 *
 * Dit stond in kapitalen met letterspatiëring -- dezelfde stijl als de
 * sectiekoppen (h2) en de kolomkoppen van een tabel. Daardoor las een
 * formulier als een tabel: "TENANT-ID" boven een invoervak ziet eruit als de
 * kop van een kolom en niet als de naam van iets dat je invult. En de
 * toevoeging erachter ("ingevuld") stond dan in kleine letters, wat eruitziet
 * als een fout.
 *
 * Kapitalen blijven voor de gravure-koppen; een label hoort daar niet bij.
 */
label { display: block; font-size: 13px; font-weight: 600; margin: 0 0 6px;
        color: var(--inkt); letter-spacing: -.005em; }
/*
 * De toevoeging achter een label, zoals "leeg = niet veranderen".
 *
 * Met een marge ervoor. Zonder die marge leest "CLIENT SECRETingevuld" als één
 * woord en dan lijkt het een typefout in het product -- want een label is
 * hoofdletters en de toevoeging niet, en dat verschil ziet eruit als iets dat
 * kapot is gegaan.
 */
/*
 * De toevoeging achter een label, zoals "ingevuld" of "optioneel".
 *
 * Als klein plaatje en niet als losse tekst: los leest "Clientgeheim ingevuld"
 * als één zin waarin "ingevuld" een woord van het label is. Met een eigen
 * vlakje is het een aantekening bij het label, en dat is wat het is.
 */
label .los {
  margin-left: 8px;
  font-weight: 500;
  font-size: 11px;
  letter-spacing: .02em;
  color: var(--stil);
  background: var(--hover);
  border: 1px solid var(--lijn-fijn);
  border-radius: 5px;
  padding: 1px 6px;
  vertical-align: 1px;
}

/*
 * Gewoon `input`, en de uitzonderingen erna. Een selector met drie :not()'s
 * weegt zwaarder dan `.zoekvak input` en zou dat veld overschrijven -- een
 * selector die zwaarder is dan nodig is een val die je pas ziet als je kijkt.
 */
input, select, textarea {
  width: 100%; padding: 10px 12px; border: 1px solid var(--lijn); border-radius: 8px;
  font: inherit; color: var(--inkt); background: var(--vlak);
  line-height: 1.4; height: auto; -webkit-appearance: none; appearance: none;
  /* Een binnenschaduwtje van één pixel. Zonder dat is een veld met een lichte
   * rand op een lichte kaart nauwelijks een veld -- je ziet een rechthoek en
   * niet iets waar je in typt. */
  box-shadow: inset 0 1px 2px rgba(20, 26, 32, .045);
  transition: border-color .12s, box-shadow .12s;
}
input::placeholder, textarea::placeholder { color: var(--flauw); }
input:hover:not(:focus), select:hover:not(:focus), textarea:hover:not(:focus) {
  border-color: var(--flauw);
}
input[type=checkbox], input[type=radio] { width: auto; padding: 0;
                                          -webkit-appearance: auto; appearance: auto; }
select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23667681' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
         background-repeat: no-repeat; background-position: right 12px center; padding-right: 34px; }
textarea { min-height: 92px; resize: vertical; height: auto;
           font-family: "IBM Plex Mono", ui-monospace, Menlo, monospace; font-size: 13px;
           line-height: 1.55; }
input:focus, select:focus, textarea:focus {
  outline: 0;
  border-color: var(--merk);
  /* Een ring in plaats van een outline: die volgt de ronde hoeken, waar een
   * outline een vierkant om een rond veld tekent. */
  box-shadow: 0 0 0 3px var(--merk-vlak), inset 0 1px 2px rgba(20, 26, 32, .03);
}
/* Gegevens die een gegeven zijn, niet een woord. */
input[type=text].mono, input.mono { font-family: "IBM Plex Mono", monospace; }

/*
 * Een veld met zijn label en zijn uitleg als één blok.
 *
 * De maten zijn hier het punt. De uitleg stond zes pixels onder zijn veld en
 * het volgende label vijftien pixels daaronder -- bijna hetzelfde. Daardoor
 * hoorde de uitleg voor het oog net zo goed bij het vólgende veld, en dan lees
 * je een formulier verkeerd zonder te weten waarom.
 *
 * Nu: vier pixels tussen veld en zijn uitleg, en twintig naar het volgende
 * blok. Vijf keer zoveel ruimte tussen twee blokken als binnen een blok, en
 * dan valt de groepering vanzelf goed.
 */
.veld { margin-bottom: 20px; }
.veld:last-child { margin-bottom: 0; }
.veld .uitleg { font-size: 12.5px; color: var(--stil); margin: 4px 0 0; line-height: 1.5; }
/* Een regellengte waar je nog op kunt lezen.
 *
 * Deze uitlegteksten liepen over de volle breedte van de bladzijde: op een
 * laptop zo'n honderdvijftig tekens per regel, het dubbele van wat comfortabel
 * is. Bij zo'n lengte verlies je aan het eind van de regel welke regel je aan
 * het lezen was, en dan slaat iemand de uitleg over -- precies de tekst die
 * uitlegt waaróm een instelling er staat.
 *
 * In `ch` en niet in pixels: de maat hoort mee te schuiven met de lettergrootte.
 * De uitleg ónder een veld (.veld .uitleg) blijft ongemoeid: die is al zo breed
 * als zijn veld. */
.uitleg { font-size: 12.5px; color: var(--stil); max-width: 74ch; }
.strook .uitleg, .veld .uitleg, .vinkje .uitleg, .tegel .uitleg { max-width: none; }
.vinkje .uitleg { max-width: 88ch; }
/*
 * Twee kolommen, van bovenaf uitgelijnd.
 *
 * Zonder `align-items: start` rekt een veld met een uitlegregel zijn buur mee
 * en staan twee invoervakken op verschillende hoogte -- met precies dezelfde
 * html. Dat is een uur zoeken naar een verschil dat er niet is.
 */
/*
 * Zes-en-twintig pixels tussen de kolommen en niet zestien: de uitleg onder het
 * linkerveld eindigt anders zo dicht bij het rechterveld dat hij erbij lijkt te
 * horen. Bij twee kolommen is de tussenruimte het enige dat zegt waar het ene
 * ophoudt.
 */
.tweekolom { display: grid; grid-template-columns: 1fr 1fr; gap: 0 26px; align-items: start; }
@media (max-width: 640px) { .tweekolom { grid-template-columns: 1fr; } }
/*
 * Drie kleine velden naast elkaar.
 *
 * Met min() erin en niet met een vaste minimum-kolom: die maakte het blad
 * eerder breder dan het venster op een telefoon, en dan valt elke kop buiten
 * het beeld. Zie het raster van de tegels voor hetzelfde verhaal.
 */
.drieko { display: grid; gap: 0 26px; align-items: start;
          grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr)); }

/*
 * Een veld voor de sleutel van een ander systeem.
 *
 * Zie sleutelveld() in app.js: dit is met opzet geen wachtwoordveld, want een
 * wachtwoordbeheerder vult daar het wachtwoord van deze site in en dan bewaart
 * hij netjes het verkeerde. Het maskeren gebeurt hier, met css.
 *
 * -webkit-text-security werkt in Safari, Chrome en Edge. Firefox kent het niet;
 * daar staat de sleutel dus leesbaar. Dat is een bewuste ruil: een sleutel die
 * op het scherm te lezen is voor wie er al voor zit, is minder erg dan een
 * sleutel die stil door iets anders wordt vervangen. En de knop ernaast heet
 * daarom "Laten zien" en niet "Verbergen".
 */
.sleutelveld { display: flex; gap: 8px; align-items: stretch; }
.sleutelveld input { min-width: 0; }
.sleutelveld .knop { flex: 0 0 auto; white-space: nowrap; }
.sleutelveld input.verborgen { -webkit-text-security: disc; text-security: disc; }

/*
 * Een proefmail: zoals een mailprogramma hem zou tonen.
 *
 * Met een onderwerpregel erboven en de tekst in <pre>, want dit is plat tekst
 * en de regelafbrekingen zijn een keuze van degene die het sjabloon schreef.
 * Zonder <pre> loopt alles aan elkaar en denk je dat je tekst stuk is.
 */
.proefmail { margin-top: 18px; border: 1px solid var(--lijn); border-radius: 10px;
             overflow: hidden; background: var(--vlak); }
.pmkop { display: flex; gap: 10px; align-items: baseline; padding: 11px 15px;
         border-bottom: 1px solid var(--lijn-fijn); background: var(--grond); }
.pmkop span { font-size: 11px; font-weight: 600; letter-spacing: .04em;
              text-transform: uppercase; color: var(--stil); flex: 0 0 auto; }
.pmkop b { font-size: 14px; color: var(--inkt); min-width: 0; overflow-wrap: anywhere; }
.proefmail pre { margin: 0; padding: 15px;
                 font: 13px/1.65 "IBM Plex Mono", ui-monospace, Menlo, monospace;
                 color: var(--inkt); white-space: pre-wrap; overflow-wrap: anywhere; }
/*
 * Een vinkje met zijn uitleg, in hetzelfde ritme als een veld.
 *
 * Twintig pixels eronder, net als .veld -- ze staan door elkaar in dezelfde
 * formulieren, en twee ritmes in één kaart leest als een kaart die half is
 * afgemaakt. En de titel in dezelfde grootte en hetzelfde gewicht als een
 * label, want dat is wat het is.
 */
.vinkje { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 20px;
          font-size: 13px; font-weight: 600; letter-spacing: -.005em; color: var(--inkt); }
.vinkje:last-child { margin-bottom: 0; }
.vinkje input { width: auto; margin-top: 2px; flex: 0 0 auto; accent-color: var(--merk); }
.vinkje strong { font-weight: 600; }
.vinkje .uitleg { display: block; font-weight: 400; margin-top: 3px; }

/*
 * De knoppenrij onderaan een kaart.
 *
 * Met een lijn erboven die binnen de marge blijft en met dezelfde ruimte
 * eronder als erboven. Dit stond met inline stijlen op drie plekken en elke
 * keer een beetje anders -- en op één plek raakte de rij de onderrand van de
 * kaart, omdat .lijf geen marge had.
 */
.kaartvoet {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  margin-top: 22px; padding-top: 18px;
  border-top: 1px solid var(--lijn-fijn);
}

/* ── Meldingen ───────────────────────────────────────────────────────────── */

.melding { padding: 12px 15px; border-radius: 8px; margin: 0 0 16px; font-size: 14px; }
.melding.fout { background: var(--fout-vlak); color: var(--fout-inkt); border: 1px solid var(--fout-lijn); }
.melding.let  { background: var(--let-vlak); color: var(--let-inkt); border: 1px solid var(--let-lijn); }
.melding.goed { background: var(--goed-vlak); color: var(--goed-inkt); border: 1px solid var(--goed-lijn); }

/*
 * "Let op" bij een klant: wat iemand moet weten vóór hij iets aanraakt.
 * Als een sticker op een apparaat -- schuine strepen aan de linkerkant, zoals
 * op waarschuwingstape.
 */
.letop { background: var(--let-vlak); color: var(--let-inkt); border: 1px solid var(--let-lijn);
         border-radius: var(--rond); padding: 15px 17px 15px 22px; margin-bottom: 20px;
         position: relative; overflow: hidden; }
.letop::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 7px;
  background: repeating-linear-gradient(135deg, var(--led-let) 0 6px, #D08A1F 6px 12px);
}
.letop b { display: block; font-size: 10px; text-transform: uppercase; letter-spacing: 1.4px;
           margin-bottom: 5px; }

/* ── Tegels ──────────────────────────────────────────────────────────────── */

/* 132 en niet 146: op een laptop van 1280 en op een tablet scheelde dat een
 * hele kolom, en dan staan de tegels in vijf rijen in plaats van vier voordat
 * je bij de inhoud bent. */
/*
 * De tegels met de aantallen.
 *
 * ── Waarom hier 144 staat en niet 132, en waarom er afbreekregels bij horen ──
 *
 * Met 132 als minimum pakte het raster op een breed venster acht kolommen, en
 * dan is er binnen de rand honderdzes pixels ruimte. "NETWERKAPPARATEN" is in
 * hoofdletters met deze letterafstand honderdzevenendertig pixels breed, en
 * omdat het één woord is zonder afbreekpunt liep het gewoon over de rand heen.
 * Hetzelfde gold voor CONTACTPERSONEN, WACHTWOORDEN en ABONNEMENTEN. Nagemeten
 * op zes breedtes: onder de 768 was er niets aan de hand, daarboven bij elke
 * breedte wel.
 *
 * Twee dingen samen lossen het op. Het minimum omhoog, zodat er in de praktijk
 * niets meer hoeft af te breken. En afbreken toestaan als het toch moet -- want
 * de naam van een eigen soort komt uit Instellingen -> Eigen velden, en hoe
 * lang iemand die maakt weet ik niet. `hyphens: auto` met lang="nl" op de
 * pagina breekt op NETWERK-APPARATEN en niet middenin een lettergreep;
 * `overflow-wrap: anywhere` is het laatste net voor iets dat niet af te breken
 * is. Over de rand heen lopen is er niet meer bij.
 */
.tegels { display: grid; gap: 10px;
          grid-template-columns: repeat(auto-fill, minmax(min(144px, 100%), 1fr));
          /* Alle rijen even hoog, en niet per rij naar de inhoud.
           *
           * Breekt één naam af naar twee regels, dan wordt zonder deze regel
           * alleen díe rij zeventien pixels hoger en staan de rijen ongelijk.
           * Dat leest als iets dat half is afgemaakt -- en het is precies het
           * soort onnetheid waar deze tegels om te doen was.
           *
           * `1fr` is hier geen breuk van de beschikbare hoogte: het raster is
           * zo hoog als zijn inhoud, en dan maakt 1fr elke rij zo hoog als de
           * hoogste. Kost niets als er niets afbreekt. */
          grid-auto-rows: 1fr; }
.tegel { background: var(--vlak); border: 1px solid var(--lijn); border-radius: var(--rond);
         padding: 13px 15px; cursor: pointer; text-align: left; font: inherit; color: inherit;
         box-shadow: var(--schaduw); position: relative;
         /* Een grid-item krimpt van zichzelf niet onder zijn inhoud. Zonder
          * deze regel duwt een lange naam de kolom breder dan het raster, en
          * dan wordt de hele pagina breder dan het venster -- precies wat de
          * drie rasters in dit bestand eerder deden. */
         min-width: 0; }
.tegel:hover { border-color: var(--flauw); }

/* Een tegel met nul erin blijft staan -- je moet de eerste server erin kunnen
 * zetten -- maar hoort niet mee te vechten om je aandacht. Bij een klant met
 * alleen wachtwoorden waren vijftien van de zestien vakken een nul, en dan
 * moet je zoeken naar het enige vak dat iets zegt. Geen schaduw, een lichtere
 * rand en een grijs getal: het staat er, en het roept niet. */
.tegel.leeg { box-shadow: none; background: transparent; border-color: var(--lijn-fijn); }
.tegel.leeg .aantal { color: var(--flauw); font-weight: 400; }
/* Een lege tegel dempt ook zijn badge: hij staat er, en hij roept niet. */
.tegel.leeg .teken { opacity: .42; filter: saturate(.45); }
/* Het getal mag flauw, het woord niet.
 *
 * Hier stond ook --flauw, en dat is op de lichte vloer 2,2 contrast -- gemeten,
 * en dat is te weinig om een woord van elf pixels te lezen. Dat een tegel leeg
 * is, blijkt al uit de weggevallen schaduw, de lichtere rand, het doorschijnende
 * vlak en het bijna onzichtbare teken. Het woord hoeft die boodschap niet nog
 * een vierde keer te dragen ten koste van de leesbaarheid. */
.tegel.leeg .naam { color: var(--stil); }
.tegel.leeg:hover { background: var(--vlak); border-color: var(--lijn); }
/* De gekozen tegel.
 *
 * Eigen tokens en niet --paneel, want de betekenis is "dit is wat je nu ziet"
 * en die moet in beide standen naar vóren komen. In het licht is dat donker
 * tegen een lichte kaart; in het donker moet het lichter zijn dan zijn buren --
 * met --paneel werd de gekozen tegel de donkerste van de rij en las hij als een
 * gat in het scherm in plaats van als iets dat bovenop ligt. */
.tegel.aan { border-color: var(--gekozen-lijn); background: var(--gekozen-vlak);
             color: var(--gekozen-tekst);
             box-shadow: inset 0 1px 0 rgba(238, 243, 245, .07); }
/*
 * Het pictogram als badge, met een tint per soort.
 *
 * Zie tegelTint() in app.js voor waarom kleur hier mag en verder in dit bestand
 * niet: de tint zit alleen op dit vierkantje. Het vak blijft wit, het getal
 * blijft inkt, en een tegel die aandacht vraagt doet dat nog steeds met een
 * lampje. Wat de tint doet is helpen terugvinden -- je zoekt de blauwgroene
 * voor het netwerk -- en dat gaat sneller dan lezen.
 *
 * ── Waarom één kleurtoon per soort en geen twee vaste kleuren ──
 *
 * Een pastel vlak met een donkere letter werkt in het licht; in het donker moet
 * het vlak diep zijn en de letter licht, anders staat er een lichtbak op een
 * donker scherm. Met twee vaste kleuren per soort zou dat tien klassen in de
 * lichte stand én tien in de donkere zijn -- twintig plekken die uit elkaar
 * kunnen lopen.
 *
 * Dus draagt een soort alleen zijn kleurtóón, en staan de verzadiging en de
 * helderheid één keer in de lichte stand en één keer in de donkere. Wisselen
 * van stand is dan vier getallen en geen twintig regels.
 */
.tegel .teken {
  font-size: 15px; line-height: 1;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border-radius: 8px;
  margin-bottom: 8px;
  background: hsl(var(--toon, 210) var(--tint-vs, 12%) var(--tint-vl, 90%));
  color: hsl(var(--toon, 210) var(--tint-is, 20%) var(--tint-il, 32%));
  transition: transform .14s ease;
}
.tegel:hover .teken { transform: scale(1.07); }
@media (prefers-reduced-motion: reduce) {
  .tegel .teken { transition: none; }
  .tegel:hover .teken { transform: none; }
}
.tegel .aantal { font-family: "IBM Plex Mono", monospace; font-size: 25px; font-weight: 500;
                 font-variant-numeric: tabular-nums; line-height: 1.2; letter-spacing: -1px; }
.tegel .naam { font-size: 11px; text-transform: uppercase; letter-spacing: .5px;
               color: var(--stil); font-weight: 600;
               overflow-wrap: anywhere; hyphens: auto; }
.tegel.aan .naam { color: var(--gekozen-naam); }
/* De gekozen tegel is donker; een lichte pastel badge daarop is een vlek. */
.tegel.aan .teken { background: rgba(238, 243, 245, .14);
                    color: var(--gekozen-tekst); }

/*
 * De kleurtonen. Verwante dingen liggen bij elkaar, en die indeling staat in
 * app.js zodat er één plek is die weet welk soort waar hoort.
 */
.t-ijzer   { --toon: 205; }   /* wat je aan kunt raken */
.t-draad   { --toon: 174; }   /* wat er tussen zit */
.t-werk    { --toon: 245; }   /* wat draait en wat je uitvoert */
.t-web     { --toon: 135; }   /* wat buiten staat */
.t-termijn { --toon: 38; }    /* wat afloopt */
.t-ding    { --toon: 4; }     /* wat er nu speelt */
.t-sleutel { --toon: 272; }
.t-mens    { --toon: 22; }
.t-blad    { --toon: 65; }
/* Een soort die iemand zelf heeft aangemaakt: grijs. Een willekeurige kleur
 * toewijzen zou de indeling juist onbetrouwbaar maken. */
.t-rest    { --toon: 210; --tint-vs: 8%; --tint-is: 9%; }


/* ── Zoekresultaat ───────────────────────────────────────────────────────── */

.treffer { display: block; width: 100%; text-align: left; font: inherit; color: inherit;
           background: none; border: 0; border-bottom: 1px solid var(--lijn-fijn);
           padding: 12px 14px 12px 17px; cursor: pointer; position: relative; }
.treffer:hover { background: var(--hover); }
.treffer[data-stand] { box-shadow: inset 3px 0 0 var(--led-uit); }
.treffer[data-stand="goed"] { box-shadow: inset 3px 0 0 var(--led-goed); }
.treffer[data-stand="let"]  { box-shadow: inset 3px 0 0 var(--led-let); }
.treffer[data-stand="fout"] { box-shadow: inset 3px 0 0 var(--led-fout); }
.treffer .kop { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.treffer .kop b { font-size: 15px; }
.treffer .waar { color: var(--stil); font-size: 13px; }
.treffer .waarom { color: var(--stil); font-size: 12.5px; margin-top: 4px;
                   font-family: "IBM Plex Mono", monospace; }

/* ── Vensters ────────────────────────────────────────────────────────────── */

.laag { position: fixed; inset: 0; z-index: 40; background: rgba(31, 42, 49, .5);
        display: flex; align-items: flex-start; justify-content: center;
        padding: 44px 16px; overflow-y: auto; }
.venster { background: var(--vlak); border-radius: 14px; width: 100%; max-width: 620px;
           box-shadow: 0 24px 70px rgba(31, 42, 49, .35); }
.venster.breed { max-width: 920px; }
/* De gebruikerslijst uit 365 heeft zes kolommen; op 920 wordt dat proppen. */
.venster.extrabreed { max-width: min(1320px, 96vw); }
.vkop { display: flex; align-items: center; justify-content: space-between;
        padding: 17px 22px; border-bottom: 1px solid var(--lijn); }
.vkop h3 { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.2px; }
.vkop button { background: none; border: 0; font-size: 22px; line-height: 1; cursor: pointer;
               color: var(--stil); padding: 0 4px; }
.vlijf { padding: 22px; }

/*
 * Het lijf van een kaart buiten een venster.
 *
 * Deze klasse werd op drie plekken gebruikt -- de RMM-koppeling, de
 * mailkoppeling, de toegangslijst -- en bestond hier niet. Gevolg: die kaarten
 * hadden géén binnenmarge, dus lag elk label tegen de rand en raakte de
 * knoppenrij de onderkant. Dat is precies het soort ding dat "de afwerking is
 * slecht" oplevert zonder dat er één regel opmaak fout staat: er stond alleen
 * niets.
 */
.lijf { padding: 22px; }
.vvoet { display: flex; gap: 8px; justify-content: flex-end; align-items: center;
         padding: 15px 22px; border-top: 1px solid var(--lijn); background: var(--hover);
         border-radius: 0 0 14px 14px; }
.vvoet .links { margin-right: auto; }

/* ── Een geheim ──────────────────────────────────────────────────────────── */

.geheimvak { background: var(--paneel); border-radius: 9px; padding: 15px 16px;
             display: flex; align-items: center; gap: 12px;
             box-shadow: inset 0 1px 0 rgba(238, 243, 245, .07); }
.geheimvak code { flex: 1 1 auto; font-family: "IBM Plex Mono", monospace;
                  font-size: 16px; word-break: break-all; color: var(--paneel-tekst);
                  letter-spacing: .3px; }
.geheimvak .knop.stil { background: rgba(238, 243, 245, .12); color: var(--paneel-tekst);
                        border-color: rgba(238, 243, 245, .22); }
.geheimvak .knop.stil:hover { background: rgba(238, 243, 245, .2); }

.piep { position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%);
        background: var(--paneel); color: var(--paneel-tekst); padding: 12px 20px; border-radius: 9px;
        font-size: 14px; z-index: 60; box-shadow: 0 10px 30px rgba(31, 42, 49, .35); }
.piep.fout { background: var(--fout-inkt); }

/* ── Aanmelden ───────────────────────────────────────────────────────────────
 *
 * Eén kaart, gecentreerd, en verder zo weinig mogelijk. Dit is een deur en geen
 * etalage: wie hier staat wil erdoor.
 *
 * De velden staan in een grid en niet op losse marges. Marges van
 * buurelementen kunnen samenvallen of verdubbelen, en dan staan twee vakken die
 * in de code hetzelfde zijn op het scherm net niet gelijk.
 */
.aanmeldblad { min-height: 100vh; display: grid; place-items: center; padding: 32px 20px;
               background: var(--paneel); }
.aanmeldkaart { width: 100%; max-width: 402px; }
.aanmeldkaart .merk { display: flex; align-items: center; gap: 12px;
                      justify-content: center; margin-bottom: 9px; color: var(--paneel-tekst); }
.aanmeldkaart .merk img { width: 44px; height: 44px; }
.aanmeldkaart .merk b { font-size: 27px; letter-spacing: -.6px; font-weight: 700; }
.aanmeldkaart .merk b span { font-weight: 400; opacity: .6; }
.aanmeldkaart .leus { text-align: center; color: rgba(238, 243, 245, .55); font-size: 13.5px;
                      margin: 0 0 26px; }
.aanmeldkaart .kaart { border-radius: 14px; border-color: transparent;
                       box-shadow: 0 20px 50px rgba(0, 0, 0, .35); }
.aanmeldkaart .vlijf { padding: 24px; display: grid; gap: 17px; }
.aanmeldkaart .veld { margin: 0; }
.aanmeldkaart .knop { width: 100%; justify-content: center; padding: 11px 16px; }
.aanmeldkaart .voet { text-align: center; color: rgba(238, 243, 245, .4); font-size: 12px;
                      margin: 20px 0 0; line-height: 1.5; }

/* ── Het patchpaneel ─────────────────────────────────────────────────────────
 *
 * Het paneel zoals het aan de wand hangt. Dat is geen versiering: naast een
 * echt paneel staan met een lijst van veertig regels betekent tellen, met een
 * tekening van hetzelfde paneel betekent het kijken.
 *
 * De poorten die er níet in staan zijn met opzet even zichtbaar als de rest --
 * dat zijn de gaten waar de volgende kabel in gaat, en die vraag komt vaker dan
 * "wat zit er op poort 7".
 */

.paneel { background: var(--paneel); border-radius: var(--rond); padding: 14px 16px 16px;
          margin-bottom: 12px; box-shadow: inset 0 1px 0 rgba(238, 243, 245, .07); }
.paneelkop { display: flex; align-items: baseline; gap: 12px; margin-bottom: 12px; }
.paneelkop b { color: var(--paneel-tekst); font-size: 13px; text-transform: uppercase; letter-spacing: 1.3px; }
.paneelkop span { font-family: "IBM Plex Mono", monospace; font-size: 11.5px;
                  color: rgba(238, 243, 245, .42); }

/*
 * Twaalf per rij met een bredere naad na elke zes, want zo zijn panelen
 * ingedeeld. Dat maakt poort 19 te vinden zonder te tellen -- je zoekt het
 * derde blok en dan de eerste.
 */
/*
 * De blokken mogen meerekken met de breedte, maar niet onbeperkt krimpen.
 * Zonder ondergrens persen vier blokken zich op één rij tot poortjes van vijf
 * pixels -- en dan is de tekening onleesbaar precies wanneer er veel poorten
 * zijn. Met een ondergrens wikkelen ze naar de volgende regel, zoals een
 * paneel van 48 in twee rijen van 24 hangt.
 */
/*
 * Vaste maten, en met opzet.
 *
 * Eerst stond hier een grid met 1fr-kolommen, daarna met minmax(0,1fr), en in
 * beide gevallen kwamen er poortjes van verschillende breedte uit bij precies
 * dezelfde html. Dat is een uur zoeken naar een verschil dat er niet is.
 *
 * Een patchpaneel heeft in het echt ook vaste maten -- alle poorten zijn even
 * groot, want er past één stekker in. Dus staat het hier in pixels: dan is er
 * niets meer om verkeerd uit te rekenen, en de tekening is op elk scherm
 * hetzelfde als het paneel aan de wand.
 */
.poorten { display: flex; flex-wrap: wrap; gap: 12px 16px; }
.blok { display: grid; grid-template-columns: repeat(6, 34px); gap: 6px; flex: 0 0 auto; }

/*
 * Een poort is een gaatje in een plaat, en geen knop.
 *
 * Dat onderscheid is de hele tekening. Eerst had elke poort een bijna zwarte
 * rand; naast elkaar liepen zes lege poorten dan in elkaar over tot één donkere
 * balk met cijfers erin, en het paneel las als een streep in plaats van als een
 * rij aansluitingen. De rand was donkerder dan de naad ertussen, en dan is de
 * naad geen naad meer.
 *
 * Nu: de naad is de plaat die ertussendoor schijnt, de lege poort is een
 * verzonken gat en de vastgelegde poort steekt eruit. Licht van boven, zoals
 * alles wat je in het echt bekijkt -- daarom een lichte streep op de bovenrand
 * van wat uitsteekt en een donkere schaduw ín wat verzonken is.
 *
 * Vaste maten, en met opzet. Eerst stond hier een grid met 1fr-kolommen, daarna
 * met minmax(0,1fr), en in beide gevallen kwamen er poortjes van verschillende
 * breedte uit bij precies dezelfde html -- een uur zoeken naar een verschil dat
 * er niet is. Een patchpaneel heeft in het echt ook vaste maten: er past één
 * stekker in, en die is overal even groot.
 *
 * 34 en niet 30 pixels: op 30 raakt een nummer van twee cijfers de rand, en
 * "13" leest dan als "1" met een veeg ernaast.
 */
/*
 * Twee rijen: het cijfer en het lampje.
 *
 * Eerst stond het cijfer midden in een flexvak met wat vulling onderaan, en
 * hing het lampje er absoluut over. Dat is twee manieren van plaatsen die van
 * elkaar niets weten, en dan hangt het van de renderer af of het cijfer een
 * paar pixels omhoog of omlaag valt. Elk zijn eigen rij is één manier: het
 * cijfer kan niet op het lampje zakken, want daar is geen ruimte voor.
 */
.poort {
  position: relative;
  height: 44px;
  min-width: 0;
  display: grid;
  grid-template-rows: 1fr 3px;
  align-items: center;
  justify-items: center;
  padding: 2px 0 5px;
  border-radius: 5px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  cursor: pointer;
  transition: background .12s, box-shadow .12s;
}

/* ── Wat is vastgelegd: het steekt eruit ── */
.poort {
  background: linear-gradient(180deg, #556775 0%, var(--paneel-poort) 100%);
  color: var(--paneel-tekst);
  border: 1px solid rgba(0, 0, 0, .22);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .11),
              0 1px 1px rgba(0, 0, 0, .18);
}
.poort:hover {
  background: linear-gradient(180deg, #617483 0%, #4E6070 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16),
              0 0 0 2px var(--merk);
  z-index: 2;
}

/*
 * ── Een lege poort: een gat ──
 *
 * Verzonken en niet omlijnd. Geen rand, want een rand maakt er een vakje van en
 * daarmee weer een knop; een schaduw naar binnen maakt er een opening van.
 *
 * Het cijfer op 34% en niet op 20%: op 20% is het bij daglicht in een
 * meterkast niet te lezen, en het nummer is juist het enige wat een leeg gat te
 * melden heeft.
 */
.poort.leeg {
  background: var(--paneel-gat);
  color: rgba(238, 243, 245, .38);
  border: 1px solid transparent;
  /*
   * Drie schaduwen, en elk doet iets:
   *
   *   naar binnen van boven   de opening ligt lager dan de plaat
   *   een lichte onderrand    de onderkant van de opening vangt licht, zoals
   *                           bij elk gat waar je van bovenaf in kijkt
   *   een lichte ring erbuiten de plaat rondom het gat
   *
   * Die laatste is de belangrijkste, en het is de tweede poging. Eerst stond er
   * een dónkere ring; naast elkaar liepen zes lege poorten dan in elkaar over
   * tot één donkere streep met cijfers erin, want de naad ertussen was even
   * donker als de gaten zelf.
   *
   * Andersom is het ook hoe het in het echt is: de plaat tussen de openingen is
   * metaal, en dat is het lichtste wat er in een paneel zit. Een ring naar
   * buiten en niet naar binnen, want een ring naar buiten verandert de maat van
   * niets -- en de maten van dit paneel zijn met opzet vast.
   */
  /*
   * Scherpe lijnen en geen vervaging.
   *
   * Eerst stond hier `inset 0 2px 4px` -- een schaduw met vier pixels vervaging.
   * Die bloedt ook naar links en rechts, en dan is de naad tussen twee gaten
   * dónkerder dan de gaten zelf: zes openingen worden één donkere streep. Met
   * gemeten pixels was dat te zien en met het oog alleen niet, want het scheelt
   * vier eenheden grijs.
   *
   * Een scherpe lijn van twee pixels bovenaan doet hetzelfde werk -- dat is de
   * schaduw die de bovenrand van een opening werpt -- en raakt de zijkanten
   * niet.
   */
  box-shadow: inset 0 2px 0 rgba(0, 0, 0, .4),
              inset 0 -1px 0 rgba(255, 255, 255, .08),
              0 0 0 1px rgba(255, 255, 255, .13);
}

/* Aanwijsbaar, want hier hoort de volgende kabel in: klikken vult het
 * paneelnummer al voor je in. Zonder deze hint is het een dood vlak. */
.poort.leeg:hover {
  background: #2A3742;
  color: rgba(238, 243, 245, .8);
  box-shadow: inset 0 2px 0 rgba(0, 0, 0, .3),
              0 0 0 2px rgba(255, 255, 255, .3);
  z-index: 2;
}
/* Bij aanwijzen een plusje op de plek van het lampje: hier hoort de volgende
 * kabel in, en klikken vult het paneelnummer al voor je in. */
.poort.leeg::before {
  content: '+';
  grid-row: 2;
  grid-column: 1;
  font-size: 11px;
  line-height: 1;
  color: rgba(238, 243, 245, .55);
  opacity: 0;
  transform: translateY(-1px);
}
.poort.leeg:hover::before { opacity: 1; }

/*
 * De stand als een lampje onderaan, zoals de LED onder een RJ45.
 *
 * Een echt vakje in de tweede rij en niet iets dat er absoluut over hangt. Bij
 * een leeg gat staat het er ook, maar dan doorzichtig -- zo staan de cijfers
 * van een gat en van een aansluiting op precies dezelfde hoogte, en dat is wat
 * een rij poorten leesbaar maakt.
 */
.poort::after {
  content: '';
  grid-row: 2;
  width: 13px;
  height: 3px;
  border-radius: 2px;
  background: transparent;
}
.poort.gebruik::after      { background: var(--led-goed); box-shadow: 0 0 6px rgba(52, 192, 122, .85); }
.poort.vrij::after         { background: rgba(238, 243, 245, .26); }
.poort.stuk                { color: #FFD9D4; }
.poort.stuk::after         { background: var(--led-fout); box-shadow: 0 0 6px rgba(232, 92, 80, .85); }
.poort.gereserveerd::after { background: var(--led-let); box-shadow: 0 0 6px rgba(239, 160, 46, .75); }

/* Een vrije poort is vastgelegd maar niet in gebruik: hij bestaat, dus hij
 * steekt eruit, maar hij mag rustiger zijn dan de rest. */
.poort.vrij {
  background: linear-gradient(180deg, #4A5A67 0%, #414F5B 100%);
  color: rgba(238, 243, 245, .72);
}

.poort .poe {
  position: absolute; top: 3px; right: 4px;
  font-size: 8px; font-weight: 700; line-height: 1;
  color: var(--led-let);
}

/*
 * De legenda. Vier standen en een gat, met dezelfde vormgeving als in de
 * tekening -- anders moet iemand raden of het grijze streepje "vrij" of "geen
 * gegevens" betekent, en dan raadt hij verkeerd.
 */
.paneeluitleg {
  display: flex; flex-wrap: wrap; gap: 6px 16px;
  margin-top: 12px; padding-top: 11px;
  border-top: 1px solid var(--paneel-lijn);
  font-size: 11.5px; color: rgba(238, 243, 245, .5);
}
.paneeluitleg span { display: inline-flex; align-items: center; gap: 6px; }
.paneeluitleg i {
  width: 13px; height: 2.5px; border-radius: 2px; display: inline-block;
}
.paneeluitleg i.gat {
  width: 11px; height: 11px; border-radius: 3px;
  background: var(--paneel-gat); box-shadow: inset 0 1px 2px rgba(0, 0, 0, .45);
}

/*
 * Op een smal scherm schuiven en niet persen.
 *
 * Eerst stonden hier 1fr-kolommen: op een telefoon werd een poort dan 24 pixels
 * breed, en dan raakt een nummer van twee cijfers de rand en lopen de gaten in
 * elkaar over. Een patchpaneel is een voorwerp met vaste maten -- er past één
 * stekker in -- en het samenpersen tot telefoonbreedte maakt het onleesbaar op
 * precies het moment dat je het nodig hebt: met de telefoon in je hand, naast
 * de kast.
 *
 * Dus blijven de poorten even groot en mag de tekening zijdelings schuiven. De
 * pagina zelf schuift niet mee; dat gebeurt binnen dit ene vak.
 */
@media (max-width: 640px) {
  .poorten {
    flex-wrap: nowrap;
    overflow-x: auto;
    padding-bottom: 6px;
    -webkit-overflow-scrolling: touch;
  }
  .paneeluitleg { font-size: 11px; }
}

/* ── Technische tekeningen ───────────────────────────────────────────────────
 *
 * Met een voorbeeld en niet alleen een naam. Een lijst met
 * "netwerk-v3-definitief.pdf" en "netwerk-nieuw.png" vertelt je niets; twee
 * plaatjes naast elkaar wel.
 */

/*
 * ── De klantenkaarten op het beginscherm ──
 *
 * Hier stond een tabel: naam, plaats, aantal. Die las je regel voor regel,
 * want alle drie de kolommen zijn tekst en er is niets dat opvalt. De vraag
 * die je op dit scherm hebt is niet hoe een klant heet maar waar je heen moet.
 *
 * Het vierkantje met de initialen doet het werk. De kleurtoon volgt uit de
 * naam (zie klantToon()), dus dezelfde klant heeft altijd dezelfde kleur en
 * herken je hem aan de vorm van de kaart voordat je hebt gelezen. De
 * verzadiging en helderheid komen uit --tint-*, dezelfde vier waarden als bij
 * de tegels -- daarom werkt dit in licht en donker zonder een tweede lijst
 * kleuren, en klopt het contrast in beide standen.
 */
.klanten { display: grid; gap: 12px;
           grid-template-columns: repeat(auto-fill, minmax(min(288px, 100%), 1fr)); }

.klantkaart { position: relative; display: flex; gap: 13px; align-items: flex-start;
              width: 100%; padding: 14px 15px;
              background: var(--vlak); border: 1px solid var(--lijn);
              border-radius: var(--rond);
              font: inherit; color: inherit; text-align: left; cursor: pointer;
              transition: border-color .12s ease, box-shadow .12s ease; }
.klantkaart:hover { border-color: var(--flauw); box-shadow: var(--schaduw); }
.klantkaart:focus-visible { outline: 2px solid var(--merk); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .klantkaart { transition: none; } }

.klantkaart .merkteken {
  flex: 0 0 auto; width: 42px; height: 42px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 700; letter-spacing: .01em;
  background: hsl(var(--toon, 210) var(--tint-vs, 12%) var(--tint-vl, 90%));
  color: hsl(var(--toon, 210) var(--tint-is, 20%) var(--tint-il, 32%));
}

/* min-width: 0 zodat een lange klantnaam binnen de kaart afbreekt en de kaart
   niet oprekt -- dezelfde reden als bij de tegels. */
.klantkaart .tekst { display: flex; flex-direction: column; gap: 2px;
                     flex: 1; min-width: 0; }
.klantkaart .naam { font-weight: 600; font-size: 15px; line-height: 1.25;
                    overflow-wrap: anywhere; }
.klantkaart .waar { font-size: 12px; color: var(--stil); overflow-wrap: anywhere; }
.klantkaart .cijfers { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
/* Zonder pillen -- als het nakijken uit staat -- hoort er geen lege regel te
   blijven staan waar ze zouden hebben gestaan. */
.klantkaart .cijfers:empty { display: none; }

/* Het merkje "let op" hangt in de hoek en niet achter de naam: het gaat over
   de klant en niet over hoe hij heet, en achter een naam die afbreekt komt het
   op een tweede regel terecht waar je het niet meer ziet. */
.klantkaart > .merkje.let { position: absolute; top: 10px; right: 10px; }

/* Een klant die niet actief is blijft staan -- zijn gegevens zijn er nog --
   maar hij hoort niet even hard te roepen als de rest. */
.klantkaart.uit { background: var(--uit-vlak); }
.klantkaart.uit .naam { color: var(--stil); }
.klantkaart.uit .merkteken { filter: saturate(.35); opacity: .75; }

/* De pilletjes met de aantallen. Kleur én woord: op een scherm in de zon is
   kleur alleen geen onderscheid. */
.pil { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 20px;
       white-space: nowrap; }
.pil.oud  { background: hsl(4 var(--tint-vs) var(--tint-vl));
            color: hsl(4 var(--tint-is) var(--tint-il)); }
.pil.verl { background: hsl(38 var(--tint-vs) var(--tint-vl));
            color: hsl(38 var(--tint-is) var(--tint-il)); }
.pil.goed { background: hsl(150 var(--tint-vs) var(--tint-vl));
            color: hsl(150 var(--tint-is) var(--tint-il)); }

/*
 * ── De keuze tussen kaarten en een lijst ──
 *
 * Rechts in de knoppenbalk, weg van "Klant toevoegen": dat is een handeling
 * met gevolgen en dit is alleen hoe je kijkt. Twee knopjes en geen menuutje --
 * er zijn er twee, en een menu waar twee dingen in staan is een klik te veel.
 */
.weergave { display: flex; gap: 4px; margin-left: auto; }

/*
 * Het gekleurde vierkantje in de lijst.
 *
 * Kleiner dan op de kaart, en met dezelfde kleur en letters: wie omschakelt
 * hoort dezelfde klanten terug te zien en niet een ander scherm. De kolom is
 * smal en zonder rechterrand, zodat het stipje bij de naam hoort en niet als
 * eigen kolom leest.
 */
.stipkolom { width: 1%; padding-right: 0 !important; }
.stip { display: flex; align-items: center; justify-content: center;
        width: 26px; height: 26px; border-radius: 7px;
        font-size: 10px; font-weight: 700; letter-spacing: .01em;
        background: hsl(var(--toon, 210) var(--tint-vs, 12%) var(--tint-vl, 90%));
        color: hsl(var(--toon, 210) var(--tint-is, 20%) var(--tint-il, 32%)); }

/* Een klant die niet actief is: net als op de kaart aanwezig maar gedempt. */
tr.uit .stip { filter: saturate(.35); opacity: .75; }
tr.uit b { color: var(--stil); font-weight: 600; }
/* En kleiner, anders leest "Praktijk Duinzicht niet actief" als één naam --
   de naam is bij een inactieve klant al grijs, dus kleur alleen scheidt niet. */
td .waar { display: block; font-size: 12px; color: var(--stil); font-weight: 400; }

/* In de lijst staan de pillen in een cel en hoeven ze geen ruimte erboven. */
td .cijfers { display: flex; flex-wrap: wrap; gap: 5px; }

/*
 * ── De tweestapscode ──
 *
 * Groot en in cijfers die allemaal dezelfde breedte hebben: dit is een getal
 * dat iemand overtikt terwijl hij naar een ander scherm kijkt, en dan mag het
 * niet verschuiven terwijl het aftelt.
 *
 * De ring is een kegelverloop met een hoek die JavaScript per seconde bijstelt.
 * Geen animatie over dertig seconden: die loopt door als het tabblad naar de
 * achtergrond gaat en staat dan verkeerd zodra je terugkomt. Een stap per
 * seconde loopt altijd gelijk met wat de server zei.
 */
.codevak { display: flex; align-items: center; gap: 14px;
           background: var(--hover); border: 1px solid var(--lijn);
           border-radius: var(--rond); padding: 14px 16px; }
.codevak .code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
                 font-size: 30px; font-weight: 600; letter-spacing: .06em;
                 font-variant-numeric: tabular-nums; flex: 1; }
.codevak .knop { margin-left: auto; }
.codevak.verlopen .code { color: var(--flauw); }

.aftel { position: relative; width: 34px; height: 34px; flex: 0 0 auto;
         border-radius: 50%;
         background: conic-gradient(var(--merk) var(--deel, 100%),
                                    var(--lijn) var(--deel, 100%)); }
/* Het gaatje in het midden, met het getal erin. */
.aftel::before { content: ''; position: absolute; inset: 3px;
                 border-radius: 50%; background: var(--hover); }
.aftel > span { position: absolute; inset: 0; display: flex;
                align-items: center; justify-content: center;
                font-size: 12px; font-weight: 600; color: var(--stil);
                font-variant-numeric: tabular-nums; }

/* Het dichtklapbare blok voor de tweestapssleutel in het wijzigvenster. */
.veld > summary { cursor: pointer; font-size: 12px; font-weight: 600;
                  color: var(--stil); text-transform: uppercase;
                  letter-spacing: .06em; }
.veld > summary::marker { color: var(--flauw); }

/*
 * ── De tijdlijn van een klant ──
 *
 * Dezelfde vorm als het dagboek hierboven: de datum links in een eigen kolom,
 * de gebeurtenissen rechts. Die kolom is er zodat je hem kunt aflopen om te
 * vinden wanneer iets gebeurde -- en omdat het dagboek al zo leest, is dit
 * geen tweede manier om naar hetzelfde te kijken.
 *
 * Per dag gegroepeerd en niet per regel: met een datum boven elke regel lees
 * je vijftig datums en tien gebeurtenissen. Zo lees je tien dagen.
 */
.tdag { display: grid; grid-template-columns: 104px 1fr; gap: 14px;
        padding: 12px 0; border-bottom: 1px solid var(--lijn-fijn); }
.tdag:last-child { border-bottom: 0; }
.tdatum { font-size: 12px; color: var(--stil); font-variant-numeric: tabular-nums;
          padding-top: 3px; }
.tregels { display: flex; flex-direction: column; gap: 9px; min-width: 0; }

/* De soort links van de tekst, met een kleurstreepje dat de toon van de tegels
   volgt -- zo hoort een melding bij dezelfde kleur als de tegel Tickets. */
.tregel { display: grid; grid-template-columns: 92px 1fr; gap: 10px;
          align-items: start; min-width: 0; }
.tregel .merkje {
  background: hsl(var(--toon, 210) var(--tint-vs, 12%) var(--tint-vl, 90%));
  color: hsl(var(--toon, 210) var(--tint-is, 20%) var(--tint-il, 32%));
  justify-self: start;
}
.tinhoud { min-width: 0; }
.tinhoud b { font-weight: 600; overflow-wrap: anywhere; }
.tinhoud .waar { display: block; font-size: 12px; margin-top: 2px; }
/* De tekst van een aantekening: de regeleinden blijven staan, maar hij mag niet
   het hele scherm in beslag nemen -- vier regels is genoeg om te herkennen. */
.tmeer { font-size: 13px; color: var(--inkt-zacht); white-space: pre-wrap;
         margin-top: 3px; display: -webkit-box; -webkit-line-clamp: 4;
         -webkit-box-orient: vertical; overflow: hidden; }

@media (max-width: 620px) {
  /* Op een telefoon past geen datumkolom naast de inhoud. */
  .tdag { grid-template-columns: 1fr; gap: 6px; }
  .tdatum { font-weight: 600; color: var(--inkt); }
  .tregel { grid-template-columns: 1fr; gap: 3px; }
}

/*
 * ── Het noodblad ──
 *
 * Dit blad bestaat om afgedrukt te worden en daarna acht maanden in een kluis
 * te liggen. Dus: geen kleurvlakken die op een zwart-witprinter grijs worden,
 * wachtwoorden in een letter waarin een l en een 1 verschillen, en de datum
 * groot bovenaan -- want het eerste dat je bij zo'n blad wil weten, is of het
 * nog klopt.
 */
.noodblad { background: var(--vlak); border: 1px solid var(--lijn);
            border-radius: var(--rond); padding: 26px 28px 30px; max-width: 900px; }
.nbkop { border-bottom: 2px solid var(--inkt); padding-bottom: 14px; margin-bottom: 20px; }
.nbkop h2 { margin: 0 0 6px; }
.nbkop p { margin: 0; font-size: 13px; color: var(--inkt-zacht); max-width: 68ch; }

.nbletop { border: 1px solid var(--let-lijn); background: var(--let-vlak);
           color: var(--let-inkt); border-radius: var(--rond);
           padding: 11px 14px; margin-bottom: 18px; font-size: 14px; }
.nbletop b { margin-right: 6px; }

.noodblad table { margin-bottom: 22px; }
.noodblad h3 { margin: 26px 0 10px; }
/* Het wachtwoord zelf: groter, en met ruimte tussen de tekens. Dit wordt van
   papier overgetikt onder tijdsdruk, en dan is een l naast een 1 een fout die
   je pas merkt als de aanmelding wordt geweigerd. */
.nbwoord { font-size: 15px; letter-spacing: .06em; font-weight: 600;
           word-break: break-all; }

@media print {
  .noodblad { border: 0; padding: 0; max-width: none; }
  .nbletop { border-color: #999; background: #fff; color: #000; }
  /* Elke regel bij elkaar houden: een wachtwoord dat over twee bladzijden
     wordt afgebroken, is een wachtwoord dat je verkeerd overtikt. */
  .noodblad tr { break-inside: avoid; page-break-inside: avoid; }
}

/*
 * ── De kennisbase ──
 *
 * Categorieën links als een inhoudsopgave, de artikelen rechts. Niet als
 * tabbladen: die zijn er voor een handvol en staan naast elkaar, en er kunnen
 * vierentwintig categorieën zijn met namen die iemand zelf bedenkt.
 */
.kennis { display: grid; grid-template-columns: 248px 1fr; gap: 24px; align-items: start; }

.knzij { position: sticky; top: 84px; }
.knzij input[type="search"] { width: 100%; margin-bottom: 12px; }
.knlijst { display: flex; flex-direction: column; gap: 1px; }

.kncat { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
         padding: 9px 11px; border: 0; border-radius: 8px; background: none;
         font: inherit; font-size: 14px; color: var(--inkt-zacht); cursor: pointer; }
.kncat:hover { background: var(--hover); color: var(--inkt); }
.kncat > span:first-child { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.kncat .aantal { font-size: 12px; color: var(--flauw); font-variant-numeric: tabular-nums; }
.kncat.aan { background: var(--gekozen-vlak); color: var(--gekozen-tekst); font-weight: 600; }
.kncat.aan .aantal { color: var(--gekozen-naam); }

.knvak { min-width: 0; }

/* Een artikel in de lijst. Titel, het begin van de tekst en de labels: genoeg
   om te weten of dit het is zonder hem te openen. */
.knregel { display: flex; align-items: flex-start; gap: 14px; width: 100%;
           text-align: left; padding: 12px 15px; border: 0;
           border-bottom: 1px solid var(--lijn-fijn); background: none;
           font: inherit; cursor: pointer; }
.knregel:last-child { border-bottom: 0; }
.knregel:hover { background: var(--hover); }
.knregel > div { flex: 1; min-width: 0; }
.knregel .waar { display: block; font-size: 12px; margin-top: 2px; }
.knregel .merkje { margin-top: 5px; margin-right: 4px; }
.knregel > .waar { flex: 0 0 auto; white-space: nowrap; font-size: 12px; }

/*
 * De tekst van een artikel.
 *
 * pre-wrap en niet een opmaaktaal: wie een werkwijze opschrijft, typt regels
 * en een streepje ervoor. Dat door een markdown-vertaler halen betekent dat
 * een sterretje in een pad ineens vet wordt, en dan moet iemand de regels van
 * die taal kennen om iets op te kunnen schrijven.
 */
.artekst { white-space: pre-wrap; line-height: 1.65; overflow-wrap: anywhere; }

/*
 * ── Een artikel met opmaak ──
 *
 * Twee vormen: .artekst voor de artikelen van vroeger (platte tekst met de
 * regeleinden aan) en .aropmaak voor de opgemaakte. Ze staan naast elkaar
 * omdat een artikel van vóór deze functie er niet ineens anders uit hoort te
 * zien -- en omdat platte tekst met pre-wrap nog steeds de juiste weergave is
 * voor iets dat zo is ingetypt.
 */
.aropmaak { line-height: 1.65; overflow-wrap: anywhere; }
.aropmaak p { margin: 0 0 12px; }
.aropmaak h3, .aropmaak h4 { margin: 22px 0 8px; }
.aropmaak ul, .aropmaak ol { margin: 0 0 12px; padding-left: 22px; }
.aropmaak li { margin-bottom: 4px; }
.aropmaak code { background: var(--hover); padding: 1px 5px; border-radius: 4px;
                 font-size: .92em; }
.aropmaak pre { background: var(--hover); padding: 12px 14px; border-radius: var(--rond);
                overflow-x: auto; }
.aropmaak pre code { background: none; padding: 0; }
.aropmaak blockquote { margin: 0 0 12px; padding-left: 14px;
                       border-left: 3px solid var(--lijn); color: var(--inkt-zacht); }
.aropmaak table { margin: 0 0 14px; }
/* Een schermafdruk mag nooit breder dan het venster: dan schuift het artikel
   zijwaarts en is de tekst niet meer te lezen. */
.aropmaak img, .arwerk img { max-width: 100%; height: auto; display: block;
                             margin: 12px 0; border: 1px solid var(--lijn);
                             border-radius: 6px; }
.aropmaak a { color: var(--merk); }

/*
 * Het werkveld waarin je typt en plakt.
 *
 * Een vaste minimumhoogte en meegroeiend: een veld dat bij het typen van
 * hoogte verandert laat de knoppen eronder wegspringen precies terwijl je
 * doortypt.
 */
/*
 * De knoppenbalk boven het artikelveld.
 *
 * Vast aan het veld eronder: één blok in plaats van twee losse dingen, zodat
 * duidelijk is dat die knoppen bij dít vak horen en niet bij het formulier.
 */
.arbalk { display: flex; flex-wrap: wrap; align-items: center; gap: 3px;
          border: 1px solid var(--lijn); border-bottom: 0;
          border-radius: var(--rond) var(--rond) 0 0;
          background: var(--hover); padding: 7px 8px; }
.arknop { font: inherit; font-size: 13px; padding: 4px 9px; border: 0;
          border-radius: 6px; background: none; color: var(--inkt-zacht);
          cursor: pointer; }
.arknop:hover { background: var(--vlak); color: var(--inkt); }
.arknop:active { background: var(--lijn); }
.arscheiding { width: 1px; height: 20px; background: var(--lijn); margin: 0 5px; }

.arwerk { min-height: 260px; max-height: 52vh; overflow-y: auto;
          border: 1px solid var(--lijn); border-radius: 0 0 var(--rond) var(--rond);
          padding: 13px 15px; background: var(--vlak);
          line-height: 1.6; }
.arwerk:focus { outline: 2px solid var(--merk); outline-offset: -1px; }
.arwerk p { margin: 0 0 10px; }
.arwerk h3 { font-size: 17px; margin: 16px 0 8px; }
.arwerk pre { background: var(--hover); padding: 10px 12px; border-radius: 8px;
              overflow-x: auto; font-size: 13px; }
.arwerk a { color: var(--merk); }
/* Een leeg veld hoort te zeggen dat je kunt beginnen. */
.arwerk:empty::before { content: 'Typ hier, of plak een artikel. Een afbeelding kun je '
                                 'erin slepen of met de knop hierboven toevoegen.';
                        color: var(--flauw); }
.arwerk ul, .arwerk ol { margin: 0 0 10px; padding-left: 22px; }
.arwerk table { width: auto; }
.arwerk td, .arwerk th { border: 1px solid var(--lijn); padding: 5px 8px; }

/* Een plaatje dat nog wordt opgehaald: een plaatshouder op de plek waar hij
   komt. Zonder dit valt er een gat in het artikel en lijkt de afbeelding
   verdwenen terwijl hij onderweg is. */
.arbezig { display: block; width: 100%; max-width: 260px; height: 60px;
           border: 1px dashed var(--lijn); border-radius: 6px;
           background: var(--hover); margin: 12px 0; }
.arbezig::after { content: 'afbeelding ophalen…'; display: block;
                  padding: 21px 12px; font-size: 12px; color: var(--stil); }

/* Terwijl je een bestand erboven houdt. Zonder dit weet je niet of je op de
   goede plek bent, en dan laat je los boven de pagina -- en dan opent de
   browser het plaatje in plaats van het artikel bij te werken. */
.arwerk.arsleep { outline: 2px dashed var(--merk); outline-offset: -2px;
                  background: var(--goed-vlak); }

.kcrij { display: flex; gap: 8px; margin-bottom: 8px; }
.kcrij input { flex: 1; }

@media (max-width: 800px) {
  /* Op een smal scherm de inhoudsopgave boven de lijst; naast elkaar past niet
     en een kolom van 248px naast 200px is twee halve schermen. */
  .kennis { grid-template-columns: 1fr; gap: 16px; }
  .knzij { position: static; }
  .knlijst { flex-direction: row; flex-wrap: wrap; gap: 4px; }
  .kncat { width: auto; border: 1px solid var(--lijn); }
}

.tekeningen { display: grid; grid-template-columns: repeat(auto-fill, minmax(216px, 1fr)); gap: 14px; }

.tekening { background: var(--vlak); border: 1px solid var(--lijn); border-radius: var(--rond);
            overflow: hidden; cursor: pointer; box-shadow: var(--schaduw); }
.tekening:hover { border-color: var(--flauw); }

/* Een vaste hoogte voor het voorbeeld, want tekeningen hebben alle verhoudingen
 * die er bestaan -- en een raster waarin elke kaart een andere hoogte heeft is
 * geen raster meer. */
.voorbeeld { height: 132px; background: var(--hover); border-bottom: 1px solid var(--lijn-fijn);
             display: grid; place-items: center; overflow: hidden; }
.voorbeeld img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
.voorbeeld.pdf { background: var(--paneel); }
.voorbeeld .soortje { font-family: "IBM Plex Mono", monospace; font-size: 15px; letter-spacing: 2px;
                      color: var(--paneel-tekst); opacity: .5; }

.tkop { padding: 11px 13px; display: flex; flex-direction: column; gap: 3px; }
.tkop b { font-size: 14px; line-height: 1.35; }
.tkop .waar { font-size: 12px; color: var(--stil); }

.grootvoorbeeld { display: block; width: 100%; max-height: 62vh; object-fit: contain;
                  background: var(--hover); border: 1px solid var(--lijn); border-radius: 8px; }
object.grootvoorbeeld { height: 62vh; }

/* Een bestandsveld ziet er standaard in elke browser anders uit; dit maakt hem
 * in elk geval even hoog als de velden eromheen. */
input[type=file] { padding: 8px 10px; font-size: 13.5px; background: var(--hover); }

/* ── MFA klaarzetten ────────────────────────────────────────────────────────
 *
 * De QR-code naast de uitleg en niet erboven. Wie hem scant heeft zijn telefoon
 * in de hand en leest de stappen ernaast; boven elkaar moet hij scrollen
 * terwijl hij bezig is.
 */
.mfarij { display: grid; grid-template-columns: 190px 1fr; gap: 22px; align-items: start; }
@media (max-width: 640px) { .mfarij { grid-template-columns: 1fr; } }

.qrvak { background: var(--vlak); border: 1px solid var(--lijn); border-radius: 10px;
         padding: 10px; }
.qrvak svg { display: block; width: 100%; height: auto; }
.mfarij p { margin: 0 0 12px; font-size: 14px; line-height: 1.5; }
.mfarij p b { font-family: "IBM Plex Mono", monospace; }

/* ── De adressenlijst van het filter ─────────────────────────────────────────
 *
 * Het adres in mono en breed genoeg voor een IPv6-bereik; de omschrijving
 * ernaast, want een lijst met acht adressen zonder uitleg is over een jaar
 * acht adressen die niemand durft weg te halen.
 */
.iplijst { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; }
.iprij { display: grid; grid-template-columns: minmax(0, 260px) minmax(0, 1fr) auto;
         gap: 8px; align-items: center; }
@media (max-width: 640px) { .iprij { grid-template-columns: 1fr; } }

/* ── De nakijkronde ──────────────────────────────────────────────────────────
 *
 * Drie knoppen naast elkaar, even breed, zodat je met je oog niet hoeft te
 * zoeken welke waar staat. Bij veertig regels op een rij is dat het verschil
 * tussen aantikken en lezen.
 */
.rondeknoppen { display: inline-grid; grid-template-columns: repeat(3, 1fr); gap: 5px;
                width: 260px; }
.rondeknoppen .knop { justify-content: center; padding: 7px 4px; font-size: 12px; }
.rondeknoppen .knop.gekozen { background: var(--knop-vlak); color: var(--knop-tekst);
                              border-color: var(--knop-vlak);
                              font-weight: 600; }
@media (max-width: 880px) {
  .rondeknoppen { width: 100%; }
  /* Op een telefoon staan de knoppen onder de regel in plaats van ernaast. */
  .kaart table td.r .rondeknoppen { width: 100%; }
}

/* ── Het verschil in het logboek ─────────────────────────────────────────────
 *
 * Één regel per veld: wat het was, een pijl, wat het werd. Geen twee kolommen
 * naast elkaar -- dan moet je heen en weer kijken om te zien wat er veranderde,
 * en bij een onderdeel met twaalf velden is dat precies het werk dat dit
 * scherm hoort weg te nemen.
 */
.verschil { margin-top: 8px; display: flex; flex-direction: column; gap: 3px; }

.vregel {
  display: grid;
  grid-template-columns: minmax(90px, auto) 1fr auto 1fr;
  gap: 8px;
  align-items: baseline;
  font-size: 12.5px;
  line-height: 1.5;
}

.vveld { color: var(--stil); font-weight: 600; }

/* Wat het was doorgestreept: dan zie je in één oogopslag welke kant de pijl op
 * wijst, ook als beide waarden op elkaar lijken -- 192.168.1.10 en .12. */
.vwas   { color: var(--stil); text-decoration: line-through; word-break: break-word; }
.vpijl  { color: var(--stil); }
.vwordt { color: var(--inkt); font-weight: 500; word-break: break-word; }

.reden {
  margin-top: 6px;
  font-size: 12.5px;
  font-style: italic;
  color: var(--stil);
}

/* Op een telefoon past die vier-koloms indeling niet; dan onder elkaar. */
@media (max-width: 640px) {
  .vregel { grid-template-columns: 1fr; gap: 1px; }
  .vpijl { display: none; }
  .vwas::after { content: ' →'; }
}

/* ── Labels en standen ───────────────────────────────────────────────────────
 *
 * Etiketjes zonder kleur per stuk. Een kleur per label klinkt aardig tot er
 * twintig labels zijn en het scherm eruitziet als een snoeptrommel; de kleuren
 * in dit systeem betekenen iets (de drie lampjes), en die betekenis houdt op
 * zodra er versiering bijkomt.
 */
.labels { display: inline-flex; flex-wrap: wrap; gap: 4px; }

.label {
  display: inline-block;
  padding: 1px 7px;
  border: 1px solid var(--lijn);
  border-radius: 999px;
  background: var(--hover);
  color: var(--inkt-zacht);
  font-size: 11.5px;
  line-height: 1.6;
  white-space: nowrap;
}

/* De stand. "In gebruik" krijgt niets -- dat is de gewone toestand, en een
 * lijst waarin alles even hard roept, roept niets. */
.stand.s-gepland,
.stand.s-uitfaseren,
.stand.s-uit {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
}
.stand.s-gepland    { background: var(--goed-vlak); color: var(--goed-inkt);
                      border: 1px solid var(--goed-lijn); }
.stand.s-uitfaseren { background: var(--let-vlak); color: var(--let-inkt);
                      border: 1px solid var(--let-lijn); }
.stand.s-uit        { background: var(--uit-vlak); color: var(--stil);
                      border: 1px solid var(--lijn); }

/* ── Filterknopjes boven een lijst ─────────────────────────────────────────── */
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--lijn);
  border-radius: 999px;
  background: var(--vlak);
  color: var(--inkt-zacht);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
}
.chip span { color: var(--flauw); font-variant-numeric: tabular-nums; }
.chip:hover { background: var(--hover); }
.chip.aan { background: var(--paneel); border-color: var(--paneel); color: var(--paneel-tekst); }
.chip.aan span { color: rgba(238, 243, 245, .6); }
.chip.weg { border-style: dashed; color: var(--stil); }

/* ── Het dagboek ─────────────────────────────────────────────────────────────
 *
 * Een tijdlijn met de datum links. Die datum links en niet in de kaart: dan
 * kun je de kolom aflopen om te vinden wanneer iets gebeurde, en dat is de
 * manier waarop iemand een dagboek werkelijk leest.
 */
.tijdlijn { display: flex; flex-direction: column; gap: 2px; }

.dbregel {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 14px;
  padding: 10px 0;
  cursor: pointer;
  border-left: 2px solid var(--lijn-fijn);
  padding-left: 14px;
}
.dbregel:hover { border-left-color: var(--paneel); background: var(--hover); }

.dbdatum {
  color: var(--stil);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  padding-top: 2px;
}

.dbkaart { min-width: 0; }

.dbkop {
  display: flex;
  gap: 10px;
  align-items: baseline;
  margin-bottom: 3px;
}
.dbwaar { font-weight: 600; font-size: 13px; }
.dbwie  { color: var(--flauw); font-size: 12px; }

.dbtekst { color: var(--inkt-zacht); font-size: 13.5px; line-height: 1.55; word-break: break-word; }

/* ── Het blokje onder een onderdeel ── */
.dbblok { margin-top: 20px; border-top: 1px solid var(--lijn-fijn); padding-top: 14px; }

.dbkop2 {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
  font-size: 13px;
  margin-bottom: 8px;
}

.dblijst { display: flex; flex-direction: column; gap: 4px; }

.dbklein {
  display: grid;
  grid-template-columns: 84px 1fr auto;
  gap: 10px;
  font-size: 12.5px;
  padding: 4px 0;
  border-bottom: 1px solid var(--lijn-fijn);
}
.dbdatum2 { color: var(--stil); font-variant-numeric: tabular-nums; }
.dbtekst2 { color: var(--inkt-zacht); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dbwie2   { color: var(--flauw); }

@media (max-width: 640px) {
  .dbregel { grid-template-columns: 1fr; gap: 2px; }
  .dbklein { grid-template-columns: 1fr; gap: 0; }
  .dbtekst2 { white-space: normal; }
}

/* Een knopje in de kop van een paneel. Rustig, want de tekening eronder is
 * waar je naar kijkt -- dit is alleen de weg om de maat recht te zetten. */
.paneelknop {
  margin-left: auto;
  padding: 3px 10px;
  border: 1px solid var(--paneel-lijn);
  border-radius: 999px;
  background: transparent;
  color: rgba(238, 243, 245, .55);
  font: inherit;
  font-size: 11.5px;
  cursor: pointer;
}
.paneelknop:hover { background: var(--paneel-op); color: var(--paneel-tekst); }

/* ── Netwerk: subnetten met hun bezetting ────────────────────────────────────
 *
 * De bezetting als balk én als getal. Alleen een balk is niet te lezen ("half
 * vol" bij een /24 kan 127 adressen zijn), alleen een getal zegt niets over hoe
 * ver het is. Samen zijn ze in één oogopslag te vatten en precies na te lezen.
 */
.subnetkaart { padding: 14px 16px 12px; margin-bottom: 12px; }

.subnetkop {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  flex-wrap: wrap;
}
.subnetkop > div:first-child { flex: 1 1 220px; min-width: 0; }
.subnetkop b { font-size: 15px; }
.subnetnaam { color: var(--inkt-zacht); font-size: 13.5px; }
.subnetkop .waar { font-size: 12px; margin-top: 3px; }

.subnetvul { display: flex; align-items: center; gap: 9px; flex: 0 0 auto; }

.vulbalk {
  width: 110px; height: 7px;
  background: var(--lijn-fijn);
  border-radius: 999px;
  overflow: hidden;
}
.vulbalk i { display: block; height: 100%; background: var(--merk); border-radius: 999px; }

.vultekst {
  font-family: "IBM Plex Mono", monospace;
  font-size: 12px;
  color: var(--stil);
  font-variant-numeric: tabular-nums;
}

/*
 * De eerste vrije adressen als knopjes.
 *
 * Dit is waar het hele onderdeel om draait: "welk adres kan ik pakken". Als
 * knop en niet als tekst, want het antwoord op die vraag is bijna altijd
 * "die, en die wil ik nu vastleggen" -- en dan hoeft niemand hem over te typen.
 */
.vrijrij {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin: 12px 0 4px;
}
.vrijkop { font-size: 12px; color: var(--stil); margin-right: 2px; }

.vrijknop {
  font-family: "IBM Plex Mono", monospace;
  font-size: 12px;
  padding: 3px 9px;
  border: 1px dashed var(--lijn);
  border-radius: 999px;
  background: var(--vlak);
  color: var(--inkt-zacht);
  cursor: pointer;
}
.vrijknop:hover { border-style: solid; border-color: var(--merk); color: var(--merk); }

.adreslijst { margin-top: 10px; }
.adreslijst td { padding: 5px 8px; }
.adreslijst tr:first-child td { border-top: 1px solid var(--lijn-fijn); }

/* ── De weg die een kabel aflegt ─────────────────────────────────────────────
 *
 * wandcontact → paneel → switch → apparaat. Als weg en niet als vier kolommen
 * in een tabel: het is één kabel met een begin en een eind, en dat is hoe
 * iemand ernaar zoekt.
 *
 * Boven elke stap staat wát het is. Zonder dat leest "12 → A 12 → SW1 poort 7"
 * als een rij nummers waarvan je moet raden welke welke is.
 */
.padblok { margin-top: 18px; border-top: 1px solid var(--lijn-fijn); padding-top: 14px; }

.pad {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 4px 8px;
  margin-bottom: 6px;
}

.padstap {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.padwat {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .7px;
  color: var(--flauw);
}

.padnaam {
  font-family: "IBM Plex Mono", monospace;
  font-size: 12.5px;
  color: var(--inkt);
  padding: 3px 9px;
  border: 1px solid var(--lijn);
  border-radius: 5px;
  background: var(--vlak);
  text-align: left;
}

/* Een stap met een onderdeel erachter is een knop: van de switch naar de server
 * en terug, want dat is de beweging die iemand tijdens een storing maakt. */
button.padnaam { cursor: pointer; font: inherit; font-family: "IBM Plex Mono", monospace;
                 font-size: 12.5px; }
button.padnaam:hover { border-color: var(--merk); color: var(--merk); }

.padpijl { color: var(--flauw); padding-bottom: 4px; }

@media (max-width: 560px) {
  .pad { flex-direction: column; align-items: stretch; }
  .padpijl { display: none; }
  .padstap + .padstap { margin-top: 4px; }
}

/* ── De lijn tussen een switchpoort en een paneelpoort ───────────────────────
 *
 * Waarvoor de tekening bestaat. Een switchpoort en een paneelpoort zijn twee
 * kanten van dezelfde patchkabel, en dat stond tot nu toe als vier velden op
 * een tabelregel — je moest zelf onthouden welk nummer bij welk hoorde.
 *
 * De svg ligt over de tekeningen en vangt geen muis: anders is de poort eronder
 * niet meer aan te wijzen, en dan is de lijn er wel en werkt er niets meer.
 */
.tekenvak { position: relative; }

.lijnen {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
  z-index: 3;
}

.lijn {
  fill: none;
  stroke: var(--merk);
  stroke-width: 1.5;
  stroke-linecap: round;
  opacity: .45;
}
.lijn.sterk { stroke-width: 2.5; opacity: 1; }

/* De tegenpoort oplichten. Ook nodig als de lijn zelf kort is: bij twee poorten
 * die vlak bij elkaar liggen is de boog nauwelijks te zien, en dan is het
 * randje het antwoord. */
.poort.aangewezen {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16),
              0 0 0 2px var(--merk);
  z-index: 4;
}

/* ── De switch als tekening ──────────────────────────────────────────────────
 *
 * Dezelfde poortjes als een patchpaneel, met opzet: twee manieren van tekenen
 * zouden er net anders uitzien, en dan moet iemand twee keer leren wat een
 * kleur betekent.
 */
.switchtekening { position: relative; }

/*
 * De uplinks staan apart, met een bredere naad ervoor.
 *
 * Niet alleen mooi: op de doos staat "28 poorten" en dat is 24 koper plus 4
 * SFP, en in het rek zitten die vier ook los van de rij. Ze doorlopend
 * nummeren zou betekenen dat wat hier poort 25 heet, op het apparaat SFP 1 is.
 */
.sfpblok {
  margin-left: 14px;
  padding-left: 14px;
  border-left: 1px dashed var(--paneel-lijn);
}

/* Een glasvezelpoort is smaller en hoger dan een RJ45 — zoals in het echt. */
.poort.sfp { border-radius: 3px; }
.blok.sfpblok { grid-template-columns: repeat(4, 28px); }

.sfpuitleg {
  margin-left: auto;
  font-family: "IBM Plex Mono", monospace;
  font-size: 11.5px;
  color: rgba(238, 243, 245, .42);
}

.paneelknop.aan,
.knop.klein.aan { background: var(--merk); border-color: var(--merk); color: #fff; }

/* Bij "alle lijnen" begint de lijn bij de rand van de kast en niet bij de poort
 * zelf; dit stipje wijst aan welke poort erbij hoort. */
.poort.geknoopt::before {
  content: '';
  position: absolute;
  bottom: -4px;
  left: 50%;
  width: 4px;
  height: 4px;
  margin-left: -2px;
  border-radius: 50%;
  background: var(--merk);
  opacity: 1;
  z-index: 4;
}

/* ── Tabs binnen een scherm ──────────────────────────────────────────────────
 *
 * Voor schermen die bij elkaar horen maar niet op één pagina passen:
 * instellingen met de eigen velden, de modellen en de gebruikers eronder, en
 * het logboek met zijn twee soorten.
 *
 * Een onderstreping en geen doosjes. Doosjes lezen als knoppen die iets doen;
 * een tab is een plek waar je bent, en dat is een ander soort ding. De actieve
 * tab draagt de lijn, en de lijn eronder loopt door — zo hangen ze aan
 * dezelfde balk in plaats van los te zweven.
 */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--lijn);
}

.tab {
  padding: 8px 14px 9px;
  margin-bottom: -1px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--stil);
  font: inherit;
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
}
.tab:hover { color: var(--inkt); background: var(--hover); }

.tab.aan {
  color: var(--inkt);
  font-weight: 600;
  border-bottom-color: var(--merk);
}
.tab.aan:hover { background: transparent; }

@media (max-width: 560px) {
  .tabs { gap: 0; overflow-x: auto; }
  .tab { padding: 8px 11px 9px; font-size: 13px; }
}

/* Het ruwe antwoord van een koppeling. Klein, met een schuifbalk, en niet
 * afgekapt: je moet er een veldnaam in kunnen terugvinden. */
pre.ruw {
  margin: 8px 0 0;
  padding: 12px 14px;
  max-height: 260px;
  overflow: auto;
  background: var(--paneel-gat);
  color: rgba(238, 243, 245, .82);
  border-radius: 8px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 11.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-all;
}

ul.uitlegrij { margin: 0; padding-left: 20px; display: grid; gap: 9px; }
ul.uitlegrij li { color: var(--inkt-zacht); font-size: 14.5px; line-height: 1.6; }

/* Een rij die er niet meer is: aanwezig maar gedempt. Weghalen zou betekenen
 * dat een kapotte agent een apparaat uit de documentatie laat verdwijnen. */
tr.flauw td { opacity: .55; }
tr.flauw:hover td { opacity: 1; }

/* ── Een koppeling kiezen ────────────────────────────────────────────────────
 *
 * Zes tegels en geen keuzelijst. Je kiest je RMM één keer en daarna nooit meer;
 * dat is geen instelling tussen andere instellingen maar een keuze uit zes
 * pakketten, en dan hoort het eruit te zien als een keuze.
 *
 * Wat nog niet af is staat er gedempt bij en niet weggelaten. Een pakket dat
 * ontbreekt laat iemand zoeken; een pakket dat er staat met "nog niet af" is
 * een antwoord.
 */
.pakketten {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin-top: 4px;
}

.pakket {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 15px;
  border: 1px solid var(--lijn);
  border-radius: 10px;
  background: var(--vlak);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.pakket:hover { border-color: var(--flauw); background: var(--hover); }

.pakket b { font-size: 14.5px; font-weight: 600; }
.pakket span {
  font-size: 11.5px;
  color: var(--stil);
  font-family: "IBM Plex Mono", monospace;
}

/* De gekozen: een rand in de merkkleur en een vinkje. Niet een gevulde tegel --
 * dan schreeuwt de keuze harder dan de gegevens die eronder staan. */
.pakket.aan {
  border-color: var(--merk);
  box-shadow: inset 0 0 0 1px var(--merk);
  background: var(--vlak);
}
.pakket.aan::after {
  content: '✓';
  position: absolute;
  top: 10px; right: 12px;
  color: var(--merk);
  font-size: 13px;
  font-weight: 700;
}

.pakket.nietaf { background: var(--hover); border-style: dashed; }
.pakket.nietaf b { color: var(--stil); }

/* "Geen koppeling" hoort erbij te staan als keuze en niet als lege regel in een
 * lijst: uitzetten is ook een keuze. */
.pakket.geen { border-style: dashed; }

/* ── Netwerktegels ─────────────────────────────────────────────────────────
 *
 * Dezelfde tegels als bij de RMM, maar met een lampje in plaats van "koppeling
 * klaar": hier gaat het niet om of de koppeling gebouwd is maar of hij werkt.
 * Het formulier van de open tegel staat eronder; de andere twee zijn dicht. */
.netwerktegels .pakket span { display: flex; align-items: center; gap: 6px; }
.netwerktegels .bol {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  flex: none;
}
.netwerktegels .bol.goed  { background: var(--led-goed); box-shadow: 0 0 0 3px rgba(52,192,122,.16); }
.netwerktegels .bol.fout  { background: var(--led-fout); box-shadow: 0 0 0 3px rgba(232,92,80,.16); }
.netwerktegels .bol.niets { background: var(--led-uit); }

.netwerkvak { margin-top: 14px; }
.netwerkvak[hidden] { display: none; }

/* Eén tegel hoort niet de hele breedte te vullen. */
.m365tegel { grid-template-columns: minmax(150px, 320px); }

/* Op het 365-overzicht bij een klant: wat uitstaat, staat er gedempt bij. */
.uitlegtegel.uit { opacity: .55; border-style: dashed; }

/* ── De gebruikerslijst uit 365 ──────────────────────────────────────────
 *
 * Vaste kolombreedtes, want de inhoud verschilt per rij enorm: iemand met
 * vijf licenties naast iemand met geen, een functie van dertig tekens naast
 * een lege. Zonder breedtes springt elke kolom per klant ergens anders heen. */
.gbtabel { table-layout: fixed; }
.gbtabel th:nth-child(1), .gbtabel td:nth-child(1) { width: 27%; }
.gbtabel th:nth-child(2), .gbtabel td:nth-child(2) { width: 17%; }
.gbtabel th:nth-child(3), .gbtabel td:nth-child(3) { width: 22%; }
.gbtabel th:nth-child(4), .gbtabel td:nth-child(4) { width: 11%; }
.gbtabel th:nth-child(5), .gbtabel td:nth-child(5) { width: 11%; white-space: nowrap; }
.gbtabel th:nth-child(6), .gbtabel td:nth-child(6) { width: 12%; }
.gbtabel td { overflow-wrap: anywhere; }
.gbtabel td .uitleg { margin: 2px 0 0; font-size: 11.5px; }
.gbtabel tr.gedempt td { opacity: .6; }
.gbtabel tr.groepkop td {
  padding: 16px 14px 6px;
  font-size: 10px; text-transform: uppercase; letter-spacing: 1.2px;
  color: var(--stil); font-weight: 600; border-bottom: 1px solid var(--lijn);
  background: transparent;
}
.gbtabel tr.groepkop:first-child td { padding-top: 6px; }
.gbtabel tr[hidden] { display: none; }
.gbtabel .stil { color: var(--stil); font-weight: 400; }

/* ── Werkt het ─────────────────────────────────────────────────────────────
 *
 * Het belangrijkste op een instellingenscherm voor een koppeling, en het stond
 * er niet: doet hij het. Een scherm met een sleutel erin en geen woord over of
 * die sleutel werkt, laat iemand gokken.
 */
.staat {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 13px 16px;
  border: 1px solid var(--lijn);
  border-radius: 10px;
  background: var(--vlak);
  margin-bottom: 14px;
}
.staat .bol { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.staat .bol.goed { background: var(--led-goed); box-shadow: 0 0 0 3px rgba(52,192,122,.16); }
.staat .bol.fout { background: var(--led-fout); box-shadow: 0 0 0 3px rgba(232,92,80,.16); }
.staat .bol.niets { background: var(--led-uit); }
.staat .wat { font-weight: 600; font-size: 14px; }
.staat .wanneer { color: var(--stil); font-size: 13px; }
.staat .rechts { margin-left: auto; }

/* ── De uitleg naast elkaar in plaats van vier lange regels ────────────────── */
.uitlegtegels {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.uitlegtegel {
  padding: 15px 16px;
  border: 1px solid var(--lijn-fijn);
  border-radius: 10px;
  background: var(--hover);
}
.uitlegtegel b { display: block; font-size: 13.5px; margin-bottom: 4px; }
.uitlegtegel span { font-size: 13px; color: var(--inkt-zacht); line-height: 1.55; }


/* ── Foto's ──────────────────────────────────────────────────────────────────
 *
 * Miniaturen in een rij die kan schuiven, niet in een raster dat de hoogte van
 * het venster opeet. Bij twaalf foto's van een meterkast wil je ze kunnen
 * langslopen; je wil niet dat ze het formulier eronder wegdrukken.
 */
.fotorij {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 2px 0 8px;
  -webkit-overflow-scrolling: touch;
}

.fototegel {
  flex: 0 0 auto;
  width: 96px;
  height: 96px;
  padding: 0;
  border: 1px solid var(--lijn);
  border-radius: 8px;
  background: var(--hover);
  overflow: hidden;
  cursor: pointer;
}
.fototegel:hover { border-color: var(--merk); }
.fototegel img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* De hele foto in een venster: passend gemaakt en niet opgerekt. Een foto van
 * een label mag klein blijven; hem uitrekken maakt hem onleesbaar. */
.fotogroot {
  display: flex;
  align-items: center;
  justify-content: center;
  max-height: 60vh;
  background: var(--paneel-gat);
  border-radius: 9px;
  overflow: hidden;
}
.fotogroot img { max-width: 100%; max-height: 60vh; object-fit: contain; display: block; }

/* Een label dat als knop dient voor een verborgen bestandsveld. Zonder dit
 * gedraagt het zich als tekst en niet als knop. */
label.knop { cursor: pointer; }


/* ── Stickers ────────────────────────────────────────────────────────────────
 *
 * Een raster van labels dat op papier hetzelfde staat als op het scherm. In
 * millimeters en niet in pixels: je legt dit naast een vel stickers en dan wil
 * je een maat die op een liniaal staat.
 *
 * De QR heeft een witte rand nodig -- de norm noemt vier blokjes, hier twee
 * omdat de sticker zelf al wit is. Zonder rand leest een telefoon hem niet.
 */
.stickervel {
  display: grid;
  gap: 3mm;
  margin-top: 24px;
}
.sticker {
  display: flex;
  align-items: center;
  gap: 3mm;
  padding: 3mm;
  border: 1px dashed var(--lijn);
  border-radius: 2mm;
  background: #fff;
  break-inside: avoid;
}
.stqr { flex: 0 0 auto; line-height: 0; }
.stqr svg { width: 20mm; height: 20mm; display: block; }
.sttekst { display: flex; flex-direction: column; gap: 1mm; min-width: 0; }
.sttekst b {
  font-size: 11pt;
  line-height: 1.15;
  color: #111;
  overflow-wrap: anywhere;
}
.sttekst span {
  font-size: 8pt;
  line-height: 1.25;
  color: #444;
  overflow-wrap: anywhere;
}
.sttekst .stcode {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 6.5pt;
  color: #888;
  letter-spacing: .02em;
}

/* Afdrukken: alleen het vel. Het menu, de werkbalk en de knoppen eromheen
 * zouden anders een halve pagina kosten -- en de eerste rij stickers staat dan
 * scheef op het vel. */
@media print {
  .zij, .werkbalk, .nietprinten, .laag { display: none !important; }
  .raam, .werkkant, .blad { display: block; margin: 0; padding: 0; max-width: none; }
  body { background: #fff; }
  .stickervel { gap: 2mm; margin: 0; }
  .sticker { border-color: #ccc; }

  /*
   * Het rapport op papier.
   *
   * De kop met de klantnaam en de datum staat alleen hier: op het scherm zie
   * je in de balk bij welke klant je bent, op een afdruk staat dat nergens
   * meer -- en een blad met tellingen zonder naam erboven is een blad dat
   * niemand later nog kan plaatsen.
   *
   * De kaarten verliezen hun schaduw en hun grijze vlak. Een schaduw wordt op
   * papier een vlek en een grijs vlak kost toner zonder iets te verduidelijken.
   * En een kop mag niet als laatste regel van een bladzijde eindigen met zijn
   * tabel op de volgende.
   */
  .alleenprinten { display: block !important; }
  .kaart { box-shadow: none; border-color: #ccc; background: #fff; }
  .lijf { padding: 0 0 8px; }
  th { background: #fff; border-bottom: 1px solid #999; }
  h2 { break-after: avoid; page-break-after: avoid; }
  table, .tegels { break-inside: avoid; page-break-inside: avoid; }
  .tegel { box-shadow: none; border-color: #ddd; }
}

/* Alleen op papier. Op het scherm staat de klantnaam al in de kop. */
.alleenprinten { display: none; }

/*
 * De lijstjes in het rapport.
 *
 * Met een teken vóór de regel en niet alleen een kleur: dit wordt afgedrukt,
 * en op een zwart-witprinter is oranje hetzelfde grijs als groen.
 */
.rapportlijst { list-style: none; margin: 10px 0 0; padding: 0; }
.rapportlijst li { padding: 4px 0 4px 22px; position: relative; }
.rapportlijst li::before { content: '·'; position: absolute; left: 6px;
                           color: var(--flauw); font-weight: 700; }
/* --let-inkt en --goed-inkt en niet --amber en --groen: die twee bestaan hier
   niet -- dat zijn de namen uit het Sloterop-portaal. Deze twee wisselen mee
   met de donkere stand, en ze zijn gekozen om op een vlak te staan. */
.rapportlijst li.let::before { content: '!'; color: var(--let-inkt); }
.rapportlijst li.goed::before { content: '✓'; color: var(--goed-inkt); }


/* ── De kop van een scherm ───────────────────────────────────────────────────
 *
 * Titel links, knoppen rechts, en bij te weinig ruimte onder elkaar. Die
 * knoppen stonden met `margin-left:auto` in een inline stijl, en als ze dan
 * afbreken naar een eigen regel blijven ze rechts hangen met een gat erboven.
 * Onder de titel horen ze links te beginnen, zoals alles daar.
 */
.schermkop { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.schermkop > :first-child { flex: 1 1 320px; }
.schermkop .rij-knoppen { margin-left: auto; }
@media (max-width: 900px) {
  .schermkop .rij-knoppen { margin-left: 0; width: 100%; }
}

/*
 * ── De breedte van de klantenlijst ──
 *
 * Hier stond een grens van 860 pixels. Die had een goede reden: de tabel had
 * drie kolommen -- naam, plaats en een aantal -- en over de hele bladzijde
 * uitgesmeerd stond dat aantal elfhonderd pixels van de naam, waarna je met je
 * vinger langs de regel moet om te zien welk getal bij wie hoort.
 *
 * Die reden is weg. De lijst heeft nu vijf kolommen, waaronder aandacht met
 * pillen erin, dus er valt geen gat meer. En hij hoort even breed te zijn als
 * de kaarten: het is dezelfde lijst anders opgeschreven, en dan is het
 * omschakelen tussen twee breedtes een sprong die niets betekent.
 *
 * Wat wél blijft: het aantal mag niet weglopen. Plaats en aantal krijgen een
 * vaste hap van de breedte, zodat de ruimte die overblijft naar de naam en de
 * pillen gaat -- de twee kolommen waar de tekst in staat.
 */
.klantenlijst .plaatskolom { width: 16%; }
.klantenlijst .telkolom { width: 9%; white-space: nowrap; }

/* ── De netwerkkaart ─────────────────────────────────────────────────────── */

/* De tekening kan breder zijn dan het blad; dan rolt hij binnen zijn eigen
 * kaart en niet met de hele pagina mee. Zie de uitleg bij .kaart:has(> table):
 * een tabel die buiten het beeld valt zonder rolbalk is een tabel waarvan de
 * rechterkant onbereikbaar is. */
.kaartrol { overflow-x: auto; overflow-y: hidden; padding: 4px; }
.netkaart { display: block; max-width: none; }

.netkaart .kaartvak { fill: var(--vlak); stroke: var(--lijn); stroke-width: 1; }
/* De bovenste switch krijgt een dikkere rand en niet een andere kleur: kleur
 * betekent in dit hele bestand een status, en "dit is de kern" is dat niet. */
.netkaart .kaartvak.kern { stroke: var(--inkt-zacht); stroke-width: 1.8; }

.netkaart .kaartnaam  { fill: var(--inkt); font-size: 13.5px; font-weight: 600; }
.netkaart .kaartonder { fill: var(--stil); font-size: 10.5px; }
.netkaart .kaartapp   { fill: var(--inkt-zacht); font-size: 11.5px; }
.netkaart .kaartmeer  { fill: var(--stil); font-size: 11px; font-style: italic; }

/* De kabels achter de vakken langs, in de kleur van een lijn en niet van het
 * merk: dit is geen aanwijzing maar de vorm van het netwerk zelf. */
.netkaart .kabel { fill: none; stroke: var(--flauw); stroke-width: 1.6; }
/* Het poortnummer op de kabel, met een halo in de kleur van de kaart eronder.
 *
 * Zonder die halo loopt de kabel dwars door de tekst heen en lijkt het woord
 * doorgestreept. `paint-order: stroke fill` tekent eerst de rand en dan de
 * letter, dus komt de rand eromheen te liggen in plaats van erover -- dat is
 * de enige manier om in svg een achtergrondje achter tekst te krijgen zonder
 * eerst te meten hoe breed die tekst is. */
.netkaart .kabelpoort { fill: var(--stil); font-size: 10px;
                        font-family: "IBM Plex Mono", monospace;
                        paint-order: stroke fill;
                        stroke: var(--vlak); stroke-width: 3.5px;
                        stroke-linejoin: round; }

.netkaart .klikbaar { cursor: pointer; }
.netkaart .klikbaar:hover .kaartvak { stroke: var(--merk); stroke-width: 1.8; }
.netkaart .klikbaar:hover .kaartnaam { fill: var(--merk); }

/* Bij het afdrukken hoort de tekening op één blad en niet op drie. */
@media print {
  .kaartrol { overflow: visible; }
  .netkaart { width: 100%; height: auto; }
}

/* ── Het dossier ─────────────────────────────────────────────────────────── */

/* De kop van het blad. Op het scherm onzichtbaar (daar staat de schermkop met
 * de knoppen), op papier de titel van het document -- want een afdruk zonder
 * naam en datum erop is over een half jaar een stapel losse tabellen. */
.doskop { display: none; }
.dosvoet { display: none; }

.dosdeel { break-inside: auto; }

@media print {
  /* Wat op papier niets doet. .nietprinten staat al in de afdrukstijl
   * hierboven; dit is de kop van het dossier zelf. */
  .doskop { display: block; margin: 0 0 18px; }
  .doskop h1 { font-size: 22px; margin: 0 0 3px; }
  .doskop p { margin: 0; font-size: 12px; color: #444; }
  .doskop .dosdatum { margin-top: 6px; font-size: 10.5px; color: #666; }

  .dosvoet { display: block; margin-top: 24px; font-size: 10px; color: #666;
             border-top: 1px solid #ddd; padding-top: 8px; }

  /* Een kopje mag niet als laatste regel op een blad staan, en een tabelrij
   * niet halverwege afbreken. Dat is het verschil tussen een afdruk die je kunt
   * lezen en een die je moet leggen. */
  .dosdeel h2 { break-after: avoid; page-break-after: avoid;
                margin: 18px 0 8px; color: #333; border: 0; }
  .dosdeel { break-before: auto; }
  tr, .kaart { break-inside: avoid; page-break-inside: avoid; }

  /* Op papier hebben schaduwen en ronde hoeken geen betekenis, en een grijs
   * vlak kost toner zonder iets toe te voegen. */
  .kaart { box-shadow: none; border: 1px solid #ccc; border-radius: 0;
           background: #fff; margin-bottom: 10px; }
  table { font-size: 10.5px; }
  th { background: #f4f4f4; color: #333; border-bottom: 1px solid #bbb; }
  td, th { padding: 4px 7px; }
  .merkje, .stand { border: 1px solid #bbb; background: #fff; color: #333; }
  .waar, .uitleg { color: #555; }
  .letop { border: 1px solid #999; background: #fff; }

  /* Een adres achter een link hoort er niet bij op papier: dit is een dossier
   * en geen webpagina. */
  a[href]::after { content: none !important; }

  @page { margin: 14mm 12mm; }
}

/* ── Het verschil tussen twee configuraties ──────────────────────────────── */

/* De klasse heet .cfgverschil en niet .verschil, en dat is met schade en schande.
 *
 * .verschil bestond al: het logboek gebruikt hem voor "ip: .10 → .12". Toen dit
 * blok er als .verschil bij kwam, kregen die logregels
 * `display: block; white-space: pre` mee -- elke regel een eigen blok dat niet
 * mag afbreken, en dus werd het logboek breder dan het venster en kwam er een
 * rolbalk onderaan de pagina. Een klassenaam die al bestaat, is geen nieuwe
 * klassenaam.

/* Mono, want dit is uitvoer van een apparaat en de uitlijning heeft betekenis.
 * En rollend in zijn eigen kaart: een firewallregel van tweehonderd tekens mag
 * de pagina niet breder maken dan het venster. */
.cfgverschil { padding: 0; overflow: hidden; }
.cfgverschil pre { margin: 0; padding: 0; overflow-x: auto;
                font: 12px/1.55 "IBM Plex Mono", ui-monospace, Menlo, monospace; }
.cfgverschil span { display: block; padding: 1px 12px 1px 0; white-space: pre; }

/* Het regelnummer in een eigen kolom, niet aan te selecteren: wie een stuk
 * config kopieert wil de config en niet de nummers. */
.cfgverschil i { display: inline-block; width: 52px; padding-right: 12px;
              text-align: right; color: var(--flauw); font-style: normal;
              user-select: none; }

.cfgverschil .dzelf { color: var(--stil); }
.cfgverschil .dbij  { background: var(--goed-vlak); color: var(--goed-inkt); }
.cfgverschil .dweg  { background: var(--fout-vlak); color: var(--fout-inkt); }

/* Het gat tussen twee stukken: wat er is weggelaten wordt gezegd en niet stil
 * overgeslagen -- anders kun je niet zien of je iets mist. */
.cfgverschil .dgat { color: var(--flauw); background: var(--hover); text-align: center;
                  font-size: 11px; padding: 4px 0; white-space: normal;
                  border-top: 1px solid var(--lijn-fijn);
                  border-bottom: 1px solid var(--lijn-fijn); }

/* ── Runbooks: de stappen ────────────────────────────────────────────────── */

/* Hoeveel er af is, als balk. Een getal zegt hetzelfde maar dit lees je zonder
 * te rekenen -- dezelfde reden als bij de statusstrook op het beginscherm. */
.voortgang { height: 4px; border-radius: 3px; background: var(--lijn-fijn);
             overflow: hidden; margin: 0 0 16px; }
.voortgang i { display: block; height: 100%; background: var(--merk);
               transition: width .2s ease; }

.stappen { list-style: none; margin: 0; padding: 0; }
.stappen li { display: grid; grid-template-columns: 1fr auto; gap: 4px 14px;
              align-items: baseline; padding: 9px 0;
              border-bottom: 1px solid var(--lijn-fijn); }
.stappen li:last-child { border-bottom: 0; }

.stappen label { display: flex; align-items: flex-start; gap: 10px; cursor: pointer;
                 font-size: 14.5px; font-weight: 400; color: var(--inkt); }
.stappen label input { width: auto; margin: 2px 0 0; flex: 0 0 auto;
                       accent-color: var(--merk); }

/* Een afgevinkte stap wordt grijs maar niet doorgestreept: je moet hem nog
 * kunnen lezen als je terugkijkt wat er is gedaan. */
.stappen li.af label span { color: var(--stil); }

/* Wie en wanneer, rechts op dezelfde regel. Klein: het is bewijs en geen
 * mededeling. */
.stapwie { font-size: 11.5px; color: var(--stil); white-space: nowrap;
           font-variant-numeric: tabular-nums; }

/* De aantekening op een eigen regel onder de stap, over de volle breedte. */
.stapnotitie { grid-column: 1 / -1; margin-left: 26px; font-size: 13px;
               padding: 6px 10px; }
.stapnot { grid-column: 1 / -1; margin-left: 26px; font-size: 12.5px;
           color: var(--inkt-zacht); }

@media (max-width: 640px) {
  .stappen li { grid-template-columns: 1fr; }
  .stapwie { white-space: normal; }
}

/* ── Een machine, om te lezen ───────────────────────────────────────────────
 *
 * Drie lagen met eigen ruimte: wie het is, wat je ermee kunt, en wat we ervan
 * weten. De knoppenrij staat bewust bovenaan en niet onderaan -- je opent dit
 * scherm omdat er iemand belt, niet om te bladeren.
 */
.mckop { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
         margin: 0 0 14px; }

.mcdoen { display: flex; gap: 8px; flex-wrap: wrap;
          padding: 12px; margin: 0 0 18px;
          background: var(--vlak); border: 1px solid var(--lijn);
          border-radius: 10px; }

/* Twee kolommen die bij weinig ruimte naar één zakken. Geen tabel: een lijst
 * met labels leest beter dan een raster met lege cellen erin. */
.mcraster { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
            gap: 2px 22px; margin: 6px 0 4px; }
@media (max-width: 620px) { .mcraster { grid-template-columns: 1fr; } }

.mcpaar { display: flex; gap: 12px; align-items: baseline;
          padding: 7px 0; border-bottom: 1px solid var(--lijn-fijn); min-width: 0; }
.mclabel { flex: 0 0 42%; color: var(--stil); font-size: 13px; }
.mcwaarde { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
