/* =============================================================================
   Backoffice Framework — stylesheet
   -----------------------------------------------------------------------------
   Alleen generieke bouwblokken. Huisstijl per app gaat via config/theme.css,
   waarin je --brand, --hover en --active overschrijft; de rest van de tokens
   is bewust identiek voor elke app.

   Volgorde: tokens, basis, layout, navigatie, card, knoppen, formulier,
   tabel, lijst, statussen, menu, modal, toast, tooltip, skeleton, media,
   regels, responsive, donker.
   ========================================================================== */

/* ------------------------------------------------------------------ tokens -- */

:root {
  color-scheme: light;

  --brand: #0746ea;
  --brand-ink: #ffffff;

  --ink: #000000;
  --muted: #6b7280;
  --bg: #f8f8f8;
  --card-bg: #ffffff;
  --hover: #f7f8fc;
  --active: #eef2ff;
  --border: rgba(0, 0, 0, 0.10);
  --border-sterk: rgba(0, 0, 0, 0.18);

  --good: #15803d;  --good-soft: #dcedc8;  --good-ink: #1b5e20;
  --warn: #b45309;  --warn-soft: #fff3cd;  --warn-ink: #856404;
  --bad:  #b91c1c;  --bad-soft:  #ffcdd2;  --bad-ink:  #b71c1c;
  --info: #1e6fb8;  --info-soft: #d8e7f5;  --info-ink: #1b4e80;
  --neutral-soft: #eeeeee; --neutral-ink: #555555;

  --radius: 15px;
  --radius-sm: 10px;
  --radius-pill: 999px;

  --sidebar-w: 200px;
  --bottomnav-h: 60px;
  /* Ruimte is hier het middel om overzicht te maken: zonder duidelijke
     tussenruimtes wordt een scherm vol vormen en tekst één brij. Op mobiel
     staan deze waarden lager, daar is de ruimte te schaars.

     Links en rechts even veel: de zijbalk is links al een grens, dus een
     bredere marge daarnaast maakt het kader scheef zonder dat het rustiger
     wordt. Dit bepaalt hoe breed de kaarten zijn; de padding ín een kaart doet
     daar niets aan. */
  --edge: 32px;
  --edge-x: 40px;
  --section-gap: 24px;
  --card-gap: 18px;

  --shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  --shadow-groot: 0 12px 32px rgba(0, 0, 0, 0.18);

  /* Vlakken die boven de achtergrond liggen: kaarten, navigatie, menu's.
     Standaard een zachte schaduw en geen rand. Wie liever een strakke rand
     heeft zet --vlak-rand op var(--border) en --vlak-schaduw op none. */
  --vlak-rand: transparent;
  --vlak-schaduw: var(--shadow);

  /* Achtergrond van tabelkoppen en lijstkoppen. */
  --kop-bg: #f4f4f5;

  --font: Poppins, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Typografie overgenomen uit app.btaald.nl. Daar zijn maar vier maten in
     gebruik en dat is precies wat het rustig houdt: inhoud op 14, bijschrift op
     12, knoppen op 15, en koppen op 16 of 19. Gebruik nooit een los getal in
     een kit; dat is hoe je aan zeven verschillende maten komt die net niet bij
     elkaar passen. Gewicht kent maar twee standen: 400 voor inhoud, 700 voor
     koppen en labels. */
  --tekst: 14px;
  --tekst-klein: 12px;
  --tekst-knop: 15px;
  --kop-klein: 16px;
  --kop: 19px;
  --font-gewicht: 400;
  --vet: 700;

  --duur: 0.15s;
}

/* Bewegingsvoorkeur van het systeem respecteren. */
@media (prefers-reduced-motion: reduce) {
  :root { --duur: 0s; }
  * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; }
}

/* -------------------------------------------------------------------- basis -- */

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

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--tekst);
  font-weight: var(--font-gewicht);
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: var(--vet); line-height: 1.3; }
p { margin: 0; }
a { color: var(--brand); }

.hidden { display: none !important; }
.right { margin-left: auto; }
.row { display: flex; align-items: center; gap: 10px; }
.muted { color: var(--muted); }
.nowrap { white-space: nowrap; }
.mono { font-family: var(--font-mono); }
.mt20 { margin-top: 20px; }

/* Zichtbaar voor screenreaders, onzichtbaar in beeld. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ------------------------------------------------------------------- layout -- */

.page {
  margin-left: var(--sidebar-w);
  padding: var(--edge) var(--edge-x);
  min-height: 100%;
}

.section { margin-bottom: var(--section-gap); }
.section:last-child { margin-bottom: 0; }

.cards { display: flex; flex-direction: column; gap: var(--card-gap); }
/* Een pagina met losse kaartgroepen onder elkaar hoort dezelfde tussenruimte
   te houden als kaarten binnen één groep. Zonder dit plakken ze aan elkaar. */
.cards + .cards { margin-top: var(--card-gap); }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--card-gap); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--card-gap); }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--card-gap); }

/* Vaste, doorschijnende kop op mobiel met de paginatitel in het midden.
   Overgenomen uit de bestaande apps; verschijnt onder het breekpunt. */
.mobile-header {
  display: none;
  position: fixed;
  inset: 0 0 auto 0;
  height: calc(60px + env(safe-area-inset-top, 0px));
  padding: calc(10px + env(safe-area-inset-top, 0px)) 20px 10px;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.3);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.12);
  z-index: 50;
}
.mobile-header p {
  font-size: var(--kop-klein);
  font-weight: var(--vet);
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --------------------------------------------------------------- navigatie -- */

/* Geen padding op de zijbalk zelf: het merkvlak moet tegen de boven- en
   linkerrand aan sluiten. De items hebben hun eigen ruimte. */
.sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  overflow-y: auto;
  width: var(--sidebar-w);
  background: var(--card-bg);
  box-shadow: var(--vlak-schaduw);
  border-radius: 0 var(--radius) var(--radius) 0;
  display: flex;
  flex-direction: column;
  padding: 0 0 12px;
  z-index: 40;
}

.sidebar_items { display: flex; flex-direction: column; gap: 4px; padding: 22px 10px 8px; }
/* Optioneel groepskopje in de zijbalk (nav-item met `groep`). Gewone tekstkleur,
   geen lichtgrijze hoofdletters. */
.sidebar_groep { padding: 16px 12px 4px; font-size: var(--tekst-klein); font-weight: 600; color: var(--ink); }
.sidebar_groep:first-child { padding-top: 2px; }

.sidebar_merk {
  font-weight: 700;
  font-size: var(--kop-klein);
  padding: 22px 16px 6px;
  color: var(--ink);
  text-decoration: none;
  letter-spacing: -0.02em;
}

/* Sluit aan op de boven- en linkerrand van het scherm, rechts afgerond. Zo
   staat het in de POS-backoffice en in app.btaald.nl. */
.sidebar_merk--vlak {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 92px;
  margin: 0;
  padding: 10px 14px;
  /* Standaard de merkkleur. Een app met een logo dat voor een andere
     achtergrond gemaakt is (vaak de donkere kleur uit de huisstijl) zet
     --merk-bg in zijn theme.css; anders vallen de delen van het logo weg die
     dezelfde kleur hebben als het vlak. */
  background: var(--merk-bg, var(--brand));
  border-radius: 0 var(--radius) var(--radius) 0;
}
.sidebar_merk--vlak img {
  display: block;
  width: 100%;
  max-width: 150px;
  height: auto;
}

/* Geldt voor <a> én <button>: knoppen erven geen font of uitlijning, dus die
   moeten expliciet gelijkgetrokken worden. Anders vallen de thema- en
   uitlogknop onderin uit de huisstijl. */
.nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--ink);
  text-decoration: none;
  font: inherit;
  font-size: var(--tekst);
  line-height: 1.4;
  text-align: left;
  cursor: pointer;
  transition: background var(--duur), color var(--duur);
}
.nav-item:hover { background: var(--hover); }
.nav-item.active { background: var(--active); color: var(--brand); font-weight: var(--vet); }
.nav-item .material-icons { font-size: 20px; flex: 0 0 auto; }
.nav-item span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* De scheidingslijn loopt tot de rand, de knoppen houden dezelfde inspringing
   als de nav-items erboven. Padding én marge maakte de knoppen te smal, zodat
   "Donkere modus" werd afgekapt. */
.sidebar_voet {
  margin-top: auto;
  padding: 10px 10px 0;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.sidebar_voet .nav-item { color: var(--muted); }
.sidebar_voet .nav-item:hover { color: var(--ink); }

/* Onderbalk op mobiel. */
/* De onderbalk is altijd zichtbaar. De safe-area-marge is nodig omdat iOS
   onderaan een eigen browserbalk toont; zonder die marge verdwijnt de balk er
   deels achter zodra je omhoog scrollt. */
.bottomnav {
  display: none;
  position: fixed;
  inset: auto 0 0 0;
  height: calc(var(--bottomnav-h) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: var(--card-bg);
  border-top: 1px solid var(--vlak-rand);
  box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.06);
  z-index: 40;
}

.bm-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  color: var(--muted);
  text-decoration: none;
  font-size: 10px;
  background: none;
  border: 0;
  font-family: inherit;
  cursor: pointer;
}
.bm-item .material-icons { font-size: 22px; }
.bm-item.active { color: var(--brand); }
.bm-item span { text-align: center; line-height: 1.2; }

.bm-overflow {
  position: fixed;
  bottom: var(--bottomnav-h);
  right: 8px;
  background: var(--card-bg);
  border: 1px solid var(--vlak-rand);
  border-radius: var(--radius);
  box-shadow: var(--shadow-groot);
  padding: 6px;
  min-width: 200px;
  z-index: 41;
}
.bm-overflow .nav-item { font-size: var(--tekst); }

/* ------------------------------------------------------------------- card -- */

.card {
  background: var(--card-bg);
  border: 1px solid var(--vlak-rand);
  box-shadow: var(--vlak-schaduw);
  border-radius: var(--radius);
  padding: 24px;
}

.card_head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 20px;
}

/* Streep onder de kop, zodat de titel en de knoppen los staan van de inhoud
   eronder. Op een detailpagina met veel velden helpt dat de blik. */
.card_head--lijn {
  border-bottom: 1px solid var(--border);
  padding-bottom: 18px;
  margin-bottom: 26px;
}
.card_titles { min-width: 0; }
.card_title { font-size: var(--kop); font-weight: var(--vet); }
.card_subtitle { font-size: var(--tekst); color: var(--muted); margin-top: 4px; }
.card_actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

/* Tweede laag van een lijstkaart: waarmee je de lijst inperkt. De kop erboven
   is voor acties, de tabel eronder voor het resultaat. */
.card_filters {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-bottom: 18px;
  flex-wrap: wrap;
}

/* De sorteer- en filterknop hoort bij het zoekveld, dus die krimpt niet mee. */
.card_filters .tk_tool { flex: 0 0 auto; }

/* Zoekveld: geen rand, icoon links, neemt de meeste ruimte. */
.card_filters input[type="search"] {
  flex: 1 1 240px;
  min-width: 0;
  max-width: 100%;
  border: 0;
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 9px 12px 9px 36px;
  font: inherit;
  font-size: var(--tekst);
  color: var(--ink);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236b7280'><path d='M15.5 14h-.79l-.28-.27A6.47 6.47 0 0016 9.5 6.5 6.5 0 109.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'/></svg>");
  background-repeat: no-repeat;
  background-position: 10px center;
  background-size: 18px;
}
.card_filters input[type="search"]::-webkit-search-cancel-button { cursor: pointer; }
/* Een <select> is standaard zo breed als zijn langste optie en krimpt niet mee.
   Met een lange optienaam duwt hij daardoor de hele pagina breder dan het
   scherm. min-width:0 en max-width:100% houden hem binnen de kaart. */
.card_filters select,
.card_filters .filter-veld {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 100%;
  border: 1px solid var(--border);
  background: var(--card-bg);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  font: inherit;
  font-size: var(--tekst);
  color: var(--ink);
}

.card_body { min-height: 20px; }

/* Vangrail: inhoud blijft binnen de kaart. Een te brede afbeelding, tabel of
   ononderbroken tekenreeks (denk aan een bericht-ID) duwt anders de hele
   pagina breder dan het scherm, en dan schuift alles. */
.card img, .card table, .card pre, .card canvas, .card svg { max-width: 100%; }
.card pre { white-space: pre-wrap; overflow-wrap: anywhere; }
.card code { overflow-wrap: anywhere; }

/* ---------------------------------------------------------------- knoppen -- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 7px 18px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  font: inherit;
  font-size: var(--tekst-knop);
  line-height: 1.5;
  white-space: nowrap;
  transition: background var(--duur), color var(--duur), box-shadow var(--duur);
}
.btn:hover { background: var(--hover); }
.btn[disabled] { opacity: 0.55; pointer-events: none; }
.btn .material-icons { font-size: 19px; }

/* Bezig: het label wordt onzichtbaar en de spinner komt op zijn plek, zodat de
   knop niet van breedte verandert. Niet uitgrijzen — dan zou de spinner mee
   vervagen en dat leest als "kapot" in plaats van "bezig". */
.btn.is-bezig {
  position: relative;
  color: transparent !important;
  pointer-events: none;
}
.btn.is-bezig > * { visibility: hidden; }
.btn.is-bezig::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 15px;
  height: 15px;
  border: 2px solid var(--bezig-kleur, currentColor);
  border-right-color: transparent;
  border-radius: 50%;
  animation: bo-draai 0.6s linear infinite;
}

/* Losse spinner, voor waar geen knop is: het baken onder een lijst, een lege
   kaart die nog laadt. Erft de tekstkleur van waar hij staat. */
.spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  opacity: 0.5;
  animation: bo-draai 0.6s linear infinite;
}

@keyframes bo-draai { to { transform: rotate(360deg); } }

/* Het baken onder een lijst: waar de waarnemer naar kijkt, en tegelijk het
   teken dat er bijgeladen wordt. */
.tk_baken { display: flex; justify-content: center; padding: 14px 0; }

/* De uploadzone zette al `is-bezig` maar er hoorde geen enkele stijl bij, dus
   je zag alleen de tekst omslaan. */
.dropzone.is-bezig { pointer-events: none; }
.dropzone.is-bezig .dropzone_tekst::before {
  content: "";
  display: inline-block;
  vertical-align: -3px;
  margin-right: 8px;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: bo-draai 0.6s linear infinite;
}

/* Wie liever geen beweging ziet, krijgt een rustige pulserende stip. */
@media (prefers-reduced-motion: reduce) {
  .btn.is-bezig::after, .spinner {
    animation: bo-pols 1.2s ease-in-out infinite;
    border-right-color: currentColor;
  }
  @keyframes bo-pols { 50% { opacity: 0.25; } }
}

/* Gevulde varianten draaien om bij hover: dat is de signatuur van deze huisstijl. */
.btn-primary { background: var(--brand); color: var(--brand-ink); border-color: var(--brand); }
.btn-primary:hover { background: var(--card-bg); color: var(--brand); box-shadow: var(--shadow); }

.btn-danger  { background: var(--bad);  color: #fff; border-color: var(--bad);  }
.btn-danger:hover  { background: var(--card-bg); color: var(--bad);  box-shadow: var(--shadow); }

.btn-success { background: var(--good); color: #fff; border-color: var(--good); }
.btn-success:hover { background: var(--card-bg); color: var(--good); box-shadow: var(--shadow); }

.btn-warning { background: var(--warn); color: #fff; border-color: var(--warn); }
.btn-warning:hover { background: var(--card-bg); color: var(--warn); box-shadow: var(--shadow); }

.btn-info    { background: var(--info); color: #fff; border-color: var(--info); }
.btn-info:hover { background: var(--card-bg); color: var(--info); box-shadow: var(--shadow); }

/* Een knop heeft een kleur, óf hij heeft een rand. Nooit geen van beide:
   zonder rand is niet te zien dat het een knop is. */
.btn-ghost { background: var(--card-bg); border-color: var(--border); }
.btn-ghost:hover { background: var(--hover); }

.btn-icon { padding: 0; width: 38px; height: 38px; justify-content: center; gap: 0; }

/* --------------------------------------------------------------- formulier -- */

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px 18px;
}
.form-grid .veld-vol { grid-column: 1 / -1; }

/* Zelf bepalen wat links en wat rechts staat, net als bij een detailweergave.
   Twee echte kolommen: met alleen grid-column loopt de plaatsing per rij door
   en zakt het tweede veld een regel. Onder het breekpunt vervalt de keuze. */
.form-kolommen { display: grid; gap: 0 18px; }
.form-kolom { display: flex; flex-direction: column; }
.form-kolommen + .form-grid { margin-top: 16px; }

@media (min-width: 741px) {
  .form-kolommen { grid-template-columns: 1fr 1fr; align-items: start; }
}

.field { display: flex; flex-direction: column; gap: 5px; }

.field > label {
  font-size: var(--tekst-klein);
  font-weight: var(--font-gewicht);
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 6px;
}

.req-star { color: var(--bad); font-weight: var(--vet); }

.field input,
.field select,
.field textarea {
  width: 100%;
  border: 1px solid var(--border-sterk);
  border-radius: var(--radius);
  padding: 12px 14px;
  font: inherit;
  font-size: var(--tekst);
  color: var(--ink);
  background: var(--card-bg);
  transition: border-color var(--duur), box-shadow var(--duur);
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 15%, transparent);
}
.field textarea { min-height: 90px; resize: vertical; }
.field input[disabled], .field select[disabled], .field textarea[disabled] {
  background: var(--bg); color: var(--muted); cursor: not-allowed;
}

/* Checkbox niet uitrekken maar links uitlijnen. */
.field-checkbox { flex-direction: row; align-items: center; gap: 9px; }
.field-checkbox input[type="checkbox"] { width: 17px; height: 17px; margin: 0; flex: 0 0 auto; }
.field-checkbox > label { order: 2; font-weight: 400; }

/* Validatie. */
.field.is-fout input,
.field.is-fout select,
.field.is-fout textarea { border-color: var(--bad); }
.field-fout {
  font-size: var(--tekst-klein);
  color: var(--bad);
  display: flex;
  align-items: center;
  gap: 4px;
}
.field-hint { font-size: var(--tekst-klein); color: var(--muted); }

.form-hint { font-size: var(--tekst-klein); margin: 4px 0 0; }
.form-hint.is-fout { color: var(--bad); }
.form-hint.is-goed { color: var(--good); }

/* Geen streep boven de knoppen: die suggereert een blok dat daar niet begint.
   Een scheiding zet je waar de inhoud verandert, met `scheiding` op een veld. */
.form-acties {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-top: 22px;
}

/* Een lijn bóven dit veld: hier begint een nieuw blok binnen hetzelfde
   formulier. Werkt ook op een veld dat de volle breedte pakt. */
.field--scheiding {
  border-top: 1px solid var(--border);
  padding-top: 20px;
  margin-top: 6px;
}

.fieldset {
  border: 0;
  padding: 0;
  margin: 20px 0;
}
.fieldset:first-child { margin-top: 0; }
.fieldset:last-of-type { margin-bottom: 0; }
/* Gewone kop in de tekstkleur. Lichtgrijze hoofdletterkopjes horen niet in
   deze huisstijl: ze lezen slecht en vallen buiten de rest van het ontwerp. */
.fieldset > legend {
  font-size: var(--tekst-knop);
  font-weight: var(--vet);
  color: var(--ink);
  padding: 0 0 10px;
}

/* Callout binnen een formulier of card. */
.callout {
  padding: 11px 14px;
  border-radius: var(--radius-sm);
  font-size: var(--tekst-klein);
  margin-bottom: 14px;
  border-left: 3px solid var(--info);
  background: var(--info-soft);
  color: var(--info-ink);
}
.callout--warn { border-left-color: var(--warn); background: var(--warn-soft); color: var(--warn-ink); }
.callout--bad  { border-left-color: var(--bad);  background: var(--bad-soft);  color: var(--bad-ink);  }
.callout--good { border-left-color: var(--good); background: var(--good-soft); color: var(--good-ink); }

/* ------------------------------------------------------------------- tabel -- */

.tabel-wrap { width: 100%; }

/* table-layout: fixed betekent: kolommen delen de beschikbare breedte en de
   inhoud past zich aan, in plaats van andersom. Daardoor is er nooit een
   horizontale schuifbalk. Past een kolom niet, dan hoort hij niet in het
   overzicht maar op de detailpagina. */
.table {
  width: 100%;
  table-layout: fixed;
  border-collapse: separate;
  border-spacing: 0;
}

.table th, .table td { padding: 10px 12px; text-align: left; }
.table th {
  background: var(--kop-bg);
  font-weight: var(--vet);
  font-size: var(--tekst);
  color: var(--ink);
  padding: 8px 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Afgeronde uiteinden zodat de kop als één pill-balk oogt. */
.table th:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.table th:last-child  { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
/* Sorteerpijl: klein en op de regel van de kolomnaam, zodat de kop even hoog blijft. */
.table th .th_pijl { font-size: 14px; line-height: 1; vertical-align: -2px; margin-left: 4px; }

.table td { font-size: var(--tekst); border-bottom: 1px solid var(--border); }
.table tbody tr:first-child td { padding-top: 14px; }

/* De laatste rij hoeft geen scheidingslijn: er komt niets meer onder. */
.table tbody tr:last-child td { border-bottom: 0; padding-bottom: 6px; }
.table tbody tr:hover td { background: var(--hover); }
.table tbody tr.is-geselecteerd td { background: var(--active); }

/* Elke cel is precies één regel hoog. Inhoud die niet past wordt afgekapt met
   een beletselteken; de volledige waarde staat in het title-attribuut en op de
   detailpagina. Zonder deze regel groeien rijen ongelijk uit zodra er tags of
   meerdere ontvangers in staan, en dat maakt een tabel onleesbaar. */
.table .cel {
  display: block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 22px;
}
.table .cel > * { vertical-align: middle; }

/* Tags binnen een cel blijven op één regel staan en worden mee afgekapt. */
.cel-tags {
  display: inline-flex;
  flex-wrap: nowrap;
  gap: 4px;
  max-width: 100%;
  vertical-align: middle;
}
.cel-tags > * {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* De "+3"-teller mag nooit zelf afgekapt worden; die is juist de aanwijzing
   dat er meer is. */
.cel-tag-meer { flex: 0 0 auto !important; font-size: var(--tekst-klein); }

.table .kol-rechts { text-align: right; }
.table .kol-midden { text-align: center; }
.table .kol-vet { font-weight: var(--vet); }
/* Vaste breedte in pixels: met table-layout:fixed is een percentage letterlijk,
   en in 1% past geen actieknop. */
.table .kol-smal { width: 48px; white-space: nowrap; }

.table a.rij-link { color: inherit; text-decoration: none; display: block; }
.table a.rij-link:hover { color: var(--brand); }

/* Ruimte onder de tabel alleen als er echt een knop staat. */
.tk_meer { text-align: center; margin-top: 12px; }
.tk_meer:empty { margin-top: 0; }

/* Sluit de kaart netjes af achter de laatste rij in plaats van er nog een
   flinke marge onder te laten staan. Alleen als het overzicht het laatste
   onderdeel van de kaart is; zit er nog iets onder, dan blijft de ruimte. */
.card:has(> .tk:last-child) { padding-bottom: 12px; }

/* -------------------------------------------------------------------- lijst -- */

.sl-list { list-style: none; margin: 0; padding: 0; }

.sl-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 4px;
  border-bottom: 1px solid var(--border);
}
/* Een lijstitem met een bestemming is een <a>. Die hoort er hetzelfde uit te
   zien als de rest van de lijst en niet als een blauwe onderstreepte regel. */
a.sl-item { color: inherit; text-decoration: none; cursor: pointer; }
a.sl-item:hover { background: var(--hover, rgba(0, 0, 0, .03)); }
.sl-item:last-child { border-bottom: 0; }
.sl-item:hover { background: var(--hover); }
.sl-item.is-geselecteerd { background: var(--active); }

.sl-icon {
  flex: 0 0 auto;
  width: 36px; height: 36px;
  border-radius: var(--radius-sm);
  display: grid; place-items: center;
  background: var(--active);
  color: var(--brand);
}
.sl-icon .material-icons { font-size: 20px; }

/* Selectie in de lijstweergave: het icoon verdwijnt niet maar wisselt van vorm.
   In rust zie je de status, bij hover een vakje, en zodra er iets geselecteerd
   is staan alle vakjes zichtbaar — anders moet je raden waar je moet mikken, en
   op een aanraakscherm bestaat hover niet. */
.sl-kies {
  flex: 0 0 auto;
  position: relative;
  width: 36px; height: 36px;
  border-radius: var(--radius-sm);
  display: grid; place-items: center;
  background: var(--active);
  color: var(--brand);
}
.sl-kies-icoon .material-icons { font-size: 20px; }
.sl-kies-icoon, .sl-kies-vak { transition: opacity 0.12s ease; }
.sl-kies-vak {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  opacity: 0;
}
.sl-item:hover .sl-kies-icoon,
.sl-item:focus-within .sl-kies-icoon,
.sl--kiesmodus .sl-kies-icoon { opacity: 0; }
.sl-item:hover .sl-kies-vak,
.sl-item:focus-within .sl-kies-vak,
.sl--kiesmodus .sl-kies-vak { opacity: 1; }
.sl-item.is-geselecteerd .sl-kies { background: var(--brand); }

/* De mislukte rijen na een bulkactie: kort lijstje, geen tabel. */
.tk_mislukt { margin: 10px 0 0; padding-left: 18px; font-size: var(--klein); }
.tk_mislukt li { margin-bottom: 4px; }

   onzichtbaar, zodat toetsenbord en schermlezer gewoon werken. */
.tk-vink {
  display: inline-grid;
  place-items: center;
  cursor: pointer;
  color: var(--brand);
  line-height: 0;
}
.tk-vink input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  margin: 0;
}
.tk-vink .material-icons { font-size: 20px; }
/* Zichtbare focus zonder gloed: een strakke rand om het icoon, geen halo. */
.tk-vink input:focus-visible + .material-icons {
  outline: 2px solid var(--brand);
  outline-offset: 0;
  border-radius: 2px;
}

/* De selectiekolom is smal; het vakje hoort er horizontaal in het midden. Alleen
   deze kolom, niet de actiekolom die dezelfde breedteklasse deelt. */
/* Het vinkje in een keuzekolom. Uitlijnen op de basislijn zet het icoon een
   paar pixels te hoog: een Material-glyph zit binnen zijn regelbox al hoog, en
   met line-height 0 valt dat samen met de bovenkant van de cel. Daarom de
   inhoud van de cel expliciet centreren in plaats van op tekstuitlijning
   vertrouwen. */
/* Geen eigen padding: de keuzekolom hoort precies dezelfde ruimte te krijgen
   als elke andere cel. Stond hier `padding: 0`, dan miste deze cel de extra
   ruimte die de eerste en de laatste rij wél krijgen, en stond het vinkje daar
   een paar pixels naast de tekst ernaast. */
th.kol-kies, td.kol-kies { text-align: center; vertical-align: middle; }
th.kol-kies .tk-vink,
td.kol-kies .tk-vink {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  line-height: 1;
}
th.kol-kies .tk-vink .material-icons,
td.kol-kies .tk-vink .material-icons { display: block; line-height: 1; }
.sl-item.is-geselecteerd .sl-kies-vak { color: var(--brand-ink, #fff); }

/* Statuskleuren voor het lijst-icoon (DashKit toonVan), zelfde tinten als een
   StatusBadge: zachte achtergrond met een gekleurd icoon. */
.sl-icon--good    { background: var(--good-soft);    color: var(--good); }
.sl-icon--warn    { background: var(--warn-soft);    color: var(--warn); }
.sl-icon--bad     { background: var(--bad-soft);     color: var(--bad); }
.sl-icon--info    { background: var(--info-soft);    color: var(--info); }
.sl-icon--neutral { background: var(--neutral-soft); color: var(--neutral-ink); }

.sl-body { flex: 1; min-width: 0; }
.sl-title {
  font-size: var(--tekst); font-weight: var(--vet); color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sl-subtitle {
  font-size: var(--tekst-klein); color: var(--muted); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sl-meta { flex: 0 0 auto; font-size: var(--tekst); color: var(--muted); }

/* Dezelfde regel, ruimer. Voor pagina's die meer een app dan een backoffice
   zijn: een beeld links, tekst die mag doorlopen, en knoppen rechts. Het is
   bewust geen tweede blok: het skelet is identiek, alleen de dichtheid
   verschilt. */
.sl-item--ruim {
  align-items: stretch;
  gap: 20px;
  padding: 20px 4px;
}
.sl-item--ruim .sl-beeld {
  flex: 0 0 auto;
  width: 160px;
  height: 160px;
  object-fit: contain;
  border-radius: var(--radius-sm);
  background: var(--bg);
}
.sl-item--ruim .sl-body { display: flex; flex-direction: column; gap: 8px; }
.sl-item--ruim .sl-title { font-size: var(--kop-klein); white-space: normal; }

/* Meerdere regels tekst, afgekapt met een puntje. Zonder grens groeit de ene
   regel tot een lap tekst en is de lijst niet meer te scannen. */
.sl-item--ruim .sl-tekst {
  font-size: var(--tekst);
  color: var(--muted);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}
/* Onder de tekst in plaats van rechts: in een kaart is dit een regel met
   gegevens, geen bedrag aan het eind van de rij. */
.sl-item--ruim .sl-meta--onder {
  flex: 0 0 auto;
  font-size: var(--tekst);
  color: var(--tekst-zacht, var(--muted));
}

.sl-item--ruim .sl-acties {
  margin-top: auto;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* Op een telefoon staat het beeld boven de tekst; naast elkaar blijft er voor
   allebei te weinig over. */
@media (max-width: 740px) {
  .sl-item--ruim { flex-direction: column; align-items: stretch; gap: 14px; }
  .sl-item--ruim .sl-beeld { width: 100%; height: 180px; }
}

.sl-link { text-decoration: none; color: inherit; display: contents; }

/* Alleen de kleur verandert bij hover, geen achtergrondvlak. Zo'n vlak komt
   vlak langs de rechterrand van de lijst te liggen en dat oogt als een fout
   uitgelijnd blokje. */
.sl-actie {
  flex: 0 0 auto;
  border: 0; background: none; cursor: pointer;
  color: var(--muted);
  width: 34px; height: 34px;
  border-radius: var(--radius-sm);
  display: grid; place-items: center;
  text-decoration: none;
  transition: color var(--duur);
}
.sl-actie:hover { color: var(--ink); }
.sl-actie:focus-visible { color: var(--brand); }

/* ------------------------------------------------------------- leeg / fout -- */

.empty-state { text-align: center; padding: 40px 20px; }
.empty-state .material-icons { font-size: 44px; color: var(--border-sterk); }
.empty-state_titel { font-size: var(--kop-klein); font-weight: var(--vet); margin-top: 10px; }
.empty-state_tekst { font-size: var(--tekst); color: var(--muted); margin-top: 4px; }
.empty-state_actie { margin-top: 16px; }

.laad-tekst { padding: 20px; text-align: center; color: var(--muted); font-size: var(--tekst); }

.fout-blok {
  padding: 14px;
  border-radius: var(--radius-sm);
  background: var(--bad-soft);
  color: var(--bad-ink);
  font-size: var(--tekst-klein);
  display: flex;
  align-items: center;
  gap: 10px;
}
.fout-blok .btn { margin-left: auto; }

/* ---------------------------------------------------------------- statussen -- */

/* Statusweergave: één gekleurde pil voor alle lijsten, tabellen en
   detailpagina's, zodat een status er overal hetzelfde uitziet. */
.status-badge {
  display: inline-block;
  max-width: 100%;
  padding: 2px 9px;
  border-radius: var(--radius-pill);
  font-size: var(--tekst-klein);
  font-weight: var(--vet);
  letter-spacing: 0.02em;
  line-height: 1.6;
  white-space: nowrap;
  /* Een lange status in een smalle kolom werd door de cel afgekapt, midden in
     een woord en zonder teken dat er meer stond: "Em processamen". De badge
     kapt nu zelf af, met een beletselteken binnen de pil. De volledige tekst
     blijft beschikbaar via de titel. */
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
}
.status-badge--good    { background: var(--good-soft);    color: var(--good-ink); }
.status-badge--warn    { background: var(--warn-soft);    color: var(--warn-ink); }
.status-badge--bad     { background: var(--bad-soft);     color: var(--bad-ink); }
.status-badge--info    { background: var(--info-soft);    color: var(--info-ink); }
.status-badge--neutral { background: var(--neutral-soft); color: var(--neutral-ink); }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--card-bg);
  font-size: var(--tekst-klein);
  cursor: pointer;
}
.chip:hover { background: var(--hover); }
.chip.is-aan { background: var(--active); border-color: var(--brand); color: var(--brand); }
/* Chips die samen één keuze vormen, staan als groep tegen elkaar aan. */
.chips { display: inline-flex; gap: 6px; flex-wrap: wrap; }

.chip_x { font-size: var(--tekst-knop); line-height: 1; opacity: 0.6; }
.chip_x:hover { opacity: 1; }

.dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; vertical-align: middle; }
.dot--good { background: var(--good); }
.dot--warn { background: var(--warn); }
.dot--bad  { background: var(--bad); }
.dot--uit  { background: var(--border-sterk); }

/* --------------------------------------------------------------------- tabs -- */

.tabs {
  display: flex;
  justify-content: flex-start;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
  overflow-x: auto;
  width: 100%;
}
/* Staat de balk in een kaartkop, dan is die kop een flexcontainer en zou de
   balk tot zijn inhoud krimpen. Dan loopt de onderlijn halverwege dood en
   lijken de tabbladen naar het midden te schuiven. */
.card_head > .tabs,
.card_head > div > .tabs { flex: 1 1 auto; min-width: 0; }
.card_head:has(> .tabs), .card_head:has(> div > .tabs) { margin-bottom: 0; }
.tab {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 7px;
  padding: 9px 15px;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--tekst);
  color: var(--muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
/* Het eerste tabblad begint bij de linkerrand van de kaart, gelijk met de
   titel en de velden eronder. Met de standaard padding sprong het icoon
   vijftien pixels in en stond de hele balk scheef ten opzichte van de rest. */
.tabs > .tab:first-child { padding-left: 0; }

.tab--link, .tab--link:hover, .tab--link:visited { text-decoration: none; }
.tab--link { color: var(--muted); }
.tab:hover { color: var(--ink); }
.tab.active { color: var(--brand); border-bottom-color: var(--brand); font-weight: var(--vet); }

.tab-paneel[hidden] { display: none; }

/* Telling achter het label. Gewoon gewicht en grijs, ook op het actieve
   tabblad: het getal hoort bij het label maar mag er niet mee concurreren. */
.tab_telling {
  font-size: var(--tekst-klein);
  font-weight: var(--font-gewicht);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.tab_telling[hidden] { display: none; }

/* --------------------------------------------------------------------- menu -- */

.sl-menu {
  position: fixed;
  min-width: 210px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-groot);
  padding: 6px;
  z-index: 60;
}
.sl-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--tekst);
  color: var(--ink);
  text-align: left;
  text-decoration: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.sl-menu-item:hover { background: var(--hover); }
/* Dezelfde tokens als .nav-item.active: één manier om "dit is het nu" te
   tonen, door de hele app heen. */
.sl-menu-item.is-actief {
  background: var(--active);
  color: var(--brand);
  font-weight: var(--vet);
}
.sl-menu-item.is-actief:hover { background: var(--active); }
.sl-menu-item.is-actief .sl-menu-icon { color: var(--brand); }
.sl-menu-item.is-danger { color: var(--bad); }
.sl-menu-item.is-danger:hover { background: var(--bad-soft); }
.sl-menu-icon { font-size: 18px; color: var(--muted); }
.sl-menu-item.is-danger .sl-menu-icon { color: var(--bad); }
.sl-menu-label { flex: 1; }
.sl-menu-leeg { color: var(--muted); cursor: default; }
.sl-menu-leeg:hover { background: none; }

.menu-kop {
  padding: 10px 10px 4px;
  font-size: var(--tekst-klein);
  font-weight: var(--vet);
  color: var(--ink);
}
.menu-scheiding { height: 1px; background: var(--border); margin: 5px 0; }

/* -------------------------------------------------------------------- modal -- */

/* Een modal staat niet in het midden maar in het bovenste kwart. Precies
   gecentreerd oogt laag: je ogen zitten hoger dan het midden van een scherm, en
   op een hoge monitor moet je kijken waar je net niet keek. De twee spacers
   verdelen de vrije ruimte 1 : 3, dus een kwart erboven en drie kwart eronder,
   ongeacht hoe hoog de modal zelf is. Bij een hoge modal knijpen ze vanzelf
   dicht en blijft hij binnen beeld. */
.modal-achtergrond {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 16px;
  z-index: 80;
  animation: bo-fade var(--duur) ease-out;
}
.modal-achtergrond::before,
.modal-achtergrond::after { content: ""; flex-shrink: 1; min-height: 0; }
.modal-achtergrond::before { flex-grow: 1; }
.modal-achtergrond::after { flex-grow: 3; }

.modal {
  flex: 0 0 auto;
  background: var(--card-bg);
  border-radius: var(--radius);
  box-shadow: var(--shadow-groot);
  /* Ook 100vw als grens: staat de pagina eronder horizontaal te ruim, dan
     rekent 100% mee met die bredere pagina en valt de modal van het scherm. */
  width: min(560px, 100%, calc(100vw - 32px));
  max-width: calc(100vw - 32px);
  max-height: min(90vh, calc(100dvh - 32px));
  display: flex;
  flex-direction: column;
  animation: bo-omhoog var(--duur) ease-out;
}
.modal--breed { width: min(880px, 100%, calc(100vw - 32px)); }
.modal--smal { width: min(400px, 100%, calc(100vw - 32px)); }

.modal_body img, .modal_body table, .modal_body pre { max-width: 100%; }
.modal_body pre, .modal_body code { overflow-wrap: anywhere; }

/* De sluitknop is hoger dan de titelregel. Met flex-start stond zijn midden
   bijna vier pixels onder dat van de titel, en dat zie je. */
.modal_head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 18px 18px 12px;
}
.modal_titel { font-size: var(--kop); font-weight: var(--vet); }
.modal_sluit {
  margin-left: auto;
  border: 0; background: none; cursor: pointer;
  color: var(--muted);
  width: 32px; height: 32px;
  border-radius: var(--radius-sm);
  display: grid; place-items: center;
}
.modal_sluit:hover { background: var(--hover); color: var(--ink); }
/* Zonder eigen maat rendert het icoon op 24px met de regelhoogte van de
   iconfont, en dan staat het kruisje net iets uit het midden van zijn vlak.
   Zelfde maat als de andere iconen in een knopvlak. */
.modal_sluit .material-icons { font-size: 20px; line-height: 1; }

.modal_body { padding: 0 18px; overflow-y: auto; flex: 1; }
/* Normaal geeft de knoppenbalk de ruimte onderaan. Een modal zonder knoppen
   heeft die niet, en dan plakt de laatste regel tekst tegen de onderrand. */
.modal_body:last-child { padding-bottom: 18px; }
.modal_tekst { font-size: var(--tekst); color: var(--ink); line-height: 1.55; }

.modal_voet {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  padding: 16px 18px 18px;
}

@keyframes bo-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes bo-omhoog { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* -------------------------------------------------------------------- toast -- */

.toast-stack {
  position: fixed;
  right: 16px;
  bottom: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 90;
  max-width: min(420px, calc(100vw - 32px));
}

.toast {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 12px 14px;
  border-radius: var(--radius);
  background: var(--card-bg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-groot);
  font-size: var(--tekst);
  animation: bo-in-rechts var(--duur) ease-out;
}
.toast.is-weg { animation: bo-uit-rechts var(--duur) ease-in forwards; }
.toast_icon { font-size: 20px; flex: 0 0 auto; }
.toast_tekst { flex: 1; min-width: 0; }
.toast_actie {
  flex: 0 0 auto;
  border: 0; background: none;
  font: inherit; font-size: var(--tekst-klein); font-weight: var(--vet);
  color: var(--brand);
  cursor: pointer;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
}
.toast_actie:hover { background: var(--active); }
.toast_sluit {
  flex: 0 0 auto;
  border: 0; background: none; cursor: pointer;
  color: var(--muted); font-size: var(--kop-klein); line-height: 1;
  padding: 2px 4px;
}

.toast--success .toast_icon { color: var(--good); }
.toast--error   .toast_icon { color: var(--bad); }
.toast--warning .toast_icon { color: var(--warn); }
.toast--info    .toast_icon { color: var(--info); }

@keyframes bo-in-rechts { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: none; } }
@keyframes bo-uit-rechts { to { opacity: 0; transform: translateX(20px); } }

/* ------------------------------------------------------------------ tooltip -- */

.tooltip-trigger {
  display: inline-grid;
  place-items: center;
  width: 16px; height: 16px;
  border-radius: 50%;
  border: 0;
  background: var(--neutral-soft);
  color: var(--muted);
  font-size: var(--tekst-klein);
  cursor: help;
  padding: 0;
  vertical-align: middle;
}
.tooltip-trigger:hover, .tooltip-trigger:focus { background: var(--active); color: var(--brand); }
.tooltip-trigger .material-icons { font-size: 13px; }

.tooltip-pop {
  position: fixed;
  max-width: 260px;
  background: var(--ink);
  color: #fff;
  padding: 8px 11px;
  border-radius: var(--radius-sm);
  font-size: var(--tekst-klein);
  line-height: 1.45;
  z-index: 95;
  box-shadow: var(--shadow-groot);
  pointer-events: none;
}

/* ----------------------------------------------------------------- skeleton -- */

.skeleton {
  background: linear-gradient(90deg, var(--neutral-soft) 25%, var(--hover) 37%, var(--neutral-soft) 63%);
  background-size: 400% 100%;
  animation: bo-glans 1.4s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
.skeleton--tekst { height: 12px; margin: 6px 0; }
.skeleton--titel { height: 18px; width: 40%; margin: 8px 0; }
.skeleton--rij { height: 46px; margin-bottom: 8px; }
.skeleton--kaart { height: 96px; }
.skeleton--cirkel { border-radius: 50%; width: 36px; height: 36px; }

@keyframes bo-glans { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* -------------------------------------------------------------------- media -- */

.media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 10px;
}
.media-tegel {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg);
}
.media-tegel img { width: 100%; height: 100%; object-fit: cover; display: block; }
.media-tegel_acties {
  position: absolute; inset: auto 0 0 0;
  display: flex; gap: 4px; padding: 5px;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.6));
  opacity: 0;
  transition: opacity var(--duur);
}
.media-tegel:hover .media-tegel_acties, .media-tegel:focus-within .media-tegel_acties { opacity: 1; }
.media-tegel_knop {
  border: 0; background: rgba(255, 255, 255, 0.9); cursor: pointer;
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center; color: var(--ink);
}
.media-tegel_knop .material-icons { font-size: 15px; }
.media-badge {
  position: absolute; top: 5px; left: 5px;
  background: var(--brand); color: var(--brand-ink);
  font-size: var(--tekst-klein); font-weight: var(--vet);
  padding: 2px 7px; border-radius: var(--radius-pill);
}

.dropzone {
  border: 2px dashed var(--border-sterk);
  border-radius: var(--radius);
  padding: 28px 16px;
  text-align: center;
  color: var(--muted);
  font-size: var(--tekst-klein);
  cursor: pointer;
  transition: border-color var(--duur), background var(--duur);
}
.dropzone:hover, .dropzone.is-over { border-color: var(--brand); background: var(--active); color: var(--brand); }
.dropzone .material-icons { font-size: 32px; display: block; margin-bottom: 6px; }

/* ------------------------------------------------------------------- regels -- */

.line-items { width: 100%; border-collapse: collapse; }
.line-items th {
  background: var(--kop-bg);
  font-size: var(--tekst-klein); font-weight: var(--vet); color: var(--muted);
  text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--border);
}
.line-items td { padding: 5px 8px; vertical-align: middle; }
/* Een regel die de backend niet accepteerde. Zonder dit verschil ziet hij er
   net zo uit als een bewaarde regel, telt hij mee in het totaal, en is hij na
   een herlaadbeurt spoorloos. */
.line-items tr.is-mislukt { background: color-mix(in srgb, var(--bad) 8%, transparent); }
.line-items tr.is-mislukt td { border-color: color-mix(in srgb, var(--bad) 35%, transparent); }
.line-items tr.is-mislukt td:first-child { box-shadow: inset 3px 0 0 var(--bad); }

.line-items input, .line-items select {
  width: 100%; border: 1px solid transparent; background: transparent;
  border-radius: var(--radius-sm); padding: 6px 8px; font: inherit; font-size: var(--tekst); color: var(--ink);
}
.line-items input:hover, .line-items select:hover { border-color: var(--border); }
.line-items input:focus, .line-items select:focus {
  outline: none; border-color: var(--brand); background: var(--card-bg);
}
.line-items .kol-bedrag input { text-align: right; }
.line-items_x {
  border: 0; background: none; cursor: pointer; color: var(--muted);
  width: 28px; height: 28px; border-radius: var(--radius-sm); display: grid; place-items: center;
}
.line-items_x:hover { background: var(--bad-soft); color: var(--bad); }
/* De knop is 28px in een bredere cel. Zonder dit staat hij links en lijkt het
   hoververvlak uit het midden te lopen. */
.line-items td.kol-x { text-align: center; width: 48px; }
.line-items td.kol-x .line-items_x { display: inline-grid; vertical-align: middle; }

.line-totals { margin-left: auto; width: min(320px, 100%); margin-top: 12px; }
.line-totals_rij { display: flex; justify-content: space-between; padding: 5px 8px; font-size: var(--tekst); }
.line-totals_rij--eind {
  border-top: 1px solid var(--border); margin-top: 5px; padding-top: 10px;
  font-weight: var(--vet); font-size: var(--kop-klein);
}

/* ----------------------------------------------------------------- kv-lijst -- */

/* Detailweergave: label vet bóven de waarde, twee kolommen, geen lijnen.
   Een label naast zijn waarde dwingt een vaste labelkolom af, en die is altijd
   te smal voor het langste label of te breed voor de rest. Zo staat het ook in
   de POS-backoffice. */
.kv { display: grid; gap: 24px; }
.kv-row { display: flex; flex-direction: column; gap: 4px; font-size: var(--tekst); line-height: 1.4; }
.kv-label { color: var(--ink); font-size: var(--kop-klein); font-weight: var(--vet); }
.kv-value {
  color: var(--ink);
  font-weight: var(--font-gewicht);
  min-width: 0;
  word-break: break-word;
  display: flex;
  align-items: center;
  gap: 6px;
}
.kv-icon { font-size: 20px; flex-shrink: 0; }

/* Opgeslagen opmaak op een detailpagina. De rij is een flexregel die alles
   verticaal centreert; een blok met meerdere alinea's hoort daar bovenaan te
   beginnen en gewoon te lopen. */
.kv-value:has(> .kv-rijketekst) { display: block; }
.kv-rijketekst { font-weight: 400; }
.kv-rijketekst > :first-child { margin-top: 0; }
.kv-rijketekst > :last-child { margin-bottom: 0; }
.kv-rijketekst p { margin: 0 0 8px; }
.kv-rijketekst ul,
.kv-rijketekst ol { margin: 0 0 8px; padding-left: 20px; }
.kv-rijketekst li { margin-bottom: 2px; }
.kv-rijketekst a { color: var(--brand); }

/* Knop naast de waarde: klein en zonder rand, zodat hij de waarde niet
   overstemt. Dezelfde actie als in de kaartkop, alleen hier. */
.kv-actie {
  width: 26px; height: 26px;
  padding: 0;
  margin-left: auto;
  border-color: transparent;
  color: var(--muted);
}
.kv-actie .material-icons { font-size: 16px; }
.kv-actie:hover { color: var(--brand); }
.kv-link { color: var(--brand); text-decoration: none; }
.kv-link:hover { text-decoration: underline; }

/* Twee kolommen waarvan de pagina zelf bepaalt wat waar staat. Met alleen een
   grid loopt de vulling per rij, en dan komt "Postcode" naast "E-mailadres" te
   staan omdat dat toevallig de volgorde is. Bij elkaar horende velden onder
   elkaar zetten is precies wat een detailpagina overzichtelijk maakt. */
.kv-kolommen { display: grid; gap: 24px; }

/* Velden die de volle breedte pakken staan in een eigen blok onder de kolommen;
   zonder deze marge plakken ze tegen het laatste veld erboven. */
.kv-kolommen + .kv, .kv + .kv, .section-heading + .kv { margin-top: 24px; }

@media (min-width: 720px) {
  .kv--cols-2 { grid-template-columns: 1fr 1fr; column-gap: 40px; }
  .kv--cols-2 .kv-row--vol { grid-column: 1 / -1; }
  .kv-kolommen { grid-template-columns: 1fr 1fr; column-gap: 40px; align-items: start; }
}

.section-heading {
  font-size: var(--tekst-knop); font-weight: var(--vet); color: var(--ink);
  margin: 22px 0 10px; padding-bottom: 8px; border-bottom: 1px solid var(--border);
}
.section-heading:first-child { margin-top: 0; }

/* ---------------------------------------------------------------- richtext -- */

/* Quill brengt zijn eigen uiterlijk mee; hier trekken we dat gelijk met de rest
   van de formuliervelden: dezelfde rand, radius, letter en focuskleur. */
/* Kolom-flex zodat de wrapper de werkbalk én het invoervlak echt omsluit.
   Quill zet op .ql-container een height:100%, en met een auto-hoge wrapper
   levert dat een hoogte op die de werkbalk niet meetelt: het veld steekt dan
   onderaan buiten de kaart. */
.richtext { width: 100%; display: flex; flex-direction: column; }
.richtext .ql-container.ql-snow { flex: 1 1 auto; height: auto; }

.richtext .ql-toolbar.ql-snow {
  border: 1px solid var(--border);
  border-bottom: 0;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: var(--bg);
  padding: 6px 8px;
}
.richtext .ql-container.ql-snow {
  border: 1px solid var(--border);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  font-family: var(--font);
  font-size: var(--tekst);
  color: var(--ink);
  background: var(--card-bg);
}
.richtext .ql-editor {
  min-height: 140px;
  padding: 10px 11px;
  line-height: 1.55;
}
.richtext .ql-editor.ql-blank::before {
  color: var(--muted);
  font-style: normal;
  left: 11px;
}
.richtext:focus-within .ql-toolbar.ql-snow,
.richtext:focus-within .ql-container.ql-snow { border-color: var(--brand); }

/* Knoppen in de werkbalk in onze kleuren in plaats van Quill-blauw. */
.richtext .ql-snow .ql-stroke { stroke: var(--muted); }
.richtext .ql-snow .ql-fill { fill: var(--muted); }
.richtext .ql-snow .ql-picker { color: var(--muted); }
.richtext .ql-snow button:hover .ql-stroke,
.richtext .ql-snow button.ql-active .ql-stroke { stroke: var(--brand); }
.richtext .ql-snow button:hover .ql-fill,
.richtext .ql-snow button.ql-active .ql-fill { fill: var(--brand); }

/* Terugval als de editor niet geladen kan worden. */
.richtext_terugval {
  width: 100%;
  min-height: 140px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 11px;
  font: inherit;
  font-size: var(--tekst);
  color: var(--ink);
  background: var(--card-bg);
  resize: vertical;
}
.richtext_terugval:focus { outline: none; border-color: var(--brand); }

@media (max-width: 860px) {
  .richtext .ql-container.ql-snow, .richtext_terugval { font-size: 16px; }
}

/* ------------------------------------------------------------------ wizard -- */

.wizard_voortgang {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 24px;
  flex-wrap: wrap;
}

.wizard_stap {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px 4px 4px;
  border-radius: var(--radius-pill);
  color: var(--muted);
  font-size: var(--tekst-klein);
}
.wizard_stap.is-actief { background: var(--active); color: var(--brand); font-weight: var(--vet); }
.wizard_stap.is-klaar { color: var(--ink); }

.wizard_bol {
  width: 26px; height: 26px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--neutral-soft);
  color: var(--muted);
  font-size: var(--tekst-klein);
  font-weight: var(--vet);
  flex: 0 0 auto;
}
.wizard_stap.is-actief .wizard_bol { background: var(--brand); color: var(--brand-ink); }
.wizard_stap.is-klaar .wizard_bol { background: var(--good-soft); color: var(--good-ink); }
.wizard_bol .material-icons { font-size: 16px; }

.wizard_titel { font-size: var(--kop); font-weight: var(--vet); }
.wizard_subtitel { font-size: var(--tekst); color: var(--muted); margin-top: 4px; }
.wizard_kop { margin-bottom: 20px; }

.wizard_voet {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-top: 24px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}
/* De hoofdactie rechts, net als in een kaart. */
.wizard_voet .btn-primary { margin-left: auto; }

@media (max-width: 860px) {
  /* Alleen de bolletjes; labels passen niet naast elkaar op een telefoon. */
  .wizard_stap-label { display: none; }
  .wizard_stap.is-actief .wizard_stap-label { display: inline; }
  .wizard_voet { flex-direction: column-reverse; align-items: stretch; }
  .wizard_voet .btn { width: 100%; justify-content: center; margin-left: 0; }
}

/* ------------------------------------------------------------------- login -- */

/* Versieregel onderin de zijbalk, net boven de scheidingslijn. De inspringing
   is die van de lijst (10px) plus die van een nav-item (12px), zodat hij in
   dezelfde kolom staat als de iconen erboven. */
.versie-stempel {
  padding: 0 22px 10px;
  font-size: var(--tekst-klein);
  color: var(--muted);
  opacity: 0.7;
  user-select: text;
}

/* De vrije ruimte zat eerst in de voet (margin-top:auto). Die schuift nu naar
   de versieregel, anders plakt die onder het laatste menu-item in plaats van
   boven de scheidingslijn. */
.sidebar > .versie-stempel { margin-top: auto; }
.sidebar > .versie-stempel + .sidebar_voet { margin-top: 0; }

/* Valt hij terug op de pagina (geen zijbalk), dan hoort hij rechtsonder. */
main.page > .versie-stempel {
  margin-top: var(--section-gap);
  padding: 0;
  text-align: right;
}

/* Taalkiezer linksonder in beeld. Als rij knoppen onder de kaart werkte dat bij
   drie talen nog; bij tien liep het van het scherm af. Nu een wereldbol met de
   huidige taal die hetzelfde menu opent als in de zijbalk. */
.auth_taalknop {
  position: fixed;
  left: 16px;
  bottom: 16px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  font: inherit;
  font-size: var(--tekst-klein);
  color: var(--muted);
  cursor: pointer;
}
.auth_taalknop:hover { color: var(--ink); background: var(--hover); }
.auth_taalknop .material-icons { font-size: 20px; }

/* ------------------------------------------------------------------- auth -- */

/* Inloggen, aanmelden en herstellen. Hergebruikt .card, .btn en .field; wat
   hier staat is alleen de opbouw van de pagina zelf. */
.auth {
  min-height: 100vh;
  display: flex;
}

/* Zelfde verdeling als bij een modal: het formulier hoort in het bovenste
   kwart, niet halverwege het scherm. */
.auth_paneel {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px 20px 40px;
}
.auth_paneel::before,
.auth_paneel::after { content: ""; flex-shrink: 1; min-height: 0; }
.auth_paneel::before { flex-grow: 1; }
.auth_paneel::after { flex-grow: 3; }

/* De pitchkolom is decoratief: daar leest en klikt niemand, dus die hoort wél
   gewoon in het midden. Het hogere zwaartepunt is voor de kolom waar je iets
   moet doen. */
.auth_paneel--pitch::after { flex-grow: 1; }
.auth_kolom { flex: 0 0 auto; }

.auth_kolom {
  width: min(400px, 100%);
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

.auth_logo {
  display: block;
  width: 200px;
  max-width: 70%;
  margin: 0 auto 28px;
  object-fit: contain;
}

/* De ruimte onder de kop hoort bij de kop zelf. Stond hij op de ondertitel,
   dan plakte de kaart tegen de titel zodra een pagina die ondertitel weglaat. */
.auth_titel {
  font-size: 24px;
  font-weight: var(--vet);
  text-align: center;
  margin-bottom: 24px;
}
.auth_ondertitel {
  font-size: var(--tekst);
  color: var(--muted);
  text-align: center;
  margin: -16px 0 24px;
  line-height: 1.5;
}

.auth_kaart { padding: 24px; }

/* Aanbieders: witte knop met het merkteken links en het label gecentreerd. */
.auth_aanbieders { display: flex; flex-direction: column; gap: 10px; }
.auth_aanbieder {
  position: relative;
  width: 100%;
  justify-content: center;
  padding: 13px 18px;
  border-color: var(--border-sterk);
}
.auth_aanbieder-icoon {
  position: absolute;
  left: 18px;
  display: inline-flex;
  width: 20px;
  height: 20px;
}
.auth_aanbieder-icoon svg { width: 100%; height: 100%; }

/* Scheiding met het woord in het midden. */
.auth_scheiding {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 20px 0;
  color: var(--muted);
  font-size: var(--tekst-klein);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.auth_scheiding::before, .auth_scheiding::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* De verzendknop vult de kaart: op een inlogpagina is er maar één ding te doen. */
.auth_kaart .form-acties { margin-top: 22px; padding-top: 0; border-top: 0; }
.auth_kaart .form-acties .btn { width: 100%; justify-content: center; padding: 13px 18px; }

.auth_klein, .auth_voet { text-align: center; color: var(--muted); }
.auth_klein { font-size: var(--tekst-klein); margin-top: 18px; line-height: 1.6; }
.auth_voet { font-size: var(--tekst); margin-top: 24px; }
.auth_voet p + p { margin-top: 12px; }
.auth_klein a, .auth_voet a { color: var(--ink); text-decoration: underline; }

/* Aanmelden: links de pitch, rechts het formulier. De kaart verliest daar zijn
   omlijsting, want het paneel is zelf al het vlak. */
.auth--split .auth_paneel--pitch { background: var(--bg); align-items: center; }
.auth--split .auth_paneel:not(.auth_paneel--pitch) { background: var(--card-bg); align-items: center; }
.auth--split .auth_kaart { background: none; box-shadow: none; border: 0; padding: 0; }

.auth_pitch { width: min(420px, 100%); }
/* Eigen inhoud (een kaart, een illustratie) heeft geen leesbreedte nodig maar
   ruimte; anders staat een kaart van 420 pixels midden in een kolom van 750. */
.auth_pitch--eigen { width: 100%; display: flex; flex-direction: column; }
.auth_pitch .auth_logo { margin: 0 0 24px; }
.auth_tagline { font-size: 18px; line-height: 1.45; margin-bottom: 40px; }

.auth_quote { margin: 0 0 36px; }
.auth_quote blockquote {
  margin: 0 0 14px;
  font-style: italic;
  color: var(--muted);
  line-height: 1.55;
}
.auth_quote-bron { display: flex; align-items: center; gap: 12px; }
.auth_quote-bron img { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; }
.auth_quote-naam { font-weight: var(--vet); }
.auth_quote-rol { color: var(--muted); font-size: var(--tekst-klein); }

@media (max-width: 860px) {
  .auth_paneel { padding: 16px 16px 40px; }
  .auth--split .auth_paneel--pitch { display: none; }
}

/* ---------------------------------------------------------------- grafiek -- */

/* Chart.js meet de beschikbare ruimte van zijn ouder. Zonder een houder met een
   vaste hoogte en position:relative groeit een canvas bij elke hertekening. */
.chart-vlak { position: relative; width: 100%; }
.chart-vlak > canvas { display: block; }

/* ------------------------------------------------------------ dashboardgrid */

/* Kop van een dashboardkaart: titel links, knoppen rechts, en op een smal
   scherm onder elkaar in plaats van samengeperst. */
.dash-head { flex-wrap: wrap; }
.dash-acties {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.dash_kop { margin-bottom: 14px; }

.dash_periode { gap: 8px; }
.dash_periode .material-icons { font-size: 18px; color: var(--muted); }
.dash_periode span { font-weight: var(--vet); }

@media (max-width: 720px) {
  .dash-acties { margin-left: 0; width: 100%; }
  .dash-acties > * { flex: 1 1 auto; }
}

/* minmax(0, 1fr) en niet 1fr: een grid-item krimpt standaard niet onder zijn
   min-content, en een grafiekcanvas heeft een eigen breedte. Eén te brede
   widget rekte zo de hele kolom op en dan liep de pagina rechts van het scherm
   af - alle kaarten, niet alleen de grafiek. */
.dash_widgets { display: grid; gap: var(--card-gap); grid-template-columns: minmax(0, 1fr); }
.dash_widgets.heeft-half { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.dash_widgets > * { min-width: 0; }
.dash_widgets .is-vol { grid-column: 1 / -1; }

/* Twee kaarten naast elkaar worden onleesbaar smal voordat het breekpunt van
   de navigatie in zicht komt; daarom een eigen, ruimere grens. */
@media (max-width: 900px) {
  .dash_widgets.heeft-half { grid-template-columns: minmax(0, 1fr); }
}

/* ----------------------------------------------------------------- kpi-tegel */

.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--card-gap); }
.kpi {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.kpi_label { font-size: var(--tekst-klein); color: var(--muted); line-height: 1.2; }
.kpi_waarde {
  font-size: 22px;
  font-weight: var(--vet);
  line-height: 1.15;
  letter-spacing: -0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kpi_delta { font-size: var(--tekst-klein); }
.kpi_delta--op { color: var(--good); }
.kpi_delta--af { color: var(--bad); }

/* Op een telefoon valt auto-fit terug op één kolom: twee tegels van 170px plus
   de tussenruimte passen niet in ~340px werkbreedte. Een kolom kaarten leest
   als een lijstje en je ziet er drie op een scherm. Twee aan twee past wel,
   mits de tegel wat compacter wordt - anders kapt het bedrag af.
   De grens ligt bewust laag: boven de 480px geeft auto-fit vanzelf al twee of
   meer kolommen, dus daar verandert deze regel niets. */
@media (max-width: 480px) {
  .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpi { padding: 14px; }
  .kpi_waarde { font-size: 19px; }
}

/* ---------------------------------------------------------------- responsive */

@media (max-width: 860px) {
  .sidebar { display: none; }
  .bottomnav { display: flex; }

  .page {
    margin-left: 0;
    margin-top: calc(60px + env(safe-area-inset-top, 0px));
    padding: 10px;
    padding-bottom: calc(var(--bottomnav-h) + env(safe-area-inset-bottom, 0px) + 14px);
  }

  /* Zoekveld en filters onder elkaar en op volle breedte; naast elkaar wordt
     het op een telefoon te krap. De flex-waarden moeten hier terug naar de
     standaard: een flex-basis van 240px gaat in een kolom over de hóógte, en
     dan wordt het zoekveld 240 pixels hoog. */
  .card_filters { flex-direction: column; align-items: stretch; }
  .card_filters > *,
  .card_filters input[type="search"],
  .card_filters select,
  .card_filters .filter-veld { flex: 0 0 auto; width: 100%; }

  .mobile-header { display: flex; }

  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
  .kv { grid-template-columns: 1fr; }

  /* iOS Safari zoomt bij focus in op elk veld onder 16px, ongeacht de
     viewport-meta. Vandaar hier expliciet 16px. */
  .field input, .field select, .field textarea,
  .card_filters input, .card_filters select, .card_filters .filter-veld,
  .line-items input, .line-items select,
  .rel input {
    font-size: var(--kop-klein);
  }

  .card { padding: 14px; }
  .card_head { margin-bottom: 16px; }
  .card_head { flex-wrap: wrap; }
  .card_actions { margin-left: 0; width: 100%; }

  .toast-stack {
    left: 12px; right: 12px; max-width: none;
    bottom: calc(var(--bottomnav-h) + env(safe-area-inset-bottom, 0px) + 12px);
  }
  .modal_voet { flex-direction: column-reverse; }
  .modal_voet .btn { width: 100%; justify-content: center; }
  .line-totals { width: 100%; }
}

/* -------------------------------------------------------------------- donker */

/* Donkere modus is neutraal zwart en grijs met witte tekst. Blauw blijft
   voorbehouden aan accenten: de merkkleur en het info-label. Een blauwe
   ondertoon in de achtergronden (wat hier eerst stond) maakt het hele scherm
   blauw in plaats van donker. */
body.dark-mode {
  color-scheme: dark;

  --ink: #f2f2f3;
  --muted: #9b9b9f;
  --bg: #0e0e10;
  --card-bg: #171719;
  --hover: #202023;
  --active: #27272b;
  --border: rgba(255, 255, 255, 0.10);
  --border-sterk: rgba(255, 255, 255, 0.22);

  --good-soft: #16301d; --good-ink: #7fd398;
  --warn-soft: #34280f; --warn-ink: #f0c274;
  --bad-soft:  #3a1818; --bad-ink:  #f2a0a0;
  --info-soft: #1a2740; --info-ink: #9ec2f0;
  --neutral-soft: #27272b; --neutral-ink: #b4b4b8;

  --shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
  --shadow-groot: 0 12px 32px rgba(0, 0, 0, 0.65);

  /* In het donker valt een schaduw weg tegen een donkere achtergrond; daar is
     een lichte rand het enige wat een kaart nog van de pagina scheidt. */
  --vlak-rand: rgba(255, 255, 255, 0.10);
  --vlak-schaduw: none;
  --kop-bg: #202023;
}

body.dark-mode .bottomnav { box-shadow: none; }

body.dark-mode .mobile-header {
  background: rgba(20, 20, 22, 0.6);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.5);
}
body.dark-mode .tooltip-pop { background: #35353a; }
body.dark-mode .media-tegel_knop { background: rgba(38, 38, 42, 0.92); color: var(--ink); }
body.dark-mode .card_filters input[type="search"] {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%239aa0aa'><path d='M15.5 14h-.79l-.28-.27A6.47 6.47 0 0016 9.5 6.5 6.5 0 109.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'/></svg>");
}

/* Afdrukken: alleen de inhoud. */
@media print {
  .sidebar, .bottomnav, .card_actions, .card_filters, .toast-stack, .modal-achtergrond { display: none !important; }
  .page { margin: 0; padding: 0; }
  .card { border: 0; padding: 0; }
  body { background: #fff; }
}


/* ------------------------------------------------------------------ kaart -- */

/* Een SVG-kaart waarvan de gebieden een staat hebben. De kleuren komen uit de
   tokens, dus een kaart neemt vanzelf de huisstijl over. */
.kaart {
  display: block;
  width: 100%;
  max-width: 100%;
  color: var(--rand-zacht, #e6e6e6);   /* vulkleur van de SVG zelf */
}
.kaart svg { display: block; width: 100%; height: auto; max-height: var(--kaart-hoogte, none); }
.kaart--leeg { min-height: 0; }

.kaart_gebied {
  fill: var(--kaart-leeg, #e4e6e4);
  stroke: var(--card-bg, #fff);
  stroke-width: 0.6;
  transition: fill var(--duur, .15s) ease-out;
}
.kaart_gebied--actief { fill: var(--brand); }

/* Hover alleen waar er iets te vertellen valt. Een gebied zonder tooltip en
   zonder klik hoeft niet te reageren; dat suggereert een actie die er niet is. */
.kaart_gebied[data-tooltip]:hover,
.kaart_gebied--klikbaar:hover { fill: var(--kaart-hover, #c9cdc9); }
.kaart_gebied--actief[data-tooltip]:hover,
.kaart_gebied--actief.kaart_gebied--klikbaar:hover { fill: var(--brand); opacity: .82; }
.kaart_gebied--klikbaar { cursor: pointer; }
.kaart_gebied:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Punten op lengte en breedte. Donker en half doorzichtig, zodat ze op zowel
   een lege als een gekleurde provincie leesbaar zijn en overlap zichtbaar
   blijft. De rand blijft één pixel, hoe groot de kaart ook getekend wordt. */
.kaart_punt {
  fill: var(--kaart-punt, var(--ink));
  fill-opacity: .5;
  stroke: var(--card-bg, #fff);
  stroke-width: 1px;
  vector-effect: non-scaling-stroke;
  transition: fill-opacity var(--duur, .15s) ease-out;
}
.kaart_punt[data-tooltip]:hover { fill-opacity: .8; }


/* Een wizard binnen een inlogkaart. Daar staat hij tussen andere formulieren,
   dus hij hoort zich als een formulier te gedragen: knop over de volle breedte,
   geen scheidingslijn, en de stappen gecentreerd onder de titel. De genummerde
   bolletjes laten we hier weg; de kaart heeft al een titel en twee bolletjes
   naast elkaar oogt als een installatiewizard. Op een eigen pagina blijft de
   wizard staan zoals hij was. */
.auth_kaart .wizard_voortgang {
  justify-content: center;
  gap: 8px;
  margin-bottom: 22px;
}
.auth_kaart .wizard_bol { display: none; }
.auth_kaart .wizard_stap { padding: 4px 12px; }

/* De stapkop herhaalt wat er in de voortgang al staat. */
.auth_kaart .wizard_kop { display: none; }

.auth_kaart .wizard_voet {
  flex-direction: column-reverse;
  align-items: stretch;
  gap: 10px;
  margin-top: 22px;
  padding-top: 0;
  border-top: 0;
}
.auth_kaart .wizard_voet .btn {
  width: 100%;
  justify-content: center;
  padding: 13px 18px;
  margin-left: 0;
}

/* Velden en kolommen met `kopieerbaar: false`. Zie TableKit en PageKit.
   Dit maakt selecteren onmogelijk, niet lezen: de waarde staat gewoon in beeld
   en in het title-attribuut. Het haalt alleen het gemak weg om in één sleep een
   hele kolom met adressen mee te nemen. */
.geen-kopie,
.geen-kopie * {
  -webkit-user-select: none;
  user-select: none;
}

/* Het keuzepaneel van RelationKit hangt aan <body> en moet dus boven een modal
   uitkomen. Zonder dit valt de landenlijst achter het venster waarin je hem opent:
   .sl-menu staat op 60 en .modal-achtergrond op 80. Onder de toasts en de tooltip
   blijven, want een melding over wat er misging hoort altijd leesbaar te zijn. */
.rel_paneel {
  z-index: 85;
  max-height: 320px;
  overflow-y: auto;
}

/* De selectie boven een vaste lijst: gewone tekst, geen pillen. Aan en uit gaat in
   de lijst zelf. */
.rel_samenvatting {
  font-size: 14px;
  color: var(--tekst-zacht, var(--muted));
  margin-bottom: 6px;
  line-height: 1.45;
}

/* Hetzelfde vinkje als in de keuzekolom van een tabel. */
.rel_vink {
  font-size: 20px;
  line-height: 0;
  color: var(--brand);
  flex: 0 0 auto;
}
