/* ==========================================================================
   ProPrisma global styles
   Loaded on every page. Tenant colours override --brand-* via /huisstijl.css.
   Conventions (CODESTYLE.md): radius 5px, transitions 0.3s ease, rem for spacing.

   Themes: <html data-theme="light|dark|system">. Colours are only defined as
   tokens below; use var(--...) everywhere so both themes keep working.
   ========================================================================== */

:root {
    color-scheme: light;
    --brand-primary: #1f5fae;
    --brand-secondary: #3fa9a0;
    --accent: #f2a93b;

    --text: #1b2a41;
    --text-muted: #5b6b80;
    --bg: #f4f6f9;
    /* Hoeveel merkkleur er in het verloop bovenaan de pagina zit (zie .main). Op een
       lichte pagina valt een tint eerder op dan op een donkere, dus daar mag minder. */
    --tint-strength: 11%;
    /* Hoe een patroon met zijn ondergrond mengt. Op wit doet soft-light bijna niets -
       daar moet de tekening juist donkerder maken, anders is hij onzichtbaar. */
    --pattern-blend: multiply;
    --pattern-opacity: 0.25;
    --surface: #ffffff;
    --border: #d9dfe7;
    /* De zijbalk volgt het thema: licht bij licht, donker bij donker */
    --sidebar-bg: #ffffff;
    --sidebar-text: #41506a;
    --sidebar-strong: #1b2a41;
    --sidebar-hover: rgba(27, 42, 65, 0.07);
    --sidebar-border: #d9dfe7;

    --success-bg: #e7f6ee;
    --success-text: #1d6b43;
    --warning-bg: #fff4e0;
    --warning-text: #8a5300;
    --error-bg: #fdecec;
    --error-text: #a12b2b;
    --info-bg: #e8f1fb;
    --info-text: #1f4f86;
    --danger-border: #efc2c2;
    /* Logos are made for a light background, in both themes */
    --logo-bg: #ffffff;
    /* Het rood uit het beeldmerk. Staat niet in de donkere blokken: een merkkleur
       hoort in beide weergaven dezelfde te zijn. */
    --brand-mark-red: #e4043a;

    --radius: 5px;
    --transition: 0.3s ease;
    --shadow: 0 1px 2px rgba(27, 42, 65, 0.06), 0 2px 8px rgba(27, 42, 65, 0.06);
    /* Barlow staat in assets/css/fonts.css en komt van onze eigen server. De rest is
       het vangnet: zolang Barlow nog laadt, en als hij ooit niet laadt. */
    --font: 'Barlow', system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

:root[data-theme="dark"] {
    color-scheme: dark;
    --text: #e4e9f0;
    --text-muted: #9aa8ba;
    --bg: #0f1722;
    --tint-strength: 16%;
    --pattern-blend: soft-light;
    --pattern-opacity: 0.4;
    --surface: #182231;
    --border: #2b3a4e;
    --sidebar-bg: #0b121c;
    --sidebar-text: #c7d2e0;
    --sidebar-strong: #ffffff;
    --sidebar-hover: rgba(255, 255, 255, 0.1);
    --sidebar-border: rgba(255, 255, 255, 0.12);

    --success-bg: #12301f;
    --success-text: #7fd3a3;
    --warning-bg: #34280f;
    --warning-text: #f2c46b;
    --error-bg: #3a1a1a;
    --error-text: #f09a9a;
    --info-bg: #13263d;
    --info-text: #8fbdf0;
    --danger-border: #6b2c2c;

    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 2px 8px rgba(0, 0, 0, 0.3);
}

@media (prefers-color-scheme: dark) {
    :root[data-theme="system"] {
        color-scheme: dark;
        --text: #e4e9f0;
        --text-muted: #9aa8ba;
        --bg: #0f1722;
        --tint-strength: 16%;
        --pattern-blend: soft-light;
        --pattern-opacity: 0.4;
        --surface: #182231;
        --border: #2b3a4e;
        --sidebar-bg: #0b121c;
        --sidebar-text: #c7d2e0;
        --sidebar-strong: #ffffff;
        --sidebar-hover: rgba(255, 255, 255, 0.1);
        --sidebar-border: rgba(255, 255, 255, 0.12);

        --success-bg: #12301f;
        --success-text: #7fd3a3;
        --warning-bg: #34280f;
        --warning-text: #f2c46b;
        --error-bg: #3a1a1a;
        --error-text: #f09a9a;
        --info-bg: #13263d;
        --info-text: #8fbdf0;
        --danger-border: #6b2c2c;

        --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 2px 8px rgba(0, 0, 0, 0.3);
    }
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    font-size: 16px;
}

body {
    margin: 0;
    font-family: var(--font);
    line-height: 1.5;
    color: var(--text);
    background: var(--bg);
}

h1, h2, h3, h4 {
    line-height: 1.25;
    margin: 0 0 0.75rem;
}

h1 { font-size: 1.6rem; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1.05rem; }
h4 { font-size: 0.95rem; }

p {
    margin: 0 0 1rem;
}

/* Een streep onder elke link is hier teveel: de meeste links staan in lijsten en tabellen,
   naast een avatar of een icoon, en dan loopt er een streep door het hele rijtje. De kleur
   doet het werk; de streep komt terug zodra je erover gaat of er met het toetsenbord op
   staat, zodat het nog steeds te zien is dat het een link is.

   Wat wél onderstreept blijft: een link midden in een lopende tekst (zie hieronder), want
   daar is kleur alleen te weinig verschil met de zin eromheen. */
a {
    color: var(--brand-primary);
    text-decoration: none;
    transition: color var(--transition);
}

a:hover {
    color: var(--text);
}

/* Een link in een alinea of in een opsomming van lopende tekst: daar hoort de streep
   wel, want hij staat tussen gewone woorden en kleur alleen is te weinig verschil.
   Niet in een tabel, een tegel of een lijst - die hebben hun eigen vorm, en een streep
   die bij het aanwijzen onder een heel blok verschijnt leest als een fout.

   Ook niet bij `:hover` voor de rest: dat stond hier even, en dan kreeg elke tegel en
   elk kaartje een streep zodra je erlangs ging. */
.card > p a,
.section > p a,
.help-body a,
.notice a,
.muted a,
.section-note a,
.plain-card a {
    text-decoration: underline;
}

/* Zichtbaar waar je bent met het toetsenbord, ook bij een link zonder streep */
a:focus-visible {
    outline: 2px solid var(--brand-primary);
    outline-offset: 2px;
    border-radius: 2px;
}

code {
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 0.9em;
    background: var(--bg);
    padding: 0.1rem 0.3rem;
    border-radius: var(--radius);
}

[hidden] {
    display: none !important;
}

.muted { color: var(--text-muted); }
.lead { font-size: 1.05rem; color: var(--text-muted); max-width: 48rem; }

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.skip-link {
    position: absolute;
    left: -999px;
    top: 0.5rem;
    background: var(--surface);
    padding: 0.5rem 1rem;
    border-radius: var(--radius);
    z-index: 100;
}

.skip-link:focus {
    left: 0.5rem;
}

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

/* --- Layout ------------------------------------------------------------- */

.layout {
    display: grid;
    grid-template-columns: 15rem 1fr;
    min-height: 100vh;
}

.sidebar {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    padding: 1.25rem 0.75rem;
    background: var(--sidebar-bg);
    color: var(--sidebar-text);
    border-right: 1px solid var(--sidebar-border);
    /* Het menu blijft staan, alleen de inhoud schuift: met veel modules moeten
       het gebruikersblok en Uitloggen bereikbaar blijven */
    position: sticky;
    top: 0;
    max-height: 100vh;
}

.sidebar nav {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    /* Smalle schuifbalk die niet opvalt */
    scrollbar-width: thin;
}

.sidebar-brand {
    padding: 0.75rem;
    background: var(--logo-bg);
    border-radius: var(--radius);
    text-align: center;
}

.sidebar-brand img {
    display: block;
    max-width: 100%;
    max-height: 3rem;
    margin: 0 auto;
}

.sidebar-brand .tag {
    margin-top: 0.5rem;
}

.module-icon {
    flex: none;
    object-fit: contain;
}

.module-icon-sm {
    width: 1.35rem;
    height: 1.35rem;
    /* De iconen zijn kleurrijk; op de donkere zijbalk mogen ze iets rustiger */
    filter: saturate(0.9);
}

.module-icon-lg {
    width: 2.75rem;
    height: 2.75rem;
    vertical-align: middle;
}

.nav-heading {
    margin: 1.25rem 0 0.35rem;
    padding: 0 0.9rem;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--sidebar-muted, var(--text-muted));
}

.nav-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.25rem;
}

.nav-list a,
.nav-button,
.sidebar-user-link {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    padding: 0.6rem 0.75rem;
    border: 0;
    border-radius: var(--radius);
    background: transparent;
    color: var(--sidebar-text);
    font: inherit;
    font-size: var(--text-ui);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}

.nav-list a:hover,
.nav-button:hover,
.sidebar-user-link:hover,
.nav-list a.is-active,
.sidebar-user-link.is-active {
    background: var(--sidebar-hover);
    color: var(--sidebar-strong);
}

.nav-list a.is-active {
    box-shadow: inset 3px 0 0 var(--brand-secondary);
}

.nav-list i,
.nav-button i,
.sidebar-user-link i {
    width: 1.25rem;
    text-align: center;
}

/* Bij een getal van een cijfer hoort dit een rondje te zijn. Dat lukt alleen als de
   hoogte net zo groot is als de kleinste breedte en de tekst gecentreerd staat; met
   alleen een text-align en een regelhoogte wordt het altijd net een ovaal. Bij twee of
   drie cijfers groeit hij mee en wordt het vanzelf een pil. */
.nav-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    margin-left: auto;
    min-width: 1.35rem;
    height: 1.35rem;
    padding: 0 0.35rem;
    border-radius: 999px;
    background: var(--accent);
    color: #1b2a41;
    font-size: 0.75rem;
    font-weight: 700;
    line-height: 1;
}

/* Credits en Configuratie: onder de schuivende lijst, dus altijd in beeld.
   margin-top: auto duwt ze naar de onderkant. Dat is nodig zodra er niets is dat de
   ruimte opvult - op een modulepagina is het menu ingeklapt, en dan zweefden ze
   halverwege in plaats van onderin te staan waar je ze zoekt. */
.nav-bottom {
    flex: none;
    margin-top: auto;
    padding-top: 0.75rem;
    border-top: 1px solid var(--sidebar-border);
}

/* De balk heeft witte tekst op de merkkleur, en die erft een keuzelijst - met een witte
   achtergrond eronder is dat wit op wit. De omgebouwde lijsten hadden hem al goed; de
   gewone <select> (bij minder keuzes bouwt select.js hem niet om) niet. */
.bulk-bar select,
.bulk-bar .pp-select-button {
    color: var(--text);
}

/* Een keuzelijst in de balk blijft binnen de perken: een lijst met lange segmentatienamen
   duwde de balk anders over de halve breedte van het scherm. */
.bulk-bar select,
.bulk-bar input[type="text"],
.bulk-bar input[type="file"],
.bulk-bar .pp-select {
    max-width: 16rem;
}

.bulk-bar input[type="file"] {
    color: #fff;
    font-size: 0.85rem;
}

/* De knop even hoog als de lijsten ernaast: dezelfde padding, en uitrekken in de balk */
.bulk-bar .btn {
    align-self: stretch;
    padding-top: 0.55rem;
    padding-bottom: 0.55rem;
}

.sidebar-user {
    margin-top: auto;
    border-top: 1px solid var(--sidebar-border);
    padding-top: 1rem;
}

.sidebar-user-link span {
    display: grid;
    line-height: 1.3;
}

.sidebar-user-link small {
    color: var(--sidebar-text);
    opacity: 0.75;
}

.sidebar-user form {
    margin: 0;
}

.sidebar-user-actions {
    display: flex;
    gap: 0.25rem;
}

.sidebar-user-actions form:first-child {
    flex: 1;
}

.theme-toggle {
    width: auto;
}

.theme-choice {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.form .theme-choice label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem 0.9rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-weight: 400;
    cursor: pointer;
}

.inline-form {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin: 0;
}

.input-schedule {
    width: 9rem;
}

code.block-code {
    display: block;
    margin-top: 0.5rem;
    padding: 0.5rem 0.75rem;
    user-select: all;
    word-break: break-all;
}

.main {
    /* Onderaan ruimte voor de vaste footerbalk, zodat er niets achter valt */
    padding: 2rem 2.5rem 5.5rem;
    min-width: 0;

    /* Een heel licht verloop bovenaan de pagina, in de kleuren van de tenant. Het staat
       er om diepte te geven aan wat anders een egaal grijs vlak is - niet om op te
       vallen; merk je het bewust op, dan is het te sterk.

       Twee lagen over elkaar: onderop het verloop van links naar rechts, daar bovenop
       een verloop naar de paginakleur dat het naar beneden toe laat oplossen. Zo is er
       geen harde rand waar het ophoudt. De kleuren komen uit de huisstijltokens, dus
       elke tenant krijgt vanzelf zijn eigen verloop. */
    background-image:
        linear-gradient(180deg, transparent 0%, var(--bg) 100%),
        linear-gradient(100deg,
            color-mix(in srgb, var(--brand-primary) var(--tint-strength), transparent) 0%,
            color-mix(in srgb, var(--accent) calc(var(--tint-strength) * 0.55), transparent) 48%,
            color-mix(in srgb, var(--brand-secondary) var(--tint-strength), transparent) 100%);
    background-repeat: no-repeat;
    background-size: 100% 22rem;
    /* Vast ten opzichte van het scherm: het verloop schuift niet mee als je scrollt,
       dus de inhoud beweegt eroverheen in plaats van ermee mee. Dat geeft diepte zonder
       dat er iets beweegt wat de aandacht pakt. */
    background-attachment: fixed;
}

.page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem 1rem;
    margin-bottom: 1.25rem;
}

/* Het icoon vóór de titel op de echte hoogte van de regel zetten. Met vertical-align
   hangt het aan de x-hoogte van de letter, en dan staat een vierkant plaatje net iets te
   hoog boven een kop met stokletters. Een flexregel legt ze wél op één as. */
.page-header h1 {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0;
    min-width: 0;
}

.page-header h1 .module-icon,
.page-header h1 > i {
    flex: none;
}

/* Knoppen die over de hele pagina gaan, rechts naast de titel */
.page-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: 0.4rem;
    margin-left: auto;
}

/* De drie puntjes zijn hier geen klein knopje in een tabelrij maar een knop naast de
   hoofdknop: even hoog, even hoog opgelijnd. */
.page-actions .row-menu {
    margin-left: 0;
    display: flex;
}

.page-actions .row-menu-toggle {
    padding: 0.55rem 0.9rem;
    line-height: 1;
}

.section {
    margin-bottom: 2.5rem;
}

.columns {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
    gap: 1.5rem;
    align-items: start;
}

@media (max-width: 800px) {
    .layout {
        grid-template-columns: 1fr;
    }

    .sidebar {
        gap: 1rem;
    }

    .main {
        padding: 1.5rem 1rem 5rem;
    }
}

/* --- Components --------------------------------------------------------- */

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1.25rem 1.5rem;
    margin-bottom: 1.5rem;
}

/* Het laatste blok in een kaart draagt geen marge meer: die kwam boven op de padding
   van de kaart, waardoor de tekst er hoog in leek te hangen - onder stond 2,25rem waar
   boven 1,25rem stond. Bij een kaart met alleen een alinea viel dat meteen op. */
.card > :last-child {
    margin-bottom: 0;
}

.card-highlight {
    border-color: var(--accent);
    box-shadow: inset 4px 0 0 var(--accent), var(--shadow);
}

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.55rem 1.1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.btn:hover {
    border-color: var(--brand-primary);
    color: var(--brand-primary);
}

.btn-primary {
    background: var(--brand-primary);
    border-color: var(--brand-primary);
    color: #ffffff;
}

.btn-primary:hover {
    background: var(--brand-primary);
    border-color: var(--brand-primary);
    color: #ffffff;
    filter: brightness(0.85);
}

.btn-danger {
    background: #a12b2b;
    border-color: #a12b2b;
    color: #ffffff;
}

.btn-danger:hover {
    background: #7d1f1f;
    border-color: #7d1f1f;
    color: #ffffff;
}

.btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.btn-block {
    width: 100%;
}

.link-button {
    border: 0;
    background: none;
    padding: 0;
    color: var(--brand-primary);
    font: inherit;
    text-decoration: underline;
    cursor: pointer;
}

.link-danger {
    color: var(--error-text);
}

.icon-button {
    border: 0;
    background: none;
    padding: 0.4rem 0.6rem;
    border-radius: var(--radius);
    font-size: 1.2rem;
    color: var(--text-muted);
    cursor: pointer;
    transition: background var(--transition);
}

.icon-button:hover {
    background: var(--bg);
}

.tag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.1rem 0.5rem;
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text-muted);
    font-size: 0.8rem;
    font-weight: 600;
}

.tag-demo { background: var(--warning-bg); color: var(--warning-text); }
.tag-success, .tag-nieuw { background: var(--success-bg); color: var(--success-text); }
.tag-beter, .tag-bijwerken { background: var(--info-bg); color: var(--info-text); }
.tag-fout { background: var(--error-bg); color: var(--error-text); }
.tag-opgelost { background: var(--warning-bg); color: var(--warning-text); }

.notice,
.banner {
    padding: 0.75rem 1rem;
    border-radius: var(--radius);
    margin-bottom: 1rem;
    background: var(--info-bg);
    color: var(--info-text);
}

.notice-info { background: var(--info-bg); color: var(--info-text); }
.notice-success { background: var(--success-bg); color: var(--success-text); }
.notice-warning, .banner-warning { background: var(--warning-bg); color: var(--warning-text); }
.notice-error { background: var(--error-bg); color: var(--error-text); }

/* Een lege lijst is geen fout, maar een leeg vlak is saai. Daarom het patroon uit
   assets/img: witte lijnen, bedoeld om over een kleur te liggen. */
.empty-state {
    position: relative;
    overflow: hidden;
    padding: 3.5rem 1.5rem;
    border-radius: var(--radius);
    text-align: center;
    background: var(--brand-primary);
    color: rgba(255, 255, 255, 0.85);
}

.empty-state::before {
    content: "";
    position: absolute;
    inset: 0;
    background: url("/assets/img/background_1.svg") center / cover no-repeat;
    /* Zoals de tekening bedoeld is: lijnen die met de kleur meegaan */
    mix-blend-mode: soft-light;
    opacity: 0.9;
    pointer-events: none;
}

/* De inhoud komt boven het patroon */
.empty-state > * {
    position: relative;
}

.empty-state p {
    margin: 0 0 0.35rem;
}

.empty-state p:last-child {
    margin-bottom: 0;
}

.empty-state .muted,
.empty-state p.muted {
    color: rgba(255, 255, 255, 0.7);
}

/* Alleen het decoratieve icoon bovenaan, en dat is een DIRECT kind. Zonder die `>` raakte
   deze regel ook het plusje in de knop eronder: een plus van 2,5rem met een marge van een
   hele regel, midden in een knop. */
.empty-state > i {
    font-size: 2.5rem;
    margin-bottom: 1rem;
    color: rgba(255, 255, 255, 0.75);
}

/* Een gewone link in een leeg vlak is wit en onderstreept. Een knop is geen link: die
   houdt zijn eigen vorm, anders staat er onderstreepte tekst in een knop. */
.empty-state a:not(.btn) {
    color: #ffffff;
    text-decoration: underline;
}

/* Op een verzadigde achtergrond leest wit-op-merkkleur beter dan merkkleur-op-merkkleur:
   zo is het onmiskenbaar een knop en niet een vlak dat toevallig iets donkerder is. */
.empty-state .btn-primary {
    background: #ffffff;
    border-color: #ffffff;
    color: var(--brand-primary);
}

.empty-state .btn-primary:hover {
    background: rgba(255, 255, 255, 0.88);
    border-color: rgba(255, 255, 255, 0.88);
}

/* --- Tiles -------------------------------------------------------------- */

.tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 1rem;
}

.tile {
    position: relative;
    display: block;
    padding: 1.25rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    color: var(--text);
    text-decoration: none;
    transition: border-color var(--transition), transform var(--transition);
}

.tile p {
    color: var(--text-muted);
    font-size: 0.9rem;
    margin: 0;
}

.tile-link:hover {
    border-color: var(--brand-primary);
    color: var(--text);
    transform: translateY(-2px);
}

.tile-icon {
    font-size: 1.5rem;
    color: var(--brand-primary);
    margin-bottom: 0.75rem;
}

.tile.is-soon {
    opacity: 0.7;
}

.tile.is-soon .tag {
    position: absolute;
    top: 1rem;
    right: 1rem;
}

/* --- Forms and tables --------------------------------------------------- */

.form {
    display: grid;
    gap: 1rem;
}

.form-narrow {
    max-width: 20rem;
}

.form label {
    display: grid;
    gap: 0.3rem;
    font-weight: 600;
    font-size: 0.9rem;
}

/* Een veld dat geen <label> om zich heen kan hebben, zoals de iconenkiezer: de
   radioknoppen erin zouden dan bij elke klik de eerste keuze aanzetten. */
.form .field {
    display: grid;
    gap: 0.3rem;
}

.form .field-label {
    font-weight: 600;
    font-size: 0.9rem;
}

/* ── Velden naast elkaar ─────────────────────────────────────────────────────
   Een formulier van vijftien velden onder elkaar over de volle breedte leest als een
   vragenlijst: alles even zwaar, en je moet zelf bedenken wat bij elkaar hoort. Twee
   kolommen waar het past, en een veld dat de hele breedte nodig heeft (een omschrijving)
   zegt dat zelf. */
.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: 0 1.25rem;
    align-items: start;
}

/* Een vak in een raster is standaard minstens zo breed als zijn inhoud. Bij een
   keuzelijst is dat de langste optie - "1000 Strings / Dutch Harp Festival - 3527GV
   Utrecht" - en dan duwt die ene kolom de hele rij het kader uit. `min-width: 0` zegt
   dat hij wél mag krimpen; de tekst erin krijgt dan puntjes (.pp-select-label). */
.form-grid > *,
.form-grid label,
.form-grid .pp-select {
    min-width: 0;
}

.form-grid select,
.form-grid input,
.form-grid textarea {
    max-width: 100%;
}

.form-grid-full {
    grid-column: 1 / -1;
}

/* Velden die uit de analyse komen en die je zelden hoeft te zien: ingeklapt, maar wel
   bereikbaar. Weglaten zou betekenen dat je ze nergens meer kunt nakijken. */
.field-details {
    margin-top: 0.75rem;
    border-top: 1px solid var(--border);
    padding-top: 0.75rem;
}

.field-details summary {
    cursor: pointer;
    color: var(--text-muted);
}

.field-details[open] summary {
    margin-bottom: 0.5rem;
}

/* De pijltjes in een getalveld: weg. Ze staan in de weg bij een bedrag of een aantal,
   ze verspringen bij scrollen over het veld, en niemand telt een bezoekersaantal met
   stapjes van één omhoog. Typen blijft precies hetzelfde. */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

.form-row {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    /* Niet uitrekken. Een <label> is een grid (opschrift, veld, uitleg); rekt die mee
       met de hoogste buur, dan rekken zijn rijen mee en zakt het invoerveld omlaag. Zo
       stond een veld zonder uitleg eronder ("Bouwjaar vanaf") lager dan het veld ernaast
       met "m²" eronder - terwijl de opschriften netjes op één lijn stonden. */
    align-items: start;
}

.form-row .grow {
    flex: 1 1 12rem;
}

/* De tegenhangers van .grow: velden die juist klein horen te zijn. Een huisnummer is
   drie tekens breed; hem net zo breed maken als de rest van de regel suggereert dat er
   meer in kan, en dan staat een adres van vier velden over de hele pagina uitgesmeerd.
   Ze groeien niet mee, dus ze blijven links bij elkaar staan. */
.form-row .short {
    flex: 0 1 10rem;
}

.form-row .mini {
    flex: 0 1 7rem;
}

/* Een bereik: twee velden onder één opschrift, met een streepje ertussen.
   "Oppervlakte vanaf" en "tot en met" als twee losse velden naast elkaar leest niet:
   het tweede opschrift zegt niet waar het bij hoort, en het eerste past niet op één
   regel in een smal veld. Samen onder "Oppervlakte" is het meteen duidelijk. */
.form-row .field {
    flex: 0 1 auto;
}

.range-fields {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.range-fields input {
    width: 6.5rem;
}

.range-dash,
.range-unit {
    color: var(--text-muted);
    font-weight: 400;
    font-size: 0.85rem;
}

.form label.checkbox {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 400;
}

/* Een keuzevakje met een uitleg eronder: het vakje hoort dan bij de eerste regel te
   staan, niet in het midden van een alinea van drie regels */
.form label.checkbox-with-note {
    align-items: flex-start;
}

.checkbox-with-note input[type="checkbox"] {
    margin-top: 0.2rem;
}

.checkbox-with-note small {
    display: block;
    margin-top: 0.2rem;
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="tel"],
input[type="search"],
input[type="number"],
select,
textarea {
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-weight: 400;
    transition: border-color var(--transition), box-shadow var(--transition);
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--brand-primary);
    box-shadow: 0 0 0 3px rgba(31, 95, 174, 0.15);
    outline: none;
}

input:disabled {
    background: var(--bg);
    color: var(--text-muted);
}

/* --- Meldingen rechtsonder --------------------------------------------- */
/* assets/js/toast.js verhuist elke paginamelding hierheen. Zonder dat script staan
   ze boven aan de pagina, zoals eerst - dan is er niets stuk, alleen minder mooi. */

.toast-stack {
    position: fixed;
    right: 1.25rem;
    bottom: 1.25rem;
    z-index: 1800;
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
    width: min(30rem, calc(100vw - 2.5rem));
    /* De stapel zelf vangt geen klikken: daaronder moet je gewoon kunnen werken */
    pointer-events: none;
}

/* Een melding die opvalt: hij schuift van rechts in beeld, is groot genoeg om vanuit
   je ooghoek te zien, en draagt links een balk in de kleur van het soort. De schaduw is
   zwaarder dan elders, want dit blok hoort boven de pagina te zweven, niet erin. */
.toast {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 0.7rem;
    margin: 0;
    padding: 0.95rem 2.75rem 0.95rem 1rem;
    border-left: 4px solid currentColor;
    box-shadow: 0 0.75rem 1.75rem rgba(15, 23, 42, 0.22);
    font-size: 0.95rem;
    line-height: 1.45;
    pointer-events: auto;
    animation: toast-in 0.34s cubic-bezier(0.22, 1, 0.36, 1);
}

.toast-body {
    min-width: 0;
}

.toast-body p:last-child {
    margin-bottom: 0;
}

/* Het icoon staat op de kleur van het soort, maar iets rustiger dan de tekst */
.toast-icon {
    flex: none;
    margin-top: 0.1rem;
    font-size: 1.05rem;
    opacity: 0.85;
}

.toast.is-leaving {
    opacity: 0;
    transform: translateX(calc(100% + 1.5rem));
    transition: opacity 0.25s ease, transform 0.25s ease-in;
}

.toast-close {
    position: absolute;
    top: 0.45rem;
    right: 0.45rem;
    padding: 0.3rem 0.45rem;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: inherit;
    font: inherit;
    opacity: 0.6;
    cursor: pointer;
}

.toast-close:hover {
    opacity: 1;
}

@keyframes toast-in {
    from {
        opacity: 0;
        transform: translateX(calc(100% + 1.5rem));
    }
    to {
        opacity: 1;
        transform: none;
    }
}

/* Wie beweging liever niet heeft, krijgt hem niet */
@media (prefers-reduced-motion: reduce) {
    .toast {
        animation: none;
    }

    .toast.is-leaving {
        transform: none;
        transition: none;
    }
}

/* Op een smal scherm over de volle breedte, net boven de voetbalk */
@media (max-width: 640px) {
    .toast-stack {
        right: 0.5rem;
        left: 0.5rem;
        bottom: 3.5rem;
        width: auto;
    }

    /* Op een smal scherm is er geen ruimte om van rechts in te schuiven */
    .toast {
        animation-name: toast-in-onder;
    }

    .toast.is-leaving {
        transform: translateY(0.75rem);
    }
}

@keyframes toast-in-onder {
    from {
        opacity: 0;
        transform: translateY(1rem);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

@media print {
    .toast-stack {
        display: none;
    }
}

/* Een kerncijfer dat ergens heen gaat: zelfde blok, maar klikbaar */
.kpi-link {
    color: inherit;
    text-decoration: none;
    transition: border-color var(--transition), box-shadow var(--transition);
}

.kpi-link:hover {
    border-color: var(--brand-primary);
    box-shadow: var(--shadow);
}

.kpi-label i {
    margin-right: 0.35rem;
    color: var(--text-muted);
}

/* Een breed venster, voor een disclaimer met lopende tekst */
.pp-dialog-wide {
    width: min(48rem, calc(100vw - 2rem));
}

.pp-dialog-wide .card {
    margin: 0;
    border: 0;
    box-shadow: none;
}

/* "Akkoord met de voorwaarden - intrekken" in de voetbalk */
.footer-disclaimer {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
    color: var(--text-muted);
}

.footer-disclaimer i {
    color: var(--success-text);
}

/* De achtergronden van het inlogscherm: lagen over elkaar die vervagen. De foto
   zelf zet JavaScript, want een style-attribuut mag niet van de CSP. */
.login-background-layer {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    opacity: 0;
    transition: opacity 1.2s ease-in-out;
}

.login-background-layer.is-visible {
    opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
    .login-background-layer {
        transition: none;
    }
}

/* Achtergronden kiezen bij een omgeving */
.background-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.background-item {
    display: block;
}

.background-item img {
    display: block;
    width: 100%;
    height: 7rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    object-fit: cover;
}

.background-item .checkbox {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.35rem;
    font-size: 0.9rem;
}

/* Een taartdiagram naast zijn tabel. Onder de duizend pixels onder elkaar. */
.pie-layout {
    display: grid;
    grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
    gap: 1.5rem;
    align-items: start;
}

@media (max-width: 1000px) {
    .pie-layout {
        grid-template-columns: minmax(0, 1fr);
    }
}

.pie {
    width: 100%;
    max-width: 20rem;
    height: auto;
}

/* De taart met zijn legenda ernaast, onder een benchmarktabel. Op een smal scherm komt
   de legenda eronder in twee kolommen, anders wordt het een lange sliert. */
.pie-with-legend {
    display: grid;
    /* De legenda krijgt de breedte die hij nodig heeft en niet alles wat er is: op een
       breed scherm stond de tweede kolom anders een halve meter van de taart vandaan. */
    grid-template-columns: minmax(0, 17rem) minmax(0, auto);
    justify-content: start;
    gap: 2rem;
    align-items: center;
    margin-top: 1.5rem;
}

@media (max-width: 60rem) {
    .pie-with-legend {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Een kop met rechts een knop: de titel links, de actie aan de andere kant. Op een smal
   scherm eronder. */
.section-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem 1rem;
}

.section-head h2 {
    margin: 0;
}

/* ── Sneltoetsen ─────────────────────────────────────────────────────────────
   Het overzicht achter `?` en de link in de voetbalk. De toetsen zelf staan als <kbd>,
   zodat ze eruitzien als iets dat je indrukt. */
.shortcuts-dialog {
    max-width: 44rem;
}

/* Twee tekstkolommen in plaats van een raster: "Ga naar" heeft elf regels en "Nieuw"
   drie, en in een raster staat de rechterkolom dan half leeg met "Altijd" eronder op een
   eigen rij. Zo lopen de groepen door, en `break-inside` houdt een groep bij elkaar. */
.shortcuts-grid {
    columns: 2;
    column-gap: 2rem;
    margin-top: 1rem;
}

.shortcuts-grid section {
    break-inside: avoid;
    margin-bottom: 1.25rem;
}

@media (max-width: 34rem) {
    .shortcuts-grid {
        columns: 1;
    }
}

.shortcuts-grid h3 {
    margin: 0 0 0.5rem;
    font-size: 0.85rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}

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

.shortcuts-list li {
    padding: 0.2rem 0;
}

.shortcuts-list a,
.shortcuts-list span {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--text);
    text-decoration: none;
}

.shortcuts-list a:hover {
    color: var(--brand-primary);
}

/* De twee toetsen naast elkaar, met een vaste breedte zodat de namen uitlijnen */
.shortcuts-keys {
    flex: none;
    min-width: 3.4rem;
}

kbd {
    display: inline-block;
    min-width: 1.4rem;
    padding: 0.1rem 0.35rem;
    border: 1px solid var(--border);
    border-bottom-width: 2px;
    border-radius: 4px;
    background: var(--bg);
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 0.8rem;
    text-align: center;
}

/* Het bericht onderin zodra je de eerste toets van een combinatie hebt ingedrukt: je
   ziet dat hij is aangekomen en dat er nog een tweede bij hoort */
.shortcut-hint {
    position: fixed;
    left: 50%;
    bottom: 4.5rem;
    z-index: 1200;
    padding: 0.5rem 1rem;
    border-radius: var(--radius);
    background: var(--text);
    color: var(--surface);
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 0.9rem;
    transform: translateX(-50%);
    pointer-events: none;
}

/* ── De waarschuwing vóór het uitloggen ──────────────────────────────────────
   Geen scherm over de pagina heen zoals bij een verlopen sessie: je bent nog bezig, en
   dit mag je niet in de weg zitten. Een balk onderin met een aftelling en een knop. */
.session-warning {
    position: fixed;
    left: 50%;
    bottom: 4.5rem;
    z-index: 1150;
    width: min(32rem, calc(100vw - 2rem));
    transform: translateX(-50%);
}

.session-warning-card {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--warning-border, var(--border));
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
}

.session-warning-card p {
    margin: 0.15rem 0 0;
    font-size: 0.9rem;
}

.session-warning-card .btn {
    flex: none;
    margin-left: auto;
}

#session_countdown {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
}

/* ── De wachtrij ─────────────────────────────────────────────────────────────
   Wat er op de achtergrond draait, met een balk zolang het bezig is. De balk krijgt zijn
   breedte via JavaScript (data-percent), want de CSP staat geen style-attribuut toe. */
.job-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.job {
    padding: 0.75rem 0;
    border-top: 1px solid var(--border);
}

.job:first-child {
    border-top: 0;
}

.job-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
}

.job-head .muted {
    margin-left: auto;
    font-size: 0.85rem;
}

.job p {
    margin: 0.35rem 0 0;
    font-size: 0.9rem;
}

.job-bar {
    height: 0.5rem;
    margin-top: 0.5rem;
    border-radius: 999px;
    background: var(--bg);
    overflow: hidden;
}

.job-bar-fill {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 999px;
    background: var(--brand-primary);
    transition: width var(--transition);
}

/* ── Eigen dashboards ────────────────────────────────────────────────────────
   Tabbladen met borden, en per tegel een paar knopjes in de aanpasstand. */
.dashboard-tabs {
    align-items: center;
}

/* De knop om een bord toe te voegen hoort rechts, los van de tabbladen: het is geen
   bord maar een actie. Er stond een invulveld naast, altijd in beeld, ook bij de mensen
   die nooit een tweede bord maken - en een leeg veld in een tabbalk ziet eruit als iets
   dat je moet invullen. De naam geef je nu in de aanpasstand, waar hij al stond. */
.dashboard-new {
    display: flex;
    gap: 0.35rem;
    margin-left: auto;
    padding-bottom: 0.35rem;
}

.dashboard-editor-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1.5rem;
    margin-bottom: 1rem;
}

@media (min-width: 55rem) {
    .dashboard-editor-row {
        grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
        align-items: start;
    }
}

.dashboard-add-tile select,
.dashboard-add-tile textarea {
    width: 100%;
}

/* ── Kiezen wat er op je bord komt ───────────────────────────────────────────
   Dit was een uitklaplijst met "Label · omschrijving" in één regel. Die omschrijving
   paste nooit, en je koos iets waarvan je pas zag wat het was toen het op je bord stond.
   Nu een raster met kaartjes: icoon, naam, en de hele omschrijving eronder. */
.tile-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
    gap: 0.6rem;
    margin: 0.5rem 0 1rem;
}

.tile-option {
    display: block;
    cursor: pointer;
}

/* Het rondje zelf hoeft niemand te zien: het kaartje is de keuze. Het blijft wel
   bedienbaar met het toetsenbord, en :focus-visible laat zien waar je bent. */
.tile-option input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.tile-option-body {
    display: block;
    height: 100%;
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    transition: border-color 0.15s, background 0.15s;
}

.tile-option-body i {
    color: var(--text-muted);
}

.tile-option-body strong {
    display: block;
    margin: 0.25rem 0 0.15rem;
}

.tile-option-body small {
    display: block;
    color: var(--text-muted);
    line-height: 1.35;
}

.tile-option:hover .tile-option-body {
    border-color: var(--brand-primary);
}

.tile-option input:checked + .tile-option-body {
    border-color: var(--brand-primary);
    background: color-mix(in srgb, var(--brand-primary) 8%, var(--surface));
}

.tile-option input:checked + .tile-option-body i,
.tile-option input:checked + .tile-option-body strong {
    color: var(--brand-primary);
}

.tile-option input:focus-visible + .tile-option-body {
    outline: 2px solid var(--brand-primary);
    outline-offset: 2px;
}

/* Een veld met de knop ernaast in plaats van eronder: "Naam" en "Opslaan" horen bij
   elkaar, en twee knopregels onder elkaar lazen als twee losse formulieren. */
.field-with-button {
    display: flex;
    gap: 0.5rem;
    align-items: stretch;
}

.field-with-button input,
.field-with-button select {
    flex: 1;
    min-width: 0;
}

.field-with-button .btn {
    flex: none;
    white-space: nowrap;
}

.dashboard-tile-text {
    margin-top: 0.75rem;
}

/* ── Tegels die de gebruiker zelf kiest ──────────────────────────────────────
   De kaart, de plaatsen, de collega's, het auditlog, je laatste zoekopdrachten en de
   grafiek van je eigen gegevens. Allemaal blokken in een tegel, dus ze houden zich aan
   de maten van de kaart eromheen en gebruiken alleen kleurtokens. */
.dash-map {
    height: 22rem;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    z-index: 0;
}

.colleague-list,
.audit-feed,
.idea-vote-list,
.search-history {
    margin: 0;
    padding: 0;
    list-style: none;
}

.colleague-list li,
.audit-feed li,
.idea-vote-list li,
.search-history li {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.4rem 0;
    border-bottom: 1px solid var(--border);
}

.colleague-list li:last-child,
.audit-feed li:last-child,
.idea-vote-list li:last-child,
.search-history li:last-child {
    border-bottom: 0;
}

.colleague-list li > :first-child,
.idea-vote-list a,
.search-history a {
    flex: 1;
    min-width: 0;
}

.search-history a {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text);
    text-decoration: none;
}

.search-history a:hover {
    color: var(--brand-primary);
}

/* Het auditlog in drie kolommen: wanneer, wat, wie. Op een telefoon onder elkaar, want
   dan is er voor drie kolommen geen ruimte en gaat het toch om "wat". */
.audit-feed li {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0.15rem 0.75rem;
}

@media (min-width: 45rem) {
    .audit-feed li {
        grid-template-columns: 11rem minmax(0, 1fr) 14rem;
        align-items: center;
    }
}

.audit-when {
    color: var(--text-muted);
    font-size: 0.9rem;
}

.audit-what small {
    display: block;
    color: var(--text-muted);
}

/* De twee keuzelijsten van een grafiektegel naast elkaar zolang het past */
.dashboard-tile-chart {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: 0.75rem;
    margin-top: 0.75rem;
}

.dashboard-tile-chart select {
    width: 100%;
}

.dashboard-order {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-top: 0.75rem;
}

.dashboard-order .tile-tools {
    margin-bottom: 0;
}

/* Weggooien onderaan, met een scheidingslijn: het is het laatste wat je hier doet, en
   het stond rechtsboven als het rodste ding op het scherm. */
.dashboard-editor-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
}

.dashboard-editor-foot p {
    margin: 0;
    max-width: 34rem;
}

/* De knoppen bij een tegel: omhoog, omlaag, weg. Ze staan bóven de tegel waar ze bij
   horen en alleen in de aanpasstand - anders wacht er bij elk cijfer een prullenbak op
   een verkeerde klik. */
.tile-tools {
    display: flex;
    gap: 0.25rem;
    margin-bottom: 0.35rem;
}

/* In de aanpasstand staat elke tegel in een eigen kader. Ze stonden onder elkaar over de
   volle breedte, en dan lijkt een bord van vijf tegels een lijst van vijf schermen; nu
   liggen ze in hetzelfde raster als daarbuiten, zodat je verschuift wat je ziet. */
.tile-edit-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
    gap: 1rem;
    margin-bottom: 1rem;
}

.tile-edit {
    padding: 0.75rem;
    border: 1px dashed var(--border);
    border-radius: var(--radius);
}

/* Een breed blok (de wachtrij, de laatste rapporten) neemt de hele rij */
.tile-edit.is-wide {
    grid-column: 1 / -1;
}

.tile-edit .kpi,
.tile-edit .card,
.tile-edit .section {
    margin: 0;
}

.tile-tools form {
    display: inline;
}

/* Het formulier om een cijfer vast te zetten: vier velden naast elkaar zolang het past */
.figures-pin {
    margin-top: 1.5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
}

.figures-pin-fields {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: 0.75rem 1rem;
}

.figures-pin-fields select,
.figures-pin-fields input {
    width: 100%;
}

/* De keuze tussen deze analyse en de reeks erboven: het zijn twee vragen, niet twee
   vormen van hetzelfde, dus ze staan los van de grafiekknoppen. */
.figures-views {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-bottom: 1rem;
}

.line-chart {
    width: 100%;
    max-width: 45rem;
    height: auto;
    margin: 1rem 0 0.5rem;
}

.line-grid {
    stroke: var(--border);
    stroke-width: 1;
}

/* De legenda onder een lijngrafiek: alleen namen, want de waarden staan in de tabel */
.line-legend {
    grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
    margin-bottom: 1rem;
}

/* De balk boven de cijfers van een rapport: wat je ermee kunt (tabel, staven, taart),
   over welke kolom, en de Excel. Op een smal scherm onder elkaar. */
.figures-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1rem;
    margin-bottom: 1rem;
}

.figures-charts,
.figures-columns {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}

/* De kolomkeuze hoort bij de grafiek ernaast, niet bij de knoppen ervoor: een streepje
   ertussen scheelt een verkeerde klik */
.figures-columns {
    padding-left: 1rem;
    border-left: 1px solid var(--border);
}

.figures-bar .btn:last-child {
    margin-left: auto;
}

/* Een kolomkop waarop je kunt sorteren. Het pijltje staat er alleen bij de kolom waarop
   gesorteerd is - een rij grijze pijltjes boven elke kolom is ruis. */
.table-sort {
    color: inherit;
    text-decoration: none;
}

.table-sort:hover {
    color: var(--brand-primary);
}

.table-sort.is-active {
    color: var(--text);
}

/* Een staaf zonder eigen betekenis in de kleur: de merkkleur, want hier gaat het over
   hoeveel en niet over wie */
.value-bar {
    fill: var(--brand-primary);
}

/* Twee grafieken naast elkaar: de verdeling links, de afwijking rechts. Ze gaan over
   dezelfde doelgroepen en beantwoorden elkaars vraag, dus ze horen naast elkaar te
   staan - onder elkaar moest je ervoor scrollen en legde niemand ze naast elkaar.
   Onder de zeventig rem past dat niet meer en gaan ze weer onder elkaar. */
.chart-pair {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1.25rem;
    margin-top: 1.5rem;
}

@media (min-width: 70rem) {
    .chart-pair:not(.chart-pair-one) {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        align-items: start;
    }
}

.chart-box {
    min-width: 0;
    margin: 0;
    padding: 1rem 1.1rem 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.chart-title {
    margin-bottom: 0.9rem;
    color: var(--text-muted);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* In een halve kolom past de legenda niet meer naast de taart, en twee kolommen namen
   past er al helemaal niet: dus de taart erboven en de namen eronder, met het percentage
   rechts uitgelijnd. Dat leest als een lijstje in plaats van als een lappendeken. */
.chart-pair .pie-with-legend {
    grid-template-columns: minmax(0, 1fr);
    justify-items: stretch;
    gap: 1rem;
    margin-top: 0;
}

.chart-pair .pie {
    justify-self: center;
    max-width: 15rem;
}

.chart-pair .pie-legend {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.2rem 1rem;
    width: 100%;
    /* Dezelfde maat als de namen in de grafiek ernaast: het is hetzelfde lijstje */
    font-size: 13px;
}

.chart-pair .pie-legend li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    white-space: normal;
}

.pie-legend-name {
    min-width: 0;
}

/* De grafiek stond hier op `max-width: none` zodat hij zijn kolom vulde. Maar een SVG
   rekt niet alleen zijn balken op: de tekst schaalt mee, en dan staan de namen rechts
   groter dan diezelfde namen in de legenda links - terwijl het over hetzelfde lijstje
   gaat. Dus dezelfde bovengrens als elders (de tekening is 720 eenheden breed, dat is
   45rem), en dan is één eenheid weer één pixel en klopt de tekstgrootte met de rest. */
.chart-pair .index-bars {
    max-width: 45rem;
    margin-top: 0;
}

.chart-pair .bars-label,
.chart-pair .bars-value {
    font-size: 13px;
}


/* ── De grafieken tekenen zichzelf ────────────────────────────────────────────
   Een balk groeit vanaf de nullijn en een partje vanuit het midden, regel voor regel.
   Dat is niet alleen leuk: je ziet dáárdoor welke kant een balk op wijst en dat het
   midden de honderd is. Het duurt samen nog geen seconde, het gebeurt één keer, en wie
   minder beweging wil (of afdrukt) krijgt de eindstand meteen te zien - daarom zit de
   beginstand in de keyframes en niet in de regel zelf. */
@keyframes pp-bar-grow {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

@keyframes pp-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes pp-pie-slice-in {
    from { opacity: 0; transform: scale(0.55); }
    to   { opacity: 1; transform: scale(1); }
}

.bars-bar {
    /* fill-box: het draaipunt is de balk zelf, en dus zijn eigen begin bij de nullijn */
    transform-box: fill-box;
    animation: pp-bar-grow 0.5s cubic-bezier(0.2, 0.8, 0.3, 1) both;
}

.bars-bar.is-right {
    transform-origin: left center;
}

.bars-bar.is-left {
    transform-origin: right center;
}

.bars-row .bars-label,
.bars-row .bars-value {
    animation: pp-fade-in 0.4s ease both;
}

/* Regel voor regel, van boven naar beneden. Meer dan tien regels heeft een indeling
   zelden; daarboven lopen ze mee met de laatste vertraging. */
.bars-row:nth-of-type(1) * { animation-delay: 0.00s; }
.bars-row:nth-of-type(2) * { animation-delay: 0.05s; }
.bars-row:nth-of-type(3) * { animation-delay: 0.10s; }
.bars-row:nth-of-type(4) * { animation-delay: 0.15s; }
.bars-row:nth-of-type(5) * { animation-delay: 0.20s; }
.bars-row:nth-of-type(6) * { animation-delay: 0.25s; }
.bars-row:nth-of-type(7) * { animation-delay: 0.30s; }
.bars-row:nth-of-type(8) * { animation-delay: 0.35s; }
.bars-row:nth-of-type(9) * { animation-delay: 0.40s; }
.bars-row:nth-of-type(n+10) * { animation-delay: 0.45s; }

/* view-box: het draaipunt is het midden van de tekening, en dat is het middelpunt van
   de taart - met fill-box zou elk partje uit zijn eigen hoekje komen */
.pie-slice {
    transform-box: view-box;
    transform-origin: 50% 50%;
    animation: pp-pie-slice-in 0.45s cubic-bezier(0.2, 0.8, 0.3, 1) both;
}

.pie-slice:nth-of-type(1) { animation-delay: 0.00s; }
.pie-slice:nth-of-type(2) { animation-delay: 0.05s; }
.pie-slice:nth-of-type(3) { animation-delay: 0.10s; }
.pie-slice:nth-of-type(4) { animation-delay: 0.15s; }
.pie-slice:nth-of-type(5) { animation-delay: 0.20s; }
.pie-slice:nth-of-type(6) { animation-delay: 0.25s; }
.pie-slice:nth-of-type(7) { animation-delay: 0.30s; }
.pie-slice:nth-of-type(8) { animation-delay: 0.35s; }
.pie-slice:nth-of-type(n+9) { animation-delay: 0.40s; }

/* De percentages in de taart komen pas als de partjes er staan */
.pie-label {
    animation: pp-fade-in 0.3s ease 0.45s both;
}

/* Wie beweging op zijn systeem heeft uitgezet, krijgt de eindstand meteen */
@media (prefers-reduced-motion: reduce) {
    .bars-bar,
    .bars-row .bars-label,
    .bars-row .bars-value,
    .pie-slice,
    .pie-label {
        animation: none;
    }
}

@media print {
    .bars-bar,
    .bars-row .bars-label,
    .bars-row .bars-value,
    .pie-slice,
    .pie-label {
        animation: none;
    }
}

/* Een dun lijntje tussen de partjes, in de kleur van de kaart eronder: dan blijft het
   ook in het donkere thema een scheiding en geen witte streep. */
.pie-slice {
    stroke: var(--surface);
    stroke-width: 1.5;
    stroke-linejoin: round;
}

/* De afwijkingsgrafiek: waar wijkt dit publiek van af. De taart laat de verdeling zien,
   deze het verschil - en dat is waar een benchmark over gaat. */
.index-bars {
    width: 100%;
    max-width: 45rem;
    height: auto;
    margin-top: 1.5rem;
}

.bars-label {
    fill: var(--text);
    font-size: 11px;
}

.bars-value {
    fill: var(--text-muted);
    font-size: 11px;
    font-weight: 600;
}

.bars-value.is-high {
    fill: var(--success-text);
}

.bars-value.is-low {
    fill: var(--warning-text);
}

.bars-scale {
    fill: var(--text-muted);
    font-size: 10px;
}

.bars-axis {
    stroke: var(--border);
    stroke-width: 1;
}

/* De toelichting stond tegen de tabel aan geplakt en las daardoor als een tabelregel */
.section-note {
    margin: 1.25rem 0 0;
    padding: 0.85rem 1rem;
    border-left: 3px solid var(--brand-primary);
    border-radius: 0 var(--radius) var(--radius) 0;
    background: var(--bg);
}

/* Twee nette kolommen in plaats van een tekstkolom die afbreekt waar hij uitkomt:
   met `columns` sprong een regel halverwege naar de volgende kolom zodra een naam lang
   was, en dan staat de lijst scheef. */
.pie-legend {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    /* Kolommen zo breed als hun langste regel. Met gelijke kolommen van een vaste breedte
       viel het percentage achter een lange naam ("De Nieuwsgierige Toekomstgrijpers")
       naar de volgende regel, en dan lijkt het bij de verkeerde doelgroep te horen. */
    grid-template-columns: repeat(2, max-content);
    gap: 0.35rem 2rem;
    font-size: 0.85rem;
}

.pie-legend li {
    white-space: nowrap;
}

@media (max-width: 40rem) {
    .pie-legend {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Op een telefoon past een lange naam niet op een regel; daar mag hij wel afbreken */
    .pie-legend li {
        white-space: normal;
    }
}

.pie-legend li {
    break-inside: avoid;
    padding: 0.15rem 0;
}

/* Een smal invoervak voor een getal in een tabel.
   Met `input.input-small` en niet `.input-small`: de algemene regel hierboven is
   `input[type="number"]` en weegt daarmee zwaarder dan een losse class. Daardoor was dit
   vak niet zeven maar honderd procent breed - een aantal van 65 in een veld van drie
   centimeter, in elke regel van de tabel. */
input.input-small,
select.input-small {
    width: 7rem;
    text-align: right;
}

/* De kolom eromheen hoeft ook niet breder dan het vak */
.table-numbers td .input-small {
    display: inline-block;
}

.pie-label {
    font-size: 13px;
    font-weight: 600;
    fill: #fff;
    text-anchor: middle;
    dominant-baseline: middle;
    paint-order: stroke;
    stroke: rgba(0, 0, 0, 0.35);
    stroke-width: 3px;
}

/* --- Wachtscherm -------------------------------------------------------- */
/* Het beeldmerk dat zich van onder naar boven rood vult. Twee kopieën boven elkaar:
   het onderste in de tekstkleur, het bovenste rood en bijgeknipt. */

.pp-loading {
    position: fixed;
    inset: 0;
    z-index: 2400;
    display: flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--bg) 70%, transparent);
    /* Matglas: je ziet dat je scherm er nog is, maar dat het even niet aan de beurt is.
       Kent een browser backdrop-filter niet, dan blijft de laag hierboven staan en
       werkt het precies zo goed - alleen zonder de vervaging. */
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}

.pp-loading[hidden] {
    display: none;
}

.pp-loading-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

.pp-loading-mark {
    position: relative;
    /* Groot genoeg om er echt naar te kijken terwijl je wacht; op een klein scherm
       past dat niet, vandaar de bovengrens in vw. */
    width: min(252px, 60vw);
    height: min(252px, 60vw);
}

.pp-loading-mark span {
    position: absolute;
    inset: 0;
    display: block;
}

.pp-loading-mark svg {
    width: 100%;
    height: 100%;
}

/* In het merk zit een rode vorm met een vaste kleur. Hier moet het hele merk één
   kleur zijn, anders vult er maar de helft; vandaar currentColor op alles. */
.pp-loading-mark svg path {
    fill: currentColor;
}

/* Het onderste merk blijft staan, in een rustige tint */
.pp-loading-base {
    color: var(--text-muted);
    opacity: 0.3;
}

/* Het bovenste vult zich: van niets tot helemaal, en dan weer opnieuw */
.pp-loading-fill {
    color: var(--brand-mark-red);
    animation: pp-loading-fill 1.8s ease-in-out infinite;
}

@keyframes pp-loading-fill {
    0% {
        clip-path: inset(100% 0 0 0);
    }
    60% {
        clip-path: inset(0 0 0 0);
    }
    100% {
        clip-path: inset(0 0 100% 0);
    }
}

.pp-loading-text {
    margin: 0;
    color: var(--text-muted);
}

/* Wie beweging liever niet heeft, ziet het merk gewoon staan */
@media (prefers-reduced-motion: reduce) {
    .pp-loading-fill {
        animation: none;
        clip-path: none;
        opacity: 0.8;
    }
}

/* --- Bevestigen in de huisstijl ----------------------------------------- */
/* Vervangt window.confirm: dat venster zet de naam van het subdomein erboven en
   trekt zich niets aan van het donkere thema. assets/js/confirm.js bouwt dit. */

.pp-confirm {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
}

.pp-confirm[hidden] {
    display: none;
}

.pp-confirm-backdrop {
    position: absolute;
    inset: 0;
    border: 0;
    padding: 0;
    background: rgba(15, 23, 34, 0.42);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    cursor: default;
}

.pp-confirm-box {
    position: relative;
    width: min(30rem, 100%);
    padding: 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 10px 30px rgba(15, 23, 34, 0.25);
}

.pp-confirm-box h2 {
    margin: 0 0 0.5rem;
    font-size: 1.15rem;
}

.pp-confirm-box p {
    margin: 0 0 1.1rem;
    color: var(--text-muted);
}

.pp-confirm-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
}

/* --- Filterpaneel in de zijbalk ----------------------------------------- */
/* Een pagina met filters zet die links neer, waar anders het menu staat. Het menu
   klapt dan in tot de pagina waar je bent; met "Alle onderdelen" komt het terug. */

.sidebar-has-filters .sidebar nav.nav-hidden {
    display: none;
}

.sidebar-has-filters .sidebar nav.nav-hidden.is-open {
    display: block;
}

.nav-here a.is-active {
    cursor: default;
}

.sidebar-menu-toggle {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    padding: 0.5rem 0.75rem;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: var(--sidebar-text);
    font: inherit;
    font-size: var(--text-ui);
    text-align: left;
    cursor: pointer;
}

.sidebar-menu-toggle:hover {
    background: var(--sidebar-hover);
}

.sidebar-filters {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    scrollbar-width: thin;
    padding-right: 0.25rem;
}

.filter-tabs {
    display: flex;
    gap: 0.25rem;
    margin: 0 0 0.75rem;
    padding: 0;
    list-style: none;
}

.filter-tabs button {
    padding: 0.4rem 0.7rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text-muted);
    font: inherit;
    font-size: 0.9rem;
    cursor: pointer;
}

.filter-tabs button.is-active {
    background: var(--brand-primary);
    border-color: var(--brand-primary);
    color: #fff;
}

.filter-panel h3 {
    margin: 0 0 0.5rem;
    font-size: 1rem;
}

.filter-panel label {
    display: block;
    margin-bottom: 0.75rem;
    font-size: 0.9rem;
    font-weight: 600;
}

.filter-panel label.checkbox {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.3rem;
    font-weight: 400;
}

.filter-panel label.checkbox input {
    width: auto;
}

.filter-group {
    margin: 0.9rem 0 0.35rem;
    font-size: 0.78rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.filter-actions {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

/* Het smalle menu heeft geen ruimte voor filters; dan blijft alleen het icoon over */
.sidebar-collapsed .sidebar-filters,
.sidebar-collapsed .sidebar-menu-toggle span {
    display: none;
}

/* Kolommen kiezen: twee kolommen vinkjes, zodat een lijst van drieëntwintig velden
   in het venster past zonder eindeloos scrollen. */
.column-picker {
    columns: 2;
    column-gap: 1.5rem;
    margin-bottom: 1rem;
}

.column-picker .filter-group,
.column-picker .checkbox {
    break-inside: avoid;
}

@media (max-width: 560px) {
    .column-picker {
        columns: 1;
    }
}

/* --- Tabbladen in de pagina --------------------------------------------- */

/* Het scherm van een locatie: gegevens links, de kaart ernaast. Op een smal scherm
   onder elkaar, met de kaart onderaan. */
.note-list {
    margin: 1rem 0 0;
    padding: 0;
    list-style: none;
}

.note-item {
    padding: 0.75rem 0;
    border-top: 1px solid var(--border);
}

.note-item p {
    margin: 0;
}

.note-meta {
    font-size: 0.85rem;
}

/* De regel boven een notitie: wie hem schreef, wanneer, en rechts de prullenbak. De
   naam en de datum horen bij elkaar; de knop hoort aan de andere kant, want je klikt er
   niet per ongeluk op als hij niet naast de tekst staat. */
.note-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    margin-bottom: 0.35rem;
    font-size: 0.85rem;
}

.note-delete {
    margin-left: auto;
}

.note-body {
    margin: 0;
    white-space: pre-line;
}

.note-form textarea {
    width: 100%;
}

/* De ster: aan is de merkkleur, uit is gewoon een knop. Geen vaste kleur, anders klopt
   het donkere thema niet. */
.favorite-form {
    display: inline-block;
}

.favorite-toggle.is-on {
    border-color: var(--brand-primary);
    color: var(--brand-primary);
}

/* Een blok favorieten op het dashboard: het spul waar je deze week aan werkt */
.favorite-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.favorite-list a {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text);
    text-decoration: none;
}

.favorite-list a:hover {
    border-color: var(--brand-primary);
    background: var(--surface);
}

.favorite-list i {
    color: var(--text-muted);
}

.favorite-list .favorite-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.favorite-list small {
    display: block;
    color: var(--text-muted);
    font-size: 0.75rem;
}

/* --- Venster (dialog) --------------------------------------------------- */
/* Een <dialog> doet het zware werk zelf: de aandacht blijft binnen, Escape sluit,
   en de rest van de pagina is niet te bedienen. Wij doen alleen de opmaak. */

.pp-dialog {
    width: min(38rem, calc(100vw - 2rem));
    max-height: calc(100vh - 4rem);
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 10px 30px rgba(15, 23, 34, 0.25);
    overflow: auto;
}

/* Het venster krijgt de aandacht bij het openen (zie list.js); een rand eromheen zou
   suggereren dat je er iets mee kunt. De elementen erin houden hun eigen focusring. */
.pp-dialog:focus {
    outline: none;
}

.pp-dialog::backdrop {
    background: rgba(15, 23, 34, 0.42);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
}

/* Ruimte binnen het venster, voor **elk** kind en niet voor een lijstje bekende kinderen.
   Dit stond eerst op `.form`, toen kwam `.pp-dialog-head`, `p` en `.shortcuts-grid` erbij, en
   het kaartvenster plakte alsnog tegen de rand: zo'n lijst groeit bij elk nieuw venster en
   wordt een keer vergeten. Een kind dat juist tot de rand hoort te lopen zegt dat zelf met
   `pp-dialog-flush`. Een `.card` staat er ook buiten: die brengt zijn eigen ruimte mee, en
   anders staat de disclaimer twee keer ingesprongen. */
.pp-dialog > *:not(.card):not(.pp-dialog-flush) {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
}

.pp-dialog > :first-child:not(.card):not(.pp-dialog-flush) {
    padding-top: 1.25rem;
}

.pp-dialog > :last-child:not(.card):not(.pp-dialog-flush) {
    padding-bottom: 1.25rem;
}

.pp-dialog-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1rem;
}

.pp-dialog-head h2 {
    margin: 0;
    font-size: 1.15rem;
}

/* **Elk venster sluit met dezelfde knop.** Er waren er drie: deze, een `.btn btn-small` in
   de sneltoetsen en een `.icon-button` in het helppaneel. Erger nog: deze zette geen `border`
   en geen `background`, dus de browser zette er zijn eigen knoprand omheen - een grijs
   blokje met een kruisje erin, terwijl ernaast een kaal icoon stond. Dit is nu `.icon-button`
   met alleen de plaatsing erbij, zodat er niets meer kan afwijken. */
.pp-dialog-close {
    flex: none;
    border: 0;
    background: none;
    padding: 0.35rem 0.55rem;
    border-radius: var(--radius);
    font-size: 1.1rem;
    line-height: 1;
    color: var(--text-muted);
    text-decoration: none;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}

.pp-dialog-close:hover {
    background: var(--bg);
    color: var(--text);
}

/* Zonder JavaScript krijgt het venster `open` van de server mee: dan staat het als
   gewoon blok in de pagina in plaats van als venster over de lijst heen. */
.pp-dialog[open]:not(:modal) {
    position: static;
    width: auto;
    max-height: none;
    margin: 0 0 1rem;
}

/* --- Icoon van een pin kiezen ------------------------------------------- */

.col-icon {
    width: 1%;
    padding-right: 0;
}

.pin-current {
    width: 22px;
    height: 22px;
    vertical-align: middle;
}

.pin-choice {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 0.9rem;
}

.pin-option input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.pin-option-body {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 2.75rem;
    height: 2.75rem;
    padding: 0 0.5rem;
    border: 2px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    cursor: pointer;
}

.pin-option-body img {
    width: 26px;
    height: 26px;
}

.pin-option input:checked + .pin-option-body {
    border-color: var(--brand-primary);
    box-shadow: 0 0 0 3px rgba(31, 95, 174, 0.15);
}

.pin-option input:focus-visible + .pin-option-body {
    outline: 2px solid var(--brand-primary);
    outline-offset: 2px;
}

/* --- Acties achter een rij ---------------------------------------------- */
/* Wijzigen is een knop, de rest zit onder de drie puntjes. De kolom is daardoor
   zo smal mogelijk en "Verwijderen" staat niet de hele dag te lonken. */

.col-actions {
    width: 1%;
    white-space: nowrap;
    text-align: right;
}

.row-menu {
    position: relative;
    display: inline-block;
    margin-left: 0.25rem;
    vertical-align: middle;
}

.row-menu-toggle {
    padding: 0.3rem 0.5rem;
    line-height: 1;
}

.row-menu-list {
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    /* Boven een Leaflet-kaart uit: die tekent zijn lagen op 400 en zijn knoppen op
       800. Daarboven, maar onder de meldingen en de vensters hieronder. */
    z-index: 900;
    min-width: 11rem;
    padding: 0.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
    text-align: left;
}

.row-menu.is-up .row-menu-list {
    top: auto;
    bottom: calc(100% + 4px);
}

.row-menu-list[hidden] {
    display: none;
}

.row-menu-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.45rem 0.6rem;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: var(--text);
    font: inherit;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.row-menu-item:hover {
    background: var(--sidebar-hover);
}

.row-menu-item.is-danger {
    color: var(--error-text);
}

/* --- Selectievakjes en bulkacties --------------------------------------- */

.table-select .col-select {
    width: 2.5rem;
    text-align: center;
}

.table-select .col-select input {
    width: auto;
    margin: 0;
}

/* De balk met bulkacties zweeft boven de voetbalk, niet eronder: hij hoort bij wat je
   nu aan het doen bent en moet dus in beeld blijven. Een eigen kleur maakt duidelijk
   dat dit iets anders is dan de rest van de pagina - je staat op het punt iets te doen
   met een stapel regels tegelijk. */
.bulk-bar {
    position: fixed;
    left: 50%;
    bottom: 4.25rem;
    transform: translateX(-50%);
    z-index: 30;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    max-width: calc(100vw - 2rem);
    padding: 0.7rem 1rem;
    border-radius: var(--radius);
    background: var(--brand-primary);
    color: #fff;
    box-shadow: 0 6px 20px rgba(15, 23, 34, 0.35);
}

.bulk-bar[hidden] {
    display: none;
}

/* De keuzelijsten houden hun gewone uiterlijk: op een gekleurde balk is een gekleurd
   invoerveld niet te lezen */
.bulk-bar select,
.bulk-bar .pp-select {
    width: auto;
    min-width: 12rem;
}

.bulk-bar .btn {
    background: #fff;
    border-color: #fff;
    color: var(--brand-primary);
}

.bulk-bar .btn:hover {
    background: var(--bg);
}

.bulk-count {
    margin-right: 0.5rem;
    color: #fff;
}

/* Naast de zijbalk, net als de voetbalk: anders staat hij half over het menu */
@media (min-width: 900px) {
    .bulk-bar {
        left: calc(15rem + (100vw - 15rem) / 2);
    }
}

.sidebar-collapsed .bulk-bar {
    left: 50%;
}

/* --- Zoekbare dropdown -------------------------------------------------- */
/* assets/js/select.js bouwt dit om elke <select> heen. De echte select blijft
   staan (naam, waarde, verplicht-melding) maar is niet te zien; hij mag niet
   display:none krijgen, want dan weigert de browser hem bij validatie. */

.pp-select {
    position: relative;
}

.pp-select-native {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 1px;
    padding: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}

.pp-select-button {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-weight: 400;
    text-align: left;
    cursor: pointer;
    transition: border-color var(--transition), box-shadow var(--transition);
}

.pp-select-button:focus-visible,
.pp-select.is-open .pp-select-button {
    border-color: var(--brand-primary);
    box-shadow: 0 0 0 3px rgba(31, 95, 174, 0.15);
    outline: none;
}

.pp-select.is-invalid .pp-select-button {
    border-color: var(--error-text);
}

.pp-select-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* Zonder dit blijft de knop zo breed als de langste optie: een kind van een flexbox
       mag standaard niet kleiner worden dan zijn inhoud, en dan doen die puntjes niets. */
    min-width: 0;
}

.pp-select-label.is-placeholder {
    color: var(--text-muted);
}

.pp-select-arrow {
    flex: none;
    font-size: 0.75em;
    color: var(--text-muted);
    transition: transform var(--transition);
}

.pp-select.is-open .pp-select-arrow {
    transform: rotate(180deg);
}

.pp-select-panel {
    display: none;
    position: absolute;
    z-index: 60;
    left: 0;
    right: 0;
    top: calc(100% + 4px);
    min-width: 12rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

.pp-select.is-open .pp-select-panel {
    display: block;
}

.pp-select.is-up .pp-select-panel {
    top: auto;
    bottom: calc(100% + 4px);
}

.pp-select-search {
    padding: 0.5rem;
    border-bottom: 1px solid var(--border);
}

.pp-select-search[hidden] {
    display: none;
}

.pp-select-list {
    max-height: 16rem;
    margin: 0;
    padding: 0.25rem;
    overflow-y: auto;
    list-style: none;
}

/* Bolletje of icoon voor een optie: een segmentatie of genre met een eigen kleur */
.pp-select-dot {
    display: inline-block;
    width: 0.7rem;
    height: 0.7rem;
    margin-right: 0.5rem;
    border-radius: 50%;
    vertical-align: baseline;
}

.pp-select-icon {
    width: 1.1rem;
    margin-right: 0.45rem;
    text-align: center;
}

/* Een gezicht (of de initialen) voor een optie: zo herken je een collega sneller
   dan aan zijn achternaam tussen twintig andere */
.pp-select-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 1.35rem;
    height: 1.35rem;
    margin-right: 0.45rem;
    border-radius: 50%;
    overflow: hidden;
    background: var(--bg);
    vertical-align: middle;
}

.pp-select-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.pp-select-avatar-text {
    font-size: 0.6rem;
    font-weight: 700;
    color: var(--text-muted);
}

/* Heeft hij een kleur meegekregen, dan is de achtergrond donker en moeten de
   initialen wit - net als in de avatar zelf */
.pp-select-avatar-text[class*="avatar-color-"] {
    color: #ffffff;
}

/* Het gekleurde icoontje van een module in een keuzelijst */
.pp-select-icon-image {
    flex: none;
    width: 1.1rem;
    height: 1.1rem;
    margin-right: 0.45rem;
    object-fit: contain;
    vertical-align: middle;
}

/* Hetzelfde icoon in een lijst of tabel */
.list-icon {
    width: 1.1rem;
    margin-right: 0.45rem;
    text-align: center;
    color: var(--text-muted);
}

.pp-select-option {
    padding: 0.45rem 0.6rem;
    border-radius: var(--radius);
    cursor: pointer;
}

.pp-select-option[hidden] {
    display: none;
}

.pp-select-option.is-marked {
    background: var(--sidebar-hover);
}

/* Vet, maar niet in de merkkleur: gekleurde tekst in een keuzelijst leest als iets waar
   je naartoe kunt klikken, terwijl het alleen "dit is je keuze" betekent. */
.pp-select-option.is-active {
    font-weight: 600;
}

.pp-select-option.is-disabled {
    color: var(--text-muted);
    cursor: default;
}

.pp-select-group {
    padding: 0.5rem 0.6rem 0.2rem;
    font-size: 0.78rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.pp-select-group[hidden] {
    display: none;
}

.pp-select-empty {
    margin: 0;
    padding: 0.6rem;
    color: var(--text-muted);
}

@media print {
    .pp-select-panel {
        display: none !important;
    }
}

/* --- Bovenbalk: waar ben ik, help, en het account ----------------------- */

.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin: -1.5rem -1.5rem 1.5rem;
    padding: 0.6rem 1.5rem;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    /* Blijft staan bij het scrollen: het accountmenu en de help zijn altijd bereikbaar */
    position: sticky;
    top: 0;
    z-index: 30;
}

.topbar-where {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
    /* De vrije ruimte gaat hierachter zitten: de naam blijft links bij de menuknop,
       en het zoekveld en de knoppen schuiven naar rechts */
    margin-right: auto;
    color: var(--text-muted);
}

.topbar-where strong {
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.topbar-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.topbar-button {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.7rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: transparent;
    color: var(--text-muted);
    font: inherit;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}

.topbar-button:hover {
    background: var(--bg);
    color: var(--text);
}

/* De ideeënknop is een link, geen knop: die krijgt van de browser een onderstreping */
a.topbar-button {
    text-decoration: none;
}

a.topbar-button.is-active {
    background: var(--bg);
    color: var(--text);
}

/* De teller staat strak tegen het icoon aan, niet helemaal rechts zoals in het menu */
.topbar-button .nav-badge {
    margin-left: 0;
}

/* --- Het account: knop met daaronder een menu --------------------------- */

.account {
    position: relative;
}

.account-trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.3rem 0.5rem;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: transparent;
    color: var(--text);
    font: inherit;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition);
}

.account-trigger:hover,
.account-trigger[aria-expanded="true"] {
    background: var(--bg);
    border-color: var(--border);
}

.account-name {
    max-width: 12rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.account-chevron {
    font-size: 0.7rem;
    color: var(--text-muted);
    transition: transform var(--transition);
}

.account-trigger[aria-expanded="true"] .account-chevron {
    transform: rotate(180deg);
}

.account-menu {
    position: absolute;
    top: calc(100% + 0.4rem);
    right: 0;
    min-width: 15rem;
    padding: 0.35rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    z-index: 40;
}

.account-menu form {
    margin: 0;
}

.account-menu-head {
    display: grid;
    gap: 0.1rem;
    padding: 0.6rem 0.7rem;
    border-bottom: 1px solid var(--border);
    margin-bottom: 0.35rem;
    line-height: 1.3;
}

.account-menu-head small {
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
}

.account-menu-item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: 0;
    border-radius: var(--radius);
    background: transparent;
    color: var(--text);
    font: inherit;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--transition);
}

.account-menu-item:hover,
.account-menu-item.is-active {
    background: var(--bg);
    color: var(--text);
}

.account-menu-item i {
    width: 1.1rem;
    text-align: center;
    color: var(--text-muted);
}

.account-menu-logout {
    border-top: 1px solid var(--border);
    margin-top: 0.35rem;
    padding-top: 0.6rem;
    border-radius: 0 0 var(--radius) var(--radius);
}

@media (max-width: 52rem) {
    .topbar {
        margin: -1rem -1rem 1rem;
        padding: 0.5rem 1rem;
    }

    /* De knoppen in de balk zijn alleen nog iconen (met title en aria-label); wat
       hier nog verdwijnt op een smal scherm is je naam naast de avatar. */
    .account-name {
        display: none;
    }
}

/* --- Uitkomst van een analyse ------------------------------------------- */

/* Getallen horen rechts uitgelijnd: dan staan de eenheden, tientallen en honderdtallen
   onder elkaar en zie je in één oogopslag welk getal het grootst is.

   Dit stond eerst alleen binnen .table-numbers, waardoor class="right" in de meeste
   tabellen niets deed - en dat is precies de klasse die overal gebruikt wordt. Nu geldt
   hij overal; tabellen met .table-numbers krijgen er cijfers van gelijke breedte bij,
   zodat kolommen met wisselende getallen niet zitten te dansen. */
td.right,
th.right {
    text-align: right;
}

.table-numbers td.right,
.table-numbers th.right {
    font-variant-numeric: tabular-nums;
}

.bar-cell {
    width: 22%;
    min-width: 6rem;
}

.bar {
    display: block;
    height: 0.6rem;
    width: var(--bar-width, 0);
    background: var(--bar-color, var(--brand-primary));
    border-radius: 999px;
}

/* Een tussenkop in een tabel met kerncijfers: leeftijd, huishoudens, wonen */
.table tr.row-group th {
    padding-top: 1rem;
    color: var(--text-muted);
    font-size: 0.85rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.index-badge {
    display: inline-block;
    min-width: 2.75rem;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: var(--bg);
    font-variant-numeric: tabular-nums;
    /* Het getal in het midden van het pilletje. Zonder dit erft het de rechtse
       uitlijning van de kolom, en dan plakt 53 tegen de rand terwijl 167 vult. */
    text-align: center;
}

.index-badge.is-high {
    background: var(--success-bg);
    color: var(--success-text);
}

.index-badge.is-low {
    background: var(--warning-bg);
    color: var(--warning-text);
}

.map {
    height: 32rem;
    border-radius: var(--radius);
    /* Leaflet tekent zelf een achtergrond; dit voorkomt een witte flits in donker thema */
    background: var(--bg);
}

/* Dezelfde kaart als tegel op het dashboard: lager, want daar staat hij naast andere
   blokken in plaats van dat hij het onderwerp van de pagina is. Hier en niet bij
   .dash-map, omdat het na .map moet staan - anders wint de hoogte van .map. Vergroot
   vult hij alsnog het scherm, want die regel is specifieker. */
.map.is-tile {
    height: 22rem;
}

/* De kaart met het watermerk erop: die twee horen bij elkaar, ook als de kaart groeit.
   isolation: isolate sluit de lagen van Leaflet hierbinnen op. Leaflet legt zijn vlakken
   op 400 en zijn knoppen op 800, en die tellen anders mee op de hele pagina - dan schuift
   bij het scrollen de kaart over de bovenbalk heen. Dit is beter dan de bovenbalk hoger
   zetten: dan begint een wedloop waarin elke laag een nummer hoger moet dan de vorige. */
.map-wrap {
    position: relative;
    isolation: isolate;
}

/* De naam van de omgeving linksonder. Boven de kaartlaag maar onder de bediening van
   Leaflet, en niet aanklikbaar: het is een merk, geen knop. */
.map-watermark {
    position: absolute;
    left: 0.75rem;
    bottom: 0.75rem;
    z-index: 400;
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin: 0;
    padding: 0.15rem 0.5rem;
    border-radius: var(--radius);
    background: color-mix(in srgb, var(--surface) 78%, transparent);
    color: var(--text-muted);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    pointer-events: none;
}

/* Een kaart binnen het blok van een gebied: geen eigen kaart eromheen, want de kaart,
   de naam en de tabel gaan over hetzelfde gebied en staan in één blok. */
.map-block {
    margin: 0.75rem 0 1.25rem;
}

/* Het gezicht van een locatie naast zijn naam in een tabelcel. Zonder dit staat het logo
   op een eigen regel en wordt elke rij twee keer zo hoog. */
.location-cell {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}

/* De tegels boven een gebiedsanalyse: waar dit rapport over gaat, in één oogopslag.
   Het silhouet is een SVG van de omtrek - geen kaart, dus geen tegels van een provider
   en geen tweede Leaflet-exemplaar per gebied. */
.area-tiles {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    /* Ruimte onder de tegels: de knoppen eronder stonden er tegenaan, en bij een tegel
       waarvan de regel afbreekt liep het door elkaar heen */
    margin: 1rem 0 1.5rem;
    padding: 0;
    list-style: none;
}

/* Een tegel is meestal een link naar het blok eronder, maar niet altijd: bij "Waar ze
   vandaan komen" is er niets om heen te springen en is het puur een plaatje bij een
   getal. Dezelfde vorm, alleen zonder het klikgedrag. */
.area-tiles a,
.area-tiles .area-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 0.15rem;
    width: 8.5rem;
    /* Allemaal even hoog, ook als de ene naam afbreekt en de andere niet */
    height: 100%;
    padding: 0.75rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--text);
    text-align: center;
    text-decoration: none;
}

/* De tegel van de plaats waarop nu gefilterd wordt. Een filter dat aanstaat hoort te
   zien te zijn, anders vraag je je af waarom de lijst zo kort is. */
.area-tiles a.is-active {
    border-color: var(--brand-primary);
    box-shadow: inset 0 0 0 1px var(--brand-primary);
}

.area-tiles a:hover {
    border-color: var(--brand-primary);
    background: var(--surface);
}

.area-tiles li {
    display: flex;
}

.area-tiles strong {
    font-size: 0.9rem;
}

.area-tiles small {
    font-size: 0.7rem;
    line-height: 1.3;
}

.area-tile-shape {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 3.5rem;
    margin-bottom: 0.25rem;
    color: var(--brand-primary);
}

/* De omtrek zelf: gevuld in de merkkleur, met een iets donkerder rand eromheen zodat
   twee gebieden die aan elkaar grenzen niet aan elkaar plakken. */
.area-outline {
    width: 3.5rem;
    height: 3.5rem;
}

.area-outline path {
    fill: color-mix(in srgb, var(--brand-primary) 22%, transparent);
    stroke: var(--brand-primary);
    stroke-width: 1.2;
    stroke-linejoin: round;
}

/* Ons beeldmerk voor de naam, op de hoogte van de letters ernaast */
.map-watermark-icon {
    width: 0.85rem;
    height: 0.85rem;
    flex: none;
}

/* Vergroot: de kaart vult het scherm. Een vaste plek in plaats van de Fullscreen-API,
   want die geeft een zwarte rand om een lichte pagina en werkt niet in een iframe.
   Op [data-map-card] en niet op .card, want een kaart in een blok is geen kaart. */
[data-map-card].is-map-full {
    position: fixed;
    inset: 0;
    z-index: 1200;
    margin: 0;
    padding: 0;
    border-radius: 0;
    background: var(--bg);
    overflow: hidden;
}

/* Vergroot vult de kaart het hele scherm en loopt hij onder de bediening door. Daarvoor
   stond de bediening in een witte strook erboven, met een leeg vlak ernaast dat nergens
   voor diende. */
[data-map-card].is-map-full .map-wrap,
[data-map-card].is-map-full .map,
[data-map-card].is-map-full .pin-map {
    height: 100vh;
    border-radius: 0;
}

/* De knoppen en de legenda zweven erover als matglas: je ziet de kaart eronder
   doorlopen, en de tekst blijft leesbaar doordat er een waas achter zit. */
[data-map-card].is-map-full .toolbar,
[data-map-card].is-map-full .map-legend {
    position: absolute;
    left: 0;
    right: 0;
    z-index: 1100;
    margin: 0;
    padding: 0.6rem 1rem;
    background: color-mix(in srgb, var(--surface) 58%, transparent);
    -webkit-backdrop-filter: blur(14px) saturate(1.2);
    backdrop-filter: blur(14px) saturate(1.2);
}

[data-map-card].is-map-full .toolbar {
    top: 0;
    border-bottom: 1px solid var(--border);
}

[data-map-card].is-map-full .map-legend {
    bottom: 0;
    border-top: 1px solid var(--border);
}

/* De zoomknoppen van Leaflet staan linksboven, precies waar nu de balk zit */
[data-map-card].is-map-full .leaflet-top {
    margin-top: 3.4rem;
}

/* En het watermerk boven de legenda in plaats van eronder */
[data-map-card].is-map-full .map-watermark {
    bottom: 3.6rem;
}

/* De introzin hoort bij de pagina, niet bij een kaart die het scherm vult */
[data-map-card].is-map-full > .muted {
    display: none;
}

/* De pagina eronder mag niet meeschuiven als je in de vergrote kaart scrolt */
body.has-map-full {
    overflow: hidden;
}

/* De keuzelijst hoort bij het keuzerondje erboven, dus hij staat ingesprongen: zo lees je
   dat het een verfijning is van die keuze en geen losse vraag. */
.compare-area {
    margin-left: 1.6rem;
    max-width: 24rem;
}

/* De legenda die tegelijk de bediening is: een uitgezette doelgroep wordt grijs */
.map-legend-toggle {
    flex-wrap: wrap;
}

.legend-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.15rem 0.4rem;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: inherit;
    font: inherit;
    font-size: 0.8rem;
    cursor: pointer;
}

.legend-toggle:hover {
    background: var(--bg);
}

.legend-toggle[aria-pressed="false"] {
    color: var(--text-muted);
    text-decoration: line-through;
}

.legend-toggle[aria-pressed="false"] .legend-swatch {
    opacity: 0.3;
}

.zip-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.zip-chip {
    padding: 0.1rem 0.45rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
}

/* Lijst met aanvinkbare keuzes die in kolommen past, zoals segmenten of provincies */
.option-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
    gap: 0.25rem 1.5rem;
    margin-bottom: 1rem;
}

.option-grid .checkbox small {
    display: block;
}

/* Lopende tekst die een beheerder zelf heeft ingevoerd, zoals de disclaimer */
.prose {
    max-width: 60rem;
    line-height: 1.65;
}

.prose p {
    margin: 0 0 1rem;
}

.prose ul,
.prose ol {
    margin: 0 0 1rem 1.25rem;
}

.prose a {
    text-decoration: underline;
}

/* Een keuze met een lange zin ernaast leest prettiger als de bol bovenaan blijft staan */
.form .fieldset label.checkbox {
    align-items: flex-start;
    margin-bottom: 0.75rem;
    line-height: 1.5;
}

.form .fieldset label.checkbox input {
    margin-top: 0.25rem;
}

/* Optionele stappen in een formulier, ingeklapt.
   Een <details> doet het werk: hij werkt zonder JavaScript, onthoudt zijn stand tijdens
   het invullen, en de server kan hem open zetten als er al iets is ingevuld. */
.more-options {
    margin: 0 0 1.5rem;
}

.more-options > summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.7rem 1rem;
    border: 1px dashed var(--border);
    border-radius: var(--radius);
    color: var(--text-muted);
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}

.more-options > summary::-webkit-details-marker {
    display: none;
}

/* Het pijltje zelf, zodat hij in beide browsers hetzelfde staat en meedraait */
.more-options > summary::after {
    content: "\f078";
    margin-left: auto;
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    font-size: 0.75rem;
    transition: transform var(--transition);
}

.more-options[open] > summary::after {
    transform: rotate(180deg);
}

.more-options > summary:hover {
    border-color: var(--brand-primary);
    color: var(--brand-primary);
}

.more-options[open] > summary {
    margin-bottom: 1rem;
    border-style: solid;
    color: var(--text);
}

/* Een blok in een formulier. Met een eigen achtergrond leest het als een stap in
   plaats van als een streep om wat velden heen: je ziet in een oogopslag uit hoeveel
   stukken het formulier bestaat. */
.fieldset {
    margin: 0 0 1.5rem;
    padding: 1.1rem 1.25rem 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
}

/* De kop van zo'n blok: klein maar in kapitalen en in de merkkleur. Dat leest als een
   kopje en niet als nog een veldnaam - bij een formulier met vier blokken is dat het
   verschil tussen overzicht en een muur. */
.fieldset legend {
    margin-left: -0.25rem;
    padding: 0.2rem 0.6rem;
    border-radius: var(--radius);
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--brand-primary);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* Twee velden onder elkaar in zo'n blok hebben lucht nodig: anders plakt de naam van
   het ene veld tegen de uitleg onder het vorige, en lees je die uitleg als een kopje.
   Het eerste veld niet: dat staat al onder de legenda. */
.fieldset > * + * {
    margin-top: 1rem;
}

.fieldset > legend + * {
    margin-top: 0;
}

/* Een veld dat nu niet aan de beurt is (de periode bij een jaartotaal): grijs, maar wel
   leesbaar. Weghalen zou erger zijn - dan springt het formulier bij elk vinkje. */
.field-off {
    opacity: 0.55;
}

/* De velden zelf staan op de kaart, niet op de grijze ondergrond: dat geeft de diepte */
.fieldset input[type="text"],
.fieldset input[type="search"],
.fieldset input[type="date"],
.fieldset input[type="number"],
.fieldset select,
.fieldset textarea {
    background: var(--surface);
}

.form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

/* Knoppen onderaan een blok die naar rechts horen, zoals downloaden onder een kaart */
.form-actions-right {
    justify-content: flex-end;
    margin-top: 0.75rem;
}

/* Zoeken en filteren boven een lijst: de velden naast elkaar in plaats van onder elkaar */
.form-inline {
    grid-auto-flow: column;
    grid-auto-columns: max-content;
    align-items: end;
}

.form-inline .form-actions {
    align-self: end;
}

@media (max-width: 40rem) {
    .form-inline {
        grid-auto-flow: row;
        grid-auto-columns: auto;
    }
}

/* Een kleurstip voor een segmentatie; de kleur zelf zet JavaScript (CSP) */
/* Geen randje: de kleur van een doelgroep is de kleur van een doelgroep. Een rand eromheen
   maakt er een badge van en vertroebelt juist de kleur die je wilt herkennen. */
.color-dot {
    display: inline-block;
    width: 0.9rem;
    height: 0.9rem;
    border-radius: 50%;
    vertical-align: -0.1rem;
    margin-right: 0.35rem;
}

/* Een knop in een tabelcel: het formulier eromheen mag geen regel opeisen */
/* ── Meldingen ───────────────────────────────────────────────────────────────
   Een regel per melding: het icoon zegt wat voor soort, de tekst wat er is, en rechts
   kun je hem weghalen. Ongelezen krijgt een streepje in de huisstijlkleur - geen vet en
   geen kleurvlak, want dan schreeuwt een lijst van twintig meldingen allemaal tegelijk. */
.notification-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.notification {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    padding: 0.85rem 0.85rem 0.85rem 0.6rem;
    border-bottom: 1px solid var(--border);
    border-left: 3px solid transparent;
}

.notification:last-child {
    border-bottom: 0;
}

.notification.is-new {
    border-left-color: var(--brand-primary);
    background: color-mix(in srgb, var(--brand-primary) 4%, transparent);
}

.notification-icon {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background: var(--bg);
    color: var(--text-muted);
}

.notification-icon.notification-success { color: var(--success-text); background: var(--success-bg); }
.notification-icon.notification-warning { color: var(--warning-text); background: var(--warning-bg); }
.notification-icon.notification-error { color: var(--error-text); background: var(--error-bg); }

.notification-body {
    flex: 1;
    min-width: 0;
}

.notification-body p {
    margin: 0.2rem 0 0;
}

.notification-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.9rem;
}

.notification-dismiss {
    flex: none;
}

/* Het onderschrift bij de foto op het inlogscherm: waar de foto over gaat. Rechtsonder,
   over de foto heen, met een donker vlak eronder zodat het leesbaar blijft op een lichte
   foto. Staat er geen onderschrift, dan staat er niets. */
.login-caption {
    position: fixed;
    right: 1.25rem;
    bottom: 3.5rem;
    z-index: 1;
    max-width: min(28rem, calc(100vw - 2.5rem));
    margin: 0;
    padding: 0.45rem 0.8rem;
    border-radius: 999px;
    background: rgba(15, 23, 34, 0.55);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    color: #ffffff;
    font-size: 0.85rem;
    line-height: 1.3;
}

@media (max-width: 45rem) {
    .login-caption {
        display: none;
    }
}

/* Het knopje dat bij een selectie verschijnt: "Zoeken". Het zweeft boven de tekst, dus
   het heeft een eigen laag nodig; waar het staat zet het script zelf, want dat hangt van
   je selectie af. */
.selection-search {
    position: absolute;
    z-index: 60;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    box-shadow: 0 4px 14px rgba(15, 23, 34, 0.18);
    color: var(--text);
    font-size: 0.85rem;
    text-decoration: none;
    white-space: nowrap;
}

.selection-search:hover {
    border-color: var(--brand-primary);
    color: var(--brand-primary);
}

/* In een afdruk heeft een zoekknop niets te zoeken */
@media print {
    .selection-search {
        display: none;
    }
}

/* Het totaal van een verdeling dat niet uitkomt op waar het heen moet. Geen rood vlak:
   het is geen fout tot je op opslaan drukt, maar je hoort het wel te zien terwijl je typt. */
[data-pie-total].is-off {
    color: var(--warning-text);
}

/* Een knopregel met een zin ernaast: de uitleg links, de knop rechts. Onder een tabel
   met rechts uitgelijnde getallen leest een knop die links tegen de rand plakt als iets
   dat er per ongeluk staat. */
.form-actions-split {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
}

.form-actions-split p {
    margin: 0;
}

.form-row-action {
    display: inline;
}

/* Een lange keuzelijst die niet de hele pagina mag vullen, zoals bestedingscategorieën */
.scroll-box {
    max-height: 28rem;
    overflow-y: auto;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
}

/* De categorieën zitten in een boom; de diepte laten we zien met inspringen */
.category-level-2 { padding-left: 1.25rem; }
.category-level-3 { padding-left: 2.5rem; }
.category-level-4 { padding-left: 3.75rem; }

/* Een smal getalveld in een tabel, bijvoorbeeld een index per segment */
.input-narrow {
    width: 7rem;
    text-align: right;
}

.form-inline-link {
    margin-top: 1rem;
    text-align: center;
}

.table {
    width: 100%;
    border-collapse: collapse;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

/* Eén maat voor alles in een tabel. De kop was kleiner dan de rijen eronder, en
   omdat niet elke tabel een kop heeft, leek de ene tabel groter dan de andere op
   dezelfde pagina. Een kop onderscheidt zich nu aan kleur en achtergrond, niet aan
   grootte - dat leest rustiger en het schaalt mee. */
.table {
    font-size: var(--text-ui);
}

.table th,
.table td {
    padding: 0.6rem 0.8rem;
    border-bottom: 1px solid var(--border);
    text-align: left;
    vertical-align: top;
}

.table th {
    font-weight: 600;
    color: var(--text-muted);
    background: var(--bg);
}

/* Getallen en bedragen rechts. Dit moet hier staan, ná de regel hierboven die alle cellen
   links zet: `td.right` en `.table td` wegen even zwaar, en dan wint wie het laatst komt.
   Daar ging het eerder mis - de klasse stond er wel, maar deed in een gewone tabel niets. */
.table th.right,
.table td.right,
.table th.num,
.table td.num {
    text-align: right;
}

.table-actions {
    text-align: right;
    white-space: nowrap;
}

.table-actions form {
    display: inline;
}

/* --- Changelog ---------------------------------------------------------- */

.update-list {
    list-style: none;
    margin: 0;
    padding: 0;
    max-width: 48rem;
}

.update {
    padding: 1.25rem 1.5rem;
    margin-bottom: 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.update.is-new {
    box-shadow: inset 4px 0 0 var(--accent);
}

.update-meta {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.5rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.update p {
    margin: 0;
}

/* --- Two-factor --------------------------------------------------------- */

.steps {
    display: grid;
    gap: 1.25rem;
    padding-left: 1.25rem;
}

.qr {
    width: 196px;
    margin: 0.75rem 0;
    padding: 0.5rem;
    background: #ffffff;
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.secret {
    letter-spacing: 0.1em;
    font-size: 1rem;
}

.code-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
    gap: 0.5rem;
    list-style: none;
    padding: 0;
    margin: 0 0 1.25rem;
}

.code-list code {
    display: block;
    padding: 0.5rem;
    text-align: center;
    font-size: 1rem;
}

/* --- Login and plain pages ---------------------------------------------- */

.login-page,
.plain-page {
    display: grid;
    place-items: center;
    min-height: 100vh;
    padding: 1.5rem 1rem;
}

.login-background {
    position: fixed;
    inset: 0;
    z-index: -1;
    background-size: cover;
    background-position: center;
}

/* Met een eigen achtergrond loopt de foto over het hele scherm en ligt het formulier
   erop als matglas. Daarvoor stond er een harde deling: wit vlak links, foto rechts.
   Die naad trok de aandacht naar zichzelf, terwijl de foto juist het eerste is wat
   iemand van deze klant ziet.

   Het paneel is niet doorzichtig maar mat: de foto blijft zichtbaar, de tekst blijft
   leesbaar. De rechterrand lost op in de foto, zodat er geen lijn meer is. */
.login-page.has-background {
    display: grid;
    grid-template-columns: minmax(22rem, 30rem) 1fr;
    /* place-items van .login-page overschrijven: anders krimpt het paneel naar nul breedte */
    place-items: stretch;
    padding: 0;
}

/* De rand tussen paneel en foto is een strakke lijn. Een vervagende naad hebben we
   geprobeerd en die trok juist de aandacht naar zichzelf.

   Het doorkijkje zit in het witte vlak zelf, en alleen onderin: bovenaan staat het
   formulier en dat hoort gewoon leesbaar te zijn, onderin is het leeg en mag de foto er
   vaag doorheen komen. Eerst de effen kleur als terugval - kent een browser color-mix
   niet, dan valt alleen het verloop weg en blijft het paneel dicht. */
.login-page.has-background .login-card {
    max-width: none;
    min-height: 100vh;
    /* Onderaan ruimte voor de voetbalk, die over de volle breedte onder het paneel
       door loopt */
    padding: 2.5rem 2.5rem 4rem;
    border-radius: 0;
    box-shadow: none;
    /* De effen kleur eerst, als terugval voor een browser die color-mix niet kent: dan
       is het paneel gewoon dicht en blijft alles leesbaar. */
    background: var(--surface);
    /* En daarna het matglas: helemaal dicht bovenaan, waar het logo en het formulier
       staan, en naar onderen toe steeds doorzichtiger. Het paneel is dan geen wit blok
       vóór de foto maar een ruit erin - je ziet waar je bent, zonder dat er iets
       leeswerk wordt. */
    background: linear-gradient(
        180deg,
        /* Het bovenste stuk helemaal dicht, en in pixels en niet in procenten: daar
           staat het logo van de omgeving, en dat heeft vaak zelf een witte achtergrond.
           Elk kleurverschil tussen dat blokje en het paneel eromheen zie je meteen, en
           dan lijkt het logo er los op geplakt. Pas daaronder begint het doorkijkje. */
        var(--surface) 0,
        var(--surface) 270px,
        color-mix(in srgb, var(--surface) 88%, transparent) 45%,
        color-mix(in srgb, var(--surface) 70%, transparent) 75%,
        color-mix(in srgb, var(--surface) 55%, transparent) 100%);
    /* Zonder waas leest de foto door de tekst heen; hiermee blijft het een ondergrond */
    -webkit-backdrop-filter: blur(22px) saturate(1.2);
    backdrop-filter: blur(22px) saturate(1.2);
    position: relative;
}

/* De foto vult het hele scherm en ligt onder het paneel door */
.login-page.has-background .login-background {
    position: fixed;
    inset: 0;
    z-index: -1;
}

.login-page.has-background .login-brand {
    text-align: left;
    padding-bottom: 1.25rem;
    border-bottom: 1px solid var(--border);
}

/* Smal scherm: de foto valt weg, het paneel wordt de hele breedte. Dan is er niets
   meer om in op te lossen, dus de vervagende rand en de extra ruimte rechts gaan eruit -
   anders staat het formulier scheef op een telefoon. */
@media (max-width: 54rem) {
    .login-page.has-background {
        grid-template-columns: 1fr;
    }

    .login-page.has-background .login-background {
        display: none;
    }

    /* Zonder foto valt er niets doorheen te kijken, dus het verloop gaat eruit: anders
       zou het paneel onderin oplichten op de gewone paginakleur, en dat is geen effect
       maar een vlek */
    .login-page.has-background .login-card {
        padding: 2.5rem 1.5rem 4rem;
        background: var(--surface);
    }
}

.login-card,
.plain-card {
    width: 100%;
    max-width: 26rem;
    padding: 2rem;
    background: var(--surface);
    border-radius: var(--radius);
    box-shadow: 0 10px 40px rgba(27, 42, 65, 0.15);
}


.login-brand {
    margin-bottom: 1.5rem;
    text-align: center;
}

.login-brand img {
    background: var(--logo-bg);
    border-radius: var(--radius);
    padding: 0.25rem;
    max-width: 14rem;
    max-height: 4rem;
}

.login-divider {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 1rem 0;
    color: var(--text-muted);
    font-size: 0.85rem;
}

.login-divider::before,
.login-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--border);
}

.login-footer {
    margin: 1.5rem 0 0;
    font-size: 0.85rem;
    text-align: center;
}

.plain-actions {
    margin: 1.5rem 0 0;
}

/* --- Help panel --------------------------------------------------------- */

.help-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(27, 42, 65, 0.28);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    z-index: 2050;
}

.help-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    /* Breder dan eerst: met een index ernaast en zinnen van normale lengte lees je
       de help niet meer door een kier. */
    width: min(36rem, 100vw);
    display: flex;
    flex-direction: column;
    background: var(--surface);
    box-shadow: -8px 0 30px rgba(27, 42, 65, 0.2);
    z-index: 2100;
}

/* Groot: een venster over bijna het hele scherm, met de index als eigen kolom. Voor
   wie de help erbij houdt terwijl hij werkt. */
.help-panel.is-expanded {
    top: 5vh;
    right: 5vw;
    bottom: 5vh;
    left: 5vw;
    width: auto;
    border-radius: var(--radius);
    box-shadow: 0 20px 60px rgba(15, 23, 34, 0.35);
}

.help-layout {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1;
}

.help-panel.is-expanded .help-layout {
    flex-direction: row;
}

/* De index: in het smalle paneel een kort lijstje bovenaan, in het grote venster een
   kolom die blijft staan terwijl je leest. */
.help-index {
    flex: none;
    max-height: 9rem;
    overflow-y: auto;
    padding: 0.5rem 1.25rem;
    border-bottom: 1px solid var(--border);
    background: var(--bg);
}

.help-panel.is-expanded .help-index {
    width: 17rem;
    max-height: none;
    border-bottom: 0;
    border-right: 1px solid var(--border);
    padding: 1rem 1rem 2rem;
}

.help-index:empty {
    display: none;
}

.help-index-list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 0.1rem;
}

.help-index-list a {
    display: block;
    padding: 0.3rem 0.5rem;
    border-radius: var(--radius);
    color: var(--text-muted);
    font-size: 0.85rem;
    text-decoration: none;
}

.help-index-list a:hover {
    background: var(--surface);
    color: var(--text);
}

.help-panel.is-expanded .help-index-list a:hover {
    background: var(--bg);
}

.help-index-list a.is-active {
    background: var(--brand-primary);
    color: #fff;
    font-weight: 600;
}

.help-header {
    display: flex;
    align-items: center;
    gap: 0.15rem;
    padding: 1rem 1.25rem 0.5rem;
}

/* De titel duwt de twee knoppen naar rechts; groter maken en sluiten horen bij elkaar,
   en niet los van elkaar over de balk verdeeld */
.help-header h2 {
    margin: 0 auto 0 0;
}

.help-search {
    padding: 0 1.25rem 0.75rem;
    border-bottom: 1px solid var(--border);
}

.help-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 1rem 1.25rem 3rem;
}

/* In het grote venster leest een regel van honderd tekens niet prettig */
.help-panel.is-expanded .help-body {
    padding: 1.5rem 2rem 3rem;
}

.help-panel.is-expanded .help-section {
    max-width: 52rem;
}

.help-section {
    padding-bottom: 1.25rem;
    margin-bottom: 1.25rem;
    border-bottom: 1px solid var(--border);
}

.help-intro {
    color: var(--text-muted);
}

.help-tips {
    padding-left: 1.25rem;
    color: var(--text-muted);
    font-size: 0.9rem;
}

.help-faq,
.help-tech {
    margin: 0.5rem 0;
    padding: 0.5rem 0.75rem;
    background: var(--bg);
    border-radius: var(--radius);
}

.help-faq summary,
.help-tech summary {
    cursor: pointer;
    font-weight: 600;
}

.help-tech {
    border-left: 3px solid var(--accent);
}

body.help-open {
    overflow: hidden;
}

/* --- Avatars ------------------------------------------------------------ */

.avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    border-radius: 50%;
    object-fit: cover;
    font-weight: 700;
    color: #ffffff;
    line-height: 1;
    user-select: none;
}

.avatar-sm { width: 1.5rem; height: 1.5rem; font-size: 0.65rem; }
.avatar-md { width: 2.25rem; height: 2.25rem; font-size: 0.85rem; }
.avatar-lg { width: 4.5rem; height: 4.5rem; font-size: 1.6rem; }

.avatar-color-0 { background: #1f5fae; }
.avatar-color-1 { background: #2e8b7e; }
.avatar-color-2 { background: #8a5cc2; }
.avatar-color-3 { background: #c2553d; }
.avatar-color-4 { background: #b07d12; }
.avatar-color-5 { background: #3b7d2f; }
.avatar-color-6 { background: #b8457a; }
.avatar-color-7 { background: #4a5a70; }

.user-cell {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.sidebar-user-link .avatar {
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.25);
}

.avatar-editor {
    display: flex;
    gap: 1.25rem;
    align-items: flex-start;
    flex-wrap: wrap;
}

.avatar-editor .form {
    flex: 1 1 14rem;
}

.profile-header {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.profile-header p {
    margin: 0 0 0.25rem;
}

.profile-name {
    font-size: 1.15rem;
    font-weight: 700;
}

/* --- Toolbars, tabs, details -------------------------------------------- */

.toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem;
    margin-bottom: 1.25rem;
}

/* Een kop in de werkbalk: dan staan de knoppen ernaast in plaats van eronder. De marge
   eraf, anders duwt hij de knoppen scheef. */
.toolbar h2 {
    margin: 0;
}

/* Een blok op het scherm Datakwaliteit. De ernst staat als streep aan de linkerkant:
   je ziet in één blik of je van boven naar beneden moet werken of dat het tips zijn. */
.quality-card {
    border-left: 4px solid var(--border);
}

.quality-card-error { border-left-color: var(--error-text); }
.quality-card-warning { border-left-color: var(--warning-text); }
.quality-card-info { border-left-color: var(--border); }

/* De locaties onder een kwestie: elk als eigen chip, met de plaats erin. Zonder dit
   liepen de namen in elkaar over en was het één regel tekst waarin je niets terugvindt. */
.quality-chips {
    gap: 0.4rem;
    margin: 0.75rem 0 0;
    padding: 0;
    list-style: none;
}

.quality-chips .chip {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    padding: 0.25rem 0.7rem;
    color: var(--text);
}

.quality-chips .chip-sub {
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* Een levering die klaarstaat maar nog niet is ingelezen. Uit elkaar gehouden met een
   lijn, want het zijn er soms vier en ze lijken op elkaar. */
.source-new {
    padding: 0.75rem 0;
    border-top: 1px solid var(--border);
}

.source-new:first-of-type {
    border-top: 0;
}

/* Een getal met een sterretje: het klopt niet helemaal, en de titel zegt waarom. Zonder
   opmaak leest het sterretje als een typefout. */
.muted-mark {
    cursor: help;
    border-bottom: 1px dotted var(--border);
}

/* De ernst van een kwestie op het scherm Datakwaliteit. Kleur alleen op het icoontje:
   een hele kop in rood leest als een storing, terwijl het om een leeg veld gaat. */
.quality-error { color: var(--error-text); }
.quality-warning { color: var(--warning-text); }
.quality-info { color: var(--text-muted); }

/* Het strookje boven een kaart waarop je het niveau kiest: op één regel, met de tekst
   ernaast in plaats van erboven. */
.map-levels {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-bottom: 0.75rem;
}

/* De knoppen in het venstertje van een kaart waarop je gebieden kiest */
.map-pick-actions {
    display: flex;
    gap: 0.4rem;
    margin-top: 0.6rem;
}

.toolbar .btn-primary,
.toolbar .toolbar-end {
    margin-left: auto;
}

/* Staan ze er allebei, dan schuift alleen de eerste naar rechts en sluit de tweede
   daarop aan - anders duwen ze elkaar uit elkaar */
.toolbar .btn-primary ~ .toolbar-end {
    margin-left: 0;
}

.toolbar-search {
    display: flex;
    gap: 0.5rem;
}

.toolbar-search input {
    min-width: 16rem;
}

/* Een strook tabbladen. Twee vormen met dezelfde opmaak: links (?tab=, een nieuwe
   pagina) en knoppen (wisselen zonder laden, zie assets/js/list.js). Met <ul> eromheen
   hebben de items geen opsommingsteken en geen eigen breedte nodig. */
.tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin: 0 0 1.5rem;
    padding: 0;
    border-bottom: 1px solid var(--border);
    list-style: none;
}

.tabs li {
    display: contents;
}

.tabs a {
    padding: 0.6rem 1rem;
    border-bottom: 3px solid transparent;
    color: var(--text-muted);
    font-weight: 600;
    text-decoration: none;
    transition: color var(--transition), border-color var(--transition);
}

.tabs a:hover {
    color: var(--text);
}

.tabs a.is-active {
    border-bottom-color: var(--brand-primary);
    color: var(--text);
}

.tabs button {
    padding: 0.6rem 1rem;
    border: 0;
    border-bottom: 3px solid transparent;
    background: none;
    color: var(--text-muted);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: color var(--transition), border-color var(--transition);
}

.tabs button:hover {
    color: var(--text);
}

.tabs button.is-active {
    border-bottom-color: var(--brand-primary);
    color: var(--text);
}

.details {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.4rem 1.25rem;
    margin: 1rem 0 0;
    font-size: var(--text-ui);
}

.details dt {
    color: var(--text-muted);
}

.details dd {
    margin: 0;
}

.details-inline {
    margin-bottom: 1.25rem;
}

.form-card {
    max-width: 40rem;
}

.form-block {
    padding-bottom: 1rem;
    margin-bottom: 1rem;
    border-bottom: 1px solid var(--border);
}

.form-block:last-child {
    border-bottom: 0;
    margin-bottom: 0;
    padding-bottom: 0;
}

.card-danger {
    border-color: var(--danger-border);
}

.link-box code {
    display: block;
    padding: 0.75rem;
    word-break: break-all;
    user-select: all;
}

.input-affix {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.input-affix span {
    color: var(--text-muted);
    font-weight: 400;
    white-space: nowrap;
}

.checkbox-inline {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 400;
    font-size: 0.85rem;
}

input[type="color"] {
    width: 4rem;
    height: 2.4rem;
    padding: 0.15rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

input[type="date"] {
    width: 100%;
    padding: 0.5rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font: inherit;
}

/* Een leeg datumveld schrijft er zelf "dd-mm-jjjj" in. Dat is een aanwijzing en geen
   datum, dus grijs - dezelfde kleur als de tekst in een keuzelijst waar nog niets
   gekozen is. list.js zet de klasse; zonder JavaScript blijft het zoals de browser het
   tekent en werkt alles gewoon. */
input[type="date"].is-empty {
    color: var(--text-muted);
}

textarea.code {
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 0.85rem;
}

.upload-field {
    display: grid;
    gap: 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0.75rem 1rem 1rem;
}

.upload-field legend {
    padding: 0 0.3rem;
    font-weight: 600;
    font-size: 0.9rem;
}

.upload-preview {
    max-width: 16rem;
    max-height: 6rem;
    object-fit: contain;
    background: var(--logo-bg);
    border-radius: var(--radius);
}

.check-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
    gap: 0.75rem;
}

.form .check-card {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    padding: 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-weight: 400;
    cursor: pointer;
    transition: border-color var(--transition);
}

.check-card:hover {
    border-color: var(--brand-primary);
}

.check-card span {
    display: grid;
    gap: 0.25rem;
}

.check-card .tag {
    justify-self: start;
}

.setting {
    display: grid;
    gap: 0.3rem;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--border);
}

.setting:last-child {
    border-bottom: 0;
}

.setting.has-error input,
.setting.has-error textarea {
    border-color: var(--error-text);
}

.text-error {
    color: var(--error-text);
}

.nowrap {
    white-space: nowrap;
}

.tag-warning, .tag-tenant-demo, .tag-status-logged { background: var(--warning-bg); color: var(--warning-text); }
.tag-tenant-active, .tag-status-sent { background: var(--success-bg); color: var(--success-text); }
.tag-tenant-inactive, .tag-status-failed { background: var(--error-bg); color: var(--error-text); }
.tag-custom { background: var(--info-bg); color: var(--info-text); }

.banner-with-action {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}

.banner-with-action form {
    margin: 0;
}

.btn-small {
    padding: 0.3rem 0.7rem;
    font-size: 0.85rem;
}

.btn.is-disabled {
    opacity: 0.45;
    pointer-events: none;
}

/* --- Log pages ---------------------------------------------------------- */

.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: 1rem;
    margin-bottom: 1.25rem;
}

.kpi {
    display: grid;
    gap: 0.25rem;
    padding: 1rem 1.25rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    text-decoration: none;
    transition: border-color var(--transition);
}

a.kpi:hover {
    border-color: var(--brand-primary);
    color: var(--text);
}

/* Een kerncijfer waarmee je filtert: je moet kunnen zien dat het aanstaat, anders is het
   een knop die iets doet zonder dat je merkt wat. */
.kpi-link.is-active {
    border-color: var(--brand-primary);
    box-shadow: inset 0 0 0 1px var(--brand-primary);
}

.kpi-label {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.kpi-value {
    font-size: 1.5rem;
    font-weight: 700;
}

/* Regel onder het getal: waar het over gaat, of waartegen het is afgezet */
.kpi-note {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.kpi-warning { box-shadow: inset 4px 0 0 var(--accent); }
.kpi-danger { box-shadow: inset 4px 0 0 var(--error-text); }

.filter-layout {
    display: grid;
    grid-template-columns: 16rem 1fr;
    gap: 1.5rem;
    align-items: start;
}

.filter-panel {
    position: sticky;
    top: 1rem;
    padding: 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.filter-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.filter-period {
    display: grid;
    gap: 0.4rem;
    border: 0;
    padding: 0;
    margin: 0;
}

.filter-period legend {
    font-weight: 600;
    font-size: 0.9rem;
    margin-bottom: 0.3rem;
}

.chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.chip {
    padding: 0.15rem 0.6rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: 0.8rem;
    color: var(--text-muted);
    text-decoration: none;
}

.chip.is-active,
.chip:hover {
    border-color: var(--brand-primary);
    color: var(--brand-primary);
}

.filter-main {
    min-width: 0;
}

/* Een brede tabel schuift opzij in plaats van de pagina uit te rekken. Twee dingen
   maken dat bruikbaar:

   - de kopregel blijft aan de bovenkant plakken terwijl je naar beneden leest, zodat
     je bij regel veertig nog weet welke kolom je ziet;
   - de eerste kolom blijft links staan terwijl je opzij schuift, zodat je bij kolom
     twaalf nog weet over welke regel het gaat.

   De kop plakt aan dit blok en niet aan het scherm. Dat is geen keuze: een blok met
   `overflow-x: auto` is volgens de regels zelf het schuifgebied van wat erin staat, ook
   omhoog en omlaag. Zolang dat blok geen hoogte heeft valt daar verticaal niets te
   schuiven en blijft `position: sticky` gewoon stilstaan - de kop leek dan niet te
   werken. Met een maximumhoogte schuift een lange tabel in zijn eigen kader en blijft de
   kop staan waar hij hoort. Een tabel die past merkt er niets van. */
.table-scroll {
    overflow-x: auto;
    overflow-y: auto;
    max-height: calc(100vh - 11rem);

    /* Valt er opzij iets te schuiven, dan hoort dat te zien te zijn. Vier lagen: twee
       die de rand afdekken met de achtergrondkleur en met de inhoud meeschuiven
       (`local`), en twee schaduwen die blijven staan (`scroll`). Staat de tabel helemaal
       links, dan schuift de linkerafdekking over de linkerschaduw heen en zie je hem
       niet; zodra je schuift komt hij tevoorschijn. Puur CSS, geen script dat mee moet
       tellen tijdens het scrollen. */
    background-image:
        linear-gradient(to right, var(--surface), rgba(255, 255, 255, 0)),
        linear-gradient(to left, var(--surface), rgba(255, 255, 255, 0)),
        linear-gradient(to right, rgba(15, 23, 34, 0.22), rgba(255, 255, 255, 0)),
        linear-gradient(to left, rgba(15, 23, 34, 0.22), rgba(255, 255, 255, 0));
    background-position: left center, right center, left center, right center;
    background-repeat: no-repeat;
    background-size: 2.5rem 100%, 2.5rem 100%, 1.4rem 100%, 1.4rem 100%;
    background-attachment: local, local, scroll, scroll;
}

.table-scroll .table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
}

/* ── Een tabel op volledig scherm ────────────────────────────────────────────
   Het Excel-idee: past een tabel niet in zijn kader, dan zet je hem over het hele
   scherm, blijft de kopregel boven staan en de eerste kolom links, en schuif je opzij
   zonder kwijt te raken over welke regel je kijkt.

   Het omhulsel bestaat alleen om de knop ergens op te hangen die níét meeschuift met de
   tabel; table-expand.js zet hem er bij het laden omheen. */
.table-frame {
    position: relative;
}

/* Hij staat standaard nergens: alleen als er echt iets te schuiven valt. Een knop die
   er altijd staat, wordt niet meer gezien op het moment dat je hem nodig hebt. */
.table-expand {
    display: none;
}

.table-expand.is-visible {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

/* Geen knoppenbalk op dit scherm: dan hangt hij rechtsboven aan de tabel zelf */
.table-frame .table-expand {
    position: absolute;
    top: 0.35rem;
    right: 0.35rem;
    z-index: 3;
    padding: 0.3rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text-muted);
    cursor: pointer;
}

.table-frame .table-expand:hover {
    border-color: var(--brand-primary);
    color: var(--brand-primary);
}

/* Zwevend boven de tabel is er geen ruimte voor tekst; in de knoppenbalk wel */
.table-frame .table-expand-label {
    display: none;
}

.table-scroll.is-fullscreen {
    position: fixed;
    inset: 0;
    z-index: 70;
    max-height: none;
    height: 100vh;
    margin: 0;
    padding: 3rem 1rem 1rem;
    background: var(--surface);
}

/* Ligt de tabel over het scherm, dan hoort de sluitknop mee naar voren te komen -
   waar hij ook vandaan kwam. */
body.has-fullscreen-table .table-expand.is-visible[aria-pressed="true"] {
    position: fixed;
    top: 0.75rem;
    right: 1rem;
    z-index: 71;
}

/* Kop vast (dat deed hij al) én de eerste kolom vast: dat laatste is wat een brede
   tabel leesbaar maakt. Alleen op volledig scherm - in een gewone kaart is de tabel
   zelden zo breed dat het nodig is, en een vastgezette kolom over een smalle tabel
   levert alleen een naad op. */
.table-scroll.is-fullscreen .table thead th:first-child,
.table-scroll.is-fullscreen .table tbody td:first-child,
.table-scroll.is-fullscreen .table tfoot th:first-child,
.table-scroll.is-fullscreen .table tfoot td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--surface);
    box-shadow: 1px 0 0 var(--border);
}

.table-scroll.is-fullscreen .table thead th:first-child {
    z-index: 4;
}

/* De pagina eronder schuift niet mee: anders sta je na het sluiten ergens anders */
body.has-fullscreen-table {
    overflow: hidden;
}

@media print {
    .table-expand {
        display: none !important;
    }
}

/* Een tweede schuifbalk bóven de tabel. Bij een tabel van twintig regels staat de
   gewone balk onder de laatste regel, en dan weet je bovenaan niet dat er rechts nog
   vier kolommen zijn. list.js hangt hem erboven en houdt de twee gelijk; komt hij er
   niet, dan is er niets kapot - alleen die extra balk mis je. */
.table-scroll-top {
    overflow-x: auto;
    overflow-y: hidden;
    margin-bottom: 0.25rem;
}

.table-scroll-top > div {
    height: 1px;
}

/* De eerste kolom blijft staan. Een doorzichtige cel zou over de tekst eronder heen
   schuiven, dus krijgt hij dezelfde achtergrond als eromheen. */
.table-sticky-first tbody td:first-child,
.table-sticky-first thead th:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--surface);
}

/* De vastgezette kolom staat over de schaduw heen; anders schemert die erdoorheen */
.table-sticky-first tbody td:first-child {
    background-clip: padding-box;
}

.table-sticky-first thead th:first-child {
    z-index: 3;
    background: var(--bg);
}

/* Bij een tabel met selectievakjes is de eerste kolom dat vakje; dan blijft de tweede
   (de naam) er ook bij staan, anders zeggen die vinkjes niets. */
.table-select.table-sticky-first tbody td:nth-child(2),
.table-select.table-sticky-first thead th:nth-child(2) {
    position: sticky;
    left: 2.5rem;
    z-index: 1;
    background: var(--surface);
}

.table-select.table-sticky-first thead th:nth-child(2) {
    z-index: 3;
    background: var(--bg);
}

/* Een randje maakt zichtbaar dat daar iets blijft staan */
.table-sticky-first tbody td:first-child,
.table-select.table-sticky-first tbody td:nth-child(2) {
    box-shadow: 1px 0 0 var(--border);
}

.pager {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.75rem;
    margin-top: 1rem;
    font-size: 0.9rem;
}

.pager .muted {
    margin-right: auto;
}

.num {
    text-align: right;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.text-success {
    color: var(--success-text);
}

.table tfoot th {
    background: var(--surface);
    border-top: 2px solid var(--border);
}

.tag-state-ok { background: var(--success-bg); color: var(--success-text); }
.tag-state-warning { background: var(--warning-bg); color: var(--warning-text); }
.tag-state-error { background: var(--error-bg); color: var(--error-text); }

.log-tail {
    max-height: 24rem;
    overflow: auto;
    padding: 1rem;
    background: var(--sidebar-bg);
    color: var(--sidebar-text);
    border-radius: var(--radius);
    font-size: 0.8rem;
    white-space: pre-wrap;
    word-break: break-word;
}

.permission-group {
    display: grid;
    gap: 0.35rem;
    border: 0;
    border-top: 1px solid var(--border);
    padding: 0.75rem 0 0.5rem;
    margin: 0;
}

.permission-group legend {
    font-weight: 600;
    padding-right: 0.5rem;
}

.check-columns {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
    gap: 0.35rem 1rem;
}

@media (max-width: 900px) {
    .filter-layout {
        grid-template-columns: 1fr;
    }

    .filter-panel {
        position: static;
    }

    .toolbar-search input {
        min-width: 0;
    }
}

/* ─── Wizard: de stappen boven een meerstapsformulier ──────────────────────── */

.wizard-steps {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    margin-bottom: 1.25rem;
    color: var(--text-muted);
    font-size: 0.9rem;
}

.wizard-step {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.wizard-step-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    border: 1px solid var(--border);
    font-weight: 700;
    font-size: 0.8rem;
}

.wizard-step.is-current {
    color: var(--text);
    font-weight: 600;
}

.wizard-step.is-current .wizard-step-number {
    background: var(--brand-primary);
    border-color: var(--brand-primary);
    color: #fff;
}

.wizard-step.is-done .wizard-step-number {
    background: var(--success-bg);
    border-color: var(--success-bg);
    color: var(--success-text);
}

/* ─── Footer: copyright, changelog en wie het gemaakt heeft ───────────────── */

.footer-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    padding: 0.7rem 2.5rem;
    background: var(--surface);
    border-top: 1px solid var(--border);
    color: var(--text-muted);
    font-size: 0.8rem;
    /* Staat altijd onderin beeld, net als de bovenbalk bovenin. Begint na de
       zijbalk, zodat het menu er niet onder verdwijnt; de inhoudskolom houdt
       onderaan ruimte vrij zodat er niets achter valt. */
    position: fixed;
    left: 15rem;
    right: 0;
    bottom: 0;
    z-index: 25;
}

/* Op het inlogscherm is er geen menu, dus daar begint de balk gewoon links. Anders
   staat hij vijftien rem naar binnen en loopt hij halverwege de foto - wat er zonder
   deze regel ook gebeurde.

   En hij ligt daar óver de foto heen in plaats van als wit blok ervoor: dezelfde ruit
   als het paneel erboven. Eerst de effen kleur als terugval, voor een browser die
   color-mix niet kent. */
.login-page .footer-bar,
.plain-page .footer-bar {
    left: 0;
    background: var(--surface);
    background: color-mix(in srgb, var(--surface) 72%, transparent);
    -webkit-backdrop-filter: blur(18px) saturate(1.2);
    backdrop-filter: blur(18px) saturate(1.2);
}

/* Ruimte onderaan het paneel, zodat de laatste regel niet achter de balk valt */
.login-page .login-card,
.plain-page .plain-card {
    padding-bottom: 4rem;
}

/* Het midden van de voetbalk: waar je vandaan komt en hoe laat het is. Op een smal
   scherm valt dit als eerste weg - het is achtergrondinformatie, geen bediening. */
.footer-meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

@media (max-width: 60rem) {
    .footer-meta {
        display: none;
    }
}

.footer-links {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 1rem;
    margin-left: auto;
}

.footer-bar a,
.footer-bar .link-button {
    color: var(--text-muted);
    font-size: 0.8rem;
    text-decoration: none;
}

.footer-bar a:hover,
.footer-bar .link-button:hover {
    color: var(--brand-primary);
    text-decoration: underline;
}

.footer-bar .nav-badge {
    margin-left: 0.25rem;
}

@media (max-width: 52rem) {
    .footer-bar {
        /* Geen zijbalk naast de inhoud meer: de balk loopt over de volle breedte */
        left: 0;
        padding: 0.6rem 1rem;
    }

    .footer-links {
        gap: 0.75rem;
    }
}

/* ─── Sessie verlopen: over de pagina heen ────────────────────────────────── */

.session-overlay {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(11, 18, 28, 0.6);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
}

.session-card {
    width: min(26rem, 100%);
    padding: 2rem;
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
    text-align: center;
}

.session-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    margin-bottom: 0.75rem;
    border-radius: 50%;
    background: var(--warning-bg);
    color: var(--warning-text);
    font-size: 1.25rem;
}

.session-card p {
    color: var(--text-muted);
}

/* Niets meer achter het scherm aanklikken of scrollen */
body.has-session-overlay {
    overflow: hidden;
}

/* ─── Bestand kiezen: slepen of klikken ───────────────────────────────────── */

.dropzone {
    display: block;
    position: relative;
    overflow: hidden;
    padding: 1.5rem 1rem;
    border: 2px dashed var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    text-align: center;
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition);

    /* Hetzelfde verloop als bovenaan de pagina, in de kleuren van de tenant. Een leeg
       vak met een stippellijn zegt "hier kan iets"; dit zegt het net iets vriendelijker.
       Van linksboven naar rechtsonder, zodat het niet dezelfde richting heeft als de
       pagina eromheen - anders lopen de twee in elkaar over. */
    background-image: linear-gradient(135deg,
        color-mix(in srgb, var(--brand-primary) var(--tint-strength), transparent) 0%,
        color-mix(in srgb, var(--accent) calc(var(--tint-strength) * 0.5), transparent) 50%,
        color-mix(in srgb, var(--brand-secondary) var(--tint-strength), transparent) 100%);
}

/* De tekening eroverheen, heel licht: het is een achtergrond en geen plaatje. Als
   ::before, zodat het invoerveld dat over de hele zone ligt er gewoon boven blijft. */
.dropzone::before {
    content: "";
    position: absolute;
    inset: 0;
    background: url("/assets/img/background_1.svg") center / cover no-repeat;
    /* Hoe de lijnen met de kleur eronder meegaan verschilt per thema: zie het token */
    mix-blend-mode: var(--pattern-blend);
    opacity: var(--pattern-opacity);
    pointer-events: none;
    transition: opacity var(--transition);
}

/* Sleep je er iets overheen, dan komt het naar voren in plaats van van kleur te
   verschieten: dat is te zien zonder dat je erop hoeft te letten */
.dropzone:hover,
.dropzone.is-over {
    border-color: var(--brand-primary);
    border-style: solid;
}

.dropzone:hover::before,
.dropzone.is-over::before {
    opacity: calc(var(--pattern-opacity) * 1.8);
}

.dropzone.is-over {
    box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--brand-primary) 35%, transparent);
}

/* Het echte veld blijft bruikbaar met het toetsenbord, maar valt over de hele zone */
.dropzone input[type="file"] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.dropzone-body {
    /* Boven het patroon */
    position: relative;
    display: grid;
    gap: 0.25rem;
    justify-items: center;
    pointer-events: none;
}

.dropzone-body i {
    font-size: 1.5rem;
    color: var(--brand-primary);
}

/* Bestand gekozen: naam tonen in plaats van de uitnodiging */
.dropzone-file {
    display: block;
    margin-top: 0.5rem;
    font-weight: 600;
    word-break: break-all;
}

/* ─── Foto uitsnijden ─────────────────────────────────────────────────────── */

.cropper {
    display: grid;
    gap: 0.75rem;
    justify-items: center;
    margin-top: 1rem;
}

.cropper-frame {
    position: relative;
    width: 15rem;
    height: 15rem;
    overflow: hidden;
    border-radius: var(--radius);
    background: var(--bg);
    cursor: grab;
    touch-action: none;
}

.cropper-frame:active {
    cursor: grabbing;
}

.cropper-frame img {
    position: absolute;
    max-width: none;
    user-select: none;
    -webkit-user-select: none;
}

/* De cirkel laat zien wat er straks van de foto overblijft */
.cropper-mask {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    box-shadow: 0 0 0 999px rgba(11, 18, 28, 0.45);
    pointer-events: none;
}

.cropper-zoom {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 15rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.cropper-zoom input {
    flex: 1;
}

.cropper p {
    margin: 0;
    font-size: 0.85rem;
}

/* ─── Kruimelpad ──────────────────────────────────────────────────────────── */

.breadcrumbs {
    margin-bottom: 1rem;
    font-size: 0.85rem;
}

.breadcrumbs ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.breadcrumbs li + li::before {
    content: "›";
    margin-right: 0.35rem;
    color: var(--text-muted);
}

.breadcrumbs a {
    color: var(--text-muted);
    text-decoration: none;
}

.breadcrumbs a:hover {
    color: var(--brand-primary);
    text-decoration: underline;
}

.breadcrumbs [aria-current="page"] {
    color: var(--text);
    font-weight: 600;
}

/* ─── Menu smal: alleen de iconen ─────────────────────────────────────────── */

body.sidebar-collapsed .layout {
    grid-template-columns: 4rem 1fr;
}

body.sidebar-collapsed .sidebar {
    padding-left: 0.4rem;
    padding-right: 0.4rem;
}

/* De labels verdwijnen, de iconen blijven; de titel per groep valt weg omdat er
   geen ruimte voor is */
body.sidebar-collapsed .nav-list a > span,
body.sidebar-collapsed .nav-heading {
    display: none;
}

body.sidebar-collapsed .nav-list a {
    justify-content: center;
    padding: 0.6rem 0.25rem;
}

body.sidebar-collapsed .nav-badge {
    position: absolute;
    margin: 0;
    transform: translate(0.9rem, -0.7rem);
}

body.sidebar-collapsed .nav-list a {
    position: relative;
}

body.sidebar-collapsed .sidebar-brand {
    padding: 0.4rem;
}

body.sidebar-collapsed .sidebar-brand img {
    max-height: 1.75rem;
}

body.sidebar-collapsed .sidebar-brand .tag {
    display: none;
}

/* De vaste footerbalk begint waar het menu ophoudt */
body.sidebar-collapsed .footer-bar {
    left: 4rem;
}

@media (max-width: 52rem) {
    /* Zonder zijbalk naast de inhoud valt er niets in te klappen */
    body.sidebar-collapsed .layout {
        grid-template-columns: 1fr;
    }

    body.sidebar-collapsed .footer-bar {
        left: 0;
    }

    #sidebar_toggle {
        display: none;
    }
}

/* ─── Logo dat meekleurt ──────────────────────────────────────────────────── */

/* De donkere vorm in het logo is currentColor (zie brandSvg); het rode accent
   blijft staan. Zo klopt het logo in de lichte en in de donkere weergave. */
.brand-logo {
    display: block;
    width: 100%;
    max-width: 11rem;
    height: auto;
    margin: 0 auto;
    color: var(--sidebar-strong);
}

/* Buiten de zijbalk (inlogscherm, herstelpagina's) volgt hij de gewone tekstkleur */
.login-brand .brand-logo,
.plain-card .brand-logo {
    color: var(--text);
    max-width: 13rem;
}

/* ── Het logo en het icoon van een tenant ────────────────────────────────────
   De lichte en donkere versie staan allebei in de pagina; de stylesheet laat er één
   zien. Dat moet zo: het thema kan "systeem" zijn, en wat dat bij deze bezoeker betekent
   weet alleen de browser - de server kan het plaatje dus niet kiezen.

   Welke versies er zijn, zegt het blok zelf met `has-dark-logo`, `has-icon` en
   `has-dark-icon`. Heeft een tenant maar één logo, dan gebeurt hier niets en blijft
   alles zoals het was.

   Breed menu = het logo; ingeklapt = het icoon, want een liggend logo past in vier
   centimeter niet. */
.brand-logo-dark,
.brand-icon-light,
.brand-icon-dark {
    display: none;
}

/* Donker thema: het donkere logo, als dat er is */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .has-dark-logo .brand-logo-light { display: none; }
    :root:not([data-theme="light"]) .has-dark-logo .brand-logo-dark { display: block; }
}

:root[data-theme="dark"] .has-dark-logo .brand-logo-light { display: none; }
:root[data-theme="dark"] .has-dark-logo .brand-logo-dark { display: block; }

/* Ingeklapt menu: het icoon in plaats van het logo */
body.sidebar-collapsed .has-icon .brand-logo-light,
body.sidebar-collapsed .has-icon .brand-logo-dark {
    display: none;
}

body.sidebar-collapsed .has-icon .brand-icon-light {
    display: block;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) body.sidebar-collapsed .has-dark-icon .brand-icon-light { display: none; }
    :root:not([data-theme="light"]) body.sidebar-collapsed .has-dark-icon .brand-icon-dark { display: block; }
}

:root[data-theme="dark"] body.sidebar-collapsed .has-dark-icon .brand-icon-light { display: none; }
:root[data-theme="dark"] body.sidebar-collapsed .has-dark-icon .brand-icon-dark { display: block; }

/* Ons eigen logo heeft geen wit vlak nodig: het kleurt met het menu mee */
.sidebar-brand-own {
    background: transparent;
    padding: 0.5rem 0.25rem;
}

/* Breed menu: het woordmerk. Smal menu: alleen het beeldmerk. */
.brand-icon {
    display: none;
    width: 2rem;
    height: auto;
    margin: 0 auto;
    color: var(--sidebar-strong);
}

body.sidebar-collapsed .brand-logo {
    display: none;
}

body.sidebar-collapsed .brand-icon {
    display: block;
}

/* Klein informatie-icoon achter een naam: opent de help op dat onderwerp */
.info-button {
    border: 0;
    background: transparent;
    padding: 0 0.15rem;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 0.85em;
}

.info-button:hover {
    color: var(--brand-primary);
}

/* De exportknop onder een tabel */
.table-export {
    margin: 0.75rem 0 0;
}

/* De bronvermelding onder een tabel: eerst de cijfers, dan waar ze vandaan komen.
   Kleiner dan de tabel, want het is een voetnoot en geen inleiding. */
.table-source {
    margin: 1.25rem 0 0;
    padding-top: 0.75rem;
    border-top: 1px solid var(--border);
    font-size: 0.85rem;
}

/* Welkom op het dashboard: je eigen foto naast de begroeting */
.welcome {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.welcome h1 {
    margin: 0;
}

.welcome p {
    margin: 0;
}

/* ─── Ideeën: de lijst met stemknop ───────────────────────────────────────── */

.idea-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.5rem;
}

.idea-row,
.idea-head {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    padding: 0.75rem 0;
    border-top: 1px solid var(--border);
}

.idea-head {
    border-top: 0;
    padding-top: 0;
}

.idea-list .idea-row:first-child {
    border-top: 0;
}

.idea-body {
    min-width: 0;
}

.idea-body p {
    margin: 0.25rem 0 0;
}

.idea-tags {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
}

/* De stemknop: een pijl met het aantal eronder */
.vote-button {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 3rem;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text-muted);
    font: inherit;
    font-weight: 700;
    line-height: 1.1;
    cursor: pointer;
    transition: border-color var(--transition), color var(--transition), background var(--transition);
}

.vote-button:hover {
    border-color: var(--brand-primary);
    color: var(--brand-primary);
}

.vote-button.is-voted {
    border-color: var(--brand-primary);
    background: var(--info-bg);
    color: var(--brand-primary);
}

/* ─── Het gesprek onder een idee ──────────────────────────────────────────── */

.comment-list {
    list-style: none;
    margin: 0 0 1.25rem;
    padding: 0;
    display: grid;
    gap: 1rem;
}

.comment {
    display: flex;
    gap: 0.75rem;
}

.comment p {
    margin: 0;
}

.comment-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    margin-bottom: 0.15rem;
}

/* Een interne notitie valt op, zodat je hem niet aanziet voor iets dat de klant leest */
.comment.is-internal {
    padding: 0.5rem;
    border-radius: var(--radius);
    background: var(--warning-bg);
}

/* ─── Roadmap: het bord ───────────────────────────────────────────────────── */

.board {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(15rem, 1fr);
    gap: 1rem;
    align-items: start;
    overflow-x: auto;
    padding-bottom: 0.5rem;
}

.board-column {
    padding: 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    min-height: 8rem;
    transition: border-color var(--transition), background var(--transition);
}

.board-column.is-over {
    border-color: var(--brand-primary);
    background: var(--info-bg);
}

.board-column h2 {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 1rem;
    margin-bottom: 0.25rem;
}

.board-column h2 .muted {
    margin-left: auto;
    font-weight: 400;
}

.board-column p {
    font-size: 0.85rem;
}

.board-cards {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.5rem;
    min-height: 2rem;
}

.board-card {
    display: grid;
    gap: 0.2rem;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    font-size: 0.9rem;
}

.board-card[draggable="true"] {
    cursor: grab;
}

.board-card.is-dragging {
    opacity: 0.5;
}

/* Verplaatsen niet opgeslagen: dan moet je het zien */
.board-card.is-failed {
    border-color: var(--error-text);
}

.board-card a {
    text-decoration: none;
}

.board-card .muted {
    font-size: 0.8rem;
}

/* Testsuites: een vinkje of een kruisje voor elke test */
.test-status {
    width: 2rem;
    text-align: center;
}

.text-ok { color: var(--success-text); }

.tag-fout { background: var(--error-bg); color: var(--error-text); }

/* --- Icoon kiezen uit voorbeelden --------------------------------------- */
/* Een klasse met een naam als `fa-mug-hot` zegt niemand iets: je wilt het plaatje
   zien. Daarom een raster met voorbeelden in plaats van een keuzelijst. */

.icon-picker {
    display: block;
}

.icon-picker-trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
}

.icon-picker-preview {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--radius);
    background: var(--bg);
    color: var(--brand-primary);
}

.icon-picker-dialog {
    width: min(46rem, calc(100vw - 2rem));
}

.icon-picker-body {
    padding: 1.25rem;
}

.icon-picker-search {
    display: block;
    margin-bottom: 1rem;
}

.icon-picker-group + .icon-picker-group {
    margin-top: 1.1rem;
}

.icon-picker-group h3 {
    margin: 0 0 0.5rem;
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.icon-picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr));
    gap: 0.4rem;
}

.icon-option {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
    padding: 0.5rem 0.25rem;
    border: 2px solid transparent;
    border-radius: var(--radius);
    cursor: pointer;
    text-align: center;
}

.icon-option:hover {
    background: var(--bg);
}

.icon-option input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
}

.icon-option-body {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.4rem;
    height: 2.4rem;
    border-radius: var(--radius);
    background: var(--bg);
    font-size: 1.1rem;
    color: var(--text);
}

.icon-option-name {
    font-size: 0.75rem;
    color: var(--text-muted);
    line-height: 1.2;
}

.icon-option:has(input:checked) {
    border-color: var(--brand-primary);
}

.icon-option:has(input:checked) .icon-option-body {
    background: var(--brand-primary);
    color: #fff;
}

.icon-option:has(input:focus-visible) {
    outline: 2px solid var(--brand-primary);
    outline-offset: 2px;
}

.icon-picker-empty {
    margin: 1rem 0 0;
}

/* Naam van een module met zijn icoon ervoor, zoals in het menu */
.module-label {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

/* --- Uitkomst die eruit hoort te springen ------------------------------- */
/* De voorgestelde reistijd is het antwoord waarvoor je de analyse draaide; die
   hoort niet als vierde grijze tegel tussen de rest te staan. */

.kpi-good {
    border-color: var(--success-text);
    box-shadow: inset 4px 0 0 var(--success-text);
}

.kpi-good .kpi-note strong {
    color: var(--success-text);
}

/* De optelregel onderaan een tabel. Geen kleur en geen kader: een totaal is geen
   markering maar een afsluiting, en dat zegt een dubbele lijn erboven - zoals in een
   boekhouding. Kleur is voor wat opvalt, niet voor wat er altijd staat. */
tr.row-total > td {
    border-top: 3px double var(--text-muted);
    font-weight: 600;
}

/* Een regel die het niet heeft gehaald: wel te lezen, maar duidelijk op de achtergrond.
   Doorstrepen zou het onleesbaar maken, en juist dát is wat iemand wil nalezen. */
tr.row-muted > td {
    color: var(--text-muted);
}

/* De regel in de tabel die bij dat voorstel hoort. Eerst stond er een kader omheen,
   maar de tabel heeft zelf al randen: dat leest als een dubbele lijn en trekt meer
   aandacht dan de regel verdient. De groene achtergrond zegt hetzelfde, en een streep
   aan de linkerkant wijst hem aan zonder ergens tegenaan te liggen. */
tr.row-marked > td {
    background: var(--success-bg);
    font-weight: 600;
}

tr.row-marked > td:first-child {
    box-shadow: inset 3px 0 0 var(--success-text);
}

.badge {
    display: inline-block;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    vertical-align: middle;
}

.badge-good {
    background: var(--success-text);
    color: var(--surface);
}

/* Verwijzing naar het voorbeeldbestand onder een upload */
.sample-link {
    margin: 0.4rem 0 0;
    font-size: 0.85rem;
    color: var(--text-muted);
}

/* "of" tussen twee manieren om hetzelfde op te geven: een bestand kiezen of er een
   inlezen, een locatie kiezen of een postcode typen */
.or-divider {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0.9rem 0;
    color: var(--text-muted);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.or-divider::before,
.or-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--border);
}

/* Twee tellingen naast elkaar onder de rapportgegevens: waar de regels bleven, en waar
   de bezoekers wonen. Op een smal scherm onder elkaar. */
.report-blocks {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
    gap: 1.5rem;
    margin-top: 1.25rem;
}

.report-blocks h3 {
    margin-top: 0;
}

/* De indexcel in een benchmarktabel: onder de 80 komt een doelgroep hier minder voor
   dan in de vergelijking, boven de 120 juist meer. Dezelfde driedeling als in
   Gebiedsprofiel, maar met tokens - een vaste kleur breekt het donkere thema. */
.index-low  { color: var(--info-text); font-weight: 600; }
.index-mid  { color: var(--text); }
.index-high { color: var(--brand-primary); font-weight: 700; }

/* --- Rapport met een inhoudsopgave ernaast -------------------------------- */
/* Een rapport is lang. De lijst rechts blijft staan terwijl je scrollt en laat zien
   waar je bent; op een smal scherm is er geen ruimte voor en valt hij weg. */

/* De inhoudsopgave staat in de zijbalk, tussen de filters van andere pagina's. Hij
   scrollt mee als hij langer is dan het scherm; de zijbalk zelf blijft staan. */
.report-toc {
    max-height: calc(100vh - 12rem);
    overflow-y: auto;
}

.toc-list {
    list-style: none;
    margin: 0;
    padding: 0;
    counter-reset: toc;
}

.toc-list li {
    counter-increment: toc;
}

.toc-list a {
    display: block;
    padding: 0.4rem 0.6rem;
    margin-bottom: 0.25rem;
    border-left: 3px solid transparent;
    border-radius: var(--radius);
    color: var(--text-muted);
    font-size: var(--text-ui);
    line-height: 1.35;
    text-decoration: none;
}

.toc-list a::before {
    content: counter(toc) ". ";
    color: var(--text-muted);
}

.toc-list a:hover {
    background: var(--bg);
    color: var(--text);
}

/* Waar je nu bent: in de kleur van de tenant, zodat het meteen opvalt */
.toc-list a.is-active {
    background: var(--bg);
    border-left-color: var(--brand-primary);
    color: var(--text);
    font-weight: 600;
}

@media print {
    .report-toc {
        display: none !important;
    }
}

/* --- Module met een kolom ernaast ---------------------------------------- */
/* Het formulier links, en rechts wat deze module al heeft opgeleverd: een leeg
   formulier zegt niets over wat je ermee kunt. Op een smal scherm komt de kolom
   eronder te staan. */

.module-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
    align-items: start;
}

@media (min-width: 60rem) {
    .module-layout {
        grid-template-columns: minmax(0, 1fr) 20rem;
    }
}

.module-main {
    min-width: 0;
}

.module-side .card {
    margin-bottom: 1rem;
}

.module-side h2 {
    font-size: 1rem;
    margin: 0;
}

/* De knop naast een kop in de zijkolom hoort tegen de rechterrand, net als in de
   toolbar boven een tabel */
.module-side .toolbar .btn {
    margin-left: auto;
}

.kpi-grid-narrow {
    grid-template-columns: minmax(0, 1fr);
}

.kpi-value-small {
    font-size: 1.1rem;
}

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

.side-list li {
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--border);
}

.side-list li:last-child {
    border-bottom: 0;
}

.side-list small {
    display: block;
    font-size: 0.75rem;
}

/* --- Kaart: schillen, legenda en schuifbalk ------------------------------- */

.map-modes {
    display: flex;
    gap: 0.35rem;
    /* Rechts in de balk, zoals elke andere knoppengroep boven een blok */
    margin-left: auto;
}

/* Twee of drie knoppen die samen één keuze zijn: tabel of kaart. Ze staan tegen elkaar
   aan zodat het één ding is en niet twee losse knoppen. */
.btn-group {
    display: inline-flex;
    gap: 0;
}

.btn-group .btn {
    border-radius: 0;
}

.btn-group .btn:first-child {
    border-top-left-radius: var(--radius);
    border-bottom-left-radius: var(--radius);
}

.btn-group .btn:last-child {
    border-top-right-radius: var(--radius);
    border-bottom-right-radius: var(--radius);
}

.btn-group .btn + .btn {
    margin-left: -1px;
}

.btn-group .btn.is-active {
    border-color: var(--brand-primary);
    color: var(--brand-primary);
    font-weight: 600;
    /* Boven de buurman, anders valt zijn rand over deze heen */
    position: relative;
    z-index: 1;
}

.map-modes .btn.is-active {
    border-color: var(--brand-primary);
    color: var(--brand-primary);
    font-weight: 600;
}

/* Het nummer van een postcodegebied, vast in het vlak. Leaflet maakt van een tooltip
   standaard een wit kaartje met een randje en een pijltje; hier moet het gewoon tekst
   zijn die over de kleur heen leesbaar blijft - vandaar de witte rand eromheen in plaats
   van een vlak eronder. De labels vangen geen muisklikken, anders klik je het vlak
   eronder niet meer aan.

   Hier staat met opzet een vaste kleur en geen kleurtoken: dit label ligt op de
   kaarttegels, en die zien er in het donkere thema net zo uit als in het lichte. Een
   token maakt de tekst in het donker wit, en wit op een lichtgroene polder leest niemand
   meer. */
.leaflet-tooltip.map-area-label {
    background: none;
    border: 0;
    box-shadow: none;
    padding: 0;
    font-size: 0.7rem;
    font-weight: 600;
    color: #1b1b1b;
    text-shadow: -1px -1px 0 rgba(255, 255, 255, 0.85), 1px -1px 0 rgba(255, 255, 255, 0.85),
        -1px 1px 0 rgba(255, 255, 255, 0.85), 1px 1px 0 rgba(255, 255, 255, 0.85);
    pointer-events: none;
    white-space: nowrap;
}

.leaflet-tooltip.map-area-label::before {
    display: none;
}

.map-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1rem;
    margin: 0.75rem 0 0;
    padding: 0;
    list-style: none;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.map-legend li {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.legend-swatch {
    display: inline-block;
    width: 0.9rem;
    height: 0.9rem;
    border-radius: 3px;
}

.map-slider {
    margin-top: 1rem;
    padding: 0.9rem 1rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
}

.map-slider-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.4rem;
}

.map-slider-label {
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.map-slider-value {
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--brand-primary);
}

.map-slider-track {
    display: block;
}

/* De balk zelf: links van de knop in de merkkleur, rechts rustig grijs. Chrome en
   Firefox willen daar elk hun eigen regels voor, vandaar de herhaling. */
.map-slider input[type="range"] {
    width: 100%;
    height: 1.4rem;
    margin: 0;
    background: transparent;
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
}

.map-slider input[type="range"]::-webkit-slider-runnable-track {
    height: 0.45rem;
    border-radius: 999px;
    background: linear-gradient(to right,
        var(--brand-primary) 0 var(--range-filled, 100%),
        var(--border) var(--range-filled, 100%) 100%);
}

.map-slider input[type="range"]::-moz-range-track {
    height: 0.45rem;
    border-radius: 999px;
    background: var(--border);
}

.map-slider input[type="range"]::-moz-range-progress {
    height: 0.45rem;
    border-radius: 999px;
    background: var(--brand-primary);
}

.map-slider input[type="range"]::-webkit-slider-thumb {
    appearance: none;
    -webkit-appearance: none;
    width: 1.1rem;
    height: 1.1rem;
    margin-top: -0.33rem;
    border: 3px solid var(--surface);
    border-radius: 50%;
    background: var(--brand-primary);
    box-shadow: 0 1px 4px rgba(15, 23, 34, 0.35);
}

.map-slider input[type="range"]::-moz-range-thumb {
    width: 1.1rem;
    height: 1.1rem;
    border: 3px solid var(--surface);
    border-radius: 50%;
    background: var(--brand-primary);
    box-shadow: 0 1px 4px rgba(15, 23, 34, 0.35);
}

.map-slider input[type="range"]:focus-visible {
    outline: 2px solid var(--brand-primary);
    outline-offset: 4px;
}

/* De stappen onder de balk: ook knoppen, zodat je er meteen heen kunt springen */
.map-slider-ticks {
    display: flex;
    justify-content: space-between;
    gap: 0.2rem;
    margin-top: 0.15rem;
}

.map-slider-tick {
    padding: 0.1rem 0.35rem;
    border: 0;
    border-radius: 999px;
    background: none;
    color: var(--text-muted);
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
}

.map-slider-tick:hover {
    color: var(--text);
}

.map-slider-tick.is-passed {
    color: var(--brand-primary);
}

.map-slider-tick.is-active {
    background: var(--brand-primary);
    color: #fff;
    font-weight: 700;
}

/* De reistijd die de analyse voorstelt: die wil je in de balk kunnen aanwijzen,
   ook als je ergens anders staat te schuiven. */
.map-slider-tick.is-suggested {
    font-weight: 700;
    color: var(--text);
}

.map-slider-tick.is-suggested::after {
    content: "";
    display: block;
    width: 0.3rem;
    height: 0.3rem;
    margin: 0.1rem auto 0;
    border-radius: 50%;
    background: var(--brand-primary);
}

.map-slider-tick.is-suggested.is-active::after {
    background: #fff;
}

.map-slider-note {
    margin: 0.5rem 0 0;
    font-size: 0.85rem;
    color: var(--text-muted);
}

/* --- Eén balk met de hele verdeling erin --------------------------------- */
/* De stapel staat boven de tabel: de verhouding zie je zo, de getallen lees je
   eronder. De kleuren komen uit driveTimeStepColors(), net als op de kaart. */

.bar-stack {
    display: flex;
    width: 100%;
    height: 1.1rem;
    margin: 0.5rem 0 1rem;
    border-radius: 999px;
    overflow: hidden;
    background: var(--bg);
}

.bar-stack span {
    display: block;
    width: var(--bar-width, 0);
    height: 100%;
}

/* Een verschil ten opzichte van de vorige keer of van een andere locatie */
.value-up {
    color: var(--success-text);
}

.value-down {
    color: var(--error-text);
}

/* De curve van de reistijdanalyse */
.curve {
    display: block;
    width: 100%;
    max-width: 44rem;
    height: auto;
}

.curve-grid {
    stroke: var(--border);
    stroke-width: 1;
}

.curve-target {
    stroke: var(--text-muted);
    stroke-width: 1;
    stroke-dasharray: 4 3;
}

.curve-axis {
    fill: var(--text-muted);
    font-size: 11px;
}

.curve-legend {
    font-size: 12px;
    font-weight: 600;
}

/* Wat een module oplevert, boven het formulier: drie korte kolommen. Geen lead, geen
   opsommingstekens - het is een wegwijzer, geen folder. */
.intro-points {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0.75rem;
    margin: 1rem 0;
    padding: 0.9rem 1rem;
    border-radius: var(--radius);
    background: var(--bg);
    list-style: none;
}

@media (min-width: 48rem) {
    .intro-points {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 1.25rem;
    }
}

.intro-points li {
    display: grid;
    grid-template-columns: 1.4rem minmax(0, 1fr);
    grid-template-rows: auto auto;
    column-gap: 0.5rem;
    align-items: start;
}

.intro-points i {
    grid-row: 1 / span 2;
    margin-top: 0.15rem;
    color: var(--brand-primary);
}

.intro-points strong {
    font-size: 0.9rem;
}

.intro-points span {
    font-size: 0.85rem;
    color: var(--text-muted);
}


/* Links in de voet: het merk en waar je akkoord mee bent, op één regel */
.footer-left {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.footer-sep {
    color: var(--border);
}

/* Kop van een onderzoekslocatie: logo naast de naam en het adres */
.location-head {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    margin-bottom: 0.75rem;
}

.location-head h2 {
    margin: 0;
}

.location-head p {
    margin: 0.15rem 0 0;
}

/* Het logo wijzigen: wat er nu staat, met het formulier ernaast */
.logo-edit {
    display: flex;
    align-items: flex-start;
    gap: 1.25rem;
    flex-wrap: wrap;
}

.logo-edit .form {
    flex: 1 1 18rem;
}

/* Het logo van de locatie bij de rapportgegevens en in de kop van een PDF */
.report-location {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.pdf-head-title {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

/* --- Rapportgegevens met een kaartje ernaast ----------------------------- */
/* De gegevens links, de plek rechts: waar gaat dit rapport eigenlijk over? */

.report-summary {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
    /* Stretch en niet start: dan loopt de kaart door tot onder aan de gegevens */
    align-items: stretch;
}

/* De gegevens hebben maar een paar regels nodig; de ruimte die overblijft is voor de
   kaart. Hoe breder het scherm, hoe meer die krijgt - je wilt zien waar het rapport
   over gaat, niet turen naar een postzegel. */
@media (min-width: 52rem) {
    .report-summary {
        grid-template-columns: minmax(18rem, 1fr) minmax(20rem, 1.15fr);
    }
}

@media (min-width: 80rem) {
    .report-summary {
        grid-template-columns: minmax(20rem, 1fr) minmax(28rem, 1.4fr);
    }
}

.report-summary-map {
    display: flex;
    flex-direction: column;
    min-height: 16rem;
}

.report-summary-map p {
    margin: 0.35rem 0 0;
    font-size: 0.8rem;
}

/* Een kaart met alleen een speld: hij vult de hoogte van het blok waar hij in staat */
.pin-map {
    width: 100%;
    flex: 1;
    min-height: 15rem;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    overflow: hidden;
    background: var(--bg);
}

/* Een kaart die zelf het antwoord is, mag ruim zijn: je kijkt naar een pand en wilt zien
   wat eromheen staat. Staat na .pin-map, net als .map.is-tile na .map - zo hoeft niemand
   over specificiteit na te denken. Vergroten kan daarnaast nog steeds. */
.pin-map.is-tall {
    min-height: 45rem;
}

/* De mijlpalen onder de kop van een reistijdanalyse: drie korte zinnen op een rij */
.milestones {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1.25rem;
    margin: 0 0 1rem;
    padding: 0.6rem 0.8rem;
    border-left: 3px solid var(--brand-primary);
    background: var(--bg);
    border-radius: 0 var(--radius) var(--radius) 0;
    font-size: 0.9rem;
}

/* Tekst die direct op een gegevenslijst volgt, heeft lucht nodig: anders plakt hij
   tegen de laatste regel aan en lijkt het erbij te horen. */
.details + p,
.details + .form {
    margin-top: 1.25rem;
}

/* --- Meekijken bij een postcode ----------------------------------------- */
/* De uitslag staat direct onder het veld, in dezelfde maat als een hint. Rustig als
   het klopt, opvallend als het niet klopt - en stil zolang er niets te zeggen valt. */

.zip-check {
    display: block;
    margin-top: 0.25rem;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.zip-check:empty {
    display: none;
}

.zip-check.is-ok {
    color: var(--success-text);
}

.zip-check.is-warning {
    color: var(--accent, #b06a00);
}

.zip-check.is-error {
    color: var(--error-text);
}

.zip-check i {
    margin-right: 0.2rem;
}

/* Naam en bijschrift in een keuzelijst: de naam waar je op scant, de rest erachter */
.pp-select-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.pp-select-sub {
    font-size: 0.8rem;
    font-weight: 400;
    color: var(--text-muted);
}

.pp-select-button .pp-select-sub {
    margin-left: 0.4rem;
}

/* Waar een rapport over ging: de locatie of de postcode, direct onder de titel */
.side-list-where {
    display: block;
    color: var(--text);
    opacity: 0.75;
    margin-top: 0.1rem;
}

/* Wie een rapport draaide, onder de titel in de zijkolom */
.side-list-meta {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.15rem;
}

.side-list-meta .avatar-sm {
    width: 1.1rem;
    height: 1.1rem;
    font-size: 0.55rem;
}

/* Onder een kaart op de roadmap: waar het over gaat, en hoeveel stemmen */
.board-card-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-top: 0.35rem;
    font-size: 0.75rem;
}

.board-card-meta .tag {
    font-size: 0.7rem;
}

/* Kruimelpad bij het bladeren door provincie, gemeente, wijk en buurt.
   Elke kruimel is een eigen formulier (een POST per klik), vandaar dat het een rij
   inline-formulieren is en geen rij links. */
.region-crumbs {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-bottom: 1rem;
    font-size: var(--text-ui);
}

.region-crumbs .link-button[disabled] {
    color: var(--text);
    text-decoration: none;
    cursor: default;
}

.region-crumb-sep {
    color: var(--text-muted);
}

/* Openen en toevoegen staan naast elkaar achter een gebied */
.region-actions {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 0.4rem;
    white-space: nowrap;
}

/* Bewaarde gebiedsselecties in de zijbalk: de naam is de knop om te laden en krijgt de
   breedte, het prullenbakje staat erachter, en eronder staat klein hoeveel gebieden het
   zijn en van wie. Twee regels, want in een zijbalk past een naam en een knop niet naast
   elkaar mét een toelichting. */
.saved-selection-list li.saved-selection {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    column-gap: 0.5rem;
}

.saved-selection .link-button {
    text-align: left;
}

/* De toelichting loopt onder allebei door, dus over de volle breedte. Het gezicht van wie
   hem bewaarde staat ervoor: in een lijstje van tien herken je dat sneller dan een naam. */
.saved-selection-meta {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

/* Kleiner dan de standaard avatar: dit staat op een regel van 0,75rem, en dan zou het
   gewone formaat de tekst ernaast in het niet doen vallen. Zelfde maat als onder een
   kaartje op de roadmap. */
.saved-selection-meta .avatar-sm {
    width: 1.1rem;
    height: 1.1rem;
    font-size: 0.55rem;
}

/* Een knop die naast een invoerveld hoort te staan: die lijnt uit op de onderrand van het
   veld, niet op de veldnaam erboven */
.form-actions-bottom {
    align-self: flex-end;
}

/* De vlag van een provincie, voor de naam. Een randje omdat wit-op-wit anders verdwijnt. */
.province-flag {
    width: 1.5rem;
    height: 1rem;
    object-fit: cover;
    vertical-align: -0.15rem;
    margin-right: 0.4rem;
    border: 1px solid var(--border);
    border-radius: 2px;
}

/* --- Modulestarter bovenin ---------------------------------------------- */
/* Alles wat ProPrisma kan, en wat deze tenant daarvan heeft. Wat niet in het pakket zit
   staat er gedempt bij: dat is de reden dat dit paneel bestaat. */
.launcher {
    position: relative;
}

.launcher-panel {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    z-index: 40;
    width: min(32rem, calc(100vw - 2rem));
    max-height: min(70vh, 34rem);
    overflow: auto;
    padding: 0.75rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

.launcher-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    flex-wrap: wrap;
    padding: 0.25rem 0.4rem 0.6rem;
    font-size: var(--text-ui);
    border-bottom: 1px solid var(--border);
}

.launcher-group {
    padding: 0.8rem 0.4rem 0.35rem;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

/* ── De bel en haar paneel ───────────────────────────────────────────────────
   Zelfde bouw als de modulestarter: de knop en het paneel zitten in één blokje, het
   paneel hangt eronder. Smaller dan de starter, want het zijn regels tekst en geen
   raster - een paneel van 32rem met acht regels erin is grotendeels leeg. */
.bell {
    position: relative;
}

.bell-panel {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    z-index: 40;
    width: min(26rem, calc(100vw - 2rem));
    max-height: min(70vh, 30rem);
    overflow: auto;
    padding: 0.75rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

.bell-empty {
    margin: 0.75rem 0.4rem;
    color: var(--text-muted);
    font-size: 0.85rem;
}

.bell-list {
    margin: 0.25rem 0 0;
    padding: 0;
    list-style: none;
}

.bell-item a {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.55rem 0.4rem;
    border-radius: var(--radius);
    color: var(--text);
    text-decoration: none;
}

.bell-item a:hover {
    background: var(--sidebar-hover);
}

/* Ongelezen: een streepje in de huisstijlkleur, geen vet en geen kleurvlak - anders
   schreeuwen acht regels tegelijk. Zelfde keuze als in de lijst op /berichten. */
.bell-item.is-new a {
    box-shadow: inset 3px 0 0 var(--brand-primary);
}

.bell-text {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}

.bell-text strong {
    font-size: 0.88rem;
    line-height: 1.3;
}

.bell-text small {
    font-size: 0.78rem;
    line-height: 1.3;
}

.bell-all {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-top: 0.5rem;
    padding: 0.55rem 0.4rem 0.2rem;
    border-top: 1px solid var(--border);
    color: var(--brand-primary);
    font-size: 0.85rem;
    text-decoration: none;
}

.launcher-legend {
    margin: 0.25rem 0.4rem 0;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.launcher-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
    gap: 0.25rem;
    /* Elke tegel even hoog. Zonder dit bepaalt de langste naam de hoogte van zijn rij
       en staan de iconen van de volgende rij op een andere lijn - dat is wat het
       rommelig maakte, niet de iconen zelf. */
    align-items: stretch;
}

/* Een module is een link als je hem hebt, en een formulier als je hem niet hebt; die
   twee moeten er hetzelfde uitzien, dus de opmaak zit op het blok eromheen. */
.launcher-item,
.launcher-button {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    width: 100%;
    padding: 0.7rem 0.4rem;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: var(--text);
    font: inherit;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--transition);
}

.launcher-item:hover,
.launcher-button:hover:not([disabled]) {
    background: var(--sidebar-hover);
}

.launcher-item-locked {
    margin: 0;
    padding: 0;
}

.launcher-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Groot: in een venster vol modules is het plaatje waar je op mikt, niet de naam.
       Vier kolommen in een paneel van 32rem laten ruim vier centimeter per tegel over,
       dus dit past zonder dat de namen in de knel komen. */
    width: 4rem;
    height: 4rem;
    border-radius: var(--radius);
    background: color-mix(in srgb, var(--brand-primary) 12%, transparent);
    color: var(--brand-primary);
    font-size: 1.7rem;
}

/* Heeft een module een eigen afbeelding, dan is die al kleurrijk: een getint vlak
   eromheen maakt er een tweede kleur bij en dat vecht. */
.launcher-icon:has(img) {
    background: none;
}

.launcher-icon .module-icon {
    width: 3.1rem;
    height: 3.1rem;
}

.launcher-name {
    font-size: 0.8rem;
    line-height: 1.25;
    /* Twee regels ruimte, ook bij een korte naam: dan staan de namen van een rij op
       dezelfde hoogte en hoeft niets te verspringen. */
    min-height: 2.5em;
}

/* Wat je niet hebt: te zien, maar duidelijk anders dan wat je wel hebt. Eén signaal in
   plaats van twee: lichter, en geen label eronder. Ook het plaatje wordt gedempt - een
   module die je niet hebt hoort niet feller te zijn dan een die je wel hebt. */
.launcher-button[disabled],
.launcher-item-locked .launcher-icon,
.launcher-item-locked .launcher-name {
    color: var(--text-muted);
}

.launcher-item-locked .launcher-icon {
    background: var(--sidebar-hover);
}

/* Maar niet achter een eigen afbeelding. Die modulebeelden hebben hun eigen vorm en
   staan op een transparante achtergrond; een grijs blokje eromheen maakt er een knop
   van die er niet is. Dat gold al voor wat je wél hebt (.launcher-icon:has(img)); deze
   regel stond daar overheen omdat hij later komt. */
.launcher-item-locked .launcher-icon:has(img) {
    background: none;
}

.launcher-item-locked .launcher-icon img {
    opacity: 0.45;
    filter: grayscale(0.6);
}

/* Bij het aanwijzen komt hij weer tot leven: dan kijk je ernaar */
.launcher-item-locked:hover .launcher-icon img {
    opacity: 0.85;
    filter: none;
}

.launcher-tag {
    font-size: 0.65rem;
    color: var(--text-muted);
    background: var(--sidebar-hover);
    border-radius: 999px;
    padding: 0.1rem 0.5rem;
}

/* --- Zoeken bovenin ------------------------------------------------------ */
.topbar-search {
    margin: 0;
    /* Niet meegroeien: de vrije ruimte hoort links van het veld te zitten */
    flex: 0 1 24rem;
    min-width: 10rem;
}

.topbar-search-wrap {
    position: relative;
}

.topbar-search-icon {
    position: absolute;
    right: 0.8rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    font-size: 0.85rem;
    pointer-events: none;
}

.topbar-search-input {
    width: 100%;
    padding: 0.4rem 2rem 0.4rem 0.8rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--bg);
    color: var(--text);
    font: inherit;
    font-size: var(--text-ui);
}

.topbar-search-input:focus {
    outline: 2px solid var(--brand-primary);
    outline-offset: 1px;
    background: var(--surface);
}

/* Het paneel met de treffers, onder het veld */
.search-panel {
    position: absolute;
    top: calc(100% + 0.4rem);
    left: 0;
    right: 0;
    z-index: 45;
    max-height: min(70vh, 28rem);
    overflow: auto;
    padding: 0.35rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

.search-group {
    padding: 0.55rem 0.6rem 0.25rem;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.search-hit {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.4rem 0.6rem;
    border-radius: var(--radius);
    color: var(--text);
    text-decoration: none;
}

.search-hit:hover,
.search-hit.is-active {
    background: var(--sidebar-hover);
}

.search-hit-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1.8rem;
    height: 1.8rem;
    border-radius: var(--radius);
    background: color-mix(in srgb, var(--brand-primary) 12%, transparent);
    color: var(--brand-primary);
    font-size: 0.8rem;
}

/* min-width: 0 is wat de tekst laat afkappen in plaats van het paneel op te rekken */
.search-hit-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.25;
}

.search-hit-label,
.search-hit-sub {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.search-hit-label {
    font-size: var(--text-ui);
}

.search-hit-sub {
    font-size: 0.75rem;
    color: var(--text-muted);
}

.search-empty,
.search-all {
    margin: 0;
    padding: 0.6rem;
    font-size: 0.78rem;
    color: var(--text-muted);
    text-align: center;
}

.search-all {
    border-top: 1px solid var(--border);
    margin-top: 0.25rem;
}

/* De hele lijst op /zoeken: dezelfde regel, wat ruimer */
.search-results {
    list-style: none;
    margin: 0;
    padding: 0;
}

.search-result {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0.4rem;
    border-radius: var(--radius);
    color: var(--text);
    text-decoration: none;
}

.search-result:hover {
    background: var(--sidebar-hover);
}

.search-result-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: var(--radius);
    background: color-mix(in srgb, var(--brand-primary) 12%, transparent);
    color: var(--brand-primary);
}

.search-result-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* Smal scherm: het zoekveld neemt te veel van de balk in */
@media (max-width: 60rem) {
    .topbar-search {
        display: none;
    }
}

/* De regel in een lijst die over je eigen omgeving gaat. Een supervisor met dertig
   tenants zoekt anders elke keer waar hij zelf is. Een tint van de merkkleur, geen
   volle kleur: het is een aanwijzing, geen waarschuwing. */
tr.row-here > td {
    background: color-mix(in srgb, var(--brand-primary) 7%, transparent);
}

tr.row-here > td:first-child {
    box-shadow: inset 3px 0 0 var(--brand-primary);
}

.tag-here {
    background: color-mix(in srgb, var(--brand-primary) 14%, transparent);
    color: var(--brand-primary);
}

/* Een kolom met alleen een selectievakje: zo smal als het vakje zelf */
.cell-check {
    width: 1px;
    padding-right: 0.25rem;
    white-space: nowrap;
}

/* Een blok dat direct op een tabel volgt, heeft lucht nodig - anders lijkt het erbij te
   horen in plaats van erna te komen */
.form-spaced {
    margin-top: 1.5rem;
}

/* Een formulier dat alleen bestaat om een knop elders zijn actie te geven (form="...") */
.form-hidden {
    display: none;
}

/* Het zoekveld boven een bladerlijst: smaller dan de pagina, want het is één woord */
.region-search {
    max-width: 28rem;
    margin-bottom: 1.25rem;
}

/* Een knop onder een tabel heeft lucht nodig: zonder lijkt hij bij de laatste regel te
   horen in plaats van bij de tabel als geheel. De tekst ernaast staat op dezelfde as
   als de knop, niet bovenaan. */
.form-actions-spaced {
    margin-top: 1.25rem;
    align-items: center;
    gap: 1rem;
}

/* Energielabel als gekleurde badge (tool Energielabel).
   Drie tonen in plaats van twaalf: de schaal van EP-Online loopt van A+++++ tot G, maar
   twaalf eigen kleuren betekent twaalf tokens die ook in beide donkere blokken moeten
   staan - en die houdt niemand uit elkaar. De indeling zit in epOnlineClassTone().
   Geen eigen kleuren hier: dit zijn de bestaande tokens, dus donker klopt vanzelf. */
.energy-label {
    display: inline-block;
    min-width: 2.4rem;
    padding: 0.1rem 0.6rem;
    border-radius: 6px;
    text-align: center;
    font-weight: 700;
    background: var(--border);
    color: var(--text-muted);
}

.energy-good { background: var(--success-bg); color: var(--success-text); }
.energy-mid { background: var(--warning-bg); color: var(--warning-text); }
.energy-bad { background: var(--error-bg); color: var(--error-text); }

/* ─── Wachtwoordveld met oogje en sterktemeter ──────────────────────────────
   De regels zelf staan in passwordRules() (PHP) en komen als data in de HTML;
   assets/js/password.js zet hier alleen klassen op. Alle kleuren zijn tokens, dus het
   donkere thema klopt vanzelf. */

.pw-field {
    position: relative;
    display: block;
}

.pw-field input {
    width: 100%;
    padding-right: 2.6rem;
}

.pw-eye {
    position: absolute;
    top: 50%;
    right: 0.5rem;
    transform: translateY(-50%);
    border: 0;
    background: none;
    cursor: pointer;
    padding: 0.3rem;
    color: var(--text-muted);
}

.pw-eye:hover,
.pw-eye[aria-pressed="true"] {
    color: var(--text);
}

.pw-meter {
    margin: 0.5rem 0 0.2rem;
}

/* De balk: vier stappen die vollopen. Een pijlpunt aan de rechterkant, zodat het
   leest als een schaal die ergens heen loopt in plaats van vier losse blokjes. */
.pw-bar {
    display: flex;
    gap: 3px;
    margin-bottom: 0.4rem;
}

.pw-step {
    flex: 1;
    height: 8px;
    background: var(--border);
    clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 50%, calc(100% - 6px) 100%, 0 100%, 6px 50%);
}

.pw-step:first-child { clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 50%, calc(100% - 6px) 100%, 0 100%); }
.pw-step:last-child { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 6px 50%); }

.pw-level-1 .pw-step:nth-child(-n+1),
.pw-level-2 .pw-step:nth-child(-n+2),
.pw-level-3 .pw-step:nth-child(-n+3),
.pw-level-4 .pw-step:nth-child(-n+4) {
    background: var(--warning-text);
}

.pw-level-3 .pw-step:nth-child(-n+3),
.pw-level-4 .pw-step:nth-child(-n+4) {
    background: var(--success-text);
}

.pw-level-1 .pw-step:first-child {
    background: var(--error-text);
}

.pw-verdict {
    margin: 0 0 0.4rem;
    font-size: 0.85rem;
    font-weight: 600;
    min-height: 1.1em;
    color: var(--text-muted);
}

.pw-rules {
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.pw-rules li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.1rem 0;
}

/* Een bolletje dat een vinkje wordt zodra de regel gehaald is. Niet alleen de kleur
   verandert: wie kleuren slecht onderscheidt, ziet dan nog steeds het verschil. */
.pw-dot {
    font-size: 0.5rem;
    width: 1em;
    text-align: center;
}

.pw-rules li.is-ok {
    color: var(--success-text);
}

.pw-rules li.is-ok .pw-dot::before {
    content: "00c";
    font-size: 0.75rem;
}

/* Het keuzeblokje voor de ondergrond (Leaflet's layers-control) in de huisstijl.
   Leaflet zet zijn eigen witte doos neer; die valt uit de toon en is in het donkere
   thema een lichtvlek. Alleen tokens, dus beide thema's kloppen vanzelf. */
.leaflet-control-layers {
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

.leaflet-control-layers-toggle {
    background-color: var(--surface);
}

.leaflet-control-layers-expanded {
    padding: 0.5rem 0.7rem;
    font-size: 0.85rem;
}

.leaflet-control-layers-list label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0.15rem 0;
    font-weight: 400;
    cursor: pointer;
}

/* De bronvermelding hoort leesbaar te zijn: bij PDOK is het een licentievoorwaarde
   en geen kleine letter die weg mag. */
.leaflet-control-attribution {
    background: var(--surface);
    color: var(--text-muted);
}

.leaflet-control-attribution a {
    color: var(--text-muted);
}

/* De kleine kaart met één speld krijgt dezelfde behandeling als de grote: een watermerk
   erop en een knop om te vergroten. Zonder die twee was het een wit vlak met een speld -
   geen schaal, geen herkomst, en te klein om een straat in te herkennen. */
.pin-map-card .map-wrap {
    position: relative;
}

.pin-map-card .map-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.5rem;
}

[data-map-card].is-map-full .map-actions {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    z-index: 1000;
    margin: 0;
}

/* De eerdere leveringen van een brondatasoort: ingeklapt onder de regel van de actieve.
   Er komen er algauw tien van elke soort en maar één telt; die negen andere horen
   bereikbaar te zijn zonder het overzicht te zijn.

   Geen tabel in een tabel: die verzint eigen kolombreedtes die nergens op uitlijnen, en
   dan leest het als een losse sectie tussen twee rijen in plaats van als iets dat bij de
   regel erboven hoort. Een streep links zegt dat wel. */
.source-history > td {
    padding: 0 0 0.5rem 1.5rem;
    border-top: 0;
}

.source-history summary {
    cursor: pointer;
    font-size: 0.85rem;
    color: var(--text-muted);
    padding: 0.2rem 0;
}

.source-history-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem;
    padding: 0.3rem 0 0.3rem 0.75rem;
    border-left: 2px solid var(--border);
    font-size: 0.85rem;
}

/* Een categorie met zijn aandeelveld ernaast. Het vinkje neemt de ruimte, het veld staat
   rechts en verschijnt pas als de categorie meetelt - een aandeel bij iets dat niet
   meedoet is een instelling die nergens op slaat. */
/* Het aandeelveld hoort NIET meer in de boom: het stond daar meters rechts van de
   categorie waar het bij hoorde, in een rij zo breed als het scherm. Het verhuist naar het
   paneel met je selectie, waar naam, bedrag en aandeel naast elkaar staan. In de boom
   blijft het staan maar verborgen, zodat een ingetypte waarde bewaard blijft als je een
   categorie even uitvinkt. */
.category-row {
    display: block;
}

/* Kiezen uit een lange lijst met een mand ernaast die meeloopt bij het scrollen.
   Algemeen gehouden: dit past net zo goed bij het kiezen van gebieden, waar de mand nu
   nog onder de lijst staat en je dus moet scrollen om te zien wat je hebt.

   De mand blijft onder de bovenbalk hangen (die staat zelf sticky op top: 0) en krijgt
   een eigen schuifbalk als de selectie lang wordt - anders duwt hij de pagina op en scrol
   je alsnog. */
.picker-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 20rem;
    gap: 1.25rem;
    align-items: start;
}

.picker-main {
    min-width: 0;
}

.picker-basket {
    position: sticky;
    top: 4.5rem;
    max-height: calc(100vh - 6rem);
    overflow-y: auto;
    padding: 0.85rem 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
}

.picker-basket h3 {
    margin: 0 0 0.6rem;
}

/* Het totaal van de mand: dikker dan de regels erboven, want dat is waar je naar kijkt
   terwijl je klikt. */
.basket-total {
    margin: 0.6rem 0 0.4rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--border);
}

/* Onder de 62rem past er geen tweede kolom naast; dan gaat de mand gewoon eronder en
   blijft hij staan waar hij staat. Een mand die op een telefoon over de lijst plakt,
   neemt de halve pagina. */
@media (max-width: 62rem) {
    .picker-layout {
        grid-template-columns: minmax(0, 1fr);
    }

    .picker-basket {
        position: static;
        max-height: none;
    }
}

.chosen-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.35rem 0;
    border-bottom: 1px solid var(--border);
}

.chosen-row:last-of-type {
    border-bottom: 0;
}

.chosen-name {
    flex: 1;
    min-width: 0;
}

.chosen-amount {
    flex: 0 0 auto;
    font-size: 0.85rem;
}

.category-factor {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    flex: 0 0 auto;
    font-size: 0.85rem;
}

.category-factor input {
    width: 4.5rem;
    text-align: right;
}

/* Een tip bij een categorie waar de brondata iets anders meet dan je zou denken. Geen
   waarschuwingskleur: het is advies en geen fout. */
.category-hint {
    display: block;
    margin-top: 0.2rem;
    padding: 0.3rem 0.5rem;
    border-left: 2px solid var(--border);
    background: var(--bg);
    color: var(--text-muted);
    line-height: 1.4;
}

.category-hint i {
    margin-right: 0.3rem;
}

/* Zoekveld boven een lange lijst met selectievakjes. Staat los van .form-row omdat het
   geen invoer is die wordt opgeslagen: het filtert alleen wat je ziet. */
.spending-search {
    display: block;
    margin: 0 0 0.6rem;
}

.spending-search input {
    width: 100%;
    max-width: 22rem;
}

/* De stappen om een bron bij te werken, en de tests die erbij horen. Allebei lijsten die
   je naast een terminal leest, dus ruim opgezet en met de commando's als code. */
.source-howto {
    margin: 0 0 1rem;
    padding-left: 1.4rem;
    line-height: 1.6;
}

.source-howto li {
    margin-bottom: 0.5rem;
}

.source-tests {
    list-style: none;
    margin: 0 0 0.75rem;
    padding: 0;
}

.source-tests li {
    padding: 0.45rem 0;
    border-bottom: 1px solid var(--border);
}

.source-tests li:last-child {
    border-bottom: 0;
}

/* De modules die op een brondatasoort draaien: chips met een icoon, zodat je in een
   oogopslag ziet wat er wegvalt als die levering wegvalt. Een telling ("gebruikt door 5
   modules") dwingt je om ergens anders te gaan kijken welke vijf dat dan zijn. */
.source-modules {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    list-style: none;
    margin: 0 0 0.75rem;
    padding: 0;
}

.source-modules li {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.3rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
    font-size: 0.9rem;
}

.source-modules i {
    color: var(--text-muted);
}

/* De knop staat NAAST de gegevens en niet rechts uitgelijnd. Met `margin-left: auto`
   belandde hij aan de uiterste rechterkant van een td met colspan=8, in een tabel die
   breder is dan het scherm - dus buiten beeld, terwijl het de enige knop op deze regel is
   en de reden dat je het blok openklapt. */
.source-history-row form {
    margin-left: 0.4rem;
}

/* Een staaf die zijn eigen betekenis heeft: een energielabel van A tot G zegt meer in
   groen en rood dan in één kleur. Dezelfde indeling als de badge bij een gevonden label
   (epOnlineClassTone()), zodat groen hier hetzelfde betekent als groen daar. */
.value-bar.bar-good { fill: var(--success-text); }
.value-bar.bar-mid { fill: var(--warning-text); }
.value-bar.bar-bad { fill: var(--error-text); }


/* ─── Juridische documenten ───────────────────────────────────────────────────
   Privacy, algemene voorwaarden en verwerkersovereenkomst. Ze staan op de plain-page
   (zonder menu) omdat ze zonder login te lezen zijn, maar een document is geen
   inlogformulier: de kaart mag breder. */

.plain-card.legal-card {
    max-width: 56rem;
    text-align: left;
}

.legal-page .plain-card {
    margin: 2rem auto;
}

.legal-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1rem;
    margin-bottom: 1.5rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--border);
    font-size: 0.85rem;
}

.legal-nav a {
    color: var(--text-muted);
    text-decoration: none;
}

.legal-nav a:hover {
    color: var(--text);
    text-decoration: underline;
}

.legal-nav-current {
    font-weight: 600;
    color: var(--text);
}

/* Terug naar de toepassing hoort niet tussen de documenten te staan: het is een andere
   soort link. Rechts, en met ruimte ervoor. */
.legal-nav-back {
    margin-left: auto;
}

.legal-meta {
    margin: -0.5rem 0 1.5rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.legal-doc h2 {
    margin: 2rem 0 0.75rem;
    font-size: 1.1rem;
}

.legal-doc h2:first-child {
    margin-top: 1rem;
}

.legal-doc hr {
    margin: 2.5rem 0;
    border: 0;
    border-top: 1px solid var(--border);
}

.legal-doc li {
    margin-bottom: 0.4rem;
}

.legal-doc .table {
    margin: 0 0 1rem;
}

/* Wat er nog ingevuld moet worden. Een leeg gat in een verwerkersovereenkomst is erger
   dan een zichtbaar gat: dat eerste ziet eruit alsof het document klaar is. */
.legal-gap {
    background: var(--warning-bg);
    color: var(--warning-text);
    padding: 0 0.25rem;
    border-radius: 3px;
    font-style: normal;
    font-weight: 600;
}

/* Een module in een tabelcel: icoon links, naam ernaast, en een omschrijving eronder als
   de omgeving hem niet afneemt. Het icoon hoort bij de eerste regel te blijven staan en
   niet in het midden van twee regels tekst - zelfde reden als bij .checkbox-with-note. */
.module-cell {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
}

.module-cell > i {
    margin-top: 0.15rem;
    color: var(--text-muted);
}

.module-cell small {
    display: block;
    margin-top: 0.1rem;
}

/* ─── Licentie: de mand blijft in beeld ───────────────────────────────────────
   Je verandert links een aantal en kijkt rechts wat het met je jaarbedrag doet. Op een
   smal scherm staan ze onder elkaar, met de mand bovenaan: daar kijk je naar. */

.license-layout {
    display: grid;
    gap: 1.25rem;
    grid-template-columns: minmax(0, 1fr) 20rem;
    align-items: start;
}

.license-basket {
    position: sticky;
    top: 1rem;
}

@media (max-width: 60rem) {
    .license-layout {
        grid-template-columns: 1fr;
    }

    .license-basket {
        position: static;
        order: -1;
    }
}

/* Een regel waarvan het aantal afwijkt van wat er nu afgenomen wordt */
.table tr.is-changed > td {
    background: var(--info-bg);
}

.amount-up { color: var(--error-text); }
.amount-down { color: var(--success-text); }

.license-due {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    margin: 1rem 0 0;
    padding-top: 0.75rem;
    border-top: 2px solid var(--border);
    font-size: 1.05rem;
}

.license-order {
    margin-top: 1.25rem;
}

/* Twee velden in één cel: het percentage en het minimum van een serviceniveau */
.sla-price-cell {
    display: flex;
    gap: 0.4rem;
}

.sla-price-cell input {
    width: 6rem;
}

/* Uitleg onder een voorwaarde in een doelgroepregel: wat de parameter betekent, waar je op
   moet letten, en bij hoeveel gebieden hij ontbreekt. Dat laatste is geen bijzaak - een
   onbekende waarde matcht nooit, dus die gebieden vallen door de voorwaarde heen. */
.rule-note {
    margin: 0.25rem 0 0.75rem;
    padding-left: 0.75rem;
    border-left: 2px solid var(--border);
}

.rule-note p {
    margin: 0.2rem 0;
    font-size: 0.85rem;
}

.rule-caution {
    color: var(--warning-text);
}


/* ── Postcodegebieden bij elkaar klikken ────────────────────────
   Het venster van services/zip_picker.php. Hier wordt gewerkt en niet gelezen: de kaart
   krijgt alles wat het venster overhoudt, de uitleg staat als een regel eronder, en de
   zijkolom is smal en vast. Een venster dat met de inhoud meegroeit laat de kaart onder je
   muis wegspringen zodra er een cijfer bij komt. */
.zip-picker-dialog {
    width: min(84rem, calc(100vw - 2rem));
    max-height: calc(100vh - 2rem);
}

/* **De indeling alleen als het venster openstaat.** Een gesloten `<dialog>` is onzichtbaar
   doordat de browser er `display: none` op zet, en elke eigen `display` wint daarvan - dus
   een kale `display: flex` hierboven zette het venster op élke pagina onderaan in beeld.
   Dat is niet zichtbaar in het venster zelf, alleen op de pagina eronder. */
.zip-picker-dialog[open] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.zip-picker-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 17rem;
    gap: 1rem;
    align-items: stretch;
    min-height: 0;
}

/* Eén gebied kiezen vraagt geen lijst en geen plakvak: dan is de kaart het hele venster */
.zip-picker-dialog.is-single .zip-picker-side,
.zip-picker-dialog.no-figures .zip-picker-figures {
    display: none;
}

.zip-picker-dialog.is-single .zip-picker-body {
    grid-template-columns: minmax(0, 1fr);
}

@media (max-width: 900px) {
    .zip-picker-body {
        grid-template-columns: minmax(0, 1fr);
    }
}

.zip-picker-main {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-width: 0;
}

/* Het kaartvlak draagt het watermerk, dus het moet een eigen positie hebben; de kaart
   zelf vult het. Dat is dezelfde opbouw als bij modules/_map.php. */
.zip-picker-canvas {
    position: relative;
    height: min(68vh, 40rem);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--bg);
}

.zip-picker-map {
    width: 100%;
    height: 100%;
}

/* De uitleg hoort onder de kaart en niet erboven: je leest hem als je even niet weet wat
   te doen, en dan wil je niet dat hij permanent een stuk kaart heeft gekost. */
.zip-picker-hint {
    margin: 0;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.zip-picker-note {
    margin-left: 0.5rem;
    color: var(--text);
    font-weight: 600;
}

.zip-picker-note.is-warning {
    color: var(--warning-text);
    font-weight: 400;
}

.zip-picker-side {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-height: 0;
}

/* De telling bovenaan, groot genoeg om hem vanaf de kaart in je ooghoek te zien */
.zip-picker-summary {
    display: grid;
    gap: 0.1rem;
    padding: 0.75rem 0.9rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.zip-picker-total {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.1;
}

.zip-picker-unit {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.zip-picker-people {
    font-size: 0.8rem;
    color: var(--text-muted);
}

/* De gekozen gebieden als blokjes. Scrollen binnen de kolom en niet het venster laten
   groeien: bij tweehonderd gebieden zou de kaart anders van het scherm af zakken. */
.zip-picker-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin: 0;
    padding: 0;
    list-style: none;
    overflow-y: auto;
    max-height: 11rem;
}

.zip-picker-chips li {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    overflow: hidden;
}

.zip-chip-go,
.zip-chip-off {
    border: 0;
    background: none;
    color: var(--text);
    cursor: pointer;
    font: inherit;
    font-size: 0.8rem;
    padding: 0.2rem 0.55rem;
    line-height: 1.4;
}

.zip-chip-go {
    font-variant-numeric: tabular-nums;
}

.zip-chip-go:hover {
    color: var(--brand-primary);
}

.zip-chip-off {
    color: var(--text-muted);
    padding-left: 0.3rem;
    padding-right: 0.45rem;
}

.zip-chip-off:hover {
    color: var(--error-text);
}

.zip-picker-figures {
    overflow-y: auto;
    min-height: 0;
}

.zip-picker-figures table {
    margin: 0;
    font-size: 0.8rem;
}

.zip-picker-figures td {
    padding: 0.15rem 0.3rem;
}

/* Plakken is de uitzondering en klikken de bedoeling, dus het tekstvak zit weggeklapt */
.zip-picker-codes summary {
    cursor: pointer;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.zip-picker-codes textarea {
    margin-top: 0.4rem;
    font-family: ui-monospace, 'Cascadia Mono', Consolas, monospace;
    font-size: 0.8rem;
}

.zip-picker-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Alles wissen hoort niet naast Overnemen en Annuleren te staan alsof het een derde
   gelijkwaardige uitweg is: het hoort bij de kaart, niet bij het afsluiten. */
.zip-picker-actions .btn-quiet {
    margin-left: auto;
    border-color: transparent;
    background: none;
    color: var(--text-muted);
}

.zip-picker-actions .btn-quiet:hover {
    color: var(--text);
    border-color: var(--border);
}

/* De knop die het venster opent, staat IN het veld: een knop over de volle breedte
   eronder leest als een actie van het formulier. */
.zip-picker-field {
    position: relative;
    display: block;
}

.zip-picker-field .has-zip-picker {
    padding-right: 2.4rem;
}

.zip-picker-open {
    position: absolute;
    top: 50%;
    right: 0.4rem;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    padding: 0;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: var(--text-muted);
    cursor: pointer;
}

/* Bij een tekstvlak hoort hij bovenin: daar begint de tekst, en onderin zit de greep
   waarmee je het vlak groter sleept. */
.zip-picker-field.is-area .zip-picker-open {
    top: 0.4rem;
    transform: none;
}

.zip-picker-open:hover {
    background: var(--bg);
    color: var(--brand-primary);
}

/* ── Een tabblad met iets visueels ernaast ─────────────────────────────────
   De tabbladen staan over de volle breedte; de inhoud eronder deelt zich in tweeen zodra
   er rechts iets te zien is. Zonder dat tweede blok houdt de inhoud de hele breedte - een
   lege kolom laten staan is ruimte weggeven voor niets. */
.location-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
    align-items: start;
}

.location-layout.has-side {
    grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
}

@media (max-width: 1100px) {
    .location-layout.has-side {
        grid-template-columns: minmax(0, 1fr);
    }
}

.location-side {
    display: grid;
    gap: 1rem;
    align-items: start;
}


/* ── Het merk van een profiel ──────────────────────────────────────────────
   Een icoon in een gekleurd rondje, zodat "Bezoekers 2024" en "Bezoekers 2024 herzien" in
   een lijst uit elkaar te houden zijn aan iets anders dan hun naam. De kleur komt van
   list.js, want een style-attribuut mag niet van de CSP. */
.profile-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    margin-right: 0.4rem;
    border-radius: 999px;
    background: var(--profile-color, var(--bg));
    color: #fff;
    font-size: 0.75rem;
    vertical-align: -0.3rem;
}

/* Zonder kleur geen witte tekst op een lichte achtergrond */
.profile-mark:not([data-profile-color]) {
    background: var(--bg);
    color: var(--text-muted);
}

/* Twee velden naast elkaar: het icoon en de kleur horen bij elkaar en nemen samen minder
   ruimte in dan twee regels onder elkaar. */
.field-row {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    align-items: flex-end;
}


/* De legenda onder de kaart van de postcodekiezer: het streepje dat zegt dat een gebied al
   bij een andere vestiging hoort. Dezelfde kleur als de kaart, hier als blokje. */
.zip-picker-legend {
    margin-left: 0.5rem;
}

.zip-picker-key {
    display: inline-block;
    width: 0.8rem;
    height: 0.8rem;
    margin-right: 0.2rem;
    border: 1px dashed #7b60a8;
    background: rgba(123, 96, 168, 0.22);
    vertical-align: -0.1rem;
}


/* ── Verzorgingsgebieden ───────────────────────────────────────────────────
   De acties van een rij op één regel. Drie knoppen onder elkaar maakte van elke rij een blok
   van vier regels hoog, en dan is een lijst van zeventig vestigingen niet meer te overzien. */
.area-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
}

.area-actions .form-inline {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    margin: 0;
}

.area-actions select {
    width: auto;
    min-width: 5.5rem;
}

/* De regel boven de tabel waarmee je alle lege gebieden in één keer vult */
.area-bulk {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 1rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
}

.area-bulk select {
    width: auto;
}


/* ── Rayons indelen ────────────────────────────────────────────────────────
   Eén werkblad: de lijst met vestigingen links, de kaart rechts. De kaart krijgt alles wat
   overblijft, want daar gebeurt het werk. */
.rayon-page {
    display: grid;
    grid-template-columns: 17rem minmax(0, 1fr);
    gap: 1rem;
    align-items: start;
}

@media (max-width: 900px) {
    .rayon-page {
        grid-template-columns: minmax(0, 1fr);
    }
}

.rayon-side {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    max-height: min(78vh, 46rem);
    padding: 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.rayon-head h2 {
    margin: 0 0 0.3rem;
    font-size: 1.1rem;
}

.rayon-head p {
    margin: 0 0 0.5rem;
    font-size: 0.8rem;
}

.rayon-search input {
    width: 100%;
}

.rayon-list {
    margin: 0;
    padding: 0;
    list-style: none;
    overflow-y: auto;
    min-height: 0;
}

.rayon-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.4rem 0.5rem;
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: var(--text);
    font: inherit;
    font-size: 0.9rem;
    text-align: left;
    cursor: pointer;
}

.rayon-item:hover {
    background: var(--bg);
}

.is-active > .rayon-item {
    background: var(--bg);
    font-weight: 600;
    box-shadow: inset 0 0 0 1px var(--brand-primary);
}

/* Het kleurvlakje van een vestiging: dezelfde kleur als haar gebied op de kaart */
.rayon-swatch {
    flex: none;
    width: 0.8rem;
    height: 0.8rem;
    border-radius: 2px;
}

.rayon-item-name {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rayon-item-count {
    flex: none;
    font-size: 0.8rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.rayon-item-count.is-empty {
    opacity: 0.6;
}

.rayon-main {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-width: 0;
}

.rayon-canvas {
    position: relative;
    height: min(72vh, 44rem);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--bg);
}

.rayon-map {
    width: 100%;
    height: 100%;
}

.rayon-hint {
    margin: 0;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.rayon-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
}

.rayon-actions .btn-quiet {
    margin-left: auto;
    border-color: transparent;
    background: none;
    color: var(--text-muted);
}
