/* ===== OMS — CORE STYLESHEET ===== */
/* Design-systeem componenten. Kleiner en gerichter dan PMS' monolithische
   stylesheet — alleen wat OMS' huidige pagina's daadwerkelijk gebruiken. */

* { box-sizing: border-box; }
html { touch-action: manipulation; }
html, body {
  margin: 0; padding: 0;
  font-family: 'Fira Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-size: 15px;
  line-height: 1.5;
  background: var(--bg-page);
  color: var(--text-primary);
}
img { display: block; max-width: 100%; }
a { color: var(--text-link); }

/* Het HTML-attribuut `hidden` moet altijd winnen. De UA-regel `[hidden]{display:none}`
   verliest namelijk van elke component-regel met een eigen display (bijv.
   `.btn{display:inline-flex}`), waardoor `el.hidden = true` in JS niets leek te doen. */
[hidden] { display: none !important; }

/* ===== LAYOUT ===== */
body.app-layout { min-height: 100vh; }

.sidebar {
  position: fixed; left: 0;
  top: var(--dev-bar-offset, 0px);
  height: calc(100vh - var(--dev-bar-offset, 0px));
  width: var(--sidebar-width);
  background: var(--bg-sidebar); border-right: 1px solid var(--border-color);
  display: flex; flex-direction: column;
  transition: width .28s cubic-bezier(.4,0,.2,1); z-index: 50;
  box-shadow: 4px 0 20px rgba(0,0,0,.06);
  /* Geen overflow:hidden hier — laat de toggle-knop uitsteken */
}

/* Alleen het nav-scrollgebied clippen, niet de hele sidebar */
.sidebar-logo,
.sidebar-footer {
  overflow: hidden;
}

.sidebar.collapsed { width: var(--sidebar-collapsed-width); }
/* Wegfaden en de breedte naar 0, niet display:none — zo animeert het label mee
   met de sidebar in plaats van er halverwege uit te klappen (zelfde als PMS). */
.sidebar.collapsed .nav-label,
.sidebar.collapsed .sidebar-logo-text,
.sidebar.collapsed .sidebar-user-info {
  opacity: 0;
  width: 0;
}

/* Vaste hoogte gelijk aan .app-header, zodat de scheidingslijn van de sidebar
   precies uitlijnt met die van de header (zelfde patroon als KMS
   .admin-sidebar-brand). Hoogte NIET door de inhoud laten bepalen. */
.sidebar-logo {
  height: var(--header-height); box-sizing: border-box;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: 11px 14px; border-bottom: 1px solid var(--border-color);
  font-weight: 600; font-size: 16px; color: var(--text-heading);
  white-space: nowrap; overflow: hidden;
  flex-shrink: 0;
}
.sidebar.collapsed .sidebar-logo { padding: 11px 8px; }

/* Geüpload menu-logo (Instellingen → Bedrijfsgegevens → Logo's). Toont de
   licht/donker-variant afhankelijk van het actieve thema. */
/* Vult het hele logovak (60px hoog min 2x7px padding, 252px breed min 2x12px)
   in plaats van de oude max-height:32px, die op een breed liggend logo maar de
   helft van de beschikbare hoogte gebruikte. object-fit:contain houdt de
   verhouding intact, dus een vierkant logo wordt hier gewoon 38px. */
.sidebar-logo-img { width: 100%; height: 100%; object-fit: contain; }
:root[data-theme="dark"] .sl-light { display: none; }
:root[data-theme="light"] .sl-dark { display: none; }
/* Standaard (geen data-theme) = licht */
:root:not([data-theme="dark"]) .sl-dark { display: none; }

.sidebar-nav {
  flex: 1;
  /* min-height:0 nodig zodat een flex-item kleiner mag worden dan zijn inhoud;
     anders krimpt de nav niet en treedt overflow-y:auto niet in werking als een
     dropdown openstaat (geen scroll mogelijk op mobiel) */
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  /* iOS: momentum-scroll + voorkom dat de scroll naar de body "doorlekt"
     (zonder deze props weigert een genest scrollvlak in een position:fixed
     sidebar soms te scrollen op iPhone Safari) */
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 6px 0;
  /* Flexkolom zodat .nav-feedback-wrap met margin-top:auto onderaan het paneel
     landt als het menu korter is dan de sidebar hoog. Past het menu niet, dan
     neemt de sticky-positionering van die wrap het over. */
  display: flex;
  flex-direction: column;
}
/* Items houden hun eigen hoogte: zonder dit worden ze bij een vol menu door
   flex-shrink platgedrukt in plaats van dat de nav gaat scrollen. */
.sidebar-nav > * { flex-shrink: 0; }

/* Groepsscheiding in het hoofdmenu. Vervangt de tekstkoppen ("Relaties",
   "Verkoop", …): die kostten elk ~32px en met zeven groepen viel de onderkant
   van het menu buiten beeld. Blijft ook in de ingeklapte stand staan — een
   lijntje van 40px breed leest daar prima. */
.nav-sep {
  height: 1px;
  margin: 7px 14px;
  background: var(--text-sidebar);
  opacity: 0.14;
}

/* Sectiekop in de sidebar (Relaties, Verkoop, …). Zelfde opzet als PMS:
   klein, uppercase, ruim gespatieerd — en gedempt via opacity op
   --text-sidebar, want --text-muted keert in dark mode juist om naar licht. */
.nav-section-label {
  padding: 14px 18px 5px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-sidebar);
  opacity: 0.5;
  white-space: nowrap; overflow: hidden;
  transition: opacity 0.2s;
}
.sidebar.collapsed .nav-section-label { opacity: 0; }

.nav-item {
  display: flex; align-items: center;
  padding: 7px 12px; margin: 1px 8px;
  border-radius: var(--radius-md);
  color: var(--text-sidebar); text-decoration: none;
  font-family: inherit; font-size: 13.5px;
  transition: background .15s ease, color .15s ease;
  white-space: nowrap; overflow: hidden;
  cursor: pointer; border: none; background: none; width: calc(100% - 16px); text-align: left;
  user-select: none;
  position: relative;
}
.nav-item:hover { background: var(--bg-sidebar-hover); color: var(--color-primary); text-decoration: none; }
.nav-item.active { background: var(--bg-sidebar-active); color: var(--text-sidebar-active, #fff); }
/* Bewust op .nav-icon en niet op `.nav-item svg` zoals PMS: die bredere
   selector wint van .nav-chevron (gelijke specificiteit, maar hij staat
   eerder) en blaast het chevronnetje op naar 18px. */
.nav-icon { flex-shrink: 0; width: 18px; height: 18px; min-width: 18px; }

/* Getal rechts op een menu-item: hoeveel er op dat scherm ligt te wachten.
   Verdwijnt met het label zodra de sidebar ingeklapt is — op 18px zou het over
   het icoon heen vallen, en de `title` op het item zegt het toch al. */
.nav-teller {
  flex-shrink: 0;
  min-width: 18px; padding: 0 5px;
  border-radius: var(--radius-full);
  background: var(--bg-sidebar-hover);
  color: inherit;
  font-size: 11px; font-weight: 700; line-height: 17px; text-align: center;
  font-variant-numeric: tabular-nums;
  transition: opacity .2s;
}
.sidebar.collapsed .nav-teller { opacity: 0; width: 0; min-width: 0; padding: 0; }

/* De ruimte tussen icoon en label zit hier en niet in een `gap` op .nav-item:
   met een gap zou de collapsed-stand (width:0) alsnog 10px overhouden. */
.nav-label {
  margin-left: 11px;
  font-size: 13.5px;
  font-weight: 500;
  opacity: 1;
  transition: opacity 0.2s;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- Dropdown --- */

.nav-chevron {
  margin-left: auto;
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  transition: transform 0.22s ease;
  opacity: 0.6;
}

.nav-dropdown-trigger.open .nav-chevron { transform: rotate(180deg); }

.nav-dropdown-content {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.28s ease;
}
.nav-dropdown-content.open { max-height: 600px; }

.sidebar.collapsed .nav-dropdown-content { display: none; }

.nav-sub-item {
  display: flex; align-items: center;
  padding: 6px 14px 6px 41px; margin: 1px 8px;
  border-radius: var(--radius-md); color: var(--text-sidebar); text-decoration: none;
  font-size: 13px; font-weight: 500;
  transition: background .15s ease, color .15s ease;
  white-space: nowrap; cursor: pointer;
}
.nav-sub-item:hover { background: var(--bg-sidebar-hover); color: var(--color-primary); text-decoration: none; }
.nav-sub-item.active { background: var(--bg-sidebar-active); color: var(--text-sidebar-active, #fff); }

/* --- Snel zoeken: veld in de header + paneel eronder --- */

.sz-wrap { position: relative; width: 100%; }

.sz-veld {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 34px;
  padding: 0 10px;
  background: var(--bg-input, var(--bg-subtle));
  border: 1px solid var(--border-input, var(--border-color));
  border-radius: var(--radius-md);
  color: var(--text-muted);
  transition: border-color .15s, box-shadow .15s;
}
.sz-veld:hover { border-color: var(--color-primary); }
/* Focusring op de WIKKEL en niet op de input: het veld is visueel één geheel
   met het icoon en de toets ernaast. */
.sz-veld.is-actief {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-light);
}
.sz-veld-icoon { width: 15px; height: 15px; flex-shrink: 0; }
.sz-input {
  flex: 1;
  min-width: 0;
  border: none;
  background: transparent;
  font-family: inherit;
  font-size: 13.5px;
  color: var(--text-primary);
  outline: none;
}
.sz-input::placeholder { color: var(--text-muted); }
.sz-veld-key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border: 1px solid var(--border-color);
  border-radius: 4px;
  background: var(--bg-subtle);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  color: var(--text-muted);
}
.sz-veld-wis {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  padding: 0;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
.sz-veld-wis:hover { color: var(--text-primary); background: var(--bg-subtle); }
.sz-veld-wis svg { width: 14px; height: 14px; }
.sz-veld-wis[hidden], .sz-veld-key[hidden] { display: none; }

/* Het paneel hangt AAN het veld en is breder dan het veld zelf: de resultaten
   dragen twee regels plus een bedrag, en dat past niet in 460px. */
.sz-paneel {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: min(720px, calc(100vw - 32px));
  max-height: min(620px, calc(100vh - 120px));
  display: flex;
  flex-direction: column;
  background: var(--bg-modal);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-modal);
  overflow: hidden;
  z-index: 60;
}
.sz-paneel[hidden] { display: none; }

.sz-results { flex: 1; overflow-y: auto; min-height: 0; padding: 6px 0; }

/* Groepskop: rustige grijze regel, géén achtergrond, icoon of teller. Hij deelt
   de lijst op — hij mag hem niet overstemmen. */
.sz-group {
  padding: 10px 16px 4px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
}
.sz-group:first-child { padding-top: 4px; }

.sz-item {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 12px;
  padding: 8px 16px;
  cursor: pointer;
  border: none;
  background: transparent;
}
.sz-item:hover,
.sz-item.sz-focused { background: var(--bg-table-row-hover); }
.sz-icoon {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
}
.sz-icoon svg { width: 16px; height: 16px; }

.sz-item-inhoud { min-width: 0; }
.sz-titel {
  font-size: 14px;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Het pad vóór de bestemming ("Instellingen › Maten"): gedempt, want het staat
   op elke tabregel hetzelfde en de tabnaam is waar je naar kijkt. Krimpt niet
   mee weg — bij een te lange regel hoort de NAAM af te kappen, niet de plek. */
.sz-pad { color: var(--text-muted); }
.sz-sub {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 3px;
  min-width: 0;
  font-size: 12.5px;
  color: var(--text-muted);
}
.sz-sub-tekst {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Rechterkolom: bedrag boven, datum of hotkey eronder — beide rechts uitgelijnd
   zodat de bedragen onder elkaar staan. */
.sz-rechts {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  text-align: right;
  white-space: nowrap;
}
.sz-bedrag {
  font-size: 14px;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.sz-datum {
  font-size: 12.5px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
/* Bij een snelle actie staan pulse en hotkey NAAST elkaar, niet onder elkaar:
   het zijn geen twee regels informatie maar één signaal plus één sneltoets. */
.sz-rechts.is-rij { flex-direction: row; align-items: center; gap: 8px; }

/* De pulses zelf komen uit het gedeelde patroon (.oms-pulse / .oms-pulse-geel);
   hier alleen de marge terugzetten die ze voor een tabelcel meekrijgen. */
.sz-pulse { margin-left: 0; }

.sz-hotkey {
  display: inline-block;
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  border: 1px solid var(--border-color);
  font-family: inherit;
  font-size: 11.5px;
  color: var(--text-muted);
}

/* De zoekterm licht op in ELK veld waar hij voorkomt — dat is wat laat zien
   waaróm een regel in de lijst staat. Alleen kleur, geen gevulde achtergrond:
   een lijst vol gele blokjes leest niet meer als een lijst. */
.sz-mark {
  background: none;
  color: var(--color-primary);
  font-weight: 700;
}

/* De statusbadge is de generieke .badge uit dit bestand — dezelfde als op de
   lijstpagina's, zodat één order hier niet anders heet dan daar. Alleen iets
   compacter: hij staat in een subregel van 12,5px en niet in een tabelcel. */
.sz-sub .badge { padding: 1px 7px; font-size: 11px; }

.sz-status {
  padding: 26px 16px;
  text-align: center;
  color: var(--text-muted);
  font-size: 13.5px;
}
.sz-status-error { color: var(--color-danger); }

.sz-footer {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 9px 16px;
  border-top: 1px solid var(--border-color);
  background: var(--bg-subtle);
  font-size: 11.5px;
  color: var(--text-muted);
  flex-shrink: 0;
  overflow-x: auto;
}
.sz-footer span { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.sz-footer kbd {
  display: inline-block;
  background: var(--bg-modal);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  padding: 1px 5px;
  font-size: 11px;
  font-family: inherit;
}

@media (max-width: 768px) {
  /* Op mobiel is de header te krap voor een invoerveld naast de paginatitel;
     het veld krimpt tot het vergrootglas en groeit uit zodra je erin klikt. */
  .sz-veld { width: 34px; padding: 0; justify-content: center; }
  .sz-veld .sz-input, .sz-veld-key { display: none; }
  /* Fixed en niet absolute: .sz-wrap is hier maar 34px breed, dus een absoluut
     veld verankerd aan zijn rechterrand schuift links het scherm uit. */
  .sz-veld.is-actief {
    position: fixed;
    left: 8px;
    right: 8px;
    top: calc(var(--dev-bar-offset, 0px) + (var(--header-height) - 34px) / 2);
    width: auto;
    padding: 0 10px;
    justify-content: flex-start;
    background: var(--bg-modal);
    z-index: 61;
  }
  .sz-veld.is-actief .sz-input { display: block; }
  .sz-paneel { position: fixed; left: 8px; right: 8px; top: calc(var(--dev-bar-offset, 0px) + var(--header-height)); width: auto; transform: none; }
}


/* --- Feedback knop --- */

/* Plakt onderaan het scrollgebied van de nav. Het menu is langer dan de
   sidebar hoog is, dus zonder sticky staat de knop pas onder de laatste
   menu-items en moet je ervoor scrollen. De achtergrond is nodig omdat de
   items er anders doorheen schuiven. */
.nav-feedback-wrap {
  position: sticky;
  bottom: -6px; /* compenseert de padding-bottom van .sidebar-nav */
  z-index: 1;
  margin-top: auto; /* duwt de knop naar de onderkant bij een kort menu */
  padding: 6px 0;
  background: var(--bg-sidebar);
}

button.nav-item.nav-feedback-btn {
  margin-bottom: 0;
  color: var(--color-danger);
  border: 1.5px dashed var(--color-danger);
  background: transparent;
}
button.nav-item.nav-feedback-btn:hover {
  color: var(--color-danger);
  background: rgba(239,68,68,.1);
}

/* Beheer-knop: staat in dezelfde sticky wrapper, bóven de feedbackknop. Geen
   uitklapper ín de lijst maar een zwevend paneel dat naast de knop opent (zie
   `uitlijning: 'naast'` in rowMenuOpen) — de wrapper plakt onderaan, dus naar
   beneden is er geen ruimte om open te klappen. */
button.nav-item.nav-beheer-btn { margin-bottom: 6px; }
button.nav-item.nav-beheer-btn.is-open {
  background: var(--bg-sidebar-hover);
  color: var(--color-primary);
}
/* De chevron wijst naar rechts en hoeft niet te draaien: het paneel gaat altijd
   diezelfde kant op. Ingeklapt valt hij weg — het label is er dan ook niet, en
   een pijl pal tegen het icoon leest als een tweede icoon. */
.sidebar.collapsed .nav-beheer-btn .nav-chevron { display: none; }

/* De huidige pagina in het Beheer-paneel. Zelfde tint als .nav-item.active in
   de sidebar; het paneel zelf is een gewone .row-dropdown. */
.beheer-menu .row-dropdown-item.is-actief {
  background: var(--bg-card-hover);
  color: var(--color-primary);
  font-weight: 600;
}
.beheer-menu .row-dropdown-item.is-actief svg { opacity: 1; }

/* --- Toggle knop (collapse) --- */

.sidebar-toggle {
  position: absolute;
  right: -14px;
  top: 121px;
  background: var(--color-primary);
  border: 2px solid var(--bg-page);
  border-radius: 50%;
  width: 28px;
  height: 28px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-md);
  color: white;
  z-index: 51;
  transition: background 0.18s ease;
}
.sidebar-toggle:hover { background: var(--color-primary-hover); }
.sidebar-toggle svg { width: 14px; height: 14px; }

/* --- Sidebar footer (gebruikersinfo) --- */

.sidebar-footer {
  padding: 0;
  border-top: 1px solid var(--border-color);
  flex-shrink: 0;
}

.sidebar-footer-row {
  display: flex;
  align-items: center;
  gap: 4px;
}

.sidebar-user {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border-radius: var(--radius-md);
  overflow: hidden;
  cursor: default;
}

.sidebar-user-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--color-primary);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  flex-shrink: 0;
  text-transform: uppercase;
}

.sidebar-user-info {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  transition: opacity 0.2s, width 0.2s;
}

.sidebar-user-name {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.3;
}

.sidebar-user-role {
  font-size: 10.5px;
  color: var(--text-muted);
  text-transform: capitalize;
  margin-top: 1px;
}

.sidebar-logout-btn {
  flex-shrink: 0;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-md);
  color: var(--text-muted);
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
  margin-right: 4px;
}
.sidebar-logout-btn:hover { background: rgba(239,68,68,0.1); color: var(--color-danger); }
.sidebar-logout-btn svg { width: 17px; height: 17px; }
/* Dezelfde vorm als <button> (het slotje naast uitloggen): zonder deze reset
   houdt hij zijn browser-eigen rand, achtergrond en padding. Zelfde reden als
   `button.row-dropdown-item` verderop. */
button.sidebar-logout-btn {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  cursor: pointer;
}

.main-content {
  margin-left: var(--sidebar-width);
  transition: margin-left .28s cubic-bezier(.4,0,.2,1);
  /* MIN DE DEV-/ONDERHOUDSBALK. Die balk is `position: fixed` maar duwt het
     document met `body { padding-top }` naar beneden (zie index.php); een kale
     100vh maakt het document dan precies die balkhoogte te lang en geeft élke
     pagina een schuifbalk van 22px — ook een pagina die zelf exact in beeld past,
     zoals de artikel-picker op ?page=artikelen. */
  min-height: calc(100vh - var(--dev-bar-offset, 0px));
  display: flex; flex-direction: column;
}
.main-content.sidebar-collapsed { margin-left: var(--sidebar-collapsed-width); }

.app-header {
  height: var(--header-height); flex-shrink: 0;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 24px; background: var(--bg-header); border-bottom: 1px solid var(--border-color);
  position: sticky; top: 0; z-index: 40;
  gap: 16px;
}
/* De paginatitel is UIT BEELD maar niet uit de DOM: het sidebar-item dat aanstaat
   zegt al waar je bent, terwijl een pagina zonder <h1> voor een schermlezer geen
   kop meer heeft om op te landen. Niet met `display: none` of `hidden` — dan
   leest de schermlezer hem ook niet meer; dit is de gebruikelijke clip-truc. */
.page-title-verborgen {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* Links en rechts krijgen dezelfde flex-basis (0) en groeifactor, zodat de
   zoekbalk in het midden ook echt gecentreerd staat en niet meeschuift met de
   accountnaam. */
.app-header-left { display: flex; align-items: center; gap: 12px; min-width: 0; flex: 1 1 0; }
.app-header-right { display: flex; align-items: center; justify-content: flex-end; gap: 14px; min-width: 0; flex: 1 1 0; }
.app-header-center { display: flex; justify-content: center; flex: 0 1 460px; min-width: 0; }

/* Hamburger-knop (alleen mobiel zichtbaar) */
.mobile-menu-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.mobile-menu-btn:hover { background: var(--bg-subtle); color: var(--text-primary); }
.mobile-menu-btn svg { width: 22px; height: 22px; }

.theme-toggle {
  width: 38px; height: 38px; border-radius: var(--radius-full);
  border: 1px solid var(--border-color); background: none;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  color: var(--text-secondary);
  flex-shrink: 0;
  position: relative;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.theme-toggle:hover {
  background: var(--bg-card-hover);
  color: var(--color-primary);
  border-color: var(--color-primary);
}
.theme-toggle svg { width: 16px; height: 16px; }

/* ===== THEMASCHAKELAAR (pill met twee knoppen) =====
   Overgenomen uit KMS (.theme-switcher): je ziet welke stand AAN staat in plaats
   van waar je naartoe zou gaan. Zit in het gebruikersmenu in de header, en als
   `.theme-switcher-fixed` rechtsboven op de inlogpagina. */
.theme-switcher {
  display: flex; align-items: center;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-full, 999px);
  background: var(--bg-subtle);
  padding: 2px;
  gap: 2px;
}
.theme-btn {
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 16px;
  background: transparent; border: none;
  color: var(--text-muted);
  cursor: pointer; transition: background .15s, color .15s;
  flex-shrink: 0;
}
.theme-btn:hover { color: var(--text-primary); }
.theme-btn.active {
  background: var(--bg-card);
  color: var(--text-primary);
  box-shadow: 0 1px 3px rgba(0,0,0,.12);
}
.theme-switcher-fixed { position: fixed; top: 20px; right: 20px; z-index: 10; }

/* ===== DONKERHEID-REGELAAR (header) =====
   Kleine popover naast de thema-knop waarmee je in het donkere thema kiest
   hoe zwart "donker" is. De slider schrijft `--dark-lift` op <html>; alle
   donkere vlakken in css/theme.css zijn daarop gebouwd. */
.theme-controls {
  position: relative;
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
}

.theme-level-btn {
  width: 20px; height: 38px;
  border: none; background: none; padding: 0;
  /* Onzichtbaar in het lichte thema, maar hij HOUDT zijn ruimte: met display:none
     werd de rij 20px smaller en verschoof de themaschakelaar ernaast bij elke
     wissel. */
  display: flex;
  visibility: hidden;
  pointer-events: none;
  align-items: center; justify-content: center;
  cursor: pointer;
  color: var(--text-secondary);
  transition: color 0.15s ease, transform 0.18s ease;
}
.theme-level-btn svg { width: 14px; height: 14px; }
.theme-level-btn:hover { color: var(--color-primary); }
.theme-level-btn.open { transform: rotate(180deg); }
[data-theme="dark-v2"] .theme-level-btn { visibility: visible; pointer-events: auto; }

.theme-popover {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 90;                   /* boven de paginainhoud, onder de modal-overlay */
  width: 210px;
  padding: 12px 14px 10px;
  background: var(--bg-modal);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  display: none;
}
.theme-popover.open { display: block; }

.theme-popover-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: 8px;
}

.theme-popover-range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 4px;
  border-radius: var(--radius-full);
  /* De baan loopt van zwart naar het lichtste grijs dat de slider kan geven,
     zodat de knop laat zien wát je instelt in plaats van alleen hoevéél. */
  background: linear-gradient(to right, #000000, #3A3A3E);
  outline: none;
  cursor: pointer;
}
.theme-popover-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--color-primary);
  border: 2px solid var(--bg-modal);
  box-shadow: 0 0 0 1px var(--border-color);
  cursor: pointer;
}
.theme-popover-range::-moz-range-thumb {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--color-primary);
  border: 2px solid var(--bg-modal);
  cursor: pointer;
}

.theme-popover-schaal {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 6px;
  font-size: 11px;
  color: var(--text-muted);
}
.theme-popover-schaal #darkLevelWaarde {
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
  font-weight: 600;
}

.theme-popover-reset {
  margin-top: 10px;
  width: 100%;
  padding: 5px 0;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  background: var(--bg-subtle);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: var(--transition);
}
.theme-popover-reset:hover {
  color: var(--color-primary);
  border-color: var(--color-primary);
}

.header-username {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
}

.header-datum {
  font-size: 13px;
  line-height: 1.35;
  color: var(--text-muted);
  text-align: right;
  white-space: nowrap;
  flex-shrink: 0;
}

.page-content { flex: 1; padding: 12px; width: 100%; }

.sidebar-overlay {
  display: none; position: fixed; inset: 0; background: rgba(0,0,0,.4); z-index: 45;
}
.sidebar-overlay.active { display: block; }

@media (max-width: 768px) {
  .sidebar { transform: translateX(-100%); transition: transform .28s; }
  .sidebar.mobile-open { transform: translateX(0); }
  .main-content, .main-content.sidebar-collapsed { margin-left: 0; }

  /* Hamburger tonen, desktop-collapse-knop verbergen */
  .mobile-menu-btn { display: inline-flex; }
  .sidebar-toggle { display: none; }

  /* Op mobiel altijd volledige sidebar tonen, ook als desktop 'collapsed' actief was.
     Spiegelt de collapsed-regels bovenin (opacity/width, geen display). */
  .sidebar.collapsed .sidebar-logo-text,
  .sidebar.collapsed .nav-label,
  .sidebar.collapsed .sidebar-user-info {
    opacity: 1;
    width: auto;
  }
  .sidebar.collapsed .nav-teller { opacity: 1; width: auto; min-width: 18px; padding: 0 5px; }
  .sidebar.collapsed .sidebar-logo {
    padding: 0 16px;
    justify-content: flex-start;
  }
  .sidebar.collapsed .nav-dropdown-content.open { display: block; }

  .app-header { padding: 0 14px; }

  /* Op mobiel alleen hamburger + paginatitel + thema-toggle tonen — te weinig
     ruimte voor account-naam en datum/week-widget. */
  .header-username,
  .header-datum {
    display: none;
  }

  /* De zoekbalk krimpt tot het vergrootglas — zie .sz-veld hierboven. */
  .app-header-center { flex: 0 0 auto; }
}

/* `.page-header` (een <h2> met de paginanaam boven de inhoud) is nergens meer in
   gebruik — het lijstpagina-patroon draagt geen paginatitel meer. Zet hem niet
   terug: de sidebar wijst de pagina al aan. */

/* ===== BUTTONS ===== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 5px 12px; border-radius: var(--radius-md);
  font-size: 13.5px; font-weight: 600;
  border: 1px solid var(--border-color); background: transparent;
  color: var(--text-primary); line-height: 1; white-space: nowrap;
  transition: background .15s, box-shadow .15s, transform .12s, border-color .15s;
  cursor: pointer; text-decoration: none;
}
.btn:hover { background: var(--bg-card-hover); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn-primary { background: var(--color-primary); color: #fff; border-color: var(--color-primary); }
.btn-primary:hover { background: var(--color-primary-hover); }
.btn-secondary { background: transparent; color: var(--text-secondary); }
.btn-success { background: var(--color-secondary); color: #fff; border-color: var(--color-secondary); }
.btn-danger { background: var(--color-danger); color: #fff; border-color: var(--color-danger); }
.btn-danger:hover { background: var(--color-danger-hover); }
.btn-ghost { border: none; background: none; }
.btn-sm { padding: 6px 12px; font-size: 12.5px; }
.btn-lg { padding: 12px 28px; font-size: 15px; }
.btn-full { width: 100%; }
.btn-icon { padding: 8px; width: 34px; height: 34px; }

/* Hotkey-badge in een knop (bijv. "N" voor + Nieuwe klant) — zie .sz-hotkey voor het analoge patroon in snel-zoeken */
.btn-hotkey {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 4px;
  border-radius: var(--radius-sm); border: 1px solid rgba(255,255,255,.4);
  font-size: 11px; font-weight: 600; line-height: 1;
  opacity: .85;
}
.btn-secondary .btn-hotkey,
.btn:not(.btn-primary):not(.btn-danger):not(.btn-success) .btn-hotkey {
  border-color: var(--border-color); color: var(--text-muted);
}

/* ===== CARDS ===== */
.card {
  background: var(--bg-card); border: 1px solid var(--border-color);
  border-radius: var(--radius-lg); padding: 15px; box-shadow: var(--shadow-sm);
  margin-bottom: 18px;
}
.card-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 14px; gap: 10px;
}
.card-title { font-size: 15px; font-weight: 700; color: var(--text-heading); margin: 0; }
/* Regel onder een kaarttitel die zegt wat er in de kaart staat. Identiek aan de
   PMS-definitie — dezelfde kaart hoort in beide apps hetzelfde te lezen. */
.card-subtitle { font-size: 13px; color: var(--text-secondary); margin-top: 2px; }

/* ===== FORMS ===== */
.form-control, .form-input, .form-select, textarea.form-control {
  width: 100%; padding: 9px 13px; border: 1px solid var(--border-input);
  border-radius: var(--radius-md); background: var(--bg-input);
  color: var(--text-primary); font-size: 14px; line-height: 1.5; font-family: inherit;
  transition: border-color .15s, box-shadow .15s;
}
.form-control:focus, .form-input:focus, .form-select:focus {
  outline: none; border-color: var(--border-focus);
  box-shadow: 0 0 0 3px rgba(24,153,255,.12);
}
.form-control.is-invalid { border-color: var(--color-danger); }
.form-control[readonly] { background: var(--bg-table-header); color: var(--text-muted); cursor: not-allowed; }
.form-label { display: block; font-size: 12.5px; font-weight: 600; color: var(--text-secondary); margin-bottom: 6px; }
.form-label .required { color: var(--color-danger); }
.form-group { margin-bottom: 18px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.form-row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; }
@media (max-width: 640px) { .form-row, .form-row-3 { grid-template-columns: 1fr; } }
.form-select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%234A6070' stroke-width='1.6' fill='none' fill-rule='evenodd'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center; padding-right: 34px;
}
.zoek-wrap { position: relative; max-width: 340px; }
.zoek-wrap input { padding-left: 34px; }
.zoek-wrap::before {
  content: ''; position: absolute; left: 11px; top: 50%; width: 15px; height: 15px;
  transform: translateY(-50%);
  background: var(--text-muted);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M10 4a6 6 0 104.47 10.03l4.75 4.75a1 1 0 001.42-1.42l-4.75-4.75A6 6 0 0010 4zm-4 6a4 4 0 118 0 4 4 0 01-8 0z'/%3E%3C/svg%3E") center/contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M10 4a6 6 0 104.47 10.03l4.75 4.75a1 1 0 001.42-1.42l-4.75-4.75A6 6 0 0010 4zm-4 6a4 4 0 118 0 4 4 0 01-8 0z'/%3E%3C/svg%3E") center/contain no-repeat;
}

/* ===== TABLES ===== */
table.data-table { width: 100%; border-collapse: collapse; margin: 12px 0 0 0; }
.data-table thead th {
  background: var(--bg-table-header); padding: 10px 16px;
  font-size: 11.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--text-secondary);
  border-bottom: 1px solid var(--border-color); text-align: left;
}
.data-table tbody td { padding: 13px 16px; border-bottom: 1px solid var(--border-color); font-size: 13.5px; }
.data-table tbody tr:hover td { background: var(--bg-table-row-hover); }
.data-table tbody tr.is-clickable { cursor: pointer; }
.data-table tbody tr.is-inactief td { opacity: .55; }

/* ── Sorteerbare kolomkoppen (.data-table[data-sorteerbaar] th[data-sort]) ──
   De pijl staat er ALTIJD, ook ongesorteerd: een kop die pas bij hover laat
   zien dat hij klikbaar is, vindt niemand die er niet overheen gaat. Bleek
   grijs tot je sorteert, dan in de tekstkleur en één kant op.

   `is-sorteerbaar` en de tabindex komen van initTabelSorteren() in js/app.js;
   de richting leest uit `aria-sort`, zodat de schermlezer en de pijl niet uit
   elkaar kunnen lopen. */
.data-table thead th.is-sorteerbaar {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: color .15s;
}
.data-table thead th.is-sorteerbaar:hover { color: var(--text-primary); }
.data-table thead th.is-sorteerbaar:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--border-focus);
}
.data-table thead th.is-sorteerbaar::after {
  content: "";
  display: inline-block;
  width: 0; height: 0;
  margin-left: 6px;
  vertical-align: middle;
  /* Dubbel driehoekje kan niet met één ::after; ongesorteerd tonen we daarom
     een neutraal ruitje en pas bij sorteren een echte pijl. */
  border: 3px solid transparent;
  border-top-color: currentColor;
  border-bottom-width: 0;
  opacity: .3;
  transition: opacity .15s, transform .15s;
}
.data-table thead th.is-gesorteerd { color: var(--color-primary); }
.data-table thead th.is-gesorteerd::after { opacity: 1; }
.data-table thead th[aria-sort="ascending"]::after { transform: rotate(180deg); }

/* ── Page toolbar — gedeelde filterbalk layout (zie PMS ?page=orderoverzicht) ── */
.page-toolbar {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
}
.toolbar-search {
  position: relative;
  width: 320px;
  flex-shrink: 0;
}
.toolbar-search > svg {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  opacity: .45;
}
.toolbar-search .form-control {
  padding-top: 5px;
  padding-bottom: 5px;
  padding-left: 32px;
}

/* ── Lijstpagina-patroon: card met icoon + naam boven een data-table
   (zie PMS .order-card-head / ?page=klanten). Standaard voor elke nieuwe
   overzichtspagina: zoekbalk-toolbar in een aparte card erboven, dan deze
   card met de tabel. Zie OMS/CLAUDE.md voor de volledige conventie. ── */
.table-card { padding: 0; overflow: hidden; }
.table-card-head {
  padding: 15px 15px 0;
  border-bottom: 1px solid var(--border-color);
}
.table-card-head h3 {
  margin: 0 0 12px;
  font-size: .95rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}
.table-card .data-table { margin: 0; }

/* ── Kop van de table-card ALS filterbalk: zoekvak links, acties rechts ──
   Vervangt de losse toolbar-card die boven de tabel stond — die kostte een hele
   card-hoogte voor één zoekveld, en de h3 eronder herhaalde alleen de paginanaam
   die de sidebar al aanwijst. Zet `table-card-toolbar` ERBIJ op `.table-card-head`
   en laat de h3 weg; een TWEEDE tabel op dezelfde pagina houdt zijn gewone kop
   mét titel, anders is niet te zien welke tabel welke is.

   Alles wat rechts hoort (primaire knop, snelfilters, tellers) gaat in
   `.table-card-acties` — dat is de enige plek met `margin-left: auto`. */
.table-card-head.table-card-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 15px;
}
.table-card-toolbar .toolbar-search { flex-shrink: 1; min-width: 200px; }
.table-card-acties {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-left: auto;
}

/* ── Filterknop met uitklappaneel ──
   Voor lijstpagina's met méér filters dan er in de kop passen (?page=events,
   ?page=activiteitenlog): alles achter één knop, met het aantal actieve filters
   als badge zodat een aanstaand filter niet onzichtbaar de tabel bijknipt.
   Het paneel gaat op `display: none` — de datumkiezer hangt zijn kalender aan
   <body> en positioneert bij het openen, dus verborgen initialiseren kan. */
/* `.table-card` staat op `overflow: hidden` (voor de afgeronde hoeken van de
   tabel); zonder deze uitzondering wordt het paneel bij een korte tabel onderaan
   afgeknipt. Veilig omdat de kop en de paginatiebalk gewone divs zijn — er is
   daar geen tabelhoek die buiten de radius zou steken. */
.table-card:has(.filter-paneel) { overflow: visible; }
.filter-knop-wrap { position: relative; }
.filter-knop-wrap > .btn { display: inline-flex; align-items: center; gap: 6px; }
.filter-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 9px; background: var(--color-primary); color: #fff;
  font-size: 11px; font-weight: 600; line-height: 1;
}
.filter-badge[hidden] { display: none; }
.filter-paneel {
  display: none; position: absolute; top: calc(100% + 6px); right: 0; z-index: 210;
  width: 320px; padding: 14px; text-align: left;
  background: var(--bg-card); border: 1px solid var(--border-input);
  border-radius: var(--radius-md); box-shadow: 0 8px 24px rgba(0,0,0,.14);
}
.filter-knop-wrap.open .filter-paneel { display: block; }
.filter-paneel-groep + .filter-paneel-groep { margin-top: 12px; }
.filter-paneel-label {
  display: block; margin-bottom: 6px;
  font-size: 12px; font-weight: 600; color: var(--text-muted);
}
.filter-paneel-2kol { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.filter-paneel-voet {
  display: flex; justify-content: flex-end;
  margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--border-color);
}

/* ===== MODALS ===== */
/* Vergrendelt de pagina erachter zodra een modal open is — anders scrollt de
   body onder de (fixed) overlay mee door als er over de overlay gescrold
   wordt buiten de .modal zelf, wat de scrollpositie ongemerkt verspringt. */
body.modal-open { overflow: hidden; }
.modal-overlay {
  position: fixed; inset: 0; background: var(--bg-overlay); z-index: 100;
  display: flex; align-items: center; justify-content: center; padding: 16px;
  opacity: 0; pointer-events: none; transition: opacity .2s ease;
}
.modal-overlay.open { opacity: 1; pointer-events: all; }
.modal {
  background: var(--bg-modal); border-radius: var(--radius-xl); padding: 26px;
  max-width: 580px; width: 100%; max-height: 88vh; overflow-y: auto;
  box-shadow: var(--shadow-modal); border: 1px solid var(--border-color);
  transform: translateY(16px) scale(.99);
  transition: transform .22s cubic-bezier(.34,1.56,.64,1);
}
.modal-overlay.open .modal { transform: translateY(0) scale(1); }
.modal-lg { max-width: 760px; } .modal-890 { max-width: 890px; }
.modal-xl { max-width: 960px; } .modal-xxl { max-width: 1280px; } .modal-xxxl { max-width: 1440px; }
.modal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
.modal-header h3 { margin: 0; font-size: 17px; font-weight: 700; color: var(--text-heading); }
.modal-close { background: none; border: none; cursor: pointer; color: var(--text-muted); font-size: 20px; line-height: 1; padding: 4px; }
.modal-footer { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }

/* ===== Keuzetegels (.keuze-tegels / .keuze-tegel) =====
   Eén-uit-meer als tegels onder elkaar, met per optie ruimte voor een icoon en
   een regel uitleg. Bewust géén .kn-seg (die is compact en heeft geen plek voor
   uitleg) en geen kale radio's: waar de opties niet vanzelf spreken — "bewerker",
   "tampondruk" — moet de toelichting meelezen.

   De aan-stand zit in `aria-pressed` op de knop, niet in een klasse: de tegel
   ís een toggle, en dan hoort de schermlezer dat ook te horen. Wie de tegels
   vult regelt zelf welke er aan staat.

   Icoon en uitleg zijn OPTIONEEL — laat het element gewoon weg. Het vinkrondje
   hoort er wel altijd bij: een tegel zónder leest als een knop.

   Staat hier en niet bij een pagina: gebruikt door de rolkeuze op
   ?page=leveranciers en de typekeuze in de bewerkingen-modal (order-detail +
   klantenkaart). Wijzig je iets, kijk dan naar alle drie. */
.keuze-tegels { display: grid; gap: 8px; }
.keuze-tegel {
    display: flex; align-items: center; gap: 11px;
    width: 100%; padding: 9px 12px;
    border: 1px solid var(--border-input);
    background: var(--bg-input);
    border-radius: var(--radius-md);
    font: inherit; text-align: left; cursor: pointer;
    transition: border-color .15s, background .15s;
}
.keuze-tegel:hover { border-color: var(--color-primary); }
.keuze-tegel:focus-visible {
    outline: none; border-color: var(--border-focus);
    box-shadow: 0 0 0 3px rgba(24, 153, 255, .12);
}
.keuze-tegel-icoon {
    flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
    width: 30px; height: 30px;
    border-radius: var(--radius-md);
    background: var(--bg-subtle);
    color: var(--text-muted);
    transition: background .15s, color .15s;
}
.keuze-tegel-tekst { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.keuze-tegel-label { font-size: 13.5px; font-weight: 600; color: var(--text-primary); }
.keuze-tegel-uitleg { font-size: 11.5px; color: var(--text-muted); }
/* Leeg keuzerondje zolang de tegel uit staat. ROND en niet vierkant — dit is
   één-uit-meer, en een vierkant vinkvakje belooft dat je er meerdere kunt
   aanzetten. */
.keuze-tegel-vink {
    flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    width: 18px; height: 18px;
    border: 1px solid var(--border-input); border-radius: 50%;
    background: var(--bg-input);
    color: #fff;
    transition: background .15s, border-color .15s;
}
.keuze-tegel-vink svg { opacity: 0; transition: opacity .12s; }
.keuze-tegel[aria-pressed="true"] {
    border-color: var(--color-primary);
    background: rgba(24, 153, 255, .08);
}
.keuze-tegel[aria-pressed="true"] .keuze-tegel-icoon {
    background: rgba(24, 153, 255, .16); color: var(--color-primary);
}
.keuze-tegel[aria-pressed="true"] .keuze-tegel-vink {
    background: var(--color-primary); border-color: var(--color-primary);
}
.keuze-tegel[aria-pressed="true"] .keuze-tegel-vink svg { opacity: 1; }

/* ===== Aanvinkbare regel (.vink-optie / .vink-vink) =====
   MEERKEUZE, en daarmee de tegenhanger van .keuze-tegel hierboven. Het verschil
   zit in het vakje: dit is VIERKANT omdat je er meerdere kunt aanzetten, waar het
   ronde keuzerondje van .keuze-tegel belooft dat je er precies één kiest. Dat
   onderscheid is de hele reden dat beide vormen bestaan — houd het intact.

   De aan-stand zit in `aria-pressed` op de knop, net als bij .keuze-tegel: het is
   een toggle, en dan hoort een schermlezer dat ook te horen. Een <button> en geen
   <input type="checkbox">: deze regels worden uit een <template> gekloond of door
   JS opgebouwd, en checkboxes zouden per kaart een unieke `name` nodig hebben.

   Staat hier en niet bij een pagina: gedeeld door het technieken-aanbod op
   ?page=leveranciers en de artikelenkeuze in de bewerkingen-modal op
   ?page=order-detail. Wijzig je iets, kijk dan naar allebei. Wat per scherm
   verschilt (de kolomindeling van de lijst, een foutrand eromheen) hoort in de
   pagina-CSS, niet hier. */
.vink-optie {
    display: flex; align-items: center; gap: 8px;
    width: 100%; padding: 6px 7px;
    border: none; border-radius: var(--radius-sm);
    background: none; font: inherit; font-size: 12.5px; text-align: left;
    color: var(--text-primary); cursor: pointer;
}
.vink-optie:hover { background: var(--bg-card-hover); }
.vink-optie:focus-visible {
    outline: none; box-shadow: 0 0 0 2px rgba(24, 153, 255, .25);
}
.vink-optie[disabled] { cursor: default; opacity: .55; }
.vink-optie[disabled]:hover { background: none; }
.vink-vink {
    flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    width: 16px; height: 16px;
    border: 1px solid var(--border-input); border-radius: var(--radius-sm);
    background: var(--bg-card);
    color: #fff;
    transition: background .15s, border-color .15s;
}
.vink-vink svg { opacity: 0; transition: opacity .12s; }
.vink-optie[aria-pressed="true"] .vink-vink {
    background: var(--color-primary); border-color: var(--color-primary);
}
.vink-optie[aria-pressed="true"] .vink-vink svg { opacity: 1; }

/* ===== Segmented control (.kn-seg) =====
   Keuze uit 2+ opties als aaneengesloten tegels i.p.v. een select of losse
   radio's: beide opties blijven zichtbaar, dat scheelt een klik en leest
   sneller. Generiek hier (niet in klanten.css) omdat meerdere pagina's het
   delen: de bewerk-modals op ?page=klant-detail en ?page=order-detail, en de
   bestemming-velden uit js/levering-details.js (order-detail + inkomend-textiel). */
.kn-seg { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; }
/* Een verborgen tegel moet ook echt weg: `display: flex` hieronder wint anders van
   de `[hidden]`-regel uit de browser-stylesheet en dan blijft hij gewoon staan. */
.kn-seg-btn[hidden] { display: none; }
.kn-seg-btn {
    display: flex; align-items: center; justify-content: center; gap: 7px;
    padding: 9px 12px;
    border: 1px solid var(--border-input);
    background: var(--bg-input);
    border-radius: 0;
    font: inherit; font-size: 13.5px; font-weight: 600;
    color: var(--text-secondary); cursor: pointer;
    transition: border-color .15s, background .15s, color .15s;
}
.kn-seg-btn + .kn-seg-btn { border-left-width: 0; }
.kn-seg-btn:first-child { border-radius: var(--radius-md) 0 0 var(--radius-md); }
.kn-seg-btn:last-child  { border-radius: 0 var(--radius-md) var(--radius-md) 0; }
.kn-seg-btn:only-child  { border-radius: var(--radius-md); }
/* Een tegel kan verborgen zijn — "Vrijgeven" op ?page=voorraad verdwijnt als er
   niets gereserveerd staat. `:last-child` telt die gewoon mee, waardoor de rij
   rechts vierkant eindigt en de ronding op een onzichtbare knop zit. Deze regel
   legt hem op de laatste ZICHTBARE tegel: geen zichtbare tegel meer erna.
   Staat ná de regels hierboven, dus wint bij gelijke specificiteit.
   De LINKERkant blijft `:first-child` — vandaag wordt alleen aan het eind een
   tegel verborgen. Verberg je ooit de eerste, dan hoort hier de spiegelregel bij. */
.kn-seg-btn:not([hidden]):not(:has(~ .kn-seg-btn:not([hidden]))) {
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
}
/* Blijft er één tegel over, dan is het geen rij meer maar één knop. */
.kn-seg-btn:not([hidden]):first-child:not(:has(~ .kn-seg-btn:not([hidden]))) {
    border-radius: var(--radius-md);
}
/* Een actieve/gehoverde knop tekent zijn eigen linkerrand weer, anders valt de
   gekleurde rand aan die kant weg tegen de buurknop. */
.kn-seg-btn.is-active + .kn-seg-btn,
.kn-seg-btn:hover + .kn-seg-btn { border-left-width: 0; }
.kn-seg-btn.is-active, .kn-seg-btn:hover { position: relative; z-index: 1; }
.kn-seg-btn svg { flex-shrink: 0; opacity: .75; }
.kn-seg-btn:hover { border-color: var(--color-primary); color: var(--text-primary); }
.kn-seg-btn.is-active {
    border-color: var(--color-primary);
    background: rgba(24, 153, 255, .10);
    color: var(--color-primary);
}
.kn-seg-btn.is-active svg { opacity: 1; }
.kn-seg-btn:focus-visible { outline: none; border-color: var(--border-focus); box-shadow: 0 0 0 3px rgba(24, 153, 255, .12); }
.kn-seg-btn.is-disabled, .kn-seg-btn:disabled {
    opacity: .5; cursor: not-allowed;
    background: var(--bg-subtle); color: var(--text-muted);
}
.kn-seg-btn.is-disabled:hover, .kn-seg-btn:disabled:hover { border-color: var(--border-input); color: var(--text-muted); }

/* Variant voor meer opties dan er naast elkaar passen (5+ tegels in een halve
   modalkolom): de tegels wikkelen over meerdere rijen en staan los van elkaar.
   Aaneengesloten kan hier niet — de radius- en randregels hierboven gaan uit
   van één rij en laten bij het wikkelen kapotte hoeken achter. */
.kn-seg.kn-seg-rijen {
    grid-auto-flow: row;
    grid-template-columns: repeat(auto-fit, minmax(125px, 1fr));
    gap: 6px;
}
.kn-seg.kn-seg-rijen .kn-seg-btn {
    border-left-width: 1px;
    border-radius: var(--radius-md);
}
/* De twee "laatste zichtbare tegel"-regels hierboven zijn specifieker dan de
   regel hier direct boven — `:not()` telt zijn argument mee, dus ze wegen (0,4,0)
   en (0,5,0) tegen de (0,3,0) hiervan. In een gewikkelde rij sloegen ze daardoor
   alsnog aan en kreeg de laatste tegel `0 md md 0`: rechts rond, links vierkant.
   Zichtbaar bij "Zit in de inkoopprijs van het artikel" in de bewerkingen-modal.
   In deze variant staan de tegels los van elkaar, dus ze horen aan alle vier de
   hoeken rond te zijn — ongeacht welke de laatste is. */
.kn-seg.kn-seg-rijen .kn-seg-btn:not([hidden]):not(:has(~ .kn-seg-btn:not([hidden]))),
.kn-seg.kn-seg-rijen .kn-seg-btn:not([hidden]):first-child:not(:has(~ .kn-seg-btn:not([hidden]))) {
    border-radius: var(--radius-md);
}

/* ===== TOOLTIP + PULSE (js/tooltip.js) ===== */
/* Directe tooltip op elk element met data-tip; verschijnt zonder de ~1s
   vertraging van de native title. white-space:pre-line houdt een opsomming
   met \n intact. Poort van KMS' #kmsTip. */
#omsTip {
  position: fixed;
  background: #1e293b; color: #fff;
  font-size: 11px; font-weight: 500;
  padding: 5px 9px; border-radius: 4px;
  pointer-events: none; opacity: 0; transition: opacity .1s;
  z-index: 10000; white-space: pre-line; line-height: 1.5;
  max-width: 320px; box-shadow: 0 2px 8px rgba(0,0,0,.25);
}
/* Paneelvariant (data-tip-stijl="paneel"): dezelfde witte kaart als het
   rij-actiemenu (.row-dropdown). Voor een tooltip die een LIJSTJE toont — een
   donker labeltje met vijf regels erin leest als een foutmelding.
   Poort van #kmsTip.is-paneel in KMS. */
#omsTip.is-paneel {
  background: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg, 12px);
  box-shadow: 0 8px 32px rgba(0,0,0,.12), 0 2px 8px rgba(0,0,0,.06);
  padding: 10px 12px;
  font-size: 12.5px;
  white-space: normal;
  max-width: 280px;
}
.oms-tip-titel {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-muted);
  margin-bottom: 6px;
}
.oms-tip-regel {
  display: flex; align-items: baseline; gap: 6px;
  padding: 3px 0;
  color: var(--text-primary); line-height: 1.4;
  overflow-wrap: anywhere;
}
.oms-tip-regel + .oms-tip-regel { border-top: 1px solid var(--border-color); }

/* Pulserende "!" bij een aandachtspunt (ontbrekende gegevens) — poort van KMS' .kms-pulse. */
@keyframes omsPulse {
  0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(220,38,38,.55); }
  70%  { transform: scale(1.12); box-shadow: 0 0 0 7px rgba(220,38,38,0); }
  100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(220,38,38,0); }
}
.oms-pulse {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--color-danger); color: #fff;
  font-size: 11px; font-weight: 800; line-height: 1;
  flex-shrink: 0; cursor: help;
  animation: omsPulse 1.6s ease-out infinite;
}
/* display:inline-flex hierboven wint van het `hidden`-attribuut; zonder deze
   regel blijft een verborgen pulse gewoon staan. */
.oms-pulse[hidden] { display: none; }
/* Naast een waarde in een tabelcel of kaartkop i.p.v. in een flex-rij — zelfde
   uitlijning als .oms-pulse-geel, zodat de twee naast elkaar netjes staan. */
.oms-pulse-inline { vertical-align: middle; margin-left: 7px; }

/* Gele variant van .oms-pulse: zelfde formaat (18px rondje met wit icoon), maar
   geel en met het waarschuwingsdriehoekje in plaats van de "!". Vraagt aandacht
   zonder te alarmeren (rood). Gebruikt op ?page=orders om te tonen dat een order
   afwijkt van de verstuurde orderbevestiging. */
@keyframes omsPulseGeel {
  0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(245,158,11,.55); }
  70%  { transform: scale(1.12); box-shadow: 0 0 0 7px rgba(245,158,11,0); }
  100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(245,158,11,0); }
}
.oms-pulse-geel {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--color-warning); color: #fff;
  flex-shrink: 0; cursor: help;
  vertical-align: middle; margin-left: 7px;
  animation: omsPulseGeel 1.6s ease-out infinite;
}
.oms-pulse-geel svg { width: 11px; height: 11px; display: block; }

/* Blauwe variant: er ligt een BEOORDELING klaar. Bewust een derde kleur en niet
   de gele hergebruikt — geel zegt op ?page=orders al "wijkt af van de verstuurde
   orderbevestiging", en dat is iets anders dan "PMS wacht op je oordeel". Twee
   betekenissen op één kleur laat de gebruiker raden welke van de twee het is. */
@keyframes omsPulseBlauw {
  0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(14,165,233,.55); }
  70%  { transform: scale(1.12); box-shadow: 0 0 0 7px rgba(14,165,233,0); }
  100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(14,165,233,0); }
}
.oms-pulse-blauw {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%;
  background: #0EA5E9; color: #fff;
  flex-shrink: 0; cursor: help;
  vertical-align: middle; margin-left: 7px;
  animation: omsPulseBlauw 1.6s ease-out infinite;
}
.oms-pulse-blauw svg { width: 11px; height: 11px; display: block; }

/* Oranje variant: er wacht een BESLISSING (annuleerverzoek uit de webshop).
   Oranje = actie vereist, los van geel (afwijkend van de bevestiging). */
@keyframes omsPulseOranje {
  0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(249,115,22,.55); }
  70%  { transform: scale(1.12); box-shadow: 0 0 0 7px rgba(249,115,22,0); }
  100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(249,115,22,0); }
}
.oms-pulse-oranje {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--color-orange, #F97316); color: #fff;
  flex-shrink: 0; cursor: help;
  vertical-align: middle; margin-left: 7px;
  animation: omsPulseOranje 1.6s ease-out infinite;
}
.oms-pulse-oranje svg { width: 10px; height: 10px; display: block; }
/* Zelfde valkuil als .oms-pulse[hidden]: inline-flex wint anders van `hidden`. */
.oms-pulse-geel[hidden], .oms-pulse-blauw[hidden], .oms-pulse-oranje[hidden] { display: none; }

/* ===== BADGES & ALERTS ===== */
.badge {
  display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px;
  border-radius: var(--radius-full); font-size: 11.5px; font-weight: 700; white-space: nowrap;
}
.badge-blue { background: #DBEAFE; color: #1D4ED8; }
.badge-green { background: #D1FAE5; color: #065F46; }
.badge-yellow { background: #FEF3C7; color: #92400E; }
.badge-red { background: #FEE2E2; color: #991B1B; }
.badge-gray { background: #F1F5F9; color: #475569; }
[data-theme="dark-v2"] .badge-blue { background: rgba(30,58,138,.3); color: #bfdbfe; }
[data-theme="dark-v2"] .badge-green { background: rgba(6,95,70,.3); color: #a7f3d0; }
[data-theme="dark-v2"] .badge-yellow { background: rgba(120,53,15,.3); color: #fde68a; }
[data-theme="dark-v2"] .badge-red { background: rgba(159,18,57,.3); color: #fecdd3; }
[data-theme="dark-v2"] .badge-gray { background: rgba(255,255,255,.08); color: #cbd5e1; }
/* Paars, oranje en cyaan komen uit de loglijsten (?page=events): het
   orderverloop kent meer gradaties dan blauw/groen/geel/rood/grijs, en die
   kleuren moeten hier staan en niet in een pagina-eigen stylesheet — badges
   worden overal hergebruikt. */
.badge-purple { background: #EDE9FE; color: #5B21B6; }
.badge-orange { background: #FFEDD5; color: #9A3412; }
.badge-cyan   { background: #CFFAFE; color: #155E75; }
/* Passen (migratie 128). Roze en niet paars: dat laatste is de externe bewerking,
   en die twee staan op dezelfde schermen naast elkaar. */
.badge-pink   { background: #FCE7F3; color: #9D174D; }
[data-theme="dark-v2"] .badge-pink   { background: rgba(157,23,77,.35); color: #fbcfe8; }
[data-theme="dark-v2"] .badge-purple { background: rgba(76,29,149,.35); color: #ddd6fe; }
[data-theme="dark-v2"] .badge-orange { background: rgba(124,45,18,.35); color: #fed7aa; }
[data-theme="dark-v2"] .badge-cyan   { background: rgba(21,94,117,.35); color: #a5f3fc; }

/* Het ordernummer dat de LEVERANCIER aan een bestelling gaf (migratie 096).
   Monospace omdat het een code is die je overtypt of vergelijkt, niet iets wat
   je leest. Staat hier en niet in de pagina-eigen stylesheet van
   ?page=besteloverzicht: dezelfde badge hoort ook bij de bestelling op
   ?page=magazijn&tab=textiel-inboeken — daar herken je aan dit nummer welke
   pakbon bij welke rij hoort. De invoerknop, het veld en het potlood eromheen
   blijven wél lokaal: alleen op het besteloverzicht is het nummer te wijzigen. */
.bestel-lev-ordernr {
    font-family: 'Fira Code', monospace;
    font-size: 11.5px;
    font-weight: 500;
}

/* ===== SEGMENTED TOGGLE (.seg-toggle) =====
   Weergavekeuze binnen één scherm: de knoppen liggen als tabletjes in een
   grijze goot, de actieve licht als "kaartje" op. Anders dan .korting-switch
   (die een WAARDE kiest die je opslaat) en dan .dtf-tab-bar (die van inhoud
   wisselt): dit filtert alleen wat je van dezelfde inhoud ziet.
   Origineel uit dashboard.css (takentabs), nu generiek — ?page=order-detail
   gebruikt hem voor Eenvoudig/Uitgebreid in het orderverloop. De JS zet
   `.active`; hier staat alleen de opmaak. */
.seg-toggle {
  display: inline-flex;
  align-items: center;
  background: var(--bg-subtle);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-full);
  padding: 3px;
  gap: 2px;
}
.seg-toggle-btn {
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-size: 12.5px;
  font-weight: 600;
  font-family: inherit;
  padding: 5px 14px;
  border-radius: var(--radius-full);
  cursor: pointer;
  transition: var(--transition);
  line-height: 1.2;
}
.seg-toggle-btn:hover { color: var(--text-heading); }
.seg-toggle-btn.active {
  background: var(--bg-card);
  color: var(--text-heading);
  box-shadow: var(--shadow-sm);
}

/* ===== SEGMENTED SWITCH =====
   Generieke keuzeschakelaar (korting-type, order/offerte, ...): een rij knoppen
   waarvan er precies één `.active` is. De JS zet die class; hier staat alleen
   de opmaak. Origineel uit klantenkaart.css, nu generiek zodat elke pagina hem
   kan gebruiken zonder de regels te dupliceren. */
.korting-switch { display: flex; border: 1px solid var(--border-color); border-radius: var(--radius-md); overflow: hidden; margin-bottom: 8px; }
.korting-switch-btn {
    flex: 1; padding: 6px 4px; border: none; border-right: 1px solid var(--border-color);
    background: var(--bg-card); cursor: pointer; font-size: 12px; font-weight: 500;
    color: var(--text-secondary); transition: background .15s, color .15s; white-space: nowrap;
}
.korting-switch-btn:last-child { border-right: none; }
.korting-switch-btn:hover { background: var(--bg-subtle); }
.korting-switch-btn.active { background: var(--color-primary); color: #fff; font-weight: 600; }

.alert { padding: 13px 16px; border-radius: var(--radius-md); margin-bottom: 16px; font-size: 13.5px; display: flex; gap: 10px; border-left: 3px solid transparent; }
.alert-success { background: #D1FAE5; color: #065F46; border-left-color: var(--color-secondary); }
.alert-error { background: #FEE2E2; color: #991B1B; border-left-color: var(--color-danger); }
.alert-warning { background: #FEF3C7; color: #78350F; border-left-color: var(--color-warning); }
.alert-info { background: #CFFAFE; color: #155E75; border-left-color: var(--color-primary); }

/* ===== VELD-MELDINGEN (hint / suggestie / fout) ==============================
 * Eén set klassen voor alles wat onder een invoerveld verschijnt. Ontstaan als
 * .whi-hint/.whi-suggestie in de Webharvester-import op ?page=order-detail;
 * hier generiek gemaakt zodat elke plek waar het systeem iets vóórstelt of iets
 * mist er hetzelfde uitziet. Zet de melding met veldHint()/veldSuggestie()/
 * veldFout() uit js/app.js — niet met eigen innerHTML per pagina.
 *
 *   .veld-hint                  neutrale toelichting (grijs, geen kader)
 *   .veld-hint.is-fout          zelfde vorm, rode tekst (korte veldfout)
 *   .veld-hint.is-suggestie     AMBER kader: een gók van het systeem die de
 *                               gebruiker moet nakijken — bewust niet groen,
 *                               want groen leest als "bevestigd"
 *   .veld-hint.is-foutmelding   RODE kader: dezelfde vorm voor wat ontbreekt of
 *                               misging en waar de gebruiker iets aan moet doen
 * ------------------------------------------------------------------------- */
.veld-hint { font-size: 12px; color: var(--text-muted); margin-top: 5px; min-height: 1px; }
.veld-hint.is-fout { color: var(--color-danger, #c0392b); }

.veld-hint.is-suggestie,
.veld-hint.is-foutmelding {
  position: relative;
  margin-top: 6px;
  padding: 7px 26px 7px 9px;
  font-size: 12px; line-height: 1.5;
  color: var(--text-primary);
  border-radius: var(--radius-md, 6px);
}
.veld-hint.is-suggestie {
  background: rgba(245, 158, 11, .12);
  border: 1px solid rgba(245, 158, 11, .40);
}
/* Geen sluitknop op een foutmelding → geen ruimte rechts reserveren. */
.veld-hint.is-foutmelding {
  padding-right: 9px;
  background: rgba(192, 57, 43, .10);
  border: 1px solid rgba(192, 57, 43, .38);
}
.veld-hint .vh-naam { font-weight: 700; }
.veld-hint .vh-hint { color: var(--text-muted); }
.veld-hint .vh-sluit {
  position: absolute; top: 4px; right: 4px;
  display: flex; align-items: center; justify-content: center;
  padding: 2px; border: none; background: none; cursor: pointer;
  color: var(--text-muted); border-radius: var(--radius-sm, 4px);
}
.veld-hint .vh-sluit:hover { color: var(--text-primary); background: rgba(0, 0, 0, .06); }

/* Rode outline om een verplicht veld dat leeg is. Werkt op de gewone inputs, op
   de toggle van een zoekbare select (die draagt de rand) en op het kleurgrid van
   de import. Zetten/wissen via veldMarkeer() in js/app.js. De losse kleurkiezer
   heeft hier zijn eigen .is-invalid voor — zie js/kleur-picker.js. */
.form-control.veld-mis,
.artikel-dropdown-toggle.veld-mis,
.kleur-sel-grid.veld-mis {
  border-color: var(--color-danger, #c0392b);
  box-shadow: 0 0 0 3px rgba(192, 57, 43, .12);
}
/* Dezelfde outline als je veldMarkeer() op de WRAPPER van een zoekbare select
   zet i.p.v. op de toggle. Dat is vaak het enige element met een id (de toggle
   zelf heeft er geen), en het scheelt per aanroep een querySelector. */
.artikel-dropdown.veld-mis .artikel-dropdown-toggle {
  border-color: var(--color-danger, #c0392b);
  box-shadow: 0 0 0 3px rgba(192, 57, 43, .12);
}
/* Een segmented control heeft zelf geen rand — die zit op de knoppen. De outline
   moet dus om de hele groep heen, anders krijgt elke tegel een eigen rode rand en
   leest het als drie fouten in plaats van één onbeantwoorde vraag. */
.kn-seg.veld-mis {
  border-radius: var(--radius-md);
  box-shadow: 0 0 0 3px rgba(192, 57, 43, .12);
  outline: 1px solid var(--color-danger, #c0392b);
}

/* Verplicht-sterretje in een label. Ook buiten .form-label: een segmented control
   staat soms achter een gewone <span> als opschrift. */
.form-label .veld-verplicht,
.veld-verplicht { color: var(--color-danger, #c0392b); }

/* ===== TOAST (omsToast() in js/app.js) ======================================
 * Korte bevestiging rechtsonder voor acties waarbij verder niets zichtbaar
 * verandert. Meldingen stapelen van onder naar boven.
 * ------------------------------------------------------------------------- */
.oms-toast-host {
  position: fixed; right: 16px; bottom: 16px; z-index: 10000;
  display: flex; flex-direction: column-reverse; gap: 8px;
  pointer-events: none;
}
.oms-toast {
  max-width: 340px;
  padding: 10px 14px;
  border-radius: var(--radius-md, 8px);
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-left: 3px solid var(--color-secondary, #10b981);
  box-shadow: 0 8px 28px rgba(0, 0, 0, .14);
  font-size: 13px; color: var(--text-primary);
  animation: omsToastIn .18s ease;
  transition: opacity .25s ease, transform .25s ease;
}
.oms-toast.is-fout { border-left-color: var(--color-danger, #c0392b); }
.oms-toast.is-weg { opacity: 0; transform: translateY(6px); }
@keyframes omsToastIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ===== RIJ-ACTIEMENU (3 puntjes + dropdown) ==================================
 * Port van KMS' .kms-row-menu / .kms-dropdown (?p=admin-producten). Eén knop per
 * tabelrij die een gedeeld dropdown-paneel opent; het paneel staat ÉÉN keer op de
 * pagina, buiten de tabel, en wordt bij het openen naar de knop toe gepositioneerd.
 *
 * `position: fixed` is daarvoor nodig: een absoluut gepositioneerd paneel binnen
 * een `overflow`-scrollende tabel wordt afgeknipt. Openen/sluiten via
 * rowMenuOpen()/rowMenuHide() in js/app.js.
 * ------------------------------------------------------------------------- */
.row-menu-btn {
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm, 4px);
  width: 30px; height: 30px; padding: 0;
  cursor: pointer;
  color: var(--text-muted);
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .15s, color .15s;
  flex-shrink: 0;
}
.row-menu-btn:hover, .row-menu-btn.is-open {
  background: var(--bg-subtle);
  color: var(--text-primary);
}
.row-menu-dots { display: flex; gap: 3px; align-items: center; }
.row-menu-dots span { width: 4px; height: 4px; border-radius: 50%; background: currentColor; display: block; }

.row-dropdown {
  position: fixed;
  z-index: 9999;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg, 12px);
  box-shadow: 0 8px 32px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06);
  min-width: 220px;
  padding: 6px;
  animation: rowDropIn .12s ease;
}
@keyframes rowDropIn {
  from { opacity: 0; transform: translateY(-6px) scale(.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.row-dropdown-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px;
  border-radius: var(--radius-md, 8px);
  font-size: 13.5px;
  cursor: pointer;
  color: var(--text-primary);
  transition: background .1s;
  user-select: none;
  white-space: nowrap;
}
.row-dropdown-item:hover { background: var(--bg-card-hover); }
.row-dropdown-item svg { flex-shrink: 0; opacity: .65; }
/* Een item mag ook een link zijn (bijv. "naar de klantenkaart"): dan hoort hij er
   hetzelfde uit te zien als de klikbare divs ernaast, zonder onderstreping. */
a.row-dropdown-item { text-decoration: none; }
a.row-dropdown-item:hover { text-decoration: none; color: var(--text-primary); }
/* Of een <button> (het gebruikersmenu in de sidebar, het actiemenu op
   ?page=werkplekken). Zonder deze regel houdt hij zijn browser-eigen rand,
   achtergrond, lettertype én `width: auto` — dan staat er een echte knop in het
   paneel in plaats van een menuregel. */
button.row-dropdown-item {
  width: 100%;
  background: none;
  border: 0;
  font: inherit;
  font-size: 13.5px;
  text-align: left;
}
/* Uitgeschakeld item — blijft staan met zijn title als uitleg waarom het niet kan. */
.row-dropdown-item.is-disabled {
  color: var(--text-muted);
  cursor: default;
  opacity: .6;
}
.row-dropdown-item.is-disabled:hover { background: transparent; }
.row-dropdown-divider { height: 1px; background: var(--border-color); margin: 4px 0; }
/* Een INSTELLING in een actiemenu: dezelfde ruimte en hoverstand als een item,
   maar met een schakelaar in plaats van een handeling. Hij sluit het menu niet —
   je moet hem zien omgaan — en de hele regel is aanklikbaar omdat het een <label>
   om de checkbox is. Alleen gebruiken ónder een `.row-dropdown-divider`: een
   stand die blijft staan hoort niet tussen acties die eenmalig iets doen. */
/* Specifieker dan `.oms-switch` moet niet nodig lijken maar is het wél: die klasse
   staat verderop in dit bestand en zou met gelijke specificiteit winnen, waarna de
   regel terugvalt op `inline-flex` en niet de volle menubreedte pakt. */
.row-dropdown .row-dropdown-schakelaar {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px;
  border-radius: var(--radius-md, 8px);
  cursor: pointer;
  transition: background .1s;
  white-space: nowrap;
}
.row-dropdown-schakelaar:hover { background: var(--bg-card-hover); }
/* Het label staat links en duwt de schakelaar naar de rechterrand: in een menu
   lees je eerst wát er te kiezen valt, de stand staat op de plek waar je hem
   aanklikt. `margin-right: auto` en niet `justify-content: space-between` — de
   verborgen <input> telt als flex-item en zou dan een gat in het midden maken. */
.row-dropdown-schakelaar .oms-switch-label {
  font-size: 13.5px;
  color: var(--text-primary);
  margin-right: auto;
}
/* Twee ingangen halen hun artikelen ergens anders vandaan dan de eigen
   artikelenlijst; die krijgen daarom een eigen kleur — icoon én label, zodat je
   ze in het menu meteen uit elkaar houdt. De :hover-regel voor links staat
   hierboven en zet de kleur terug op --text-primary; vandaar dat de a-variant
   hier apart genoemd wordt. */
.row-dropdown-item.is-productdata,
a.row-dropdown-item.is-productdata:hover  { color: var(--color-primary, #1899FF); }
.row-dropdown-item.is-klantenkaart,
a.row-dropdown-item.is-klantenkaart:hover { color: var(--color-warning, #F59E0B); }
/* Aangeleverd textiel (migratie 071) is de derde herkomst in dat rijtje: niet
   de eigen catalogus, niet ProductData, maar de klant zelf. Violet en geen
   bestaande statuskleur: primary-blauw is ProductData, warning-amber is de
   klantenkaart en groen is al de voorraadtag op ?page=textiel-inboeken. Dezelfde
   tint keert terug op de orderregel en op de inboeklijst. */
.row-dropdown-item.is-aangeleverd,
a.row-dropdown-item.is-aangeleverd:hover { color: #7C3AED; }
[data-theme="dark-v2"] .row-dropdown-item.is-aangeleverd,
[data-theme="dark-v2"] a.row-dropdown-item.is-aangeleverd:hover { color: #A78BFA; }
.row-dropdown-item.is-productdata svg,
.row-dropdown-item.is-klantenkaart svg,
.row-dropdown-item.is-aangeleverd svg { opacity: 1; }
.row-dropdown-danger { color: var(--color-danger, #c0392b); }
.row-dropdown-danger svg { opacity: 1; color: var(--color-danger, #c0392b); }
/* De tegenhanger van .row-dropdown-danger: het item dat de gewenste afloop is.
   Gebruik hem hooguit één keer per menu — groen werkt alleen als aanwijzing
   zolang het de enige gekleurde uitweg naar voren is. Nu op "Converteren naar
   order" in het header-actiemenu van een offerte, tegenover het rode "Offerte
   archiveren" onderaan datzelfde menu. */
.row-dropdown-item.is-succes { color: var(--color-success, #22C55E); }
.row-dropdown-item.is-succes svg { opacity: 1; color: var(--color-success, #22C55E); }

/* ===== KLIK-EN-HOUD-VAST (initHoldActie in js/app.js) =====
   De balk loopt achter de inhoud langs en kleurt mee met de knop
   (currentColor), zodat dezelfde klasse op een rode én een neutrale knop
   werkt. touch-action: none houdt het vasthouden op mobiel bij de knop i.p.v.
   dat het als scroll wordt opgevat. */
.hold-knop {
  position: relative;
  overflow: hidden;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}
.hold-knop > * { position: relative; z-index: 1; }
.hold-vulling {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  z-index: 0;
  width: 0;
  background: currentColor;
  opacity: .18;
  border-radius: inherit;
  pointer-events: none;
  transition: width 140ms linear;
}
.hold-knop.is-bezig { background: color-mix(in srgb, currentColor 8%, transparent); }
.hold-hint {
  margin-left: auto;
  padding-left: 10px;
  font-size: 11.5px;
  opacity: .7;
  white-space: nowrap;
}
/* Bewust géén prefers-reduced-motion-uitzondering: de balk is geen versiering
   maar de voortgang zelf — zonder animatie staat hij meteen vol terwijl de
   actie nog niet is bevestigd. */

/* ===== EMPTY STATE ===== */
.empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 80px 20px; text-align: center; color: var(--text-muted);
}
.empty-state svg { opacity: .4; margin-bottom: 16px; }
.empty-state h3 { font-size: 16px; font-weight: 700; color: var(--text-secondary); margin: 0 0 6px; }
.empty-state p { font-size: 13.5px; margin: 0; max-width: 360px; }

/* ===== LOGIN ===== */
/* De publieke schermen (inloggen, activeren, wachtwoord vergeten, vergrendeld)
   VULLEN het venster en scrollen NIET. Het is één kaart met één handeling; een
   pagina die meeschuift laat de kaart half onder de vouw beginnen en zet de
   geanimeerde achtergrond in beweging bij elke scroll.
   Past de kaart niet op een laag scherm, dan scrollt zijn eigen formulierkolom
   (.login-right) — niet de pagina eromheen.
   100dvh ná 100vh: op mobiel telt 100vh de in-/uitschuivende URL-balk niet mee
   en zou er alsnog een strook buiten beeld vallen. Oudere browsers houden de
   100vh-regel. */
body.login-body {
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-page); padding: 20px;
}
/* Zweeft boven de geanimeerde login-achtergrond: transparant is daar
   onzichtbaar, dus eigen glas-achtergrond + duidelijke rand in beide thema's. */
.theme-toggle-fixed {
  position: fixed; top: 20px; right: 20px; z-index: 20;
  width: 42px; height: 42px;
  background: rgba(255, 255, 255, 0.75);
  border-color: rgba(15, 23, 42, 0.14);
  color: var(--text-primary);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: 0 2px 10px rgba(15, 23, 42, 0.14);
}
.theme-toggle-fixed:hover {
  background: rgba(255, 255, 255, 0.92);
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.theme-toggle-fixed svg { width: 18px; height: 18px; }
[data-theme="dark-v2"] .theme-toggle-fixed {
  background: rgba(255, 255, 255, 0.10);
  border-color: rgba(255, 255, 255, 0.24);
  color: #F0F0F2;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
}
[data-theme="dark-v2"] .theme-toggle-fixed:hover {
  background: rgba(255, 255, 255, 0.18);
  border-color: rgba(24, 153, 255, 0.9);
  color: #FFFFFF;
}
.login-card {
  display: flex; width: 100%; max-width: 900px;
  /* min() en geen kale 520px: op een laag venster zou die ondergrens de kaart
     buiten het scherm duwen — precies de scroll die hier niet hoort te zijn. */
  min-height: min(520px, 100%);
  max-height: 100%;
  background: var(--bg-card); border-radius: var(--radius-xl); overflow: hidden;
  box-shadow: var(--shadow-lg); border: 1px solid var(--border-color);
}
.login-left {
  flex: 1; background: linear-gradient(160deg, var(--color-primary-dark), var(--color-primary));
  color: #fff; padding: 48px 40px; display: flex; flex-direction: column; justify-content: space-between;
}
.login-left h1 { font-size: 26px; font-weight: 700; margin: 0 0 12px; }
.login-left p { font-size: 14px; opacity: .9; margin: 0 0 24px; }
.login-feature-list { list-style: none; padding: 0; margin: 0; }
.login-feature-list li { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; font-size: 13.5px; opacity: .95; }
/* min-height/min-width 0: zonder die twee weigert een flex-kind te krimpen en
   loopt het buiten de kaart door in plaats van te scrollen. */
.login-right {
  flex: 1; min-width: 0; min-height: 0; overflow-y: auto;
  padding: 48px 44px; display: flex; flex-direction: column; justify-content: center;
}
.login-right h2 { font-size: 20px; font-weight: 700; margin: 0 0 6px; color: var(--text-heading); }
.login-right .sub { color: var(--text-secondary); font-size: 13.5px; margin: 0 0 26px; }
@media (max-width: 720px) { .login-card { flex-direction: column; } .login-left { display: none; } }

/* ===== SETTINGS ===== */
.settings-layout {
  display: flex; gap: 24px; align-items: flex-start;
  min-height: calc(100vh - var(--header-height) - 24px - var(--dev-bar-offset, 0px));
}
.settings-sidenav {
  width: 220px; flex-shrink: 0; background: var(--bg-sidebar);
  border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-sm); align-self: stretch;
  /* Zonder deze regel plakt het laatste item tegen de rand van het paneel. */
  padding-bottom: 10px;
}
.settings-sidenav-title {
  /* Kleinere padding-bottom dan links/rechts: de scheidingslijn eronder brengt
     zelf al 7px marge mee. */
  display: flex; align-items: center; gap: 8px; padding: 16px 18px 5px;
  font-size: 15px; font-weight: 700; color: var(--text-heading);
}
.settings-sidenav-title svg { width: 19px; height: 19px; flex-shrink: 0; }

/* Maatvoering en kleur van de items komen van .nav-item / .nav-section-label
   bij de sidebar-nav bovenin — dit paneel gebruikt exact dezelfde vorm. */

/* Waarschuwingsbadge op een menu-item (bijv. e-mail nog niet vanaf eigen
   domein). Zelfde vorm als in PMS: amber driehoek, rechts uitgelijnd. */
.settings-sidenav .nav-item .nav-badge-alert {
  margin-left: auto;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  color: #f59e0b;
  background: none;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .18));
}
.settings-sidenav .nav-item .nav-badge-alert svg { width: 16px; height: 16px; display: block; }
.settings-content { flex: 1; min-width: 0; }
@media (max-width: 900px) { .settings-layout { flex-direction: column; min-height: 0; } .settings-sidenav { width: 100%; } }

/* ===== CONTACT ROWS (klant-detail) ===== */
.contact-row {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px; border: 1px solid var(--border-color); border-radius: var(--radius-md); margin-bottom: 8px;
}
.contact-row-line1, .contact-row-line2 { display: flex; gap: 10px; align-items: center; }
.contact-row-line1 > input, .contact-row-line2 > input { flex: 1; min-width: 0; }
@media (max-width: 800px) { .contact-row-line1 { flex-direction: column; align-items: stretch; } }

/* Tekstweergave (niet-bewerk-modus) van naam/telefoon/e-mail — zelfde ruimte als de inputs */
.contact-naam-text, .contact-tel-text, .contact-email-text {
  font-size: 13.5px; color: var(--text-primary);
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Vinkje ("Opslaan") en prullenbak ("Verwijderen") van een contactrij. Primair
   maken, Bewerken en Verwijderen van een OPGESLAGEN rij zitten achter de 3
   puntjes (.contact-acties-btn → #contactActiesMenu); de prullenbak hieronder
   is alleen nog die van een nieuwe, nog niet opgeslagen rij. */
/* Badge rechtsboven bij een primaire contactpersoon — gedeeld door de read-only
   kaart "Levering & contact" (.contact-lees-naam) en de rijen in de bewerk-modal
   (.contact-row-line1). Bewust niet absoluut gepositioneerd: in bewerk-modus
   vullen de invoervelden die regel en zou een overlay er bovenop komen. */
.contact-primair-badge { flex-shrink: 0; margin-left: auto; }
.contact-primair-badge svg { width: 11px; height: 11px; }
@media (max-width: 800px) {
  /* Regel 1 van een modalrij wordt hier een kolom (align-items: stretch) —
     zonder dit rekt de badge over de volle breedte uit. */
  .contact-row-line1 .contact-primair-badge { align-self: flex-end; margin-left: 0; }
}
.btn-opslaan-contact, .btn-annuleer-contact { flex-shrink: 0; white-space: nowrap; }
.btn-opslaan-contact svg { vertical-align: -2px; }
/* Bewerkstand: de rij leest als een formulier, niet als een gewone regel. De
   primair-badge wijkt dan; de velden hebben de hele breedte nodig. */
.contact-row.is-bewerken {
  border-color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 4%, var(--bg-card));
}
.contact-row.is-bewerken .contact-primair-badge { display: none; }
.btn-verwijder-contact {
  background: var(--color-danger); border-color: var(--color-danger); color: #fff; flex-shrink: 0;
}
.btn-verwijder-contact:hover { background: var(--color-danger-hover); }

/* Info grid (detail-overzicht rijen) — overgenomen van PMS css/style.css */
.info-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border-color);
}
/* `display: flex` wint van de browser-regel voor [hidden], dus een rij die met
   `el.hidden = true` verborgen wordt zou gewoon blijven staan. */
.info-row[hidden] { display: none; }
.info-row:last-child { border-bottom: none; }

.info-label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-secondary);
  min-width: 140px;
  flex-shrink: 0;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.info-value {
  font-size: 13.5px;
  color: var(--text-primary);
  flex: 1;
}

/* Meerdere regels binnen 1 info-value (bijv. naam/straat/postcode-plaats van een afleveradres). */
.info-value-pre { white-space: pre-line; }

/* ===== Adressuggesties (adresZoekVeld() + js/adres-zoek.js) =====
   De lijst hangt onder het zoekveld en overlapt het veld eronder, dus de wikkel
   moet de positioneercontext leveren. In een modal met een scrollende body
   schuift hij gewoon mee — hij zit ín die body. */
.adres-zoek { position: relative; }
/* Bij een buitenlands adres gaat het veld op `hidden`; een display-regel op
   .form-group wint anders van de browser-regel voor [hidden]. */
.adres-zoek[hidden] { display: none; }
.adres-suggesties {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 10;
  list-style: none; margin: 2px 0 0; padding: 4px;
  max-height: 220px; overflow-y: auto;
  background: var(--bg-card);
  border: 1px solid var(--border-color); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
}
.adres-suggesties li {
  padding: 6px 8px; font-size: 12.5px; border-radius: var(--radius-sm); cursor: pointer;
}
.adres-suggesties li:hover, .adres-suggesties li.is-actief { background: var(--bg-card-hover); }

/* ===== Kopieerknop (omsKopieer + de listener in js/app.js) =====
   Alleen een icoon; het vinkje vervangt het kopieer-icoon kort na een geslaagde
   kopie. Staat naast een waarde, dus flex-start: bij een adres over meerdere
   regels hoort hij op de eerste regel te blijven staan. */
.kopieer-btn {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0; align-self: flex-start;
  width: 26px; height: 26px; padding: 0;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: transparent; color: var(--text-muted); cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.kopieer-btn:hover { background: var(--bg-subtle); color: var(--text-primary); border-color: var(--border-color); }
.kopieer-btn .kopieer-icoon, .kopieer-btn .kopieer-vink { display: flex; }
.kopieer-btn .kopieer-vink { display: none; }
.kopieer-btn.is-gekopieerd { color: var(--color-secondary); }
.kopieer-btn.is-gekopieerd .kopieer-icoon { display: none; }
.kopieer-btn.is-gekopieerd .kopieer-vink { display: flex; }
/* Niets te kopiëren = geen knop. Via :empty i.p.v. een JS-toggle, zodat een
   waarde die door JS gevuld of geleegd wordt vanzelf goed staat. */
.info-value:empty + .kopieer-btn, .info-value-pre:empty + .kopieer-btn { display: none; }

/* Rechts uitgelijnde waarden voor specifieke detailkaarten (klant-detail) */
.card-values-right .info-value { text-align: right; }

/* ===== GEBRUIKER-AVATAR =====================================================
   Initialen in een gekleurd bolletje, eventueel met de naam ernaast. Gedeeld
   door de kolom "Gebruiker" op ?page=orders, de gekoppelde gebruiker op
   ?page=order-detail, het gebruikersmenu in de header en de gebruikerslijst van
   "Bekijken als". De kleur komt uit omsTegelKleur() (het user-id, niet de naam)
   en staat inline op het element — dezelfde acht kleuren als de tegels op het
   inlogscherm, zodat "de blauwe J" overal dezelfde persoon is.

   Zet hier GEEN vaste achtergrondkleur neer als terugval: een bolletje dat bij
   iedereen dezelfde kleur heeft breekt precies de belofte waar het voor bestaat.
   ------------------------------------------------------------------------- */
.gebruiker-cel {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.gebruiker-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px; height: 24px;
  border-radius: 50%;
  /* Wit op elk van de acht paletkleuren — die zijn allemaal donker genoeg. */
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .2px;
  line-height: 1;
  flex-shrink: 0;
}
.gebruiker-naam {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ===== UTILITIES ===== */
.text-sm { font-size: 12.5px; }
.text-muted { color: var(--text-muted); }
.text-secondary { color: var(--text-secondary); }
.text-success { color: var(--color-secondary); }
.text-danger { color: var(--color-danger); }
.font-bold { font-weight: 700; }
.font-medium { font-weight: 500; }
.text-right { text-align: right; }
.text-center { text-align: center; }
.save-status { font-size: 12px; color: var(--color-secondary); opacity: 0; transition: opacity .2s; }
.save-status.visible { opacity: 1; }

/* Toggle switch (schuif) — gemodelleerd naar PMS' .pms-switch */
.oms-switch { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; user-select: none; }
.oms-switch input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.oms-switch-track { position: relative; width: 38px; height: 21px; border-radius: 999px; background: var(--border-color); transition: background .2s; flex-shrink: 0; }
.oms-switch input:checked + .oms-switch-track { background: var(--color-primary); }
.oms-switch-thumb { position: absolute; top: 2px; left: 2px; width: 17px; height: 17px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.25); transition: transform .2s; }
.oms-switch input:checked + .oms-switch-track .oms-switch-thumb { transform: translateX(17px); }
.oms-switch input:focus-visible + .oms-switch-track { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.oms-switch-label { font-size: 13px; color: var(--text-secondary); line-height: 1.4; }

/* ===== RECHTEN-MODAL (#modalRechten, migratie 127) ===== */

/* Opent BOVENOP #modalBewerkGebruiker (overlay z-index 100). Zonder deze laag
   verdwijnt hij erachter — zelfde ingreep als bij #kleurPickerModal. */
#modalRechten { z-index: 1600; }

.rt-balk {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    margin: 0 0 20px;
    padding: 10px 12px;
    background: var(--bg-subtle);
    border-radius: var(--radius-md);
}
.rt-balk-acties { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }

/* Elke groep is een omkaderd blok met de kop erbuiten: zonder kader lopen de
   rijen van twee groepen in elkaar over en zegt de kop niet meer waar hij bij
   hoort. Daarom hier GEEN .kn-section (die zet alleen een lijn bovenaan). */
.rt-groep { margin-bottom: 18px; }
.rt-groep:last-of-type { margin-bottom: 0; }
.rt-groep-titel {
    margin: 0 0 8px;
    font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
    color: var(--text-secondary);
}
.rt-groep-body {
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.rt-pagina + .rt-pagina { border-top: 1px solid var(--border-color); }
.rt-pagina-kop {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px;
    transition: background .12s;
}
.rt-pagina-kop:hover { background: var(--bg-table-row-hover); }
.rt-naam { font-size: 13.5px; color: var(--text-primary); }
.rt-telling {
    font-size: 11px; color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    padding: 2px 7px;
    background: var(--bg-subtle);
    border-radius: var(--radius-full);
}
.rt-pagina-kop .oms-switch { margin-left: auto; }
.rt-pagina-hint { margin: -6px 0 10px 34px; padding-right: 12px; }

.rt-klap {
    width: 22px; height: 22px; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 0; background: none; color: var(--text-muted); cursor: pointer;
    border-radius: var(--radius-sm);
    transition: transform .15s, background .15s, color .15s;
}
.rt-klap:hover { background: var(--bg-card-hover); color: var(--text-primary); }
.rt-klap[aria-expanded="true"] { transform: rotate(90deg); }
/* Een pagina zonder sub-rechten houdt de ruimte van de chevron, anders staat
   zijn naam een halve centimeter links van de rest. */
.rt-klap.is-leeg { cursor: default; }

.rt-subs {
    padding: 4px 12px 12px 34px;
    display: flex; flex-direction: column; gap: 2px;
    background: var(--bg-subtle);
    border-top: 1px solid var(--border-color);
}
.rt-sub {
    align-items: flex-start;
    gap: 12px;
    padding: 7px 0;
}
.rt-sub + .rt-sub { border-top: 1px solid var(--border-color); }
.rt-sub .oms-switch-label { flex: 1; color: var(--text-primary); font-size: 13px; }
.rt-sub .oms-switch-label .kn-hint { display: block; margin-top: 2px; }
.rt-sub .oms-switch-track { margin-top: 2px; }

/* Een uitgezette pagina dimt zijn sub-schakelaars maar WIST ze niet: de waarde
   blijft staan en gaat gewoon mee in de payload, zodat de pagina weer aanzetten
   je eerdere keuze terugbrengt. De server AND't toch met de ouder. */
.rt-subs.is-uit { opacity: .45; }

.rt-voet {
    margin: 16px 0 0;
    padding-top: 14px;
    border-top: 1px solid var(--border-color);
}

/* Sleepbare tabelrijen (drag-to-reorder) — gemodelleerd naar PMS' .pos-parent-row */
.drag-handle { cursor: grab; color: var(--text-muted); }
tr.dragging { opacity: .4; }
tr.drag-over { box-shadow: inset 0 2px 0 var(--color-primary); background: var(--bg-table-row-hover); }

/* ===== FEEDBACK MODAL ===== */

/* BOVEN ELKE ANDERE MODAL. De feedbackknop staat in de zijbalk, maar het venster
   wordt óók geopend vanuit een modal die al open is — "Fout melden" in het
   ProductData-leesvenster (#modalWhProductInfo, z-index 1500). Op de standaard
   laag (100) zou het formulier dan achter dat venster verdwijnen. Het venster
   eronder blijft bewust openstaan: sluiten kost de gebruiker precies de gegevens
   waarover hij een melding doet. */
#feedbackModal { z-index: 2000; }

.feedback-type-btn { display: inline-flex; align-items: center; }

.btn.feedback-type-bug {
  color: var(--color-danger);
  border-color: var(--color-danger);
}
.btn.feedback-type-bug.active,
.btn.feedback-type-bug:hover {
  background: var(--color-danger);
  border-color: var(--color-danger);
  color: #fff;
}
/* ── Zoekbare select-dropdown (js/select-dropdown.js) — gedeeld, gebruik voor ALLE nieuwe selects ── */
.artikel-dropdown { position: relative; }
.artikel-dropdown-toggle {
    display: flex; align-items: center; justify-content: space-between;
    padding: 7px 10px; border-radius: var(--radius-sm);
    border: 1px solid var(--border-input); background: var(--bg-input);
    color: var(--text-primary); cursor: pointer; font-size: .875rem;
    min-height: 36px; user-select: none;
}
.artikel-dropdown-toggle:hover { border-color: var(--color-primary); }
.artikel-dropdown-toggle .artikel-caret {
    width: 14px; height: 14px; opacity: .5; flex-shrink: 0; margin-left: 6px;
    transition: transform .15s;
}
.artikel-dropdown.open .artikel-caret { transform: rotate(180deg); }
.artikel-dropdown-toggle.is-disabled { opacity: .55; cursor: not-allowed; pointer-events: none; }
.artikel-dropdown-panel {
    display: none; position: absolute; top: calc(100% + 2px); left: 0; right: 0;
    background: var(--bg-card); border: 1px solid var(--border-input);
    border-radius: var(--radius-sm); box-shadow: 0 4px 16px rgba(0,0,0,.12);
    z-index: 200; overflow: hidden;
}
.artikel-dropdown.open .artikel-dropdown-panel { display: block; }
.artikel-dropdown-toggle.is-invalid { border-color: var(--color-danger); }
.artikel-list { max-height: 220px; overflow-y: auto; }
.combi-search-wrap { padding: 8px; border-bottom: 1px solid var(--border-color); }
.combi-search-input {
    width: 100%; padding: 5px 8px; border-radius: var(--radius-sm);
    border: 1px solid var(--border-input); background: var(--bg-input);
    color: var(--text-primary); font-size: .85rem; box-sizing: border-box;
}
.combi-search-input:focus { outline: none; border-color: var(--color-primary); }
.combi-search-input::placeholder { color: var(--text-muted); }
.combi-item {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 12px; cursor: pointer; font-size: .875rem;
    color: var(--text-primary); transition: background .1s;
}
.combi-item:hover, .combi-item.focused { background: var(--bg-table-header); }
.combi-item.selected { background: var(--color-primary-light, rgba(59,130,246,.1)); font-weight: 600; }
.combi-empty { padding: 10px 12px; font-size: .85rem; color: var(--text-muted); font-style: italic; }

.btn.feedback-type-btn:not(.feedback-type-bug).active {
  background: var(--color-primary);
  color: #fff;
  border-color: var(--color-primary);
}

/* ══════════════════════════════════════════════════════════════════════════
   Positie Dropdown Component — poort van PMS' css/style.css (positie-dropdown.js).
   Generieke component (net als .artikel-dropdown/.combi-* hierboven) — niet
   pagina-specifiek, dus hier i.p.v. in css/klantenkaart.css. Eerste gebruik:
   de live PMS-positiepicker in de klantenkaart designs-editor.
   ══════════════════════════════════════════════════════════════════════════ */
.positie-dropdown-wrap {
  position: relative;
}

.positie-dropdown-trigger {
  width: 100%;
  background: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  font-size: 14px;
  color: var(--text-primary);
  cursor: pointer;
  transition: border-color 0.15s;
  min-height: 38px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  text-align: left;
  font-family: inherit;
}
.positie-dropdown-trigger:hover,
.positie-dropdown-trigger:focus {
  border-color: var(--color-primary);
  outline: none;
}
.positie-dropdown-trigger:disabled,
.positie-dropdown-trigger:disabled:hover {
  background: var(--bg-subtle);
  border-color: var(--border-color);
  color: var(--text-muted);
  cursor: not-allowed;
}
.positie-dropdown-trigger.positie-dropdown-placeholder .positie-dropdown-label {
  color: var(--text-muted);
}

/* Hoofd dropdown panel */
.positie-dropdown-panel {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  min-width: 100%;
  width: max-content;
  max-width: 320px;
  z-index: 110;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  max-height: 320px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Zoekbalk bovenin het positie-panel (vaste header) */
.positie-dropdown-search {
  flex-shrink: 0;
  padding: 8px;
  border-bottom: 1px solid var(--border-color);
  background: var(--bg-card);
}
.positie-dropdown-search-input {
  width: 100%;
  box-sizing: border-box;
  padding: 7px 10px;
  font-size: 13px;
  color: var(--text-primary);
  background: var(--bg-input, var(--bg-card));
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  outline: none;
}
.positie-dropdown-search-input:focus {
  border-color: var(--color-primary);
}
.positie-dropdown-search-input::placeholder {
  color: var(--text-muted);
}

/* Scrollbare lijst onder de zoekbalk */
.positie-dropdown-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: visible;
  -webkit-overflow-scrolling: touch;
}

.positie-dropdown-empty {
  padding: 12px;
  font-size: 13px;
  color: var(--text-muted);
  text-align: center;
}

.positie-dropdown-item.focused {
  background: var(--bg-table-row-hover);
}

.positie-dropdown-group {
  padding: 5px 12px 4px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  background: var(--bg-table-header);
  border-bottom: 1px solid var(--border-color);
  position: sticky;
  top: 0;
}

.positie-dropdown-separator {
  height: 1px;
  background: var(--border-color);
  margin: 2px 0;
}

.positie-dropdown-item {
  padding: 7px 12px;
  font-size: 14px;
  color: var(--text-primary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  user-select: none;
  white-space: nowrap;
}

/* Mobiel: panel mag niet breder zijn dan het scherm — lange positienamen
   wikkelen dan i.p.v. buiten het paneel te lopen. */
@media (max-width: 640px) {
  .positie-dropdown-panel {
    min-width: 0;
    width: calc(100vw - 32px);
    max-width: calc(100vw - 32px);
  }
  .positie-dropdown-item {
    white-space: normal;
    word-break: break-word;
  }
}
.positie-dropdown-item:hover {
  background: var(--bg-table-row-hover);
}
.positie-dropdown-item.selected {
  color: var(--color-primary);
  font-weight: 600;
}
/* Terug-knop in de positie-kiezer (touch drill-down) */
.positie-dropdown-back {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 9px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-primary);
  cursor: pointer;
  user-select: none;
  border-bottom: 1px solid var(--border-color);
}
.positie-dropdown-back:hover {
  background: var(--bg-table-row-hover);
}
.positie-dropdown-back svg {
  flex-shrink: 0;
}

/* Parent item met children: relative voor flyout positionering */
.positie-dropdown-item.has-children {
  position: relative;
  padding-right: 28px;
  color: var(--text-secondary);
  font-weight: 500;
}
.positie-dropdown-item.has-children > .pd-chevron {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  opacity: 0.5;
  pointer-events: none;
}

/* Touch: los tikbaar "meer"-label (zoomt in op subposities) — de rest van de
   rij selecteert de hoofdpositie zelf. Alleen tekst + pijltje, geen pil. */
.positie-dropdown-item.has-children > .pd-drill-btn {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 3px;
  padding: 6px 2px;
  color: var(--color-primary);
}
.positie-dropdown-item.has-children > .pd-drill-btn:active {
  opacity: 0.6;
}
.pd-drill-btn-label {
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

@media (max-width: 640px) {
  .positie-dropdown-item.has-children {
    padding-right: 68px;
  }
}

/* Flyout submenu — via JS gepositioneerd als sibling van het panel */
.positie-dropdown-flyout {
  position: absolute;
  z-index: 115;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  min-width: 180px;
  max-height: 320px;
  overflow-y: auto;
  overflow-x: hidden;
}
.positie-dropdown-flyout .positie-dropdown-item {
  padding: 7px 14px;
  font-size: 13px;
}

/* Hover tooltip op design-cards (design-zoek-modal) — poort van PMS' .card-tooltip */
.card-tooltip {
  position: fixed;
  z-index: 9999;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 12px 14px;
  min-width: 320px;
  max-width: 460px;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease, visibility 0.12s ease;
}
.card-tooltip.visible {
  opacity: 1;
  visibility: visible;
}
@media (max-width: 768px) {
  .card-tooltip {
    min-width: 0;
    max-width: calc(100vw - 16px);
  }
}
.card-tooltip-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-heading);
  margin-bottom: 8px;
  line-height: 1.3;
}
.card-tooltip-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
  font-size: 12px;
  padding: 2px 0;
  border-top: 1px solid var(--border-color);
}
.card-tooltip-row:first-of-type {
  border-top: none;
}
.card-tooltip-label {
  color: var(--text-muted);
  flex-shrink: 0;
}
.card-tooltip-value {
  color: var(--text-primary);
  text-align: right;
  word-break: break-word;
}
.card-tooltip-opmerking {
  font-size: 11.5px;
  color: var(--text-secondary);
  margin-top: 7px;
  padding-top: 7px;
  border-top: 1px solid var(--border-color);
  font-style: italic;
  line-height: 1.4;
}

/* ── Filterpaneel (gedeeld) ──────────────────────────────────
   Gebruikt door het takenfilter op het dashboard. Stond eerst in
   css/dashboard.css; die wordt alleen op het dashboard geladen.
   ------------------------------------------------------------ */

.filter-panel {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 300;
  width: 320px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 16px;
  max-height: 80vh;
  overflow-y: auto;
}
.filter-panel.open { display: block; }
.filter-section { margin-bottom: 14px; }
.filter-section:last-child { margin-bottom: 0; }
.filter-section-title {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .06em;
  margin-bottom: 7px;
}
.filter-pills { display: flex; flex-wrap: wrap; gap: 5px; }
.filter-pill { cursor: pointer; }
.filter-pill input[type=checkbox],
.filter-pill input[type=radio] { display: none; }
.filter-pill span {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  font-size: 12px;
  border: 1px solid var(--border-input);
  border-radius: var(--radius-full);
  color: var(--text-secondary);
  transition: background 0.1s, color 0.1s, border-color 0.1s;
  user-select: none;
  cursor: pointer;
}
.filter-pill input:checked + span {
  background: var(--color-primary);
  color: #fff;
  border-color: var(--color-primary);
}
.filter-pill span:hover { border-color: var(--color-primary); }
.filter-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--color-primary);
  color: #fff;
  border-radius: var(--radius-full);
  font-size: 11px;
  font-weight: 700;
  padding: 1px 6px;
  min-width: 18px;
  line-height: 1.4;
}
.filter-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-top: 12px;
  margin-top: 14px;
  border-top: 1px solid var(--border-color);
}

/* Design zoeken modal — kaarten grid (poort van PMS' .design-cards-grid) */
.design-cards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(185px, 1fr));
  gap: 18px;
}
@media (max-width: 640px) {
  .design-cards-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
  }
}

/* ============================================================= */
/* Kleur-picker (geport uit PMS order-wijzigen)                  */
/* ============================================================= */
.kleur-picker { display: flex; flex-direction: column; gap: 6px; }
.kleur-picker.is-invalid .kleur-dots {
  outline: 2px solid var(--color-danger);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}
/* padding zodat de selected/hover box-shadow-ring + scale van het eerste/laatste
   bolletje niet tegen (en door) de rand van een clippende container wordt afgekapt. */
.kleur-dots { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; padding: 4px; }
.kleur-dot {
  position: relative;
  width: 28px; height: 28px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer; padding: 0; flex-shrink: 0;
  transition: transform 0.15s, border-color 0.15s, box-shadow 0.15s;
  outline: none;
}
.kleur-dot:hover { transform: scale(1.18); border-color: var(--color-primary); }
.kleur-dot.selected {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.25);
  transform: scale(1.1);
}
.kleur-combo-badge {
  position: absolute; top: -5px; right: -5px;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--color-primary); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
  box-shadow: 0 0 0 1.5px var(--bg-card);
}
.kleur-dot-wit { border-color: var(--border-color) !important; }
.kleur-dot-wit.selected { border-color: var(--color-primary) !important; }
.kleur-dot-meer {
  background: var(--bg-table-header) !important;
  border: 2px dashed var(--border-color) !important;
  color: var(--text-secondary);
  font-size: 17px; font-weight: 700; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.kleur-dot-meer:hover { border-color: var(--color-primary) !important; color: var(--color-primary); transform: scale(1.12); }
.kleur-gekozen-dot {
  display: inline-block; width: 32px; height: 32px; border-radius: 50%;
  border: 2px solid var(--color-primary); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.22); flex-shrink: 0;
}
.kleur-gekozen { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text-secondary); margin-top: 4px; }
.kleur-gekozen-swatch { width: 13px; height: 13px; border-radius: 50%; border: 1px solid var(--border-color); flex-shrink: 0; }
.kleur-modal-dot { width: 34px; height: 34px; }
/* Toegevoegde kleuren (enkel of combinatie) als chip — bulk-kleurenmodal op
   ?page=artikelen. Zelfde vorm als KMS' bulk-variatiescherm. */
.kleur-combi-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 8px 4px 6px; border-radius: 9999px;
  border: 1px solid var(--border-color); background: var(--bg-table-header);
  font-size: 12px; color: var(--text-primary);
}
.kleur-combi-chip-swatch {
  width: 15px; height: 15px; border-radius: 50%;
  border: 1px solid var(--border-color); flex-shrink: 0;
}
.kleur-combi-chip-x {
  border: none; background: none; cursor: pointer; padding: 0;
  color: var(--text-muted); font-size: 14px; line-height: 1;
}
.kleur-combi-chip-x:hover { color: var(--color-danger); }
#kleurDotTooltip {
  position: fixed;
  background: #1e293b; color: #fff;
  font-size: 11px; font-weight: 500;
  padding: 3px 8px; border-radius: 4px;
  pointer-events: none; opacity: 0; transition: opacity 0.12s;
  z-index: 10000; white-space: nowrap; line-height: 1.5;
}
/* De gedeelde kleur-modal opent bóvenop een andere modal → hogere z-index. */
#kleurPickerModal { z-index: 2000; }

/* ─────────────────────────────────────────────────────────────────────────────
   Wizard-stappenbalk — gedeeld door de inboek-modal (?page=textiel-inboeken) en
   de verwerk-modal (?page=inkomend-textiel). Geport uit PMS ?page=order-invoer.
   Stond eerst inline in views/magazijn.php; hier generiek zodat beide wizards
   niet uiteen kunnen lopen.
   ───────────────────────────────────────────────────────────────────────────── */
.wizard-progress {
    display: flex; align-items: center; flex-shrink: 0;
    margin-bottom: 12px; padding: 7px 18px;
    background: var(--bg-card); border-radius: var(--radius-lg);
    border: 1px solid var(--border-color); box-shadow: var(--shadow-sm);
}
.wizard-step { display: flex; flex-direction: column; align-items: center; flex: 1; position: relative; }
.wizard-step:not(:last-child)::after {
    content: ''; position: absolute; top: 14px; left: 55%; right: -45%;
    height: 2px; background: var(--border-color); z-index: 0; transition: background .3s ease;
}
.wizard-step.completed::after { background: var(--color-secondary); }
.wizard-step.active::after    { background: var(--color-primary); }
.wizard-step-circle {
    width: 28px; height: 28px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 12px; z-index: 1;
    border: 2px solid var(--border-color); background: var(--bg-card); color: var(--text-muted);
    transition: all .25s ease;
}
.wizard-step.completed .wizard-step-circle { background: var(--color-secondary); border-color: var(--color-secondary); color: #fff; }
.wizard-step.active .wizard-step-circle    { background: var(--color-primary); border-color: var(--color-primary); color: #fff; box-shadow: 0 0 0 4px rgba(24,153,255,0.15); }
.wizard-step-label { font-size: 11px; font-weight: 600; color: var(--text-muted); margin-top: 4px; text-align: center; white-space: nowrap; letter-spacing: .01em; }
.wizard-step.active .wizard-step-label,
.wizard-step.completed .wizard-step-label { color: var(--text-primary); }

/* Verticale +/input/− stepper voor aantallen — ook gedeeld door beide wizards. */
.nal-stepper { display:inline-flex;flex-direction:column;align-items:stretch;border:1px solid var(--border-color);border-radius:4px;overflow:hidden;background:var(--bg-input,var(--bg-card)); }
.nal-step-btn { width:52px;height:22px;border:none;background:var(--bg-subtle);color:var(--text-primary);font-size:.8rem;font-weight:700;cursor:pointer;line-height:1;flex-shrink:0;transition:background .12s;display:flex;align-items:center;justify-content:center; }
.nal-step-btn:hover { background:var(--border-color); }
.nal-step-btn[data-dir="-1"] { border-top:1px solid var(--border-color); }
.nal-step-btn[data-dir="1"]  { border-bottom:1px solid var(--border-color); }
.nal-inp { width:52px;text-align:center;padding:4px 2px;font-size:.875rem;font-family:inherit;border:none;border-radius:0;background:var(--bg-input,var(--bg-card));color:var(--text-primary);line-height:1.4;-moz-appearance:textfield; }
.nal-inp::-webkit-outer-spin-button,.nal-inp::-webkit-inner-spin-button { -webkit-appearance:none;margin:0; }
.nal-inp:focus { outline:none;background:var(--bg-subtle); }

/* ── Meegestuurde gegevens bij een melding ────────────────────────────────
   Een leesblokje, geen invoer: twee kolommen (label smal, waarde breed) op de
   achtergrondkleur van de pagina zodat het als "dit is er al" leest en niet als
   een veld dat nog ingevuld moet worden. */
.fb-context {
    display: grid;
    grid-template-columns: minmax(110px, auto) 1fr;
    gap: 3px 14px;
    margin: 0;
    padding: 10px 12px;
    background: var(--bg-page);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    font-size: 12.5px;
}
.fb-context dt { color: var(--text-secondary); }
.fb-context dd { margin: 0; color: var(--text-primary); font-weight: 500; overflow-wrap: anywhere; }
.fb-context-noot { font-size: 11.5px; color: var(--text-secondary); margin-top: 5px; }

/* ── Feedback-sleepzone (screenshot) ──────────────────────────────────────
   Zelfde opzet als de DTF-uploadzone: gestippelde rand, oplichten bij hover
   en tijdens slepen. De formaten en maximale grootte staan in de zone zelf,
   zodat je niet pas ná het kiezen een foutmelding krijgt. */
.fb-drop {
    border: 2px dashed var(--border-color);
    border-radius: 10px;
    padding: 18px 12px;
    text-align: center;
    cursor: pointer;
    background: var(--bg-page);
    transition: border-color 150ms, background 150ms;
}

.fb-drop:hover,
.fb-drop.drag-over {
    border-color: var(--color-primary);
    background: color-mix(in srgb, var(--color-primary) 6%, transparent);
}

/* Toetsenbordgebruikers zien dezelfde focusring als elders in de app. */
.fb-drop:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

.fb-drop svg {
    width: 26px;
    height: 26px;
    color: var(--text-secondary);
    display: block;
    margin: 0 auto 6px;
}

.fb-drop-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 2px;
}

.fb-drop-sub {
    font-size: 11.5px;
    color: var(--text-secondary);
}

.fb-drop-formats {
    font-size: 10.5px;
    color: var(--text-secondary);
    margin-top: 6px;
    opacity: .7;
}

/* Regel onder de voorbeeldafbeelding: bestandsnaam + grootte links, knop rechts. */
.fb-drop-file {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-top: 6px;
    font-size: 11.5px;
    color: var(--text-secondary);
    word-break: break-all;
}


/* ---------------------------------------------------------------------------
 * MAAT-PILL — één vorm voor de hele app
 *
 * Een maat met een aantal komt op vier plekken voor: de orderregeltabel en de
 * bestellen-modal op ?page=order-detail, de voorraadtabel en het besteloverzicht.
 * Die liepen uiteen (eens "M:8" in monospace, eens een pil met een rondje, eens
 * kale tekst in een cel) terwijl het overal hetzelfde gegeven is. Vorm:
 *
 *     <span class="maat-pill">M<span class="maat-pill-aantal">8</span></span>
 *
 * De maat is de TEKST, het aantal het gevulde rondje — met beide in dezelfde
 * grijstint leest "XL 2" als één woord. Het aantal mag weggelaten worden als er
 * niets te tellen valt (een losse maataanduiding).
 *
 * Stond eerder in css/order-detail.css; dat bestand wordt lang niet overal
 * geladen, waardoor elke andere pagina zijn eigen variant kreeg.
 * ------------------------------------------------------------------------- */
.maat-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 1px 4px 1px 8px;
  margin: 1px 3px 1px 0;
  border-radius: var(--radius-full);
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  vertical-align: middle;
}
/* Zonder aantal blijft het een gewone pil: dan is er rechts geen rondje dat de
   extra ruimte opvult. */
.maat-pill:not(:has(.maat-pill-aantal)) { padding: 1px 8px; }
/* Gelijke breedte houdt een rij S/M/L/XL/XXL rustig. */
.maat-pill > :first-child { min-width: 22px; }
.maat-pill-aantal {
  display: inline-block;
  min-width: 18px;
  padding: 1px 5px;
  border-radius: var(--radius-full);
  background: var(--color-primary);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.35;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
/* De stand van een maat op ?page=order-detail. Vier kleuren, één ladder:
   grijs (de kale pil) = nog niet besteld · rood = besteld maar niets binnen ·
   oranje = deels binnen (het rondje toont dan "3/8") · groen = compleet.
   Geel is vervallen: dat zei alleen "besteld" en niet of het er ook is. */
.maat-pill.is-open { background: #fef2f2; border-color: #fecaca; color: #b91c1c; }
.maat-pill.is-open .maat-pill-aantal { background: #dc2626; }
.maat-pill.is-deels { background: #fffbeb; border-color: #fde68a; color: #b45309; }
.maat-pill.is-deels .maat-pill-aantal { background: #d97706; }
.maat-pill.is-binnen { background: #f0fdf4; border-color: #bbf7d0; color: #15803d; }
.maat-pill.is-binnen .maat-pill-aantal { background: #16a34a; }

[data-theme="dark-v2"] .maat-pill.is-open { background: rgba(127,29,29,.3); border-color: rgba(220,38,38,.5); color: #fecaca; }
[data-theme="dark-v2"] .maat-pill.is-open .maat-pill-aantal { background: #b91c1c; color: #fff; }
[data-theme="dark-v2"] .maat-pill.is-deels { background: rgba(120,53,15,.3); border-color: rgba(180,83,9,.5); color: #fde68a; }
[data-theme="dark-v2"] .maat-pill.is-deels .maat-pill-aantal { background: #b45309; color: #fff; }
[data-theme="dark-v2"] .maat-pill.is-binnen { background: rgba(20,83,45,.3); border-color: rgba(22,163,74,.5); color: #bbf7d0; }
[data-theme="dark-v2"] .maat-pill.is-binnen .maat-pill-aantal { background: #15803d; color: #fff; }

/* Bij "3/8" past het vaste rondje niet meer — daar mag het meegroeien. */
.maat-pill.is-deels .maat-pill-aantal { padding: 1px 7px; }

/* Van deze maat ligt iets apart om gepast te worden (migratie 128). Een STIP
   rechtsboven en geen eigen achtergrondkleur: de drie kleuren hierboven zeggen
   hoe ver het textiel is, en dat blijft de hoofdvraag. Passen is een aantekening
   erbovenop, geen vierde stand — de pil moet dus allebei tegelijk kunnen tonen.
   Violet, dezelfde kleur als de taak en de tag "aangeleverd": textiel dat hier
   ligt zonder dat het onze volgende stap gehad heeft. */
.maat-pill.heeft-passtuk { position: relative; overflow: visible; }
.maat-pill.heeft-passtuk::after {
  content: ''; position: absolute; top: -2px; right: -2px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--taak-pas_wacht, #7c3aed);
  border: 1.5px solid var(--bg-card, #fff);
}

/* "onesize" — geen maat, dus geen pil, maar wél dezelfde plek in de cel. */
.maten-cel-leeg { color: var(--text-muted); font-size: 12px; }
.maten-cel-leeg.is-open,
.maten-cel-leeg.is-deels,
.maten-cel-leeg.is-binnen {
  display: inline-block;
  padding: 1px 8px;
  border-radius: var(--radius-full);
  border: 1px solid transparent;
}
.maten-cel-leeg.is-open   { background: #fef2f2; border-color: #fecaca; color: #b91c1c; }
.maten-cel-leeg.is-deels  { background: #fffbeb; border-color: #fde68a; color: #b45309; }
.maten-cel-leeg.is-binnen { background: #f0fdf4; border-color: #bbf7d0; color: #15803d; }
[data-theme="dark-v2"] .maten-cel-leeg.is-open   { background: rgba(127,29,29,.3); border-color: rgba(220,38,38,.5); color: #fecaca; }
[data-theme="dark-v2"] .maten-cel-leeg.is-deels  { background: rgba(120,53,15,.3); border-color: rgba(180,83,9,.5); color: #fde68a; }
[data-theme="dark-v2"] .maten-cel-leeg.is-binnen { background: rgba(20,83,45,.3); border-color: rgba(22,163,74,.5); color: #bbf7d0; }

/* "MATEN N.N.B." — een offerteregel waarvan de maatverdeling nog niet bekend is
   (migratie 102). Staat op dezelfde plek in de cel als "onesize", maar mag daar
   niet op lijken: dat zegt dat het artikel géén maten kent, dit zegt dat de
   vraag nog openstaat. Vandaar de gestippelde omlijning — de vorm van iets dat
   nog ingevuld moet worden — en niet een van de drie bestelkleuren hierboven:
   die gaan over textiel dat onderweg is, en hier is nog niets besteld. */
.maten-cel-leeg.is-nnb {
  display: inline-block;
  padding: 1px 8px;
  border-radius: var(--radius-full);
  border: 1px dashed var(--border-color);
  color: var(--text-secondary);
  cursor: help;
}

/* ===== LOGLIJSTEN (?page=events + ?page=activiteitenlog) =====
   Twee pagina's met dezelfde vorm: een filterbalk met snelfilter-stippen, een
   tabel die server-side gepagineerd wordt en een laag-over-de-tabel tijdens het
   ophalen. Staat hier generiek en niet in een pagina-eigen bestand omdat beide
   pagina's er precies hetzelfde uit horen te zien — twee kopieën lopen uiteen.
   ========================================================================= */

/* ── Snelfilter: gekleurde stip + label, klikbaar als toggle ── */
.log-cat-filter { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.log-cat-btn {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  background: none; border: 1px solid transparent; padding: 5px 10px;
  border-radius: var(--radius-md); cursor: pointer; font-size: 13px;
  color: var(--text-muted); font-family: inherit;
  transition: border-color .12s, background .12s, color .12s;
}
.log-cat-btn:hover {
  border-color: var(--border-color); color: var(--text-primary); background: var(--bg-subtle);
}
.log-cat-btn.is-active {
  border-color: var(--color-primary); color: var(--text-primary);
  background: var(--bg-subtle); font-weight: 600;
}
.log-cat-stip { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex-shrink: 0; }

/* ── Laag over de tabel tijdens het ophalen ──
   De tabel blijft staan en vervaagt; hem leegmaken zou de pagina bij elke
   filterwissel laten opspringen. */
.log-tabel-wrap { position: relative; }
.log-loader {
  display: none; position: absolute; inset: 0; z-index: 5;
  align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--bg-card) 65%, transparent);
}
.log-loader.is-zichtbaar { display: flex; }
.log-spinner {
  width: 26px; height: 26px; border-radius: 50%;
  border: 3px solid var(--border-color); border-top-color: var(--color-primary);
  animation: logSpin .7s linear infinite;
}
@keyframes logSpin { to { transform: rotate(360deg); } }

/* ── Tabelcellen ── */
.log-col-datum { white-space: nowrap; font-size: 12px; color: var(--text-muted); }
.log-col-ip    { white-space: nowrap; font-size: 11.5px; color: var(--text-muted); }
.log-col-tekst { font-size: 12.5px; color: var(--text-secondary); max-width: 340px; }
.log-subtekst  { font-size: 11px; color: var(--text-muted); }

/* ── Paginatiebalk ── */
.log-paginatie {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 15px; border-top: 1px solid var(--border-color); flex-wrap: wrap;
}
.log-paginatie:empty { display: none; }
.log-pag-info { font-size: 12px; color: var(--text-muted); }
.log-pag-knoppen { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin-left: auto; }
.log-pag-btn {
  min-width: 32px; padding: 4px 9px; font-size: 13px; font-family: inherit;
  border: 1px solid var(--border-color); border-radius: var(--radius-md);
  background: var(--bg-card); color: var(--text-primary); cursor: pointer;
  transition: background .12s, border-color .12s;
}
.log-pag-btn:hover:not(:disabled):not(.is-active) { background: var(--bg-subtle); }
.log-pag-btn.is-active {
  background: var(--color-primary); border-color: var(--color-primary); color: #fff; font-weight: 600;
}
.log-pag-btn:disabled { opacity: .4; cursor: default; }
.log-pag-ellips { padding: 0 4px; color: var(--text-muted); font-size: 13px; }

/* De datumvelden staan sinds de filterknop in het uitklappaneel (.filter-paneel-2kol),
   waar de mount-div zijn breedte van de rasterkolom krijgt. De oude .log-datumveld
   met vaste 140px is daarmee vervallen. */

/* ── Artikelbeeld in een tabelrij ────────────────────────────────────────────
   Eén vierkant kader voor de kleine productfoto's in overzichtstabellen
   (?page=besteloverzicht, ?page=voorraad). Zelfde opbouw als `.tv-beeld` op
   ?page=transfervoorraad en `.order-regel-afbeelding` op ?page=order-detail:
   `contain` met wat lucht eromheen, want je moet zien wát er besteld wordt en
   niet een uitsnede daarvan — `cover` sneed een niet-vierkant beeld bij.
   `max-width:none` defeat de globale `img{max-width:100%}`, anders krimpt de
   breedte mee met een krappe cel en wordt het kader een rechthoek. Het witte
   vlak is de achtergrond waarop een beeld met transparantie staat. */
.oms-thumb {
  width: 56px; height: 56px;
  max-width: none;
  box-sizing: border-box;
  display: block;
  object-fit: contain;
  padding: 3px;
  background: #fff;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
}
/* De kolom eromheen: vaste breedte zodat de rijen niet verspringen zodra één
   artikel geen beeld heeft. De rechterpadding van .data-table (16px) valt weg,
   anders past het 56px-kader niet binnen de kolom en knipt `overflow:hidden`
   van een tabel met `table-layout:fixed` het beeld rechts af. Zelfde maatvoering
   als `.tv-beeld-cel` op ?page=transfervoorraad. */
.oms-thumb-cel { width: 76px; padding-right: 0 !important; }

/* ── Volledig scherm ────────────────────────────────────────────────────────
   Overgenomen van PMS ?page=productie-overzicht (.prod-fullscreen-btn), zelfde
   klassenamen zodat de knop op beide systemen hetzelfde heet. Een ronde knop
   rechtsonder die sidebar en header wegklapt; Escape zet hem terug.

   Staat hier in style.css en niet in een paginabestand: hij zit inmiddels op
   ?page=kassa en ?page=artikelen, en de markup komt uit één gedeelde include
   (views/_sections/fullscreen-knop.php). Wil je hem op een pagina erbij, dan is
   die include het enige wat je nodig hebt.

   De page-content begint op --dev-bar-offset en niet op 0: de dev-/onderhouds-
   balk is `position: fixed` bovenaan, en een kale `inset: 0` schuift er
   overheen. */
.prod-fullscreen-btn {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 90;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: var(--bg-card);
    border: 1.5px solid var(--border-color);
    box-shadow: 0 2px 10px rgba(0,0,0,.15);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    transition: background .15s, box-shadow .15s, color .15s;
}
.prod-fullscreen-btn:hover {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: #fff;
    box-shadow: 0 4px 16px rgba(24,153,255,.3);
}
.prod-fullscreen-btn .icon-compress { display: none; }
.prod-fullscreen-btn .icon-expand   { display: block; }

body.prod-fullscreen .sidebar,
body.prod-fullscreen .app-header {
    display: none !important;
}
body.prod-fullscreen .main-content {
    margin-left: 0 !important;
}
body.prod-fullscreen .page-content {
    position: fixed;
    top: var(--dev-bar-offset, 0px);
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 80;
    background: var(--bg-page);
    overflow-y: auto;
}
body.prod-fullscreen .prod-fullscreen-btn { z-index: 91; }
body.prod-fullscreen .prod-fullscreen-btn .icon-compress { display: block; }
body.prod-fullscreen .prod-fullscreen-btn .icon-expand   { display: none; }

/* ===== Spoed (migratie 100) ==============================================
   Eén vorm voor alle plekken waar "deze order gaat vóór" getoond wordt: naast
   het ordernummer in de lijst (?page=orders) en naast de kaarttitel "Levering &
   condities" op ?page=order-detail.

   Géén .badge: die zijn even zwaar als de statuspill ernaast in dezelfde cel, en
   dan strijden twee gelijkwaardige labels om de aandacht terwijl er maar één van
   de twee urgent is. Deze is compacter, draagt het bliksem-icoon en heeft een
   volle rand — hij hoort op te vallen zónder de status te verdringen. */
.spoed-pill {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    margin-left: 6px;
    padding: 1px 6px 1px 4px;
    border: 1px solid #FCA5A5;
    border-radius: 999px;
    background: #FEE2E2;
    color: #991B1B;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .02em;
    text-transform: uppercase;
    white-space: nowrap;
    vertical-align: middle;
}
.spoed-pill svg { flex-shrink: 0; }
.spoed-pill[hidden] { display: none; }
[data-theme="dark"] .spoed-pill,
[data-theme="dark-v2"] .spoed-pill {
    border-color: rgba(248,113,113,.45);
    background: rgba(159,18,57,.3);
    color: #fecdd3;
}

/* ===== Leverdatum-blok (views/_sections/leverdatum-velden.php) ============
   De schakelaar staat boven de keuze die hij stuurt en heeft daarom onder zich
   ruimte nodig; de velden eronder houden de gewone .form-group-afstanden. */
.ld-blok .ld-spoed-switch { margin-bottom: 12px; }
.ld-blok .oms-switch-label {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}
/* Bij spoed kleurt het bliksempje mee met de pill elders op de pagina: dezelfde
   vlag hoort er overal hetzelfde uit te zien. */
.ld-blok.is-spoed .oms-switch-label svg { color: var(--color-danger); }
.ld-blok .ld-termijn-blok[hidden],
.ld-blok .ld-datum-blok[hidden] { display: none; }
/* De uitkomstregel is een .kn-hint, maar leest zwaarder dan de andere hints in de
   modal: dit is niet de toelichting bij een veld maar het ANTWOORD — de dag die
   uit de termijnknop of de kalender rolt, en het enige wat de klant te horen
   krijgt. Vandaar groter en in de gewone tekstkleur in plaats van gedempt.

   Extra lucht boven én onder: hij hoort bij het hele blok en niet bij het laatste
   veld, en tegen de onderrand van de sectie geplakt las hij als een bijschrift
   dat er per ongeluk onder was gevallen. */
.ld-blok .ld-uitkomst {
    margin-top: 12px;
    margin-bottom: 4px;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.5;
    color: var(--text-primary);
}
/* Zolang er niets gekozen is staat er nog geen antwoord maar een aanwijzing, en
   die hoort wél gedempt te zijn — anders schreeuwt een lege stand net zo hard als
   een ingevulde. */
.ld-blok:not(.heeft-datum) .ld-uitkomst {
    font-weight: 400;
    color: var(--text-muted);
}
