/* ── Omgevingsgrootte ────────────────────────────────────────────────────────────────────────────
   Het voorkeuren-paneel biedt compact/normaal/comfortabel aan; deze regels maken die keuze zichtbaar.
   Ze stonden tot 0.20.0 alleen in de app.css van ADM One, waardoor de knoppen in elke andere app niets
   deden. Op <html>, niet op body: alles wat in rem rekent (ook DevExpress) volgt dan mee. */
html.adm-size-compact { font-size: 14px; }
html.adm-size-normal { font-size: 16px; }
html.adm-size-comfortable { font-size: 18px; }

/* ── Accent → Bootstrap, per thema ───────────────────────────────────────────────────────────────
   AdmShell zet op <html> enkel de INVOER (--adm-accent*, licht én donker). De vertaling naar Bootstraps
   --bs-*-variabelen gebeurt hier, want een inline stijl op <html> wint van elke [data-bs-theme=dark]-regel en
   kan dus per definitie niet meeflippen.
   Waarom een aparte donkere tint nodig is: het Fluent-thema gebruikt in dark een LICHTER accent en berekent
   daar ZWARTE tekst op. Zetten we onze (donkere) basistint ook in dark, dan krijg je die zwarte tekst op een
   donkere vulling: volle primary-badges op 3,90 : 1 — onder de AA-drempel — en links in donkerblauw op een
   donkere achtergrond. Met 25% wit erbij zit elk van de elf accenten op 5,8–7,3 : 1. Zie AdmAccent.DarkHex. */
:root {
    --bs-primary: var(--adm-accent, #0f6cbd);
    --bs-primary-rgb: var(--adm-accent-rgb, 15, 108, 189);
    --bs-link-color: var(--adm-accent, #0f6cbd);
    --bs-link-color-rgb: var(--adm-accent-rgb, 15, 108, 189);
    --bs-link-hover-color: var(--adm-accent-hover, #0b5699);
    --bs-link-hover-color-rgb: var(--adm-accent-hover-rgb, 11, 86, 153);
    /* Accent-tint als achtergrond: color-mix met `transparent` mengt met wát erachter staat en flipt dus
       vanzelf mee met het thema (0.101.27). */
    --bs-primary-bg-subtle: color-mix(in srgb, var(--adm-accent, #0f6cbd) 12%, transparent);
    --adm-accent-on: var(--adm-accent-fg);
}

[data-bs-theme="dark"] {
    --bs-primary: var(--adm-accent-dark, #4b91ce);
    --bs-primary-rgb: var(--adm-accent-dark-rgb, 75, 145, 206);
    --bs-link-color: var(--adm-accent-dark, #4b91ce);
    --bs-link-color-rgb: var(--adm-accent-dark-rgb, 75, 145, 206);
    --bs-link-hover-color: var(--adm-accent-dark-hover, #639fd4);
    --bs-link-hover-color-rgb: var(--adm-accent-dark-hover-rgb, 99, 159, 212);
    --bs-primary-bg-subtle: color-mix(in srgb, var(--adm-accent-dark, #4b91ce) 12%, transparent);
    --adm-accent-on: var(--adm-accent-dark-fg);
}

/* ── AdmFormPopup — ademruimte en knopvolgorde ───────────────────────────────────────────────────
   Twee dingen die DevExpress' default niet goed doet voor een INVOER-venster, gemeld door Dominique
   (10/08/2026) op het gebruikersbeheer:

   1. De voettekst plakt tegen de inhoud. In een leesvenster valt dat niet op, in een formulier wel: het
      invoerveld en de knop eronder lijken één blok. Een scheidingslijn + ruimte maakt duidelijk waar de
      invoer stopt en de beslissing begint.
   2. Knoppen stonden rechts uitgelijnd, waardoor de bevestigknop — die als laatste in de markup staat —
      helemaal rechts belandde. Vloot-conventie is: **bevestigen eerst (links), annuleren erna.** De actie
      waarvoor de gebruiker het venster opende, staat vooraan; annuleren is de uitweg, niet de hoofdweg.
      De volgorde zet je in je eigen FooterContent; deze regel zorgt dat ze links begint i.p.v. rechts.

   ⚠️ De lange selector hieronder is nodig, geen slordigheid: DevExpress stuurt de voettekst met
   `.dxbl-modal > .dxbl-modal-root > .dxbl-popup > .dxbl-modal-content > .dxbl-modal-footer` (specificiteit
   0,5,0). Een kortere regel verliest en doet dan stil niets — gemeten in de playground, 10/08/2026. */
.dxbl-modal > .dxbl-modal-root > .dxbl-popup.adm-form-popup > .dxbl-modal-content > .dxbl-modal-footer {
    justify-content: flex-start;
    gap: .5rem;
    padding-top: 1rem;
    margin-top: .5rem;
    border-top: 1px solid var(--bs-border-color);
}
.dxbl-modal > .dxbl-modal-root > .dxbl-popup.adm-form-popup > .dxbl-modal-content > .dxbl-modal-body {
    padding-bottom: .25rem;
}


/* ── AdmJournaal — de zijkant van een record ─────────────────────────────────────────────────────
   Schakelaar vast bovenaan, inhoud eronder die zelf scrollt. De hoogte komt van de omhullende schil
   (lade of paneel); vandaar flex + min-height:0, anders groeit de inhoud eruit i.p.v. te scrollen. */
.adm-journaal-switch {
    flex: 0 0 auto; padding: .625rem 0; border-bottom: 1px solid var(--bs-border-color);
}
.adm-journaal-content { flex: 1; min-height: 0; overflow: auto; padding: .5rem 0; }

/* Lege toestand: gecentreerde, lichtgrijze illustratie + tekst. */
.adm-journaal-leeg {
    flex: 1; min-height: 10rem;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: .75rem; padding: 1.5rem; text-align: center;
}
.adm-journaal-leeg-icoon { color: var(--bs-border-color); opacity: .85; }
.adm-journaal-leeg-tekst { color: var(--bs-secondary-color); font-size: .9rem; max-width: 20rem; }


/* ── Verplicht veld ──────────────────────────────────────────────────────────────────────────────
   Zet .adm-req op het label (of op CaptionCssClass van een DxFormLayoutItem) van een verplicht veld.
   Kwam uit Nimble's eigen app.css; naar de fundering gehaald op 10/08/2026 zodat elke app hetzelfde
   sterretje toont en niemand het opnieuw hoeft te verzinnen. */
.adm-req::after { content: " *"; color: var(--bs-danger); font-weight: 600; }


/* ── AdmTaskList — de gedeelde takenlijst ────────────────────────────────────────────────────────
   Een lijst, geen grid: taken lees je als regels tekst met een datum, niet als kolommen. Elke rij is
   selectievakje · inhoud · acties, met de acties pas zichtbaar bij hover zodat een lange lijst rustig blijft. */
.adm-tasklist .adm-task {
    display: flex; gap: .6rem; align-items: flex-start;
    padding: .5rem 0; border-bottom: 1px solid var(--bs-border-color);
    position: relative;          /* anker voor de acties, die uit de stroom staan — zie hieronder */
}
.adm-tasklist .adm-task:last-child { border-bottom: none; }
.adm-task-body { flex: 1; min-width: 0; }
/* ⚠️ Twee waarden voor de gap: eerst de RIJ-afstand, dan de kolom-afstand. Met één waarde geldt .4rem ook
   verticaal, en dan valt de badge in een smalle lade met een volle regel eronder — het leest als een fout in
   plaats van als een afgebroken regel. Gemeld vanuit Nimble (smalle journaal-lade), 10/08/2026. */
.adm-task-titel { display: flex; align-items: center; gap: .1rem .4rem; flex-wrap: wrap; }
.adm-task-tekst {
    font-size: .85rem; color: var(--bs-secondary-color); margin-top: .15rem;
    /* Lange notities mogen de lijst niet uit elkaar trekken; de volle tekst staat in het bewerkvenster. */
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.adm-task-meta {
    /* Idem: krappe rij-afstand, ruimere kolom-afstand. "Van 15/10/2026" en "Tot 22/10/2026" horen bij elkaar,
       ook als ze niet naast elkaar passen — met .8rem ertussen leken het twee losse blokjes. */
    display: flex; gap: .1rem .8rem; flex-wrap: wrap;
    font-size: .78rem; color: var(--bs-secondary-color); margin-top: .2rem;
}
/* ⚠️ De acties staan ABSOLUUT, niet in de flex-rij. Met `visibility: hidden` bleven ze wél ruimte innemen: de
   tekst kreeg daardoor maar een deel van de breedte en brak veel te vroeg af ("Vijf dagen na / verzending nog
   geen…" in een lade waar de volle regel paste). Onzichtbaar is niet hetzelfde als weg. Uit de stroom halen geeft
   de tekst de volle breedte, met een nette insprong bij het afbreken. Gemeld vanuit Nimble, 10/08/2026. */
.adm-task-acties {
    position: absolute; top: .35rem; right: 0; z-index: 1;
    display: flex; gap: .25rem; visibility: hidden;
    /* Achtergrond, want ze zweven nu bóven de tekst zodra ze verschijnen. */
    background: var(--bs-body-bg); box-shadow: -.75rem 0 .75rem .25rem var(--bs-body-bg);
}
.adm-task:hover .adm-task-acties, .adm-task:focus-within .adm-task-acties { visibility: visible; }
/* De eigenaar is context, geen gegeven: iets rustiger dan de rest van de meta-regel. */
.adm-task-eigenaar { color: var(--bs-secondary-color); font-style: italic; }
/* Afgewerkt: gedempt en doorstreept — herkenbaar zonder dat het gewicht van de lijst verandert. */
.adm-task-af .adm-task-titel { text-decoration: line-through; color: var(--bs-secondary-color); }
.adm-task-af { opacity: .65; }

/* Rasterweergave (AdmTaskList Weergave=Raster, sinds 0.220.0). De rij zelf blijft van de grid — daar hoort de
   fundering niet in te grijpen — maar een afgewerkte taak moet er ook hier afgewerkt uitzien. Zonder dit ziet
   een afgevinkte rij er identiek uit als een openstaande, en dan is het vinkje het enige verschil. */
/* ⚠️ De flex-keten. Een AdmGrid met FullHeight vult alleen als ÉLKE ouder een volle-hoogte flexkolom is; één
   gewone div ertussen en de grid clipt in plaats van te scrollen — dat is de fix van 0.101.10, en deze wrapper
   is precies zo'n div ertussen. Zonder deze regel is RasterVult een parameter die niets doet. */
.adm-tasklist-raster { display: flex; flex-direction: column; min-height: 0; height: 100%; }

.adm-task-af-cel { text-decoration: line-through; color: var(--bs-secondary-color); }

/* Het toelichtinkje onder het onderwerp krijgt in een rastercel wat minder ruimte dan in de lijst: een
   gridrij hoort niet mee te groeien met de lengte van een notitie. */
.dxbl-grid .adm-task-tekst { -webkit-line-clamp: 2; margin-top: .1rem; }

/* ── AdmRecordHistorie — wat er aan een record veranderde ────────────────────────────────────────
   De cel draagt een LIJST van velden, geen tekstregel: één wijziging kan tien velden raken, en die horen
   onder elkaar te staan in plaats van achter elkaar te wikkelen. Zelfde reden als bij de meta-regel van
   AdmTaskList, waar zes losse brokjes een taak in zeven regeltjes uit elkaar trokken. */
.adm-historie-velden { list-style: none; margin: 0; padding: 0; }
.adm-historie-velden li {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: .1rem .4rem;
    font-size: .85rem; padding: .1rem 0;
}
/* De veldnaam is de sleutel van de regel: hij mag niet wegvallen tegen de waarden ernaast. */
.adm-historie-veld { font-weight: 600; color: var(--bs-body-color); }
/* De oude waarde is context — doorstreept, want ze geldt niet meer. */
.adm-historie-van { color: var(--bs-secondary-color); text-decoration: line-through; }
.adm-historie-pijl { color: var(--bs-secondary-color); }
.adm-historie-naar { color: var(--bs-body-color); }

/* ── AdmBadge — één badge-recept voor de hele vloot ──────────────────────────────────────────────
   Waarom een component en niet "kies maar een Bootstrap-klasse": apps mengden `.text-bg-*` (vol vlak) en
   `.bg-*-subtle` (zachte vulling) in dezelfde kolom. Dat leest als twee SOORTEN dingen i.p.v. twee waarden
   van één veld, en de volle variant zakt in dark onder AA zodra het accent in het spel is. Gemeld door
   Dominique op de Nimble-relatielijst (Klant vol blauw naast Leverancier subtiel groen), 10/08/2026.
   Het subtiele trio (bg-subtle + text-emphasis + border-subtle) flipt per thema by design en haalt in beide
   thema's 7 : 1 of meer. Voor een kolom met herhaalde labels is het bovendien rustiger dan volle vlakken. */
.adm-badge {
    display: inline-flex; align-items: center; gap: .3em;
    padding: .2em .6em; border-radius: 999px;
    font-size: .78em; font-weight: 600; line-height: 1.35;
    white-space: nowrap; vertical-align: baseline;
    border: 1px solid transparent;
}
/* ⚠️ De tonen gebruiken bewust Bootstraps SEMANTISCHE families (secondary/info/success/warning/danger) en
   NIET het accent. Het accent is merkkleur en wisselt per gebruiker; zou `info` daarop draaien, dan krijg je
   bij accent "rose" een roze vulling met de blauwe emphasis-tekst van het thema. De semantische families zijn
   per thema op elkaar afgestemd — vulling, tekst en rand horen bij elkaar. */
.adm-badge-neutraal     { background: var(--bs-secondary-bg);       color: var(--bs-secondary-color);        border-color: var(--bs-border-color); }
.adm-badge-info         { background: var(--bs-info-bg-subtle);     color: var(--bs-info-text-emphasis);     border-color: var(--bs-info-border-subtle); }
.adm-badge-succes       { background: var(--bs-success-bg-subtle);  color: var(--bs-success-text-emphasis);  border-color: var(--bs-success-border-subtle); }
.adm-badge-waarschuwing { background: var(--bs-warning-bg-subtle);  color: var(--bs-warning-text-emphasis);  border-color: var(--bs-warning-border-subtle); }
.adm-badge-fout         { background: var(--bs-danger-bg-subtle);   color: var(--bs-danger-text-emphasis);   border-color: var(--bs-danger-border-subtle); }

/* ── Visuele taal v2 — surface-tokens (fase 1) ───────────────────────────────────────────────────
   Opgemeten op de DevExpress Fluent CRM-demo (02/08/2026) en gekoppeld aan de Fluent design-system-tokens
   (de dxds-color-surface- en -border-tokens), zodat ze VANZELF meeflippen in licht/dark. De hex-fallbacks zijn de
   opgemeten demo-waarden. Kern: de CANVAS (pagina + zijbalk) is één toon; enkel INHOUD wordt een verhoogde kaart.
   Zie docs/visuele-taal-v2.md. */
:root {
    --adm-canvas: var(--dxds-color-surface-neutral-subdued-rest, #f4f4f3);   /* licht #f4f4f3 · dark #1d1e1d */
    --adm-card: var(--dxds-color-surface-neutral-default-rest, #fffffe);     /* licht wit · dark #252525 */
    --adm-card-border: var(--dxds-color-border-neutral-default-rest, #d3d3d2);/* licht #d3d3d2 · dark #767676 */
    --adm-radius: 4px;
    --adm-pos: #4ba747;   /* stijgend/goed (semantisch) */
    --adm-neg: #e0615a;   /* dalend/slecht (semantisch) */
}

/* Inhoudskaart: het enige dat "verhoogd" is boven de canvas. Gebruik dit op panelen/lijsten/tegels. */
.adm-card {
    background: var(--adm-card);
    border: 1px solid var(--adm-card-border);
    border-radius: var(--adm-radius);
}

/* Gedeelde shell-CSS voor de AppKit-topbar-panelen (voorkeuren + help) en widgets. De app includeert dit via
   <link href="_content/Adm.AppKit.Web/adm-shell.css">. Shell-structuur (.shell/.sidebar/grootte) blijft app-CSS. */

/* Topbar-icoonknoppen (menu in-/uitklappen, help). */
.icon-btn {
    border: none; background: transparent; padding: 6px; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--bs-body-color); border-radius: 8px;
}
/* Hover: een subtiele overlay op de HUIDIGE tekstkleur (currentColor) → flipt sowieso mee (donkere tint in licht,
   lichte tint in dark) en is lichter dan een vaste grijze vlek. Vervangt --bs-secondary-bg (dat NIET flipt: blijft
   #e9ecef licht in het Fluent dark-thema → een lichte vlek op de donkere topbar). */
.icon-btn:hover { background: color-mix(in srgb, currentColor 9%, transparent); }

/* Avatar (initialen of foto). Neutrale demo-stijl: een dunne neutrale rand, GÉÉN vól accent — het accent blijft
   voorbehouden voor betekenis (net als de tegels/werkbalk). De demo doet net zo (transparante cirkel, 1px rand). */
.avatar-btn { border: none; background: transparent; padding: 0; cursor: pointer; display: inline-flex; border-radius: 50%; }
.avatar {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 50%;
    /* Transparant (zoals de demo) i.p.v. --bs-secondary-bg: dat token blijft #e9ecef (licht) in het Fluent
       DARK-thema → een lichte cirkel op de donkere topbar mét lichte initialen = onleesbaar. Transparant toont
       de topbar-kleur (canvas) en flipt dus altijd mee; initialen in de volle tekstkleur voor contrast. */
    background: transparent;
    color: var(--bs-body-color);
    border: 1px solid var(--adm-card-border, var(--bs-border-color, #d3d3d2));
    font-size: 0.8rem; font-weight: 600;
    object-fit: cover;
}
.avatar-lg { width: 44px; height: 44px; font-size: 1rem; }
/* Foto-avatar: geen vulling, wel dezelfde dunne rand als de demo. */
.avatar-img { background: none; padding: 0; object-fit: cover; }
/* Toetsenbord-focus: een nette ring rond de avatar (had er geen). */
.avatar-btn:focus-visible { outline: none; }
.avatar-btn:focus-visible .avatar { outline: 2px solid var(--bs-primary); outline-offset: 2px; }

/* Uitschuifbare zijpanelen (voorkeuren + help). */
.prefs-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.35); z-index: 1040; }
.prefs-panel, .help-panel {
    position: fixed; top: 0; right: 0; height: 100vh; width: 330px; max-width: 92vw;
    background: var(--bs-body-bg); color: var(--bs-body-color);
    border-left: 1px solid var(--bs-border-color); z-index: 1041;
    display: flex; flex-direction: column; box-shadow: -4px 0 18px rgba(0, 0, 0, 0.18);
}

/* De hulp-assistent krijgt méér breedte dan zijn buren, en enkel hij.
   ⚠️ `.help-panel` wordt door DRIE laden gedeeld — help, feedback en deze assistent. Die eerste twee tonen
   korte tekst en een formulier; verbreden zou daar enkel lege ruimte geven. Vandaar een modifier in plaats
   van een aanpassing aan de gedeelde regel.

   Waarom breder: sinds 0.174.0 rendert deze lade de Markdown van het model — genummerde stappen,
   opsommingen, `code`. Gemeten op 16/08/2026 bleef er van de 330px maar 252px tekstbreedte over, en daar
   liep zelfs een kort opsommingspunt al over twee regels.

   ⚠️ En waarom niet nóg breder: deze lade legt zich over het scherm waarover je de vraag stelt. Zegt de
   assistent "klik rechtsboven op Nieuwe taak", dan moet je die knop kunnen zien. 420px laat op een scherm van
   1436 nog altijd ruim driekwart vrij. De max-width van 92vw uit de gedeelde regel blijft gelden, dus op een
   telefoon verandert er niets. */
.help-panel.docs-panel { width: 420px; }
.prefs-header {
    display: flex; align-items: center; gap: 12px; padding: 16px;
    border-bottom: 1px solid var(--bs-border-color);
}
.prefs-id { flex: 1; min-width: 0; }
.prefs-user { font-weight: 600; }
.help-head-title { display: flex; align-items: center; gap: 8px; font-weight: 600; flex: 1; }
.prefs-close {
    border: none; background: transparent; color: var(--bs-secondary-color);
    font-size: 1.1rem; cursor: pointer; line-height: 1; padding: 4px 8px; border-radius: 6px;
}
.prefs-close:hover { background: var(--bs-secondary-bg); }

.prefs-body, .help-body { flex: 1; overflow-y: auto; padding: 16px; }
.help-body { font-size: 0.92rem; line-height: 1.55; }
.help-body :first-child { margin-top: 0; }
.help-body :last-child { margin-bottom: 0; }

/* Typografie voor de helptekst. De lade is smal, dus de browserstandaarden deugen hier niet: een <ul>
   springt standaard 40px in en <h4> wordt bijna even groot als de paneeltitel. Zonder deze regels ziet
   een OPGEMAAKTE helptekst er slechter uit dan een kale — en dan schrijft niemand er nog een. Dit hoort
   dus vóór de controle die opmaak afdwingt (0.136.0). */
.help-body p { margin: 0 0 10px; }
.help-body ul, .help-body ol { margin: 0 0 10px; padding-left: 20px; }
.help-body li { margin-bottom: 4px; }
.help-body li:last-child { margin-bottom: 0; }
.help-body h4, .help-body h5, .help-body h6 {
    font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--bs-secondary-color); margin: 16px 0 6px; font-weight: 600;
}
.help-body strong, .help-body b { font-weight: 600; }
.help-body code {
    font-size: 0.85em; padding: 1px 5px; border-radius: 4px;
    background: var(--bs-secondary-bg); color: var(--bs-body-color);
}
.help-body a { color: var(--bs-primary); }
.help-body hr { margin: 14px 0; border: 0; border-top: 1px solid var(--bs-border-color); }
.help-body table { width: 100%; margin: 0 0 10px; border-collapse: collapse; font-size: 0.95em; }
.help-body th, .help-body td { text-align: left; padding: 4px 6px; border-bottom: 1px solid var(--bs-border-color); }
.help-body th { font-weight: 600; color: var(--bs-secondary-color); }

.prefs-section { margin-bottom: 18px; }
.prefs-label {
    font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--bs-secondary-color); margin-bottom: 8px;
}
.prefs-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.prefs-chip {
    display: inline-flex; align-items: center; gap: 5px; padding: 6px 12px;
    border: 1px solid var(--bs-border-color); border-radius: 999px;
    font-size: 0.85rem; color: var(--bs-body-color); text-decoration: none; cursor: pointer;
}
.prefs-chip:hover { background: var(--bs-secondary-bg); }
.prefs-chip.active { background: var(--bs-primary); color: #fff; border-color: var(--bs-primary); }

.prefs-swatches { display: flex; flex-wrap: wrap; gap: 10px; }
.prefs-swatch {
    width: 28px; height: 28px; border-radius: 50%;
    border: 2px solid transparent; box-shadow: 0 0 0 1px var(--bs-border-color);
}
.prefs-swatch.active { border-color: var(--bs-body-bg); box-shadow: 0 0 0 2px var(--bs-primary); }

.prefs-footer { padding: 16px; border-top: 1px solid var(--bs-border-color); }
.prefs-logout {
    display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
    padding: 8px; border: 1px solid var(--bs-border-color); border-radius: 8px;
    background: transparent; color: var(--bs-body-color); text-decoration: none; cursor: pointer;
}
.prefs-logout:hover { background: var(--bs-secondary-bg); }

/* ── Handleiding-assistent (AdmDocsAssistant): chat-lade ─────────────────────────────────────────────────
   Eigen lichte chat-lade (geen DxAIChat). Hergebruikt de lade-hulzen (.help-panel/.prefs-*); enkel de
   berichtenbubbels + het invoerveld zijn hier eigen. Bot-antwoorden zijn platte tekst (de prompt vraagt géén
   markdown) → pre-wrap bewaart de regelafbrekingen. */
.docs-chat { display: flex; flex-direction: column; gap: 8px; }
.docs-intro { margin-bottom: 4px; }
.docs-msg {
    max-width: 85%;
    padding: 8px 12px;
    border-radius: 12px;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: 0.9rem;
    line-height: 1.4;
}
.docs-msg-user {
    align-self: flex-end;
    background: var(--bs-primary, #0d6efd);
    color: #fff;
    border-bottom-right-radius: 3px;
}
.docs-msg-bot {
    align-self: flex-start;
    background: var(--bs-tertiary-bg, var(--bs-secondary-bg, #f1f1f1));
    color: var(--bs-body-color);
    border-bottom-left-radius: 3px;
}
.docs-typing { font-style: italic; opacity: 0.7; }
.docs-textarea { resize: none; }

/* Auth-kaart: gedeeld door de login én andere zelfstandige auth-schermen (bv. wachtwoord wijzigen). Niet-scoped
   zodat élke auth-pagina (ook buiten de AppKit, zoals CreditSoft's WachtwoordWijzigen) dezelfde nette kaart krijgt. */
.login-page {
    min-height: 100vh;
    display: flex; align-items: center; justify-content: center;
    background: var(--bs-tertiary-bg); padding: 24px;
}
.login-card {
    width: 100%; max-width: 380px;
    background: var(--bs-body-bg); border: 1px solid var(--bs-border-color);
    border-radius: 14px; padding: 32px 28px; box-shadow: 0 10px 30px rgba(0, 0, 0, .06);
}
.login-lang { display: flex; justify-content: flex-end; gap: 10px; margin-bottom: 8px; font-size: .85rem; }
.login-lang a { color: var(--bs-secondary-color); text-decoration: none; }
.login-lang a.active { color: var(--bs-primary); font-weight: 700; }
.login-brand { font-weight: 700; font-size: 1.25rem; margin-bottom: 18px; }
.login-title { font-size: 1.4rem; margin: 0 0 4px; }
.login-subtitle { color: var(--bs-secondary-color); margin-bottom: 20px; font-size: .92rem; }
.login-label { display: block; font-size: .85rem; font-weight: 600; margin: 12px 0 4px; }
.login-submit { margin-top: 20px; }

/* Badge-teller op een nav-item (bv. ongelezen privé-overleg). Duwt naar rechts in de uitgeklapte zijbalk. */
.nav-menu .nav-link .nav-badge {
    margin-left: auto;
    min-width: 17px; height: 17px; padding: 0 5px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 999px; font-size: 0.68rem; font-weight: 500; line-height: 1;
    background: var(--bs-primary); color: #fff;
}

/* Notificatie-belletje (AdmNotifications) rechtsboven in de topbar. */
.notif-btn { position: relative; }
.notif-count {
    position: absolute; top: 0; right: 0;
    min-width: 16px; height: 16px; padding: 0 4px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 999px; font-size: 0.62rem; font-weight: 500; line-height: 1;
    background: var(--bs-danger); color: #fff;
    /* Fijne uitsnede-ring in de canvas-kleur → het cijfer scheidt schoon van het belletje. */
    box-shadow: 0 0 0 1.5px var(--adm-canvas, var(--bs-body-bg));
}
.notif-panel { width: 360px; }
.notif-body { flex: 1; overflow-y: auto; padding: 4px 0; }
.notif-empty { padding: 16px; }
.notif-item {
    display: flex; align-items: flex-start; gap: 10px; width: 100%; text-align: left;
    border: none; border-bottom: 1px solid var(--bs-border-color); background: transparent;
    padding: 10px 16px; cursor: pointer; color: var(--bs-body-color);
}
.notif-item:hover { background: var(--bs-secondary-bg); }
/* Theme-veilige accent-tint. HISTORIEK: tot 0.101.26 zette AdmShell `--bs-primary-bg-subtle` als INLINE stijl op
   <html> op een vaste lichte hex. Inline wint van `[data-bs-theme=dark]`, dus die tint bleef in dark licht →
   lichtblauw vlak + lichte tekst = onleesbaar. Sinds 0.101.27 levert AdmShell de variabele zélf als color-mix met
   `transparent`, dus `var(--bs-primary-bg-subtle)` is nu overal veilig. Deze expliciete color-mix mag blijven
   staan (zelfde resultaat) en dient als voorbeeld van het recept. */
.notif-unread { background: color-mix(in srgb, var(--bs-primary) 12%, transparent); }
.notif-ico { color: var(--bs-secondary-color); margin-top: 2px; flex: 0 0 auto; }
.notif-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.notif-msg { font-size: 0.85rem; }
.notif-time { font-size: 0.72rem; color: var(--bs-secondary-color); }
.notif-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--bs-primary); margin-top: 6px; flex: 0 0 auto; }

/* Variabelen-palet (AdmVariablePicker): draggable {{token}}-chips voor sjabloon-editors. */
.adm-var-panel {
    border: 1px solid var(--bs-border-color); border-radius: 6px; padding: 10px 12px; background: var(--bs-secondary-bg);
}
.adm-var-chip {
    cursor: pointer; padding: 2px 8px; border-radius: 4px;
    background: var(--bs-body-bg); border: 1px solid var(--bs-border-color);
    color: var(--bs-primary); font-size: .82rem;
}
.adm-var-chip:hover { border-color: var(--bs-primary); background: var(--bs-primary-bg-subtle); }

/* Leesbare .btn-outline-secondary op het DevExpress-Fluent-thema. Fluent zet --bs-secondary bijna wit (#ebebeb),
   waardoor Bootstrap's outline-secondary lichtgrijze tekst op wit geeft (contrast ~1.1:1, onleesbaar — enkel bij
   hover leesbaar). We overschrijven de Bootstrap 5.3-knopvariabelen: donkere tekst + neutrale rand in rust, een
   subtiele grijze vulling bij hover/focus. Vloot-breed (elke app die deze knop toont). */
.btn-outline-secondary {
    --bs-btn-color: var(--bs-body-color);
    --bs-btn-border-color: var(--bs-border-color);
    --bs-btn-hover-color: var(--bs-body-color);
    --bs-btn-hover-bg: var(--bs-secondary-bg);
    --bs-btn-hover-border-color: var(--bs-border-color);
    --bs-btn-active-color: var(--bs-body-color);
    --bs-btn-active-bg: var(--bs-secondary-bg);
    --bs-btn-active-border-color: var(--bs-border-color);
}

/* De nav vult de zijbalk, zodat het versielabel onderaan kan blijven staan i.p.v. mee te schuiven met het
   laatste menu-item. Deze twee regels horen samen: zonder de volle hoogte heeft `margin-top: auto` niets om
   tegen te duwen.
   ⚠️ `.nav-menu` wordt door NavMenu in dít pakket gerenderd, dus hoort de bijhorende stijl hier — niet in de
   app-CSS (playbook §6). Tot 0.23.0 stond ze enkel app-kant, waardoor het label bij weinig menu-items
   halverwege de zijbalk hing. Gemeld door Dominique, 22/07/2026. */
.nav-menu { min-height: 100%; }

/* Versielabel onderaan de zijbalk → versiehistoriek: gecentreerd met een scheidingslijn erboven. */
.nav-version {
    /* auto, niet 4px: dit duwt het label naar de onderkant van de zijbalk. Stond hier eerst 4px, waardoor
       het label direct onder het laatste menu-item hing i.p.v. onderaan. */
    margin-top: auto;
    display: block; text-align: center;
    padding: 10px 12px 2px;
    border-top: 1px solid var(--bs-border-color);
    font-size: 0.75rem; letter-spacing: 0.02em;
    color: var(--bs-secondary-color); text-decoration: none;
}
.nav-version:hover { color: var(--bs-primary); }

/* Nav v2 — inklapbare sectiegroepen (demo-stijl). De sectiekop is nu een <button> (klikbaar in/uitklappen) met
   een chevron rechts. De kop-TYPOGRAFIE staat sinds 0.97.0 hier in de FUNDERING (was app-side → apps liepen
   uiteen: DAMC vet/uppercase, CreditSoft normaal). Standaard = klein, vet, hoofdletters, gedempt (Dominique koos
   dit, 03/08). Apps mogen hun lokale `.nav-section`-typografie laten vallen; deze regel wint sowieso op
   specificiteit. De items worden bij inklappen via CSS verborgen (niet uit de DOM) zodat de mini-rail ze toont. */
.nav-menu button.nav-section {
    display: flex; align-items: center; width: 100%;
    background: none; border: 0; cursor: pointer; font-family: inherit; text-align: left;
    padding: 12px 12px 4px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    /* --bs-secondary-color flipt wél (75% wit in dark) → leesbare gedempte kop op zowel lichte als donkere zijbalk.
       Apps die hun `.nav-section` een niet-flippende (donkere) kleur gaven, kregen anders onzichtbare koppen. */
    color: var(--bs-secondary-color);
}
.nav-menu .nav-section-caret { margin-left: auto; flex: 0 0 auto; opacity: .55; transition: transform .15s ease; }
.nav-menu button.nav-section.collapsed .nav-section-caret { transform: rotate(-90deg); }
.nav-menu button.nav-section:hover .nav-section-caret { opacity: .9; }
.nav-section-items.collapsed { display: none; }

/* Nav-spacer: de FUNDERING rendert dit element (in NavMenu, vóór de footer-links + versielabel), dus ze moet 'm
   ook STYLEN — anders `flex-grow:0` → geen groei → footer-items (`Footer=true`) + Afmelden + versie klitten bovenaan
   i.p.v. onderaan gepind. Was tot 0.99.1 app-side, maar de v2-guidance ("`.nav-spacer` = fundering-eigendom, niet
   terugzetten") liet apps 'm droppen → pinning viel stil (gemeld door CreditSoft 03/08). Nu fundering-eigendom mét
   stijl; apps hoeven hun eigen `.nav-spacer`-regel niet meer. */
.nav-menu .nav-spacer { flex: 1 1 auto; }

/* Nav-link hover/actief: FLIPPENDE, subtiele achtergronden. Overschrijft de app-CSS (die `--bs-secondary-bg` voor
   hover en `--bs-primary-bg-subtle` voor actief gebruikt — die flippen NIET mee in het Fluent dark-thema → een
   lichte vlek op de donkere zijbalk met witte tekst). De `.sidebar`-prefix geeft net genoeg specificiteit om te
   winnen van de app-regel (die later laadt). Hover = overlay op de tekstkleur (flipt); actief = accent-op-opacity
   (mode-agnostisch) + accent-tekst. */
.sidebar .nav-menu .nav-link:hover {
    background: color-mix(in srgb, currentColor 9%, transparent);
}
.sidebar .nav-menu .nav-link.active {
    background: color-mix(in srgb, var(--bs-primary) 15%, transparent);
    color: var(--bs-primary);
}
/* Actief/hover item STRAK (4px), niet de ronde 8px-variant — uniform (Dominique koos CreditSofts strakke look,
   03/08). Hogere specificiteit dan de app-side `.nav-menu .nav-link { border-radius }`. */
.sidebar .nav-menu .nav-link {
    border-radius: var(--adm-radius, 4px);
}

/* Afmelden werd in 0.124.0 een POST-form (een link die je afmeldt, is een GET met een gevolg — zie
   MapAdmLogout). Het form mag geen eigen ruimte innemen en de knop moet zich gedragen als de link ernaast:
   een <button> brengt van zichzelf een rand, een grijze achtergrond, een eigen font en gecentreerde tekst mee.
   Zonder deze reset staat er onderaan élke zijbalk in de vloot een grijs knopje tussen de menu-items. */
.sidebar .nav-menu .nav-logout { margin: 0; padding: 0; }
.sidebar .nav-menu .nav-logout .nav-link {
    width: 100%; text-align: left; font: inherit; cursor: pointer;
    background: none; border: 0; appearance: none;
}
/* Idem in het voorkeuren-paneel: .prefs-logout stond al op transparant, maar niet op het paginafont. */
.prefs-footer form { margin: 0; }
button.prefs-logout { font: inherit; appearance: none; }

/* ── Standaard zijbalk-look: afgebakend paneel in LICHT, blend in DARK (Dominique 03/08) ────────────────
   Dominique koos DAMC's afgebakend paneel, maar `--bs-tertiary-bg` springt in dark naar ~#4e4e4e op de bijna-zwarte
   content (een storende grijs-op-donker sprong die CreditSoft in z'n dark-pilot bewust wegnam). DevExpress signaleert
   dark niet via een CSS-attribuut/klasse (het wisselt de thema-CSS), dus we kunnen niet op een dark-selector mikken.
   Oplossing: THEMA-ADAPTIEF via de tokens zelf — een lichte tint van de TEKSTkleur (flipt) over de CANVAS (flipt):
     · licht (donkere tekst over lichte canvas) → subtiel grijs paneel;
     · dark  (witte tekst over donkere canvas)  → nauwelijks lichter dan de content → blend, géén #4e4e4e-sprong.
   De rechterlijn blijft in beide thema's als subtiele afbakening. `.shell`-specificiteit + apps droppen hun eigen
   `.sidebar { background }` (verplicht: CreditSofts eigen `.sidebar`-bg overschreef anders de standaard). */
.shell .sidebar {
    /* Tint SEMI-TRANSPARANT over de achtergrond i.p.v. gemengd met `var(--adm-canvas)`: een `var()` als 2e
       color-mix-argument wordt in een GELINKTE stylesheet niet toegepast in Chrome 148 (valt terug op dat argument →
       kale canvas i.p.v. de tint; gemeld door DAMC 03/08). Met `transparent` als 2e argument werkt het wél (zoals
       `.nav-link.active`). 5% tekstkleur over de canvas-achtergrond → subtiel grijs paneel in licht, near-blend in
       dark — zelfde theme-adaptieve effect, quirk-vrij. */
    background: color-mix(in srgb, var(--bs-body-color) 5%, transparent);
    border-right: 1px solid var(--bs-border-color);
}

/* ── AdmGrid-werkbalk ───────────────────────────────────────────────────────────────────────────────
   Deze regels horen HIER en niet in de app-CSS: AdmGrid zit in deze RCL en rendert deze klassen, dus de
   bijhorende stijl moet met het pakket meereizen. Stond ze tot 0.17.1 alleen in de app.css van CreditSoft,
   waardoor elke andere app een ongestylede werkbalk kreeg (zoekvak, titel en "⋯"-menu zonder opmaak).
   Zie de valkuil in het playbook §6. */

/* Geconsolideerde grid-werkbalk: embedded titel + acties links, zoek + hulpmiddelen rechts. */
.adm-grid-title {
    font-size: 1.15rem;
    font-weight: 600;
    margin-right: 2px;
    white-space: nowrap;
}

.adm-grid-info {
    color: var(--bs-secondary-color);
    cursor: help;
    display: inline-flex;
    align-items: center;
    margin-right: 4px;
    /* Het is een <button> (focusbaar, klikbaar), maar hij hoort als een icoontje te lezen. */
    background: none;
    border: 0;
    padding: 0;
}

.adm-grid-info:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
    border-radius: 3px;
}

.adm-grid-info-text {
    color: var(--bs-secondary-color);
    font-size: 0.8125rem;
    margin-right: 8px;
}

/* ── Rijmarkering: SELECTIE en FOCUS zijn twee verschillende dingen ───────────────────────────────
   Selectie = "dit record heb ik gekozen"; die blijft staan, ook als de focus het grid verlaat.
   Focus    = "hier staat mijn toetsenbord nu"; die is vluchtig en verspringt bij Tab.

   ⚠️ Ze mogen er NIET hetzelfde uitzien. Tot 0.19.0 kreeg enkel de selectie een blauwe vlakvulling en
   had de focus geen enkele markering. Wie dat in een app aanvulde met een tweede vlakvulling voor de
   focus, kreeg bij Tab-navigatie twee identiek blauwe rijen (selectie en focus staan dan op
   verschillende rijen) — wat leest als "de blauwe lijn blijft hangen op het vorige record". Vandaar:
   selectie = vulling + balk, focus = outline. Nooit twee vullingen.

   Stond tot 0.19.0 in de app-eigen app.css terwijl AdmGrid uit dít pakket komt — de zevende keer dat
   fundering-CSS in een app bleek te staan (zie playbook §6). Gevolg: elke app kon de regel ongemerkt
   overschrijven, en twee sessies maten een uur lang tegengestelde dingen over hetzelfde component. */
.adm-grid tr[role="row"][data-visible-index] { cursor: pointer; }

/* Selectie: accent-achtergrond + balk links. !important omdat het DevExpress-thema zijn eigen
   rij-achtergrond zet; adm-shell.css laadt ná het thema, maar de themaregel is specifieker. */
.adm-grid tr[aria-selected="true"] > td {
    background-color: color-mix(in srgb, var(--adm-accent) 18%, transparent) !important;
}
.adm-grid tr[aria-selected="true"] > td:first-child {
    box-shadow: inset 4px 0 0 0 var(--adm-accent);
}

/* Focus: een omlijning, géén vulling. Meteen ook de zichtbare focusindicator die we nergens hadden
   (WCAG 2.4.7). focus-within en niet :focus, want de focus landt op een link of knop ín de cel. */
.adm-grid tbody tr:focus-within {
    outline: 2px solid var(--adm-accent);
    outline-offset: -2px;
}

/* Zoekveld met loep-icoon binnenin (demo-stijl). De wrapper positioneert de loep; de input krijgt links extra
   padding zodat de tekst niet onder het icoon loopt.
   ⚠️ Klasse heet bewust `.adm-grid-searchwrap` en NIET `.adm-grid-search`: sommige apps hadden al een oude
   `.adm-grid-search { width: 300px }` in hun app.css (voor het kale zoekveld). Die dwong deze wrapper op 300px
   terwijl de input 220px is → ~80px leeg gat rechts. Eigen naam = geen botsing meer. */
.adm-grid-searchwrap { position: relative; display: inline-flex; align-items: center; width: fit-content; }
.adm-grid-search-icon {
    position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
    color: var(--bs-secondary-color); pointer-events: none;
}

.adm-grid-searchbox {
    width: 220px;
    max-width: 100%;
    height: 32px;
    padding: 4px 10px 4px 30px;   /* links ruimte voor de loep */
    border: 1px solid var(--bs-border-color, #ced4da);
    border-radius: 6px;
    background: var(--bs-body-bg, #fff);
    color: var(--bs-body-color, inherit);
    font-size: 0.9rem;
}

.adm-grid-searchbox:focus {
    outline: none;
    border-color: var(--adm-accent, #2563eb);
    box-shadow: 0 0 0 2px rgba(37, 99, 235, .15);
}

/* "⋯"-menu op de grid-werkbalk: bundelt kolomkiezer + Excel/CSV-export achter één knop. */
.adm-grid-menu { position: relative; display: inline-flex; }

.adm-menu-backdrop { position: fixed; inset: 0; z-index: 1040; }

.adm-menu-panel {
    position: absolute; top: calc(100% + 6px); right: 0; z-index: 1050;
    min-width: 210px;
    background: var(--bs-body-bg, #fff);
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: 10px; box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
    padding: 6px; display: flex; flex-direction: column;
}

.adm-menu-item {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 8px 10px; border: 0; background: transparent; border-radius: 7px;
    font-size: 0.9rem; color: var(--bs-body-color); text-align: left; cursor: pointer;
    white-space: nowrap;   /* label ("Excel (.xlsx)") op één regel; anders wrapt het in de smalle dropdown */
}

/* Export-dropdown breed genoeg voor de langste optie op één regel (DxDropdown sizet standaard te krap). */
.adm-grid-menu-dropdown { min-width: 190px; }

/* "Toevoegen"-actie: neutrale tekst+icoon-actie, een PEER van de andere werkbalk-acties (kolomkiezer/export/
   refresh) — precies zoals de CRM-demo ("+ Add Task" = neutraal grijs, gewicht 400, géén accent, géén vet;
   opgemeten rgb(200,200,199) in dark = de gewone werkbalk-tekstkleur). Bewust NIET beklemtoond. */
.adm-grid-add {
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
    padding: 6px 10px; border: 0; background: transparent; border-radius: var(--adm-radius, 4px);
    color: var(--bs-body-color); font-size: 0.9rem; font-weight: 400; cursor: pointer;
}
.adm-grid-add:hover { background: var(--bs-tertiary-bg, rgba(0, 0, 0, .05)); }
.adm-grid-add .adm-icon { flex: 0 0 auto; color: var(--bs-secondary-color); }

/* Filter/scope-controls in de grid-werkbalk (AdmFilterSelect / AdmFilterCheckList): een lichte GHOST-dropdown,
   zelfde familie als de "Exporteren ▾"-actie — geen gerand invoervak. Bedoeld voor de Toolbar-slot (links). */
.adm-filter { display: inline-flex; align-items: center; }
.adm-filter-btn {
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
    height: 32px; padding: 0 8px;
    border: 0; background: transparent; border-radius: var(--adm-radius, 4px);
    color: var(--bs-body-color); font-size: 0.9rem; font-weight: 400; cursor: pointer;
}
.adm-filter-btn:hover, .adm-filter-btn.active { background: var(--bs-tertiary-bg, rgba(0, 0, 0, .05)); }
.adm-filter-btn-label { color: var(--bs-secondary-color); }
.adm-filter-btn-value { font-weight: 500; }
.adm-filter-caret { color: var(--bs-secondary-color); opacity: .8; flex: 0 0 auto; }
/* Actieve keuze in de dropdown gemarkeerd. */
.adm-menu-item.active { background: color-mix(in srgb, var(--adm-accent, #2563eb) 12%, transparent); font-weight: 500; }

/* Checkbox-rij in AdmFilterCheckList. */
.adm-filter-check {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 6px 10px; border-radius: 7px; cursor: pointer;
    font-size: 0.9rem; color: var(--bs-body-color); white-space: nowrap;
}
.adm-filter-check:hover { background: var(--bs-tertiary-bg, #f1f3f5); }
.adm-filter-check input { cursor: pointer; margin: 0; }
.adm-filter-clear {
    display: block; width: 100%; text-align: left; margin-top: 4px; padding: 6px 10px;
    border: 0; border-top: 1px solid var(--bs-border-color); background: transparent;
    color: var(--bs-secondary-color); font-size: 0.82rem; cursor: pointer;
}
.adm-filter-clear:hover { color: var(--bs-body-color); }

/* Borderless "ghost" werkbalk-iconknop (kolomkiezer, verversen) — géén gevulde/omrande knop-chrome zoals de
   vroegere DxButton-Secondary (dat gaf de "lege vakjes"); precies de demo: transparant, neutraal, hover = subtiel
   vlak. */
.adm-grid-tool {
    display: inline-flex; align-items: center; justify-content: center;
    height: 32px; min-width: 32px; padding: 0 6px;
    border: 0; background: transparent; border-radius: var(--adm-radius, 4px);
    color: var(--bs-secondary-color); cursor: pointer;
}
.adm-grid-tool:hover, .adm-grid-tool.active {
    background: var(--bs-tertiary-bg, rgba(0, 0, 0, .05)); color: var(--bs-body-color);
}

/* Export-actie: tekst + caret (demo: "Export ▾"), zelfde ghost-stijl als de andere acties. */
.adm-grid-export {
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
    height: 32px; padding: 0 8px;
    border: 0; background: transparent; border-radius: var(--adm-radius, 4px);
    color: var(--bs-body-color); font-size: 0.9rem; font-weight: 400; cursor: pointer;
}
.adm-grid-export:hover, .adm-grid-export.active { background: var(--bs-tertiary-bg, rgba(0, 0, 0, .05)); }
.adm-grid-export .adm-icon { flex: 0 0 auto; color: var(--bs-secondary-color); }
.adm-grid-export-caret { margin-left: -2px; opacity: .8; }

/* AdmGrid/AdmTreeList Fill-modus: de grid/treelist vult de volle hoogte van zijn container. De toolbar
   (.adm-grid-bar) blijft vast bovenaan; het lichaam (.adm-grid-body) neemt de resterende hoogte; DxGrid
   (Height=100%) scrollt zijn DATA-gebied INTERN terwijl header + pager vast blijven. Weinig rijen → wit vlak
   eronder + pager onderaan; veel rijen → scrollbalk op de rijen + pager onderaan. Ships met het pakket zodat
   apps geen eigen `.adm-grid-fill`/`.adm-tree-fill`-hack in app.css meer nodig hebben — wie het element rendert,
   styilt het (valkuil 4: kritieke layout niet aan de app overlaten). */
.adm-grid-fill { flex: 1; min-height: 0; display: flex; flex-direction: column; }

/* ⚠️ De schil van AdmUserAdmin moet MEEDOEN in de flex-keten, anders werkt FullHeight daar niet.
   `.adm-grid-fill` vult met `flex: 1`, en dat vraagt dat élke tussenliggende container een flex-kolom is met
   `min-height: 0`. `.adm-useradmin` had helemaal geen CSS — een gewoon blok — en brak de keten dus precies
   tussen de pagina en de grid.

   Gemeten door de CreditSoft-sessie op 16/08/2026 met de paginabalk als meetpunt, want het rijaantal vertekent
   een hoogtevergelijking: bij de prullenbak stond die balk op 1254 met de vlakrand op 1324 (dus onderaan), bij
   gebruikers op 896 — 379 px wit eronder. Hun diagnose was meteen juist: "mogelijk staat FullHeight er wel maar
   breekt een tussenliggende container de hoogteketen."

   Dit is dezelfde valkuil als in 0.101.10, toen een FullHeight-grid clipte omdat de keten ontbrak. Wie hier een
   nieuwe wikkel toevoegt, moet hem opnemen in deze regel — een blok zonder hoogte is onzichtbaar in de code en
   zichtbaar op het scherm. */
.adm-useradmin { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.adm-grid-fill .adm-grid-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.adm-grid-fill .adm-grid-bar { flex: 0 0 auto; }               /* toolbar houdt z'n natuurlijke hoogte */
.adm-grid-fill .dxbl-grid { flex: 1; min-height: 0; }          /* de grid zelf vult (naast DxGrid Height=100%) */
.adm-grid-fill .adm-treelist-inner { flex: 1; min-height: 0; }

/* Rail/pin-drawer als master-detail: DxDrawer's target-host (.dxbl-drawer-content, standaard display:block) moet
   een volle-hoogte flex-kolom zijn, zodat een FullHeight-grid die er DIRECT in hangt (zonder eigen flex-wrapper —
   zoals de meeste lijst-schermen) de hoogte vult i.p.v. te clippen. Zo krijgt de lijst-kant automatisch: grid vult
   de hoogte, data-gebied scrollt intern, pager onderaan vast — gelijk met het journaal-paneel ernaast. */
.adm-detail-drawer .dxbl-drawer-content { display: flex; flex-direction: column; min-height: 0; }

.adm-menu-item:hover { background: var(--bs-tertiary-bg, #f1f3f5); }

.adm-menu-item .adm-icon { color: var(--bs-secondary-color); flex: 0 0 auto; }
/* Destructieve actie in een menu (AdmRowMenuItem Danger): rood label + rood icoon. */
.adm-menu-item--danger { color: var(--bs-danger, #dc3545); }
.adm-menu-item--danger .adm-icon { color: var(--bs-danger, #dc3545); }

/* ── AdmSectionSwitch — sectie-kiezer (ghost-dropdown, vervangt tabs in een smal paneel) ────────────────
   Zelfde ghost-familie als de filter-controls, maar het label is prominenter (gewicht 600) want het fungeert als
   de "titel" van de zichtbare sectie in het journaal. */
.adm-section-switch { display: inline-flex; align-items: center; }
.adm-section-switch-btn {
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
    padding: 4px 8px; border: 0; background: transparent; border-radius: var(--adm-radius, 4px);
    color: var(--bs-body-color); font-family: inherit; font-size: 0.95rem; cursor: pointer;
}
.adm-section-switch-btn:hover, .adm-section-switch-btn.active { background: var(--bs-tertiary-bg, rgba(0, 0, 0, .05)); }
.adm-section-switch-btn > .adm-icon { flex: 0 0 auto; color: var(--bs-secondary-color); }
.adm-section-switch-label { font-weight: 600; }
.adm-section-switch-caret { color: var(--bs-secondary-color); opacity: .8; flex: 0 0 auto; }

/* ── AdmRowMenu — "⋯"-overflowmenu per rij ─────────────────────────────────────────────────────────────── */
.adm-rowmenu { display: inline-flex; }
.adm-rowmenu-btn {
    display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
    width: 28px; height: 28px; padding: 0; border: 0; background: transparent; border-radius: var(--adm-radius, 4px);
    color: var(--bs-secondary-color); cursor: pointer; transition: background-color .12s ease, color .12s ease;
}
.adm-rowmenu-btn:hover {
    background: color-mix(in srgb, currentColor 12%, transparent);
    color: var(--bs-body-color);
}
.adm-rowmenu-dots { font-size: 1.15rem; line-height: 1; }

/* Topbar-spacer: duwt hulp + voorkeuren naar rechts. MainLayout rendert dit element, dus de regel hoort
   hier — stond ze alleen in de app.css van CreditSoft, dan schuiven avatar en hulpknop in elke andere app
   naar links tegen de merknaam aan. */
.topbar-spacer { flex: 1; }

/* QR-code bij het inschakelen van 2FA (TwoFactorSetupPanel). Zonder de vaste maat rendert de SVG op zijn
   natuurlijke grootte en vult hij het halve scherm. */
.qr-box {
    display: inline-block;
    background: #fff;
    padding: 8px;
    border-radius: 8px;
}

.qr-box svg {
    display: block;
    width: 200px;
    height: 200px;
}

/* Ingeklapte zijbalk. De knop en de JS zitten allebei in deze RCL (MainLayout rendert #sidebar-toggle,
   adm-shell.js zet de klasse op <html> en onthoudt ze in een cookie) — dus hoort ook de bijbehorende CSS
   hier. Stond ze alleen in de app-CSS van CreditSoft en ADM One, waardoor de knop in elke andere app wél
   de klasse zette maar er zichtbaar niets gebeurde.
   Wordt een smalle icoon-balk: labels/secties/versie verbergen, iconen blijven. */
html.adm-sidebar-collapsed .sidebar { flex-basis: 54px; padding: 12px 6px; }
/* Subtiel, thema-volgend verloop op de ingeklapte rail: bovenaan ~canvas, onderaan iets meer tint. Puur
   cosmetisch (een vleugje diepte), enkel in de smalle icoon-strook — de uitgeklapte balk blijft plat zodat
   het nav-verloop de labels/actieve-staat niet stoort. Zelfde theme-adaptieve truc als `.shell .sidebar`:
   een lichte tint van de TEKSTkleur (flipt licht↔dark) over de canvas, met `transparent` als 2e color-mix-arg
   (een `var()` daar wordt in een gelinkte stylesheet niet toegepast — Chrome 148, zie `.shell .sidebar`). */
html.adm-sidebar-collapsed .sidebar {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--bs-body-color) 2%, transparent) 0%,
        color-mix(in srgb, var(--bs-body-color) 12%, transparent) 100%);
}
html.adm-sidebar-collapsed .sidebar .nav-link { justify-content: center; padding: 8px; }
html.adm-sidebar-collapsed .sidebar .nav-link span,
html.adm-sidebar-collapsed .sidebar .nav-section,
html.adm-sidebar-collapsed .sidebar .nav-user,
html.adm-sidebar-collapsed .sidebar .nav-version { display: none; }
/* In de mini-rail: toon álle item-iconen, ongeacht sectie-collapse (de rail is een snelle icoon-strip; de
   sectiekoppen zijn er toch verborgen). */
html.adm-sidebar-collapsed .sidebar .nav-section-items.collapsed { display: block; }

/* ── DevExpress-kolomkoppen: uitlijning ─────────────────────────────────────────────────────────────
   `CaptionAlignment` zet wel `.dxbl-align-right`/`.dxbl-align-center` op de kop, maar in de praktijk komt
   die kop toch niet mee: nagemeten op 26.1.3 blijft `justify-content` op `normal` staan, en
   `.dxbl-grid-header-content` is een FLEX-container — daar doet de `text-align` die DevExpress wél zet
   niets. Gevolg: "Prijs" links boven een kolom met rechts uitgelijnde bedragen.

   Dit is bewust een correctie op DevExpress zelf (`.dxbl-*`), niet op AdmGrid: ze geldt voor élke DxGrid
   in de app, ook eentje zonder AdmGrid eromheen. Ze hoort daarom hier en niet in de app-CSS.
   (Gemeld + gemeten door de Damc-sessie, 22/07.) */
.dxbl-grid-header-content.dxbl-align-right  { justify-content: flex-end; }
.dxbl-grid-header-content.dxbl-align-center { justify-content: center; }

/* De kop-span houdt 6px vrij voor de filtertrechter, óók als die verborgen is (geen filter actief).
   Bij een rechtse kop staat het opschrift daardoor 13px van de rand terwijl de waarden eronder op 7px
   staan. Enkel bij rechtse uitlijning weghalen, zodat de trechter elders zijn ruimte houdt.
   Nagemeten: kop 13px → 7px, gelijk aan de cel eronder (verschil 0). */
.dxbl-grid-header-content.dxbl-align-right > span { margin-right: 0; }

/* ── Kerncijfer-tegels (<AdmMetric> / <AdmMetricGroup>) ──────────────────────────────────────────────
   Compacte strip boven een grid, of grote dashboard-kaarten met Large="true". Kleuraccent via c-<kleur>. */
.adm-metric-group { display: flex; align-items: stretch; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.adm-metric-group.is-large {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; margin-bottom: 1.75rem;
}
/* Visuele taal v2: NEUTRALE kaart; enkel het icoon (cirkel-chip @ 12%) + de delta-pil dragen kleur —
   níét het hele vlak. Kleur volgt de betekenis. Opgemeten op de DevExpress-demo. */
.adm-metric {
    --c: #2563eb;
    display: flex; align-items: center; gap: 10px; min-width: 165px;
    background: var(--adm-card);
    border: 1px solid var(--adm-card-border);
    border-radius: var(--adm-radius);
    padding: 10px 14px;
    color: var(--bs-body-color);
}
.adm-metric-group.is-large .adm-metric { padding: 14px 18px; }
.adm-metric-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 50%;                       /* cirkel */
    background: color-mix(in srgb, var(--c) 12%, transparent);           /* 12%-tint */
    color: var(--c); flex: 0 0 auto;                                     /* volle kleur op het icoon */
}
.adm-metric-group.is-large .adm-metric-icon { width: 40px; height: 40px; }
.adm-metric-text { flex: 1 1 auto; min-width: 0; }
.adm-metric-value { font-size: 1.2rem; font-weight: 500; line-height: 1.15; }   /* neutraal, niet gekleurd */
.adm-metric-group.is-large .adm-metric-value { font-size: 1.7rem; line-height: 1.1; }
.adm-metric-label { font-size: 0.78rem; color: var(--bs-secondary-color); line-height: 1.1; }
.adm-metric-group.is-large .adm-metric-label { font-size: 0.85rem; }
.adm-metric .adm-metric-loading { color: var(--bs-secondary-color); }
/* Delta-pil: kleur naar betekenis (positief = --adm-pos, negatief = --adm-neg), 12%-tint + volle tekst. */
.adm-metric-delta {
    flex: 0 0 auto; font-size: 0.72rem; font-weight: 500; line-height: 1;
    border-radius: 999px; padding: 3px 8px;
    background: color-mix(in srgb, var(--dc, var(--bs-secondary-color)) 12%, transparent);
    color: var(--dc, var(--bs-secondary-color));
}
.adm-metric-delta.positive { --dc: var(--adm-pos); }
.adm-metric-delta.negative { --dc: var(--adm-neg); }
/* Icoon-chip-accenten (categorie of betekenis). */
.adm-metric.c-blue   { --c: #2563eb; }
.adm-metric.c-violet { --c: #7c3aed; }
.adm-metric.c-teal   { --c: #0d9488; }
.adm-metric.c-green  { --c: var(--adm-pos, #059669); }
.adm-metric.c-amber  { --c: #d97706; }
.adm-metric.c-red    { --c: var(--adm-neg, #dc2626); }
/* Klikbare tegel (Href): geen link-opmaak + subtiele hover. */
a.adm-metric { text-decoration: none; color: inherit; transition: border-color .12s ease, background .12s ease; }
a.adm-metric:hover { border-color: color-mix(in srgb, var(--c) 45%, var(--adm-card-border)); }

/* ── Fout-grens (<AdmErrorBoundary>) ────────────────────────────────────────────────────────────────── */
.adm-errorboundary {
    max-width: 560px; margin: 2rem auto; padding: 20px 24px;
    background: var(--bs-body-bg);
    border: 1px solid color-mix(in srgb, #dc2626 30%, transparent);
    border-radius: 12px;
}
.adm-eb-title { font-size: 1.1rem; font-weight: 600; margin: 0 0 6px; color: #b91c1c; }
.adm-eb-text  { font-size: 0.9rem; color: var(--bs-secondary-color); margin: 0 0 14px; line-height: 1.4; }
.adm-eb-btn {
    border: 1px solid var(--bs-border-color); background: var(--bs-body-bg); color: var(--bs-body-color);
    border-radius: 8px; padding: 7px 16px; font-size: 0.9rem; cursor: pointer;
}
.adm-eb-btn:hover { background: var(--bs-tertiary-bg); }

/* ── Focusrand: enkel bij toetsenbord, niet bij muis/programmatisch (WCAG 2.4.7) ───────────────────────
   Vloot-brede regel: elk klikbaar/focusbaar element (knop, link, of iets met tabindex) toont de
   browser-focusrand ENKEL bij échte toetsenbordnavigatie (:focus-visible), nooit na een muisklik of na het
   sluiten van een popup. Zonder deze blanket-regel valt élke NIEUWE custom-knop/link in een app terug op de
   zwarte UA-rand (de per-element-regels hierboven dekken enkel de grid-onderdelen die de shell zelf kent) —
   dat per app opvangen = drift. De zichtbare :focus-visible-rand voor toegankelijkheid blijft; die zetten de
   per-element-regels. `:where(...)` heeft 0 specificiteit, dus een app kan dit altijd overschrijven.

   De <h1> staat er apart bij: Routes.razor bevat `<FocusOnNavigate Selector="h1" />` — bij elke navigatie
   verplaatst Blazor de focus naar de titel zodat een schermlezer die voorleest (toegankelijkheid; blijft).
   Neveneffect zonder deze regel: de browser tekent een 'kader' rond die titel bij élke paginawissel. */
:where(button, a, [tabindex]):focus:not(:focus-visible),
h1:focus:not(:focus-visible) { outline: none; }

/* ── Hub-tegels: groepstitel ───────────────────────────────────────────────────────────────────────────
   Losse (niet-scoped) klasse voor een groepstitel tussen tegelblokken in een beheer-hub (AdmHubTileGrid /
   AdmHubTile). De tegels zelf zitten in de scoped component-CSS; dit is de losse tussentitel die de consument
   in z'n hub-pagina plaatst. */
.hub-group-label {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--bs-secondary-color);
    font-weight: 600;
    margin: 22px 0 10px;
}
.hub-group-label:first-of-type { margin-top: 8px; }

/* ── AdmDetailDrawer · rail-modus (vaste smalle zijbalk rechts) ─────────────────────────────────────────
   Deze regels staan GLOBAAL (niet scoped): de mini-toestandsklasse `.adm-detail-drawer--mini` zet DevExpress
   op de drawer-root — een scoped selector (die het component-attribuut aan elke schakel plakt) bereikt die
   root niet. De binnenelementen (__rail/__full) zijn de onze; ze matchen hier op kale klassenaam.

   Gedrag: dicht = DxDrawer mini-modus toont de smalle balk (__rail, verticale titel); open = het volle paneel
   (__full). We wisselen puur op de aanwezigheid van --mini. */
.adm-detail-drawer__full {
    display: flex;
    flex-direction: column;
    /* DevExpress' drawer-body is een flex-container; zonder expliciete breedte krimpt dit paneel tot z'n
       content-breedte en blijft er rechts een gat (kop-knoppen/rijen/voettekst schuiven mee naar links).
       width:100% + flex:1 dwingen af dat het de volle body-breedte vult → links en rechts symmetrisch. */
    width: 100%;
    flex: 1 1 auto;
    height: 100%;
    min-height: 0;
}

/* De mini-panel-body van DevExpress is een flex-container; een gewone flex-child klapt hier tot breedte 0.
   We vullen de balk daarom absoluut binnen de body (die we relatief maken) i.p.v. via flex-sizing. */
.adm-detail-drawer--rail .dxbl-drawer-body { position: relative; }

.adm-detail-drawer__rail {
    display: none;
    position: absolute;
    inset: 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    padding: 0.75rem 0;
    border: 0;
    background: transparent;
    color: var(--bs-body-color);
    cursor: pointer;
    font-family: inherit;
    transition: background-color .12s ease, color .12s ease;
}

/* Ingeklapt: toon de balk, verberg het volle paneel. */
.adm-detail-drawer--mini .adm-detail-drawer__rail { display: flex; }
.adm-detail-drawer--mini .adm-detail-drawer__full { display: none; }

.adm-detail-drawer__rail:hover {
    background: color-mix(in srgb, currentColor 9%, transparent);
    color: var(--bs-primary);
}

.adm-detail-drawer__rail-label {
    writing-mode: vertical-rl;
    transform: rotate(180deg);   /* bij een rechter balk leest de titel van onder naar boven */
    font-weight: 600;
    font-size: 0.82rem;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

/* Canvas-gutter tussen de lijst-kaart en het rail-paneel: de twee omranden mogen NIET aan elkaar plakken
   (gemeld door Dominique 03/08 — hij wil een gap in de achtergrondkleur tussen de rand rond de lijst en de rand
   rond het zijpaneel). De drawer-root is een flex-row met transparante achtergrond; een column-gap toont dus de
   canvas ertussen. De content is `flex:1 1 auto` en krimpt mee → geen overloop. */
.adm-detail-drawer--rail {
    /* Smalle canvas-gutter tussen de lijst en het rail-paneel (gemeld door Dominique 03/08 — de twee randen
       mochten niet aan elkaar plakken, maar een klein gapje volstaat). Achtergrond = canvas → de gutter toont
       altijd de achtergrondkleur, ook als een app de drawer op een wit vlak zet. Flipt mee in dark. */
    column-gap: 8px;
    background: var(--adm-canvas, #f4f4f3);
}
/* Het paneel is nu een losse kaart naast de lijst: eigen rand rondom + afronding + kaart-achtergrond, i.p.v. enkel
   een scheidingslijn links. Strakkere binnenmarge (DevExpress zet standaard 24px l/r — te veel in een smal paneel). */
.adm-detail-drawer--rail .dxbl-drawer-panel {
    border: 1px solid var(--adm-card-border, #d3d3d2);
    border-radius: var(--adm-radius, 6px);
    background: var(--adm-card, #fff);
    /* Gestandaardiseerde horizontale binnenmarge (gutter) voor ALLES in het paneel: de foundation-kop (titel +
       actieknoppen) ÉN de app-ChildContent zitten allebei binnen deze DevExpress panel-body-padding, dus ze lijnen
       out-of-the-box uit. APPS: zet GEEN eigen horizontale padding op je drawer-inhoud — die zou de app-inhoud t.o.v.
       de foundation-titel/sectielijn verschuiven (gemeld door CreditSoft 03/08). Eén knop om te tunen: --adm-drawer-gutter. */
    --dxbl-drawer-panel-body-padding-x: var(--adm-drawer-gutter, 16px);
}
/* Animatie tijdelijk uit (voor het HERSTELLEN van de gepersisteerde open-stand bij paginalaad): het journaal moet
   dan meteen in z'n bewaarde stand staan, niet openschuiven. Bij een echte GEBRUIKERS-actie (klik openen/sluiten)
   staat deze klasse er niet → dan animeert het wél. Gemeld door Dominique (03/08). */
.adm-detail-drawer--no-anim { --dxbl-drawer-animation-duration: 0s; }

/* ── Actieve (gefocuste) rij in AdmGrid/AdmTreeList ────────────────────────────────────────────────────
   De FOCUS is de enige actieve-rij-markering (enkelvoudige klik-selectie staat uit → geen blijvende "tweede"
   highlight). DevExpress geeft de gefocuste rij standaard een VOLLE accent-vulling en maakt enkel gewone celtekst
   wit — links (e-mail), gekleurde status-tekst (bv. "Fase") én actie-iconen (potlood/vink) behielden dan hun eigen
   kleur → blauw-op-blauw / zwart-op-blauw / onzichtbaar. Daarom een SUBTIELE tint + een accentbalk links i.p.v. de
   volle vulling: zo blijft ALLE celinhoud vanzelf leesbaar, zonder iets naar wit te moeten forceren.
   Gemeld door Dominique (03/08). */
.dxbl-grid-focused-row,
.dxbl-treelist-focused-row,
.dxbl-grid-focused-row > td,
.dxbl-treelist-focused-row > td {
    /* OPAQUE tint (gemengd met de rij-achtergrond, niet met 'transparent') — anders schijnt DevExpress' volle
       blauwe rij-vulling eronder er nog doorheen. Zowel de rij als de cellen overschrijven → volledig gedekt. */
    background-color: color-mix(in srgb, var(--bs-primary) 12%, var(--bs-body-bg, #fff)) !important;
    color: var(--bs-body-color) !important;
}
.dxbl-grid-focused-row > td:first-child,
.dxbl-treelist-focused-row > td:first-child {
    box-shadow: inset 3px 0 0 0 var(--bs-primary);
}
/* DevExpress kleurt op de gefocuste rij de link-knop-inhoud bijna wit (via `--dxbl-grid-focus-color`, bedoeld voor
   de oude volle blauwe vulling) → command-iconen (svg volgt `currentColor`) worden onleesbaar op onze subtiele tint.
   Reset naar de leesbare inhoudskleur. Specificiteit bewust laag (0,2,0): een bewust-gekleurde icoonknop (bv. een
   groene "factureer"-actie via `.grid-action-btn.ga-invoice`, óók 0,2,0) wint op BRONVOLGORDE — app.css laadt ná
   adm-shell.css → z'n eigen kleur blijft. End-to-end getest door DAMC (03/08). */
.dxbl-grid-focused-row .dxbl-btn-link,
.dxbl-treelist-focused-row .dxbl-btn-link {
    color: var(--bs-body-color);
}

/* Verantwoordelijke in de takenlijst: een naam, dus iets steviger dan de datums eromheen. */
.adm-task-wie { color: var(--bs-body-color); font-weight: 500; }

/* ── Voorkeuren-pagina (PreferencesView) ─────────────────────────────────────────────────────────────
   De tegenhanger van de lade: hier is wél plaats voor label, uitleg en validatie. De index links blijft
   staan bij het scrollen, want een voorkeurenlijst die groeit is precies het geval waarvoor ze bedoeld is. */
.adm-prefs-page { max-width: 1100px; }
.adm-prefs-title { font-size: 1.4rem; font-weight: 600; margin-bottom: 20px; }
.adm-prefs-layout { display: flex; gap: 32px; align-items: flex-start; }
.adm-prefs-index {
    flex: 0 0 200px; display: flex; flex-direction: column; gap: 2px;
    position: sticky; top: 16px;
}
.adm-prefs-index-link {
    padding: 6px 10px; border-radius: 6px; text-decoration: none;
    color: var(--bs-secondary-color); font-size: 0.9rem;
}
.adm-prefs-index-link:hover { background: var(--bs-secondary-bg); color: var(--bs-body-color); }
.adm-prefs-sections { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 28px; }
.adm-prefs-section {
    border: 1px solid var(--bs-border-color); border-radius: 10px; padding: 18px 20px;
    background: var(--bs-body-bg); scroll-margin-top: 16px;
}
.adm-prefs-section-title {
    font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--bs-secondary-color); font-weight: 600; margin: 0 0 14px;
}

/* Onder de 900px verdwijnt de index: twee kolommen van 200px + inhoud werkt niet op een tablet, en een
   index die smaller wordt dan zijn eigen labels is erger dan geen index. */
@media (max-width: 900px) {
    .adm-prefs-layout { flex-direction: column; gap: 16px; }
    .adm-prefs-index { display: none; }
}

/* "Als standaard voor iedereen" onderaan een voorkeuren-sectie (AdmPlatformDefault). Bewust rustig: het is
   een beheerhandeling naast de gewone bewaarknop, geen tweede primaire actie. */
.adm-prefs-default {
    display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
    margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--bs-border-color);
    font-size: 0.85rem;
}
.adm-prefs-default-uitleg { color: var(--bs-secondary-color); }

/* ── Topbar-actie (AppKitOptions.TopBarActionsComponent) ──────────────────────────────────────────────
   De app-eigen snelknop in de bovenbalk, bv. "Nieuwe taak".

   ⚠️ Waarom deze klasse bestaat. De fundering bood wél het SLOT maar géén stijl, dus moest elke app de vorm
   zelf verzinnen. CreditSoft greep naar een DxButton en kreeg een geránde knop naast de ghost-icoonknoppen
   (maan, bel, chat, ?, sparkle, avatar) — Dominique zag dat meteen: "jouw stijl past wel mooier in de header."
   Hij had gelijk, en het lag niet aan hun keuze maar aan mijn gat: een slot zonder stijl is een uitnodiging om
   iets te verzinnen.

   Dit is dezelfde ghost-familie als .icon-btn ernaast en .adm-grid-add in de werkbalk: transparant, geen rand,
   gewicht 400, hover als een overlay op currentColor zodat ze in beide thema's meeflipt. Bewust GÉÉN accent —
   het accent blijft voorbehouden voor betekenis, niet voor "dit is een knop". */
.adm-topbar-action {
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
    padding: 6px 10px; border: 0; background: transparent; border-radius: 8px;
    color: var(--bs-body-color); font-size: 0.9rem; font-weight: 400; cursor: pointer;
    font-family: inherit; line-height: 1.4;
}
.adm-topbar-action:hover { background: color-mix(in srgb, currentColor 9%, transparent); }
.adm-topbar-action:disabled { opacity: .5; cursor: default; }
.adm-topbar-action:disabled:hover { background: transparent; }
.adm-topbar-action .adm-icon { flex: 0 0 auto; color: var(--bs-secondary-color); }

/* === AdmFichePagina =========================================================================== */
/* De schil onder elke entiteitsfiche (AppKit 0.162.0). Overgenomen uit adm-creditsoft, waar deze vorm op
   15–16/08/2026 in zes fiches gegroeid is; de uitleg hieronder komt uit hun commentaar en blijft staan omdat
   je zonder die uitleg alle drie de keuzes verkeerd raadt.

   ⚠️ De BREEDTE hoort hier en nergens anders. In CreditSoft stonden er op 16/08 drie caps naast elkaar:
   .content-inner op 1100px (die werkt), vijf fiches met een inline max-width van 1200px (die nooit bindt,
   want groter dan de ouder) en Bedrijfsfiche op 1000px (die wél bindt). Gevolg: één fiche ~52px smaller dan
   de vijf andere, en niemand zag waarom — die 1200 óógt als een beslissing. */
.adm-fiche {
    /* Links, niet gecentreerd (beslist 16/08/2026). Centreren laat de inhoud zijwaarts springen wanneer je
       van een volle-breedte lijst naar een fiche navigeert; links blijft de linkerrand staan, en dáár staan
       de titel, de labels en de eerste kolom.

       ⚠️ DEZE KEUZE IS NIET BEZONKEN, en dat hoort hier te staan. Dominique kwam er dezelfde avond op terug:
       "ik blijf struggelen met het links aligneren, maar we laten het voorlopig zo". Het alternatief is
       centreren, zoals Billit doet. Blijft het schuren, dan is de echte vraag niet "links of gecentreerd" maar
       wat er op een breed scherm rechts van die 1100 px hoort te gebeuren — nu is dat leegte, en leegte is wat
       het oog als scheef leest. Wie hier ooit aan raakt: het is één regel, maar ze geldt vloot-breed en raakt
       elke fiche tegelijk. */
    max-width: var(--adm-fiche-breedte, 1100px);

    /* ── Volle hoogte, onvoorwaardelijk sinds 0.262.0 ──────────────────────────────────────────────────
       Een fiche is een hoogte-kolom. Dit stond hiervoor in een apart blok achter `:has(.adm-fiche-tabstrip-
       vullend)` — een vlag die per tab gezet moest worden en die over vijf apps door NUL tabs gezet werd. */
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

/* Een fiche die de volle breedte nodig heeft: `<AdmFichePagina Breed="true">`.
   ⚠️ Waarom dit bestaat, en waarom het níét "gewoon een grotere max-width" is. De leescap van 1100px is
   juist voor een formulier — regels van 2000px lezen niet. Maar een fiche met een TABEL erin (prijslijnen,
   taken, factuurregels) heeft die ruimte wél nodig, en dan is de cap schadelijk in plaats van behulpzaam.
   Ontdekt op 16/08/2026 bij de eerste echte adoptie: DAMC zet tien schermen op volle breedte, met de reden
   erbij in commentaar — "zodat de rechterkolom met prijs-/takentabellen alle ruimte krijgt". Een schil die
   dat niet kan, wordt niet aangezet.

   Twee regels, want er zijn twee caps: die van de fiche zelf en die van .content-inner erboven. Zonder de
   tweede blijft de pagina op 1100px staan en lijkt Breed="true" stil niets te doen.

   De app hoefde hier tot nu een eigen klasse voor te verzinnen — .adm-wide in DAMC, .adm-page-wide in de
   scaffold. Drie namen voor één idee is precies hoe drift begint; dit is de vloot-brede naam. */
.adm-fiche-breed { max-width: none; }
.content:has(.adm-fiche-breed) > .content-inner { max-width: none; }

/* Hoogte doorgeven aan een fiche waarvan de ACTIEVE tab schermvullend is.

   ⚠️ WAAROM DIT HIER STAAT EN NIET IN DE APP. `Vullend` is geen keuze van een app: NaarFicheTabs zet het op
   ÉLKE journaal-tab. De schil vroeg dus schermvullend gedrag en liet het doorgeven van de hoogte aan de app
   over — beschreven in een commentaarblok, nergens afgedwongen. Wie die vier regels niet kende, kreeg een tab
   die om volle hoogte vraagt en ze stil niet krijgt: geen fout, geen waarschuwing, alleen een pagina die
   uitrekt in plaats van een lijst die scrollt.

   Gemeten op 21/08/2026 over de vloot: van de vijf apps met journaal-tabs had er ÉÉN de regel (CreditSoft, die
   ze op 16/08 zelf ontdekte na een fiche van 3237px bij 33 mails, terwijl de scroller op 1272 stond — de
   PAGINA scrolde en de tabstrook schoof uit beeld). De andere vier wisten van niets. Dominique zag het verschil
   zonder de oorzaak te kennen: "de weergave van CreditSoft is veel professioneler door het duidelijke vlak met
   de witte rand over de ganse hoogte."

   Een voorwaarde die in een commentaar staat, is geen voorwaarde. De schil bezit deze layout (MainLayout
   rendert .content-inner), dus de schil brengt dit zelf mee — precies zoals bij .adm-fiche-breed hierboven.

   ⚠️ ALLEEN wanneer de actieve tab vullend is, vandaar :has(...). Een blanco height:100% zou élke pagina een
   vaste hoogte geven en een lang formulier afkappen in plaats van laten groeien. Op een record-tab groeit de
   pagina dus gewoon mee zoals altijd. */
/* ⚠️ Sinds 22/08/2026 op `.adm-fiche` en niet meer op `.adm-fiche-tabstrip-vullend`.

   De nota hierboven zegt terecht dat een blanco `height:100%` élke pagina zou afkappen. Dat blijft waar — de
   fout zat in wáár de voorwaarde aan hing. Ze hing aan een VLAG die per tab gezet moest worden, en die vlag
   zette niemand: nul van alle tabs in Nimble, CreditSoft, DAMC, CleanOps en Auto's Bart.

   Nu hangt ze aan de ZAAK: is dit een fiche, dan is de pagina een hoogte-kolom. Een gewone pagina raakt dit
   niet en groeit zoals altijd. En het afkappen is opgelost waar het hoort — `.adm-fiche-tabinhoud` krijgt
   hieronder zijn eigen schuifbalk in plaats van te klemmen.

   Drie voorwaarden die allemaal opt-in waren en alle drie stil faalden, is geen conventie maar een
   ontwerpfout. Dit is de laatste van de drie die omgaat. */
.content-inner:has(.adm-fiche) {
    height: 100%;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* De actiebalk blijft onderaan in beeld, ook bij een lange fiche: een fiche is al gauw 1000px en het scherm
   van een tester soms 620. Zonder dit moet je scrollen om te kunnen bewaren, en dat wordt erger naarmate de
   fiche groeit. Plakt binnen de scrollende MAIN.content. */
.adm-fiche-acties {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    gap: .5rem;
    /* Alles rechts. Geen ontsnappingsroute — beslist 16/08/2026, en er stond hier tot 0.166.0 een
       commentaarregel die naar een klasse `.adm-fiche-acties-links` verwees die NOOIT bestaan heeft. Nul
       treffers in de hele bron. Wie die aanwijzing volgde, kreeg stil niets: geen foutmelding, de knop bleef
       rechts. Gemeld door de CreditSoft-sessie.

       ⚠️ Een element met `flex-grow` of een auto-marge (`ms-auto`, `flex-grow-1`) BINNEN deze balk maakt de
       uitlijning stil ongedaan: het slokt de vrije ruimte op en dan blijven de knoppen links staan. Bij
       CreditSoft gebeurde dat op vijf van de zes fiches, zonder dat iets het meldde — ze hadden een
       tussenstuk als veiligheidsafstand tussen Annuleren en Verwijderen. `AdmDeployChecklist.Fichepagina`
       betrapt dat sinds 0.166.0. */
    justify-content: flex-end;
    /* ⚠️ Géén ZIJmarge. De knoppen lijnen uit op de BUITENrand van de kaarten, niet op de velden bínnen die
       kaarten. Een binnenmarge van 16px lijkt logischer, maar is fout zodra de balk geen zichtbare container
       heeft: dan zijn de kaartranden de enige verticale lijnen op de pagina, en alles wat daar niet op ligt
       oogt zwevend. */
    padding: .75rem 0;
    /* ⚠️ Ademruimte boven de balk, en 4px is te weinig. Overgenomen uit CreditSoft stond hier .25rem; gemeten
       in DAMC op 16/08/2026 eindigde de dichtstbijzijnde kaart daardoor op 4 px van de scheidingslijn. Dat
       leest als een fout in plaats van als een rand. Dominique zag het op een schermafdruk.

       Waarom marge en geen scrollaanloop onder de inhoud: dat was mijn eerste voorstel, en het meten wees uit
       dat het niet nodig is. Bij een fiche die langer is dan het scherm staat de balk op het scrolleinde op
       zijn natuurlijke plek en is álle inhoud erboven zichtbaar (gemeten: balk 20 px boven de vensterrand).
       Onder de balk verdwijnen doet de inhoud enkel tíjdens het scrollen, en dat is wat een plakkende balk
       hoort te doen. Het probleem was dus de rand, niet de aanloop. */
    margin-top: 1.25rem;
    /* ⚠️ Ondoorzichtig, en de kleur van de PAGINA — niet wit en niet transparant. Wit leest als een kaart
       zonder randen; transparant laat de velden dwars door de knoppen scrollen, want de balk plakt. */
    background: var(--adm-canvas);
    border-top: 1px solid var(--adm-card-border);
}

/* Tabbladen op een fiche: het inhoudspaneel houdt de hoogte van de langste tab aan, zodat wisselen de fiche
   niet doet springen. Zet --adm-tab-minh per fiche.

   ⚠️ DIT IS EEN AFWEGING EN GEEN VERBETERING ZONDER KEERZIJDE. De prijs van een vaste hoogte is dat het
   kórtste tabblad altijd een leegte toont ter grootte van het verschil met het langste. Loont wanneer de
   tabbladen ongeveer even lang zijn; werkt tegen wanneer ze sterk verschillen.

   Correctie op het getal dat hier stond. Tot 0.176.0 vermeldde deze nota "~500 px" voor CreditSoft's
   RelationDetail. Nagemeten door de CreditSoft-sessie op 16/08/2026: op het type PARTICULIER is het verschil
   234 px (Algemene informatie 706, Bijkomende informatie 472). De 500 sloeg vermoedelijk op het bedrijfstype
   en is nooit nagemeten. Een getal in een nota dat niemand meer kan herleiden, weegt in de volgende beslissing
   even zwaar als een gemeten getal — vandaar dat het hier vervangen is en niet aangevuld.

   ⚠️ En de sprong is op een PAGINA ook minder erg dan in een pop-up, waar deze truc vandaan komt: een pop-up
   springt zichtbaar op als hij van hoogte verandert, een pagina wordt gewoon korter — en de actiebalk plakt
   toch onderaan het scherm.

   Correctie op wat hier tot 0.166.0 stond: ik schreef dat de klasse in CreditSoft dode code was omdat iemand
   vergat ze te gebruiken. Dat klopte niet. Er stond in `RelationDetail.razor` een uitgeschreven redenering
   waarom die fiche géén vaste tabhoogte krijgt. Nul treffers gemeten en "vergeten" geconcludeerd — dat is een
   conclusie voorbij de meting. Zij hebben de regel intussen geschrapt, met die reden erbij. */
.adm-fiche-tabstrip .dxbl-tabs-content-panel {
    /* De hoogte-keten loopt hier dóór naar de tab-inhoud. `min-height: 0` moet, anders weigert een flex-kind
       te krimpen en scrollt de PAGINA in plaats van de lijst. */
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

/* ── De tabstrip die AdmFichePagina zélf bezit (Tabs + Gerelateerd), sinds 0.177.0 ────────────────────────
   Twee groepen in ÉÉN strip: links het record, rechts wat eraan hangt. De scheiding is witruimte en geen
   lijn — op een smal scherm vallen de tabs onder elkaar en dan scheidt een lijn niets meer, terwijl de
   witruimte gewoon verdwijnt zonder rommel achter te laten.

   ⚠️ De duw naar rechts moet op de <li>, niet op het element dat onze klasse draagt. DevExpress rendert
   `<ul><li><dxbl-tab-item class="…">`, en de FLEX-ITEMS zijn de li's. Onze CssClass landt op het tab-item
   daarbinnen; `margin-left: auto` doet daar niets en rekent stil af op 0px. Gemeten in de playground op
   16/08/2026 — de eerste versie van deze regel stond op het tab-item en de tabs bleven gewoon links staan,
   zonder enige melding. Vandaar `:has()`: het tilt de duw naar de li die ons item bevat. */
.adm-fiche-tabstrip li:has(> .adm-fiche-tab-groepstart) { margin-left: auto; }

/* ⚠️ HET VULLENDE HOOGTEMODEL — het echte risico van dit component, en het is vóór de bouw gemeld.

   Een record-tab groeit met haar inhoud (bij CreditSoft gemeten: 472 tot 706 px). Een gerelateerde tab met
   een mailhistoriek of een bijlagenlijst hoort schermvullend te zijn. Dat zijn TWEE HOOGTEMODELLEN in één
   tabstrip, en `FullHeight` werkt enkel met een ONONDERBROKEN flex-keten: elke tussenliggende doos moet
   flex-kolom zijn met `min-height: 0`. Eén schakel die dat niet is en de grid klapt dicht — de bouw is
   groen, de test is groen, en enkel het scherm toont wit. Dat is exact hoe 0.170.0 strandde op de
   `.adm-useradmin`-wikkel.

   Daarom staat de keten hier VOLLEDIG uitgeschreven, en enkel voor de tab die erom vraagt (Vullend="true").
   Meng het niet: een formulier in een vullende tab rekt zijn laatste veld uit tot onderaan het scherm.

   ⚠️ Dat we hier `.dxbl-tabs-content-panel` aanspreken is DevExpress' interne DOM, en dat is broos — het kan
   bij een DX-upgrade van vorm veranderen. Het verschil met een app die hetzelfde doet: dit staat in de
   fundering, het draait in de playground (/fiche-tabs), en één plek breekt zichtbaar in plaats van tien
   plekken stil. Dat is de reden dat dit hier hoort en niet in een app.css. */
/* ⚠️ VOORWAARDE: JE APP-SHELL MOET HOOGTE DOORGEVEN, anders doet `Vullend` niets.

   `flex: 1` hieronder werkt alleen als de OUDER een flex-kolom is met een echte hoogte. Zit `.adm-fiche` in een
   gewone `display: block`-container, dan is deze regel een lege huls: geen fout, geen melding, en de tab groeit
   gewoon door tot de pagina scrolt.

   Dat is exact dezelfde ongeschreven voorwaarde als bij `AdmDetailDrawer` — die schreef ik op 16/08/2026 op, en
   maakte hem diezelfde avond hier opnieuw: in onze playground zat `.adm-fiche` rechtstreeks in `<body>`
   (display: block), dus kón de vullende tab daar niet werken, en mijn "pagina scrolt niet"-meting bewees enkel
   dat de grid zichzelf begrensde. Een voorwaarde die je in het ene component opschrijft en in het volgende
   vergeet, is nog geen conventie. */
/* ⚠️ ONVOORWAARDELIJK sinds 22/08/2026, en dat is het hele punt.

   Dit stond als `.adm-fiche:has(.adm-fiche-tabstrip-vullend)` — de keten kwam er dus enkel wanneer een tab
   `Vullend` zette. Gemeten die dag over Nimble, CreditSoft, DAMC, CleanOps en Auto's Bart: NUL tabs zetten
   die vlag. De volle-hoogte-stand bestond, was gestyled, en had geen enkele gebruiker.

   Dominique vond het door in Nimble één relatiefiche te openen. `Fichepagina` stond groen, want die vraagt
   "gebruikt deze fiche de schil?" — en dat deed ze. Alleen bewaakt die vraag iets anders dan de afspraak
   (volle hoogte, lay-out zoals CreditSoft). Ik had de regel meetbaar gemaakt door hem kleiner te maken, en
   dat nooit hardop gezegd.

   Een fiche is nu altijd een hoogte-kolom. Vergeten levert daarmee het JUISTE resultaat op in plaats van het
   verkeerde — dat is de enige vorm waarin zo'n afspraak standhoudt. `Vullend` bepaalt nog steeds of de
   INHOUD van een tab meerekt (een grid) of bovenaan blijft staan (een formulier); dat onderscheid is echt en
   blijft. */

.adm-fiche-tabstrip {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}


/* ⚠️ WAT ER IN 0.177.0 ONTBRAK — en het was NIET wat we allebei eerst dachten.

   Het symptoom, gemeten door de CreditSoft-sessie op een echte relatie (30 taken, 23 notities, 20 bijlagen,
   33 mails): de PAGINA scrolde 1968 px en de tabstrook schoof uit beeld. Precies het geval waarvoor we de tabs
   boven de lade gekozen hadden.

   Er zijn DRIE voorwaarden, en ze zijn alle drie nodig. Dat kostte me twee meetrondes, want elke ontbrekende
   voorwaarde afzonderlijk geeft hetzelfde beeld:

     1. de app-shell geeft hoogte door      → zie de nota bij `.adm-fiche:has(…)` hierboven
     2. `.dxbl-tabs-content` mag krimpen    → deze regel
     3. de vullende tab scrollt zelf        → de `overflow-y` hieronder

   Gemeten, met telkens één voorwaarde uitgezet (venster 1324, 40 notities):

     alle drie                pagina    0 px   lijst scrolt binnenin
     zonder 1                 pagina +1255 px  tabstrook UIT BEELD   ← het gemelde symptoom
     zonder 2 of 3            pagina +1228 px  tabinhoud 2255 px, niets te scrollen

   ⚠️ WAT DE BLOKKADE PRECIES IS — en het is NIET `min-height`. DevExpress zet op `.dxbl-tabs-content` zelf al
   `min-height: 0` (nagemeten: `0px`, ook zónder onze regel). De blokkade is `display: block`: een blok-element
   geeft de flex-context niet door, dus alles eronder rekt uit tot de inhoudshoogte. Wat deze regel toevoegt is
   dus de `display: flex`; de `min-height: 0` staat er defensief bij voor als DX de zijne ooit weghaalt.

   ⚠️ EN EEN WAARSCHUWING OVER HOE JE DIT MEET — twee keer ben ik hier de mist in gegaan:

   1. Ik haalde deze regel eerst wéér weg omdat een proef zei dat ze niets deed. Die proef was waardeloos: mijn
      demo-lijst had op dat moment ZELF `overflow-y: auto` en `flex: 1 1 0%`, dus ze begrensde zichzelf en de
      keten hoefde niets te doen.
   2. Daarna probeerde ik te saboteren met inline styles vanuit de console. Dat bijt niet: de berekende
      `min-height` bleef `0px`, dus de sabotage veranderde niets en de proef bleef groen om de verkeerde reden.

   De enige zuivere proef bleek: de regel ECHT uit dit bestand halen, herbouwen, meten. Dán pas: pagina +1228 px,
   tab 2255 px, niets te scrollen. Een sabotage die je niet kunt zien aanslaan, bewijst niets — ook niet groen. */
/* ⚠️ DIT ELEMENT STAAT OP `position: absolute` — gemeten in de browser op 22/08/2026, niet gelezen.

   Daardoor deden de flex-eigenschappen hieronder NIETS: een absoluut gepositioneerd element ligt buiten de
   flow, dus `flex: 1` en `min-height: 0` zijn er betekenisloos. De keten leek compleet — elke schakel had
   netjes zijn drie eigenschappen — en brak stil op deze ene. Gemeten: het paneel erboven was 473 px, dit
   element 91.

   Precies de reden dat de nota bovenaan dit blok DevExpress' interne DOM "bros" noemt. Je kunt dit niet uit
   de code afleiden; je moet het openen en meten.

   De ingreep is klein en raakt hun animatie niet: het paneel wordt het positioneringsanker (`relative`) en de
   inhoud krijgt volle hoogte. Hun eigen horizontale plaatsing voor het wisselen blijft staan — vandaar
   `height` en niet `inset: 0`, wat die plaatsing zou overschrijven en twee tabbladen over elkaar zou leggen. */
.adm-fiche-tabstrip .dxbl-tabs-content-panel { position: relative; }

.adm-fiche-tabstrip .dxbl-tabs-content {
    height: 100%;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* Voorwaarde 3. Dit hoort in de fundering en niet in elke app: laat je het aan de app over, dan zet de ene
   `overflow-y: auto` en de andere niet, en betekent `Vullend` twee verschillende dingen per scherm. */
/* De gewone tab-inhoud: vult de resterende hoogte en krijgt daar zélf de schuifbalk.

   ⚠️ Dit bestond niet. Er was enkel een regel voor de VULLENDE tab, en dus had een record-tab geen enkele
   hoogte-afspraak — de pagina groeide gewoon door. Dat werkte zolang de pagina zelf mocht groeien; nu de
   fiche een hoogte-kolom is, zou dezelfde tab klemmen. Vandaar de schuifbalk hier en niet op de pagina: de
   tabstrook en de actiebalk horen in beeld te blijven, en dat is precies het verschil dat Dominique bij
   CreditSoft zag ("een duidelijk vlak met witte rand over de ganse hoogte").

   `:not(...-vullend)` want een vullende tab draagt zijn eigen scroller diep in de keten (`.adm-scrollt`);
   twee schuifbalken boven elkaar is erger dan geen. */
.adm-fiche-tabinhoud {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

/* De schuifbalk komt op de tab-inhoud zelf — TENZIJ er binnenin al een `.adm-scrollt` staat die hem draagt.
   Twee schuifbalken boven elkaar is erger dan geen. */
.adm-fiche-tabinhoud:not(:has(.adm-scrollt)) { overflow-y: auto; }

/* ⚠️ EEN BOOTSTRAP-`.row` STAK ER 8 PX BUITEN, EN DAT WERD PAS ZICHTBAAR DOOR DE REGEL HIERBOVEN.

   Een `.row` draagt `margin-inline: calc(-.5 * var(--bs-gutter-x))` — een negatieve marge die opgevangen
   hoort te worden door de padding van een `.container` of een `.col`. `.adm-fiche-tabinhoud` heeft padding 0,
   dus de row is een halve gutter breder dan zijn ouder aan élke kant. Dat stond er altijd al en was
   ONZICHTBAAR, want `overflow-x` was `visible`.

   Sinds 0.262.0 staat er `overflow-y: auto`, en de CSS-spec maakt van `overflow-x` dan automatisch `auto`.
   Vanaf dat moment werd die overloop een horizontale schuifbalk onderaan élk fiche-tabblad met een row erin.
   Gemeten door de Cares-sessie (1009/997 en 1024/1012) en door Dominique gezien; nagemeten in de playground:
   container 945, row 961, overloop 8 — en op elke breedte dezelfde 8.

   Dat is de vorm die vandaag vier keer terugkwam: een container die niet meer mag overlopen, maakt overloop
   zichtbaar die er al jaren was. De wijziging heette "de fiche vult de hoogte" en het gevolg zat in de
   BREEDTE — de naam van een wijziging is geen afbakening van wat je moet nameten. */
.adm-fiche-tabinhoud > .row { margin-inline: 0; }

/* ══ De INHOUD van een tab ═════════════════════════════════════════════════════════════════════════════════

   De keten brengt de hoogte tot aan `.adm-fiche-tabinhoud`. Daar hield de fundering op, en
   wat erna kwam moest elke app zelf schrijven. Dat werd overal dezelfde lijst met eigen klassenamen:

       .adm-fiche-tabinhoud > .journaal-taken,
       .adm-fiche-tabinhoud > .journaal-notities,
       … nog drie, en bij elke nieuwe tab een regel erbij, op twee plaatsen …

   Vijf apps hebben journaal-tabs, dus vijf van die lijsten. De CreditSoft-sessie voegde op 22/08/2026 een zesde
   tab toe en moest die lijst weer uitbreiden; vergeet je dat, dan groeit de tab door en scrollt de PÁGINA in
   plaats van de lijst. Geen fout, geen waarschuwing, alleen een scherm dat niet klopt.

   ⚠️ WAAROM DIT GEEN BLINDE REGEL IS. `.adm-fiche-tabinhoud > *` lijkt de oplossing en is het niet: dat
   werkt alleen zolang een tab precies ÉÉN kind heeft. Zodra er een toolbar naast de lijst staat, krijgt die ook
   `flex: 1` en groeit hij mee. Welk kind de vaste kop is en welk de scrollende romp, is app-kennis — de schil
   kan dat niet afleiden. Vandaar drie klassen die de app zélf zet, in plaats van een lijst die ze onderhoudt.

       .adm-vast      de kop: groeit niet, krimpt niet
       .adm-vullend   vult de resterende hoogte en geeft ze dóór aan zijn eigen kinderen
       .adm-scrollt   vult de resterende hoogte en krijgt de schuifbalk (het eindpunt van de keten)

   Een journaal-tab wordt daarmee:

       <div class="journaal-bijlagen adm-vullend">
           <div class="journaal-toolbar adm-vast">…</div>
           <div class="adm-scrollt">…de lijst…</div>
       </div>

   Een zesde tab kost dan een klasse op het element in plaats van een regel in twee CSS-lijsten in vijf apps.

   ⚠️ ZET DIT NOOIT OP EEN <table> — en dit is niet theoretisch. Precies dit gaf op 22/08/2026 het beeld dat een
   tester bij CreditSoft meldde: drie bijlagen, uitgesmeerd over de volle taghoogte, met tweehonderd pixels lucht
   tussen elk bestand. Een tabel met een opgelegde hoogte verdeelt de overhoogte namelijk over de RIJEN, niet
   over zichzelf. Hetzelfde geldt voor een DevExpress-component die intern een tabel rendert.
   Pak de tabel in een `<div class="adm-scrollt">` en zet de klasse op die div. */
/* ── De inhoud van een tab die maar ÉÉN kind heeft ──────────────────────────────────────────────────────

   ⚠️ Dit is bewust `:only-child` en niet `> *`. De nota hierboven waarschuwt terecht voor die blinde vorm:
   zodra een tab een toolbar NAAST een lijst heeft, krijgt die toolbar ook `flex: 1` en groeit hij mee. Welk
   kind de vaste kop is en welk de scrollende romp, is app-kennis.

   `:only-child` grijpt per definitie enkel wanneer er niets is om mee te concurreren — dan ís dat ene kind de
   romp, en dat hoeft niemand te weten. Gemeten op 22/08/2026: de journaal-tabs in Nimble hebben precies één
   wortelelement, en dat is de gewone vorm.

   Waarom dit ertoe doet: tot vandaag moest élke app zelf een lijst onderhouden die haar tabwortels op `flex: 1`
   zette (`.adm-fiche-tabinhoud > .journaal-taken, > .journaal-notities, …`). Van de zes gemeten apps had er
   ÉÉN die lijst — CreditSoft — en de andere vijf wisten van niets. Niet omdat ze slordig waren, maar omdat het
   werk was dat je moest wéten. Een tab met meerdere kinderen houdt gewoon zijn eigen lijst; die van CreditSoft
   blijft dus staan en blijft nodig. */
/* ⚠️ `:not(.row)` — EN DIT WAS EEN ECHTE BUG, GEEN VOORZORG.

   Een Bootstrap-`.row` is zelf al een flexbox met `flex-direction: row`. Is hij het enige kind van een
   tabinhoud, dan greep de regel hieronder hem óók en zette er `flex-direction: column` op. Gevolg: de
   kolommen stapelden ALTIJD onder elkaar, ongeacht `col-lg-6` en ongeacht de vensterbreedte, met de halve
   fiche leeg ernaast.

   Gemeld door de Cares-sessie als "een row wrapt niet onder 992 px". Ze hadden het symptoom bij de verkeerde
   oorzaak gelegd — het heeft niets met de breakpoint te maken — en twee omwegen gemeten en verworpen. Terecht:
   geen van beide raakte dit.

   Nagemeten in de playground: `getComputedStyle(row).flexDirection` gaf `column`. Dezelfde row buiten de
   fiche gaf `row` en stond netjes naast elkaar. Dát verschil wees het aan; drie eerdere experimenten
   (speling op de breedte, `flex-shrink: 1`, container op `display: block`) verklaarden alle drie niets, want
   ik zocht bij de verkeerde oorzaak. De vergelijking binnen/buiten was de meting die het besliste.

   Waarom uitsluiten en niet repareren: een `.row` IS al de romp-vorm die deze regel wil maken. Hij heeft de
   hoogte-doorgifte niet nodig en hij verdraagt de richting-omzetting niet. */
.adm-fiche-tabinhoud > :only-child:not(.row) {
    /* ⚠️ Óók `display: flex`, en dat is een bewuste keuze met een risico. Zonder dit vult de WORTEL van de tab
       wel de hoogte, maar geeft ze niets door aan wat erin zit — dan zie je een lange lege doos met de lijst
       bovenaan, en dat is de fout die je niet meteen herkent als "keten gebroken".
       Het risico: staat er in die wortel iets dat op een block-layout rekent, dan herschikt dit. Aanvaardbaar
       omdat het enkel om een ENIG kind gaat — dat is in de praktijk altijd een blokcontainer — en omdat elke
       andere schakel van deze keten dezelfde drie eigenschappen zet. Eén vorm, geen uitzondering. */
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.adm-fiche-tabinhoud .adm-vast {
    flex: 0 0 auto;
}

.adm-fiche-tabinhoud .adm-vullend {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.adm-fiche-tabinhoud .adm-scrollt {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

/* De terugweg wanneer hij op een EIGEN RIJ staat — boven een lijst, een formulier of een dashboard. Op een
   fiche zit dezelfde knop in de kopregel naast de titel en levert die kopregel de afstand; daar zet
   AdmTerugKnop `Vrijstaand="false"` en verschijnt deze klasse niet.

   `.5rem` sluit aan bij de `mb-2` die de CreditSoft-sessie in hun app-component gebruikte — dat was daar
   gemeten en het werkt, dus geen reden om er iets anders van te maken.

   ⚠️ Deze klasse heette tot 0.181.0 `.adm-grid-terug`, en dat was een verkeerde naam. CreditSoft gebruikte hem
   op negen beheerschermen ZONDER grid — dat werkte (hij zit niet onder `.adm-grid` genest), maar de naam
   beloofde iets anders dan hij deed. Precies het soort naam waar iemand over een half jaar op afgaat en dan de
   verkeerde conclusie trekt. Bovendien hoeft geen enkele app hem nog te kennen: AdmTerugKnop zet hem zelf. */
.adm-terugweg { margin-bottom: .5rem; }

/* "Nieuw"-badge bij het versielabel: verschijnt tot de gebruiker de release notes bekeken heeft.
   Standaard `hidden` in de markup — adm-shell.js beslist. Zo ziet wie alles gelezen heeft geen flikkering. */
.nav-version-badge {
    display: inline-block;
    margin-left: .4em;
    padding: 0 .4em;
    border-radius: 999px;
    background: var(--bs-primary);
    color: #fff;
    font-size: .62rem;
    line-height: 1.5;
    letter-spacing: .02em;
    text-transform: uppercase;
    vertical-align: middle;
}
.nav-version-badge[hidden] { display: none; }

/* Som van de tellers op een INGEKLAPTE sectiekop. Zonder deze regel zou een teller onder een dichte sectie
   onzichtbaar zijn — en secties staan bij het openen van de app standaard dicht. Bij een open sectie staat
   de badge er niet: dan zijn de items zelf zichtbaar met hun eigen teller. */
.nav-menu button.nav-section .nav-section-badge {
    margin-left: auto;
    margin-right: .4rem;
}

/* De "niet gevonden"-melding van een fiche. `pre-line` zodat een uitleg die uit meerdere alinea's bestaat ook
   als meerdere alinea's leest — zonder dit worden regeleindes spaties en wordt het één lap.
   `max-width` want een melding over de volle breedte van een breed scherm leest niemand. */
.adm-fiche-nietgevonden {
    white-space: pre-line;
    max-width: 46rem;
    text-align: left;
}
