/*
 * 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:   #2A3640; /* 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;

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

* { 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);
}

.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; }
.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; }
.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: rgba(239, 242, 241, .9);
            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; }
}

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

.blad { max-width: 1220px; 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; }

.kaart { background: var(--vlak); border: 1px solid var(--lijn); border-radius: var(--rond);
         box-shadow: var(--schaduw); overflow: 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: #FBFAF8; }
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(--inkt); border-radius: 8px; background: var(--inkt);
        color: #fff; 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); }
.rij-knoppen { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

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

label { display: block; font-size: 11px; font-weight: 600; margin: 0 0 6px;
        color: var(--inkt-zacht); text-transform: uppercase; letter-spacing: .9px; }
label .los { font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--stil); }

/*
 * 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;
}
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: 2px solid var(--merk); outline-offset: -1px;
                                            border-color: var(--merk); }
/* Gegevens die een gegeven zijn, niet een woord. */
input[type=text].mono, input.mono { font-family: "IBM Plex Mono", monospace; }

.veld { margin-bottom: 15px; }
.veld .uitleg { font-size: 12.5px; color: var(--stil); margin: 6px 0 0; }
.uitleg { font-size: 12.5px; color: var(--stil); }
.tweekolom { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
@media (max-width: 640px) { .tweekolom { grid-template-columns: 1fr; } }
.vinkje { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 13px;
          font-weight: 500; text-transform: none; letter-spacing: 0; font-size: 14px; }
.vinkje input { width: auto; margin-top: 3px; }
.vinkje .uitleg { display: block; font-weight: 400; }

/* ── 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 ──────────────────────────────────────────────────────────────── */

.tegels { display: grid; grid-template-columns: repeat(auto-fill, minmax(146px, 1fr)); gap: 10px; }
.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; }
.tegel:hover { border-color: var(--flauw); }
.tegel.aan { border-color: var(--inkt); background: var(--paneel); color: var(--paneel-tekst);
             box-shadow: inset 0 1px 0 rgba(238, 243, 245, .07); }
.tegel .teken { font-size: 15px; opacity: .45; }
.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: .9px;
               color: var(--stil); font-weight: 600; }
.tegel.aan .naam { color: rgba(238, 243, 245, .62); }

/* ── 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; }
.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; }
.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: 10px 14px; }
.blok { display: grid; grid-template-columns: repeat(6, 30px); gap: 4px; flex: 0 0 auto; }

/*
 * Een vaste hoogte en geen aspect-ratio.
 *
 * aspect-ratio op een grid-item wordt niet door elke renderer hetzelfde
 * uitgerekend, en dan schieten er een paar poortjes uit het gelid -- met
 * precies dezelfde html als hun buren. Dat is een uur zoeken naar een verschil
 * dat er niet is. Een hoogte in pixels doet het overal gelijk.
 */
.poort {
  position: relative; height: 42px; min-width: 0;
  display: flex; align-items: center; justify-content: center; border-radius: 4px;
  font-family: "IBM Plex Mono", monospace; font-size: 11px; font-variant-numeric: tabular-nums;
  background: var(--paneel-poort); color: rgba(238, 243, 245, .55);
  border: 1px solid rgba(0, 0, 0, .35);
  box-shadow: inset 0 1px 0 rgba(238, 243, 245, .06);
  cursor: pointer;
}
.poort:hover { outline: 2px solid var(--merk); outline-offset: 1px; z-index: 2; }

/* Een lege poort is een gat: donker en zonder rand, zoals een onbezette plek. */
.poort.leeg { background: var(--paneel-gat); color: rgba(238, 243, 245, .2);
              border-color: rgba(0, 0, 0, .5); box-shadow: none; cursor: default; }
.poort.leeg:hover { outline: none; }

/* De stand als een lampje onderaan de poort -- zoals de LED onder een RJ45. */
.poort::after { content: ''; position: absolute; bottom: 3px; left: 50%;
                transform: translateX(-50%); width: 12px; height: 2.5px; border-radius: 2px;
                background: transparent; }
.poort.gebruik { color: var(--paneel-tekst); }
.poort.gebruik::after { background: var(--led-goed); box-shadow: 0 0 6px rgba(52, 192, 122, .8); }
.poort.vrij::after    { background: rgba(238, 243, 245, .22); }
.poort.stuk           { color: #FFD9D4; }
.poort.stuk::after    { background: var(--led-fout); box-shadow: 0 0 6px rgba(232, 92, 80, .8); }
.poort.gereserveerd::after { background: var(--led-let); box-shadow: 0 0 6px rgba(239, 160, 46, .7); }

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

/* ── 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.
 */

.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; } }
