
  /* v2026-05-23-C — Theme-systeem.
     Twee complete themas (`dark` / `occ`) op de body-class.
     - Default voor nieuwe users = OCC Mode (per user-request).
     - localStorage-key `occ_theme` houdt de keuze persistent.
     - Toggle-knop zit in de topbar (zie #theme-toggle).
     OCC Mode-kleuren komen direct uit de OCC brand-guide v1.1
     (web/portal-palette, Brand-01/02/03 + UI-01..UI-06 + alerts). */
  :root, body.theme-dark {
    /* v2026-07-20-B — native controls (date-pickers, selects, scrollbars) in het
       juiste kleurenschema renderen. Zonder dit toonde <input type=date> de
       ingevoerde datum in donkere tekst op de donkere achtergrond → onzichtbaar. */
    color-scheme: dark;
    --bg: #0f1419;
    --bg-2: #151b23;
    --panel: #1c232d;
    --panel-2: #232c37;
    --border: #2f3a47;
    --text: #e6edf3;
    --text-dim: #8a96a4;
    --accent: #4da6ce;
    --accent-2: #5bc68a;
    --danger: #e86a62;
    --warning: #f5a742;
    --lane-label: #6fb8d9;
    /* v2026-05-23-C — Aanvullende theme-tokens voor secundair UI-werk.
       Maken het mogelijk om inline-styles in app.js naar variabelen te porten. */
    --text-strong: #ffffff;    /* tekst op gekleurde accenten */
    --text-on-accent: #ffffff;  /* v2026-05-24-A — brand-guide: wit-op-turqoise/blauw in beide themas */
    --bg-overlay: rgba(0,0,0,0.45);
    --shadow-soft: 0 2px 10px rgba(0,0,0,0.30);
    --shadow-card: 0 4px 16px rgba(0,0,0,0.40);
    --brand-logo-stroke: #ffffff;       /* OCC-mark animatie: witte C-shapes */
    --brand-logo-cutout: #0f1419;       /* OCC-mark animatie: diamond-cutouts */
    --font-heading: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-body:    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    /* v2026-05-24-A — Semantische theme-tokens voor hover/stripe/tints/overlays.
       Vervangen de wijdverspreide hardcoded rgba's zodat OCC Mode echt mee
       schakelt. Dark = wit-transparant op donker; OCC = donkerblauw-transparant
       op licht. Hex-basis voor tints = accent-RGB van het betreffende thema. */
    --hover-bg:           var(--hover-bg);
    --hover-bg-strong:    rgba(255,255,255,0.08);
    --row-stripe:         var(--row-stripe);
    --row-stripe-strong:  rgba(255,255,255,0.03);
    --divider-subtle:     var(--divider-subtle);
    --divider-dashed:     var(--divider-subtle);
    --accent-tint-04:     var(--accent-tint-04);
    --accent-tint-06:     var(--accent-tint-06);
    --accent-tint-08:     var(--accent-tint-08);
    --accent-tint-10:     var(--accent-tint-10);
    --accent-tint-12:     var(--accent-tint-12);
    --accent-tint-15:     var(--accent-tint-15);
    --accent-tint-18:     var(--accent-tint-18);
    --accent-tint-22:     var(--accent-tint-22);
    --accent-tint-25:     var(--accent-tint-25);
    --accent-tint-35:     var(--accent-tint-35);
    --accent-border-30:   rgba(77,166,206,0.30);
    --accent-border-40:   rgba(77,166,206,0.40);
    --accent-border-45:   var(--accent-border-45);
    --accent-border-50:   rgba(77,166,206,0.50);
    --accent-glow:        var(--accent-glow);
    --accent-glow-strong: var(--accent-glow-strong);
    --accent-2-tint-10:   var(--accent-2-tint-10);
    --accent-2-tint-18:   var(--accent-2-tint-18);
    --danger-tint:        var(--danger-tint);
    --danger-tint-strong: var(--danger-tint-strong);
    --danger-border-40:   rgba(232,106,98,0.40);
    --danger-border-50:   rgba(232,106,98,0.50);
    --success-tint:       rgba(91,198,138,0.15);
    --success-border-40:  rgba(91,198,138,0.40);
    --warning-tint:       rgba(245,167,66,0.15);
    --warning-tint-soft:  rgba(245,158,11,0.10);
    --warning-border-40:  rgba(245,167,66,0.40);
    --warning-border-45:  rgba(245,158,11,0.45);
    --warning-strong:     #f5a742;
    --warning-text-soft:  #f5d390;
    --text-on-warning:    #000000;
    --tooltip-bg:         var(--tooltip-bg);
    --tooltip-bg-strong:  var(--tooltip-bg-strong);
    --tooltip-border:     var(--tooltip-border);
    --tooltip-text:       #ffffff;
    --panel-overlay:      rgba(28,35,45,0.40);
    --panel-overlay-strong: rgba(28,35,45,0.92);
    --panel-overlay-deep: var(--panel-overlay-deep);
    --map-mask:           var(--map-mask);
    --map-mask-strong:    var(--map-mask-strong);
    --map-marker-stroke:  #ffffff;
    --map-marker-text:    #ffffff;
    --pdf-canvas-bg:      #ffffff;
    --pdf-canvas-empty:   #fafafa;
    --pdf-canvas-empty-text: #666666;
    --pdf-viewer-bg:      #525659;
    --map-empty-bg:       #0c1116;
    --debug-code-bg:      #000000;
    --debug-code-text:    #e6edf3;
    --debug-clear-text:   #f87171;
    --status-ok:          #5bc68a;
    --status-warn:        #f5a742;
    --status-err:         #e86a62;
    --shadow-modal:       0 12px 28px rgba(0,0,0,0.55);
    --shadow-deep:        0 16px 40px rgba(0,0,0,0.50);
    --shadow-floating:    0 4px 12px rgba(0,0,0,0.20);
    --shadow-tooltip:     0 2px 6px rgba(0,0,0,0.40);
    --shadow-marker:      0 2px 4px rgba(0,0,0,0.50);
    --shadow-text-stroke: 0 0 2px rgba(0,0,0,0.55), 0 0 4px rgba(0,0,0,0.35);
    --node-text-glow:     rgba(255,255,255,0.92);
    --node-icon-fill:     var(--node-icon-fill);
    --pm-amber:           #FFB95C;
    --pm-amber-border:    #C18F4E;
    --pm-amber-tint:      rgba(193,143,78,0.08);
    --code-inline-bg:     var(--code-inline-bg);
  }
  body.theme-occ {
    color-scheme: light;      /* v2026-07-20-B — native controls in licht schema */
    --bg: #FFFFFF;             /* UI-01 White */
    --bg-2: #F3F4F5;           /* UI-02 Light Grey */
    --panel: #F9FAFB;          /* Brand-03-2 zeer licht */
    --panel-2: #F3F3F6;        /* Brand-03-5 */
    --border: #D5D8DB;         /* UI-03 Medium Grey */
    --text: #282F66;           /* Donkerblauw — brand text */
    --text-dim: #5A6873;       /* UI-05 Dark Grey */
    --accent: #009EB5;         /* Brand-01 Turqoise — primaire accent */
    --accent-2: #0075A1;       /* Brand-02 Blue — ondersteunend (geen groen) */
    --danger: #C9391F;         /* Alert Red */
    --warning: #F9DE7E;        /* Alert Yellow */
    --lane-label: #32B1C3;     /* Brand-01-80 */
    --text-strong: #282F66;
    --text-on-accent: #FFFFFF; /* tekst op turqoise/blue blijft wit */
    --bg-overlay: rgba(40,47,102,0.35);
    --shadow-soft: 0 2px 10px rgba(40,47,102,0.10);
    --shadow-card: 0 4px 16px rgba(40,47,102,0.15);
    --brand-logo-stroke: #282F66;
    --brand-logo-cutout: #FFFFFF;
    --font-heading: "Titillium Web", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    --font-body:    "Open Sans",     -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    /* v2026-05-24-A — OCC-tegenhangers van de semantische tokens.
       Tints afgeleid van Brand-01 Turqoise (0,158,181) en de brand-text
       donkerblauw (40,47,102). Geen wit-transparant op licht — i.p.v. dat
       gebruiken we donkerblauw-transparant zodat hovers/strepen subtiel
       in de OCC-stijl blijven. */
    --hover-bg:           rgba(40,47,102,0.05);
    --hover-bg-strong:    rgba(40,47,102,0.09);
    --row-stripe:         rgba(40,47,102,0.025);
    --row-stripe-strong:  rgba(40,47,102,0.045);
    --divider-subtle:     rgba(40,47,102,0.07);
    --divider-dashed:     rgba(40,47,102,0.10);
    --accent-tint-04:     rgba(0,158,181,0.05);
    --accent-tint-06:     rgba(0,158,181,0.07);
    --accent-tint-08:     rgba(0,158,181,0.08);
    --accent-tint-10:     rgba(0,158,181,0.10);
    --accent-tint-12:     var(--accent-2-tint-10);
    --accent-tint-15:     rgba(0,158,181,0.14);
    --accent-tint-18:     var(--accent-2-tint-18);
    --accent-tint-22:     rgba(0,158,181,0.20);
    --accent-tint-25:     rgba(0,158,181,0.22);
    --accent-tint-35:     rgba(0,158,181,0.30);
    --accent-border-30:   rgba(0,158,181,0.35);
    --accent-border-40:   rgba(0,158,181,0.45);
    --accent-border-45:   rgba(0,158,181,0.50);
    --accent-border-50:   rgba(0,158,181,0.55);
    --accent-glow:        rgba(0,158,181,0.40);
    --accent-glow-strong: rgba(0,158,181,0.65);
    --accent-2-tint-10:   rgba(0,117,161,0.10);
    --accent-2-tint-18:   rgba(0,117,161,0.16);
    --danger-tint:        rgba(201,57,31,0.07);
    --danger-tint-strong: rgba(201,57,31,0.13);
    --danger-border-40:   rgba(201,57,31,0.40);
    --danger-border-50:   rgba(201,57,31,0.50);
    --success-tint:       rgba(0,151,108,0.12);
    --success-border-40:  rgba(0,151,108,0.45);
    --warning-tint:       rgba(249,222,126,0.45);
    --warning-tint-soft:  rgba(249,222,126,0.30);
    --warning-border-40:  rgba(230,168,0,0.55);
    --warning-border-45:  rgba(230,168,0,0.60);
    --warning-strong:     #E6A800;
    --warning-text-soft:  #8A6A00;
    --text-on-warning:    #282F66;
    --tooltip-bg:         #282F66;
    --tooltip-bg-strong:  #282F66;
    --tooltip-border:     rgba(40,47,102,0.25);
    --tooltip-text:       #FFFFFF;
    --panel-overlay:      rgba(40,47,102,0.04);
    --panel-overlay-strong: rgba(243,244,245,0.95);
    --panel-overlay-deep: rgba(243,244,245,0.98);
    --map-mask:           rgba(40,47,102,0.45);
    --map-mask-strong:    rgba(40,47,102,0.65);
    --map-marker-stroke:  #FFFFFF;
    --map-marker-text:    #FFFFFF;
    --pdf-canvas-bg:      #FFFFFF;
    --pdf-canvas-empty:   #F3F4F5;
    --pdf-canvas-empty-text: #5A6873;
    --pdf-viewer-bg:      #E1E3E6;
    --map-empty-bg:       #ECEEF1;
    --debug-code-bg:      #282F66;
    --debug-code-text:    #FFFFFF;
    --debug-clear-text:   #C9391F;
    --status-ok:          #009878;
    --status-warn:        #E6A800;
    --status-err:         #C9391F;
    --shadow-modal:       0 12px 28px rgba(40,47,102,0.20);
    --shadow-deep:        0 16px 40px rgba(40,47,102,0.18);
    --shadow-floating:    0 4px 12px rgba(40,47,102,0.10);
    --shadow-tooltip:     0 2px 6px rgba(40,47,102,0.18);
    --shadow-marker:      0 2px 4px rgba(40,47,102,0.25);
    --shadow-text-stroke: 0 0 2px rgba(255,255,255,0.85), 0 0 4px rgba(255,255,255,0.55);
    --node-text-glow:     rgba(40,47,102,0.92);
    --node-icon-fill:     rgba(40,47,102,0.20);
    --pm-amber:           #C18F4E;
    --pm-amber-border:    #C18F4E;
    --pm-amber-tint:      rgba(193,143,78,0.10);
    --code-inline-bg:     rgba(40,47,102,0.08);
  }
  /* ══ Stapel-schaal (z-index) — v2026-08-04-G ═══════════════════════════════
     Eén oplopende reeks voor álles wat buiten zijn eigen container moet
     stapelen. Vóór deze ronde liepen er twee parallelle systemen naast elkaar
     (modal-lagen 2000/11800 in CSS + losse waarden 1100–100000 verspreid over
     de JS-modules), wat structureel "knop doet niets"-bugs opleverde: een
     dialoog opende ónder de overlay die 'm aanriep — onzichtbaar én
     onklikbaar, terwijl de code op een antwoord stond te wachten.

     REGEL: nieuwe code gebruikt uitsluitend deze variabelen. Een hardcoded
     z-index mag alleen nog binnen een eigen stacking context (plattegrond-
     markers, sticky koppen, een dropdown binnen een overlay) en blijft dan
     onder de 100 — zodat één blik op het getal al zegt "dit is lokaal".
     Werkt ook in inline-styles vanuit JS: `z-index:var(--z-overlay)`.

     Gelijke waarden stapelen op DOM-volgorde: de laatst geopende overlay wint,
     wat precies het gewenste gedrag is bij twee schermen van dezelfde soort. */
  :root {
    --z-map-ui:       1050;  /* knop/legenda over Leaflet (panes 700, ctrls 1000) */
    --z-map-ui-menu:  1060;  /* menu dat uit zo'n kaartknop klapt               */
    --z-map-ui-hint:  1100;  /* instructie-banner/hint over de hele kaart       */
    --z-header:       1200;  /* app-header — boven de kaart, onder elke overlay */
    --z-dropdown:     1400;  /* autocomplete/menu buiten een overlay            */
    --z-overlay-low:  1900;  /* overlay die bewust ÓNDER #modal blijft          */
    --z-overlay:      2000;  /* laag 1: #modal + élke feature-overlay + viewers */
    --z-overlay-2:    2500;  /* overlay geopend vanuit laag 1 (sub-formulier)   */
    --z-dialog:       3000;  /* laag 2: #modal2 — confirm/prompt, boven alles   */
    --z-popover:      4000;  /* context-menu's, tooltips — boven elke dialoog   */
    --z-morph:        5000;  /* view-switch morph-effect                        */
    --z-boot:         9000;  /* boot-loader                                     */
    --z-busy:         9100;  /* busy-overlay                                    */
    --z-toast:        9200;  /* toasts + systeem-banners                        */
    --z-splash:       9300;  /* login-splash                                    */
    --z-critical:     9400;  /* geen toegang / sessie verlopen — altijd bovenaan */
  }
  * { box-sizing: border-box; }
  /* v2026-05-14 BL13 — OCC Splash-overlay bij opstart */
  #splash {
    position: fixed; inset: 0;
    z-index: var(--z-splash);
    background: var(--bg);
    display: flex; align-items: center; justify-content: center;
    opacity: 1;
    transition: opacity 0.45s ease;
    cursor: pointer;
    user-select: none;
  }
  #splash.fade-out { opacity: 0; pointer-events: none; }
  /* v2026-07-04-F — Boot-loader (laadscherm met progress bar). Zelfde OCC-
     huisstijl als de splash, maar z-index onder de login-splash zodat die
     tijdens het aanmelden bovenaan blijft. Verdwijnt (fade) via .boot-done
     zodra alle opstart-data geladen is. */
  #boot-loader {
    position: fixed; inset: 0;
    z-index: var(--z-boot);
    background: var(--bg);
    display: flex; align-items: center; justify-content: center;
    opacity: 1;
    transition: opacity 0.45s ease;
    user-select: none;
  }
  #boot-loader.boot-done { opacity: 0; pointer-events: none; }
  .boot-inner {
    display: flex; flex-direction: column; align-items: center;
    width: 340px; max-width: 80vw;
    animation: splash-rise 0.6s ease-out;
  }
  .boot-logo {
    width: 280px; max-width: 70vw; height: auto;
    margin-bottom: 22px;
    user-select: none; -webkit-user-drag: none;
  }
  .boot-app {
    font-size: 14px; color: var(--accent);
    letter-spacing: 2px; text-transform: uppercase; font-weight: 500;
    margin-bottom: 22px;
  }
  .boot-bar {
    width: 100%; height: 6px;
    border-radius: 999px;
    background: var(--border);
    overflow: hidden;
  }
  .boot-bar-fill {
    width: 0%; height: 100%;
    border-radius: 999px;
    background: var(--accent);
    transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  }
  .boot-row {
    display: flex; align-items: center; justify-content: space-between;
    width: 100%; margin-top: 10px; gap: 12px;
  }
  .boot-step {
    font-size: 12px; color: var(--text-dim);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .boot-pct {
    font-size: 12px; color: var(--text-dim);
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums; flex: 0 0 auto;
  }
  .boot-version {
    font-size: 11px; color: var(--text-dim);
    margin-top: 24px;
    font-family: ui-monospace, Menlo, Consolas, monospace;
    opacity: 0.7;
  }
  /* v2026-07-05-E — Subtiele credit-regel op het opstartscherm (boot-loader),
     gelijk aan die op het bezig-overlay. */
  .boot-credit {
    font-size: 10.5px; color: var(--text-dim);
    margin-top: 10px; opacity: 0.6;
    letter-spacing: 0.2px; text-align: center;
  }
  /* v2026-07-11-I — Boot-takenlijst: live status + aantallen per opstart-load,
     zodat de splash niet "stil" lijkt tijdens een trage load. */
  .boot-tasks {
    display: flex; flex-direction: column; gap: 5px;
    width: 100%; margin-top: 16px;
  }
  .boot-task {
    display: flex; align-items: center; gap: 8px;
    font-size: 11.5px; color: var(--text-dim);
    opacity: 0.65; transition: opacity 0.3s ease, color 0.3s ease;
  }
  .boot-task-ico { flex: 0 0 14px; text-align: center; }
  .boot-task-label {
    flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .boot-task-detail {
    flex: 0 0 auto; color: var(--text-dim);
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums; opacity: 0.85;
  }
  .boot-task.is-done { opacity: 1; color: var(--text); }
  .boot-task.is-done .boot-task-ico { color: var(--accent); }
  .boot-task.is-pending .boot-task-ico { animation: bootTaskPulse 1.1s ease-in-out infinite; }
  @keyframes bootTaskPulse { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } }
  /* v2026-07-05-D — Herbruikbaar bezig-overlay (Claude-calls + PDF-generatie).
     Zelfde OCC-huisstijl als de boot-loader, maar met een indeterminate balk
     (glijdende animatie, geen %) en subtiele credit-regel. z-index boven de
     modals (die zitten lager) zodat het overlay altijd bovenop komt. */
  #busy-overlay {
    position: fixed; inset: 0;
    z-index: var(--z-busy);
    background: var(--bg);
    display: flex; align-items: center; justify-content: center;
    opacity: 1;
    transition: opacity 0.25s ease;
    user-select: none;
  }
  #busy-overlay.busy-hidden { opacity: 0; pointer-events: none; visibility: hidden; }
  .busy-inner {
    display: flex; flex-direction: column; align-items: center;
    width: 340px; max-width: 80vw;
    animation: splash-rise 0.4s ease-out;
  }
  .busy-logo {
    width: 260px; max-width: 68vw; height: auto;
    margin-bottom: 22px;
    user-select: none; -webkit-user-drag: none;
  }
  .busy-app {
    font-size: 14px; color: var(--accent);
    letter-spacing: 2px; text-transform: uppercase; font-weight: 500;
    margin-bottom: 22px;
  }
  .busy-bar {
    width: 100%; height: 6px;
    border-radius: 999px;
    background: var(--border);
    overflow: hidden;
  }
  .busy-bar-fill {
    width: 38%; height: 100%;
    border-radius: 999px;
    background: var(--accent);
    animation: busy-slide 1.15s cubic-bezier(0.45, 0, 0.55, 1) infinite;
  }
  @keyframes busy-slide {
    0%   { transform: translateX(-120%); }
    100% { transform: translateX(320%); }
  }
  .busy-step {
    font-size: 12px; color: var(--text-dim);
    margin-top: 12px; text-align: center;
    max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .busy-credit {
    font-size: 10.5px; color: var(--text-dim);
    margin-top: 26px; opacity: 0.6;
    letter-spacing: 0.2px; text-align: center;
  }
  .splash-inner {
    display: flex; flex-direction: column; align-items: center;
    gap: 4px;
    animation: splash-rise 0.6s ease-out;
  }
  @keyframes splash-rise {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  /* v2026-05-14 BL15 — Echt OCC-logo (Diapositief = wit op donker)
     v2026-05-14 BL49 — staged in een wrapper met 4-rechthoeken-intro-animatie.
     De stage heeft een vaste hoogte zodat de layout niet verschuift tijdens
     de overgang van animatie naar static logo. */
  .splash-logo-stage {
    position: relative;
    width: 320px; max-width: 75vw;
    height: 140px;
    margin-bottom: 14px;
    display: flex; align-items: center; justify-content: center;
  }
  .splash-logo {
    position: absolute; inset: 0; margin: auto;
    width: 100%; height: auto; max-height: 100%;
    user-select: none;
    -webkit-user-drag: none;
    opacity: 0;
    /* v2026-05-15-BM08 — Img fade-in NA de morph van de animation-svg.
       Tijdens de morph (1.85–2.40s) zijn alleen de vier vierkantjes zichtbaar,
       daarna verschijnt tekst + img-mark rondom de eind-positie. */
    animation: splash-logo-reveal 0.45s 2.40s ease-out forwards;
  }
  @keyframes splash-logo-reveal {
    from { opacity: 0; transform: scale(0.98); }
    to   { opacity: 1; transform: scale(1); }
  }
  /* v2026-05-14 BL50 + v2026-05-15-BM08 — Animatie met de echte OCC-mark-vormen.
     Fase 1 (0–0.75s): de 4 paths vliegen ieder vanuit een eigen hoek naar
                       hun positie in de mark, gecentreerd in de stage.
     Fase 2 (0.85–1.85s): de hele groep tolt 360° om het gemeenschappelijke
                          centrum.
     Fase 3 (1.85–2.40s): de complete mark MORPHT (transform-translate + scale)
                          naar de positie + grootte van de mark in het uiteinde-
                          lijke horizontale logo, zodat de vierkantjes naadloos
                          ovevloeien in de "logo-vierkantjes".
     Fase 4 (2.40–2.80s): het horizontale logo (tekst + mark) fade-in op de
                          eind-positie. Animation-svg blijft staan en valt
                          exact samen met de mark van het horizontale logo —
                          visueel één doorlopende beweging. */
  .splash-logo-anim {
    position: absolute; inset: 0; margin: auto;
    width: 200px; height: 200px;
    display: flex; align-items: center; justify-content: center;
    pointer-events: none;
    /* v2026-07-05-H — Na de morph fadet de animatie-mark uit terwijl het
       definitieve logo verschijnt (cross-fade). Voorheen bleef de anim-mark
       staan; op de lichte achtergrond (met nu zichtbaar statisch logo) gaf dat
       een "spookmark" die niet exact samenviel met het logo. */
    animation: splash-anim-morph 0.55s 1.85s cubic-bezier(0.5, 0, 0.3, 1) forwards,
               splash-anim-fade 0.40s 2.42s ease-out forwards;
    transform-origin: center center;
  }
  @keyframes splash-anim-fade { to { opacity: 0; } }
  .splash-logo-anim svg {
    width: 100%; height: 100%; display: block;
    overflow: visible;
  }
  /* Groep-rotatie rond het centrum van de viewBox (40,12,38,41 → center ≈ 59, 32.5) */
  .splash-logo-anim .rotator {
    transform-origin: 59px 32.5px;
    animation: rotator-spin 1.0s 0.85s cubic-bezier(0.5, 0, 0.5, 1) forwards;
  }
  @keyframes rotator-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
  }
  .splash-logo-anim path {
    transform-box: fill-box;
    transform-origin: center;
    opacity: 0;
  }
  /* v2026-05-23-H — Themable fills voor de OCC-mark animatie. In dark mode
     wit-op-donker, in OCC Mode donkerblauw-op-wit (volgens brand-guide). */
  .splash-logo-anim .r1, .splash-logo-anim .r3 { fill: var(--brand-logo-stroke); }
  .splash-logo-anim .r2, .splash-logo-anim .r4 { fill: var(--brand-logo-cutout); }
  .splash-logo-anim .r1 { animation: splash-r1 0.65s 0.05s cubic-bezier(0.22, 0.85, 0.30, 1) forwards; }
  .splash-logo-anim .r2 { animation: splash-r2 0.65s 0.18s cubic-bezier(0.22, 0.85, 0.30, 1) forwards; }
  .splash-logo-anim .r3 { animation: splash-r3 0.65s 0.10s cubic-bezier(0.22, 0.85, 0.30, 1) forwards; }
  .splash-logo-anim .r4 { animation: splash-r4 0.65s 0.23s cubic-bezier(0.22, 0.85, 0.30, 1) forwards; }
  @keyframes splash-r1 {
    from { transform: translate(-220%, -220%) scale(0.3) rotate(-180deg); opacity: 0; }
    50%  { opacity: 1; }
    to   { transform: translate(0, 0) scale(1) rotate(0); opacity: 1; }
  }
  @keyframes splash-r2 {
    from { transform: translate(-220%, 220%) scale(0.3) rotate(180deg); opacity: 0; }
    50%  { opacity: 1; }
    to   { transform: translate(0, 0) scale(1) rotate(0); opacity: 1; }
  }
  @keyframes splash-r3 {
    from { transform: translate(220%, -220%) scale(0.3) rotate(180deg); opacity: 0; }
    50%  { opacity: 1; }
    to   { transform: translate(0, 0) scale(1) rotate(0); opacity: 1; }
  }
  @keyframes splash-r4 {
    from { transform: translate(220%, 220%) scale(0.3) rotate(-180deg); opacity: 0; }
    50%  { opacity: 1; }
    to   { transform: translate(0, 0) scale(1) rotate(0); opacity: 1; }
  }
  /* v2026-05-15-BM08 — Morph i.p.v. fade-out: schuift de 4 vierkantjes naar
     de positie/grootte van de mark in het horizontale logo. Berekening:
     - Stage: 320×140 px. Animation-svg-container: 200×200 px, gecentreerd
       (visueel-center ≈ stage-center (160, 70)).
     - Horizontale logo (164×140 px in stage) zit gecentreerd; mark erin op
       viewBox-x=40..78, y=12..53 → mark-center op stage-pixel (≈161, 46).
     - Verschil van stage-center naar mark-center ≈ (0, -24) px.
     - Mark in animation-svg vult ~185×200; mark in img is 53×58 → schaal
       ≈ 0.28. */
  @keyframes splash-anim-morph {
    from { transform: translate(0, 0) scale(1); opacity: 1; }
    to   { transform: translate(0, -24px) scale(0.28); opacity: 1; }
  }
  .splash-app {
    font-size: 14px; color: var(--accent);
    margin-top: 2px; letter-spacing: 2px; text-transform: uppercase;
    font-weight: 500;
  }
  .splash-divider {
    width: 36px; height: 1px;
    background: var(--border);
    margin: 18px 0 14px;
  }
  .splash-user {
    font-size: 14px; color: var(--text-dim);
    font-style: italic;
  }
  /* v2026-05-14 BL35 — copyright-regel onder de designer-credit */
  .splash-copyright {
    font-size: 11.5px; color: var(--text-dim);
    margin-top: 4px;
    opacity: 0.75;
  }
  .splash-version {
    font-size: 11px; color: var(--text-dim);
    margin-top: 20px;
    font-family: ui-monospace, Menlo, Consolas, monospace;
    opacity: 0.7;
  }
  /* v2026-05-22-A — Demo-label + wachtwoord-lock onderaan de splash.
     Verschijnt pas ná de logo-animatie (start ~2.8s) via .ready-class. */
  .splash-gate {
    display: flex; flex-direction: column; align-items: center;
    gap: 10px;
    margin-top: 22px;
    opacity: 0; pointer-events: none;
    transition: opacity 0.5s ease;
    width: 320px; max-width: 90vw;
  }
  .splash-gate.ready { opacity: 1; pointer-events: auto; }
  .splash-demo-label {
    font-size: 12px; color: var(--accent);
    letter-spacing: 1.5px; text-transform: uppercase;
    font-weight: 600;
  }
  .splash-login-row {
    display: flex; gap: 8px; width: 100%;
  }
  .splash-login-row input[type="password"] {
    flex: 1;
    padding: 8px 12px;
    border: 1px solid var(--border);
    background: var(--bg-2);
    color: var(--text);
    border-radius: 6px;
    font-size: 14px;
    outline: none;
    transition: border-color 0.2s ease;
  }
  .splash-login-row input[type="password"]:focus {
    border-color: var(--accent);
  }
  .splash-login-row input[type="password"]:disabled {
    opacity: 0.5; cursor: not-allowed;
  }
  .splash-login-row #splash-login-btn {
    padding: 8px 16px;
    font-size: 14px;
  }
  .splash-login-row #splash-login-btn:disabled {
    opacity: 0.5; cursor: not-allowed;
  }
  .splash-feedback {
    font-size: 12px;
    color: var(--text-dim);
    min-height: 16px;
    text-align: center;
  }
  .splash-feedback.error { color: var(--danger); }
  .splash-feedback.lockout { color: var(--warning-strong); font-weight: 500; }

  /* Sprint 7 — Microsoft Entra login-knop op de splash */
  .splash-ms-btn {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 20px;
    background: var(--bg-2);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 14px; font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
    white-space: nowrap;
  }
  .splash-ms-btn:hover  { background: var(--bg-3); border-color: var(--accent); }
  .splash-ms-btn:active { opacity: 0.85; }
  .splash-ms-btn:disabled { opacity: 0.5; cursor: not-allowed; }

  /* Sprint 7 — Gebruikerspill in de topbar */
  .auth-user-pill {
    display: none; align-items: center; gap: 6px;
    font-size: 12px; color: var(--text-dim);
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: 20px;
    padding: 3px 10px 3px 8px;
    white-space: nowrap;
    max-width: 200px; overflow: hidden; text-overflow: ellipsis;
  }
  .auth-user-icon { font-size: 13px; }
  .auth-user-name { overflow: hidden; text-overflow: ellipsis; }
  .auth-user-signout {
    background: none; border: none; cursor: pointer;
    color: var(--text-dim); font-size: 13px; padding: 0 0 0 4px;
    line-height: 1;
  }
  .auth-user-signout:hover { color: var(--danger); }
  .auth-role-badge {
    font-size: 10px; font-weight: 700; letter-spacing: .04em;
    background: var(--accent, #d97706); color: #fff;
    border-radius: 4px; padding: 1px 5px; line-height: 1.4;
  }
  /* v2026-06-01-C — kleur-varianten per rol. Sales krijgt geen badge (= geen
     class), de andere drie ieder een eigen tint zodat ze in één oogopslag te
     onderscheiden zijn. */
  .auth-role-badge.badge-admin    { background: #d97706; }
  .auth-role-badge.badge-pm       { background: #c026d3; } /* roze — CLAUDE.md "pm-rol roze" */
  .auth-role-badge.badge-delivery { background: #0ea5e9; } /* delivery-blauw */
  /* v2026-07-24-V — nieuwe rollen: administratie (grijsblauw) + productie (groen). */
  .auth-role-badge.badge-administratie { background: #64748b; }
  .auth-role-badge.badge-productie     { background: #16a34a; }
  /* v2026-08-08-I — New Business (teal): suspect-domein in de Sales-view. */
  .auth-role-badge.badge-newbusiness   { background: #0d9488; }
  /* v2026-08-09-B — Product Sales (indigo): tweede saleskanaal, demo-proces.
     Bewust een andere tint dan New Business (teal) — de twee kanalen moeten in
     één oogopslag te onderscheiden zijn. */
  .auth-role-badge.badge-productsales  { background: #4f46e5; }
  /* v2026-08-19-A — Marketing (amber): communicatiedomein + adresboek. */
  .auth-role-badge.badge-marketing     { background: #ca8a04; }
  .auth-role-badge.badge-development   { background: #7c3aed; } /* v2026-08-08-O — dev-groep (rechten = admin) */
  /* v2026-07-24-V — admin: badge klikbaar → rol-preview-menu. */
  .auth-role-badge.badge-clickable { cursor: pointer; }

  /* v2026-08-25-A — Omgevingsindicatie rechtsboven. Zelfde vormtaal als de
     rol-badge, maar iets steviger: dit moet opvallen. Productie krijgt géén
     chip — dat is de normale situatie, en een chip die er altijd staat wordt
     niet meer gelezen. Alles wat niet productie is valt daardoor juist op. */
  /* Staat direct achter de titel linksboven — daar valt 'ie op, en de vraag
     "waar zit ik?" hoort bij de naam van de applicatie. Groter dan de
     rol-badge rechtsboven: dit is de belangrijkste chip in de balk. */
  .omgeving-chips {
    display: inline-flex; align-items: center; gap: 7px;
    margin-left: 12px; margin-right: 8px;
  }
  .omgeving-chip {
    font-size: 12px; font-weight: 700; letter-spacing: .06em;
    border-radius: 5px; padding: 4px 11px; line-height: 1.35;
    color: #fff; white-space: nowrap; cursor: default;
  }
  /* De omgevingschips pulseren, elk in hun eigen kleur: --puls-kleur voedt de
     gedeelde keyframe hieronder. Productie heeft geen chip en pulseert dus ook
     niet — precies de bedoeling. */
  .omgeving-chip.omg-dev {
    background: #dc2626; --puls-kleur: rgba(220, 38, 38, .55);   /* rood — ontwikkel */
    animation: omg-puls 2s ease-in-out infinite;
  }
  .omgeving-chip.omg-test {
    background: #d97706; --puls-kleur: rgba(217, 119, 6, .55);   /* amber — test */
    animation: omg-puls 2s ease-in-out infinite;
  }
  /* Blauw, niet groen. Groen leest als "in orde, ga door" — precies de
     verkeerde boodschap voor een omgeving waar je wijzigingen níét blijven.
     Bewust #2563eb en niet het #0ea5e9 van de delivery-rolbadge, zodat de twee
     naast elkaar in de balk niet op elkaar lijken. */
  .omgeving-chip.omg-acc {
    background: #2563eb; --puls-kleur: rgba(37, 99, 235, .55);   /* blauw — acceptatie */
    animation: omg-puls 2s ease-in-out infinite;
  }
  .omgeving-chip.omg-onbekend  { background: #64748b; } /* grijs — APP_ENV onbekend */
  /* Geplande taken uit. Rood + zacht pulserend als ALLES uit staat, amber als
     het er een paar zijn. Klikbaar: de popup legt uit wat er stilligt.
     Beide met een vast kleurvlak en witte tekst, zodat ze in light én dark
     evenveel opvallen — een variant op var(--text-dim) verdween in light mode
     vrijwel volledig. */
  .omgeving-chip.omg-taken { cursor: pointer; }
  .omgeving-chip.omg-taken:focus-visible {
    outline: 2px solid var(--accent, #d97706); outline-offset: 2px;
  }
  .omgeving-chip.omg-taken-alles {
    background: #dc2626; color: #fff; --puls-kleur: rgba(220, 38, 38, .55);
    animation: omg-puls 2s ease-in-out infinite;
  }
  .omgeving-chip.omg-taken-alles:hover { background: #b91c1c; }
  .omgeving-chip.omg-taken-deels {
    background: #d97706; color: #fff;
  }
  .omgeving-chip.omg-taken-deels:hover { background: #b45309; }
  /* Zacht: alleen de gloed en een fractie dekking. Geen schaal of beweging —
     een chip die in de topbar op en neer springt leidt de hele dag af. De
     kleur komt uit --puls-kleur, zodat elke chip in zijn eigen tint pulseert. */
  @keyframes omg-puls {
    0%, 100% { box-shadow: 0 0 0 0 var(--puls-kleur, rgba(220, 38, 38, .55)); opacity: 1; }
    50%      { box-shadow: 0 0 0 5px transparent; opacity: .82; }
  }
  @media (prefers-reduced-motion: reduce) {
    .omgeving-chip { animation: none !important; }
  }

  /* v2026-08-25-A — Entra-gegevens op het opstartscherm, alleen buiten
     productie. Bij een mislukte login noemt Entra alleen een client-id in een
     AADSTS-code; dit blok laat vooraf zien of dat de bedoelde registratie is. */
  .splash-entra {
    margin-top: 10px; padding: 8px 12px;
    border: 1px solid var(--border); border-radius: 8px;
    font-size: 11px; line-height: 1.5; text-align: left;
    max-width: 340px; margin-left: auto; margin-right: auto;
  }
  .splash-entra-kop {
    font-weight: 700; letter-spacing: .05em; margin-bottom: 4px;
    color: var(--text);
  }
  .splash-entra-rij { display: flex; gap: 8px; align-items: baseline; }
  .splash-entra-rij span { flex: 0 0 44px; color: var(--text-dim); }
  .splash-entra-rij code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 10.5px; word-break: break-all; color: var(--text);
  }
  .splash-entra-bron { margin-top: 4px; color: var(--text-dim); font-size: 10px; }

  /* Instantie-chip: welke server handelt dit verzoek af. Informatie, geen
     waarschuwing — dus een omlijning in plaats van een kleurvlak, zodat 'ie de
     omgevings- en taken-chip niet overschreeuwt. Wel var(--text) en niet
     var(--text-dim): dat laatste was in light mode nauwelijks leesbaar. */
  .omgeving-chip.omg-instantie {
    background: transparent; color: var(--text);
    border: 1px solid var(--border);
    font-weight: 600; letter-spacing: .02em;
    max-width: 220px; overflow: hidden; text-overflow: ellipsis;
  }
  .omgeving-chip.omg-instantie.omg-klikbaar { cursor: pointer; }
  .omgeving-chip.omg-instantie.omg-klikbaar:hover { border-color: var(--text-dim); }
  .omgeving-chip.omg-instantie:focus-visible {
    outline: 2px solid var(--accent, #d97706); outline-offset: 2px;
  }

  /* Configuratie-scherm (Beheer → Systeem → Configuratie). Tweekoloms: naam
     links in een vaste kolom, waarde rechts met de toelichting eronder. Drie
     kolommen naast elkaar paste niet — een GUID is 36 tekens. */
  .cfg-scherm .cfg-inleiding { font-size: 12px; color: var(--text-dim); margin: 0 0 12px; }
  .cfg-scherm .cfg-omgeving {
    font-size: 12px; margin: 0 0 14px; padding: 8px 10px;
    background: var(--row-stripe); border-radius: 8px;
  }
  .cfg-scherm .cfg-kop { font-size: 11.5px; font-weight: 600; margin: 0 0 6px; }
  .cfg-scherm .cfg-kaart {
    border: 1px solid var(--border); border-radius: 8px;
    padding: 2px 12px; margin: 0 0 14px;
  }
  .cfg-scherm .cfg-rij {
    display: flex; gap: 14px; align-items: baseline;
    padding: 7px 0; border-bottom: 1px solid var(--border);
  }
  .cfg-scherm .cfg-rij:last-child { border-bottom: 0; }
  .cfg-scherm .cfg-naam {
    flex: 0 0 200px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11px; color: var(--text-dim); word-break: break-all;
  }
  .cfg-scherm .cfg-waarde { flex: 1 1 auto; min-width: 0; font-size: 12px; word-break: break-all; }
  .cfg-scherm .cfg-waarde.cfg-leeg { color: var(--text-dim); font-style: italic; }
  .cfg-scherm .cfg-hint { display: block; font-size: 10.5px; color: var(--text-dim); margin-top: 2px; }
  .cfg-scherm .cfg-voetnoot { font-size: 11px; color: var(--text-dim); margin: 0; }
  .cfg-scherm .cfg-taken { padding: 8px 12px; }
  /* Smal scherm: labels boven de waarde in plaats van ernaast. */
  @media (max-width: 700px) {
    .cfg-scherm .cfg-rij { flex-direction: column; gap: 2px; }
    .cfg-scherm .cfg-naam { flex: none; }
  }
  #role-preview-menu {
    position: fixed; z-index: var(--z-popover);
    background: var(--bg-2); border: 1px solid var(--border);
    border-radius: 8px; padding: 6px; min-width: 180px;
    box-shadow: 0 8px 24px rgba(0,0,0,.35);
    display: flex; flex-direction: column; gap: 2px;
  }
  #role-preview-menu .role-preview-title {
    font-size: 10px; font-weight: 700; letter-spacing: .05em;
    text-transform: uppercase; color: var(--text-dim);
    padding: 4px 8px 2px;
  }
  #role-preview-menu .role-preview-item {
    background: transparent; border: 0; text-align: left;
    font-size: 12px; color: var(--text); padding: 6px 8px;
    border-radius: 5px; cursor: pointer;
  }
  #role-preview-menu .role-preview-item:hover  { background: var(--accent-tint-18); }
  #role-preview-menu .role-preview-item.active { color: var(--accent); font-weight: 700; }
  /* v2026-08-08-S — multi-select preview (stapeling sprint 4): apply-knop. */
  #role-preview-menu .role-preview-apply {
    margin-top: 4px; border-top: 1px solid var(--border); border-radius: 0 0 5px 5px;
    font-weight: 700; color: var(--accent);
  }
  #role-preview-menu .role-preview-apply:disabled { color: var(--text-dim); cursor: not-allowed; font-weight: 400; }

  /* v2026-06-01-C — Beheer-menu: zichtbaar voor admin én pm (PM heeft
     catalogus-beheer nodig). Verberg voor delivery + sales. Fine-grained
     gating per item kan later (bv. Aanbieders alleen voor admin). */
  /* v2026-07-26-L — Export/Beheer/Help samengevoegd tot één "Beheer"-menu dat
     nu voor ÁLLE rollen zichtbaar is (bevat ook Documenten/Prijslijst + Help).
     De pm/admin-only onderdelen krijgen .staff-only; admin-only houdt
     .admin-only. Submenu-parents met zo'n klasse verbergen zich (incl. hun
     items) voor rollen zonder toegang, zodat sales alleen Documenten + Help
     ziet. */
  body:not(.role-admin):not(.role-pm) .staff-only { display: none; }
  /* v2026-06-20-C — fine-grained: items met .admin-only alleen voor admin. */
  body:not(.role-admin) .admin-only { display: none; }
  /* v2026-08-22-U — begroting & prognose: admin, pm én New Business (Martijn en
     Jelmer werken samen aan de pijplijn; keuze Martijn 22-08). */
  body:not(.role-admin):not(.role-pm):not(.role-newbusiness) .forecast-only { display: none; }
  /* v2026-08-24-F — productoverzicht: admin, Productie én Administratie. Marcel
     krijgt het rapport maandelijks en weet zelf het beste welke artikelen voor
     inkoop van belang zijn; Caitlin zit op dezelfde stroom (keuze Martijn 24-08).
     De ONTVANGERS van de mail blijven admin-only — dat bepaalt waar bedrijfsdata
     naartoe gaat; zie openProductoverzichtModal. */
  body:not(.role-admin):not(.role-productie):not(.role-administratie) .povz-only { display: none; }
  /* v2026-08-24-L — Product Sales mag sinds deze versie in Universe (organisatie
     en workspace opzoeken bij het valideren en plannen), maar ziet daar géén
     bedragen: de afspraak van 09-08 is dat dit kanaal geen prijzen, calculaties
     of offertes ziet. De tabs Financieel en Overzicht in het rechterpaneel gaan
     daarom dicht.
     De :not()-keten is nodig omdat rollen stapelen: wie naast Product Sales óók
     een rol heeft die de cijfers wél mag zien, houdt ze. !important omdat de
     Overzicht-tab zijn display via een inline-style krijgt. */
  body.role-productsales:not(.role-admin):not(.role-pm):not(.role-sales):not(.role-delivery):not(.role-administratie):not(.role-newbusiness) .orgs-side-tab[data-tab="fin"],
  body.role-productsales:not(.role-admin):not(.role-pm):not(.role-sales):not(.role-delivery):not(.role-administratie):not(.role-newbusiness) .orgs-side-tab[data-tab="overzicht"] {
    display: none !important;
  }
  /* v2026-07-24-V — Productie-rol: ziet uitsluitend de Productie-view. Alle
     andere top-level tabs + het Beheer-menu gaan uit; switchView forceert
     daarnaast de view zelf (URL-routes, refresh, programmatische aanroepen). */
  /* v2026-08-08-Q — rollen-stapeling sprint 2: de beperkende regels op
     body.role-productie / body.role-newbusiness zijn verwijderd. Die waren op
     het één-rol-model geschreven; met meervoudige body-classes (één per rol)
     zouden ze bij bv. productie+sales juist rechten afpakken. Tab- en
     Beheer-menu-gating gebeurt nu in JS via _applyViewGating() (app.js),
     dat de optelsom van toegestane views per rollen-set berekent. */
  /* v2026-06-27 — Geblokkeerde configuratie = read-only. Interactieve onderdelen
     uitschakelen (behalve de lock-knop zelf, die buiten deze selectors valt). */
  .cfgview-block[data-locked="1"] .cfg-body,
  .cfgview-block[data-locked="1"] .cfgview-rename,
  .cfgview-block[data-locked="1"] .cfgview-type-select,
  .cfgview-block[data-locked="1"] .cfgview-system-toggle,
  .cfgview-block[data-locked="1"] .cfgview-del { pointer-events: none; opacity: 0.5; }

  /* Sprint 7 — Volledig-scherm foutpagina (geen toegang / sessie verlopen).
     v2026-07-27 — z-index van 10000 naar 100000: moet ALTIJD boven de
     boot-loader (99990) en de login-splash (99999) uitkomen, anders staat dit
     scherm onzichtbaar te wachten achter een bevroren laadscherm (zie de
     boot-loader-hang-bug bij een verlopen JWT). */
  .auth-error-screen {
    position: fixed; inset: 0; z-index: var(--z-critical);
    display: flex; align-items: center; justify-content: center;
    background: var(--bg-1, #111);
  }
  .auth-error-inner {
    display: flex; flex-direction: column; align-items: center;
    gap: 16px; text-align: center;
    padding: 48px 40px;
    background: var(--bg-2, #1a1a1a);
    border: 1px solid var(--border, #333);
    border-radius: 12px;
    max-width: 480px; width: 90%;
  }
  .auth-error-logo { height: 36px; opacity: 0.85; }
  .auth-error-lock { font-size: 48px; line-height: 1; }
  .auth-error-title { margin: 0; font-size: 22px; color: var(--text, #eee); }
  .auth-error-body {
    margin: 0; font-size: 14px; color: var(--text-dim, #aaa); line-height: 1.5;
  }
  .auth-error-hint {
    margin: 0; font-size: 12px; color: var(--text-dim, #aaa); line-height: 1.5;
  }

  html, body {
    height: 100%; margin: 0;
    font-family: var(--font-body);
    color: var(--text); background: var(--bg);
    overflow: hidden;
  }
  /* v2026-05-23-H — Brand-typografie in OCC Mode: koppen krijgen Titillium Web. */
  h1, h2, h3, h4, h5, h6,
  header h1,
  .group-name, .view-btn, .action-btn,
  .splash-app, .splash-demo-label {
    font-family: var(--font-heading);
  }
  header {
    /* v2026-07-21-F — compacter: 52→44px hoog, padding 8→6px, gap 10→8px.
       Levert 9px op élk scherm op; de knoppen zelf (32px hoog) passen ruim. */
    display: flex; align-items: center; gap: 8px;
    padding: 6px 14px;
    /* v2026-05-23-I — gradient verwijderd, solid bg-2 conform brand-guide */
    background: var(--bg-2);
    border-bottom: 1px solid var(--border);
    position: relative; z-index: var(--z-header);  /* boven Leaflet-controls (1000) zodat dropdowns niet onder de map vallen */
    min-height: 44px;
  }
  /* v2026-05-23-C — Theme-toggle in topbar. Lichte pill-stijl die in beide
     thema's leesbaar is. Icon (☀ / ☾) en label (OCC / DARK) worden door JS
     gevuld op basis van de huidige theme. */
  #theme-toggle {
    display: inline-flex; align-items: center; gap: 6px;
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-dim);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.4px;
    padding: 3px 10px;
    border-radius: 12px;
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
  }
  #theme-toggle:hover {
    color: var(--accent);
    border-color: var(--accent);
  }
  #theme-toggle .theme-toggle-icon {
    font-size: 13px;
    line-height: 1;
  }
  /* v2026-05-23-C — App-version-pill + debug-log-knop: voorheen inline-styled in
     header HTML, nu via class zodat thema-swap meegaat. */
  #app-version {
    font-size: 10px;
    color: var(--text-dim);
    font-family: ui-monospace, Menlo, Consolas, monospace;
    padding: 2px 8px;
    border: 1px solid var(--border);
    border-radius: 10px;
    letter-spacing: 0.3px;
  }
  /* v2026-08-19-A — De #debug-log-btn-regels stonden hier nog uit de tijd dat de
     knop in de topbar zat (v2026-05-23-C). Sinds v2026-06-03-E staat 'ie in
     Beheer → Systeem, waar de id-selector het randje + eigen padding van de
     oude pill over .topbar-menu-item heen legde (id wint van class) — het item
     zag eruit als een invoerveld tussen de andere menu-items. Regels verwijderd
     i.p.v. overschreven; het menu-item styling komt nu volledig uit
     .topbar-menu-item, net als alle andere items. */
  header h1 {
    font-size: 14px; margin: 0 6px 0 0; letter-spacing: .3px;
    display: flex; align-items: center; gap: 8px;
    font-weight: 700;
  }
  header h1 .dot {
    width: 8px; height: 8px; border-radius: 50%; background: var(--accent-2);
    box-shadow: 0 0 12px var(--accent-2);
  }
  /* v2026-05-14 BL15 — OCC-beeldmerk vóór het "Universe Builder"-tekst */
  header h1 .occ-mark {
    width: 22px; height: 22px;
    display: inline-block; flex-shrink: 0;
    object-fit: contain;
  }
  /* Subtiele verticale scheiders tussen logische groepen in de topbar. */
  .topbar-sep {
    width: 1px; align-self: stretch;
    background: var(--border); opacity: 0.6;
    margin: 4px 2px;
  }
  .workspace-badge {
    display: inline-flex; align-items: center; gap: 8px;
    background: var(--panel); color: var(--text);
    border: 1px solid var(--border); border-radius: 6px;
    padding: 4px 12px; font-size: 12px; cursor: pointer;
    transition: border-color .15s, background .15s;
    max-width: 320px;
    line-height: 1.25;
  }
  .workspace-badge:hover { border-color: var(--accent); background: var(--panel-2); }
  .workspace-badge .ws-text {
    display: flex; flex-direction: column;
    min-width: 0; max-width: 250px;
  }
  .workspace-badge .ws-name {
    font-weight: 700; color: var(--accent);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    font-size: 12px;
  }
  .workspace-badge .ws-address {
    font-size: 10.5px; color: var(--text-dim); font-weight: 400;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    max-width: 250px;
  }
  .workspace-badge .ws-address:empty { display: none; }
  .workspace-badge .ws-edit { color: var(--text-dim); font-size: 11px; align-self: flex-start; margin-top: 2px; }

  /* EY: rol-pill CSS verwijderd. Rol-gebaseerde gating komt straks bij de
     database-koppeling met echte autorisatie-matrix. */

  /* v2026-05-07-C: .user-pill / .lock-pill / .locked-by-me / .locked-by-other
     CSS verwijderd. User-identity-flow + soft-lock zijn weg (zie HTML/JS). */

  /* v2026-05-07-D: percelen-rij + select-pill styling.
     Compacte rij-layout in de Percelen-tab. Vijf gekleurde selects per perceel
     (Calc/SPOC/1e/2e/SLA) met pill-look. Hover toont zachte highlight. */
  .perceel-row { transition: background 0.15s; }
  .perceel-row:hover { background: var(--hover-bg) !important; }
  .percelen-pill {
    transition: filter 0.15s, box-shadow 0.15s;
    line-height: 1.4;
  }
  .percelen-pill:hover:not(:disabled) {
    filter: brightness(1.1);
    box-shadow: 0 0 0 1px var(--hover-bg-strong);
  }
  .percelen-pill:focus {
    outline: none;
    box-shadow: 0 0 0 2px var(--accent);
  }
  .percelen-pill option {
    background: var(--panel);
    color: var(--text);
  }
  /* v2026-05-07-J: override-marker. Pill afwijkt van workspace-default →
     oranje ring (zelfde kleur als reset-knop). */
  .percelen-pill.override {
    box-shadow: 0 0 0 1.5px var(--warning);
  }
  .percelen-pill.override:hover:not(:disabled) {
    box-shadow: 0 0 0 1.5px var(--warning), 0 0 0 3px var(--warning-tint);
  }
  .percelen-pill-reset {
    transition: transform 0.15s, color 0.15s;
  }
  .percelen-pill-reset:hover {
    transform: rotate(-90deg);
    color: var(--pm-amber);
  }
  /* Beheer-modal — percelen master-tabel rij. */
  .pm-row:hover { background: var(--row-stripe-strong); }
  .pm-row .pm-delete:hover { background: var(--danger-tint-strong); border-color: var(--danger); color: var(--danger); }

  /* EY: gating-regels (.pm-only / .sales-only / data-role-only) verwijderd.
     Komt terug bij de database-koppeling met echte autorisatie-matrix. */
  .file-btn, .action-btn {
    background: var(--panel); color: var(--text);
    border: 1px solid var(--border); border-radius: 6px;
    padding: 6px 12px; font-size: 12.5px; cursor: pointer;
    transition: background .15s, border-color .15s, color .15s;
    display: inline-flex; align-items: center; gap: 6px;
    font-weight: 500;
  }
  .file-btn:hover, .action-btn:hover {
    background: var(--panel-2); border-color: var(--accent); color: var(--accent);
  }
  /* Topbar-knoppen krijgen een ietwat compactere variant met subtiele icoon. */
  header .topbar-menu-btn,
  header .file-btn,
  header .action-btn {
    height: 28px;   /* v2026-07-21-F — 32→28px, past bij de lagere header */
  }
  .hint { color: var(--text-dim); font-size: 12px; }
  main {
    display: grid;
    grid-template-columns: 1fr var(--panel-width, 420px);
    /* v2026-08-03-H — hoogte gecompenseerd voor de weergave-zoom (Aa S/M/L):
       vh-eenheden schalen mee met CSS-zoom, waardoor de onderkant leeg bleef
       bij S/M. --ui-zoom wordt door setupUiZoom (app.js) gezet. */
    height: calc(100vh / var(--ui-zoom, 1) - 53px);
    position: relative;
  }
  /* Resize-handle tussen canvas en rechterpaneel — sleep om te verbreden/versmallen */
  #panel-resize {
    position: absolute;
    top: 0; bottom: 0;
    right: var(--panel-width, 420px);
    margin-right: -3px;       /* zodat de 6px breed handle de boundary straddled */
    width: 6px;
    cursor: col-resize;
    z-index: 10;
    background: transparent;
    transition: background .15s;
  }
  #panel-resize:hover, #panel-resize.dragging {
    background: var(--accent-tint-35);
    box-shadow: 0 0 12px var(--accent-border-40);
  }
  #panel-resize::after {
    content: "";
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 2px; height: 28px;
    border-radius: 2px;
    background: var(--border);
    transition: background .15s, height .15s;
  }
  #panel-resize:hover::after { background: var(--accent); height: 50px; }
  body.resizing-panel { cursor: col-resize !important; user-select: none !important; }
  /* v2026-07-27 — Verticale resize-handle (bv. Configuraties-strook ↔
     Catalogus in de WS-Producten-aside). Zelfde visuele taal als
     #panel-resize, maar horizontaal (row-resize i.p.v. col-resize). */
  .v-resize-handle {
    height: 6px;
    flex-shrink: 0;
    cursor: row-resize;
    background: transparent;
    position: relative;
    transition: background .15s;
  }
  .v-resize-handle:hover, .v-resize-handle.dragging {
    background: var(--accent-tint-35);
    box-shadow: 0 0 12px var(--accent-border-40);
  }
  .v-resize-handle::after {
    content: "";
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    height: 2px; width: 28px;
    border-radius: 2px;
    background: var(--border);
    transition: background .15s, width .15s;
  }
  .v-resize-handle:hover::after { background: var(--accent); width: 50px; }
  body.resizing-v-panel { cursor: row-resize !important; user-select: none !important; }
  /* v2026-08-13-C — Kolom-resize in tabellen (public/js/table-resize.js).
     Zelfde visuele taal als #panel-resize: onzichtbaar tot je erover hovert,
     dan een accentlijn op de kolomgrens. De handle zit binnen de <th> (in de
     rechter-padding), zodat een th met overflow:hidden 'm niet afknipt.
     z-index blijft bewust onder de 100: dit is een lokale stacking context
     binnen de tabelkop, geen overlay — zie de stapel-schaal in :root. */
  th.tblrz-th { position: relative; }
  .tblrz-h {
    position: absolute;
    top: 0; bottom: 0; right: 0;
    width: 7px;
    cursor: col-resize;
    z-index: 5;
    user-select: none;
    touch-action: none;
    background: transparent;
  }
  .tblrz-h::after {
    content: "";
    position: absolute;
    top: 12%; bottom: 12%; right: 3px;
    width: 2px;
    border-radius: 2px;
    background: transparent;
    transition: background .12s;
  }
  .tblrz-h:hover::after, .tblrz-h.is-dragging::after { background: var(--accent); }
  .tblrz-h.is-dragging { background: var(--accent-tint-35); }
  body.resizing-cols, body.resizing-cols * { cursor: col-resize !important; user-select: none !important; }
  #canvas-wrap {
    position: relative;
    /* v2026-05-23-I — radial gradient verwijderd, solid bg */
    background: var(--bg);
    overflow: hidden;   /* zelf niet scrollen — zoom-controls & legend blijven vast */
  }
  #canvas-scroll {
    position: absolute; inset: 0;
    overflow: auto;     /* hier gebeurt de scroll van de SVG */
  }
  #canvas-wrap.drag-over::after {
    content: "Laat los om Excel te laden";
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: var(--accent); font-size: 20px;
    background: var(--accent-tint-08);
    border: 2px dashed var(--accent);
    pointer-events: none;
    z-index: 6;
  }

  /* v2026-07-05-A — #empty-state overlay-styling verwijderd (XLS-laadscherm weg). */

  svg { display: block; }  /* width/height dynamisch gezet */

  .lane-bg { stroke-dasharray: 2 4; opacity: 0.9; }
  .lane-bg.tech { stroke-dasharray: 1 6; }
  /* Hele tech-LANE oplichten als de geselecteerde aanbieder/consument deze
     technologie raakt — niet alleen het pill-tekstvak. */
  .lane-bg.tech.lane-active {
    stroke-width: 2.5px !important;
    stroke-dasharray: 0 !important;
    opacity: 1 !important;
    filter: drop-shadow(0 0 14px var(--accent-glow))
            drop-shadow(0 0 4px rgba(255,255,255,0.25));
  }
  .lane-label {
    font-size: 11px; font-weight: 700;
    letter-spacing: 1.5px; text-transform: uppercase;
    cursor: grab;
    user-select: none;
  }
  .lane-label.dragging { cursor: grabbing !important; opacity: 0.7; }
  .lane-drop-indicator {
    stroke: var(--accent);
    stroke-width: 3;
    stroke-dasharray: 8 4;
    pointer-events: none;
  }
  .lane-label.tech { font-size: 10px; }

  .link {
    fill: none; stroke: var(--border); stroke-width: 1.4;
    opacity: 0.75;
  }
  .link.tech {
    stroke-dasharray: 5 4;
    opacity: 0.7;
    stroke-width: 1.2;
  }
  .link.highlight { stroke: var(--accent); stroke-width: 2.2; opacity: 1; }
  .link.dimmed { opacity: 0.12; }

  .node rect.card {
    fill: var(--panel); stroke: var(--border); stroke-width: 1;
    rx: 8; ry: 8;
    filter: drop-shadow(0 2px 4px rgba(0,0,0,0.35));
  }
  .node:hover rect.card { stroke: var(--accent); }
  .node.selected rect.card { stroke: var(--accent); stroke-width: 2.5; filter: drop-shadow(0 0 8px var(--accent-border-50)); }
  .node.highlight rect.card { stroke: var(--accent); stroke-width: 2; }
  .node.highlight { filter: drop-shadow(0 0 6px var(--accent-border-45)); }
  /* Tech-node krijgt extra zichtbare glow als 'ie geactiveerd is door de
     selectie — zodat de gebruiker meteen ziet welke draadloze laag erbij hoort. */
  .node.tech.highlight rect.card {
    stroke-width: 3 !important;
    fill-opacity: 0.55 !important;
  }
  .node.tech.highlight {
    filter: drop-shadow(0 0 14px var(--accent-glow-strong))
            drop-shadow(0 0 6px rgba(255,255,255,0.4));
  }
  .node.tech.highlight text.name { fill: #fff; font-weight: 900; }
  .node.dimmed { opacity: 0.20; }
  /* Placeholder: nog-niet-gedefinieerd artikel op de laag */
  .node.placeholder rect.card {
    stroke: var(--text-dim);
    stroke-width: 1.4;
    stroke-dasharray: 5 4;
    fill: rgba(139,149,165,0.10);
    filter: drop-shadow(0 1px 2px var(--code-inline-bg));
  }
  .node.placeholder text.name,
  .node.placeholder text.sub,
  .node.placeholder text.card-icon,
  .node.placeholder text.type-chip-text,
  .node.placeholder text.icon-emoji { opacity: 0.70; }
  .node.placeholder .placeholder-badge {
    fill: #C18F4E;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.5px;
  }
  .node.placeholder.selected rect.card { stroke: var(--accent); stroke-dasharray: 5 4; }
  .node.dragging { opacity: 0.8; filter: drop-shadow(0 4px 10px rgba(0,0,0,0.6)); cursor: grabbing !important; }
  .node, .node * { cursor: grab; }
  .node.dragging, .node.dragging * { cursor: grabbing !important; }
  .node.tech, .node.tech * { cursor: pointer; }   /* tech-nodes zijn niet sleepbaar */
  .drop-target-rect {
    fill: var(--accent-tint-18) !important;
    stroke: var(--accent) !important;
    stroke-width: 3px !important;
    stroke-dasharray: 0 !important;
    filter: drop-shadow(0 0 8px var(--accent-glow));
  }
  /* Locatie-container die geselecteerd is voor multi-select bulk-acties */
  .zorg-container.loc-selected {
    stroke-width: 3px !important;
    stroke: #fff !important;
    filter: drop-shadow(0 0 6px rgba(255,255,255,0.5));
  }
  /* Drop-hover bij het slepen van een Configuratie naar een locatie */
  .zorg-container.cfg-drop-hover {
    fill: rgba(122,168,116,0.30) !important;
    stroke: var(--accent-2) !important;
    stroke-width: 3px !important;
    filter: drop-shadow(0 0 10px rgba(91,198,138,0.55));
  }
  /* Locaties die GEKOPPELD zijn aan de geselecteerde configuratie:
     groene gestreepte rand zodat je in één oogopslag ziet welke locaties
     deze configuratie hebben toegepast. */
  .zorg-container.cfg-linked {
    stroke: var(--accent-2) !important;
    stroke-width: 2.5px !important;
    stroke-dasharray: 6 4 !important;
    filter: drop-shadow(0 0 5px rgba(91,198,138,0.45));
  }
  /* Verbindingslijnen tussen geselecteerde cfg-card en gekoppelde locaties */
  .cfg-link-line {
    fill: none;
    stroke: var(--accent-2);
    stroke-width: 1.5;
    stroke-dasharray: 5 4;
    pointer-events: none;
    opacity: 0.8;
  }
  /* Lane die als 'extern geleverd / blackbox' is gemarkeerd: gestreepte rand
     en een lichtere fill zodat ie visueel uit de eigen-design-lanes valt. */
  .lane-bg.lane-external {
    stroke-dasharray: 8 6;
    opacity: 0.55;
  }
  .lane-external-badge {
    fill: rgba(180,140,80,0.95);
  }
  .lane-external-badge-text {
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.8px;
    fill: #1a1410;
    pointer-events: none;
  }
  .lane-extspec-text {
    font-size: 11px;
    fill: var(--text-dim);
    font-style: italic;
    pointer-events: none;
  }
  .lane-nofin-badge {
    fill: rgba(120,135,150,0.85);
  }
  .lane-nofin-badge-text {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.6px;
    fill: var(--text-on-accent);
    pointer-events: none;
  }
  /* Right-click context menu voor locaties */
  .loc-context-menu {
    position: fixed;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: var(--shadow-modal);
    min-width: 220px;
    z-index: var(--z-popover);
    padding: 4px;
    font-size: 12px;
    color: var(--text);
  }
  .loc-context-menu .ctx-item {
    padding: 7px 12px;
    border-radius: 4px;
    cursor: pointer;
    display: flex; justify-content: space-between; align-items: center;
    gap: 12px;
  }
  .loc-context-menu .ctx-item:hover { background: var(--accent-tint-18); color: var(--accent); }
  .loc-context-menu .ctx-item.disabled { color: var(--text-dim); cursor: default; }
  .loc-context-menu .ctx-item.disabled:hover { background: transparent; color: var(--text-dim); }
  .loc-context-menu .ctx-section {
    padding: 6px 12px 4px;
    font-size: 10px; color: var(--text-dim);
    text-transform: uppercase; letter-spacing: 1px; font-weight: 700;
  }
  .loc-context-menu .ctx-sep {
    border-top: 1px solid var(--border);
    margin: 4px 0;
  }
  /* Lane-achtergrond oplichten bij dragover op een hiërarchische lane */
  .lane-bg.drop-target-lane {
    stroke: var(--accent) !important;
    stroke-width: 2.5px !important;
    fill: var(--accent-tint-10) !important;
    filter: drop-shadow(0 0 6px var(--accent-tint-35));
  }
  .lane-bg.drop-blocked {
    stroke: var(--danger) !important;
    stroke-width: 2px !important;
    stroke-dasharray: 6 4 !important;
    fill: var(--danger-tint) !important;
  }
  .node text.name {
    fill: var(--text); font-size: 12px; font-weight: 600;
  }
  .node text.sub {
    fill: var(--text-dim); font-size: 10px;
  }
  .node .status-dot { r: 4; }
  .node .type-chip {
    fill: var(--panel-2); rx: 3; ry: 3;
  }
  .node .type-chip-text { fill: var(--text-dim); font-size: 9px; }

  /* Technology-layer node (pill shape, coloured) */
  .node.tech rect.card {
    stroke-width: 2;
  }
  .node.tech text.name {
    font-size: 13px; letter-spacing: .4px;
    font-weight: 700;
    text-anchor: middle;
  }
  .node.tech text.sub {
    text-anchor: middle;
    font-size: 10px;
  }
  /* Managed-service kaart: zelfde middel-uitlijning als tech-nodes */
  .node.svc text.name {
    font-size: 13px; letter-spacing: .3px;
    font-weight: 700;
    text-anchor: middle;
  }
  .node.svc text.sub {
    text-anchor: middle;
    font-size: 10px;
    fill: var(--text-dim);
  }
  .node.svc, .node.svc * { cursor: pointer; }

  /* v2026-08-22-R — een placeholder moet zichtbaar GEEN waarde zijn.
     De app had hier niets voor, dus koos de browser zijn eigen grijs; in het
     donkere thema is dat nauwelijks van ingevulde tekst te onderscheiden.
     Gevolg: een voorbeeldadres ("Gemaalweg 12, 5301 KX Zaltbommel") las als een
     ingevuld adres (gemeld Martijn 22-08). Cursief + duidelijk lichter maakt
     het verschil ook in één oogopslag zichtbaar. */
  input::placeholder,
  textarea::placeholder {
    color: var(--text-dim);
    opacity: .55;
    font-style: italic;
  }

  /* Status colors */
  .status-Actief { fill: var(--accent-2); }
  .status-Storing { fill: var(--danger); }
  .status-Onderhoud, .status-Waarschuwing { fill: var(--warning); }

  /* Detail panel — staat in grid-kolom 2, samen met #locations-panel
     (alleen één van de twee is tegelijk zichtbaar via display:none) */
  aside { grid-column: 2; grid-row: 1; }
  aside#panel,
  aside#configuraties-panel,
  aside#contacten-panel,
  aside#communicatie-panel,
  aside#sales-panel, /* v2026-07-15-AC: ontbrak — geen scroll op lage resoluties */
  aside#productsales-panel { /* v2026-08-22-N: idem — het detailpaneel liep onderaan uit beeld */
    background: var(--panel); border-left: 1px solid var(--border);
    overflow-y: auto; padding: 0;
  }
  /* v2026-07-21-F — KPI-tegels op het Sales-dashboard staan op één rij van zes.
     Op smallere schermen zou dat te krap worden; dan drie per rij, en onder de
     640px twee. Media-query i.p.v. auto-fit zodat de volgorde herkenbaar blijft. */
  @media (max-width: 980px) {
    .sales-kpi-row { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
  }
  @media (max-width: 640px) {
    .sales-kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  }

  /* v2026-07-21-E — Sales-zijmenu volgt nu de theme-variabelen (was het
     hardcoded donkerblauwe palet van de oude losse Sales-tool). Inactieve items
     staan op --text-dim; deze hover maakt duidelijk dat ze aanklikbaar zijn.
     Het actieve item krijgt z'n stijl inline mee (zie renderSalesSideNav). */
  #sales-sidenav .sales-nav-item { transition: background 0.12s, color 0.12s; }
  #sales-sidenav .sales-nav-item:hover { background: var(--panel); color: var(--text); }

  /* v2026-07-12-B — Contactpersonen-adresboek lijstrijen */
  #contacts-list .contact-row:hover { background: var(--panel-2, var(--panel)); border-color: var(--accent); }

  /* v2026-07-14-C — Kalender/klok-icoon zichtbaar in dark mode voor ÁLLE datum/tijd-
     inputs in de app (niet meer alleen de communicatiemomenten). */
  input[type="date"]::-webkit-calendar-picker-indicator,
  input[type="time"]::-webkit-calendar-picker-indicator,
  input[type="datetime-local"]::-webkit-calendar-picker-indicator,
  input[type="month"]::-webkit-calendar-picker-indicator,
  input[type="week"]::-webkit-calendar-picker-indicator {
    filter: invert(1); opacity: .85; cursor: pointer;
  }
  /* v2026-07-13-B — Communicatie: geplande momenten als sub-items onder de campagne. */
  #campagne-list .cmp-mom-sub:hover { background: var(--panel-2, var(--panel)); border-left-color: var(--accent); }

  /* v2026-07-14-D — Klantcontacten-UI (geadresseerde/ondertekenaar/CC) — gedeeld
     door de calc-modal en het calc-overzicht (calc-contacts-ui.js). */
  .ccui-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px; }
  .ccui-grid.ccui-compact { grid-template-columns: 1fr; gap: 8px; }
  .ccui-slot { border: 1px solid var(--border); border-radius: 6px; padding: 10px 12px; margin-bottom: 12px; }
  .ccui-grid .ccui-slot { margin-bottom: 0; }
  .ccui-slot-title { font-size: 12px; font-weight: 600; margin-bottom: 8px; color: var(--text); }
  .ccui-chip { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border: 1px solid var(--border); border-radius: 5px; background: var(--bg); margin-bottom: 5px; }
  .ccui-chip:last-child { margin-bottom: 0; }
  .ccui-chip-main { flex: 1; font-size: 12px; color: var(--text); }
  .ccui-dim { color: var(--text-dim); }
  .ccui-remove { background: transparent; border: 1px solid var(--border); color: var(--danger); cursor: pointer; padding: 1px 8px; border-radius: 4px; font-size: 12px; line-height: 1.4; }
  .ccui-remove:hover { border-color: var(--danger); }
  /* v2026-08-07-E — ✎ Wijzig op een gevuld slot + annuleren-knop in de picker. */
  .ccui-edit { background: transparent; border: 1px solid var(--border); color: var(--accent); cursor: pointer; padding: 1px 8px; border-radius: 4px; font-size: 12px; line-height: 1.4; }
  .ccui-edit:hover { border-color: var(--accent); }
  .ccui-cancel { background: transparent; border: 1px solid var(--border); color: var(--text-dim); cursor: pointer; padding: 6px 10px; border-radius: 4px; font-size: 12px; line-height: 1.2; flex: 0 0 auto; }
  .ccui-cancel:hover { color: var(--text); border-color: var(--text-dim); }
  .ccui-cc-list { margin-bottom: 6px; }
  .ccui-empty { font-size: 11px; color: var(--text-dim); font-style: italic; margin-bottom: 6px; }
  /* v2026-07-26-G — de eigen zoek-picker (ccui-new/results/res/nores) is
     vervangen door de app-brede ContactPicker; alleen het invoerveld blijft.
     De dropdown + "＋ Nieuw"-regel komen nu uit ContactPicker (eigen styling). */
  .ccui-pick { position: relative; display: flex; gap: 6px; align-items: center; }
  .ccui-search { flex: 1; padding: 6px 8px; border: 1px solid var(--border); border-radius: 5px; background: var(--bg); color: var(--text); font-size: 12.5px; }
  aside .empty {
    padding: 28px 20px; color: var(--text-dim); font-size: 13px;
    line-height: 1.5;
  }
  aside .detail { padding: 20px; }
  aside h2 { font-size: 16px; margin: 0 0 4px 0; }
  aside .sub-id { color: var(--text-dim); font-size: 11px; letter-spacing: .6px; text-transform: uppercase; }
  aside .status-pill {
    display: inline-block; margin-top: 8px;
    padding: 3px 10px; border-radius: 12px; font-size: 11px;
    font-weight: 600;
    background: var(--success-tint);
    color: var(--accent-2);
    border: 1px solid var(--success-border-40);
  }
  aside .status-pill.Storing {
    background: rgba(232, 106, 98, 0.15);
    color: var(--danger);
    border-color: rgba(232, 106, 98, 0.4);
  }
  aside .status-pill.Onderhoud, aside .status-pill.Waarschuwing {
    background: var(--warning-tint);
    color: var(--warning);
    border-color: var(--warning-border-40);
  }
  aside section {
    border-top: 1px solid var(--border);
    padding: 14px 20px;
  }
  aside section h3 {
    font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase;
    color: var(--text-dim); margin: 0 0 10px 0;
  }
  aside .kv { display: grid; grid-template-columns: 110px 1fr; gap: 6px 12px; font-size: 13px; }
  aside .kv .k { color: var(--text-dim); }
  aside .conn-item {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 8px; border-radius: 4px; font-size: 12px;
    cursor: pointer;
  }
  aside .conn-item:hover { background: var(--panel-2); }
  aside .conn-item .arrow { color: var(--text-dim); }
  aside .conn-item .chip {
    font-size: 10px; padding: 2px 6px; border-radius: 3px;
    background: var(--panel-2); color: var(--text-dim);
  }
  aside .tech-badge {
    display: inline-block; padding: 2px 8px; border-radius: 10px;
    font-size: 10px; font-weight: 600; letter-spacing: .3px;
    margin: 2px 4px 2px 0;
    background: var(--hover-bg);
    border: 1px solid var(--border);
  }

  /* Tab bar in de rechter aside */
  .tab-bar {
    display: flex; border-bottom: 1px solid var(--border);
    background: var(--bg-2); position: sticky; top: 0; z-index: 2;
  }
  .tab-btn {
    flex: 1; padding: 10px 8px;
    background: transparent; color: var(--text-dim);
    border: none; border-bottom: 2px solid transparent;
    cursor: pointer; font-size: 12px; font-weight: 600;
    letter-spacing: .4px;
  }
  .tab-btn:hover { color: var(--text); background: var(--panel-2); }
  .tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); }
  .tab-content { display: none; }
  .tab-content.active { display: block; }

  /* Artikelen-lijst */
  .articles-toolbar {
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    display: flex; flex-direction: column; gap: 8px;
  }
  .articles-toolbar .articles-status {
    font-size: 11px; color: var(--text-dim);
  }
  .articles-search {
    width: 100%;
    background: var(--bg); color: var(--text);
    border: 1px solid var(--border); border-radius: 5px;
    padding: 6px 10px; font-size: 12px;
  }
  .articles-empty {
    padding: 30px 20px;
    color: var(--text-dim); font-size: 12px;
    text-align: center; line-height: 1.6;
  }
  .article-group { border-bottom: 1px solid var(--border); }
  .group-header {
    display: flex; align-items: center; gap: 8px;
    padding: 9px 14px; cursor: pointer;
    background: var(--panel); user-select: none;
  }
  .group-header:hover { background: var(--panel-2); }
  .group-header .toggle { color: var(--text-dim); width: 12px; font-size: 12px; }
  .group-header .group-name { flex: 1; font-size: 12px; font-weight: 600; }
  .group-header .group-count {
    font-size: 10px; color: var(--text-dim);
    background: var(--bg); padding: 1px 7px; border-radius: 10px;
  }
  .group-header .group-default-layer {
    font-size: 10px; color: var(--accent);
    background: var(--accent-tint-10);
    padding: 1px 7px; border-radius: 10px;
    white-space: nowrap;
  }
  .group-items { background: var(--bg); padding: 2px 0 6px 0; }
  .article-item {
    padding: 6px 14px 6px 34px;
    font-size: 12px; line-height: 1.4;
    border-top: 1px solid var(--row-stripe);
  }
  .article-item:hover { background: var(--panel); }
  /* Artikel-rij die op dat moment het context-menu open heeft staan: blauwe
     accent-tint + linker-strook zodat duidelijk is welk artikel actief is. */
  .article-item.ctx-target {
    background: var(--accent-tint-18) !important;
    box-shadow: inset 3px 0 0 var(--accent);
  }
  /* Artikel mét Product Definitie: hele rij sleepbaar, grab-cursor overal. */
  .article-item.has-pd,
  .article-item.has-pd .article-name,
  .article-item.has-pd .article-code,
  .article-item.has-pd .article-icon,
  .article-item.has-pd .article-text { cursor: grab; }
  .article-item.has-pd:active { cursor: grabbing; }
  .article-name { color: var(--text); }
  .article-code { color: var(--text-dim); font-size: 10px; margin-top: 2px; }
  /* v2026-05-22-B — Extra omschrijving onder artikel-code; iets dimmer dan de
     code zelf en kursief om duidelijk onderscheid te maken. Truncate gebeurt
     in JS (max 20 chars + ellipsis); volledige tekst via title-tooltip. */
  .article-extra {
    color: var(--text-dim);
    font-size: 10px;
    font-style: italic;
    opacity: 0.75;
    margin-top: 1px;
  }
  .article-item .article-main { display: flex; align-items: center; gap: 8px; }
  .article-item .article-text { flex: 1; min-width: 0; }
  .article-item .article-icon { font-size: 18px; width: 22px; text-align: center; flex-shrink: 0; }
  .article-item .article-handle {
    color: var(--accent); font-weight: 700; cursor: grab;
    user-select: none; padding: 0 4px; flex-shrink: 0;
  }
  .article-item .article-handle:active { cursor: grabbing; }
  .article-item .article-define-btn {
    font-size: 11px; padding: 3px 8px;
    background: transparent; color: var(--text-dim);
    border: 1px solid var(--border); border-radius: 4px;
    cursor: pointer; flex-shrink: 0;
  }
  .article-item .article-define-btn:hover { border-color: var(--accent); color: var(--accent); }
  .article-item .article-define-btn.define { color: var(--accent); border-color: var(--accent-border-40); }
  .article-item.has-pd { background: var(--accent-tint-04); }
  .article-drop-hint {
    outline: 2px dashed var(--accent) !important;
    background: var(--accent-tint-12) !important;
  }
  /* v2026-05-10 BK27 — Configuraties-view styling */
  .cfgview-block {
    margin-bottom: 6px;
    background: var(--bg-2, var(--panel));
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
    transition: box-shadow .12s, border-color .12s;
  }
  .cfgview-block.drop-hover {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-tint-18);
  }
  /* v2026-07-03-C — Configuraties als uitgelijnde tabel: head + kolomkop delen
     dezelfde grid-kolommen zodat alles netjes onder elkaar staat. */
  .cfgview-block .cfg-head,
  .cfgview-colhead {
    display: grid;
    /* v2026-07-03-E — Systeem = checkbox, Slot = icoon → smallere vaste kolommen,
       meer ruimte voor de configuratienaam. */
    grid-template-columns: 14px minmax(0, 1fr) 116px 58px 54px 104px 72px;
    align-items: center;
    gap: 10px;
  }
  .cfgview-block .cfg-head {
    padding: 6px 12px;
    cursor: pointer;
    background: var(--row-stripe);
  }
  .cfgview-block .cfg-head:hover { background: var(--accent-tint-06); }
  .cfgview-colhead {
    padding: 4px 12px 6px 12px;
    font-size: 9.5px; letter-spacing: 0.8px; text-transform: uppercase;
    color: var(--text-dim); border-bottom: 1px solid var(--border);
    margin-bottom: 6px;
  }
  .cfgview-block .cfg-col-price,
  .cfgview-colhead .cfg-col-price { text-align: right; white-space: nowrap; }
  .cfgview-block .cfg-col-actions,
  .cfgview-colhead .cfg-col-actions { display: flex; gap: 6px; justify-content: flex-end; }
  .cfgview-block .cfg-col-type,
  .cfgview-block .cfg-col-system,
  .cfgview-block .cfg-col-lock { display: flex; align-items: center; min-width: 0; }
  .cfgview-block .cfg-icon-btn {
    width: 28px; height: 26px; padding: 0; display: inline-flex;
    align-items: center; justify-content: center; font-size: 13px; line-height: 1;
    border-radius: 5px; cursor: pointer; background: transparent;
  }
  .cfgview-block .cfg-body { padding: 0 14px 12px 14px; }
  .cfgview-items-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
    margin-top: 8px;
    /* v2026-05-14 BL11 — fixed layout zodat kolombreedtes van álle tabellen
       gelijk lopen, ongeacht de lengte van product-namen. */
    table-layout: fixed;
  }
  .cfgview-items-table td:first-child { word-break: break-word; }
  .cfgview-items-table th {
    text-align: left;
    font-weight: 600;
    color: var(--text-dim);
    text-transform: uppercase;
    font-size: 10px;
    letter-spacing: 1px;
    padding: 6px 8px;
    border-bottom: 1px solid var(--border);
  }
  .cfgview-items-table td {
    padding: 7px 8px;
    border-bottom: 1px solid var(--hover-bg);
    vertical-align: middle;
  }
  .cfgview-items-table tr:hover td { background: var(--row-stripe); }
  .cfgview-items-table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
  .cfgview-dropzone {
    margin-top: 8px;
    padding: 10px 12px;
    border: 1px dashed var(--border);
    border-radius: 5px;
    color: var(--text-dim);
    font-size: 11px;
    font-style: italic;
    text-align: center;
  }
  .cfgview-block.drop-hover .cfgview-dropzone {
    border-color: var(--accent);
    color: var(--accent);
    background: var(--accent-tint-06);
  }
  /* Catalogus rechts in cfgview */
  #cfgview-right .cfgview-cat-row {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 8px;
    border-radius: 5px;
    cursor: grab;
    border: 1px solid transparent;
  }
  #cfgview-right .cfgview-cat-row:hover {
    background: var(--accent-tint-06);
    border-color: var(--accent-border-30);
  }
  #cfgview-right .cfgview-cat-row:active { cursor: grabbing; }
  #cfgview-right .cfgview-cat-row.no-pd { cursor: not-allowed; opacity: 0.55; }
  /* Zoom controls */
  .zoom-controls {
    position: absolute; right: 16px; bottom: 16px;
    display: flex; flex-direction: column; gap: 4px;
    background: var(--panel); border: 1px solid var(--border);
    border-radius: 6px; padding: 4px;
  }
  .zoom-controls button {
    width: 30px; height: 30px;
    background: transparent; color: var(--text);
    border: none; font-size: 16px; cursor: pointer;
    border-radius: 4px;
  }
  .zoom-controls button:hover { background: var(--panel-2); }
  .legend {
    position: absolute; left: 16px; bottom: 16px;
    background: var(--panel); border: 1px solid var(--border);
    border-radius: 6px; padding: 10px 14px;
    display: flex; gap: 14px; font-size: 11px;
    color: var(--text-dim);
    flex-wrap: wrap; max-width: 60%;
  }
  .legend .item { display: flex; align-items: center; gap: 6px; }
  .legend .dot { width: 8px; height: 8px; border-radius: 50%; }
  .legend .sep { width: 1px; height: 14px; background: var(--border); }

  /* Topbar primary button */
  .top-primary {
    background: var(--accent); color: var(--text-on-accent); border: none;
    border-radius: 6px; padding: 7px 14px; font-size: 13px;
    font-weight: 600; cursor: pointer;
  }
  .top-primary:hover { background: var(--accent); }
  header .spacer { flex: 1; }

  /* Topbar dropdown-menu (Nieuw ▾) */
  .topbar-menu { position: relative; display: inline-block; }
  /* ET: alle menu-knoppen even breed zodat ze visueel uitgelijnd zijn. */
  .topbar-menu-btn {
    /* v2026-07-21-F — 110→88px: de labels (Export/Beheer/Help) zijn kort. */
    min-width: 88px;
    text-align: left;
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
  }
  .topbar-menu-btn .caret {
    font-size: 9px;
    color: var(--text-dim);
    margin-left: 2px;
    transition: transform .15s, color .15s;
    display: inline-block;
  }
  .topbar-menu.open .topbar-menu-btn .caret {
    transform: rotate(180deg);
    color: var(--accent);
  }
  .topbar-menu.open .topbar-menu-btn {
    background: var(--accent-tint-18);
    border-color: var(--accent);
    color: var(--accent);
  }
  .topbar-menu-list {
    position: absolute;
    top: 100%; left: 0;
    margin-top: 4px;
    min-width: 180px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: var(--shadow-modal);
    padding: 4px;
    display: none;
    flex-direction: column;
    z-index: 10;       /* lokaal: .topbar is zelf een stacking context (--z-header) */
  }
  .topbar-menu.open .topbar-menu-list { display: flex; }
  .topbar-menu-item {
    background: transparent;
    color: var(--text);
    border: 0;
    padding: 8px 12px;
    text-align: left;
    font-size: 12px;
    font-weight: 500;
    border-radius: 4px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    transition: background .12s, color .12s;
  }
  .topbar-menu-item:hover {
    background: var(--accent-tint-18);
    color: var(--accent);
  }
  /* BK14: submenu (side-out) — verschijnt rechts van het parent-item op hover. */
  .topbar-submenu-parent { position: relative; }
  .topbar-submenu {
    position: absolute;
    top: -4px;
    left: 100%;
    margin-left: 6px;
    min-width: 200px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: var(--shadow-modal);
    padding: 4px;
    display: none;
    flex-direction: column;
    z-index: 11;       /* lokaal, boven .topbar-menu-list */
  }
  .topbar-submenu-parent:hover > .topbar-submenu,
  .topbar-submenu-parent:focus-within > .topbar-submenu { display: flex; }

  /* View-switch (tab-stijl) in topbar — wisselen tussen Map / WS Products /
     WS Locations. Knoppen hebben dezelfde breedte zodat het visueel als
     drie identieke drukknoppen oogt. */
  .view-switch {
    display: inline-flex;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 2px;
    gap: 2px;
  }
  .view-btn {
    background: transparent;
    color: var(--text-dim);
    border: 0;
    padding: 5px 11px;
    /* v2026-07-21-F — min-width:124px verwijderd. Die stamt uit BK27, toen er
       vier view-knoppen waren en gelijke breedte netjes stond. Met zeven views
       kostte het 868px aan minimumbreedte en klapte de balk om op kleinere
       schermen. Natuurlijke breedte + iets meer letterruimte leest net zo
       rustig en scheelt zo'n 300px. */
    text-align: center;
    white-space: nowrap;       /* geen tekst-wrap */
    font-size: 12px;
    font-weight: 600;
    border-radius: 4px;
    cursor: pointer;
    transition: background .15s, color .15s;
  }
  .view-btn:hover { color: var(--text); }
  .view-btn.active {
    background: var(--accent-tint-18);
    color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent-tint-35);
  }

  /* Leaflet-tegels op donkere achtergrond een tikkeltje verzachten zodat
     de OCC-app-look bewaard blijft. */
  #leaflet-map { filter: brightness(0.92) saturate(0.85); }

  /* ---------- View-switch container-morph ---------- */
  /* Beide views krimpen/groeien vanuit hetzelfde focuspunt (knop of pin),
     met blur, opacity en border-radius die meeanimatieren — de oude view
     "verfrommelt" tot een kleine bal op dat punt en de nieuwe view explodeert
     er weer uit. Voelt als een continue morph i.p.v. twee losse animaties. */
  .view-morph-out {
    transition:
      transform 0.55s cubic-bezier(0.7, 0, 0.84, 0),
      filter 0.55s cubic-bezier(0.7, 0, 0.84, 0),
      opacity 0.45s ease 0.10s,
      border-radius 0.55s cubic-bezier(0.7, 0, 0.84, 0);
    will-change: transform, filter, opacity, border-radius;
  }
  .view-morph-in {
    transition:
      transform 0.65s cubic-bezier(0.16, 1, 0.3, 1),
      filter 0.65s cubic-bezier(0.16, 1, 0.3, 1),
      opacity 0.55s ease,
      border-radius 0.65s cubic-bezier(0.16, 1, 0.3, 1);
    will-change: transform, filter, opacity, border-radius;
  }
  /* Tijdens de morph een glow-aura rond het focuspunt — "the view collapses
     into this glowing point" — geeft de transitie het echte morph-gevoel. */
  .view-morph-glow {
    position: fixed;
    pointer-events: none;
    z-index: var(--z-morph);
    width: 12px; height: 12px;
    transform: translate(-50%, -50%) scale(1);
    border-radius: 50%;
    /* v2026-05-23-I — radial gradient verwijderd; solid accent met box-shadow-glow voor click-ripple */
    background: var(--accent);
    box-shadow:
      0 0 60px 10px var(--accent),
      0 0 140px 20px var(--accent);
    opacity: 0;
    transition:
      transform 0.55s cubic-bezier(0.16, 1, 0.3, 1),
      opacity 0.45s ease;
  }
  .view-morph-glow.expand { transform: translate(-50%, -50%) scale(35); opacity: 0.85; }
  .view-morph-glow.fade   { opacity: 0; }
  .leaflet-popup-content-wrapper {
    background: var(--panel) !important;
    color: var(--text) !important;
    border: 1px solid var(--border);
  }
  .leaflet-popup-tip { background: var(--panel) !important; }
  .leaflet-popup-content { font-size: 12px; line-height: 1.5; }
  .leaflet-popup-content strong { color: var(--accent); }
  /* WS-Design: assets-aside zit in dezelfde grid-kolom als #panel zodat
     hij automatisch dezelfde breedte (var(--panel-width)) en positie krijgt. */
  #locations-panel,
  #map-panel,
  #organisations-panel,
  /* v2026-06-05-H — calculations-panel ontbrak hier; daardoor was het géén
     hoogte-begrensde flex-kolom en kon het Overzicht-paneel (overflow-y:auto)
     niet scrollen na de DOM-move van de orgs-side-panes. */
  #calculations-panel {
    background: var(--bg-2);
    border-left: 1px solid var(--border);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    grid-column: 2;
    grid-row: 1;
    height: 100%;
  }
  /* WS-Design hoofdkolom: gebouw + verdiepingen */
  .building-header {
    display: flex; align-items: center; gap: 12px;
    margin-bottom: 16px;
  }
  .building-header h3 {
    margin: 0; font-size: 14px; font-weight: 700; color: var(--text);
    letter-spacing: 0.3px;
  }
  .building-header .sub { color: var(--text-dim); font-size: 12px; }
  .floor-card {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 10px;
    margin-bottom: 10px;
    box-shadow: var(--shadow-floating);
    overflow: hidden;
  }
  .floor-card .floor-title {
    display: flex; justify-content: space-between; align-items: center;
    padding: 12px 16px;
    cursor: pointer;
    user-select: none;
    transition: background .15s;
  }
  .floor-card .floor-title:hover { background: var(--panel-2); }
  .floor-card .floor-title .name {
    font-size: 14px; font-weight: 700; color: var(--text);
    letter-spacing: 0.3px;
    display: flex; align-items: center; gap: 10px;
  }
  .floor-card .floor-title .chev {
    color: var(--text-dim);
    font-size: 11px;
    width: 14px;
    transition: transform .2s ease;
    display: inline-block;
  }
  .floor-card.expanded .floor-title .chev { transform: rotate(90deg); }
  .floor-card .floor-title .count {
    font-size: 11px; color: var(--text-dim);
    text-transform: uppercase; letter-spacing: 1px; font-weight: 600;
  }
  .floor-card .floor-body {
    display: none;
    padding: 14px 16px 16px;
    border-top: 1px solid var(--border);
  }
  .floor-card.expanded .floor-body { display: block; }
  /* Plattegrond-slot — full width binnen de body, max-height ruim om hoge
     resolutie ten volle te tonen */
  .floor-plan {
    position: relative;
    width: 100%;
    min-height: 420px;
    background: var(--bg);
    border: 1px dashed var(--border);
    border-radius: 8px;
    overflow: hidden;
    display: flex; align-items: center; justify-content: center;
  }
  .floor-plan.has-image { border-style: solid; border-color: var(--border); }
  .floor-plan img {
    width: 100%; height: auto; max-height: 80vh;
    object-fit: contain;
    display: block; background: #fff;
    pointer-events: none;
    /* Hint aan de browser om bij downscalen/upscalen
       hoge-kwaliteits-resampling te gebruiken zodat technische tekenlijnen
       crisp blijven. */
    image-rendering: auto;
    image-rendering: -webkit-optimize-contrast;
  }
  /* Geen visuele highlight op de plattegrond tijdens drop —
     de drag-image (rondje) bij de cursor is voldoende feedback. */
  /* Marker voor een geplaatste locatie — blauw rondje met permanent
     label dat naam + type toont. Klik op het rondje of het label opent
     een edit-modal voor de locatie-eigenschappen. */
  .floor-plan-marker {
    position: absolute;
    transform: translate(-50%, -50%);
    width: 16px; height: 16px;
    z-index: 5;
    cursor: pointer;
  }
  .floor-plan-marker::before {
    content: "";
    position: absolute;
    left: 0; top: 0;
    width: 16px; height: 16px;
    border-radius: 50%;
    background: var(--accent);
    border: 2px solid var(--map-marker-stroke);
    box-shadow: 0 0 0 2px var(--accent-border-45), var(--shadow-marker);
    transition: transform .12s;
  }
  .floor-plan-marker:hover::before { transform: scale(1.25); }
  .floor-plan-marker .label {
    position: absolute;
    left: 18px; top: 50%;
    transform: translateY(-50%);
    background: var(--tooltip-bg);
    color: var(--text);
    padding: 4px 8px;
    border-radius: 4px;
    border: 1px solid var(--border);
    box-shadow: var(--shadow-tooltip);
    font-size: 11px;
    line-height: 1.25;
    white-space: nowrap;
    cursor: pointer;
  }
  .floor-plan-marker .label .m-name {
    color: var(--text); font-weight: 700;
  }
  .floor-plan-marker .label .m-type {
    color: var(--text-dim);
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 600;
    margin-top: 1px;
  }
  /* Klein × knopje rechtsboven voor "verwijder van plattegrond" — verschijnt
     bij hover op de marker, wist alléén de positie (locatie blijft bestaan). */
  .floor-plan-marker .m-remove {
    position: absolute;
    left: -8px; top: -8px;
    width: 16px; height: 16px;
    border-radius: 50%;
    border: 1px solid var(--map-marker-stroke);
    background: var(--danger);
    color: var(--map-marker-text);
    font-size: 11px; line-height: 1;
    font-weight: 700;
    padding: 0;
    cursor: pointer;
    display: none;
    box-shadow: var(--shadow-marker);
  }
  .floor-plan-marker:hover .m-remove { display: block; }
  .floor-plan-marker .m-remove:hover { filter: brightness(1.15); }
  /* Long-press → drag-modus: visuele feedback dat de marker "los" zit */
  .floor-plan-marker.armed::before {
    transform: scale(1.35);
    box-shadow: 0 0 0 3px var(--map-marker-stroke),
                0 0 0 6px var(--accent-glow),
                0 6px 14px var(--bg-overlay);
    animation: marker-pulse 1.2s ease-in-out infinite;
  }
  .floor-plan-marker.dragging-marker {
    cursor: grabbing;
    z-index: 10;
    transition: none;
  }
  .floor-plan-marker.dragging-marker::before {
    transform: scale(1.5);
    box-shadow: 0 0 0 3px var(--map-marker-stroke),
                0 0 0 6px var(--accent),
                var(--shadow-deep);
    animation: none;
  }
  .floor-plan-marker.dragging-marker .label { opacity: 0.6; }
  /* Apparaat-markers rondom een locatie-marker.
     Klein rond icoon-knopje. Naam verschijnt alleen bij hover als tooltip
     onder de marker. Sleepbaar; laatste positie wordt opgeslagen in
     state.floorplans[floor].devicePositions. */
  .floor-device-marker {
    position: absolute;
    transform: translate(-50%, -50%);
    width: 28px; height: 28px;
    border-radius: 50%;
    background: var(--tooltip-bg);
    border: 1.5px solid var(--accent);
    color: var(--text);
    cursor: grab;
    user-select: none;
    z-index: 5;
    box-shadow: var(--shadow-tooltip);
    transition: transform 0.12s ease, border-color 0.12s, box-shadow 0.12s;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .floor-device-marker .dev-icon {
    pointer-events: none;
    width: 18px; height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    line-height: 1;
    color: var(--text);
  }
  .floor-device-marker .dev-icon svg {
    width: 100%; height: 100%;
    color: inherit;
    fill: none;
    stroke: currentColor;
  }
  .floor-device-marker:hover {
    transform: translate(-50%, -50%) scale(1.18);
    z-index: 12;
    border-color: var(--accent-2);
    box-shadow: 0 4px 12px rgba(91,198,138,0.45);
  }
  .floor-device-marker.dragging-dev {
    cursor: grabbing;
    z-index: 20;
    transform: translate(-50%, -50%) scale(1.3);
    border-color: var(--map-marker-stroke);
    box-shadow: 0 0 0 2px var(--accent-glow), var(--shadow-deep);
    /* Tijdens drag uit: anders interpoleert de browser de scale-up én onze
       JS left/top tegelijk → eerste 100ms voelt schokkerig totdat de
       transition is afgelopen. Direct snappen geeft een vloeiende start. */
    transition: none;
  }
  .floor-device-marker.dragging-dev .dev-tip { transition: none; }
  .floor-device-marker.unlinked {
    opacity: 0.55;
    border-color: var(--text-dim);
    border-style: dashed;
  }
  /* SVG-overlay over de plattegrond met dunne verbindingslijntjes van elke
     apparaat-marker naar de locatie-pin. Pointer-events uit zodat ze niet
     in de weg zitten van slepen of klikken. */
  .floor-plan-links {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    pointer-events: none;
    z-index: 2;
    overflow: visible;
  }
  /* Twee lagen per lijn voor maximaal contrast op een willekeurige
     plattegrond-achtergrond:
     - .halo  : witte halo (achterste laag)
     - .core  : duidelijke blauwe stippellijn (voorste laag) */
  .floor-plan-links line.halo {
    stroke: rgba(255,255,255,0.85);
    stroke-width: 3;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
  }
  .floor-plan-links line.core {
    stroke: #1f6f9b;
    stroke-width: 1.6;
    stroke-dasharray: 5 4;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
  }
  .floor-plan-links line.core.highlighted {
    stroke: #2aa564;
    stroke-width: 2;
    stroke-dasharray: 0;
  }
  /* Apparaat→apparaat audio-verbinding (microfoon op gateway audio-poort).
     Subtieler dan de location-link-lijntjes: dunner, fijnere stippels en een
     warme bronzen kleur zodat je in één oogopslag ziet dat dit een ander
     soort verbinding is. Halo iets transparanter — bedoeld om op witte plus
     donkere achtergronden leesbaar te blijven zonder te schreeuwen. */
  .floor-plan-links line.audio-halo {
    stroke: rgba(255,255,255,0.7);
    stroke-width: 2.4;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
  }
  .floor-plan-links line.audio-core {
    stroke: #b87a3a;
    stroke-width: 1.1;
    stroke-dasharray: 1.6 2.4;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
    opacity: 0.9;
  }
  /* Mic↔speaker pairing — een fysiek kort kabeltje, geen UTP. We tekenen
     het als een korte donkergrijze doorlopende lijn (geen stippels), net
     dik genoeg om zichtbaar te zijn maar dunner dan de UTP-Audio-lijnen.
     Bewust géén label, want het is "fysiek aan elkaar". */
  .floor-plan-links line.pair-halo {
    stroke: rgba(255,255,255,0.6);
    stroke-width: 2.2;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
  }
  .floor-plan-links line.pair-core {
    stroke: var(--text-dim);
    stroke-width: 1.3;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
    opacity: 0.85;
  }
  /* Het label "UTP - Audio" als HTML-laag — preserveAspectRatio="none" op de
     SVG zou tekst vervormen, en HTML-tekst staat sowieso scherper. We zetten
     'm op het midden van de lijn met een kleine rotatie zodat hij meeloopt. */
  .floor-plan .audio-link-label {
    position: absolute;
    transform-origin: 50% 50%;
    transform: translate(-50%, -50%) rotate(var(--ang, 0deg));
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    font-size: 9px;
    font-weight: 500;
    letter-spacing: 0.3px;
    color: var(--node-text-glow);
    text-shadow: var(--shadow-text-stroke);
    pointer-events: none;
    user-select: none;
    white-space: nowrap;
    z-index: 3;
    padding: 0 3px;
    background: var(--node-icon-fill);
    border-radius: 2px;
    backdrop-filter: blur(1px);
  }
  /* SVG-overlay voor zone-polygonen (locatietype-vakken). Onder de
     verbindingslijntjes zodat lijnen + markers er bovenop blijven liggen. */
  .floor-plan-zones {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    pointer-events: none;     /* click-doorlatend, behalve op zones zelf */
    z-index: 1;
    overflow: visible;
  }
  .floor-plan-zones polygon.zone {
    fill-opacity: 0.22;
    stroke-width: 1.5;
    vector-effect: non-scaling-stroke;
    pointer-events: auto;
    cursor: pointer;
    transition: fill-opacity .15s, stroke-width .15s;
  }
  .floor-plan-zones polygon.zone:hover { fill-opacity: 0.38; stroke-width: 2.5; }
  .floor-plan-zones polygon.zone.selected {
    fill-opacity: 0.45;
    stroke-width: 3;
    stroke-dasharray: 0;
  }
  /* Zone-labels staan als HTML-pillen bovenop de plattegrond zodat ze
     dezelfde styling delen met de Locatie-markers — auto-sizing op tekst,
     scherpe SVG-tekst geeft te weinig achtergrond-contrast op willekeurige
     plattegronden. */
  .floor-plan-zone-labels {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    pointer-events: none;
    z-index: 2;        /* boven zones, onder markers */
    overflow: visible;
  }
  .floor-plan-zone-labels .zone-label-pill {
    position: absolute;
    transform: translate(-50%, -50%);
    background: var(--tooltip-bg);
    color: var(--text);
    padding: 4px 8px;
    border-radius: 4px;
    border: 1px solid var(--border);
    box-shadow: var(--shadow-tooltip);
    font-size: 11px;
    line-height: 1.25;
    font-weight: 700;
    white-space: nowrap;
    pointer-events: none;
    text-align: center;
  }
  .floor-plan-zone-labels .zone-label-pill .zl-type {
    display: block;
    color: var(--text-dim);
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 600;
    margin-top: 1px;
  }
  /* Live-preview tijdens tekenen */
  .floor-plan-zones polyline.draw-preview {
    fill: none;
    stroke: var(--accent);
    stroke-width: 2;
    stroke-dasharray: 5 4;
    vector-effect: non-scaling-stroke;
  }
  .floor-plan-zones circle.draw-vertex {
    fill: var(--accent);
    stroke: #ffffff;
    stroke-width: 2;
    r: 4;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
  }
  /* Eerste hoekpunt is groter zodat duidelijk is dat 't 't startpunt is. */
  .floor-plan-zones circle.draw-vertex.start {
    fill: #ffffff;
    stroke: var(--accent);
    stroke-width: 3;
    r: 5;
  }
  /* Bij snap-detectie: groene fill om visueel te bevestigen dat klik zal sluiten. */
  .floor-plan-zones circle.draw-vertex.start.snap {
    fill: var(--accent-2);
    stroke: #ffffff;
    stroke-width: 2.5;
    r: 6;
  }
  /* Halo rondom 't startpunt tijdens snap — geeft een "klik hier" cue. */
  .floor-plan-zones circle.draw-start-halo {
    fill: rgba(91,198,138,0.25);
    stroke: rgba(91,198,138,0.6);
    stroke-width: 2;
    r: 11;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
    animation: pulse-snap 1s ease-in-out infinite;
  }
  @keyframes pulse-snap {
    0%, 100% { r: 10; opacity: 0.7; }
    50%      { r: 13; opacity: 1.0; }
  }
  /* Cursor binnen de plattegrond als drawmode actief is */
  .floor-plan.draw-mode { cursor: crosshair; }
  .floor-plan.draw-mode .floor-plan-zones { pointer-events: auto; }
  .floor-plan-toolbar {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
  }
  .floor-plan-toolbar .draw-btn {
    font-size: 11px;
    padding: 4px 10px;
    background: transparent;
    color: var(--text-dim);
    border: 1px solid var(--border);
    border-radius: 4px;
    cursor: pointer;
  }
  .floor-plan-toolbar .draw-btn.active {
    background: var(--accent-2-tint-18);
    color: var(--accent);
    border-color: var(--accent);
  }
  /* Legenda van locatietypen op de plattegrond — visueel identiek aan
     .floor-plan-actions buttons (zelfde achtergrond, border, padding,
     border-radius, blur), zodat 't paneel naadloos aansluit op de toolbar.
     Plaatsing onder de toolbar zodat 'ie niet over de knoppen valt. */
  .floor-plan-legend {
    position: absolute;
    top: 44px;       /* 8px toolbar-top + ~28px button-hoogte + 8px gap */
    right: 8px;
    z-index: 6;
    background: var(--tooltip-bg);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 4px 8px;
    font-size: 11px;
    backdrop-filter: blur(4px);
    min-width: 150px;
    max-width: 240px;
    max-height: calc(100% - 60px);
    overflow: auto;
    user-select: none;
    -webkit-user-select: none;
  }
  .floor-plan-legend .fpl-header {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    color: var(--text-dim);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.4px;
    margin: 0;
    padding: 0;
    transition: color .12s;
  }
  .floor-plan-legend .fpl-header:hover { color: var(--accent); }
  .floor-plan-legend .fpl-chev {
    display: inline-block;
    width: 10px;
    text-align: center;
    color: var(--text-dim);
    font-size: 9px;
    transition: transform .15s ease;
    flex-shrink: 0;
  }
  .floor-plan-legend.is-collapsed .fpl-chev { transform: rotate(-90deg); }
  .floor-plan-legend.is-collapsed .fpl-body { display: none; }
  .floor-plan-legend.is-collapsed {
    padding: 4px 8px;
    min-width: 0;
  }
  .floor-plan-legend .fpl-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid var(--border);
  }
  .floor-plan-legend .fpl-row {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    color: var(--text);
  }
  .floor-plan-legend .fpl-swatch {
    display: inline-block;
    width: 11px;
    height: 11px;
    border-radius: 2px;
    flex-shrink: 0;
    border: 1px solid var(--tooltip-border);
  }
  .floor-plan-legend .fpl-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .floor-plan-legend .fpl-count { color: var(--text-dim); font-size: 10px; flex-shrink: 0; }
  /* Sectie-koppen in de Calculatie-modal — visuele scheider tussen de
     6 logische blokken (Basisgegevens / Klant / Project / Kosten / Korting / Opties). */
  .modal-body .calc-section-title {
    font-size: 11px;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 700;
    margin: 18px 0 8px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--border);
  }
  .modal-body .calc-section-title:first-child { margin-top: 0; }

  /* Compact samenvatting-vakje binnen Calculatie-modal — visueel
     consistent met de top-vak in WS-Products → Samenvatting. */
  .modal-body .calc-stat {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px 10px;
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .modal-body .calc-stat-label {
    font-size: 10px;
    color: var(--text-dim);
    letter-spacing: 0.6px;
    text-transform: uppercase;
    font-weight: 600;
  }
  .modal-body .calc-stat-value {
    font-size: 18px;
    font-weight: 700;
    color: var(--text);
  }
  .modal-body .calc-stat-total {
    background: var(--accent-2-tint-10);
    border: 1px solid var(--accent);
    border-radius: 6px;
    padding: 10px 12px;
    margin-top: 4px;
  }
  .modal-body .calc-stat-value-big {
    font-size: 20px;
    font-weight: 700;
    color: var(--accent);
    margin-top: 2px;
  }
  /* Eigen tooltip onder de marker — verschijnt direct bij hover (sneller dan
     het browser-title-tooltip) en blijft tijdens slepen ook zichtbaar. */
  .floor-device-marker .dev-tip {
    position: absolute;
    top: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--tooltip-bg-strong);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 3px 8px;
    font-size: 10.5px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--text);
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.1s;
    z-index: 25;
    box-shadow: var(--shadow-tooltip);
  }
  .floor-device-marker .dev-tip .dev-tip-sub {
    color: var(--text-dim);
    font-weight: 400;
    margin-left: 4px;
  }
  .floor-device-marker:hover .dev-tip,
  .floor-device-marker.dragging-dev .dev-tip {
    opacity: 1;
  }
  @keyframes marker-pulse {
    0%, 100% { box-shadow: 0 0 0 3px var(--map-marker-stroke),
                            0 0 0 6px var(--accent-glow),
                            0 6px 14px var(--bg-overlay); }
    50%      { box-shadow: 0 0 0 3px var(--map-marker-stroke),
                            0 0 0 10px var(--accent-tint-25),
                            0 6px 14px var(--bg-overlay); }
  }
  /* v2026-05-16-BN05/BN06/BN08 — Workspaces met een lopende "Offerte"-calc
     krijgen op de Map-view een echte "ripple"-pulse: een uitdijende oranje
     halo-ring (gerenderd als HTML divIcon, niet SVG, voor cross-browser
     consistentie) plus een subtiele schaal-pulse op de marker zelf.
     BN08-fix: BN06 gebruikte SVG-circleMarker + transform-box: fill-box voor
     de halo, maar dat schaalde in sommige browsers vanuit de SVG-origin
     i.p.v. het marker-center → halo wegschuift, visueel onzichtbaar.
     Nu via een HTML-div in een L.divIcon — transform werkt daar correct uit
     de eigen midden van het element. */
  @keyframes ws-marker-offerte-pulse-anim {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.25); }
  }
  .leaflet-interactive.ws-marker-offerte-pulse {
    animation: ws-marker-offerte-pulse-anim 1.6s ease-in-out infinite;
    transform-box: fill-box;
    transform-origin: center;
  }
  /* HTML divIcon halo — geen Leaflet-default background/border. BN09: dubbele
     radar-ring (::before + ::after met 0.9 s delay) zodat er altijd een ring
     onderweg is, plus een grotere container (80 px) en dikkere oranje border
     met glow zodat de pulse opvalt tussen 700+ rode Zorgorganisatie-markers
     op een uitgezoomde NL-view. */
  .ws-marker-offerte-halo-icon {
    background: transparent !important;
    border: 0 !important;
    pointer-events: none;
  }
  .ws-marker-offerte-halo-ring {
    position: relative;
    width: 80px;
    height: 80px;
  }
  .ws-marker-offerte-halo-ring::before,
  .ws-marker-offerte-halo-ring::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 3px solid var(--warning-strong);
    box-shadow: 0 0 8px 2px var(--warning-border-40),
                inset 0 0 6px var(--warning-border-40);
    animation: ws-marker-offerte-halo-anim 1.8s ease-out infinite;
  }
  .ws-marker-offerte-halo-ring::after {
    animation-delay: 0.9s;
  }
  @keyframes ws-marker-offerte-halo-anim {
    0%   { transform: scale(0.2); opacity: 1;   border-width: 4px; }
    80%  {                         opacity: 0.15; }
    100% { transform: scale(1);   opacity: 0;   border-width: 1px; }
  }
  .floor-plan-empty {
    text-align: center; padding: 18px;
    color: var(--text-dim); font-size: 12px;
  }
  .floor-plan-actions {
    position: absolute;
    top: 8px; right: 8px;
    display: flex; gap: 4px;
    align-items: center;
    z-index: 6;
  }
  .floor-plan-actions button {
    background: var(--tooltip-bg);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 4px 8px;
    font-size: 11px;
    cursor: pointer;
    backdrop-filter: blur(4px);
  }
  .floor-plan-actions button:hover { border-color: var(--accent); color: var(--accent); }
  /* Lijst van niet-toegewezen apparaten in de Locations-tab van de aside. */
  .unassigned-dev-row {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 8px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 5px;
    cursor: grab;
    user-select: none;
    transition: border-color 0.12s, background 0.12s;
  }
  .unassigned-dev-row:hover {
    border-color: var(--accent);
    background: var(--accent-tint-08);
  }
  .unassigned-dev-row:active { cursor: grabbing; }
  .unassigned-dev-row .ud-icon {
    flex-shrink: 0;
    width: 22px; height: 22px;
    display: flex; align-items: center; justify-content: center;
    background: var(--tooltip-bg);
    border: 1px solid var(--border);
    border-radius: 50%;
    font-size: 13px;
  }
  .unassigned-dev-row .ud-icon svg {
    width: 14px; height: 14px;
    fill: none; stroke: currentColor; color: var(--accent);
  }
  .unassigned-dev-row .ud-text {
    flex: 1; min-width: 0;
    overflow: hidden;
  }
  .unassigned-dev-row .ud-name {
    font-size: 12px; font-weight: 600; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .unassigned-dev-row .ud-sub {
    font-size: 10px; color: var(--text-dim);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .unassigned-dev-row .ud-handle {
    flex-shrink: 0; color: var(--text-dim); font-size: 11px;
    padding-right: 2px;
  }
  /* Drop-target highlight op de plattegrond tijdens slepen van een
     niet-toegewezen apparaat. Subtiele blauwe gloed zodat de gebruiker
     weet dat dit het juiste droppoint is. */
  .floor-plan.dev-drop-active::after {
    content: "";
    position: absolute; inset: 0;
    border: 2px dashed var(--accent);
    border-radius: inherit;
    background: var(--accent-tint-08);
    pointer-events: none;
    z-index: 8;
  }
  /* Filenaam-pil rechtsboven op de plattegrond — herkenbaar bij meerdere
     verdiepingen en plattegronden welke versie/file er actief is. */
  .floor-plan-filename {
    background: var(--tooltip-bg);
    color: var(--text-dim);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 4px 9px;
    font-size: 11px;
    font-family: ui-monospace, Menlo, "SF Mono", Consolas, monospace;
    max-width: 280px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    backdrop-filter: blur(4px);
  }
  .floor-plan-filename strong {
    color: var(--text);
    font-weight: 600;
  }
  .floor-plan-filename .pg {
    color: var(--accent);
    margin-left: 4px;
    font-weight: 700;
  }
  /* Locatie-lijst rechts */
  .floor-locs {
    display: flex; flex-direction: column; gap: 6px;
  }
  .floor-locs-header {
    font-size: 10px; color: var(--text-dim);
    text-transform: uppercase; letter-spacing: 1px; font-weight: 700;
    margin-bottom: 4px;
  }
  .floor-loc-row {
    display: grid;
    grid-template-columns: auto 1fr auto auto;
    gap: 8px;
    align-items: baseline;
    padding: 6px 10px;
    background: var(--panel-2);
    border-radius: 4px;
    font-size: 12px;
    cursor: grab;
    transition: background .12s, border-color .12s;
    border: 1px solid transparent;
  }
  .floor-loc-row:hover { background: var(--panel); border-color: var(--border); }
  .floor-loc-row:active { cursor: grabbing; }
  /* Tijdens slepen geen kleurwijziging — alleen de drag-image (rondje) is
     visuele feedback dat je sleept; de bron-rij blijft ongewijzigd. */
  .floor-loc-row.placed { background: var(--accent-tint-10); border-color: var(--accent-tint-35); }
  .floor-loc-row .loc-type {
    font-size: 10px;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 600;
  }
  .floor-loc-row .loc-name { color: var(--text); }
  .floor-loc-row .loc-check {
    color: var(--accent-2);
    font-size: 13px;
    font-weight: 700;
    width: 14px;
    text-align: center;
  }
  .floor-loc-row .loc-devices { color: var(--text-dim); font-size: 11px; }

  /* Crop-modal: full-screen overlay met PDF-canvas en sleep-rectangle */
  #crop-modal {
    position: fixed; inset: 0;
    background: var(--map-mask-strong);
    z-index: var(--z-overlay);
    display: none; align-items: stretch; justify-content: stretch;
  }
  #crop-modal.open { display: flex; }
  .crop-dialog {
    position: relative;
    margin: auto;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: var(--shadow-deep);
    max-width: 92vw;
    max-height: 92vh;
    display: flex; flex-direction: column;
    overflow: hidden;
  }
  .crop-header {
    display: flex; justify-content: space-between; align-items: center;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-2);
  }
  .crop-header h2 { margin: 0; font-size: 14px; color: var(--text); font-weight: 700; }
  .crop-header .sub { font-size: 11px; color: var(--text-dim); }
  .crop-body {
    position: relative;
    flex: 1; overflow: auto;
    padding: 18px;
    background: var(--bg);
    display: flex;
    /* `safe` valt terug op start-uitlijning zodra de inhoud groter is dan
       het scrolvenster; daardoor blijft de bovenkant van de tekening
       bereikbaar i.p.v. te worden afgekapt door flex-centering. */
    align-items: safe center;
    justify-content: safe center;
  }
  /* Polygoon-overlay: dunne SVG bovenop de canvas voor de veelhoek-mode. */
  .crop-canvas-wrap svg.crop-poly {
    position: absolute; top: 0; left: 0;
    width: 100%; height: 100%;
    pointer-events: none;
  }
  .crop-canvas-wrap svg.crop-poly polygon,
  .crop-canvas-wrap svg.crop-poly polyline {
    fill: var(--accent-tint-18);
    stroke: var(--accent);
    stroke-width: 2;
    vector-effect: non-scaling-stroke;
  }
  .crop-canvas-wrap svg.crop-poly polyline { fill: none; stroke-dasharray: 6 4; }
  .crop-canvas-wrap svg.crop-poly circle.vtx {
    fill: var(--accent); stroke: #fff; stroke-width: 2;
  }
  .crop-canvas-wrap svg.crop-poly circle.vtx.first {
    stroke: var(--accent-2);
  }
  /* Mode-knoppen in de crop-header */
  .crop-mode-btn {
    background: var(--bg-2);
    border: 1px solid var(--border);
    color: var(--text);
    padding: 4px 10px;
    border-radius: 6px;
    font-size: 12px;
    cursor: pointer;
  }
  .crop-mode-btn.active {
    background: var(--accent-tint-18);
    border-color: var(--accent);
    color: var(--accent);
  }
  .crop-canvas-wrap {
    position: relative;
    display: inline-block;
    cursor: crosshair;
  }
  .crop-canvas-wrap canvas {
    display: block;
    background: var(--pdf-canvas-bg);
    box-shadow: var(--shadow-deep);
  }
  .crop-rect {
    position: absolute;
    border: 2px solid var(--accent);
    background: var(--accent-tint-15);
    box-shadow: 0 0 0 9999px var(--map-mask);
    pointer-events: none;
  }
  .crop-footer {
    display: flex; justify-content: space-between; align-items: center;
    gap: 12px;
    padding: 12px 18px;
    border-top: 1px solid var(--border);
    background: var(--bg-2);
  }
  .crop-footer .left, .crop-footer .right { display: flex; gap: 8px; align-items: center; }
  .crop-page-btn {
    background: var(--panel-2); border: 1px solid var(--border);
    color: var(--text); padding: 5px 10px; border-radius: 4px;
    font-size: 12px; cursor: pointer;
  }
  .crop-page-btn:disabled { opacity: 0.4; cursor: not-allowed; }
  .crop-info { font-size: 11px; color: var(--text-dim); }
  /* Foto-blok bovenaan: streetview iframe + caption-overlay */
  .locations-photo {
    position: relative;
    width: 100%;
    height: 200px;
    background: var(--bg);
    overflow: hidden;
    flex-shrink: 0;
    border-bottom: 1px solid var(--border);
  }
  .locations-photo iframe {
    width: 100%; height: 100%;
    border: 0;
    pointer-events: auto;
  }
  .locations-photo-overlay {
    position: absolute; inset: 0;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    text-align: center; padding: 20px;
    /* v2026-05-23-I — gradient verwijderd, solid bg */
    background: var(--bg);
    pointer-events: none;
  }
  .locations-photo-caption {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 8px 12px 10px;
    /* v2026-05-23-I — fade-to-transparent gradient vervangen door solid
       semi-transparent overlay zodat caption-tekst op foto's leesbaar blijft. */
    background: var(--bg-overlay);
    color: var(--text);
    font-size: 12px;
    line-height: 1.4;
    pointer-events: none;
  }
  .locations-photo-caption strong { color: var(--accent); font-weight: 700; }
  .locations-photo-caption .sub { color: var(--text-dim); font-size: 10px; letter-spacing: 0.8px; text-transform: uppercase; font-weight: 600; }
  /* Tab-bar in de assets-aside (zelfde stijl als de hoofd-tabs) */
  .locations-tabbar {
    display: flex;
    border-bottom: 1px solid var(--border);
    background: var(--bg-2);
    flex-shrink: 0;
  }
  .loc-tab-btn {
    flex: 1;
    background: transparent;
    color: var(--text-dim);
    border: 0;
    border-bottom: 2px solid transparent;
    padding: 10px 8px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: color .15s, background .15s, border-color .15s;
  }
  .loc-tab-btn:hover { color: var(--text); background: var(--panel-2); }
  .loc-tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); }
  .locations-tabbody {
    flex: 1;
    overflow: auto;
    padding: 14px;
  }
  .locations-tabbody .empty-tab {
    color: var(--text-dim);
    font-size: 12px;
    line-height: 1.6;
    padding: 20px;
    text-align: center;
    border: 1px dashed var(--border);
    border-radius: 8px;
    background: var(--panel-overlay);
  }

  /* Equipment-samenvatting (rechtertab + map-popup) */
  .summary-card {
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 10px 12px;
  }
  .summary-label {
    font-size: 10px;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 600;
  }
  .summary-value {
    font-size: 22px;
    color: var(--text);
    font-weight: 700;
    margin-top: 2px;
    font-variant-numeric: tabular-nums;
  }
  .summary-value-big {
    font-size: 26px;
    color: var(--accent);
    font-weight: 700;
    margin-top: 4px;
    font-variant-numeric: tabular-nums;
  }
  .summary-total {
    background: var(--accent-tint-08);
    border: 1px solid var(--accent-border-30);
    border-radius: 8px;
    padding: 12px 14px;
    margin-bottom: 16px;
  }
  .summary-h3 {
    font-size: 11px;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 1.4px;
    font-weight: 700;
    margin: 18px 0 8px;
  }
  /* Tabellen in de samenvatting — vaste kolombreedtes via table-layout zodat
     code, count en subtotaal netjes uitlijnen over alle rijen heen. */
  .summary-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
  }
  .summary-table th {
    text-align: left;
    font-size: 10px;
    color: var(--text-dim);
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    padding: 4px 8px;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
  }
  .summary-table td {
    padding: 6px 8px;
    border-bottom: 1px dashed var(--divider-subtle);
    color: var(--text);
    vertical-align: top;
  }
  .summary-table .num {
    text-align: right;
    white-space: nowrap;
  }
  .summary-table tbody tr:hover td {
    background: var(--accent-tint-04);
  }
  /* Laag-sub-header in de per-artikel tabel — visueel rustig zodat hij
     niet concurreert met de echte tabelinhoud. */
  .summary-table tr.layer-row td {
    background: var(--accent-tint-06);
    color: var(--text-dim);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    padding: 8px 8px 4px;
    border-bottom: 1px solid var(--border);
  }
  .summary-table tr.layer-row:hover td { background: var(--accent-tint-06); }
  /* Per-artikel tabel: artikelcode in monospace blauw, naam-cel mag wrappen */
  .summary-articles td.code {
    color: var(--accent);
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-size: 11px;
    white-space: nowrap;
    width: 1%;       /* shrink-to-fit */
  }
  .summary-articles td.name { color: var(--text); word-break: break-word; }
  .summary-articles td.name .brand { color: var(--text-dim); font-size: 11px; }
  .summary-articles th:nth-child(3),
  .summary-articles td:nth-child(3) { width: 1%; }     /* count: shrink */
  .summary-articles th:nth-child(4),
  .summary-articles td:nth-child(4) { width: 100px; }  /* subtotaal: vaste breedte */
  .summary-layers th:nth-child(2),
  .summary-layers td:nth-child(2) { width: 1%; }
  .summary-layers th:nth-child(3),
  .summary-layers td:nth-child(3) { width: 100px; }
  /* Street View card slide-in (verschijnt onder de pin-popup) */
  @keyframes streetview-in {
    0%   { transform: translate(0, 30px) scale(0.94); opacity: 0; }
    100% { transform: translate(0, 0)   scale(1);    opacity: 1; }
  }
  /* Tooltip op de referentie-stippen */
  .leaflet-tooltip.ref-tooltip {
    background: var(--panel-overlay-deep);
    color: var(--text);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-floating);
    font-size: 11px;
    padding: 5px 9px;
    border-radius: 4px;
  }
  .leaflet-tooltip.ref-tooltip::before {
    border-top-color: var(--border);
  }

  /* Per-lane "+" button (SVG) */
  .lane-add {
    cursor: pointer;
  }
  .lane-add rect {
    fill: var(--hover-bg);
    stroke: var(--border);
    stroke-dasharray: 3 3;
    rx: 6;
    transition: fill .15s, stroke .15s;
  }
  .lane-add:hover rect { fill: var(--accent-tint-18); stroke: var(--accent); stroke-dasharray: 0; }
  .lane-add text { fill: var(--text-dim); font-size: 11px; font-weight: 600; text-anchor: middle; dominant-baseline: middle; }
  .lane-add:hover text { fill: var(--accent); }

  /* Lane up/down move buttons */
  .lane-move {
    cursor: pointer;
  }
  .lane-move rect {
    fill: var(--hover-bg);
    stroke: var(--border);
    rx: 5;
    transition: fill .15s, stroke .15s;
  }
  .lane-move:hover rect { fill: rgba(77,166,206,0.2); stroke: var(--accent); }
  .lane-move text {
    fill: var(--text-dim); font-size: 14px; font-weight: 700;
    text-anchor: middle; dominant-baseline: middle;
  }
  .lane-move:hover text { fill: var(--accent); }
  .lane-move.disabled { cursor: not-allowed; opacity: 0.3; pointer-events: none; }

  /* Modal */
  /* v2026-06-08-C — Toast-notificaties (vervangen native alert()). Rechtsboven,
     container vangt geen klikken; de toasts zelf wel.

     v2026-07-20-Y — z-index en positie gecorrigeerd. De oude waarde (1200) was
     gekozen toen modal2 nog op 1100 zat, maar is sindsdien door de rest van de
     app ingehaald. (v2026-08-04-G: de losse nummers uit dit lijstje zijn
     vervangen door de stapel-schaal in :root; toasts zitten op --z-toast, boven
     élke overlay en dialoog.) Gevolg destijds: elke
     status- of foutmelding die tijdens een open modal of tijdens een
     lopende actie werd getoond viel er volledig achter, en een toast bovenaan
     schoof deels achter de header. Precies de meldingen die je het hardst
     nodig hebt (opslaan mislukt, koppelen geweigerd) waren dus onzichtbaar.

     Nu 99996: boven alles wat de app over het scherm legt, maar onder de splash
     (99999) en de boot-loader (99990 — die blokkeert de app toch). `top` staat
     onder de header, zodat de knoppen rechtsboven bereikbaar blijven zolang er
     een toast staat. */
  #toast-container {
    position: fixed;
    top: 58px; right: 16px;
    z-index: var(--z-toast);
    display: flex; flex-direction: column; gap: 10px;
    max-width: min(420px, calc(100vw - 32px));
    pointer-events: none;
  }
  .toast {
    pointer-events: auto;
    display: flex; align-items: flex-start; gap: 10px;
    padding: 12px 14px;
    border-radius: 8px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-left: 4px solid var(--text-dim);
    box-shadow: var(--shadow-deep);
    color: var(--text);
    font-size: 13px; line-height: 1.5;
    opacity: 0; transform: translateX(12px);
    transition: opacity 0.2s ease, transform 0.2s ease;
  }
  .toast.toast-in  { opacity: 1; transform: translateX(0); }
  .toast.toast-out { opacity: 0; transform: translateX(12px); }
  /* v2026-07-20-Y — dezelfde melding opnieuw: korte puls i.p.v. een tweede
     regel, zodat je ziet dát er iets gebeurde zonder een stapel identieke
     toasts. */
  .toast.toast-pulse { animation: toast-pulse 0.45s ease; }
  @keyframes toast-pulse {
    0%   { transform: translateX(0)    scale(1);    }
    35%  { transform: translateX(-3px) scale(1.025); }
    100% { transform: translateX(0)    scale(1);    }
  }
  /* v2026-07-20-Y — een gekleurd streepje van 4px links was te subtiel om een
     fout van een bevestiging te onderscheiden, zeker bovenop een modal waar de
     toast dezelfde panel-kleur heeft als wat eronder ligt. De rand krijgt nu de
     signaalkleur rondom en de achtergrond een lichte tint. */
  .toast-error   { border-left-color: var(--danger);  border-color: var(--danger);   background: color-mix(in srgb, var(--danger) 12%, var(--panel)); }
  .toast-success { border-left-color: var(--accent-2); border-color: var(--accent-2); background: color-mix(in srgb, var(--accent-2) 12%, var(--panel)); }
  .toast-info    { border-left-color: var(--accent);  border-color: var(--accent);   background: color-mix(in srgb, var(--accent) 10%, var(--panel)); }
  /* Foutmeldingen blijven staan tot je ze wegklikt (zie showToast); maak de
     sluitknop dan ook duidelijk vindbaar in plaats van een grijs kruisje. */
  .toast-error .toast-close { color: var(--danger); font-weight: 700; }
  .toast-icon { flex-shrink: 0; font-size: 14px; line-height: 1.45; }
  .toast-msg  { flex: 1; word-break: break-word; }
  .toast-close {
    flex-shrink: 0; background: transparent; border: none;
    color: var(--text-dim); cursor: pointer;
    font-size: 13px; line-height: 1.2; padding: 0 2px;
    transition: color 0.15s;
  }
  .toast-close:hover { color: var(--text); }

  .modal-overlay {
    position: fixed; inset: 0;
    background: var(--map-mask);
    display: flex; align-items: center; justify-content: center;
    z-index: var(--z-overlay);     /* laag 1 van de stapel-schaal — zie :root */
    backdrop-filter: blur(3px);
    transition: padding-right 0.15s ease;
  }
  .modal-overlay.hidden { display: none; }
  /* v2026-06-08-B: tweede modal-laag — stackt bovenop #modal zodat
     confirm/prompt-dialogen vanuit een open modal getoond kunnen worden.

     v2026-08-04-F: was 2100, wat alleen boven #modal (2000) uitkwam. Diverse
     schermen bouwden hun eigen overlay op een veel hogere z-index (11000-11600:
     mail-templates, help, org-modals, contact-picker). Een confirmAction() daaruit
     opende wél, maar ónder die overlay — onzichtbaar, dus de knop leek kapot
     (melding Martijn 04-08 over Verwijderen bij Mail-templates).

     v2026-08-04-G: die ad-hoc waarden zijn opgeruimd. Elke overlay zit nu op
     --z-overlay en deze dialoog-laag op --z-dialog erboven — één schaal, zie
     het :root-blok bovenin dit bestand. Bewust ónder de systeemlaag
     (--z-toast/--z-splash/--z-critical): die horen boven een dialoog. */
  #modal2.modal-overlay { z-index: var(--z-dialog); }
  #modal2 .modal-box { min-width: 460px; max-width: 560px; }
  .modal-box {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 10px;
    min-width: 440px; max-width: 540px;
    max-height: 88vh; overflow-y: auto;
    box-shadow: var(--shadow-deep);
  }
  /* v2026-05-07-F: brede variant voor admin-modals met veel kolommen
     (Beheer → Percelen, e.d.). Combineert met openModal({wide:true}).
     v2026-05-07-K: max-width naar 1080px om naam-kolom + 6 selecties + delete
     comfortabel te tonen. */
  .modal-box.wide {
    min-width: 720px;
    max-width: 1080px;
  }
  /* v2026-05-12-BL02: tussenmaat — gebruikt door openOrganisationModal zodat
     de workspace-cards binnen de organisatie-modal genoeg ruimte hebben voor
     volledige plaatsnamen ('Nieuw-Beijerland' e.d.). */
  .modal-box.medium {
    min-width: 640px;
    max-width: 720px;
  }
  .modal-head {
    padding: 18px 44px 10px 22px;   /* extra rechts-padding zodat titel niet onder de ✕ loopt */
    border-bottom: 1px solid var(--border);
    /* v2026-06-08-A: sticky zodat de ✕-sluitknop altijd in beeld blijft,
       ook bij lange modals waar de .modal-box scrollt. */
    position: sticky;
    top: 0;
    background: var(--panel);
    z-index: 2;
    border-top-left-radius: 10px;
    border-top-right-radius: 10px;
  }
  .modal-head h3 { margin: 0; font-size: 16px; font-weight: 700; }
  .modal-head p { margin: 4px 0 0; color: var(--text-dim); font-size: 12px; }
  /* v2026-06-08-A: universele sluitknop rechtsboven in elke openModal()-modal. */
  .modal-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: 6px;
    color: var(--text-dim);
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
  }
  .modal-close:hover {
    background: var(--hover-bg-strong);
    color: var(--text);
  }
  .modal-body { padding: 16px 22px; }
  .modal-body .row {
    display: grid; grid-template-columns: 120px 1fr;
    gap: 10px 14px; margin-bottom: 12px; align-items: start;
  }
  /* v2026-05-15-BM06: 2-koloms layout voor de PD-modal — past beter op
     standaard schermen zonder dat de modal eindeloos lang wordt. Pak je
     de gewone .row-grid (120px label + 1fr input) en plaats er twee naast
     elkaar in een outer 2-koloms grid. Rijen met knop-blokken / icon-picker
     / textarea-blokken krijgen 'wide' en spannen beide kolommen. */
  .modal-body .pd-form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 28px;
    align-items: start;
  }
  /* v2026-05-28-O — Coherent design-systeem voor PD-modal:
     - Alle inputs/selects op exact 28px hoog
     - Section-headers spannen volledig over beide kolommen (op .row-niveau)
     - Chips uniforme min-breedte + vaste hoogte
     - Icon-picker-row alle controls even hoog
     - Bundle-row eigen class-systeem voor consistente typografie */
  .modal-body .pd-form-grid > .row {
    /* v2026-05-28-U — Labels uitgelijnd met BOVENSTE regel van de inhoud (was
       verticaal gecentreerd → label zweefde midden in chip-blokken). Meer
       margin-bottom voor duidelijkere groepering tussen rijen. */
    margin-bottom: 9px;
    grid-template-columns: 110px 1fr;
    gap: 4px 12px;
    align-items: start;
  }
  .modal-body .pd-form-grid > .row.wide,
  .modal-body .pd-form-grid > .row.pd-section-header {
    grid-column: 1 / -1;
  }
  .modal-body .pd-form-grid > .row > label {
    font-size: 11px;
    /* padding-top dat label-baseline matched met die van een 28px-input
       op de eerste regel (mid-line van de input). */
    padding-top: 6px;
    align-self: start;
  }
  .modal-body .pd-form-grid > .row input[type=text],
  .modal-body .pd-form-grid > .row input[type=number],
  .modal-body .pd-form-grid > .row select {
    padding: 0 8px;
    font-size: 12px;
    height: 28px;
    box-sizing: border-box;
    line-height: 26px;
  }
  .modal-body .pd-form-grid > .row textarea {
    padding: 5px 8px;
    font-size: 12px;
    min-height: 48px;
    box-sizing: border-box;
  }
  /* Section-header: full-width op .row niveau (fix v2026-05-28-N waar de header
     in 1 kolom stond → layout omklap-bug). v2026-05-28-U: extra margin-top
     zodat de groep visueel los staat van de voorgaande sectie. */
  .modal-body .pd-form-grid > .row.pd-section-header {
    margin-top: 16px;
    margin-bottom: 6px;
    display: block;
  }
  .modal-body .pd-form-grid > .row.pd-section-header:first-child {
    margin-top: 0;
  }
  .modal-body .pd-form-grid > .row.pd-section-header > label {
    display: none;
  }
  /* v2026-05-28-Z — Cloud-hide state. Wordt gezet door _updatePdSectionsForLayer
     wanneer layer = "OCC | Cloud". !important zodat 't wint van inline styles
     die door applyRoleVisibility (data-show-for) of bundle-section JS worden
     gezet — anders zou de cloud-hide weer ongedaan worden gemaakt zodra de rol
     of een chip wijzigt. */
  .modal-body .pd-form-grid .pd-cloud-hidden {
    display: none !important;
  }
  /* Hint-teksten compact. */
  .modal-body .pd-form-grid .pd-hint {
    font-size: 9.5px;
    color: var(--text-dim);
    margin-top: 2px;
    line-height: 1.35;
  }
  /* v2026-05-28-O — Chips (toggle-knoppen) binnen PD-form-grid: uniforme
     min-breedte en hoogte zodat ze visueel een rij vormen. */
  .modal-body .pd-form-grid .option-btns {
    gap: 4px;
    min-height: auto;
  }
  .modal-body .pd-form-grid .opt-btn {
    min-width: 78px;
    padding: 0 10px;
    height: 26px;
    font-size: 11.5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    border-radius: 13px;
  }
  /* v2026-05-28-O — Icon-picker-row: alle controls precies even hoog (28px). */
  .modal-body .pd-form-grid .icon-picker-row {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 0;
  }
  .modal-body .pd-form-grid .icon-preview {
    width: 28px; height: 28px;
    font-size: 16px;
    border: 1px solid var(--border);
    border-radius: 4px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg);
    flex-shrink: 0;
  }
  .modal-body .pd-form-grid .icon-input {
    width: auto !important;
    flex: 1 1 auto;
    min-width: 80px;
    font-size: 12px !important;
    text-align: left;
    height: 28px;
    padding: 0 8px;
    box-sizing: border-box;
  }
  .modal-body .pd-form-grid .icon-picker-row > button,
  .modal-body .pd-form-grid .icon-picker-row > .action-btn {
    height: 28px;
    font-size: 11px;
    padding: 0 10px;
    flex-shrink: 0;
    line-height: 26px;
  }
  /* v2026-05-28-O — Bundle-row (Device Licentie / SWAS / MDM / system-MS):
     alle kolommen consistente font-size en uitlijning. Code + prijs in
     monospace zodat tabular-nums werken; naam in normaal proza-font. */
  .pd-bundle-row {
    display: flex;
    gap: 10px;
    align-items: center;
    padding: 4px 10px;
    background: var(--row-stripe-strong);
    border: 1px solid var(--border);
    border-radius: 5px;
    font-size: 12px;
    line-height: 1.25;
    min-height: 30px;
  }
  .pd-bundle-row .pd-bundle-code {
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-size: 11.5px;
    color: var(--text-dim);
    flex-shrink: 0;
    min-width: 76px;
  }
  .pd-bundle-row .pd-bundle-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 12px;
    color: var(--text);
  }
  /* v2026-05-30-C — Erft .amount-eigenschappen (text-align:right, tabular-nums,
     nowrap) via class composition; PD-bundle-specifieke styling (monospace +
     min-width + flex-shrink) blijft hier. Voor consistentie gebruikt de bundle-
     row markup nu class="pd-bundle-price amount" — zie .pd-bundle-price in JS. */
  .pd-bundle-row .pd-bundle-price {
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-size: 11.5px;
    color: var(--text-dim);
    font-variant-numeric: tabular-nums;
    min-width: 78px;
    text-align: right;
    white-space: nowrap;
    flex-shrink: 0;
  }
  .pd-bundle-row .pd-bundle-remove {
    padding: 0 8px !important;
    height: 22px;
    font-size: 14px;
    line-height: 20px;
    flex-shrink: 0;
  }
  /* v2026-05-15-BM07: input met €-prefix voor Verkoopprijs in PD-modal. */
  .modal-body .input-with-prefix {
    display: flex;
    align-items: stretch;
    width: 100%;
  }
  .modal-body .input-with-prefix .prefix {
    display: inline-flex;
    align-items: center;
    padding: 0 9px;
    background: var(--bg);
    color: var(--text-dim);
    border: 1px solid var(--border);
    border-right: none;
    border-radius: 5px 0 0 5px;
    font-size: 12.5px;
    font-family: inherit;
  }
  .modal-body .input-with-prefix input {
    border-radius: 0 5px 5px 0 !important;
    flex: 1;
    min-width: 0;
  }
  .modal-body label { color: var(--text-dim); font-size: 12px; padding-top: 8px; }
  .modal-body input[type=text],
  .modal-body input[type=color],
  .modal-body input[type=number],
  .modal-body input[type=date],
  .modal-body input[type=email],
  .modal-body input[type=url],
  .modal-body select,
  .modal-body textarea {
    width: 100%;
    box-sizing: border-box;
    background: var(--bg); color: var(--text);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 7px 10px; font-size: 13px;
    font-family: inherit;
    line-height: 1.4;
    height: 34px;
  }
  /* Native macOS/Chrome select rendering uitschakelen + eigen chevron erop. */
  .modal-body select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 28px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'><path fill='%23889bb0' d='M2 4l4 4 4-4z'/></svg>");
    background-repeat: no-repeat;
    background-position: right 8px center;
    background-size: 12px 12px;
    cursor: pointer;
  }
  .modal-body textarea { height: auto; min-height: 60px; resize: vertical; }
  .modal-body input[type=color] { height: 34px; padding: 2px; cursor: pointer; }
  /* Versie-pill in de Calculatie-modal — read-only badge die de huidige versie toont. */
  .modal-body .calc-version-pill {
    display: inline-block;
    background: var(--accent-2-tint-18);
    border: 1px solid var(--accent);
    color: var(--accent);
    padding: 4px 12px;
    border-radius: 12px;
    font-weight: 700;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.5px;
  }
  .modal-body input:focus, .modal-body select:focus, .modal-body textarea:focus {
    outline: none; border-color: var(--accent);
  }
  .modal-body .checks {
    display: flex; flex-wrap: wrap; gap: 8px;
  }
  .modal-body .checks label {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px; border-radius: 12px;
    border: 1px solid var(--border);
    font-size: 12px; color: var(--text);
    cursor: pointer; user-select: none;
    background: var(--bg);
  }
  .modal-body .checks input { margin: 0; }
  .modal-body .checks label.selected {
    border-color: var(--accent);
    background: var(--accent-tint-12);
  }
  /* Toggle-knoppen voor opties (voeding, technologie, port-types) */
  .option-btns {
    display: flex; flex-wrap: wrap; gap: 6px;
    min-height: 28px;
  }
  .opt-btn {
    padding: 5px 11px; border-radius: 14px;
    border: 1px solid var(--border);
    background: var(--bg); color: var(--text);
    font-size: 12px; cursor: pointer;
    user-select: none;
    transition: all 0.12s ease;
  }
  .opt-btn:hover { border-color: var(--accent); }
  .opt-btn.on {
    background: var(--accent-tint-22);
    border-color: var(--accent);
    color: var(--text);
    font-weight: 600;
  }
  /* Bulk-bewerken: knop staat aan voor SOMMIGE geselecteerde devices */
  .opt-btn.partial {
    background: var(--accent-tint-10);
    border-color: var(--accent-border-45);
    border-style: dashed;
    color: var(--text);
    font-weight: 500;
  }
  .opt-btn-add {
    border-style: dashed;
    color: var(--text-dim);
    background: transparent;
  }
  .opt-btn-add:hover { color: var(--accent); }
  .option-btns-compact .opt-btn {
    font-size: 11px; padding: 3px 8px; border-radius: 11px;
  }
  .modal-foot {
    display: flex; justify-content: flex-end; gap: 8px;
    padding: 12px 22px 18px;
    border-top: 1px solid var(--border);
  }
  .modal-foot button {
    padding: 8px 16px; border-radius: 5px; font-size: 13px;
    border: 1px solid var(--border);
    background: transparent; color: var(--text);
    cursor: pointer;
  }
  .modal-foot button.primary {
    background: var(--accent); color: var(--text-on-accent);
    border-color: var(--accent); font-weight: 600;
  }
  .modal-foot button.primary:hover { background: var(--accent); }
  .modal-foot button.secondary:hover { border-color: var(--accent); }
  .modal-foot button.danger {
    color: var(--danger); border-color: var(--danger-border-40);
    margin-right: auto;
  }
  .modal-foot button.danger:hover { background: var(--danger-tint-strong); }
  .modal-foot button.danger:disabled {
    opacity: 0.4; cursor: not-allowed; background: transparent;
  }
  .field-error { color: var(--danger); font-size: 11px; margin-top: 4px; }

  /* v2026-05-30-C — UNIVERSELE UX-REGEL: bedragen rechts uitgelijnd.
     Gebruik class `.amount` op elke <span>, <td>, <div> die een €-bedrag,
     percentage of ander getal-met-eenheid toont in een tabel- of kolom-
     context. tabular-nums maakt cijfers even breed → rijen onder elkaar
     lijnen netjes uit. nowrap voorkomt regelafbreking midden in een bedrag.
     Voor inline tekst ("kp €1,37 · marge 18%") binnen lopende tekst is de
     class niet nodig — daar maakt rechts uitlijnen geen verschil. */
  .amount {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  /* Zorg dat .amount in een tabelcell de hele cell-breedte vult zodat de
     rechts-uitlijning op cell-niveau zichtbaar wordt (anders shrink-fit). */
  td > .amount, th > .amount { display: block; }

  /* v2026-05-28-W — Universele chip-class voor uniforme weergave van labels
     (aanbieder OCP/EHT, PLM-status Beta/GA/EOSale/EOService/EOLife, EOL-markers,
     etc.). Allen exact dezelfde grootte/typografie zodat ze visueel in lijn
     komen. Modifier-classes (.chip-eht, .chip-ga, …) zetten alleen de kleuren.
     Werkt op zowel <span> als <button>. */
  .chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    height: 18px;
    min-width: 38px;
    padding: 0 7px;
    border-radius: 9px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    line-height: 1;
    border: 1px solid currentColor;
    background: transparent;
    color: var(--text-dim);
    vertical-align: middle;
    white-space: nowrap;
    user-select: none;
    cursor: default;
  }
  button.chip { cursor: pointer; font-family: inherit; }
  .chip + .chip { margin-left: 4px; }
  /* Iets kleinere variant voor inline-gebruik in dichte lijsten. */
  .chip-sm {
    height: 16px;
    min-width: 34px;
    padding: 0 6px;
    font-size: 9px;
    border-radius: 8px;
  }
  /* Aanbieder-varianten — OCP (blauw) en EHT (groen). */
  .chip-ocp { color: #3b9fe3; background: rgba(59,159,227,0.12); border-color: rgba(59,159,227,0.40); }
  .chip-eht { color: #7bd389; background: rgba(123,211,137,0.15); border-color: rgba(123,211,137,0.45); }
  .chip-ncp { color: #e0913b; background: rgba(224,145,59,0.13); border-color: rgba(224,145,59,0.42); }
  /* PLM-status-varianten — zie PLM_STATUS_DEFS in app.js. */
  .chip-beta      { color: #a855f7; background: rgba(168,85,247,0.15); border-color: rgba(168,85,247,0.40); }
  .chip-ga        { color: #22c55e; background: rgba(34,197,94,0.15);  border-color: rgba(34,197,94,0.40);  }
  .chip-eosale    { color: #f59e0b; background: rgba(245,158,11,0.15); border-color: rgba(245,158,11,0.40); }
  .chip-eoservice { color: #ef4444; background: rgba(239,68,68,0.15);  border-color: rgba(239,68,68,0.40);  }
  .chip-eolife    { color: #6b7280; background: rgba(107,114,128,0.18); border-color: rgba(107,114,128,0.45); }
  /* Neutrale variant — voor "geen waarde"-chip of placeholder. */
  .chip-empty { color: var(--text-dim); background: transparent; border-color: var(--border); font-weight: 500; }
  /* v2026-07-27 — AFAS-koppeling ontbreekt (afas_matched = 0). Zie renderAfasMatchChip. */
  .chip-afas-warn { color: #ef4444; background: rgba(239,68,68,0.14); border-color: rgba(239,68,68,0.45); }
  /* v2026-07-27 — Artikel geblokkeerd in AFAS (Blocked=true of ExportToTool=false). Zie renderBlockedChip. */
  .chip-blocked { color: #fff; background: rgba(107,33,33,0.85); border-color: #6b2121; }

  /* Icon picker */
  .icon-picker-row { display: flex; gap: 10px; align-items: center; margin-bottom: 8px; }
  .icon-preview {
    font-size: 28px; width: 44px; height: 44px;
    display: flex; align-items: center; justify-content: center;
    background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
  }
  .icon-input { width: 100px !important; font-size: 18px; text-align: center; }
  .icon-grid {
    display: grid; grid-template-columns: repeat(10, 1fr); gap: 4px;
    max-height: 140px; overflow-y: auto;
    padding: 6px; background: var(--bg);
    border: 1px solid var(--border); border-radius: 6px;
  }
  .icon-opt {
    font-size: 20px; text-align: center; padding: 4px 0;
    cursor: pointer; border-radius: 4px;
    user-select: none;
  }
  .icon-opt:hover { background: var(--panel-2); }
  .icon-opt.selected { background: rgba(77,166,206,0.2); outline: 1px solid var(--accent); }
  .icon-opt.custom { position: relative; }
  .icon-opt.custom::after {
    content: "★"; position: absolute; top: -2px; right: 1px;
    font-size: 9px; color: var(--accent-2); pointer-events: none;
  }
  .icon-opt.add-new {
    color: var(--accent); font-weight: 700;
    border: 1px dashed var(--accent-border-50);
  }
  .icon-opt.add-new:hover { background: var(--accent-tint-10); }
  .icon-opt.custom::after {
    content: "★";
    position: absolute; top: -1px; right: 2px;
    font-size: 8px; color: var(--accent-2); line-height: 1;
  }
  .icon-opt.add-new {
    background: var(--panel-2);
    color: var(--accent);
    font-weight: 700;
    border: 1px dashed var(--accent);
  }
  .icon-opt.add-new:hover { background: var(--accent-tint-15); }

  /* ---- Inklapbare secties in #map-controls ---- */
  .map-section-header {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
    padding: 2px 0;
    border-radius: 3px;
    transition: color .12s;
  }
  .map-section-header:hover { color: var(--text); }
  .map-section-chevron {
    display: inline-block;
    width: 10px;
    text-align: center;
    color: var(--text-dim);
    font-size: 9px;
    transition: transform .15s ease;
    flex-shrink: 0;
  }
  .map-section-collapsed > .map-section-chevron,
  .map-section-collapsed .map-section-chevron { transform: rotate(-90deg); }
  /* Verberg álles in een sectie behalve de header. */
  .map-section.is-collapsed > *:not(.map-section-header) { display: none !important; }
  /* Geef ingeklapte secties een wat compacter padding zodat het paneel
     mooi inzakt zonder grote witte gaten. */
  .map-section.is-collapsed { padding-bottom: 0 !important; }

  /* ---- Top-level toggle: het hele #map-controls paneel inklappen ---- */
  .map-controls-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
    padding: 4px 6px;
    margin: -4px -6px 8px;
    border-radius: 4px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.7px;
    text-transform: uppercase;
    color: var(--text);
    background: var(--accent-tint-10);
    transition: background .12s, color .12s;
  }
  .map-controls-toggle:hover { background: var(--accent-tint-18); }
  .map-controls-toggle .map-section-chevron { color: var(--accent); }
  .map-controls-toggle .filter-count {
    font-size: 9.5px;
    letter-spacing: 0.3px;
    text-transform: none;
    color: var(--text-dim);
    font-weight: 500;
    flex-shrink: 0;
  }
  /* Volledig ingeklapt: paneel krimpt tot een nette kleine pill, secties weg. */
  #map-controls.is-fully-collapsed {
    min-width: 0 !important;
    max-width: 200px !important;
    padding: 6px 10px !important;
    overflow: hidden !important;
  }
  #map-controls.is-fully-collapsed > .map-section { display: none !important; }
  #map-controls.is-fully-collapsed .map-controls-toggle {
    margin: 0;
    background: transparent;
  }
  #map-controls.is-fully-collapsed .map-controls-toggle:hover {
    background: var(--accent-tint-15);
  }
  #map-controls.is-fully-collapsed .map-controls-toggle .map-section-chevron {
    transform: rotate(-90deg);
  }

/* v2026-05-21-T/U — PDF-viewer rechts: bewerk-tooling permanent verbergen.
   User-wens: alleen view + zoom + pagina-navigatie zichtbaar houden.
   Sinds -U: niveau-select wél tonen — die fungeert nu als koppel-dropdown
   (pagina → Gebouw of een verdieping), niet meer als bewerk-tool. */
#orgs-side-pdf-floorplan-del,
#orgs-side-pdf-crop-btn {
  display: none !important;
}

/* v2026-06-03-I — Loading-state voor calc-overzicht-paneel. Vervangt het
   volledige paneel met een spinner + tekst zolang devices voor de zojuist
   gekozen calc nog niet geladen zijn — voorkomt dat oude data van een
   vorige calc-versie kort flitst voordat de nieuwe binnen is.
   Gebruikt door renderBuildingOverviewPane (zie app.js, stale-check). */
.ovz-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 64px 16px;
  color: var(--text-dim);
  font-size: 13px;
  letter-spacing: 0.3px;
}
.ovz-loading-spinner {
  width: 28px;
  height: 28px;
  border: 2.5px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: ovz-spin 0.9s linear infinite;
}
@keyframes ovz-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* v2026-06-03-N — Drag-over feedback voor KP-perceel-cards (drop-targets in
   de Kostenplaats-tree). Accent-border + lichte achtergrond zodat duidelijk
   is waar het product zal landen bij loslaten. */
.kp-perceel-card.kp-drop-hover,
.kp-card-frame.kp-drop-hover {
  border-color: var(--accent) !important;
  background: var(--accent-tint-06, rgba(77, 166, 206, 0.08)) !important;
  box-shadow: 0 0 0 1px var(--accent) inset;
}

/* v2026-06-05-A — Sprint 3b: in-app "What's new"-modal styling. De content
   komt uit dbo.release_notes.body_html (vooraf gegenereerd door
   scripts/release-notes/generate.js); we strippen de email-wrapper en
   stylen 'm hier opnieuw zodat 'ie matcht met de Universe-modal look. */
.whats-new-content {
  font-size: 14px;
  line-height: 1.55;
  color: var(--text);
  max-height: 60vh;
  overflow-y: auto;
  padding-right: 8px;
}
.whats-new-content h1,
.whats-new-content h2 {
  color: var(--accent);
  line-height: 1.25;
  margin-top: 24px;
  margin-bottom: 10px;
}
.whats-new-content h1 { font-size: 20px; }
.whats-new-content h2 { font-size: 16px; }
.whats-new-content h1:first-child,
.whats-new-content h2:first-child { margin-top: 0; }
.whats-new-content p  { margin: 10px 0; }
.whats-new-content ul { padding-left: 22px; margin: 8px 0 14px; }
.whats-new-content li { margin: 5px 0; }
.whats-new-content strong { color: var(--text); font-weight: 600; }
.whats-new-content hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: 20px 0;
}
.whats-new-content code {
  background: var(--debug-code-bg, #f4f4f4);
  color: var(--debug-code-text, #333);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 0.92em;
}

/* Sprint P6 — Productie 3-paneel split met twee sleepbare dividers. */
#prod-left { min-width: 200px; }
#prod-mid  { min-width: 280px; }
#prod-right { min-width: 240px; }
.prod-divider {
  flex: 0 0 6px;
  cursor: col-resize;
  background: var(--border);
  transition: background .15s;
}
.prod-divider:hover { background: var(--accent, #4da6ce); }

/* Lopende tijdbalk op de actieve productie-stap (indeterminate). */
.prod-timebar {
  position: relative;
  height: 4px;
  background: rgba(127, 127, 127, 0.15);
  border-radius: 2px;
  overflow: hidden;
}
.prod-timebar::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -40%;
  width: 40%;
  background: var(--accent, #4da6ce);
  border-radius: 2px;
  animation: prodTimebar 1.1s ease-in-out infinite;
}
@keyframes prodTimebar {
  0%   { left: -40%; }
  100% { left: 100%; }
}

/* ============================================================
   v2026-07-15-E — Help-menu: werkinstructie-modal (js/help.js)
   Zelfde leespatroon als .whats-new-content, maar met tabel-opmaak
   voor de status-/beheer-tabellen in de instructies.
============================================================ */
.help-guide-content {
  font-size: 14px;
  line-height: 1.55;
  color: var(--text);
  overflow-y: auto;
  padding: 14px 18px 18px;
}
.help-guide-content .hg-intro { color: var(--text-dim); margin-top: 0; }
.help-guide-content h3 {
  color: var(--accent);
  font-size: 15px;
  line-height: 1.25;
  margin: 20px 0 8px;
}
.help-guide-content h3:first-of-type { margin-top: 12px; }
.help-guide-content p  { margin: 8px 0; }
.help-guide-content ul { padding-left: 22px; margin: 6px 0 12px; }
.help-guide-content li { margin: 5px 0; }
.help-guide-content strong { color: var(--text); font-weight: 600; }
.help-guide-content .hg-table {
  border-collapse: collapse;
  width: 100%;
  margin: 8px 0 14px;
  font-size: 13px;
}
.help-guide-content .hg-table th,
.help-guide-content .hg-table td {
  border: 1px solid var(--border);
  padding: 5px 8px;
  text-align: left;
  vertical-align: top;
}
.help-guide-content .hg-table th {
  background: var(--panel-2, rgba(77, 166, 206, 0.08));
  color: var(--accent);
  font-weight: 600;
}
/* v2026-07-21-Y — Zoek-highlight in de werkinstructie, theme-proof. */
.help-guide-content mark {
  background: var(--accent);
  color: var(--text-on-accent, #fff);
  border-radius: 2px;
  padding: 0 1px;
}
.help-guide-content .hg-sec { margin: 0; }

/* ============================================================
   v2026-07-15-G — Communicatie: WYSIWYG-editor voor momenten
   Witte achtergrond bewust: zo ziet de ontvanger het bericht in
   de mail-client (ook in dark theme van de app zelf).
============================================================ */
.cmp-wysiwyg {
  background: #fff;
  color: #222;
  border: 1px solid var(--border);
  border-radius: 6px;
  min-height: 180px;
  max-height: 46vh;
  overflow-y: auto;
  padding: 12px 14px;
  font-family: "Segoe UI", Arial, sans-serif;
  font-size: 14px;
  line-height: 1.5;
}
.cmp-wysiwyg:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.cmp-wysiwyg img { max-width: 100%; height: auto; }
.cmp-wysiwyg table { border-collapse: collapse; }
.cmp-wysiwyg table td, .cmp-wysiwyg table th { border: 1px solid #ccc; padding: 4px 8px; }
.cmp-wysiwyg a { color: #2f7fa3; }

/* v2026-08-20-A — percentage-invoervelden (slagingskans op een saleskans).
   De native spinner-pijltjes vielen over het %-teken rechts in het veld zodra
   je het aanraakte; het veld is een getal van 0-100 dat je gewoon typt, dus de
   pijltjes voegen niets toe. */
.pct-input::-webkit-outer-spin-button,
.pct-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pct-input { -moz-appearance: textfield; appearance: textfield; }
