/* ==========================================================================
   Arctic CRM — ontwerpsysteem
   Rustig, strak en met materiaal: matglas voor de dragende vlakken (zijbalk,
   bovenbalk, kerncijfers), haarlijnen in plaats van zware randen, en veel wit.
   Alle kleuren komen uit variabelen; de accentkleur wordt door de app op <body>
   gezet vanuit Instellingen → Huisstijl.
   ========================================================================== */

:root {
    /* Vlakken */
    --canvas: #f2f3f6;
    --surface: #ffffff;
    --surface-2: #f7f8fa;

    /* Tekst */
    --text: #14181f;
    --text-2: #495260;
    --muted: #767d89;

    /* Lijnen & diepte */
    --hairline: rgba(20, 24, 31, .09);
    --hairline-strong: rgba(20, 24, 31, .16);
    --shadow-sm: 0 1px 2px rgba(16, 24, 40, .04), 0 1px 3px rgba(16, 24, 40, .06);
    --shadow-md: 0 4px 12px rgba(16, 24, 40, .06), 0 2px 4px rgba(16, 24, 40, .04);
    --shadow-lg: 0 18px 40px rgba(12, 24, 45, .12);

    /* Accent (wordt overschreven vanuit de huisstijl-instellingen) */
    --primary: #2b5ce6;
    --primary-soft: rgba(43, 92, 230, .10);

    /* Signaalkleuren */
    --danger: #c0392b;
    --danger-soft: #fdecea;
    --success: #1e8f57;
    --success-soft: #e7f6ee;
    --warning: #b26a00;
    --warning-soft: #fdf3e2;

    /* Statuskleuren (docs/ui-regels.md, "Statuskleuren"): naast success/warning/danger een vaste
       blauwe tint voor "verzonden / in behandeling" en een grijze zachte achtergrond voor
       "concept / gesloten". Bewust NIET de accentkleur: die komt uit de huisstijl en kan per
       installatie anders zijn, terwijl een status overal dezelfde kleur hoort te hebben. */
    --info: #1d4ed8;
    --info-soft: rgba(37, 99, 235, .12);
    --muted-soft: rgba(20, 24, 31, .06);
    /* Een gewoon label (geen status) in de merkkleur. In donker een lichtere tint (zie onder). */
    --accent-label: var(--primary);
    --accent-label-soft: var(--primary-soft);
    /* Labeltekst op een -soft-achtergrond (badges, statuslabels). Kleine tekst (.76-.8rem) heeft
       4.5:1 nodig (WCAG AA). Groen, oranje en grijs halen dat als signaalkleur op hun zachte tint
       niet, dus voor de TEKST een donkerdere tint van dezelfde kleur. Knoppen, meldingen en
       achtergronden houden de signaalkleur. Rood en blauw halen het al: die gebruiken --danger/--info.
       tests/Unit/StatusKleurenTest.php rekent het contrast na. */
    --success-text: #187a4a;
    --warning-text: #985b00;
    --muted-text: #5f6672;

    /* Donkere zijbalk */
    --sidebar-a: #101a2c;
    --sidebar-b: #16233b;
    --sidebar-text: rgba(255, 255, 255, .72);

    --radius: 14px;
    --radius-sm: 10px;
    --radius-pill: 980px;

    /* De standaard paginabreedte: elke gewone adminpagina (facturen, offertes, klanten,
       creditnota's, …) rendert in .content en deelt deze bovengrens. Eén knop, zodat de
       breedte overal gelijk loopt (kassa en reparatie-ticket zijn fullscreen en vallen
       hier buiten -- die hebben hun eigen layout). */
    --content-max: 1500px;

    /* De zijmarge (gutter) van de inhoud op een smal scherm: .content op de telefoon. Een strook
       die tot de schermrand doorloopt (tabs, bord, de vaste bulkbalk) gebruikt deze waarde voor
       zijn negatieve marge, zodat hij precies de gutter volgt. De balie-schil heeft een smallere
       gutter (.rep-main, zie "Werkplek-schil" onderaan) en zet daar zijn eigen waarde. */
    --pagina-rand: 1rem;
}

* { box-sizing: border-box; }

/* [hidden] wint altijd. Een klasse die zelf display zet (.btn inline-flex, .field-error block,
   .flash en .row-actions flex, …) wint anders van de browserregel [hidden] { display: none }
   (auteur boven browser), en dan bleef een verborgen element gewoon zichtbaar: de melding
   "geen e-mailadres" onder de klant-kiezer, de knop "+ Nieuwe taak" op een project. Daarom één
   keer globaal. Toon een element door hidden weg te halen, niet met een display-regel of
   style.display (docs/ui-regels.md §1). De losse regels hieronder (.flash, .capslock, …) mogen
   blijven staan. */
[hidden] { display: none !important; }
.field-error[hidden] { display: none; }

body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI Variable Text",
                 "Segoe UI", Inter, system-ui, sans-serif;
    font-size: 14.5px;
    line-height: 1.55;
    color: var(--text);
    background: var(--canvas);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

a { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 { letter-spacing: -.017em; font-weight: 600; }
h1 { font-size: 1.55rem; margin: 0 0 .4rem; }
h2 { font-size: 1.02rem; margin: 0 0 .9rem; }

.muted { color: var(--muted); }
.small { font-size: .82rem; }

/* Bedragen en aantallen uitlijnen op cijferbreedte */
.num, .stat__value, td.num, th.num {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

/* ── Layout ────────────────────────────────────────────────────────────── */
.layout { display: flex; min-height: 100vh; }

.sidebar {
    width: 248px; flex-shrink: 0;
    /* Vast aan het scherm, niet aan de paginahoogte. Met position:sticky liet de balk
       los zodra er iets onder .layout de pagina langer maakte dan de zijbalk (bijv. de
       absoluut-gepositioneerde feedback-pinnen op een factuurpagina): de sticky-grens
       ligt bij de onderkant van .layout, en daaronder scrolde de balk mee weg. Fixed is
       immuun voor wat de pagina ook langer maakt. .main schuift ernaast (margin-left). */
    position: fixed; top: 0; left: 0; bottom: 0;
    overflow-y: auto; overscroll-behavior: contain;
    display: flex; flex-direction: column;
    padding: .8rem .7rem .9rem;
    color: var(--sidebar-text);
    /* Egale, diepe kleur in plaats van een flauw verloop: geeft de kolom een
       duidelijke rand en laat de accentkleur het werk doen. */
    background: var(--sidebar-a);
    box-shadow: inset -1px 0 0 rgba(255, 255, 255, .07);
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, .18) transparent;
}
.sidebar::-webkit-scrollbar { width: 8px; }
.sidebar::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .16); border-radius: 8px; }

/* ── Inklapbare zijbalk: alleen de pictogrammen ────────────────────────────
   De knop staat onderaan (margin-top:auto). Ingeklapt versmalt de balk en
   verdwijnen de labels + groepskoppen, zodat een lange lijst weer past. De
   keuze wordt per browser onthouden (zie admin.twig). */
.sidebar-toggle {
    position: sticky; bottom: 0; margin-top: auto;
    display: flex; align-items: center; gap: .6rem;
    padding: .6rem .7rem; border: 0; border-top: 1px solid rgba(255, 255, 255, .08);
    background: var(--sidebar-a); color: var(--sidebar-text);
    font: inherit; font-size: .85rem; cursor: pointer;
    transition: color .14s ease;
}
.sidebar-toggle:hover { color: #fff; }
.sidebar-toggle svg { flex: 0 0 auto; transition: transform .18s ease; }

/* Ingeklapt tonen we álle items als pictogrammen (ook die van een dichtgeklapte groep),
   dus de kolom kan langer worden dan het scherm. Daarom scrollt hij verticaal -- net als
   de uitgeklapte balk -- in plaats van met `overflow: visible` de items buiten de balk te
   laten doorlopen: zo dekt de achtergrond de volle schermhoogte en blijft elk pictogram
   bereikbaar, i.p.v. dat er items boven en onder de balk langs schuiven. Horizontaal
   verbergen (geen tweede scrollbalk); het label komt bij hover als title (zie arctic.js),
   want een balk die scrolt kan een uitstekende CSS-tooltip niet buiten zijn rand tonen.
   Inklappen is een desktopkeuze: op telefoon en tablet (≤1024px) is het menu een
   uitschuifpaneel (zie "Mobiele schil" onderaan) en telt de ingeklapte stand niet mee. */
@media (min-width: 1025px) {
.sidebar.is-ingeklapt { width: 66px; overflow-x: hidden; overflow-y: auto; z-index: 30; }
.sidebar.is-ingeklapt .brand { justify-content: center; padding-left: 0; padding-right: 0; }
/* Ingeklapt is er geen ruimte voor het volledige logo of de naam: toon het merkteken. */
.sidebar.is-ingeklapt .brand__logo,
.sidebar.is-ingeklapt .brand__name { display: none; }
.sidebar.is-ingeklapt .brand__mark { display: grid; place-items: center; }
.sidebar.is-ingeklapt .nav__group { display: none; }
/* Icoonmodus: een groep kan hier niet in- of uitgeklapt worden (de kop is verborgen),
   dus tonen we alle items -- ook die van een dichte groep -- zodat elk pictogram
   bereikbaar blijft. */
.sidebar.is-ingeklapt .nav__groep.is-dicht .nav__items { display: flex; }
.sidebar.is-ingeklapt .nav__item { justify-content: center; padding-left: 0; padding-right: 0; gap: 0; }
.sidebar.is-ingeklapt .nav__item > span { display: none; }
.sidebar.is-ingeklapt .nav__item.is-active::before { display: none; }
.sidebar.is-ingeklapt .sidebar-toggle { justify-content: center; padding-left: 0; padding-right: 0; }
.sidebar.is-ingeklapt .sidebar-toggle__tekst { display: none; }
.sidebar.is-ingeklapt .sidebar-toggle svg { transform: rotate(180deg); }
.layout:has(.sidebar.is-ingeklapt) .main { margin-left: 66px; }
}

/* Label bij de ingeklapte zijbalk: nu de balk verticaal scrolt (zodat de achtergrond de
   volle hoogte dekt), kan een eigen CSS-tooltip niet meer rechts buiten de balk uitsteken
   -- een scrollende balk clipt zijn eigen overflow. Het label komt daarom bij hover als
   native title, die admin.twig alléén ingeklapt op de nav-items zet (uitgeklapt staat het
   label er al, dus geen dubbele tooltip). aria-label blijft voor schermlezers. */

.main { flex: 1; display: flex; flex-direction: column; min-width: 0; position: relative; margin-left: 248px; }
/* Volgt de ingeklapte zijbalk (66px): zie de regel binnen het desktopblok hierboven. */

.topbar, .content { position: relative; z-index: 1; }

/* Merk: logo + naam uit de huisstijl-instellingen */
.brand {
    display: flex; align-items: center; gap: .6rem;
    padding: .3rem .5rem .9rem;
    color: #fff; font-weight: 600; font-size: 1.02rem; letter-spacing: -.01em;
}
/* Vaste hoogte, breedte schaalt mee en wordt begrensd door de zijbalk (244px
   min padding). Zo blijft élk aangeleverd logo netjes en onvervormd. */
.brand__logo {
    display: block; height: 36px; width: auto;
    max-width: 200px; object-fit: contain; object-position: left center;
}
.brand__name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Het schermnaam-label naast het logo in de fullscreen-schillen (reparaties/werkplek) is overbodig:
   de schermwisselaar ernaast toont het actieve scherm al. Daarom verborgen. De werkplek-/kassa-schil
   laten 'm al weg in de template; deze regel dekt de reparatie-schil (eigen template van een andere
   sessie) zonder dat bestand aan te hoeven raken. Hogere specificiteit dan repairs.css z'n eigen regel. */
.rep-topbar .rep-brand__label { display: none; }
/* Reserveer de ruimte voor het logo in de fullscreen-schillen vóór het geladen is, zodat de balk niet
   verspringt als het logo laat binnenkomt. De werkplek-/kassa-schil zetten width/height al als attribuut
   op het <img>; deze aspect-ratio dekt de reparatie-schil (template van een andere sessie, zonder die
   attributen). Afgestemd op het huidige logo (625×150); object-fit houdt een ander logo onvervormd. */
.rep-topbar .rep-brand img { aspect-ratio: 625 / 150; object-fit: contain; }
/* Het merkteken (favicon): standaard verborgen; alleen zichtbaar als de zijbalk is
   ingeklapt (zie de is-ingeklapt-regel hierboven). Vierkant en klein, past in 66px.
   Zonder geüpload merkteken is het een gekleurd vierkantje met de beginletter. */
.brand__mark {
    display: none; flex: 0 0 auto;
    width: 34px; height: 34px; border-radius: 9px; object-fit: contain;
}
.brand__mark--letter {
    background: rgba(255, 255, 255, .14); color: #fff;
    font-weight: 700; font-size: 1rem; line-height: 1;
}
.brand--center { justify-content: center; padding-bottom: 0; }

.nav { display: flex; flex-direction: column; gap: 2px; }

/* Kop boven een groep items: houdt een lange lijst leesbaar. Nu een echte knop,
   want klikken vouwt de groep open of dicht (zie .nav__groep hieronder). De
   typografie blijft gelijk aan de oude kop; alleen de knop-chrome halen we eraf. */
.nav__group {
    display: flex; align-items: center; gap: .4rem;
    width: 100%; margin: .6rem 0 .2rem; padding: .15rem .75rem;
    background: none; border: 0; border-radius: var(--radius-sm);
    font-family: inherit; font-size: .66rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .11em; text-align: left;
    color: rgba(255, 255, 255, .5); cursor: pointer;
}
.nav__group:hover { color: rgba(255, 255, 255, .82); background: rgba(255, 255, 255, .04); }
.nav__group:focus-visible { outline: 2px solid rgba(255, 255, 255, .45); outline-offset: 1px; }
.nav__group-tekst { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* De caret rechts in de kop: wijst omlaag als de groep open is, naar rechts als hij
   dicht is. */
.nav__caret { flex: 0 0 auto; opacity: .7; transition: transform .16s ease; }

/* Een inklapbare groep is de kop plus zijn items. */
.nav__groep { display: flex; flex-direction: column; }
.nav__items { display: flex; flex-direction: column; gap: 2px; }
.nav__groep.is-dicht .nav__items { display: none; }
.nav__groep.is-dicht .nav__caret { transform: rotate(-90deg); }

/* Rustige regels: alleen tekst en pictogram. De doorzichtige rand houdt de breedte
   gelijk aan het actieve item, dat er wél een echte rand omheen krijgt. */
.nav__item {
    position: relative;
    display: flex; align-items: center; gap: .65rem;
    padding: .38rem .7rem; border-radius: var(--radius-sm);
    border: 1px solid transparent;
    color: var(--sidebar-text); text-decoration: none;
    font-size: .91rem; font-weight: 450;
    transition: background-color .14s ease, color .14s ease;
}
.nav__icon { flex: 0 0 20px; opacity: .62; transition: opacity .14s ease; }
.nav__item:hover { background: rgba(255, 255, 255, .06); color: #fff; text-decoration: none; }
.nav__item:hover .nav__icon { opacity: .9; }

/* Alleen waar je staat krijgt matglas: een opgetild vlak in de accentkleur, met
   een lichte rand en een glans langs de bovenrand. Eén element dat eruit springt
   wijst beter de weg dan vijftien die allemaal om aandacht vragen. */
.nav__item.is-active {
    background: color-mix(in srgb, var(--primary) 42%, rgba(255, 255, 255, .10));
    border-color: color-mix(in srgb, var(--primary) 26%, rgba(255, 255, 255, .34));
    color: #fff; font-weight: 550;
    box-shadow: 0 6px 18px rgba(4, 10, 24, .35),
                inset 0 1px 0 rgba(255, 255, 255, .3);
    -webkit-backdrop-filter: saturate(1.6) blur(12px);
    backdrop-filter: saturate(1.6) blur(12px);
}
.nav__item.is-active .nav__icon { opacity: 1; }
.nav__item.is-active::before {
    content: ""; position: absolute; left: -.7rem; top: 50%; transform: translateY(-50%);
    width: 3px; height: 20px; border-radius: 0 3px 3px 0; background: #fff;
}

/* Bovenbalk: egaal, blijft staan bij scrollen. Matglas heeft hier geen zin —
   wat erachter langs schuift is toch bijna wit. */
.topbar {
    position: sticky; top: 0; z-index: 20;
    display: flex; align-items: center; gap: 1rem;
    padding: .7rem 1.6rem;
    /* Globaal iets doorzichtig (frosted) op álle adminpagina's — Calvins wens: de
       bovenbalk is geen solide wit vlak maar licht matglas, zodat content die eronder
       door scrollt zacht doorschemert. In donker zet de override hieronder zijn eigen
       matglas. Kassa/reparatie gebruiken eigen klassen (.kassa-topbar/.rep-topbar) en
       blijven dus ongemoeid. */
    background: rgba(255, 255, 255, .72);
    -webkit-backdrop-filter: blur(20px) saturate(1.35);
    backdrop-filter: blur(20px) saturate(1.35);
    border-bottom: 1px solid var(--hairline);
}
.page-title { font-weight: 600; letter-spacing: -.01em; }
.user-menu { display: flex; align-items: center; gap: .9rem; margin-left: auto; color: var(--muted); font-size: .9rem; }
.user-name { font-weight: 500; color: var(--text-2); }
/* Naam + foto samen één klikbare link naar het eigen profiel. */
.profiel-knop {
    display: inline-flex; align-items: center; gap: .5rem;
    padding: .25rem .5rem .25rem .3rem; border-radius: 999px;
    text-decoration: none; transition: background .15s ease;
}
.profiel-knop:hover { background: var(--hairline); }
.profiel-knop:hover .user-name { color: var(--text); }
.profiel-knop .avatar { flex: 0 0 auto; }
.inline-form { display: inline; }

/* Uren-knop in de bovenbalk (module Urenregistratie). Zelfde maat en gedrag als het
   belletje ernaast; de stip verschijnt zodra er voor de gebruiker een timer loopt. De
   stijl staat bewust in app.css (altijd geladen) en niet in een module-bestand, want
   de knop zelf komt al via een 'ignore missing'-partial mee of niet. */
.uren-knop {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: var(--radius-pill);
    color: var(--text-2); text-decoration: none;
}
.uren-knop:hover, .uren-knop:focus-visible { background: var(--surface-2); color: var(--text); }
.uren-knop .nav__icon { flex: 0 0 20px; opacity: 1; }
/* De stip met een ringetje in de balkkleur, zodat hij loskomt van het pictogram. */
.uren-knop__stip {
    position: absolute; top: 3px; right: 3px;
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--success); box-shadow: 0 0 0 2px var(--surface);
}

/* Extra lucht onderaan: rechtsonder zweeft de feedbackknop, en die dekte anders af
   wat daar toevallig eindigde — op het factuurformulier precies het totalenblok. Deze
   ruimte zorgt dat je altijd langs de knop heen kunt scrollen. */
.content { padding: 1.6rem 1.6rem 5.5rem; max-width: var(--content-max); width: 100%; }

/* ── Globaal zoeken ────────────────────────────────────────────────────── */
.topsearch { flex: 0 1 340px; margin-left: 1.5rem; }
.topsearch__input {
    width: 100%; padding: .45rem .8rem;
    background: var(--surface-2); border: 1px solid transparent; border-radius: var(--radius-pill);
    font: inherit; font-size: .9rem; color: var(--text);
    transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.topsearch__input::placeholder { color: var(--muted); }
.topsearch__input:focus {
    outline: none; background: var(--surface);
    border-color: var(--hairline-strong);
    box-shadow: 0 0 0 4px var(--primary-soft);
}

/* ── Panelen & kaarten ─────────────────────────────────────────────────── */
/* Egaal wit met een haarlijn. Matglas werkt alleen als er iets áchter zit om te
   vervagen; op een bijna witte pagina levert het alleen vaagheid op. De scheiding
   komt hier van de rand en een lichte schaduw. */
.panel {
    background: var(--surface);
    border: 1px solid var(--hairline);
    box-shadow: var(--shadow-sm);
    border-radius: var(--radius);
    padding: 1.35rem;
    margin-bottom: 1.1rem;
}
.cards-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; margin-bottom: 1.1rem; }

.page-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; margin-bottom: 1.1rem;
}
.page-head__title { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
/* Een kop met een titel én een regel tekst eronder: de knoppen bovenaan uitgelijnd. */
.page-head--boven { align-items: flex-start; flex-wrap: wrap; }
/* ── Kaartenraster op een detailpagina ─────────────────────────────────────────
   Korte kaarten (Contact, Adres, Notities) naast elkaar in een vullend raster in plaats van
   onder elkaar (feedback klantpagina: "eindeloos lang met veel witruimte"); een brede kaart
   (tabel, formulier) krijgt .panel--breed en pakt de hele rij. */
.kaarten-raster {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: 1rem;
    align-items: start; /* geen kaarten die uitrekken tot gelijke hoogte */
    margin-bottom: 1.1rem;
}
.kaarten-raster > .panel { margin: 0; padding: 1rem 1.1rem; min-width: 0; }
.kaarten-raster > .panel--breed { grid-column: 1 / -1; }
.kaarten-raster .panel > h2 { margin: 0 0 .6rem; }
/* Dichtere definitielijsten: een smallere labelkolom voor korte labels als "E-mail". */
.kaarten-raster .details { grid-template-columns: 110px 1fr; gap: .3rem .8rem; font-size: .92rem; }
@media (max-width: 640px) {
    .kaarten-raster .details { grid-template-columns: 1fr; gap: .1rem .8rem; }
    .kaarten-raster .details dt { margin-top: .4rem; }
}

/* Knoppen onder een formulier of gegevenslijst in dezelfde kaart (bijv. Gewonnen/Verloren in de dealpopup). */
.panel > .form + .row-actions, .panel > .details + .row-actions { margin-top: .9rem; }

/* Een knop met een pictogram ervoor (Terug, Bewerken, PDF). */
.knop-met-icoon { display: inline-flex; align-items: center; gap: .4rem; }

/* ── Tabs (tabs.js): tabbladen op een detailpagina ─────────────────────────── */
.tabs { display: flex; flex-wrap: wrap; gap: .2rem; border-bottom: 1px solid var(--hairline); margin: 0 0 1.3rem; }
.tabs__knop {
    border: 0; background: none; cursor: pointer; font: inherit; padding: .6rem .95rem; color: var(--muted);
    border-bottom: 2px solid transparent; margin-bottom: -1px; border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.tabs__knop:hover { color: var(--text); background: var(--surface-2); }
.tabs__knop.is-active { color: var(--text); font-weight: 600; border-bottom-color: var(--primary); }
.tabs__knop:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.tabs__telt {
    display: inline-block; min-width: 1.3em; padding: 0 .35em; margin-left: .35em; font-size: .72rem; line-height: 1.5;
    text-align: center; background: var(--surface-2); border-radius: var(--radius-pill); color: var(--muted);
}
.tabpaneel > .panel:first-child, .tabpaneel > .cards-2:first-child { margin-top: 0; }
/* Op de telefoon schuiven de tabs zijwaarts in plaats van over twee regels te breken. */
@media (max-width: 640px) {
    /* Tot de schermrand: de negatieve marge volgt de gutter (--pagina-rand), ook in de
       balie-schil waar die smaller is; anders schoof de pagina daar zijwaarts. */
    .tabs {
        flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
        margin-left: calc(-1 * var(--pagina-rand)); margin-right: calc(-1 * var(--pagina-rand));
        padding: 0 var(--pagina-rand);
    }
    .tabs::-webkit-scrollbar { display: none; }
    .tabs__knop { flex: none; white-space: nowrap; }
}

/* Terug: een pijl vóór de titel (componenten/paginakop.twig), op elke detailpagina op dezelfde plek. */
.page-head__terug {
    display: inline-flex; align-items: center; justify-content: center; flex: none;
    width: 36px; height: 36px; border-radius: var(--radius-sm);
    border: 1px solid var(--hairline-strong); background: var(--surface); color: var(--text);
}
.page-head__terug:hover { border-color: var(--primary); color: var(--primary); text-decoration: none; }
.page-head__title h1 { margin: 0; }

/* ── Hero: zachte merkachtergrond waar de glazen kaarten op rusten ─────── */
.hero {
    position: relative; isolation: isolate;
    margin: -.4rem -.4rem 1.2rem;
    padding: 1.5rem 1.6rem 1.7rem;
    border-radius: 22px;
    overflow: hidden;
    background: linear-gradient(150deg, #16233b 0%, #1d3557 45%, #24507e 100%);
    box-shadow: var(--shadow-lg);
}
/* Het berglandschap ligt er heel subtiel onder, zodat het glas iets te tonen heeft. */
.hero::before {
    content: ""; position: absolute; inset: 0; z-index: -1;
    background-image: var(--hero-image); background-size: cover; background-position: center 65%;
    opacity: .34;
}
.hero::after {
    content: ""; position: absolute; inset: 0; z-index: -1;
    background: linear-gradient(180deg, rgba(12, 24, 45, .30) 0%, rgba(12, 24, 45, .72) 100%);
}
.hero__intro h1 { color: #fff; margin: 0 0 .1rem; font-size: 1.6rem; }
.hero__date { margin: 0; color: rgba(255, 255, 255, .68); font-size: .9rem; }
.hero .stat-grid { margin: 1.3rem 0 0; }

/* Binnen de hero zijn de kaarten écht van glas */
.hero .stat {
    background: linear-gradient(rgba(255, 255, 255, .16), rgba(255, 255, 255, .07));
    border-color: rgba(255, 255, 255, .18);
    color: #fff;
    box-shadow: 0 8px 26px rgba(5, 19, 34, .18);
}
.hero .stat__label { color: rgba(255, 255, 255, .68); }
.hero .stat__sub { color: rgba(255, 255, 255, .62); }
.hero a.stat:hover { background: linear-gradient(rgba(255, 255, 255, .22), rgba(255, 255, 255, .10)); }
.hero .stat--alert { border-color: rgba(255, 168, 160, .55); }
.hero .stat--alert .stat__value { color: #ffcfc9; }

/* ── Kerncijfers: matglas op een subtiel verloop ───────────────────────── */
.stat-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(178px, 1fr));
    gap: .75rem; margin: 1.1rem 0;
}
/* Bewust wat compacter dan eerst (feedback: "deze blokken mogen kleiner"): minder
   padding en een kleiner bedrag, zodat er meer naast elkaar past zonder dat de cijfers
   onleesbaar worden. Gedeeld component, dus dit werkt op alle lijstpagina's door. */
.stat {
    display: flex; flex-direction: column; gap: .15rem;
    padding: .85rem 1rem;
    border-radius: var(--radius);
    background: var(--surface);
    border: 1px solid var(--hairline);
    box-shadow: var(--shadow-sm);
    text-decoration: none; color: var(--text);
    transition: transform .16s cubic-bezier(.2, .7, .3, 1), box-shadow .16s ease;
}
a.stat:hover { text-decoration: none; transform: translateY(-2px); box-shadow: var(--shadow-md); }
.stat__label {
    font-size: .74rem; font-weight: 600; letter-spacing: .045em; text-transform: uppercase;
    color: var(--muted);
}
.stat__value { font-size: 1.4rem; font-weight: 600; letter-spacing: -.022em; }
.stat__sub { font-size: .82rem; color: var(--muted); }
.stat--alert { border-color: rgba(192, 57, 43, .28); }
.stat--alert .stat__value { color: var(--danger); }

/* ── Snelkoppelingen: glazen tegels op de huisstijl-achtergrond ────────── */
.quick-nav {
    margin-top: 1.4rem; padding: 1.4rem;
    border-radius: 20px;
    background-size: cover; background-position: center;
    box-shadow: var(--shadow-lg);
}
.quick-nav__title {
    margin: 0 0 .2rem; font-size: .74rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: .09em;
    color: rgba(255, 255, 255, .62);
}
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(172px, 1fr)); gap: .8rem; margin-top: 1rem; }
.tile {
    padding: 1.05rem 1.15rem;
    border-radius: var(--radius);
    background-color: rgba(18, 30, 52, .40);
    background-image: linear-gradient(rgba(255, 255, 255, .12), rgba(255, 255, 255, .04));
    -webkit-backdrop-filter: blur(16px) saturate(1.3);
    backdrop-filter: blur(16px) saturate(1.3);
    border: .8px solid rgba(255, 255, 255, .16);
    box-shadow: 0 8px 24px rgba(5, 19, 34, .16);
    color: #fff; text-decoration: none;
    transition: transform .16s cubic-bezier(.2, .7, .3, 1), border-color .16s ease, background-color .16s ease;
}
.tile:hover {
    text-decoration: none; transform: translateY(-2px);
    border-color: rgba(255, 255, 255, .3);
    background-color: rgba(18, 30, 52, .5);
}
.tile__label { font-weight: 550; font-size: .95rem; }

/* ── Formulieren ───────────────────────────────────────────────────────── */
.form, .field { display: block; }
.field { margin-bottom: .95rem; }
.field > span { display: block; font-size: .82rem; color: var(--text-2); margin-bottom: .3rem; font-weight: 500; }
.field-row { display: flex; gap: .9rem; flex-wrap: wrap; }
.field-row .field { flex: 1; min-width: 140px; }
.field--grow { flex: 2; }
.field--small { flex: 0 0 110px; }
.field-error { display: block; color: var(--danger); font-size: .8rem; font-style: normal; margin-top: .25rem; }
.form--narrow { max-width: 620px; }
.form--wide { max-width: 820px; }
.form-actions { display: flex; gap: .6rem; margin-top: 1.4rem; }

/* ── Documentformulier (factuur, offerte) ──────────────────────────────────
   Een document met een regeltabel is geen invulformulier maar een werkblad: de
   tabel heeft zes kolommen plus een keuzelijst per regel en past niet in de
   820px van .form--wide (die blijft ongemoeid, elders in gebruik). Vandaar een
   eigen, veel bredere variant. De bovengrens houdt de leesregels van de
   kopvelden hanteerbaar op een zeer breed scherm.

   De opbouw volgt het patroon dat boekhoudpakketten hanteren: kopgegevens in
   twee kolommen naast elkaar, daaronder de regels over de volle breedte. */
.form--document { max-width: var(--content-max); }
.form__kop {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 0 2rem;
    align-items: start;
}
/* Onder deze breedte is twee kolommen naast elkaar smaller dan één leesbare
   kolom; dan vallen de blokken onder elkaar. */
@media (max-width: 900px) {
    .form__kop { grid-template-columns: minmax(0, 1fr); gap: 0; }
}
.form__kop-blok { min-width: 0; }
.form__kop-titel {
    font-size: .82rem; font-weight: 600; letter-spacing: .02em;
    text-transform: uppercase; color: var(--text-2);
    margin: 0 0 .7rem;
}
.form__regels { margin-top: 1.6rem; }
/* De regeltabel gebruikt de volle breedte; de tekstkolommen rekken mee en de
   getalkolommen blijven zo smal als hun inhoud. */
.form__regels .table { width: 100%; table-layout: auto; }
.form__regels .table td { vertical-align: top; }
.regel__product { margin-bottom: .35rem; }
/* In een tabelcel moeten de getalvelden zich naar hun kolom voegen in plaats van
   de width:100% van een gewoon formulierveld te erven. */
.form__regels .table td input[type=text],
.form__regels .table td select { width: 100%; min-width: 0; }
/* .row-actions is elders een flexrij, maar op een <td> haalt display:flex de cel
   uit de tabelopmaak: de tabel rekent haar breedte dan zonder die kolom en de
   rijscheiding stopt te vroeg. Binnen de regeltabel blijft het dus een gewone cel. */
.form__regels .table td.row-actions { display: table-cell; text-align: right; }
.col--getal { width: 7rem; }
.col--smal { width: 6rem; }
/* Ruim genoeg voor "21% (hoog)" plus het uitklappijltje van de browser. */
.col--btw { width: 10rem; }
.col--acties { width: 7rem; }

input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], input[type=datetime-local], input[type=time], input[type=search],
input[type=tel], input[type=url], input[type=color],
select, textarea {
    width: 100%; padding: .55rem .75rem;
    background: var(--surface);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius-sm);
    font: inherit; font-size: .93rem; color: var(--text);
    transition: border-color .15s ease, box-shadow .15s ease;
}
input:focus, select:focus, textarea:focus {
    outline: none; border-color: var(--primary);
    box-shadow: 0 0 0 4px var(--primary-soft);
}
input:disabled, select:disabled, textarea:disabled { background: var(--surface-2); color: var(--muted); }
textarea { resize: vertical; }

/* Label met een actie ernaast, bijv. "Klant  + Nieuwe klant" */
.field__label {
    display: flex; align-items: baseline; justify-content: space-between; gap: .75rem;
    font-size: .82rem; color: var(--text-2); margin-bottom: .3rem; font-weight: 500;
}

.check { display: flex; align-items: center; gap: .5rem; margin: .9rem 0; font-size: .93rem; }
.check input { width: auto; }
.toolbar { display: flex; align-items: center; gap: .6rem; margin-bottom: 1.1rem; flex-wrap: wrap; }
.toolbar input[type=search] { max-width: 300px; }

/* In een filterbalk sturen de velden zich naar hun inhoud. Zonder dit erven ze de
   width:100% van een gewoon formulierveld, en springt elk filter op een eigen regel:
   op een breed scherm krijg je dan een kolom van balken over de volle breedte in
   plaats van een balk. */
/* Onderdelen die samen één gedachte vormen (twee vinkjes plus hun knop) breken als
   één geheel af in plaats van los van elkaar. */
.toolbar__groep { display: inline-flex; align-items: center; gap: .6rem; flex: 0 0 auto; }

.toolbar select,
.toolbar input[type=text],
.toolbar input[type=date],
.toolbar input[type=number],
.toolbar .picker {
    width: auto;
    min-width: 170px;
    flex: 0 1 auto;
}

/* ── Knoppen ───────────────────────────────────────────────────────────── */
.btn {
    display: inline-flex; align-items: center; justify-content: center;
    padding: .5rem .95rem; border-radius: var(--radius-sm);
    border: 1px solid var(--hairline-strong);
    background: var(--surface); color: var(--text);
    font: inherit; font-size: .9rem; font-weight: 500;
    cursor: pointer; text-decoration: none; white-space: nowrap;
    transition: background-color .14s ease, border-color .14s ease, transform .1s ease;
}
.btn:hover { text-decoration: none; background: var(--surface-2); }
.btn:active { transform: scale(.985); }
.btn-primary {
    background: var(--primary); border-color: transparent; color: #fff;
    box-shadow: 0 1px 2px rgba(16, 24, 40, .12);
}
.btn-primary:hover { background: var(--primary); filter: brightness(1.07); }
/* Onomkeerbare acties: rood van tekst en rand, maar niet gevuld — het is een
   uitweg, geen hoofdactie, en mag dus niet om aandacht schreeuwen. */
.btn-danger { color: var(--danger); border-color: rgba(192, 57, 43, .28); }
.btn-danger:hover { background: var(--danger-soft); border-color: rgba(192, 57, 43, .45); }
/* Gevuld rood: alleen voor de bevestigknop van iets onomkeerbaars in een vraag-popup. */
.btn-danger--vol { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn-danger--vol:hover { background: var(--danger); border-color: var(--danger); filter: brightness(1.08); }
.btn-block { width: 100%; }
.btn-link {
    background: none; border: 0; padding: 0;
    color: var(--primary); font: inherit; font-size: .89rem; cursor: pointer;
}
.btn-link:hover { text-decoration: underline; }
.row-actions { display: flex; gap: .8rem; align-items: center; white-space: nowrap; }

/* ── Kleine, herbruikbare hulpjes (globaal, zodat er geen losse CSS per pagina nodig is) ── */
.nowrap { white-space: nowrap; }
/* Een inhouds-thumbnail (bijv. een productafbeelding), begrensd en met de standaardronding. */
.thumb { display: block; max-width: 220px; height: auto; border-radius: var(--radius-sm); }
/* Boomweergave: inspringing per diepte via een variabele --diepte, zodat de OPMAAK globaal
   blijft en alleen de (dynamische) waarde inline staat. */
.boom-node { margin-left: calc(var(--diepte, 0) * 1.6rem); }
/* Paginering onder een tabel: info links, knoppen rechts. */
.pager { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: 1rem; flex-wrap: wrap; }

/* ── Meldingen ─────────────────────────────────────────────────────────── */
/* Melding met een pictogram links en een kruisje rechts. Het pictogram zegt of het
   goed of mis ging zonder dat je de kleur hoeft te kunnen zien; het kruisje geeft je
   de kans hem weg te halen in plaats van eromheen te lezen. */
.flash {
    display: flex; align-items: flex-start; gap: .6rem;
    padding: .75rem 1rem; border-radius: var(--radius);
    margin: 1rem 0; font-size: .92rem;
    border: 1px solid transparent;
    box-shadow: var(--shadow-sm);
}
/* Een leeg meldingsvak dat pas door JavaScript gevuld wordt, staat als [hidden] in de
   HTML. Zonder deze regel wint de display:flex hierboven van de browser-standaard en zie
   je een lege rode balk (o.a. in het taak-popupformulier). Geldt overal. */
.flash[hidden] { display: none !important; }
/* In de adminlayout staat de melding tussen de bovenbalk en .content en zou hij
   anders vlak tegen de balk plakken en tot de rand doorlopen. Deze regel geeft hem
   lucht aan de bovenkant en lijnt hem uit met de padding van .content. Alleen daar:
   op het inlogscherm zit de melding in een kaart en hoort dit niet. (.app-inhoud is het deel
   dat de snelle navigatie wisselt; de melding hoort daarbij.) */
.app-inhoud > .flash { margin: 1.2rem 1.6rem 0; }
@media (max-width: 760px) { .app-inhoud > .flash { margin: 1rem 1rem 0; } }
.flash__teken { flex: 0 0 auto; display: flex; margin-top: .05rem; }
.flash__tekst { flex: 1 1 auto; min-width: 0; }
.flash__sluit {
    flex: 0 0 auto;
    margin: -.15rem -.35rem 0 .4rem; padding: 0 .35rem;
    border: 0; background: none; cursor: pointer;
    color: inherit; opacity: .55;
    font: inherit; font-size: 1.25rem; line-height: 1.2;
    border-radius: var(--radius-sm);
}
.flash__sluit:hover { opacity: 1; background: rgba(20, 24, 31, .08); }
.flash--error { background: var(--danger-soft); color: var(--danger); border-color: rgba(192, 57, 43, .22); }
.flash--success { background: var(--success-soft); color: var(--success-text); border-color: rgba(30, 143, 87, .22); }
.flash--info { background: var(--primary-soft); color: var(--primary); border-color: color-mix(in srgb, var(--primary) 22%, transparent); }

/* ── Tabellen ──────────────────────────────────────────────────────────── */
.table-wrap { overflow-x: auto; border-radius: var(--radius); }
.table {
    width: 100%; border-collapse: separate; border-spacing: 0;
    background: var(--surface);
    border: 1px solid rgba(255, 255, 255, .68);
    border-radius: var(--radius);
    overflow: hidden;
    font-size: .92rem;
}
/* Binnen een paneel staat de tabel al op glas: dan geen tweede laag. */
.panel .table { background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; border-color: var(--hairline); }
.table th, .table td { text-align: left; padding: .68rem .85rem; border-bottom: 1px solid var(--hairline); }
.table th {
    background: rgba(247, 248, 250, .8);
    font-size: .72rem; font-weight: 600; text-transform: uppercase; letter-spacing: .05em;
    color: var(--muted);
}
.table tr:last-child td { border-bottom: 0; }
.table tbody tr { transition: background-color .12s ease; }
/* Subtiele zebra: even rijen een heel lichte tint, zodat lange lijsten beter te volgen zijn. */
.table tbody tr:nth-child(even) { background: color-mix(in srgb, var(--surface-2) 55%, transparent); }
.table tbody tr:hover { background: var(--surface-2); }
.table td.num, .table th.num { text-align: right; white-space: nowrap; }
.table tr.is-muted td { color: var(--muted); }

/* ── Lijst als kaarten zodra er weinig ruimte is ───────────────────────────
   Een tabel met zes, zeven kolommen schuift in een smalle ruimte horizontaal weg:
   je ziet nooit de hele rij. Krijgt de tabel .table--cards, dan valt ze uiteen tot
   losse kaarten -- elke rij een kaart, elke cel een "Label: waarde"-regel. Het label
   komt uit data-label op de <td>, dus de kop mag verdwijnen. De eerste inhoudscel
   krijgt .kaart-titel en staat groot bovenaan zonder label.

   Het kijkt naar de ruimte die de LIJST heeft, niet naar de schermbreedte (container
   query op .table-wrap): op een telefoon, maar ook op een laptop of breed scherm als het
   zijpaneel (facturen, offertes, …) ernaast openstaat en de lijst smal maakt. Daar
   scrolde de tabel eerst zijwaarts. Een brede lijst verandert niets. */
/* Het vak zelf krijgt geen ronding: de tabel heeft al een eigen ronding, en in kaartvorm knipte
   die van het vak de bovenhoeken van de eerste kaart af. */
.table-wrap:has(> .table--cards) { container: lijst / inline-size; border-radius: 0; }
@container lijst (max-width: 640px) {
    .table--cards { border: 0; background: transparent; border-radius: 0; overflow: visible; font-size: .95rem; }
    .table--cards thead { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); border: 0; }
    .table--cards tbody tr {
        display: block;
        background: var(--surface);
        border: 1px solid var(--hairline);
        border-radius: var(--radius-sm);
        padding: .8rem .95rem;
        margin-bottom: .7rem;
        box-shadow: 0 1px 2px rgba(20, 24, 31, .04);
    }
    /* Zebra en hover slaan nergens op zodra elke rij al een eigen kaart is. */
    .table--cards tbody tr:nth-child(even),
    .table--cards tbody tr:hover { background: var(--surface); }
    .table--cards tbody tr:last-child td { border-bottom: 0; }
    .table--cards td, .table--cards tfoot th {
        display: flex; gap: 1rem; align-items: baseline; justify-content: space-between;
        padding: .32rem 0; border: 0; text-align: right; min-width: 0;
        /* Eén lang e-mailadres of URL maakt anders de hele tabel, en dus elke kaart, breder dan het vak. */
        overflow-wrap: anywhere;
    }
    .table--cards td + td, .table--cards tfoot th + th { border-top: 1px solid var(--hairline); }
    .table--cards td::before, .table--cards tfoot th::before {
        content: attr(data-label);
        flex: 0 0 auto; text-align: left;
        font-size: .7rem; font-weight: 600; text-transform: uppercase;
        letter-spacing: .04em; color: var(--muted);
    }
    /* Cellen zonder data-label (bijv. het selectievinkje) horen niet in de kaart. */
    .table--cards td:not([data-label]):not(.kaart-titel),
    .table--cards tfoot th:not([data-label]):not(.kaart-titel) { display: none; }
    /* De titelcel: vol breed, groot, bovenaan, zonder label en zonder scheidingslijn erna. */
    .table--cards td.kaart-titel, .table--cards tfoot th.kaart-titel {
        display: block; text-align: left; padding: 0 0 .55rem; border: 0; font-size: 1.02rem;
    }
    .table--cards td.kaart-titel::before, .table--cards tfoot th.kaart-titel::before { content: none; }
    .table--cards td.kaart-titel + td, .table--cards tfoot th.kaart-titel + th { border-top: 0; }
    /* Een waarde die uit meer dan één stukje bestaat (balk + percentage, datum +
       badge) stapelt netjes rechts onder elkaar in plaats van op één drukke regel. */
    .table--cards .kaart-waarde { display: flex; flex-direction: column; align-items: flex-end; gap: .25rem; }
    .table--cards .row-actions { white-space: normal; }

    /* De totaalrij (<tfoot>, met <th>-cellen) is een eigen kaart onderaan, met dezelfde regels
       als de kaarten erboven. */
    .table--cards tfoot, .table--cards tfoot tr { display: block; }
    .table--cards tfoot tr {
        background: var(--surface);
        border: 1px solid var(--hairline);
        border-radius: var(--radius-sm);
        padding: .8rem .95rem;
    }
    .table--cards tfoot th { background: none; color: inherit; font-size: .95rem; font-weight: 600; text-transform: none; letter-spacing: 0; }
    :root[data-theme="dark"] .table--cards tfoot th { background: none; }

    /* De hele kaart is aantikbaar: de hoofdlink in de titel (die een popup of zijpaneel opent)
       spant met ::after over de kaart. Andere links en knoppen in de kaart liggen erboven. */
    .table--cards tbody tr { position: relative; }
    .table--cards td.kaart-titel a:is([data-venster], [data-paneel])::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
    .table--cards tbody tr :is(a:not([data-venster]):not([data-paneel]), button, input, select, label, summary) { position: relative; z-index: 1; }

    /* De kaart die in het zijpaneel openstaat: een rand om de hele kaart i.p.v. gekleurde cellen. */
    .table--cards tbody tr.is-paneel-actief { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
    .table--cards tbody tr.is-paneel-actief > td { background: transparent; }
}

/* Net te smal voor alle kolommen, maar nog breed genoeg voor een tabel (bijv. een lijst naast
   het zijpaneel op een breed scherm): kolommen met .col--extra (op de <th> én de <td>) vallen
   dan als eerste weg, zodat de rest past. In kaartvorm (≤640px) staan ze er gewoon weer bij. */
@container lijst (min-width: 641px) and (max-width: 960px) {
    .table--cards .col--extra { display: none; }
}
/* Een tabel die net niet past (laptop, of veel kolommen): eerst iets minder lucht in de cellen,
   zodat hij binnen de breedte blijft in plaats van zijwaarts te gaan schuiven. */
@container lijst (min-width: 641px) and (max-width: 1100px) {
    .table--cards th, .table--cards td { padding-left: .55rem; padding-right: .55rem; }
    /* Lange woorden zonder afbreekpunt (e-mailadressen, URL's) en actieknoppen naast elkaar
       duwden de tabel breder dan zijn vak; hier mogen ze afbreken. De hoofdlijsten (.lijst) zijn
       daarop afgestemd met .col--extra. Elders alleen wat echt lang kan worden: anders knijpt de
       automatische tabelopmaak ook gewone namen midden in een woord af. */
    .lijst .table--cards td,
    .table--cards td :is(a[href^="mailto:"], a[href^="http"], .small) { overflow-wrap: anywhere; }
    .table--cards .row-actions { flex-wrap: wrap; white-space: normal; row-gap: .1rem; }
}

/* ── Het lijst-onderdeel (templates/componenten/lijst.twig, lijst.js) ────── */
/* Terwijl de lijst ververst (zoeken, filteren, bladeren): even iets lichter, geen spinner. */
/* Ook de lijst zelf is een "lijst"-container, zodat alles erin (de bulkbalk) meedoet met de
   kaartvorm als de lijst smal wordt -- niet alleen de tabel. */
.lijst { container: lijst / inline-size; transition: opacity .12s ease; }
.lijst.is-laden { opacity: .55; }
/* Met JavaScript ververst de lijst al tijdens het typen: de Zoeken-knop is dan overbodig. */
.lijst-live .lijst-filters__zoekknop { display: none; }
/* Niets gevonden: een rustig vak met wat je kunt doen (filters wissen of iets toevoegen). */
.lijst-leeg {
    display: flex; flex-direction: column; align-items: center; gap: .8rem;
    padding: 2.2rem 1.2rem; text-align: center;
    border: 1px dashed var(--hairline-strong); border-radius: var(--radius);
    background: var(--surface);
}
.lijst-leeg__tekst { margin: 0; color: var(--muted); }
/* Filterbalk en bulkbalk: een vinkje staat in de rij, zonder eigen marge. */
.toolbar .check { margin: 0; white-space: nowrap; }
.lijst-bulk { margin: 0; }
.lijst-bulk .bulk-bar { margin-bottom: .9rem; }
.table th.vink, .table td.vink { width: 1px; padding-right: 0; }
/* Selecteren in kaartvorm (lijst.js, feedback e4d4d577). Op een brede lijst staan vinkjes en
   bulkbalk er altijd en is de knop "Selecteren" weg. In kaartvorm (telefoon, of de lijst naast het
   zijpaneel) leunt de bulkbalk op vinkjes die er niet zijn: dan staan ze er pas na een tik op
   "Selecteren" (.is-selecteren op de lijst). Elke kaart krijgt links zijn vinkje, een
   geselecteerde kaart een rand, en de bulkbalk staat vast onderin, boven de veilige zone van de
   iPhone. Werkt voor elke kaartlijst met een kolom {vink: true}, ook als de kaart zelf flex is. */
.lijst-selecteer { display: none; }
@container lijst (max-width: 640px) {
    .lijst-selecteer { display: flex; align-items: center; justify-content: flex-end; gap: .6rem; margin: 0 0 .5rem; }
    .lijst-selecteer__alles { display: none; margin-right: auto; }
    .lijst.is-selecteren .lijst-selecteer__alles { display: inline-flex; }
    .lijst-bulk .bulk-bar { display: none; }
    .lijst.is-selecteren .lijst-bulk { display: flex; flex-direction: column; }
    .lijst.is-selecteren .table--cards tbody tr:has(> td.vink) { padding-left: 2.75rem; }
    .lijst.is-selecteren .table--cards tbody tr > td.vink {
        display: block; position: absolute; top: .8rem; left: .85rem; width: auto; padding: 0; border: 0;
    }
    .lijst.is-selecteren .table--cards td.vink input[type=checkbox] { width: 22px; height: 22px; margin: 0; }
    .lijst.is-selecteren .table--cards tbody tr:has(input[data-lijst-vink]:checked) {
        border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary);
    }
    /* De bulkbalk staat in de HTML boven de lijst; in de selectiemodus komt hij eronder
       (order) en blijft hij onderin in beeld (sticky) tot het einde van de lijst. */
    .lijst.is-selecteren .lijst-bulk > .bulk-bar {
        display: flex; order: 1; position: sticky; bottom: 0; z-index: 3;
        max-height: 55vh; overflow-y: auto;
        margin: .5rem calc(-1 * var(--pagina-rand)) 0;
        padding: .7rem var(--pagina-rand) max(.7rem, env(safe-area-inset-bottom, 0px));
        background: var(--surface); border-top: 1px solid var(--hairline); box-shadow: var(--shadow-lg);
    }
    .lijst.is-selecteren .lijst-bulk > .bulk-bar > .muted:first-child { flex: 1 1 100%; }
    .lijst.is-selecteren .lijst-bulk > .bulk-bar > :is(select, .picker) { flex: 1 1 calc(50% - .6rem); min-width: 0; }
    .lijst.is-selecteren .lijst-bulk > .bulk-bar > .toolbar__groep { flex: 1 1 100%; min-width: 0; }
    .lijst.is-selecteren .lijst-bulk > .bulk-bar > .toolbar__groep > :is(select, .picker) { flex: 1 1 auto; min-width: 0; }
}
/* De zwevende feedbackknop (rechtsonder, z-index 9100) viel in de selectiemodus precies over de
   knoppen rechtsonder in de vaste bulkbalk (op 375px: "Prioriteit" van Taken). Net als bij een
   invoerveld (feedback.js, is-aan-de-kant) gaat hij dan half doorzichtig opzij en laat hij
   klikken door naar de balk; na "Klaar" is hij weer gewoon terug. */
body:has(.lijst.is-selecteren) #feedback-root .fb-launcher { opacity: .22; pointer-events: none; }

/* ── Het bord-onderdeel (templates/componenten/bord.twig, bord.js) ──────────
   Taken, Deals en Projecten: kolommen naast elkaar, zijwaarts scrollen binnen het bord (niet de
   pagina). Een kolom mag een eigen kleur hebben (--bord-kleur, bijv. de taakstatus). */
.bord { display: flex; gap: 1rem; align-items: flex-start; overflow-x: auto; padding-bottom: .75rem; overscroll-behavior-x: contain; }
.bord__kolom {
    flex: 0 0 17rem; display: flex; flex-direction: column;
    background: var(--surface-2); border: 1px solid var(--hairline); border-radius: var(--radius);
}
.bord__kop {
    padding: .7rem .9rem; border-bottom: 1px solid var(--hairline);
    border-top: 3px solid var(--bord-kleur, transparent); border-radius: var(--radius) var(--radius) 0 0;
}
.bord__titel { font-weight: 600; display: flex; justify-content: space-between; align-items: center; gap: .5rem; }
.bord__kolom[style] .bord__titel > :first-child { color: var(--bord-kleur); }
.bord__sub { font-size: .82rem; color: var(--muted); }
.bord__kaarten { display: flex; flex-direction: column; gap: .6rem; padding: .75rem; min-height: 5rem; }
.bord__leeg { margin: 0; color: var(--muted); font-size: .85rem; }
.bord__meer {
    align-self: flex-start; padding: .2rem .1rem; background: none; border: 0; cursor: pointer;
    font: inherit; font-size: .82rem; font-weight: 600; color: var(--primary);
}
.bord__meer:hover { text-decoration: underline; }
.bord-kaart { border: 1px solid var(--hairline); border-radius: var(--radius-sm); padding: .6rem .7rem; background: var(--surface); }
.bord-kaart.is-ingekort { display: none; }
.bord-kaart__boven {
    display: block; margin-bottom: .15rem; font-size: .72rem; font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bord-kaart__boven:hover { color: var(--primary); }
.bord-kaart__titel { font-weight: 600; display: block; }
.bord-kaart__meta { font-size: .82rem; color: var(--muted); }
.bord-kaart__meta--let-op { color: var(--danger); font-weight: 600; }
.bord-kaart__waarde { font-weight: 600; }
.bord-kaart__persoon { display: flex; align-items: center; gap: .4rem; margin: .3rem 0 .15rem; }
.bord-kaart__team { margin-top: .45rem; }
.bord-kaart__labels { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .4rem; }
.bord-kaart__acties { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem; margin-top: .5rem; }
.bord-kaart__acties .btn-link { font-size: .8rem; }
/* .inline-form zet display:inline en wint daarmee van het hidden-attribuut ("Afronden" in de afrondkolom). */
.bord-kaart__acties form[hidden] { display: none; }
.bord-stap {
    background: var(--surface); border: 1px solid var(--hairline-strong); border-radius: 4px; cursor: pointer;
    font: inherit; font-size: .8rem; line-height: 1; padding: .2rem .45rem; color: var(--text);
}
.bord-stap:hover:not([disabled]) { border-color: var(--primary); color: var(--primary); }
.bord-stap[disabled] { opacity: .35; cursor: default; }
/* Slepen (bord.js maakt de kaarten pas sleepbaar; zonder JavaScript raakt dit niets). */
.bord-kaart[draggable="true"] { cursor: grab; }
.bord-kaart.is-gesleept { opacity: .4; cursor: grabbing; }
.bord__kolom.is-doel { border-color: var(--primary); }
.bord__kolom.is-doel .bord__kaarten { background: var(--primary-soft); border-radius: 0 0 var(--radius) var(--radius); }
.bord__streep { height: 3px; border-radius: 3px; background: var(--primary); }
@media (prefers-reduced-motion: no-preference) {
    .bord__kolom, .bord-kaart { transition: border-color .15s ease, background-color .15s ease, opacity .12s ease; }
    .bord-kaart.is-geland { animation: bord-geland .9s ease-out; }
    @keyframes bord-geland { from { background: var(--primary-soft); border-color: var(--primary); } }
}

/* ── Bladerbalk onder een lijst (partials/_paginering.twig) ─────────────── */
.lijst-pager {
    display: flex; align-items: center; flex-wrap: wrap; gap: .75rem 1.1rem;
    margin-top: 1rem;
}
.lijst-pager__tel { font-variant-numeric: tabular-nums; }
.lijst-pager__grootte { display: inline-flex; align-items: center; gap: .45rem; }
.lijst-pager__grootte select {
    padding: .38rem .5rem; border-radius: var(--radius-sm);
    border: 1px solid var(--hairline-strong); background: var(--surface);
    color: var(--text); font: inherit; font-size: .86rem;
}
/* De knoppen rechts uitlijnen zodat Vorige/Volgende los van de teller staat. */
.lijst-pager__knoppen { margin-left: auto; display: inline-flex; align-items: center; gap: .5rem; }
.lijst-pager__knop { padding: .4rem .8rem; font-size: .85rem; }
.lijst-pager__pos { font-variant-numeric: tabular-nums; min-width: 3.5rem; text-align: center; }
.lijst-pager .is-disabled { opacity: .45; pointer-events: none; }

/* ── Labels ────────────────────────────────────────────────────────────────
   .badge zonder toon = een gewoon label in de merkkleur (type, "Testmodus", ...). Een STATUS krijgt
   altijd een vaste toon (docs/ui-regels.md, "Statuskleuren"), via badgeClass() op de enum:
     --success  groen   betaald, voltooid, klaar, actief, akkoord
     --warning  oranje  wacht (op de klant, een onderdeel, een bevestiging, de wachtrij)
     --danger   rood    verlopen, mislukt, verloren, afgewezen
     --info     blauw   verzonden, in behandeling, lopend
     --muted    grijs   concept, gesloten, geannuleerd
   Kleuren alleen via de tokens; het donkere thema zet alleen andere tokenwaarden. */
.badge {
    display: inline-block; padding: .16rem .6rem;
    border-radius: var(--radius-pill);
    background: var(--accent-label-soft); color: var(--accent-label);
    font-size: .76rem; font-weight: 550; letter-spacing: -.005em;
    white-space: nowrap;
}
.badge--muted { background: var(--muted-soft); color: var(--muted-text); }
.badge--danger { background: var(--danger-soft); color: var(--danger); }
.badge--success { background: var(--success-soft); color: var(--success-text); }
.badge--warning { background: var(--warning-soft); color: var(--warning-text); }
.badge--info { background: var(--info-soft); color: var(--info); }
/* De documentstatussen (InvoiceStatus, QuoteStatus, CreditNoteStatus) hebben eigen klassenamen;
   hier wijzen ze naar dezelfde vaste tonen, zodat ze op elke pagina kloppen (ook in een
   klantpaneel of het dashboard, zonder document-formulier.css). */
.badge--concept { background: var(--muted-soft); color: var(--muted-text); }
.badge--verzonden { background: var(--info-soft); color: var(--info); }
.badge--betaald { background: var(--success-soft); color: var(--success-text); }
/* Voldaan via verrekening met een creditnota: er is geen geld ontvangen, dus niet groen
   (niet te verwarren met betaald). De factuur is afgesloten: grijs. */
.badge--gecrediteerd { background: var(--muted-soft); color: var(--muted-text); }
.badge--geannuleerd { background: var(--muted-soft); color: var(--muted-text); text-decoration: line-through; }

/* ── Popups: de pagina erachter staat stil ─────────────────────────────────
   Regel 1 uit docs/ui-regels.md: zolang er een popup open is, scrollt de pagina erachter
   niet mee. Geldt voor ELKE modale <dialog> (showModal) op een adminpagina, dus ook voor
   popups die later bijkomen. Beperkt tot body.app: de kassa- en reparatieschil (eigen
   body-class) houden hun eigen gedrag.
   scrollbar-gutter: stable houdt de ruimte van de schuifbalk altijd vrij, zodat de pagina
   niet opzij springt als de schuifbalk bij het openen wegvalt. */
html:has(body.app) { scrollbar-gutter: stable; }
html:has(body.app dialog:modal) { overflow: hidden; }
/* Scrollen binnen een popup loopt niet door naar de pagina (mobiel: geen "doorschieten"). */
.modal, .venster__inhoud { overscroll-behavior: contain; }

/* ── Venster (native <dialog>) ─────────────────────────────────────────── */
/* Matglas, net als het inlogscherm: doorschijnend wit met blur en een lichte
   glans langs de bovenrand. */
.modal {
    width: min(560px, calc(100vw - 2rem));
    padding: 1.6rem 1.7rem 1.5rem;
    border: 1px solid rgba(255, 255, 255, .55);
    border-radius: 22px;
    box-shadow: 0 30px 80px rgba(8, 20, 40, .28), inset 0 1px 0 rgba(255, 255, 255, .75);
    background: linear-gradient(165deg, rgba(255, 255, 255, .90), rgba(255, 255, 255, .80));
    -webkit-backdrop-filter: saturate(1.8) blur(26px);
    backdrop-filter: saturate(1.8) blur(26px);
    color: var(--text);
}
/* Quick-create-popups altijd volledig in beeld, nooit afgekapt bovenaan (feedback Calvin "alle popups"):
   expliciet gecentreerd (zoals .venster) + begrensd op de zichtbare schermhoogte, lange inhoud scrollt intern. */
.modal[open] { position: fixed; inset: 0; margin: auto; max-height: calc(100dvh - 1.5rem); overflow-y: auto; }
.modal::backdrop {
    background: rgba(10, 22, 42, .45);
    -webkit-backdrop-filter: blur(6px) saturate(1.2);
    backdrop-filter: blur(6px) saturate(1.2);
}
/* Velden in het venster iets doorschijnend, zodat ze bij het glas passen. */
.modal input[type=text], .modal input[type=email], .modal select {
    background: rgba(255, 255, 255, .72);
    border-color: rgba(20, 24, 31, .12);
}
.modal input:focus, .modal select:focus { background: #fff; }
.modal h2 { margin: 0 0 .2rem; }
.modal .form-actions { margin-top: 1.2rem; }
.modal__close-form { float: right; margin: -.4rem -.4rem 0 0; }
.modal__close {
    background: none; border: 0; cursor: pointer;
    font-size: 1.4rem; line-height: 1; color: var(--muted); padding: .2rem .35rem;
    border-radius: var(--radius-sm);
}
.modal__close:hover { background: var(--surface-2); color: var(--text); }

/* ── Popup: één sjabloon voor elke popup ──────────────────────────────────
   templates/componenten/popup.twig en public/assets/js/popup.js; regels in
   docs/ui-regels.md §4. Kop (titel + sluitknop), een inhoud die zelf scrolt en een voet
   met knoppen. De soort bepaalt de breedte en het gedrag op de telefoon:
     popup--bevestigen  klein; telefoon: onderblad
     popup--formulier   middel; telefoon: volledig scherm
     popup--record      breed; telefoon: volledig scherm
   Altijd gecentreerd in beeld (position:fixed + inset + margin:auto), ook op een ver
   gescrolde pagina; dat de pagina erachter stilstaat regelt de regel bij .badge--warning. */
.popup {
    position: fixed; inset: 0; margin: auto;
    width: min(var(--popup-breedte, 560px), calc(100vw - 2rem));
    max-height: calc(100vh - 2rem);
    max-height: calc(100dvh - 2rem);
    padding: 0;
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}
.popup[open] { display: flex; flex-direction: column; }
.popup::backdrop {
    background: rgba(10, 22, 42, .45);
    -webkit-backdrop-filter: blur(6px) saturate(1.2);
    backdrop-filter: blur(6px) saturate(1.2);
}
.popup--bevestigen { --popup-breedte: 440px; }
.popup--formulier { --popup-breedte: 560px; }
.popup--record { --popup-breedte: 940px; }

.popup__kop {
    display: flex; align-items: center; gap: .75rem; flex: none;
    padding: .85rem .85rem .8rem 1.4rem;
    border-bottom: 1px solid var(--hairline);
}
.popup__titel { flex: 1 1 auto; min-width: 0; margin: 0; font-size: 1.08rem; }
.popup__sluit-form { display: contents; }
.popup__sluit {
    flex: none; display: grid; place-items: center; width: 36px; height: 36px; padding: 0;
    border: 1px solid var(--hairline); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--muted);
    font: inherit; font-size: 1.35rem; line-height: 1; cursor: pointer;
}
.popup__sluit:hover { background: var(--surface-2); color: var(--text); }
.popup__inhoud {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
    padding: 1.1rem 1.4rem 1.3rem;
}
.popup__inhoud > :first-child { margin-top: 0; }
.popup__inhoud > :last-child { margin-bottom: 0; }
.popup__intro { margin: 0 0 1rem; }
.popup__tekst { margin: 0; font-size: 1rem; line-height: 1.5; }
.popup__voet {
    display: flex; justify-content: flex-end; flex-wrap: wrap; gap: .6rem; flex: none;
    margin: 0; padding: .8rem 1.4rem;
    border-top: 1px solid var(--hairline); background: var(--surface-2);
}
/* Een popup waarvan inhoud en voet samen één formulier zijn (Arctic.vraag): het formulier doet
   niet mee in de opbouw, zodat inhoud en voet gewoon onder elkaar staan. */
.popup__formulier { display: contents; }
/* Geen knoppen in de voet: geen lege balk. */
.popup__voet:not(:has(*)) { display: none; }
.popup--bevestigen .popup__inhoud { padding: 1.3rem 1.4rem; }
.popup--bevestigen .popup__voet { border-top: 0; background: transparent; padding-top: 0; }

@media (prefers-reduced-motion: no-preference) {
    .popup[open] { animation: popup-in .16s cubic-bezier(.2, .7, .3, 1); }
    .popup[open]::backdrop { animation: popup-achtergrond .16s ease; }
}
@keyframes popup-in { from { opacity: 0; transform: translateY(8px) scale(.985); } }
@keyframes popup-onderblad { from { transform: translateY(100%); } }
@keyframes popup-achtergrond { from { opacity: 0; } }

/* ── Menu: het uitklapmenu achter een knop (⋯ Meer, PDF, …) ─────────────
   Een native <details class="menu"> met een <summary> als knop en een .menu__paneel:
   werkt ook zonder JavaScript. popup.js sluit hem bij een klik ernaast of Escape, en er staat
   er maar één tegelijk open. Op de telefoon schuift hij als onderblad van onderen in beeld.
       <details class="menu">
           <summary class="btn">Meer</summary>
           <div class="menu__paneel"> <a>…</a> <form><button>…</button></form> </div>
       </details> */
.menu { position: relative; display: inline-block; }
.menu > summary { list-style: none; cursor: pointer; }
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary.btn::after { content: " \25BE"; opacity: .6; }
.menu__paneel {
    position: absolute; right: 0; top: calc(100% + .3rem); z-index: 30; min-width: 210px;
    padding: .35rem; background: var(--surface);
    border: 1px solid var(--hairline-strong); border-radius: var(--radius); box-shadow: var(--shadow-lg);
}
.menu__paneel a, .menu__paneel button {
    display: block; width: 100%; padding: .5rem .7rem; border: 0; border-radius: var(--radius-sm);
    background: none; color: var(--text); font: inherit; font-size: .9rem; text-align: left;
    text-decoration: none; white-space: nowrap; cursor: pointer;
}
.menu__paneel a:hover, .menu__paneel button:hover { background: var(--surface-2); text-decoration: none; }
.menu__paneel form { margin: 0; }
.menu__paneel hr { border: 0; border-top: 1px solid var(--hairline); margin: .3rem 0; }
.menu__paneel .menu__gevaar { color: var(--danger); }

/* ── Melding onderin beeld (Arctic.melding in popup.js) ──────────────────── */
.toast {
    position: fixed; left: 50%; z-index: 9500;
    bottom: max(1.5rem, calc(env(safe-area-inset-bottom, 0px) + 1rem));
    max-width: min(520px, calc(100vw - 2rem));
    padding: .7rem 1.05rem; border-radius: var(--radius-sm);
    background: var(--text); color: var(--surface);
    font-size: .92rem; font-weight: 500; box-shadow: var(--shadow-lg);
    opacity: 0; transform: translate(-50%, .6rem); pointer-events: none;
    transition: opacity .2s ease, transform .2s ease;
}
.toast.is-zichtbaar { opacity: 1; transform: translate(-50%, 0); }
.toast--error { background: var(--danger); color: #fff; }
.toast--success { background: var(--success); color: #fff; }

/* ── Venster: een record bekijken/bewerken in een popup ─────────────────────
   venster.js bouwt een <dialog class="popup popup--record venster">: de schil (breedte,
   centreren, achtergrond, telefoon schermvullend) is het gedeelde .popup hierboven. De kop zit
   hier in het fragment van de server (titel, status, ⋯-menu), dus geen .popup__kop: alleen de
   sluitknop zweeft rechtsboven, op dezelfde plek als in elke andere popup. */
.venster__sluit { position: absolute; top: .85rem; right: .85rem; z-index: 5; }
.venster__inhoud { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 1.3rem 1.5rem 1.5rem; }
.venster__laden { padding: 3.5rem 1.5rem; text-align: center; color: var(--muted); }
/* Onopvallende melding boven het fragment na een actie (verschijnt kort). */
.venster__flits { margin: 0 0 1rem; }
/* De melding bij het plakken van een schermafdruk (Ctrl+V) is de gedeelde .toast (Arctic.melding). */

/* Twee kolommen op een breed venster (werk links, gegevens rechts), één kolom
   op smal. Fragmenten gebruiken dit voor de Perfex-achtige indeling. */
.venster-grid { display: grid; gap: 1.3rem 1.6rem; align-items: start; }
@media (min-width: 800px) { .venster-grid { grid-template-columns: minmax(0, 1fr) 290px; } }
.venster-grid > * { min-width: 0; }

/* ── Detailpaneel naast de lijst ─────────────────────────────────────────────
   paneel.js dokt de VOLLEDIGE detailpagina (in een iframe met ?paneel=1) rechts naast
   de lijst; de lijst (.main) schuift ernaast en wordt smaller — precies zoals bij een
   factuur die je opent. Vast aan het scherm, net als de zijbalk. Anders dan het venster
   (een modal met een uitgekleed fragment) blijven hier álle knoppen en formulieren
   werken, want het is de echte pagina, alleen zonder de admin-schil. Op smallere
   schermen legt het paneel zich als overlay over de lijst i.p.v. ernaast. */
:root { --paneel-breedte: min(50vw, 860px); }

.paneel {
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 40;
    width: var(--paneel-breedte);
    display: flex; flex-direction: column;
    background: var(--surface);
    border-left: 1px solid var(--hairline-strong);
    box-shadow: -12px 0 40px rgba(12, 24, 45, .12);
}
.paneel__balk {
    display: flex; align-items: center; gap: .75rem;
    padding: .5rem .7rem .5rem 1rem;
    border-bottom: 1px solid var(--hairline);
    background: var(--surface-2);
}
.paneel__titel {
    flex: 1; min-width: 0;
    font-weight: 600; font-size: .95rem; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.paneel__vol { font-size: .85rem; color: var(--primary); text-decoration: none; white-space: nowrap; }
.paneel__vol:hover { text-decoration: underline; }
/* De sluitknop is dezelfde als in elke popup (.popup__sluit); paneel.js zet beide klassen. */
.paneel__laden { padding: 2.5rem 1.5rem; text-align: center; color: var(--muted); }
.paneel__frame { flex: 1; width: 100%; border: 0; background: var(--canvas); }
/* Dicht = weg. paneel.js bouwt de <aside> één keer en hergebruikt hem: sluiten haalt
   `has-paneel` van de body en maakt de iframe leeg, maar de aside is `position: fixed`
   en zou anders als leeg wit paneel blijven staan (het kruisje leek dan niets te doen).
   Deze regel verbergt hem zodra het paneel dicht is; open() zet `has-paneel` terug. */
body:not(.has-paneel) .paneel { display: none; }
/* De achtergrond-scrim: standaard weg (op breed scherm staat het paneel naast de lijst,
   die blijft bruikbaar). Alleen in de overlay-modus hieronder komt hij in beeld. */
.paneel__scrim { display: none; }

/* De lijst schuift naast het paneel en wordt smaller. */
body.has-paneel .main { margin-right: var(--paneel-breedte); }

/* De aangeklikte rij blijft gemarkeerd zolang het paneel open is. */
tr.is-paneel-actief > td { background: var(--primary-soft); }

/* De zwevende feedbackknop (en pinnen) zitten op de lijstpagina op z-index 9000+ en zouden
   over het paneel heen vallen; verberg ze zolang het paneel open is. */
body.has-paneel #feedback-root,
body.has-paneel #feedback-pins { display: none; }

/* In het paneel zweeft geen feedbackknop, dus de extra ruimte onder .content (die daar
   langs laat scrollen) is hier overbodig. */
.paneel-body .content { padding-bottom: 1.6rem; }

@media (max-width: 1279px) {
    /* Te weinig ruimte voor een split: het paneel wordt een overlay over de lijst, met
       een scrim eronder zodat de lijst niet per ongeluk meebeweegt of aangeklikt wordt. */
    :root { --paneel-breedte: min(94vw, 860px); }
    body.has-paneel .main { margin-right: 0; }
    body.has-paneel { overflow: hidden; }
    body.has-paneel .paneel__scrim {
        display: block;
        position: fixed; inset: 0; z-index: 39;
        background: rgba(12, 24, 45, .45);
        -webkit-backdrop-filter: blur(2px);
        backdrop-filter: blur(2px);
    }
}

/* ── Detailregels ──────────────────────────────────────────────────────── */
.details { display: grid; grid-template-columns: 168px 1fr; gap: .45rem .9rem; margin: 0; font-size: .93rem; }
.details dt { color: var(--muted); }
.details dd { margin: 0; }

/* ── Instellingen-hub ──────────────────────────────────────────────────── */
/* minmax(0, 1fr): met een kale 1fr groeide de inhoudskolom mee met een brede tabel (bijv. de
   mail-wachtrij) en schoof de hele pagina zijwaarts; nu scrolt alleen die tabel binnen zijn vak. */
.settings { display: grid; grid-template-columns: 252px minmax(0, 1fr); gap: 1.4rem; align-items: start; }
.settings__nav {
    background: var(--surface);
    border: 1px solid rgba(255, 255, 255, .7);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255, 255, 255, .6);
    padding: .9rem .6rem; position: sticky; top: 5rem;
}
.settings__nav-title { font-weight: 600; padding: .2rem .55rem .8rem; letter-spacing: -.01em; }
.settings__group { margin-bottom: .9rem; }
.settings__group-label {
    display: block; padding: 0 .55rem .3rem;
    font-size: .69rem; font-weight: 600; text-transform: uppercase; letter-spacing: .07em;
    color: var(--muted);
}
.settings__link {
    display: block; padding: .42rem .55rem; border-radius: var(--radius-sm);
    color: var(--text-2); text-decoration: none; font-size: .91rem;
    transition: background-color .14s ease, color .14s ease;
}
.settings__link:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.settings__link.is-active { background: var(--primary); color: #fff; font-weight: 500; }
.settings__head { margin-bottom: 1.2rem; }
.settings__head h1 { margin-bottom: .2rem; }
.settings__body .panel:last-of-type { margin-bottom: 0; }

/* Tabstrip (ook gebruikt door de rapportages) */
.settings-nav { display: flex; gap: .15rem; border-bottom: 1px solid var(--hairline); margin: 0 0 1.2rem; }
.settings-nav a {
    padding: .5rem .85rem; color: var(--muted); text-decoration: none;
    border-bottom: 2px solid transparent; margin-bottom: -1px; font-size: .92rem;
}
.settings-nav a:hover { color: var(--text); text-decoration: none; }
.settings-nav a.is-active { color: var(--primary); border-bottom-color: var(--primary); font-weight: 550; }

/* Huisstijl-voorbeeld */
.brand-preview {
    border-radius: var(--radius); background-size: cover; background-position: center;
    padding: 2rem; display: flex; align-items: center; justify-content: center; min-height: 160px;
}
.brand-preview__card {
    background: rgba(8, 24, 41, .46);
    -webkit-backdrop-filter: blur(18px) saturate(1.2);
    backdrop-filter: blur(18px) saturate(1.2);
    border: .8px solid rgba(255, 255, 255, .16); border-radius: 20px;
    padding: 1.15rem 1.6rem; display: flex; align-items: center; gap: .75rem;
}
.brand-preview__logo { height: 26px; width: auto; max-width: 200px; object-fit: contain; }
.brand-preview__dot { width: 12px; height: 12px; border-radius: var(--radius-pill); display: inline-block; }

/* Voorbeeld van de zijbalk: zelfde ondergrond en maten als het echte menu. */
.brand-preview--sidebar {
    background: linear-gradient(180deg, var(--sidebar-a) 0%, var(--sidebar-b) 100%);
    justify-content: flex-start; align-items: flex-start; padding: 1.25rem; min-height: 120px;
}
.brand-preview__sidebar {
    width: 244px; max-width: 100%; padding: .35rem .5rem;
    display: flex; align-items: center; gap: .6rem;
}

/* ── Inloggen: matglas op het Webarctic-berglandschap ──────────────────── */
.guest { background: #0b1b2e; overflow: hidden; }
/* Precies zo hoog als het scherm, niet hoger. Met min-height:100vh rekent mobiel de
   adresbalk niet mee: de pagina werd dan een paar tientallen pixels te lang en je kon
   hem wegscrollen. 100dvh volgt de werkelijk zichtbare hoogte; de 100vh-regel erboven
   blijft staan als terugval voor browsers die dvh niet kennen.
   background-attachment: fixed is eruit — bij een vaste hoogte voegt het niets toe en
   op iOS geeft het schokkerig gedrag. */
.guest-wrap {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 1.25rem; padding: 1.5rem;
    background-size: cover; background-position: center; background-repeat: no-repeat;
}
.glass-card {
    width: 100%; max-width: 420px; padding: 2.5rem;
    /* Past de kaart bij uitzondering toch niet (telefoon in liggende stand), dan
       schuift hij van binnen mee. Beter dan een inlogknop die buiten beeld valt. */
    max-height: 100%; min-height: 0; overflow-y: auto;
    background-color: rgba(8, 24, 41, .46);
    background-image: linear-gradient(rgba(255, 255, 255, .10), rgba(255, 255, 255, .043));
    -webkit-backdrop-filter: blur(18px) saturate(1.2);
    backdrop-filter: blur(18px) saturate(1.2);
    border: .8px solid rgba(255, 255, 255, .16);
    border-radius: 30px;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18), 0 30px 90px rgba(5, 19, 34, .28);
    color: #fff; text-align: center;
    animation: glass-arrive .5s cubic-bezier(.22, .61, .36, 1) both;
}
@keyframes glass-arrive {
    from { opacity: 0; transform: translateY(10px) scale(.985); filter: blur(4px); }
    to { opacity: 1; transform: none; filter: none; }
}
/* Ook hier vaste hoogte + begrensde breedte, zodat een breed of hoog logo de
   kaart niet uit balans trekt. */
.glass-card__logo {
    display: block; height: 34px; width: auto;
    max-width: 260px; object-fit: contain;
    margin: 0 auto 1.5rem;
}
.glass-card__wordmark {
    margin: 0 auto 1.5rem; color: #fff;
    font-size: 1.15rem; font-weight: 600; letter-spacing: .01em;
}
.glass-pill {
    display: inline-block; margin-bottom: 1rem; padding: .3rem .85rem;
    background: rgba(255, 255, 255, .06); border: .8px solid rgba(255, 255, 255, .14);
    border-radius: var(--radius-pill); color: rgba(255, 255, 255, .78);
    font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
}
.glass-title { font-size: 1.7rem; margin: 0 0 .25rem; color: #fff; }
.glass-sub { margin: 0 0 1.5rem; color: rgba(255, 255, 255, .7); font-size: .95rem; }
.glass-card .form { text-align: left; }
.glass-card .field > span { color: rgba(255, 255, 255, .72); }
.glass-card input[type=email],
.glass-card input[type=password],
.glass-card input[type=text] {
    background: rgba(255, 255, 255, .07); border: .8px solid rgba(255, 255, 255, .18);
    color: #fff; border-radius: 12px; padding: .7rem .85rem;
}
.glass-card input::placeholder { color: rgba(255, 255, 255, .45); }
.glass-card input:focus {
    border-color: rgba(255, 255, 255, .45); background: rgba(255, 255, 255, .12);
    box-shadow: none;
}
.btn-glass {
    display: block; width: 100%; padding: .75rem 1rem; border-radius: 14px; cursor: pointer;
    font: inherit; font-weight: 600; border: .8px solid rgba(255, 255, 255, .18);
    background: rgba(255, 255, 255, .06); color: #fff; margin-top: .5rem;
}
.btn-glass--primary { background: #fff; color: #0c1f33; border-color: transparent; }
.btn-glass--primary:hover { background: rgba(255, 255, 255, .9); }
/* Wachtwoordveld met een toon/verberg-knop erin, plus de caps-lock-hint eronder. */
.glass-card .wachtwoord { position: relative; display: block; }
.glass-card .wachtwoord input { width: 100%; padding-right: 4.4rem; }
.wachtwoord__toon {
    position: absolute; top: 50%; right: .5rem; transform: translateY(-50%);
    border: 0; background: none; cursor: pointer; font: inherit; font-size: .8rem;
    color: rgba(255, 255, 255, .72); padding: .25rem .45rem; border-radius: 8px;
}
.wachtwoord__toon:hover { color: #fff; background: rgba(255, 255, 255, .12); }
.capslock { display: block; margin-top: .35rem; font-size: .78rem; color: #ffd9a8; font-style: normal; }
/* Het hidden-attribuut moet winnen van de display:block hierboven, anders staat de
   caps-lock-hint meteen aan (dezelfde val als .picker__paneel[hidden]). */
.capslock[hidden] { display: none; }
/* "Ingelogd blijven" links, "wachtwoord vergeten?" rechts. */
.login-rij { display: flex; align-items: center; justify-content: space-between; gap: .75rem; margin: .1rem 0 .2rem; }
.onthoud { display: flex; align-items: center; gap: .5rem; margin: 0; cursor: pointer; font-size: .86rem; color: rgba(255, 255, 255, .8); }
.glass-card .onthoud input[type=checkbox] { width: auto; padding: 0; accent-color: #fff; }
.login-link { font-size: .84rem; color: rgba(255, 255, 255, .78); text-decoration: none; white-space: nowrap; }
.login-link:hover { color: #fff; text-decoration: underline; }
.glass-card .flash { background: rgba(255, 255, 255, .10); border-color: rgba(255, 255, 255, .2); color: #fff; text-align: left; }
.glass-card .flash--error { background: rgba(192, 57, 43, .28); border-color: rgba(255, 140, 130, .45); color: #ffe3e0; }
.guest-footer { color: rgba(255, 255, 255, .55); font-size: .8rem; margin: 0; }

/* ---- Passkey-first inlog ---- */
/* Directe, voelbare feedback op druk + focus; het accent is een helder blauw (geen paars). */
.btn-glass { transition: transform .12s cubic-bezier(.22, .61, .36, 1), background .18s ease, box-shadow .18s ease, border-color .16s ease; }
.btn-glass:active { transform: scale(.985); }
.btn-glass:focus-visible { outline: none; box-shadow: 0 0 0 4px rgba(79, 147, 242, .5); }
.btn-glass--primary { box-shadow: 0 12px 28px -14px rgba(79, 147, 242, .6); }
.btn-glass--primary:hover { box-shadow: 0 16px 34px -14px rgba(79, 147, 242, .78); transform: translateY(-1px); }
.btn-glass--icon { display: flex; align-items: center; justify-content: center; gap: .55rem; }
.btn-glass--icon svg { flex: none; }
/* [hidden] moet winnen van de display-regels hierboven (zelfde val als .capslock[hidden]). */
.login-passkey[hidden], .form[hidden], .login-terug[hidden] { display: none !important; }
.passkey-hint { margin: .55rem 0 0; font-size: .8rem; line-height: 1.45; color: rgba(255, 255, 255, .7); }
.passkey-melding { display: block; margin-top: .5rem; font-size: .82rem; color: rgba(255, 255, 255, .82); font-style: normal; }
.passkey-melding:empty { display: none; }
.login-of { display: flex; align-items: center; gap: .7rem; margin: 1.05rem 0 .1rem; color: rgba(255, 255, 255, .6); font-size: .74rem; text-transform: uppercase; letter-spacing: .12em; }
.login-of::before, .login-of::after { content: ""; height: 1px; flex: 1; background: rgba(255, 255, 255, .16); }
.login-of span { flex: none; }
.login-terug { display: block; width: 100%; margin: .4rem 0 0; padding: .5rem; border: 0; background: none; cursor: pointer; font: inherit; font-size: .85rem; font-weight: 600; color: rgba(255, 255, 255, .75); }
.login-terug:hover { color: #fff; }
/* Accent-focusring op de velden i.p.v. de vlakke rand van voorheen. */
.glass-card input:focus { border-color: rgba(130, 175, 250, .85); background: rgba(255, 255, 255, .12); box-shadow: 0 0 0 4px rgba(79, 147, 242, .4); }
@media (prefers-reduced-motion: reduce) {
    .glass-card { animation: none; }
    .btn-glass { transition: none; }
    .btn-glass:active, .btn-glass--primary:hover { transform: none; }
}
@media (prefers-reduced-transparency: reduce) {
    .glass-card { background: #10263d; -webkit-backdrop-filter: none; backdrop-filter: none; }
}

/* Lage schermen: alles krimpt mee zodat de kaart binnen het scherm blijft passen.
   De volgorde van weglaten is bewust — eerst het decor (het label "Portaal", de
   ondertitel), dan de kop, en pas als laatste raken we het merk aan. Wat er hoe dan
   ook moet blijven staan zijn de twee velden en de knop; daar kom je om. */
@media (max-height: 680px) {
    .guest-wrap { gap: .6rem; padding: .7rem; }
    .glass-card { padding: 1.35rem 1.6rem; border-radius: 22px; }
    .glass-card__logo { height: 26px; margin-bottom: .8rem; }
    .glass-card__wordmark { margin-bottom: .8rem; font-size: 1.02rem; }
    .glass-pill { display: none; }
    .glass-title { font-size: 1.25rem; margin-bottom: .15rem; }
    .glass-sub { margin-bottom: .9rem; font-size: .88rem; }
    .glass-card .field { margin-bottom: .6rem; }
}

@media (max-height: 500px) {
    .guest-wrap { gap: .4rem; padding: .5rem; }
    .glass-card { padding: 1rem 1.4rem; }
    .glass-card__logo { height: 22px; margin-bottom: .55rem; }
    .glass-card__wordmark { margin-bottom: .55rem; font-size: .95rem; }
    /* Kop en ondertitel zijn hier puur sfeer; het formulier spreekt voor zich. */
    .glass-title, .glass-sub { display: none; }
    .glass-card .field { margin-bottom: .45rem; }
    .glass-card .field > span { font-size: .78rem; }
    .guest-footer { display: none; }
    .passkey-hint, .login-of { display: none; }
}

.error-code { font-size: 2.6rem; letter-spacing: -.03em; }

/* ── Responsief ────────────────────────────────────────────────────────── */
@media (max-width: 980px) {
    .cards-2 { grid-template-columns: 1fr; }
    .settings { grid-template-columns: 1fr; }
    .settings__nav { position: static; }
    .topsearch { flex-basis: 220px; margin-left: .75rem; }
}

@media (max-width: 760px) {
    /* De zijbalk/menu op smalle schermen staat in het blok "Mobiele schil" onderaan. */
    .content { padding: var(--pagina-rand); }
    .details { grid-template-columns: 1fr; gap: .1rem .9rem; }
    .details dt { margin-top: .5rem; }
    /* Documentformulier (factuur/offerte/creditnota): de twee kopblokken onder elkaar. */
    .form__kop { grid-template-columns: 1fr; }
    /* Paginakop en knoprijen mogen afbreken i.p.v. horizontaal buiten beeld te lopen. */
    .page-head { flex-wrap: wrap; }
    .row-actions { flex-wrap: wrap; white-space: normal; }
    .form-actions { flex-wrap: wrap; }
    /* Het detailpaneel (master-detail) is op smal al een overlay; laat 'm de volle breedte
       pakken zodat de knoppen erin niet ingeklemd raken. */
    :root { --paneel-breedte: 100vw; }
}

/* ── Medewerkerstegels ─────────────────────────────────────────────────── */
/* Overal waar een taak, opmerking of klus een persoon heeft. Een foto als die er
   is, anders de initialen in een kleur die uit de naam volgt. */
.avatar {
    display: inline-grid; place-items: center;
    flex: none;
    border-radius: var(--radius-pill);
    object-fit: cover;
    color: #fff; font-weight: 650; letter-spacing: .01em;
    line-height: 1;
    user-select: none;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, .85), 0 1px 2px rgba(16, 24, 40, .18);
}

.avatar--leeg {
    background: var(--surface-2);
    color: var(--muted);
    box-shadow: inset 0 0 0 1px var(--hairline-strong);
    font-weight: 600;
}

.avatar--meer {
    background: var(--surface-2);
    color: var(--text-2);
    font-weight: 650;
}

.avatar-naam { display: inline-flex; align-items: center; gap: .45rem; }

/* Overlappende rij: de tegels schuiven over elkaar heen, de eerste bovenop. */
.avatar-stapel { display: inline-flex; align-items: center; }
.avatar-stapel .avatar + .avatar { margin-left: -8px; }

/* In een donkere omgeving (bordkaart op kleur, zijbalk) moet de rand meelopen. */
.is-dark .avatar { box-shadow: 0 0 0 1px rgba(255, 255, 255, .25); }

/* Fotoveld op het medewerkersformulier */
.foto-veld { display: flex; align-items: flex-start; gap: 1rem; }
.foto-veld__keuze { display: flex; flex-direction: column; gap: .45rem; min-width: 0; }
.foto-veld__keuze input[type="file"] { font-size: .88rem; }

/* ── Nummerreeksen (Instellingen) ──────────────────────────────────────────
   Eén blok per documentsoort in plaats van één tabelregel: er hoort per reeks
   een waarschuwing en een bevestiging bij te kunnen staan, en dat past niet in
   een cel. */
.seq__kop { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.seq__titel { margin: 0 0 .2rem; font-size: 1.02rem; }
.seq__voorbeeld { margin: .5rem 0 .2rem; font-size: .95rem; }
.seq__badge {
    display: inline-block; margin-left: .4rem;
    padding: .1rem .45rem; border-radius: 999px;
    background: var(--primary-soft); color: var(--primary);
    font-size: .72rem; font-weight: 600;
}
.seq__uitleg { margin: .4rem 0 0; padding-left: 1.1rem; }
.seq__uitleg li { margin-bottom: .45rem; }

/* ==========================================================================
   Licht/donker-thema (stap 1).
   LICHT is de standaard (alle :root-waarden hierboven) en blijft ongewijzigd.
   DONKER is opt-in via de schakelaar in de bovenbalk: een donker-navy palet met
   glas op de dragende vlakken (zijbalk + bovenbalk). Alles loopt via de bestaande
   tokens, dus bestaande pagina's kleuren mee zonder dat de lichte modus verandert.
   ========================================================================== */
:root[data-theme="dark"] {
    --canvas: #0a1322;
    --surface: #102038;
    --surface-2: #142741;
    --text: #eaf1fb;
    --text-2: #a9b5c6;
    --muted: #7d899a;
    --hairline: rgba(255, 255, 255, .10);
    --hairline-strong: rgba(255, 255, 255, .18);
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
    --shadow-md: 0 10px 26px -12px rgba(0, 0, 0, .6);
    --shadow-lg: 0 22px 48px -24px rgba(0, 0, 0, .7);
    --danger: #ff6f61;
    --danger-soft: rgba(255, 111, 97, .16);
    --success: #43d19e;
    --success-soft: rgba(67, 209, 158, .16);
    --warning: #f3b14e;
    --warning-soft: rgba(243, 177, 78, .16);
    --info: #9cc8ff;
    --info-soft: rgba(79, 155, 255, .16);
    --muted-soft: rgba(255, 255, 255, .08);
    /* Labeltekst (zie boven): groen en oranje halen op donker het contrast al, grijs niet. */
    --success-text: #43d19e;
    --warning-text: #f3b14e;
    --muted-text: #9aa5b5;
    /* De merkkleur is op donker te donker als tekst: een lichtere tint van dezelfde kleur. */
    --accent-label: color-mix(in srgb, var(--primary) 50%, #fff);
    --accent-label-soft: color-mix(in srgb, var(--primary) 24%, transparent);
    --sidebar-text: rgba(234, 241, 251, .72);
    color-scheme: dark;
}
/* Gevulde signaalvlakken: de signaalkleuren zijn op donker licht van tint, dus witte tekst
   haalt daar maar 2,7:1. Donkere tekst (de ondergrond) haalt ruim 6:1. */
:root[data-theme="dark"] .btn-danger--vol,
:root[data-theme="dark"] .toast--error,
:root[data-theme="dark"] .toast--success { color: var(--canvas); }
/* Rustige arctic-gloed achter het glas (alleen donker). */
:root[data-theme="dark"] body {
    background:
        radial-gradient(44% 48% at 6% 4%, rgba(56, 214, 224, .14), transparent 55%),
        radial-gradient(50% 52% at 98% 2%, rgba(79, 155, 255, .18), transparent 56%),
        radial-gradient(60% 55% at 88% 112%, rgba(38, 196, 228, .10), transparent 60%),
        linear-gradient(160deg, #0a1322, #070f1d);
    background-attachment: fixed;
}
/* Glas op de dragende vlakken: zijbalk en bovenbalk vervagen de arctic-gloed. */
:root[data-theme="dark"] .sidebar {
    background: linear-gradient(180deg, rgba(20, 36, 64, .4), rgba(12, 24, 44, .52));
    -webkit-backdrop-filter: blur(40px) saturate(1.7);
    backdrop-filter: blur(40px) saturate(1.7);
    border-right: 1px solid rgba(255, 255, 255, .1);
    box-shadow: inset -1px 0 0 rgba(255, 255, 255, .07);
}
:root[data-theme="dark"] .topbar {
    background: linear-gradient(180deg, rgba(11, 20, 36, .5), rgba(11, 20, 36, .22));
    -webkit-backdrop-filter: blur(30px) saturate(1.6);
    backdrop-filter: blur(30px) saturate(1.6);
    border-bottom: 1px solid rgba(255, 255, 255, .08);
}
/* Kaarten/kerncijfers worden in donker echt matglas: ze vervagen de arctic-gloed
   erachter, met een lichte bovenrand (licht dat op het materiaal valt) en zachte diepte. */
:root[data-theme="dark"] .panel,
:root[data-theme="dark"] .stat,
:root[data-theme="dark"] .card {
    background-color: rgba(16, 30, 54, .46);
    background-image: linear-gradient(180deg, rgba(255, 255, 255, .06), rgba(255, 255, 255, .012));
    -webkit-backdrop-filter: blur(22px) saturate(1.45);
    backdrop-filter: blur(22px) saturate(1.45);
    border-color: rgba(255, 255, 255, .12);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 14px 32px -20px rgba(0, 8, 22, .7);
}
/* Een tabel binnen een glas-paneel blijft bewust solide (geen glas-op-glas → leesbaar). */
:root[data-theme="dark"] .panel .table,
:root[data-theme="dark"] .panel .table th { background-color: transparent; }

/* De licht/donker-schakelaar in de bovenbalk (zelfde ronde vorm als de uren-knop). */
.thema-knop {
    width: 34px; height: 34px; flex: none; padding: 0;
    display: grid; place-items: center;
    border-radius: 50%; border: 1px solid var(--hairline);
    background: var(--surface); color: var(--text-2); cursor: pointer;
}
.thema-knop:hover { color: var(--text); background: var(--surface-2); }
.thema-maan { display: none; }
:root[data-theme="dark"] .thema-zon { display: none; }
:root[data-theme="dark"] .thema-maan { display: block; }

/* Donker: leesbaarheids-correcties.
   - Links (klantnamen, factuurnummers, "alle …"-links) kleuren standaard op de
     accentkleur; die is op donker te donker. Hier een heldere azuur.
   - De tabelkop had een vaste lichte achtergrond (rgba(247,248,250,…)); op donker
     geven we 'm een subtiele lichte sluier i.p.v. een witte balk. */
:root[data-theme="dark"] a { color: #7fb0ff; }
:root[data-theme="dark"] a:hover { color: #a7caff; }
:root[data-theme="dark"] .btn-link { color: #7fb0ff; }
:root[data-theme="dark"] .table th { background: rgba(255, 255, 255, .05); }
/* Labels en statuskleuren: geen klasse-overrides hier. Het donkere thema zet alleen andere
   tokenwaarden (--info, --muted-soft, --accent-label, ... in het blok bovenaan), zodat
   "Betaald" ook in donker groen blijft en "Verzonden" blauw. */
/* De snel-aanmaken-popups (.modal) zijn wit glas met donkere tekst. In donker werd de tekst
   licht terwijl het glas wit bleef: onleesbaar. Hier krijgen glas en velden de donkere vlakken. */
:root[data-theme="dark"] .modal {
    border-color: var(--hairline-strong);
    background: linear-gradient(165deg, rgba(20, 39, 65, .94), rgba(16, 32, 56, .90));
    box-shadow: 0 30px 80px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .06);
}
:root[data-theme="dark"] .modal input[type=text],
:root[data-theme="dark"] .modal input[type=email],
:root[data-theme="dark"] .modal select { background: rgba(255, 255, 255, .06); border-color: var(--hairline-strong); }
:root[data-theme="dark"] .modal input:focus,
:root[data-theme="dark"] .modal select:focus { background: rgba(255, 255, 255, .1); }

/* ── Dashboard: aandacht-eerst indeling ─────────────────────────────────────
   Themat via de tokens (licht én donker). Eerst "Vraagt aandacht" (de alert-tegels),
   dan de kerncijfers, de module-blokken en de snelkoppelingen. */
.dash-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin: 0 0 .2rem; }
.dash-head h1 { font-size: 1.6rem; margin: 0; }
.dash-head__date { margin: .15rem 0 0; color: var(--text-2); font-size: .95rem; }
.dash-inrichten { flex: none; display: inline-block; padding: .5rem .85rem; border-radius: var(--radius-sm);
    border: 1px solid var(--hairline); background: var(--surface); color: var(--text);
    font-size: .85rem; font-weight: 600; text-decoration: none; box-shadow: var(--shadow-sm); }
.dash-inrichten:hover { background: var(--surface-2); text-decoration: none; }
.dash-groet { margin: .4rem 0 0; padding: .85rem 1.05rem; border-radius: var(--radius);
    background: var(--surface); border: 1px solid var(--hairline); box-shadow: var(--shadow-sm);
    color: var(--text-2); font-size: .95rem; line-height: 1.55; max-width: 72ch; }
.dash-groet p { margin: 0; }
.dash-groet p + p { margin-top: .55rem; }
.dash-groet a { color: var(--primary); }
.dash-sectie { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: var(--muted); margin: 1.5rem 0 .6rem; }
.dash-leeg { margin: 1.2rem 0 0; color: var(--muted); font-size: .92rem; }

.attn { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); grid-auto-rows: 1fr; gap: .75rem; }
.attn-card { position: relative; display: flex; align-items: center; gap: .8rem; padding: .85rem 1rem; overflow: hidden;
    background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--radius);
    box-shadow: var(--shadow-sm); color: var(--text); text-decoration: none; transition: transform .14s ease, box-shadow .18s ease; }
.attn-card::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--danger); }
a.attn-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); text-decoration: none; }
.attn-ic { width: 36px; height: 36px; flex: none; border-radius: 10px; display: grid; place-items: center; background: var(--danger-soft); color: var(--danger); }
.attn-ic svg { width: 18px; height: 18px; }
.attn-tekst b { display: block; font-size: 1.1rem; letter-spacing: -.01em; }
.attn-tekst small { color: var(--text-2); font-size: .82rem; }
.attn-go { margin-left: auto; color: var(--muted); }
.attn-go svg { width: 18px; height: 18px; }

.dash-quick { display: grid; grid-template-columns: repeat(auto-fill, minmax(165px, 1fr)); grid-auto-rows: 1fr; gap: .6rem; }
.dash-tile { display: flex; align-items: center; padding: .72rem .95rem; border-radius: var(--radius);
    background: var(--surface); border: 1px solid var(--hairline); box-shadow: var(--shadow-sm);
    color: var(--text); text-decoration: none; font-size: .88rem; font-weight: 550; transition: transform .14s ease, box-shadow .18s ease; }
.dash-tile:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); text-decoration: none; }

/* Donker: dezelfde matglas-behandeling als de andere kaarten. */
:root[data-theme="dark"] .attn-card,
:root[data-theme="dark"] .dash-tile,
:root[data-theme="dark"] .dash-groet,
:root[data-theme="dark"] .dash-inrichten {
    background-color: rgba(16, 30, 54, .46);
    background-image: linear-gradient(180deg, rgba(255, 255, 255, .06), rgba(255, 255, 255, .012));
    -webkit-backdrop-filter: blur(22px) saturate(1.45);
    backdrop-filter: blur(22px) saturate(1.45);
    border-color: rgba(255, 255, 255, .12);
}

/* ── Dashboard-achtergrond: de arctic-foto áchter de content ────────────────
   Dezelfde foto als de login, zodat het matglas iets heeft om doorheen te vervagen.
   Een vaste (fixed) laag áchter de content; zijbalk + bovenbalk liggen erboven, dus de
   foto toont alleen in het contentgebied en scrollt niet mee (rustig parallax-effect). */
/* De foto zit ACHTER álles (body::before, z-index:-1) — ook achter de zijbalk, zodat
   het matglas de foto laat doorschemeren (zijbalk in donker + de kaarten). Een vaste
   laag over het hele venster: de solide vlakken dekken 'm af, de glazen tonen 'm. Omdat
   hij op de body zit (niet in .content) raakt hij de zijbalk niet kwijt. */
body.heeft-dash-foto::before {
    content: ""; position: fixed; top: 0; right: 0; bottom: 0; left: 248px; z-index: -1; pointer-events: none;
    background-image: var(--dash-overlay), var(--dash-photo);
    background-size: cover; background-position: center;
}
/* De foto hoort alleen áchter de inhoud, niet achter de zijbalk (248px, ingeklapt 66px):
   zo blijft de zijbalk overal het standaard-ontwerp. In donker toont het zijbalk-matglas
   dan de arctic-gloed i.p.v. de foto, net als op elke andere adminpagina. */
body.heeft-dash-foto:has(.sidebar.is-ingeklapt)::before { left: 66px; }
/* Licht: de foto zacht oplichten zodat donkere tekst tussen de kaarten leesbaar blijft. */
body.heeft-dash-foto { --dash-overlay: linear-gradient(rgba(232, 242, 252, .55), rgba(220, 235, 250, .68)); }
:root[data-theme="dark"] body.heeft-dash-foto { --dash-overlay: linear-gradient(rgba(7, 20, 38, .5), rgba(8, 18, 34, .82)); }

/* Zijbalk + bovenbalk blijven óók op het dashboard het standaard-ontwerp (Calvins wens:
   de nav aan de zijkant overal gelijk). Het glas-effect zit op de KAARTEN over de foto,
   niet op de nav-chrome zelf. In donker zijn zijbalk/bovenbalk sowieso al het globale
   matglas; de foto hierboven is weggehouden van de zijbalk, dus die toont de arctic-gloed. */

/* De kaarten worden matglas óver de foto. Donker gebruikt de bestaande donker-glas-regels
   hierboven; licht krijgt wit matglas — alleen op het dashboard (.dash), zodat andere
   lichte pagina's clean/solide blijven. */
:root[data-theme="light"] .dash .attn-card,
:root[data-theme="light"] .dash .stat,
:root[data-theme="light"] .dash .dash-tile,
:root[data-theme="light"] .dash .dash-inrichten,
:root[data-theme="light"] .dash .dash-groet {
    background-color: rgba(255, 255, 255, .6);
    -webkit-backdrop-filter: blur(20px) saturate(1.4); backdrop-filter: blur(20px) saturate(1.4);
    border-color: rgba(255, 255, 255, .72);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95), 0 16px 34px -22px rgba(12, 24, 45, .28);
}
:root[data-theme="light"] .dash .panel {
    background-color: rgba(255, 255, 255, .76);
    -webkit-backdrop-filter: blur(20px) saturate(1.4); backdrop-filter: blur(20px) saturate(1.4);
    border-color: rgba(255, 255, 255, .72);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .95), 0 16px 34px -22px rgba(12, 24, 45, .28);
}

/* ==========================================================================
   Mobiele schil en aanraakbediening (telefoon/tablet, iPhone voorop)
   Regels: docs/ui-regels.md. Grenzen: telefoon ≤640px, tablet ≤1024px.
   Bewust ONDERAAN dit bestand, zodat deze regels winnen van de desktopregels hierboven
   (zoals de dashboardfoto die op desktop pas rechts van de zijbalk begint).
   ========================================================================== */

/* Laadbalk van de snelle navigatie (arctic.js): een dun streepje bovenaan zolang een pagina
   onderweg is. Verschijnt pas na een korte pauze, dus niet bij een snelle wissel. */
.arctic-laadbalk {
    position: fixed; top: 0; left: 0; z-index: 9990; height: 3px; width: 0;
    background: var(--primary); opacity: 0; pointer-events: none;
    transition: width 8s cubic-bezier(.1, .7, .2, 1), opacity .2s ease;
}
.arctic-laadbalk.is-bezig { width: 85%; opacity: 1; }
.arctic-laadbalk.is-klaar { width: 100%; opacity: 0; transition: width .18s ease, opacity .3s ease .15s; }
@media (prefers-reduced-motion: reduce) { .arctic-laadbalk { transition: opacity .2s ease; } }
/* Na een wissel krijgt de kop van de nieuwe pagina de focus (voor schermlezers); geen rand
   eromheen, want het is geen bedieningselement. */
.app-inhoud [tabindex="-1"]:focus { outline: none; }

/* Onderdelen die alleen in het uitschuifmenu horen; op desktop zijn ze er niet. */
.menu-knop, .sidebar__sluit, .topsearch--menu, .sidebar__account, .menu-scrim, .rep-menuknop { display: none; }

/* iOS maakt tekst in liggende stand anders zelf groter. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

@media (max-width: 1024px) {
    /* ── De zijbalk wordt een uitschuifmenu achter de menuknop (arctic.js: data-menu-*) ── */
    .layout { display: block; }
    .main { margin-left: 0; }
    .sidebar {
        z-index: 70; width: min(86vw, 320px);
        padding-top: max(.8rem, env(safe-area-inset-top, 0px));
        padding-bottom: max(.9rem, env(safe-area-inset-bottom, 0px));
        transform: translateX(-102%); visibility: hidden;
        transition: transform .24s cubic-bezier(.22, .61, .36, 1), visibility 0s linear .24s;
    }
    body.menu-open .sidebar {
        transform: none; visibility: visible;
        transition: transform .24s cubic-bezier(.22, .61, .36, 1), visibility 0s;
        box-shadow: 18px 0 40px rgba(0, 0, 0, .28);
    }
    .menu-scrim {
        display: block; position: fixed; inset: 0; z-index: 69;
        background: rgba(10, 22, 42, .45); opacity: 0; pointer-events: none; transition: opacity .2s ease;
    }
    body.menu-open .menu-scrim { opacity: 1; pointer-events: auto; }
    /* Zelfde regel als bij popups: met het menu open staat de pagina erachter stil. */
    html:has(body.menu-open) { overflow: hidden; }
    /* Inklappen is een desktopkeuze. */
    .sidebar-toggle { display: none; }

    .menu-knop {
        display: inline-grid; place-items: center; flex: none;
        width: 44px; height: 44px; margin-left: -.55rem;
        border: 0; border-radius: var(--radius-sm); background: none; color: var(--text); cursor: pointer;
    }
    .menu-knop:hover { background: var(--surface-2); }

    .brand { padding-right: 3.2rem; }
    .sidebar__sluit {
        display: grid; place-items: center; position: absolute; right: .55rem;
        top: max(.6rem, env(safe-area-inset-top, 0px));
        width: 44px; height: 44px; border: 0; border-radius: var(--radius-sm);
        background: rgba(255, 255, 255, .07); color: #fff; cursor: pointer;
    }
    .topsearch--menu { display: block; flex: none; margin: 0 0 .8rem; }
    .topsearch--menu .topsearch__input {
        width: 100%; background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .14); color: #fff;
    }
    .topsearch--menu .topsearch__input::placeholder { color: rgba(255, 255, 255, .55); }
    .topbar > .topsearch { display: none; }

    /* Menu-items op duimformaat. */
    .nav__item { min-height: 44px; font-size: .97rem; }
    .nav__group { min-height: 40px; }

    .sidebar__account {
        display: flex; flex-direction: column; gap: .5rem;
        margin-top: auto; padding-top: .9rem; border-top: 1px solid rgba(255, 255, 255, .1);
    }
    .sidebar__profiel {
        display: flex; align-items: center; gap: .65rem; min-height: 44px; padding: .2rem .55rem;
        border-radius: var(--radius-sm); color: #fff; font-weight: 550; text-decoration: none;
    }
    .sidebar__profiel:hover { background: rgba(255, 255, 255, .06); text-decoration: none; }
    .sidebar__account-acties { display: flex; gap: .5rem; }
    .sidebar__account-acties .thema-knop,
    .sidebar__account-acties .uitlog-form .btn-link {
        flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
        width: auto; height: 44px; padding: 0 .9rem; border-radius: var(--radius-sm);
        border: 1px solid rgba(255, 255, 255, .14); background: rgba(255, 255, 255, .07);
        color: #fff; font: inherit; font-size: .92rem; font-weight: 550; text-decoration: none;
    }
    .sidebar__account-acties .uitlog-form { display: flex; flex: 1; }

    /* ── De bovenbalk: alleen wat je onderweg nodig hebt ── */
    .topbar {
        gap: .5rem; padding: .35rem .9rem;
        padding-top: max(.35rem, env(safe-area-inset-top, 0px));
    }
    .topbar .page-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 1rem; }
    .user-menu { gap: .35rem; flex: 0 0 auto; }
    /* Thema en uitloggen staan in het menu; de naam naast je foto vervalt. */
    .user-menu > .thema-knop, .user-menu > .uitlog-form, .user-menu .user-name { display: none; }
    .profiel-knop { padding: .2rem; }

    /* Geen zijbalk links: de dashboardfoto begint aan de rand. */
    body.heeft-dash-foto::before, body.heeft-dash-foto:has(.sidebar.is-ingeklapt)::before { left: 0; }

    /* Instellingen: het menu links wordt een uitklapknop boven de inhoud. */
    .settings { grid-template-columns: minmax(0, 1fr); }
    .settings__nav { position: static; padding: .35rem; }
    .settings__nav-title { display: none; }
    .settings__nav .settings__menuknop { display: flex; }
    .settings__nav:not(.is-open) .settings__group { display: none; }
    .settings__link { padding: .7rem .8rem; }
}

/* De uitklapknop van het Instellingen-menu bestaat alleen op telefoon/tablet. */
.settings__menuknop {
    display: none; width: 100%; min-height: 48px; align-items: center; justify-content: space-between; gap: .75rem;
    padding: .5rem .8rem; border: 0; border-radius: var(--radius-sm); background: none;
    font: inherit; font-weight: 600; color: var(--text); cursor: pointer; text-align: left;
}
.settings__menuknop small { display: block; font-size: .72rem; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.settings__menuknop svg { flex: none; transition: transform .15s ease; }
.settings__nav.is-open .settings__menuknop svg { transform: rotate(180deg); }
.settings__nav.is-open .settings__menuknop { margin-bottom: .4rem; border-bottom: 1px solid var(--hairline); border-radius: var(--radius-sm) var(--radius-sm) 0 0; }

/* Filterbalk die op de telefoon inklapt tot zoekveld + "Filters"-knop (arctic.js voegt de
   knop toe aan <form class="toolbar" data-inklapbaar>). Zonder JavaScript blijft alles staan. */
.toolbar__filterknop { display: none; }

@media (max-width: 640px) {
    /* Paginakop met drie of meer knoppen: de knoppen op één eigen rij onder de titel. */
    .page-head > .row-actions:has(> :nth-child(3)) { width: 100%; gap: .5rem; }
    .page-head > .row-actions:has(> :nth-child(3)) > .btn { flex: 1 1 auto; padding-left: .6rem; padding-right: .6rem; }

    /* ── Lijsten en filters ── (kaartvorm van lijsten: zie "Lijst als kaarten" hoger) */
    .toolbar > input[type=search] { flex: 1 1 100%; max-width: none; }
    .toolbar > select, .toolbar > .picker { flex: 1 1 calc(50% - .6rem); min-width: 0; }
    .toolbar[data-inklapbaar] > input[type=search] { flex: 1 1 0; }
    .toolbar[data-inklapbaar] .toolbar__filterknop { display: inline-flex; align-items: center; gap: .4rem; flex: none; }
    .toolbar[data-inklapbaar]:not(.is-open) > :not(input[type=search]):not(.toolbar__filterknop):not([type=hidden]) { display: none; }
    .toolbar[data-inklapbaar].is-open .toolbar__groep { flex-wrap: wrap; }

    /* Tabstrips (producten, rapportages): één rij die zijwaarts schuift i.p.v. de pagina te verbreden. */
    .settings-nav { overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none; }
    .settings-nav::-webkit-scrollbar { display: none; }
    .settings-nav a { white-space: nowrap; flex: none; }

    /* ── Popups: op de telefoon het hele scherm (regel 6 in docs/ui-regels.md) ── */
    /* Het venster is een .popup--record (schermvullend, zie hieronder); alleen zijn inhoud en
       de zwevende sluitknop hebben eigen maten. */
    .venster__inhoud { padding: 1rem 1rem calc(1.5rem + env(safe-area-inset-bottom, 0px)); }
    .venster__sluit { top: max(.45rem, env(safe-area-inset-top, 0px)); right: .45rem; }
    .modal, .modal[open] {
        width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh;
        border: 0; border-radius: 0; padding: max(1.1rem, env(safe-area-inset-top, 0px)) 1rem 0;
    }
    .modal__close { width: 44px; height: 44px; }
    /* De knoppen blijven onderin in beeld, binnen bereik van je duim. */
    .modal .form-actions {
        position: sticky; bottom: 0; z-index: 2;
        margin: 1.2rem -1rem 0; padding: .75rem 1rem calc(.75rem + env(safe-area-inset-bottom, 0px));
        background: var(--surface); border-top: 1px solid var(--hairline);
    }
    .modal .form-actions .btn { flex: 1 1 0; justify-content: center; }

    /* Het popup-sjabloon: formulier en record schermvullend, een vraag als onderblad; de
       knoppen staan altijd onderin, binnen bereik van je duim. */
    .popup--formulier, .popup--record {
        width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh;
        border: 0; border-radius: 0;
    }
    .popup--formulier .popup__kop, .popup--record .popup__kop { padding-top: max(.8rem, env(safe-area-inset-top, 0px)); }
    .popup__inhoud { padding: 1rem; }
    .popup__voet { padding: .75rem 1rem calc(.75rem + env(safe-area-inset-bottom, 0px)); }
    .popup__voet > .btn { flex: 1 1 0; }
    .popup--bevestigen {
        inset: auto 0 0 0; margin: 0; width: 100vw; max-width: 100vw;
        border: 0; border-radius: 16px 16px 0 0;
    }
    .popup--bevestigen .popup__inhoud { padding: 1.4rem 1.1rem 1rem; }
    .popup--bevestigen[open] { animation-name: popup-onderblad; }

    /* Een uitklapmenu als onderblad, met een donkere laag erachter (een tik daarop sluit hem). */
    .menu[open]::before {
        content: ""; position: fixed; inset: 0; z-index: 75; background: rgba(10, 22, 42, .35);
    }
    .menu[open] > .menu__paneel {
        position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 76; min-width: 0;
        padding: .5rem .5rem calc(.75rem + env(safe-area-inset-bottom, 0px));
        border: 0; border-radius: 16px 16px 0 0;
        max-height: 70dvh; overflow-y: auto;
    }
    .menu__paneel a, .menu__paneel button { padding: .85rem 1rem; font-size: 1rem; white-space: normal; }

    /* ── Borden (taken, deals, projecten): één kolom per schermbreedte, vegen naar de volgende ── */
    .bord {
        scroll-snap-type: x mandatory; scroll-padding-left: var(--pagina-rand);
        margin-left: calc(-1 * var(--pagina-rand)); margin-right: calc(-1 * var(--pagina-rand));
        padding-left: var(--pagina-rand); padding-right: var(--pagina-rand);
    }
    .bord__kolom { flex-basis: min(84vw, 340px); scroll-snap-align: start; }
}

/* ── Aanraakschermen: duimformaat en geen inzoomende velden (body.app = adminschil) ── */
@media (pointer: coarse) {
    /* iOS zoomt in zodra je een veld aantikt met tekst kleiner dan 16px. */
    body.app input[type=text], body.app input[type=email], body.app input[type=password],
    body.app input[type=number], body.app input[type=date], body.app input[type=datetime-local],
    body.app input[type=time], body.app input[type=search], body.app input[type=tel],
    body.app input[type=url], body.app select, body.app textarea { font-size: 16px; }
    /* Knoppen minstens 44px hoog: zo groot als een vingertop (Apple-richtlijn). */
    body.app .btn { min-height: 44px; }
    body.app .lijst-pager__knop { min-height: 44px; min-width: 44px; display: inline-flex; align-items: center; justify-content: center; }
    body.app .lijst-pager__grootte select { min-height: 44px; }
    body.app .check { min-height: 44px; margin: .3rem 0; }
    body.app .check input[type=checkbox], body.app .check input[type=radio],
    body.app .toolbar input[type=checkbox], body.app td > input[type=checkbox],
    body.app th > input[type=checkbox] { width: 22px; height: 22px; }
    /* Tekstlinks die als knop dienen (Bewerken, Verwijderen, Wissen, + Nieuwe klant) krijgen een
       groter raakvlak; alleen niet midden in een lopende zin. */
    body.app .btn-link:not(p .btn-link) {
        display: inline-flex; align-items: center; min-height: 44px; padding-left: .35rem; padding-right: .35rem;
    }
    body.app .thema-knop, body.app .uren-knop, body.app .melding__knop { width: 40px; height: 40px; }
    .popup__sluit { width: 44px; height: 44px; font-size: 1.4rem; }
    body.app .page-head__terug { width: 44px; height: 44px; }
    body.app .paneel__vol { display: inline-flex; align-items: center; min-height: 44px; padding: 0 .4rem; }
    body.app .settings-nav a { padding-top: .75rem; padding-bottom: .75rem; }
    /* De pijlknoppen en "Afronden"/"Gewonnen" op de borden. */
    body.app .bord-stap { min-width: 44px; min-height: 40px; font-size: .95rem; }
    body.app .bord-kaart__acties .btn-link { display: inline-flex; align-items: center; min-height: 40px; padding: 0 .5rem; }
    body.app a, body.app button, body.app summary, body.app label, body.app select { touch-action: manipulation; }
}

/* ── Een bestand ergens op slepen ──────────────────────────────────────────────────────
   venster.js zet .is-sleepdoel op een [data-sleepzone] (en op een uploadformulier) zolang er een
   bestand boven hangt: een gestippelde azuurblauwe rand met een zachte vulling. Eén regel voor
   alle modules (bijlagen van een taak, documenten van een project, …). */
.is-sleepdoel {
    outline: 2px dashed var(--primary); outline-offset: 4px;
    border-radius: var(--radius-sm); background: var(--primary-soft);
}

/* ── Hulpklassen (achteraan, zodat ze winnen van een gewone onderdeelregel) ───────────
   Voor de kleine afwijking die geen eigen onderdeel waard is, in plaats van style="…". */
.m-0 { margin: 0; }
.mt-s { margin-top: .6rem; }
.mt-m { margin-top: 1rem; }
.mb-s { margin-bottom: .8rem; }
.mb-m { margin-bottom: 1rem; }
.rij { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.rij--ruim { gap: 1rem; }
/* Formulierhulpjes. Staan met dezelfde naam ook in pos.css, want een pagina als "Bon corrigeren"
   draait zowel in de adminschil (app.css) als in de kassa-beheerschil (pos.css). */
.veld-smal { max-width: 5rem; }
.veld-bedrag { max-width: 7rem; }
.veld-rechts { text-align: right; }
.uitleg-smal { max-width: 60ch; }
.uitleg-blok { display: block; margin-top: .4rem; }
/* Een kaart die aandacht vraagt (bijv. storno's op het dashboard). */
.panel--let-op { border-color: var(--danger); border-left: 4px solid var(--danger); background: var(--danger-soft); }
.panel--let-op > .page-head h2 { color: var(--danger); }

/* ══ Werkplek-schil: paneel ══════════════════════════════════════════════════════════
   De balie-schillen (layouts/werkplek.twig en de reparatie-schil) laden ook app.css
   (feedback 74ccb1d2 en 15eeae74).
   - Het detailpaneel (paneel.js) begint daar op breed scherm onder de vaste bovenbalk, zodat
     schermwisselaar, klok en Uitloggen bereikbaar blijven; de inhoud (.rep-main) schuift ernaast,
     zoals .main in de adminschil; de kopbalk van het ticket (.rep-bar) ook, zodat de knoppen
     daarin niet onder het paneel verdwijnen. Smaller ligt het paneel als overlay over alles heen.
   - .schil-inhoud (het inhoudsvak van de snelle navigatie) en .schil-vervang (een stuk van de
     balk dat per scherm wisselt) zijn alleen haakjes voor arctic.js: ze tekenen zelf geen vak,
     zodat de opmaak van de schil precies blijft zoals hij was.
   - Het submenu markeert het huidige scherm (aria-current), net als de kassabalk (pos.css).
   - Uitloggen staat rechtsboven naast de naam (partials/_schil-gebruiker.twig). */
.schil-inhoud, .schil-vervang { display: contents; }
/* De gutter van de balie-schil: .rep-main heeft op een smal scherm .8rem zijmarge (repairs.css,
   max-width 860px). Stroken die tot de rand lopen (tabs op de klantpagina) volgen die via
   --pagina-rand, anders schoof de pagina op 375px 3px zijwaarts. */
@media (max-width: 860px) {
    .rep-main { --pagina-rand: .8rem; }
}
.schil-inhoud [tabindex="-1"]:focus { outline: none; }
/* De schermwisselaar in de balk (partials/_surface-switch.twig): het actieve scherm is een gevulde
   azuurblauwe knop (aria-current), de rest rustig. Staat hetzelfde in pos.css, want de kassa laadt
   geen app.css. */
.surface-switch { display: flex; gap: .2rem; align-items: center; flex-wrap: wrap; }
.surface-switch__item {
    padding: .4rem .8rem; border-radius: 8px; text-decoration: none;
    font-size: .9rem; font-weight: 600; white-space: nowrap; color: inherit; opacity: .78;
}
.surface-switch__item:hover { opacity: 1; }
.surface-switch__item[aria-current="page"] { background: var(--primary); color: #fff; opacity: 1; }
.surface-switch__item:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.rep-topnav a[aria-current="page"] { color: var(--primary); font-weight: 700; }
.rep-user .uitlog-form { margin-left: .75rem; }
@media (min-width: 1280px) {
    body.rep-body .paneel { top: var(--schil-balk-hoogte, var(--rep-topbar-h, 5rem)); }
    body.rep-body.has-paneel .rep-main,
    body.rep-body.has-paneel .rep-bar { margin-right: var(--paneel-breedte); }
    /* .rep-main heeft een vaste breedte (width: 100%, max-width in repairs.css): alleen een
       marge zou hem rechts onder het paneel laten doorlopen. Dus ook smaller maken. */
    body.rep-body.has-paneel .rep-main { width: calc(100% - var(--paneel-breedte)); }
}
