/* ── Geist (self-hosted, CSP-veilig — geen Google Fonts/CDN) ──
   square-ui-restyle (backofficev2). Variable woff2 uit het geist-pakket. */
@font-face {
  font-family: "Geist";
  src: url("/backofficev2/assets/fonts/geist-latin.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Geist";
  src: url("/backofficev2/assets/fonts/geist-latin-ext.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/backofficev2/assets/fonts/geist-mono-latin.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
}

/* Iselmar Receptie — Cursor grey / light theme layer
   Loaded after style.css — overrides legacy beige/navy styling */

/* ── Tokens ── */
/* html[data-theme=...] (0,1,1) wint bewust van de tenant-CSS die het palet op
   :root (0,1,0) zet en ná dit bestand laadt. Een EXPLICIET gekozen thema gaat
   dus vóór de tenant-default. (Zonder deze hogere specificiteit overschreef
   /api/v1/theme/iselmar.css elk token hier → grey/light deden niets.) */
html[data-theme="grey"] {
  --type-scale: 1.2;
  --font: "Geist", "Inter", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SFMono-Regular", monospace;
  --success: #5fb487;
  --success-soft: rgba(95,180,135,.16);
  --warning: #e0913f;
  --warning-soft: rgba(224,145,63,.16);
  --danger: #e07a70;
  --danger-soft: rgba(224,122,112,.16);
  /* Zesde badgekleur, toegevoegd 28 aug 2026 voor het logboek: de bron van een
     handeling kent zes soorten (ui, gast, systeem, cron, webhook, api) en de
     bestaande vier statuskleuren dekken er vijf. Zonder token stond hier een
     hardgecodeerde violet die in dark mode niet meebewoog. */
  --info: #a78bfa;
  --info-soft: rgba(167,139,250,.16);
  /* Iselmar lichtblauw accent (matcht webapp #577C8E). */
  --accent: #577C8E;
  --accent-hover: #6E93A6;
  --accent-soft: rgba(87,124,142,.18);
  --bg: #0e0f0d;
  --panel: #181915;
  --surface: #24251f;
  --rail: #141511;
  --border: #2a2b26;
  --border-strong: #3a3b34;
  --text: #ededea;
  --text-muted: #a4a69d;
  --text-faint: #6c6e65;
  --nav-link: #a4a69d;
  --hover: #20211c;
  --active-bg: #24251f;
  --slot-booked: rgba(255,255,255,.06);
  --slot-booked-border: rgba(87,124,142,.55);
  --slot-booked-text: #D4D4D8;
  --modal-overlay: rgba(0,0,0,.55);
  --shadow: 0 8px 24px rgba(0,0,0,.35);
  /* Restaurant status (muted, theme-aware) */
  --rest-peak: rgba(87,124,142,.16);
  --rest-hp: rgba(74,155,127,.16);
  --rest-hp-border: rgba(74,155,127,.35);
  --rest-req: rgba(184,147,90,.14);
  --rest-alacarte: rgba(78,139,201,.14);
  --rest-alacarte-border: rgba(78,139,201,.28);
  --rest-group: rgba(78,139,201,.12);
  --rest-confirmed: rgba(78,139,201,.1);
  --rest-confirmed-border: rgba(78,139,201,.22);
  --rest-cancelled: rgba(184,107,107,.14);
  --rest-seated: rgba(74,155,127,.18);
  --rest-done: rgba(255,255,255,.04);
  /* Legacy aliases */
  --beige: var(--bg);
  --white: var(--panel);
  --sky: var(--slot-booked);
  --teal: var(--accent);
  --navy: var(--text);
  --ink: var(--text);
  --muted: var(--text-muted);
  --line: var(--border);
  --line-soft: var(--border);
  --accent-legacy: var(--accent);
  --terracotta: var(--accent);
}

html[data-theme="light"] {
  --type-scale: 1.2;
  --font: "Geist", "Inter", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SFMono-Regular", monospace;
  /* LIGHT palet (warm crème + Iselmar lichtblauw accent). */
  --accent: #2196C4;
  --accent-hover: #1b86ae;
  --accent-soft: rgba(87,124,142,.14);
  --success: #2f8f5b;
  --success-soft: rgba(47,143,91,.12);
  --warning: #c2620d;
  --warning-soft: #fbecdc;
  --danger: #c0453b;
  --danger-soft: rgba(192,69,59,.1);
  --info: #6D28D9;
  --info-soft: rgba(124,58,237,.10);
  --bg: #f6f6f4;
  --panel: #ffffff;
  --surface: #eeeeec;
  --rail: #fbfbfa;
  --border: #ececea;
  --border-strong: #dcdcd6;
  --text: #1c1d1a;
  --text-muted: #5b5d57;
  --text-faint: #94968e;
  --nav-link: #5b5d57;
  --hover: #f4f4f2;
  --active-bg: #eeeeec;
  --slot-booked: #FFFFFF;
  --slot-booked-border: rgba(87,124,142,.6);
  --slot-booked-text: #1A1A1A;
  --modal-overlay: rgba(0,0,0,.4);
  --shadow: 0 8px 24px rgba(0,0,0,.12);
  --rest-peak: rgba(87,124,142,.11);
  --rest-hp: rgba(5,150,105,.1);
  --rest-hp-border: rgba(5,150,105,.28);
  --rest-req: rgba(217,119,6,.1);
  --rest-alacarte: rgba(78,139,201,.1);
  --rest-alacarte-border: rgba(78,139,201,.25);
  --rest-group: rgba(78,139,201,.08);
  --rest-confirmed: rgba(78,139,201,.08);
  --rest-confirmed-border: rgba(78,139,201,.2);
  --rest-cancelled: rgba(220,38,38,.08);
  --rest-seated: rgba(5,150,105,.12);
  --rest-done: rgba(0,0,0,.04);
  --beige: var(--bg);
  --white: var(--panel);
  --sky: var(--surface);
  --teal: var(--accent);
  --navy: var(--text);
  --ink: var(--text);
  --muted: var(--text-muted);
  --line: var(--border);
  --line-soft: var(--border);
  --terracotta: var(--accent);
}

/* ── Global ── */
html, body {
  background: var(--bg) !important;
  color: var(--text) !important;
  font-family: var(--font) !important;
  font-feature-settings: "cv05" 1, "tnum" 1;
  -webkit-font-smoothing: antialiased;
}

/* Geen blauw/grijs tap-vierkant bij aanraken (iPad/Safari/Chrome) — overal weg. */
* { -webkit-tap-highlight-color: transparent !important; }

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

/* ── Foutvak in formulieren (app-breed). De login heeft zijn eigen vorm in
   het LOGIN-blok verderop; die stond hier vroeger mee in dezelfde selector en
   overstemde met !important de shadcn-alert van het inlogscherm. ── */
.form-err {
  background: var(--danger-soft) !important;
  border: 1px solid rgba(184,107,107,.25) !important;
  color: var(--danger) !important;
  border-radius: 6px !important;
  font-size: calc(12px * var(--type-scale, 1.2)) !important;
  font-family: var(--font) !important;
  padding: 10px 12px !important;
  margin: 0 !important;
}
[data-theme="light"] .form-err {
  border-color: rgba(220,38,38,.2) !important;
}

/* ── Form fields (app-wide) ── */
.field > span {
  font-family: var(--font) !important;
  font-size: calc(11px * var(--type-scale, 1.2)) !important;
  font-weight: 500 !important;
  letter-spacing: normal !important;
  text-transform: none !important;
  color: var(--text-muted) !important;
}
.field > input, .field > select, .field > textarea {
  background: var(--surface) !important;
  border: 1px solid var(--border-strong) !important;
  border-radius: 6px !important;
  color: var(--text) !important;
  font-family: var(--font) !important;
  font-size: calc(13px * var(--type-scale, 1.2)) !important;
}
.field > input:focus, .field > select:focus, .field > textarea:focus {
  border-color: var(--accent) !important;
  box-shadow: 0 0 0 2px var(--accent-soft) !important;
  outline: none !important;
}
.form-err {
  background: var(--danger-soft) !important;
  border: 1px solid rgba(184,107,107,.25) !important;
  color: var(--danger) !important;
  border-radius: 6px !important;
  font-size: calc(12px * var(--type-scale, 1.2)) !important;
}

/* ── Buttons ── */
.btn-primary {
  background: var(--accent) !important;
  color: #fff !important;
  border: none !important;
  border-radius: 6px !important;
  font-family: var(--font) !important;
  font-weight: 500 !important;
  font-size: calc(13px * var(--type-scale, 1.2)) !important;
  letter-spacing: normal !important;
  text-transform: none !important;
  padding: 10px 16px !important;
}
.btn-primary:hover:not(:disabled) { background: var(--accent-hover) !important; }
/* Primaire knoppen = Iselmar-groen accent (Claude Design handoff). */
[data-theme] .btn-primary {
  background: var(--accent) !important;
  color: #fff !important;
  border: none !important;
}
/* Dark thema: donkere tekst op het lichtere groen (handoff-spec). */
[data-theme="grey"] .btn-primary { color: #0e0f0d !important; }
[data-theme] .btn-primary:hover:not(:disabled) { background: var(--accent-hover) !important; }
.btn-ghost, .bl-btn-secondary {
  background: transparent !important;
  color: var(--text-muted) !important;
  border: 1px solid var(--border-strong) !important;
  border-radius: 6px !important;
  font-family: var(--font) !important;
  font-weight: 500 !important;
  font-size: calc(12px * var(--type-scale, 1.2)) !important;
  padding: 8px 12px !important;
  cursor: pointer;
}
.btn-ghost:hover, .bl-btn-secondary:hover { background: var(--hover) !important; color: var(--text) !important; }
.btn-danger {
  background: var(--danger-soft) !important;
  color: var(--danger) !important;
  border: 1px solid rgba(184,107,107,.25) !important;
  border-radius: 6px !important;
  font-family: var(--font) !important;
  font-weight: 500 !important;
  font-size: calc(12px * var(--type-scale, 1.2)) !important;
  padding: 8px 12px !important;
  cursor: pointer;
}

/* ── Shell ── */
.app-shell {
  background: var(--bg) !important;
  padding-bottom: 64px !important;
}
@media (min-width: 1100px) {
  .app-shell { padding-bottom: 0 !important; }
}

.app-body {
  min-height: 100vh;
}
@media (min-width: 1100px) {
  .app-body { flex-direction: row !important; }
}

.app-sidebar {
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
/* Desktop: zwevende afgeronde "kaart" met ruimte eromheen, i.p.v. een
   vastgeplakte kolom tegen de rand. */
@media (min-width: 1100px) {
  .app-sidebar {
    width: 196px;
    flex-shrink: 0;
    margin: 12px;
    border: 1px solid var(--border);
    /* Linkerhoeken scherper (ronding begint later), rechts ronder. */
    border-radius: 9px 16px 16px 9px;
    box-shadow: 0 1px 2px rgba(0,0,0,.10), 0 12px 30px rgba(0,0,0,.05);
    /* De topbar (~50px) staat erbóven in de flow: zonder die aftrek stak de
       kaart onder de viewport uit en was het profielvlak (sidebar-foot) half
       verstopt tot je scrolde (Nick 16 jul). */
    height: calc(100dvh - 24px - 50px);
    position: sticky;
    top: 12px;
    align-self: flex-start;
    overflow: hidden;
  }
}

.sidebar-head {
  padding: 16px 14px 12px;
  border-bottom: 1px solid var(--border);
}
/* Sidebar-merk (zwart ISELMAR-logo op witte achtergrond, geen alpha).
   We gebruiken blend-modes zodat de witte achtergrond wegvalt én het logo
   meekleurt met het thema:
   - Light: multiply → wit verdwijnt op het lichte paneel, zwart logo blijft.
   - Dark:  invert(1) maakt het logo wit; screen → zwart verdwijnt op het
            donkere paneel, wit logo blijft. */
.sidebar-logo {
  height: 34px; width: auto; display: block; margin: 2px auto 16px;
}
/* Donker thema: gebruik de witte logo-variant i.p.v. de blauwe-op-wit. */
html[data-theme="grey"] .sidebar-logo {
  content: url(./iselmar-logo-white.png?v=5);
}
.sidebar-user {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.sidebar-avatar {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font);
  font-size: calc(11px * var(--type-scale, 1.2));
  font-weight: 600;
  letter-spacing: .03em;
}
.sidebar-user-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.sidebar-user strong {
  font-size: calc(13px * var(--type-scale, 1.2));
  font-weight: 600;
  color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sidebar-user span {
  font-size: calc(11px * var(--type-scale, 1.2));
  color: var(--text-faint);
}

/* Sidebar-voet: thema-toggle + uitloggen, onderaan de zwevende kaart. */
/* Voet = alleen de minimalistische thema-toggle (donker/licht), links. */
.sidebar-foot {
  margin-top: auto;
  padding: 12px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
}

.theme-seg {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface);
}
.theme-seg-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 6px 10px;
  border: none;
  border-right: 1px solid var(--border);
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font);
  font-size: calc(11px * var(--type-scale, 1.2));
  font-weight: 500;
  cursor: pointer;
}
.theme-seg-btn svg { width: 16px; height: 16px; flex-shrink: 0; }
.theme-seg-btn:last-child { border-right: none; }
.theme-seg-btn.is-active { background: var(--active-bg); color: var(--text); }
.theme-seg-btn:not(.is-active):hover { color: var(--text); }
/* In de sidebar-voet: icoon-only mini-toggle (login houdt z'n tekstknoppen). */
.sidebar-foot .theme-seg-btn { width: 38px; height: 30px; padding: 0; gap: 0; }

/* Uitloggen: minimalistisch icoon-knopje, rechts naast de gebruiker. */
.app-logout {
  flex-shrink: 0;
  margin-left: auto;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
.app-logout svg { width: 16px; height: 16px; flex-shrink: 0; }
.app-logout:hover { background: var(--surface); color: var(--text); }

.nav-label {
  display: block;
  font-size: calc(11px * var(--type-scale, 1.2));
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-faint);
  padding: 16px 12px 6px;
}
.nav-divider {
  display: none;
}

/* Module nav */
.module-nav {
  background: transparent !important;
  border: none !important;
  padding: 4px 8px 12px !important;
  gap: 2px !important;
  flex: 1;
  overflow-y: auto;
}
@media (min-width: 1100px) {
  .module-nav {
    flex: 1;
    width: 100% !important;
    max-height: none !important;
    position: static !important;
    top: auto !important;
  }
}
.module-btn {
  background: transparent !important;
  border: none !important;
  border-radius: 6px !important;
  color: var(--nav-link) !important;
  font-family: var(--font) !important;
  font-weight: 400 !important;
  font-size: calc(12px * var(--type-scale, 1.2)) !important;
  letter-spacing: normal !important;
  padding: 8px 10px !important;
  text-align: left !important;
  justify-content: flex-start !important;
  gap: 10px !important;
  width: 100%;
}
.module-btn + .module-btn { border-left: none !important; }
.module-btn:hover:not(.is-active) {
  background: var(--hover) !important;
  color: var(--text) !important;
}
.module-btn.is-active {
  background: var(--active-bg) !important;
  color: var(--text) !important;
  font-weight: 500 !important;
  border: none !important;
}
.module-btn.is-active .module-ico { color: var(--text) !important; }
.module-ico { width: 16px !important; height: 16px !important; opacity: .85; }
@media (max-width: 1099px) {
  .module-ico { display: block !important; }
  /* De nav zit < 1100px in een VERTICALE off-canvas drawer (.app-sidebar), niet
     in de oude horizontale tab-bar. Dus verticale lijst zoals op desktop — geen
     horizontale row (die brak de drawer: lege ruimte + verborgen items). */
  .module-nav {
    flex-direction: column !important;
    overflow-x: visible !important;
    overflow-y: auto !important;
  }
  .module-btn {
    width: 100% !important;
    justify-content: flex-start !important;
    white-space: nowrap;
    flex: 0 0 auto !important;
  }
}

/* Topbar + content */
.app-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.app-topbar {
  padding: 8px 12px;
  border-bottom: none;
  background: var(--bg);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 8px;
}
.sidebar-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  flex-shrink: 0;
}
.sidebar-toggle svg { width: 18px; height: 18px; }
.sidebar-toggle:hover { background: var(--hover); color: var(--text); }
@media (min-width: 1100px) {
  .sidebar-toggle { display: none; }
}
.sidebar-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(17,17,19,.28);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  z-index: 850;
}
@media (min-width: 1100px) {
  .sidebar-backdrop { display: none !important; }
}
@media (max-width: 1099px) {
  .app-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 900;
    width: min(280px, 88vw);
    height: 100vh;
    height: 100dvh;
    transform: translateX(-105%);
    transition: transform .22s ease;
    border-right: 1px solid var(--border);
    border-bottom: none;
    overflow-y: auto;
  }
  .app-sidebar.is-open { transform: translateX(0); }
}
.topbar-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}
.cmd-trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-muted);
  font-family: var(--font);
  font-size: calc(11px * var(--type-scale, 1.2));
  cursor: pointer;
}
.cmd-trigger svg { width: 14px; height: 14px; flex-shrink: 0; }
.cmd-trigger:hover { background: var(--hover); color: var(--text); border-color: var(--border-strong); }
.cmd-trigger-label { display: none; }
@media (min-width: 640px) {
  .cmd-trigger-label { display: inline; }
}
.cmd-kbd {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: calc(10px * var(--type-scale, 1.2));
  padding: 2px 5px;
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text-faint);
  background: var(--bg);
  line-height: 1.2;
}
.datum-nav {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  justify-content: center;
}
.datum-arrow {
  border: none !important;
  background: transparent !important;
  color: var(--text-muted) !important;
  border-radius: 6px !important;
  padding: 6px !important;
  cursor: pointer;
}
.datum-arrow:hover { background: var(--hover) !important; color: var(--text) !important; }
.datum-arrow svg { width: 16px; height: 16px; }

.act-tabs {
  padding: 8px 12px !important;
  gap: 4px !important;
  background: var(--bg) !important;
  border-bottom: none !important;
}
.act-tab {
  padding: 4px 10px !important;
  border-radius: 8px !important;
  border: 1px solid var(--border) !important;
  background: var(--surface) !important;
  color: var(--text-muted) !important;
  font-family: var(--font) !important;
  font-size: calc(11px * var(--type-scale, 1.2)) !important;
  font-weight: 500 !important;
  cursor: pointer;
}
.act-tab.is-active {
  background: var(--panel) !important;
  color: var(--text) !important;
  border-color: var(--border-strong) !important;
  box-shadow: inset 0 -2px 0 var(--accent) !important;
}

.app-main {
  flex: 1;
  overflow: auto;
  padding: 12px !important;
  background: var(--bg) !important;
}

/* Loading */
.loading { color: var(--text-muted) !important; font-size: calc(13px * var(--type-scale, 1.2)) !important; }
.loading p { font-family: var(--font) !important; }
.spin {
  border-color: var(--border) !important;
  border-top-color: var(--accent) !important;
}

/* Toast */
.iv-toast {
  background: var(--panel) !important;
  color: var(--text) !important;
  border: 1px solid var(--border-strong) !important;
  font-family: var(--font) !important;
  border-radius: 10px !important;
  box-shadow: var(--shadow) !important;
}
.iv-toast-description { color: var(--text-muted); }
.iv-toast-close { color: var(--text-muted); }
.iv-toast-close:hover { background: var(--surface); color: var(--text); }
.iv-toast[data-type="error"] { border-color: color-mix(in oklab, var(--danger) 30%, var(--border)) !important; }
.iv-toast[data-type="success"] { border-color: color-mix(in oklab, var(--success) 24%, var(--border)) !important; }
.iv-toast[data-type="warning"] { border-color: color-mix(in oklab, var(--warning) 28%, var(--border)) !important; }

/* ── Activiteiten grids ── */
.act-section {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
  margin-bottom: 12px !important;
  overflow: hidden;
}
.act-section-head {
  padding: 10px 12px !important;
  border-bottom: 1px solid var(--border) !important;
  display: flex !important;
  justify-content: space-between !important;
  align-items: center !important;
}
.act-section-title {
  font-family: var(--font) !important;
  font-size: calc(13px * var(--type-scale, 1.2)) !important;
  font-weight: 600 !important;
  color: var(--text) !important;
  margin: 0 !important;
}
.act-settings-btn, .act-beheer-link {
  border: none;
  background: transparent;
  color: var(--accent);
  font-family: var(--font);
  font-size: calc(11px * var(--type-scale, 1.2));
  font-weight: 500;
  cursor: pointer;
  padding: 4px 0;
}
.act-beheer-link:hover { text-decoration: underline; }

/* Icoon-acties rechtsboven in de activiteit-kop: slotje (blokkades) + tandwiel
   (instellingen). Vervangt de oude tekst-link "Beheer →" en de globale
   "Blokkades beheren"-knop. */
.act-head-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}
.act-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Touch-vriendelijke hit-area (iPad-receptie): 40px op touch, 30px op
     desktop (muis) waar precisie groter is. */
  width: 40px;
  height: 40px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
@media (min-width: 1100px) {
  .act-icon-btn { width: 30px; height: 30px; }
}
.act-icon-btn:hover {
  background: var(--surface) !important;
  color: var(--text) !important;
}
.act-icon-btn svg { display: block; }
/* Slotje actief = blokkades-modus aan → duidelijk gemarkeerde chip. */
.act-lock-btn.is-active {
  background: var(--active-bg) !important;
  color: var(--text) !important;
  border-color: var(--border-strong) !important;
}

.banen-grid, .ag-grid {
  background: transparent !important;
  border: none !important;
}
/* Edge-padding rond de tegels — bij Adventuregolf zorgt .ag-slots (padding:
   10px 12px) al voor lucht aan de randen; de banen-grid (bowling/tennis/squash)
   plaatst cellen direct in het grid zonder rand-padding, waardoor tegels tegen
   de rand plakken. Zelfde lucht toevoegen zodat het consistent oogt. */
.banen-grid { padding: 8px !important; }
.banen-cell {
  font-family: var(--font) !important;
  font-size: calc(11px * var(--type-scale, 1.2)) !important;
  color: var(--text-muted) !important;
  border-color: var(--border) !important;
  min-height: 36px !important;
  padding: 8px 6px !important;
}
/* Kop- en tijd-labels als platte tekst (zoals Adventuregolf's .ag-tijd) i.p.v.
   een gevuld surface-vlak. */
.banen-cell.banen-hed, .banen-cell.banen-tijd {
  background: transparent !important;
  font-weight: 500 !important;
  color: var(--text-muted) !important;
  font-family: var(--font) !important;
}
/* Vrije baan-cel = schone gevulde "chip" — identiek aan Adventuregolf's
   .ag-slot: subtiele vulling, GEEN gestreepte rand, afgeronde hoeken; hover
   licht iets op. */
.banen-cell.banen-vrij {
  background: var(--panel) !important;
  color: var(--text) !important;
  font-size: calc(11px * var(--type-scale, 1.2)) !important;
  font-weight: 600 !important;
  border: 1.5px solid var(--border) !important;
  margin: 2px;
  border-radius: var(--radius-sm);
  width: calc(100% - 4px);
  height: calc(100% - 4px);
}
.banen-cell.banen-vrij::before {
  content: '';
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--success, #059669);
  margin-right: 6px;
  vertical-align: 1px;
}
.banen-cell.banen-vrij:hover {
  background: var(--success-soft, rgba(5,150,105,.08)) !important;
  border-color: var(--success, #059669) !important;
  color: var(--text) !important;
}
.banen-cell.banen-geboekt {
  background: var(--text) !important;
  color: var(--panel) !important;
  border: 1.5px solid var(--text) !important;
  font-weight: 600 !important;
  font-size: calc(11px * var(--type-scale, 1.2)) !important;
  margin: 2px;
  border-radius: 5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.banen-cell.banen-geboekt:hover {
  opacity: .85;
  box-shadow: none !important;
}
.banen-cell.banen-blok {
  background: repeating-linear-gradient(-45deg, var(--warning-soft, rgba(184,147,90,.18)) 0 6px, transparent 6px 12px) !important;
  color: var(--warning) !important;
  border: 1.5px dashed color-mix(in srgb, var(--warning, #B8935A) 45%, transparent) !important;
}
.banen-cell.banen-vol, .banen-cell.banen-empty-cell {
  color: var(--text-faint) !important;
  opacity: .5;
}
.banen-cell.is-selected, .ag-slot.is-selected {
  box-shadow: none !important;
}

.ag-row { border-color: var(--border) !important; }
.ag-tijd {
  background: transparent !important;
  font-family: var(--font) !important;
  font-size: calc(11px * var(--type-scale, 1.2)) !important;
  color: var(--text-muted) !important;
}
/* Schone gevulde "chips": subtiele vulling, GEEN harde rand → nette tegels
   zonder hokjes-look. Hover licht iets op. Status-slots houden hun kleur. */
.ag-slot {
  background: var(--panel) !important;
  border: 1.5px solid var(--border) !important;
  border-radius: var(--radius-sm) !important;
  font-family: var(--font) !important;
  font-size: calc(10px * var(--type-scale, 1.2)) !important;
  font-variant-numeric: tabular-nums;
  color: var(--text) !important;
}
.ag-slot:hover:not(.geboekt):not(.vol):not([disabled]):not(.geblokkeerd) {
  background: var(--success-soft, rgba(5,150,105,.08)) !important;
  border-color: var(--success, #059669) !important;
  color: var(--text) !important;
}
.ag-slot:not(.geboekt):not(.geblokkeerd):not(.vol):not(.vastgehouden):not(.is-verleden):not(:disabled)::before {
  content: '';
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--success, #059669);
  margin-right: 5px;
  vertical-align: 1px;
}
.ag-slot.geboekt {
  background: var(--text) !important;
  color: var(--panel) !important;
  border-color: var(--text) !important;
  font-weight: 600 !important;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ag-slot.vol { opacity: .4; }
/* Tijdelijke hold (gast nu online aan het boeken): amber + streepjesrand, vol
   zichtbaar (niet gedimd zoals 'vol'), zodat de receptie ziet dat het slot zo
   weer vrij kan komen. */
.ag-slot.vastgehouden {
  opacity: 1 !important;
  background: var(--warning-soft, rgba(217,119,6,0.16)) !important;
  color: var(--warning, #D97706) !important;
  border: 1px dashed var(--warning, #D97706) !important;
}
.banen-cell.banen-vol.vastgehouden {
  opacity: 1 !important;
  background: var(--warning-soft, rgba(217,119,6,0.16)) !important;
  color: var(--warning, #D97706) !important;
  border-color: var(--warning, #D97706) !important;
}
.ag-slot.geblokkeerd {
  background: repeating-linear-gradient(-45deg, var(--warning-soft, rgba(184,147,90,.18)) 0 6px, transparent 6px 12px) !important;
  color: var(--warning) !important;
  border: 1.5px dashed color-mix(in srgb, var(--warning, #B8935A) 45%, transparent) !important;
}
/* Rij-teller "N vrij" onder het uur-label (variant A). */
.ag-vrij-tel {
  display: block;
  font-size: calc(10px * var(--type-scale, 1.2));
  font-weight: 700;
  color: var(--success, #059669);
  margin-top: 2px;
}
/* Over-uur doorlopende boeking: vlakke + gestreepte rand aan de doorloop-kant. */
.ag-slot.geboekt.cont-r { border-top-right-radius: 0 !important; border-bottom-right-radius: 0 !important;
  border-right-style: dashed !important; border-right-color: var(--accent) !important; }
.ag-slot.geboekt.cont-l { border-top-left-radius: 0 !important; border-bottom-left-radius: 0 !important;
  border-left-style: dashed !important; border-left-color: var(--accent) !important; }
/* Doorloop-pijl (⤴) 45° met de klok mee gedraaid. */
.ag-cont-arrow { display: inline-block; transform: rotate(90deg); }
.ag-cont-arrow-r { display: inline-block; }

/* Blokkades toolbar */
.blokkeer-toolbar {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
  padding: 8px 12px !important;
  margin-bottom: 10px !important;
}

/* ── Inklapbare contextpanelen (activiteiten + restaurant) ── */
/* Inklap-tab op de LINKERrand van het paneel (verticaal gecentreerd), zoals het
   ontwerp — niet meer een knopje rechtsboven in de kaart. */
.aside-collapse-btn {
  position: absolute;
  left: -11px; top: 50%; transform: translateY(-50%);
  width: 18px; height: 40px;
  display: grid; place-items: center;
  border: 1px solid var(--border); border-right: none;
  border-radius: 8px 0 0 8px;
  background: var(--panel); color: var(--text-muted); cursor: pointer;
  box-shadow: -3px 0 8px rgba(0,0,0,.05);
  z-index: 6;
  transition: background .12s, color .12s;
}
.aside-collapse-btn:hover { background: var(--hover); color: var(--text); }
.aside-collapse-btn svg { width: 12px; height: 12px; }
.rp-layout.is-aside-collapsed { grid-template-columns: 1fr !important; }
.rp-layout.is-aside-collapsed .rp-aside { display: none !important; }
.aside-reopen {
  position: fixed; right: 0; top: 50%; transform: translateY(-50%);
  width: 26px; height: 56px; z-index: 55;
  border: 1px solid var(--border); border-right: none; border-radius: 10px 0 0 10px;
  background: var(--panel); color: var(--text-muted); display: grid; place-items: center;
  box-shadow: var(--shadow); cursor: pointer;
}
.aside-reopen:hover { background: var(--hover); color: var(--text); }
.rp-aside { position: relative; }

/* ── Activiteiten planning-kolom (rechterpaneel verwijderd, Nick 30 jul) ── */
.act-plan { min-width: 0; }

/* ── Modals ── */
.modal {
  background: var(--modal-overlay) !important;
  backdrop-filter: blur(4px);
}
.modal-inner, .gb-overlay-inner {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 12px !important;
  border-top: 1px solid var(--border) !important;
  box-shadow: var(--shadow) !important;
  color: var(--text) !important;
}
@media (min-width: 720px) {
  .modal {
    align-items: stretch !important;
    justify-content: flex-end !important;
    padding: 0 !important;
  }
  .modal-inner, .modal-inner.modal-slide {
    max-width: min(480px, 100vw) !important;
    width: 100% !important;
    height: 100% !important;
    max-height: 100vh !important;
    border-radius: 0 !important;
    border-top: none !important;
    border-right: none !important;
    animation: slideInRight .22s ease-out;
    display: flex !important;
    flex-direction: column !important;
    padding: 0 !important;
  }
}
.modal-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 24px 22px 16px;
  -webkit-overflow-scrolling: touch;
}
.modal-footer {
  flex-shrink: 0;
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  padding: 12px 22px 20px;
  border-top: 1px solid var(--border);
  background: var(--panel);
}
.modal-footer.bd-actions { justify-content: space-between; }
.modal-footer .btn-danger { margin-right: auto; }
.modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
  background: var(--surface) !important;
  color: var(--text-muted) !important;
  border-radius: 6px !important;
  border: 1px solid var(--border) !important;
  font-size: calc(18px * var(--type-scale, 1.2)) !important;
}
@keyframes slideInRight {
  from { transform: translateX(100%); opacity: .6; }
  to { transform: translateX(0); opacity: 1; }
}
.modal-title {
  font-family: var(--font) !important;
  font-weight: 600 !important;
  font-size: calc(16px * var(--type-scale, 1.2)) !important;
  color: var(--text) !important;
  letter-spacing: -.015em !important;
}
.bkflow-overlay {
  background: var(--modal-overlay) !important;
}
@media (min-width: 720px) {
  .bkflow-overlay {
    align-items: stretch !important;
    justify-content: flex-end !important;
    padding: 0 !important;
    overflow: hidden !important;
  }
  .bkflow.bkflow-card {
    max-width: min(560px, 100vw) !important;
    width: 100% !important;
    min-height: 100vh !important;
    max-height: 100vh !important;
    margin: 0 !important;
    border-radius: 0 !important;
    border-top: none !important;
    border-right: none !important;
    overflow-y: auto !important;
    animation: slideInRight .22s ease-out;
  }
}
.bkflow-panel {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 12px !important;
  color: var(--text) !important;
}
.gb-overlay {
  background: var(--modal-overlay) !important;
}

/* ── Restaurant ── */
.rp-shell, .rpg-shell { color: var(--text) !important; }
.rp-segmented, .rp-view-toggle {
  display: inline-flex;
  gap: 4px;
  background: var(--surface) !important;
  border: none !important;
  border-radius: 11px !important;
  padding: 4px !important;
  overflow: visible;
}
.rp-seg-btn, .rp-view-btn {
  font-family: var(--font) !important;
  font-size: calc(12px * var(--type-scale, 1.2)) !important;
  color: var(--text-muted) !important;
  background: transparent !important;
  border: none !important;
  border-radius: 8px !important;
  padding: 7px 18px !important;
  transition: background .15s, color .15s, box-shadow .15s;
}
/* Actief segment = witte pill met schaduw (iOS-stijl), zoals het ontwerp. */
.rp-seg-btn.is-active, .rp-view-btn.is-active {
  background: var(--panel) !important;
  color: var(--text) !important;
  font-weight: 600 !important;
  box-shadow: 0 1px 3px rgba(0,0,0,.14), 0 1px 2px rgba(0,0,0,.06) !important;
}
/* Tijdlijn als zwevende kaart (look & feel handoff): frame op de wrap zodat de
   horizontale scroll binnen de afgeronde hoeken blijft. */
.rpg-grid-wrap {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 16px !important;
  box-shadow: var(--shadow) !important;
  overflow: hidden !important;
}
.rpg-grid {
  background: var(--panel) !important;
  border: none !important;
  border-radius: 0 !important;
}
.rpg-cell, .rpg-hdr {
  border-color: var(--border) !important;
  font-family: var(--font) !important;
  font-size: calc(11px * var(--type-scale, 1.2)) !important;
  color: var(--text-muted) !important;
}
.rpg-booking {
  border-radius: 5px !important;
  font-family: var(--font) !important;
  font-size: calc(10px * var(--type-scale, 1.2)) !important;
}
.rp-aside, .rpg-aside {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 16px !important;
  box-shadow: var(--shadow) !important;
  padding: 18px !important;
  position: relative;
  overflow: visible !important; /* zodat de inklap-tab op de linkerrand niet wordt afgekapt */
}
.rp-queue-item {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  border-radius: 6px !important;
  color: var(--text) !important;
  font-family: var(--font) !important;
  font-size: calc(12px * var(--type-scale, 1.2)) !important;
}

/* ── Betaallink, dagafsluiting, mailings, cron ── */
.bl-shell, .da-shell, .ml-shell, .cr-shell, .gb-shell, .beheer-shell {
  color: var(--text) !important;
}
.bl-tbl, .da-tbl, .gb-tbl, .beheer-tbl, .cg-table {
  width: 100%;
  border-collapse: collapse;
  font-size: calc(12px * var(--type-scale, 1.2));
}
.bl-tbl th, .da-tbl th, .gb-tbl th, .beheer-tbl th {
  text-align: left;
  padding: 8px 10px;
  font-size: calc(10px * var(--type-scale, 1.2));
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-faint);
  border-bottom: 1px solid var(--border);
}
.bl-tbl td, .da-tbl td, .gb-tbl td, .beheer-tbl td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.da-card, .cr-card, .ml-card {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
}
.da-stat, .da-kpi-val {
  font-family: var(--font) !important;
  font-weight: 600 !important;
  color: var(--text) !important;
  font-variant-numeric: tabular-nums;
}
.ml-list-item, .cg-list-item {
  padding: 8px 10px !important;
  border-radius: 6px !important;
  border: 1px solid transparent !important;
  cursor: pointer;
  font-size: calc(12px * var(--type-scale, 1.2)) !important;
  color: var(--text-muted) !important;
}
.ml-list-item.is-active, .cg-list-item.is-active {
  background: var(--surface) !important;
  border-color: var(--border-strong) !important;
  border-left: 2px solid var(--accent) !important;
  color: var(--text) !important;
}
.cr-card code, .beheer-shell code {
  font-size: calc(11px * var(--type-scale, 1.2));
  background: var(--surface);
  padding: 2px 6px;
  border-radius: 4px;
  color: var(--text-muted);
}

/* ── Beheer ── */
.beheer-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 12px;
}
.beheer-tab {
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  font: inherit;
  font-size: calc(11px * var(--type-scale, 1.2));
  font-weight: 500;
  cursor: pointer;
}
.beheer-tab.is-active {
  background: var(--panel);
  color: var(--text);
  border-color: var(--border-strong);
  box-shadow: inset 0 -2px 0 var(--accent);
}
.beheer-panel { display: none; }
.beheer-panel.is-active { display: block; }
.beheer-layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 12px;
  min-height: 400px;
}
@media (max-width: 899px) {
  .beheer-layout { grid-template-columns: 1fr; }
}
.beheer-list {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.beheer-list-head {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  font-size: calc(11px * var(--type-scale, 1.2));
  font-weight: 600;
  color: var(--text-muted);
}
.beheer-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  border: none;
  border-bottom: 1px solid var(--border);
  background: transparent;
  cursor: pointer;
  font: inherit;
  color: var(--text-muted);
}
.beheer-item:last-child { border-bottom: none; }
.beheer-item strong { display: block; font-size: calc(12px * var(--type-scale, 1.2)); font-weight: 500; color: var(--text); }
.beheer-item small { font-size: calc(10px * var(--type-scale, 1.2)); color: var(--text-faint); }
.beheer-item.is-active {
  background: var(--surface);
  border-left: 2px solid var(--accent);
  padding-left: 8px;
}
.beheer-section {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 10px;
  overflow: hidden;
}
/* Sectiekoppen in gewone zinsvorm, niet in kapitalen: de kapitalen-koppen op
   Seizoenstarieven, Blokkades, Restaurant en Activiteiten-detail waren de enige
   in de backoffice die zo schreeuwden (voorstel-beheer.html, "één
   koppenstructuur"). */
.beheer-section-head {
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  font-size: calc(12.5px * var(--type-scale, 1.2));
  font-weight: 650;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text);
}
.beheer-section-body { padding: 12px; }
.beheer-section-body--flush { padding: 0; overflow-x: auto; }
.beheer-table {
  width: 100%;
  border-collapse: collapse;
  font-size: calc(12px * var(--type-scale, 1.2));
}
.beheer-table th,
.beheer-table td {
  padding: 8px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.beheer-table th {
  font-size: calc(10px * var(--type-scale, 1.2));
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-muted);
  background: var(--surface);
}
.beheer-table tbody tr:last-child td { border-bottom: none; }
.beheer-num { font-variant-numeric: tabular-nums; }
/* Eén lege-staat-toon over alle Beheer-schermen: rustige zin, text-muted,
   nooit cursief, eindigend op een punt ("Nog geen [items]."). */
.beheer-empty {
  text-align: center;
  color: var(--text-muted);
  font-style: normal;
  padding: 20px 12px !important;
}
.beheer-table-hint { padding: 10px 12px 12px; margin: 0; }
/* ══ De ENIGE statusbadge van Beheer — één vorm, vier tonen ══
   Vervangt de drie losse statusbadges van Modules, Mailings en Koppelingen,
   die alle drie hetzelfde werk deden met eigen kleuren, eigen hoofdletter-
   regels en eigen padding (en waarvan Cron er letterlijk één leende).
   Sentence case, nooit kapitalen:
     (geen)      = uit / standaard  — bestaat wel, staat uit
     .is-ok      = aan              — werkt volledig
     .is-beperkt = beperkt          — bestaat, maar niet het hele proces
     .is-soon    = binnenkort       — bestaat nog niet
     .is-danger  = fout / ingetrokken */
.beheer-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: calc(10px * var(--type-scale, 1.2));
  font-weight: 600;
  line-height: 1.35;
  padding: 3px 10px;
  border-radius: 100px;
  white-space: nowrap;
  text-transform: none;
  letter-spacing: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text-muted);
}
.beheer-badge.is-ok {
  color: var(--success);
  border-color: rgba(5, 150, 105, .35);
  background: rgba(5, 150, 105, .08);
}
.beheer-badge.is-beperkt {
  color: var(--warning);
  border-color: rgba(217, 119, 6, .35);
  background: var(--warning-soft, rgba(217, 119, 6, .1));
}
.beheer-badge.is-soon {
  color: var(--text-faint);
  background: none;
  border: 1px dashed var(--border-strong);
}
.beheer-badge.is-danger {
  color: var(--danger);
  border-color: rgba(220, 38, 38, .35);
  background: rgba(220, 38, 38, .08);
}

/* ═══ Bonnen/bonsoorten (kortingsbonnen, 1 aug 2026) ═══
   Sub-tabbladen binnen de module + kaarten/overlay-onderdelen voor
   bonsoorten-beheer en bonnen-uitgifte. Hergebruikt de bestaande
   .beheer-*/.field/.btn-*/.gb-overlay-vocabulaire waar mogelijk; dit zijn
   alleen de onderdelen die nog niet bestonden. */
.kb-subtabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.kb-subtab {
  border: 1px solid var(--border); background: var(--surface); color: var(--text-muted);
  font: 600 12.5px var(--font); padding: 7px 13px; border-radius: 100px; cursor: pointer;
}
.kb-subtab:hover { color: var(--text); }
.kb-subtab.on { background: var(--accent); color: #fff; border-color: var(--accent); }

.bon-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
.bon-card {
  display: flex; flex-direction: column; gap: 8px; text-align: left; font: inherit; color: inherit;
  border: 1px solid var(--border); background: var(--panel); border-radius: 12px; padding: 14px; cursor: pointer;
}
.bon-card:hover { border-color: var(--accent); box-shadow: 0 4px 16px rgba(0,0,0,.08); }
.bon-card h4 { margin: 0; font-size: 14px; font-weight: 650; color: var(--text); }
.bon-card-tekst { font-size: 12px; color: var(--text-muted); font-style: italic; margin: 0; }
.bon-card-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-top: auto; }

.bon-choice { display: flex; flex-direction: column; gap: 8px; }
.bon-choice-opt { display: flex; gap: 10px; align-items: flex-start; border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; cursor: pointer; }
.bon-choice-opt input { margin-top: 2px; accent-color: var(--accent); }
.bon-choice-opt b { display: block; font-size: 13px; font-weight: 650; color: var(--text); }
.bon-choice-opt p { margin: 2px 0 0; font-size: 11.5px; color: var(--text-muted); }
.bon-choice-opt:has(input:checked) { border-color: var(--accent); background: rgba(87,124,142,.1); }

.bon-summary { display: flex; flex-direction: column; gap: 6px; background: var(--surface); border-radius: 10px; padding: 10px 12px; margin: 10px 0; }
.bon-summary-row { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; }
.bon-summary-row span { color: var(--text-muted); }
.bon-summary-row b { color: var(--text); font-weight: 600; text-align: right; }
.bon-code { font-family: var(--font-mono, monospace); font-size: 24px; font-weight: 700; letter-spacing: .06em; color: var(--text); background: var(--surface); border: 1.5px dashed var(--border); border-radius: 10px; padding: 12px; text-align: center; margin: 4px 0; }

.bon-koppel-gekozen { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; border: 1px solid var(--accent); background: rgba(87,124,142,.1); border-radius: 10px; padding: 9px 11px; margin-top: 4px; }
.bon-koppel-gekozen > div:first-child { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.bon-koppel-gekozen strong { font-size: 13px; color: var(--text); }
.bon-koppel-gekozen span { font-size: 11px; color: var(--text-muted); }
.bon-koppel-bedrag { font-weight: 700; font-size: 13.5px; color: var(--text); white-space: nowrap; }
.bon-boeking-lijst { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.bon-boeking-opt { display: flex; flex-direction: column; gap: 2px; text-align: left; border: 1px solid var(--border); background: var(--panel); border-radius: 8px; padding: 8px 10px; cursor: pointer; font: inherit; width: 100%; }
.bon-boeking-opt:hover { border-color: var(--accent); background: var(--hover, var(--surface)); }
.bon-boeking-opt strong { font-size: 12.5px; color: var(--text); }
.bon-boeking-opt span { font-size: 11px; color: var(--text-muted); }

.bon-deliver { display: flex; flex-direction: column; gap: 10px; border-top: 1px solid var(--border); padding-top: 12px; margin-top: 4px; }
.bon-deliver-row { display: flex; gap: 8px; }
.bon-deliver-row .btn-ghost { flex: 1; justify-content: center; }
.bon-deliver-row .btn-ghost.is-klaar { border-color: var(--success); color: var(--success); background: rgba(5,150,105,.08); }
.bon-deliver-sub { display: flex; gap: 8px; }
.bon-deliver-sub input { flex: 1; min-width: 0; font: inherit; font-size: 13px; border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; background: var(--panel); color: var(--text); }
.bon-deliver-done { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--success); font-weight: 600; }

.beheer-row-actions {
  white-space: nowrap;
  text-align: right;
}
.beheer-row-btn {
  font-size: calc(10px * var(--type-scale, 1.2)) !important;
  padding: 2px 6px !important;
}
.beheer-row-del { color: var(--danger) !important; }
.beheer-seizoen-form { margin-bottom: 10px; }
.beheer-seizoen-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
.beheer-field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
}
.field-hint { font-size: calc(10px * var(--type-scale, 1.2)); color: var(--text-faint); margin-top: 3px; }
.banen-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.baan-chip {
  font-size: calc(10px * var(--type-scale, 1.2));
  padding: 3px 8px;
  border-radius: 4px;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text-muted);
}
.beheer-week-table, .beheer-tier-table {
  width: 100%;
  border-collapse: collapse;
  font-size: calc(11px * var(--type-scale, 1.2));
}
.beheer-week-table th, .beheer-tier-table th {
  padding: 6px 8px;
  text-align: left;
  font-size: calc(10px * var(--type-scale, 1.2));
  font-weight: 500;
  color: var(--text-faint);
  border-bottom: 1px solid var(--border);
}
.beheer-week-table td, .beheer-tier-table td {
  padding: 5px 6px;
  border-bottom: 1px solid var(--border);
}
.beheer-week-table select, .beheer-week-table input,
.beheer-tier-table input, .beheer-tier-table select {
  font: inherit;
  font-size: calc(11px * var(--type-scale, 1.2));
  padding: 4px 6px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  width: 100%;
}
.db-note {
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px dashed var(--border-strong);
  background: var(--surface);
  font-size: calc(11px * var(--type-scale, 1.2));
  color: var(--text-muted);
  line-height: 1.5;
  margin-top: 10px;
}
.db-note strong { color: var(--text); display: block; margin-bottom: 4px; }
.beheer-save-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-top: 10px;
  font-size: calc(11px * var(--type-scale, 1.2));
  color: var(--text-faint);
}

/* Activity settings (modal + beheer) */
.as-tiers, .beheer-tiers {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.as-tiers-title, .beheer-tiers-title { font-size: calc(12px * var(--type-scale, 1.2)); font-weight: 600; color: var(--text); }
.as-tiers-hint, .beheer-tiers-hint { font-size: calc(11px * var(--type-scale, 1.2)); color: var(--text-faint); margin: 4px 0 8px; }
.as-tier-row, .beheer-tier-row {
  display: grid;
  grid-template-columns: 1fr 1fr auto auto auto;
  gap: 6px;
  align-items: center;
  margin-bottom: 6px;
}
.as-tier-row input, .as-tier-row select,
.beheer-tier-row input, .beheer-tier-row select,
.beheer-staffel-row input {
  font: inherit;
  font-size: calc(11px * var(--type-scale, 1.2));
  padding: 6px 8px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
}
/* Staffel-regel labels volgen de thema-tekstkleur (dark + light). */
.beheer-staffel-row .field-hint { color: var(--text-muted); }

/* ═══ Annuleringsbeleid (Beheer-tab, 7 aug 2026) ═══
   box-sizing staat niet globaal (zie r4931 hieronder) — dit paneel zet het
   zelf. Verder hergebruikt het .beheer-*, .bon-choice-opt, .beheer-staffel-row
   en .beheer-save-bar; dit zijn de enige regels die nog niet bestonden. */
.ab-panel, .ab-panel *, .ab-panel *::before, .ab-panel *::after { box-sizing: border-box; }
.ab-mode-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.ab-mode-row .bon-choice-opt { flex: 1 1 220px; }
.ab-edit-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.bd-meta-hint { font-size: calc(11px * var(--type-scale, 1.2)); color: var(--text-faint); margin-bottom: 12px; }

/* ── Scan ── */
.scan-page-title {
  font-family: var(--font) !important;
  font-size: calc(16px * var(--type-scale, 1.2)) !important;
  font-weight: 600 !important;
  color: var(--text) !important;
}
.scan-page-hint { color: var(--text-muted) !important; font-size: calc(12px * var(--type-scale, 1.2)) !important; }
.scan-video-wrap {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
}
.scan-frame { border-color: var(--success) !important; opacity: .35 !important; }
.scan-match, .scan-action {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
  color: var(--text) !important;
}
.scan-match h3 { font-family: var(--font) !important; color: var(--text) !important; }

/* ── Bottom nav ── */
.bottom-nav {
  background: var(--panel) !important;
  border-top: 1px solid var(--border) !important;
  box-shadow: none !important;
}
.bnav-btn {
  color: var(--text-muted) !important;
  font-family: var(--font) !important;
  font-size: calc(10px * var(--type-scale, 1.2)) !important;
}
.bnav-btn.is-active { color: var(--text) !important; }
.bnav-btn.is-active::after { background: var(--accent) !important; }

/* ── Calendar widget overrides ── */
.datum-cal-wrap {
  flex: 1;
  min-width: 140px;
  max-width: 280px;
  position: relative;
}
.datum-cal-wrap .iselcal-root { width: 100%; }
.app-shell .iselcal-value,
.app-shell .iselcal-value.has-value,
.bkflow-overlay .iselcal-value,
.bkflow-overlay .iselcal-value.has-value {
  color: var(--text) !important;
  font-weight: 500 !important;
}
.app-shell .iselcal-caret-btn,
.bkflow-overlay .iselcal-caret-btn {
  color: var(--text-muted) !important;
}
.iselcal-pop {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
  box-shadow: var(--shadow) !important;
}

/* ── Booking flow ── */
.bkflow-title, .bkf-title {
  font-family: var(--font) !important;
  font-weight: 600 !important;
  color: var(--text) !important;
}
.bk-betaal {
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
  background: var(--surface) !important;
}
.bk-betaal-opt { color: var(--text) !important; font-family: var(--font) !important; font-size: calc(13px * var(--type-scale, 1.2)) !important; }

/* ── Gebruikers ── */
.gb-shell-title, .gb-shell-hint, .gb-rollen-titel {
  font-family: var(--font) !important;
  color: var(--text) !important;
}
/* Ook de kaartkop "Rollen & rechten" in zinsvorm (stond in Lekton-kapitalen). */
.gb-rollen-titel {
  text-transform: none !important;
  letter-spacing: 0 !important;
  font-size: calc(14px * var(--type-scale, 1)) !important;
  font-weight: 650 !important;
}
.gb-shell-hint, .gb-rollen-list { color: var(--text-muted) !important; font-size: calc(12px * var(--type-scale, 1.2)) !important; }
.gb-rol-sel, .gb-toggle {
  font-family: var(--font) !important;
  font-size: calc(12px * var(--type-scale, 1.2)) !important;
}
.gb-tbl-wrap {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
  overflow: hidden;
}

.beheer-head { margin-bottom: 12px; }
.beheer-title {
  font-family: var(--font) !important;
  font-size: calc(16px * var(--type-scale, 1.2)) !important;
  font-weight: 600 !important;
  color: var(--text) !important;
  margin: 0 0 4px !important;
}
.beheer-sub { font-size: calc(12px * var(--type-scale, 1.2)); color: var(--text-muted); margin: 0; }
.gb-overlay-card {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 12px !important;
  padding: 20px !important;
  max-width: 420px;
  width: 100%;
  color: var(--text) !important;
}
.gb-overlay {
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  padding: 24px !important;
}
.gb-overlay-acties { display: flex; gap: 8px; justify-content: flex-end; margin-top: 12px; }
.gb-muted { color: var(--text-muted); font-size: calc(12px * var(--type-scale, 1.2)); }

/* ── Command palette ── */
.cmd-palette {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 12vh 16px 16px;
}
.cmd-palette[hidden] { display: none !important; }
.cmd-backdrop {
  position: absolute;
  inset: 0;
  background: var(--modal-overlay);
  backdrop-filter: blur(4px);
}
.cmd-dialog {
  position: relative;
  width: min(520px, 100%);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 24px 48px rgba(0,0,0,.35);
  overflow: hidden;
}
.cmd-input-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.cmd-input-wrap svg { width: 16px; height: 16px; color: var(--text-faint); flex-shrink: 0; }
.cmd-input {
  flex: 1;
  border: none;
  background: transparent;
  font-family: var(--font);
  font-size: calc(14px * var(--type-scale, 1.2));
  color: var(--text);
  outline: none;
}
.cmd-input::placeholder { color: var(--text-faint); }
.cmd-kbd-inline { margin-left: auto; }
.cmd-results { max-height: min(360px, 50vh); overflow-y: auto; padding: 6px; }
.cmd-group-label {
  font-size: calc(10px * var(--type-scale, 1.2));
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-faint);
  padding: 6px 8px 4px;
}
.cmd-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--text);
  font-family: var(--font);
  font-size: calc(13px * var(--type-scale, 1.2));
  cursor: pointer;
}
.cmd-item:hover, .cmd-item.is-active { background: var(--active-bg); }
.cmd-item-hint { font-size: calc(11px * var(--type-scale, 1.2)); color: var(--text-muted); flex-shrink: 0; }
.cmd-empty { padding: 16px; text-align: center; font-size: calc(12px * var(--type-scale, 1.2)); color: var(--text-faint); }

/* ── Context feed collapse (tablet) ── */

/* ── Touch targets in planning grid ── */
.banen-vrij, .banen-geboekt, .ag-slot {
  min-height: 44px;
  min-width: 44px;
}
@media (min-width: 1100px) {
  .banen-vrij, .banen-geboekt { min-height: 36px; min-width: auto; }
  .ag-slot { min-height: 32px; min-width: 32px; }
}

/* ── Booking flow: segmented + sticky footer ── */
.bkflow.bkflow-card {
  display: flex;
  flex-direction: column;
  max-height: 100vh;
  padding: 0 !important;
}
.bkflow-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 28px 26px 12px;
  -webkit-overflow-scrolling: touch;
}
/* Popup-titel blijft bovenaan staan tijdens scrollen (sticky header). Negatieve
   marges = full-bleed over de scroll-padding; padding-right houdt ruimte voor de ×. */
.bkflow-card .bkflow-scroll { padding-top: 0 !important; }
.bkflow-card .bkflow-scroll > .bkflow-title {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--panel) !important;
  margin: 0 -26px 14px !important;
  padding: 24px 52px 12px 26px;
  border-bottom: 1px solid var(--border);
}
.bkflow-card .modal-close { z-index: 5; }
@media (max-width: 700px) {
  .bkflow-card .bkflow-scroll > .bkflow-title { margin: 0 -16px 12px !important; padding: 18px 48px 10px 16px; }
}
.bkflow-footer {
  flex-shrink: 0;
  padding: 12px 26px 20px;
  border-top: 1px solid var(--border);
  background: var(--panel);
}
/* Footer met ID-formulier-knop ernaast: knoppen op één rij, submit vult de rest. */
.bkflow-footer:has(.bkf-idform-btn:not([hidden])),
.bkf-idform-footer {
  display: flex;
  gap: 10px;
  align-items: stretch;
}
.bkf-idform-btn:not([hidden]), .bd-idform-btn:not([hidden]) {
  display: inline-flex !important;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
  flex-shrink: 0;
}
.bkf-idform-btn[hidden], .bd-idform-btn[hidden] { display: none !important; }
.bkf-idform-btn.is-filled, .bd-idform-btn.is-filled {
  color: var(--accent) !important;
  border-color: var(--accent) !important;
}
/* Badge rechtsboven op de ID-formulier-knop: groen vinkje = volledig ingevuld,
   rood "!" = verplicht maar nog niet volledig. */
.bkf-idform-btn { position: relative; overflow: visible; }
.bkf-idform-badge {
  position: absolute; top: -8px; right: -8px;
  min-width: 20px; height: 20px; padding: 0 4px;
  border-radius: 999px; display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; line-height: 1; color: #fff;
  border: 2px solid var(--panel); box-shadow: 0 1px 3px rgba(0,0,0,.22);
}
.bkf-idform-badge.ok { background: var(--success); }
.bkf-idform-badge.warn { background: var(--danger); }
/* Leeg formulier: reserveren mag zonder (Paulien 31 jul) — neutrale 'i',
   het hoort pas bij afhalen compleet te zijn. */
.bkf-idform-badge.info { background: var(--muted, #8a94a6); font-style: italic; }

/* Boeking-detail: banen wijzigen + prijs-herrekening (Paulien 31 jul). */
.bd-banen-stepper { display: flex; align-items: center; gap: 6px; }
.bd-banen-stepper .btn-ghost { padding: 4px 12px; min-width: 36px; font-size: 16px; line-height: 1.4; }
.bd-banen-stepper input {
  width: 56px; text-align: center; font-weight: 600;
  border: 1px solid var(--border, #d6dce4); border-radius: 8px; padding: 6px 4px;
  background: var(--panel, #fff); color: inherit;
}
.bd-banen-hint { display: block; margin-top: 4px; color: var(--muted, #667); font-size: 11.5px; }
.bd-herreken {
  border: 1px solid var(--border, #d6dce4); border-left: 3px solid var(--accent, #577C8E);
  border-radius: 8px; padding: 10px 12px; font-size: 12.5px; line-height: 1.45;
  background: color-mix(in srgb, var(--accent, #577C8E) 7%, transparent);
}
.bd-herreken strong { font-variant-numeric: tabular-nums; }
.bd-herreken.is-fout { border-left-color: var(--danger, #DC2626); background: color-mix(in srgb, var(--danger, #DC2626) 7%, transparent); }
/* Mobiel: footer-knoppen stapelen (ID-formulier boven, opslaan eronder) i.p.v.
   overlappen. Badge blijft netjes rechtsboven op de volle-breedte ID-knop. */
@media (max-width: 700px) {
  .bkflow-footer:has(.bkf-idform-btn:not([hidden])), .bkf-idform-footer {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }
  .bkf-idform-btn:not([hidden]) { width: 100%; justify-content: center; }
  .bkf-idform-btn .bkf-idform-badge { right: 10px; }
}
/* In de detail-footer staat de ID-knop links; Verwijderen schuift ernaast. */
.modal-footer.bd-actions .bd-idform-btn:not([hidden]) ~ .btn-danger { margin-right: 0; }
.modal-footer.bd-actions .bd-idform-btn { margin-right: auto; }
.bkf-idform-card { max-width: 560px; }
.bkf-idform-intro {
  margin: 0 0 16px;
  color: var(--text-muted);
  font-size: calc(12px * var(--type-scale, 1.2));
  line-height: 1.5;
}
.bk-seg {
  display: flex;
  gap: 4px;
  border: none;
  border-radius: 11px;
  overflow: hidden;
  background: var(--surface);
  padding: 4px;
}
/* Sectiekopjes in de Nieuwe boeking-sidebar (voorstel-bo-sidebar, Nick 16 jul). */
.bkf-sec {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 16px 0 8px;
}
.bkf-sec:first-child { margin-top: 2px; }
.bk-seg-btn {
  flex: 1;
  padding: 8px 10px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font);
  font-size: calc(11px * var(--type-scale, 1.2));
  font-weight: 600;
  cursor: pointer;
  min-height: 40px;
}
/* Actieve segment = witte pill op het grijze vlak, zoals de andere
   backoffice-switchers (rp-segmented) — het zwarte vulblok paste niet in het
   thema (Nick 16 jul, voorstel-bo-sidebar). */
.bk-seg-btn.is-active {
  background: var(--panel);
  color: var(--text);
  font-weight: 700;
  box-shadow: 0 1px 3px rgba(0,0,0,.12);
}
.bk-seg-field { margin-bottom: 12px; }
.bk-seg-field > span {
  display: block;
  font-size: calc(11px * var(--type-scale, 1.2));
  color: var(--text-muted);
  margin-bottom: 6px;
}

/* Datum + tijdslot: gelijke kolombreedte en veldhoogte */
.bkflow-overlay .booking-form .field-row {
  display: grid !important;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
  align-items: end;
}
.bkflow-overlay .booking-form .field-row > .field {
  min-width: 0;
  width: 100%;
}
.bkflow-overlay .booking-form .field-row > .field > select,
.bkflow-overlay .booking-form .field-row > .field > input:not([type="hidden"]) {
  width: 100% !important;
  box-sizing: border-box;
  min-width: 0;
}
/* Date/time-inputs vullen hun cel niet vanzelf op iOS (intrinsieke breedte) → bv.
   Geboortedatum oogt smaller. appearance:none normaliseert ze tot een box op 100%
   breedte; de calendar-indicator houden we expliciet zichtbaar zodat desktop de
   native picker behoudt. */
.bkflow-overlay .booking-form input[type="date"],
.bkflow-overlay .booking-form input[type="time"] {
  -webkit-appearance: none !important;
  appearance: none !important;
  width: 100% !important;
  min-width: 0;
  box-sizing: border-box;
  min-height: 40px;
}
.bkflow-overlay .booking-form input[type="date"]::-webkit-calendar-picker-indicator,
.bkflow-overlay .booking-form input[type="time"]::-webkit-calendar-picker-indicator {
  opacity: 1;
  cursor: pointer;
}
/* Velden uniform + responsive: de datum-trigger nooit over 2 regels (zodat 'ie even hoog
   is als de Tijdslot-select), en op mobiel stapelen de tekst-rijen tot volle breedte zodat
   alle velden even breed en ruim in beeld passen. Stepper-rijen blijven compact naast elkaar. */
.bkflow-overlay .booking-form .iselcal-trigger {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 560px) {
  .bkflow-overlay .booking-form .field-row:not(:has(.bkf-stepper)) {
    grid-template-columns: 1fr !important;
  }
}

/* Wellness-openingstijden (Beheer) — responsive: 3 koloms op desktop/iPad,
   naam op eigen regel + Open/Sluit naast elkaar op mobiel. */
/* Wellness: was een eigen tab die alleen doorverwees, is nu één regel op het
   Modules-scherm (voorstel-beheer.html, "ná"-stand). */
.mod-wellrow { display: flex; align-items: center; gap: 8px; font-size: calc(12px * var(--type-scale, 1)); color: var(--text-muted); border: 1px dashed var(--border-strong); border-radius: 9px; padding: 9px 12px; margin-top: 12px; line-height: 1.5; }
.mod-wellrow svg { flex: none; color: var(--accent); }
.mod-wellrow strong { color: var(--text); font-weight: 600; }
.mod-wellrow-lnk { border: 0; background: none; padding: 0; font: inherit; color: var(--accent); font-weight: 600; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.mod-wellrow-lnk:hover { color: var(--accent-hover); }
.wl-grid { display: grid; gap: 0; }
.wl-row { display: grid; grid-template-columns: minmax(110px, 1fr) minmax(0, 150px) minmax(0, 150px); align-items: center; gap: 8px 16px; padding: 12px 0; border-bottom: 1px solid var(--border); }
.wl-row:last-child { border-bottom: 0; }
.wl-name { font-weight: 600; color: var(--text); }
.wl-fld { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-muted); }
.wl-fld input[type="time"] { flex: 1 1 auto; width: 100%; -webkit-appearance: none; appearance: none; padding: 8px 9px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); color: var(--text); font: inherit; box-sizing: border-box; }
.wl-err { color: var(--danger); min-height: 18px; margin-top: 8px; font-size: 13px; }
@media (max-width: 560px) {
  .wl-row { grid-template-columns: 1fr 1fr; }
  .wl-name { grid-column: 1 / -1; }
}

.beheer-time-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.beheer-time-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: calc(11px * var(--type-scale, 1.2));
  padding: 4px 8px;
  border-radius: 4px;
  background: var(--surface);
  border: 1px solid var(--border);
}
.beheer-time-chip button {
  border: none;
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  font-size: calc(14px * var(--type-scale, 1.2));
  line-height: 1;
  padding: 0 2px;
}
.beheer-recipient-row {
  display: grid;
  grid-template-columns: 1fr 1.4fr auto;
  gap: 8px;
  align-items: end;
  margin-bottom: 8px;
}

.rpg-booking.is-hp {
  background: var(--rest-hp) !important;
  color: var(--text) !important;
  border: 1px solid var(--rest-hp-border) !important;
}
.rpg-booking.is-alacarte {
  background: var(--rest-alacarte) !important;
  color: var(--text) !important;
  border: 1px solid var(--rest-alacarte-border) !important;
}
.rpg-booking.is-request,
.rpg-booking.is-alacarte.is-request {
  background: var(--rest-req) !important;
  color: var(--text) !important;
  border: 1px dashed rgba(184,147,90,.35) !important;
}
.rpg-booking.is-group {
  background: var(--rest-group) !important;
  color: var(--text) !important;
  border: 1px solid var(--rest-alacarte-border) !important;
}
.rpg-booking.is-cancelled {
  background: var(--rest-cancelled) !important;
  color: var(--text-muted) !important;
  opacity: .65 !important;
}
.rpg-booking.is-gezeten {
  background: var(--rest-seated) !important;
  color: var(--text) !important;
  border-left: 3px solid var(--success) !important;
}
.rpg-booking.is-afgerond {
  background: var(--rest-done) !important;
  color: var(--text-muted) !important;
  opacity: .55 !important;
}
.rpg-booking:not(.is-hp):not(.is-request):not(.is-alacarte):not(.is-group):not(.is-cancelled):not(.is-gezeten):not(.is-afgerond) {
  background: var(--rest-confirmed) !important;
  color: var(--text) !important;
  border: 1px solid var(--rest-confirmed-border) !important;
}
.rpg-b-naam, .rpg-b-time, .rpg-b-pers, .rpg-request-naam, .rpg-request-pers, .rpg-request-time {
  color: inherit !important;
  font-family: var(--font) !important;
}
.rpg-slot-head.is-peak,
.rpg-cell.is-peak {
  background: var(--rest-peak) !important;
}
/* Piek-tijdvak: kolom-band + groene, vette, onderstreepte koptekst (handoff). */
.rpg-slot-head.is-peak {
  color: var(--accent) !important;
  font-weight: 700 !important;
  box-shadow: inset 0 -2px 0 var(--accent) !important;
}
/* Lijst-weergave als zwevende kaart (zelfde look & feel als de tijdlijn). */
.rp-lijst-wrap {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 16px !important;
  box-shadow: var(--shadow) !important;
  overflow: hidden !important;
}
.rp-lijst-wrap { overflow-x: auto !important; }
/* Sleep-hint boven de aanvragenlijst */
.rp-req-hint {
  display: flex; align-items: center; gap: 7px;
  margin: 2px 0 12px;
  font-size: calc(12px * var(--type-scale, 1.2));
  color: var(--text-faint);
}
.rp-req-hint svg { width: 14px; height: 14px; flex: none; }
/* ── Rechten-matrix (Beheer → Gebruikers) — handoff Fase 6 ── */
.pmatrix-card { background: var(--panel); border: 1px solid var(--border); border-radius: 14px; padding: 18px; margin-bottom: 16px; }
.pmatrix-note { margin: 4px 0 14px; font-size: 13px; color: var(--text-muted); line-height: 1.45; }
.pmatrix-wrap { overflow-x: auto; }
.pmatrix { width: 100%; border-collapse: collapse; }
.pmatrix th { text-align: center; font-size: 12px; font-weight: 700; color: var(--text-muted); padding: 10px 8px; border-bottom: 1px solid var(--border); }
.pmatrix th:first-child { text-align: left; font-size: 11.5px; letter-spacing: .05em; text-transform: uppercase; color: var(--text-faint); }
.pmatrix td { padding: 11px 8px; border-bottom: 1px solid var(--border); text-align: center; }
.pmatrix tr:last-child td { border-bottom: none; }
.pmatrix td:first-child { text-align: left; font-size: 14px; font-weight: 500; color: var(--text); }
.pmatrix .rolehead { display: block; color: var(--text); }
.pmatrix .rolehead small { display: block; font-weight: 500; color: var(--text-faint); font-size: 10.5px; text-transform: none; letter-spacing: 0; margin-top: 2px; }
.cbx { width: 22px; height: 22px; padding: 0; border-radius: 6px; border: 1.5px solid var(--border-strong); background: var(--panel); display: inline-grid; place-items: center; color: transparent; margin: 0 auto; cursor: pointer; transition: background .12s, border-color .12s; }
.cbx:not(.lock):hover { border-color: var(--accent); }
.cbx.on { background: var(--accent); border-color: var(--accent); color: #fff; }
[data-theme="grey"] .cbx.on { color: #0e0f0d; }
.cbx.lock { background: var(--surface); border-color: var(--border); color: var(--text-faint); cursor: default; }
.cbx.on.lock { background: var(--accent); border-color: var(--accent); color: #fff; opacity: .7; cursor: default; }
[data-theme="grey"] .cbx.on.lock { color: #0e0f0d; }
/* Niet-delegeerbaar recht: het slotje maakt zichtbaar dát het dichtstaat en
   waarom (title). Vervangt de stille HARD_VERBORGEN-uitsluiting die vroeger
   alleen in code stond — een vinkje zetten deed dan zichtbaar niets. */
.cbx.cbx-slot:not(.on) { background: var(--warning-soft); border-color: var(--warning); border-style: dashed; color: var(--warning); }
.cbx.cbx-slot:not(.lock) { cursor: pointer; }
.cbx.cbx-slot.on { border-style: dashed; }
/* "SERVICE"-label: gewone sans, bold, strakkere spacing (handoff i.p.v. Lekton). */
.rp-toolbar-label {
  font-family: var(--font) !important;
  font-size: calc(11.5px * var(--type-scale, 1.2)) !important;
  font-weight: 700 !important;
  letter-spacing: .08em !important;
  text-transform: uppercase !important;
  color: var(--text-faint) !important;
}
/* Aanvraag-kaart in handoff-stijl: naam + groene tijd-pill boven, meta eronder. */
.rpg-req-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.rpg-req-naam { font-size: calc(14px * var(--type-scale, 1.2)); font-weight: 600; color: var(--text); }
.rpg-req-time { flex: none; padding: 3px 9px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent); font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums; }
[data-theme="grey"] .rpg-req-time { color: #cdeede; }
.rpg-req-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 6px;
  font-size: 13px; color: var(--text-muted); }
.rpg-kchip { display: inline-flex; align-items: center; gap: 3px; padding: 2px 8px; border-radius: 999px;
  background: var(--warning-soft, rgba(217,119,6,.12)); color: var(--warning, #c2620d); font-size: 12px; font-weight: 600; }
.rpg-kchip--kid { background: var(--surface); color: var(--text-muted); }
.rpg-req-note { margin-top: 6px; font-size: 12.5px; color: var(--warning, #c2620d); }
.rpg-corner, .rpg-row-head, .rpg-slot-head, .rpg-slot-count, .rpg-corner-count {
  background: var(--surface) !important;
  color: var(--text-muted) !important;
  border-color: var(--border) !important;
}
.rpg-row.is-leeg .rpg-row-head,
.rpg-row.is-leeg .rpg-cell {
  background: var(--bg) !important;
  opacity: .35 !important;
}
.rpg-cell.is-dragover {
  background: var(--accent-soft) !important;
  outline: 2px dashed var(--accent) !important;
  outline-offset: -2px;
}
.rpg-request {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  color: var(--text) !important;
  border-radius: 6px !important;
}
.rpg-request:hover { background: var(--hover) !important; border-color: var(--border-strong) !important; }
.rpg-request-group-head { color: var(--text-muted) !important; font-family: var(--font) !important; }
.rpg-chrono-item { border-color: var(--border) !important; color: var(--text-muted) !important; }
.rpg-chrono-swatch.is-alacarte { background: var(--accent) !important; opacity: .55; }
.rpg-chrono-swatch.is-hp { background: var(--success) !important; opacity: .55; }
.rpg-chrono-swatch.is-group { background: var(--accent) !important; opacity: .45; }
.rpg-chrono-swatch.is-request { background: var(--warning) !important; opacity: .55; }
.rpg-chrono-swatch.is-cancelled { background: var(--danger) !important; opacity: .55; }
.rpg-chrono-swatch.is-gezeten { background: var(--success) !important; opacity: .75; }
.rpg-chrono-swatch.is-afgerond { background: var(--text-faint) !important; opacity: .55; }
.rp-aside-title, .rp-page-title, .rpg-shell h2, .rp-shell h2 {
  font-family: var(--font) !important;
  font-weight: 600 !important;
  color: var(--text) !important;
}
.rp-badge-geel, .rp-kinderstoelen-banner {
  background: var(--warning-soft) !important;
  color: var(--warning) !important;
  border: 1px solid rgba(184,147,90,.25) !important;
  font-family: var(--font) !important;
}
.rp-stats-mini, .rp-empty, .rpg-empty { color: var(--text-muted) !important; font-family: var(--font) !important; }
.rp-layout, .rpg-layout { color: var(--text) !important; }

/* Blokkades — geen navy/terracotta meer */
.blokkeer-toggle {
  background: var(--surface) !important;
  border: 1px solid var(--border-strong) !important;
  color: var(--text) !important;
  font-family: var(--font) !important;
  font-weight: 500 !important;
  letter-spacing: normal !important;
  border-radius: 6px !important;
}
.blokkeer-toggle:hover {
  border-color: var(--accent) !important;
  color: var(--accent) !important;
  background: var(--hover) !important;
}
.blokkeer-toggle.is-active {
  background: var(--accent) !important;
  color: #fff !important;
  border-color: var(--accent) !important;
}
.blokkeer-bar {
  background: var(--panel) !important;
  color: var(--text) !important;
  border-top: 1px solid var(--border) !important;
  box-shadow: 0 -8px 24px rgba(0,0,0,.25) !important;
}
.blokkeer-bar-count {
  background: var(--accent) !important;
  color: #fff !important;
  font-family: var(--font) !important;
  border-radius: 6px !important;
}
.blokkeer-bar-lbl {
  font-family: var(--font) !important;
  color: var(--text-muted) !important;
}
.blokkeer-bar-cancel {
  background: transparent !important;
  color: var(--text-muted) !important;
  border: 1px solid var(--border-strong) !important;
  border-radius: 6px !important;
  font-family: var(--font) !important;
}
.blokkeer-bar-cancel:hover { background: var(--hover) !important; color: var(--text) !important; }
.blokkeer-bar-confirm {
  background: var(--accent) !important;
  color: #fff !important;
  border: none !important;
  border-radius: 6px !important;
  font-family: var(--font) !important;
}
.blokkeer-bar-confirm:hover { background: var(--accent-hover) !important; }
.banen-cell.is-selected, .ag-slot.is-selected {
  outline: 2px solid var(--accent) !important;
  outline-offset: -2px;
  background: var(--accent-soft) !important;
  color: var(--accent) !important;
}
.banen-cell.banen-blok {
  background: var(--warning-soft) !important;
  color: var(--warning) !important;
  border: 1px solid rgba(184,147,90,.22) !important;
}
.banen-tijd-clickable, .banen-hed-clickable, .ag-tijd-clickable {
  color: var(--text-muted) !important;
}
.banen-tijd-clickable:hover, .banen-hed-clickable:hover, .ag-tijd-clickable:hover {
  color: var(--accent) !important;
  background: var(--hover) !important;
}

/* Mailings editor */
.ml-shell, .ml-sidebar, .ml-editor-wrap {
  background: var(--panel) !important;
  border-color: var(--border) !important;
  color: var(--text) !important;
}
.ml-list-item:hover { background: var(--hover) !important; }
.ml-list-label, .ml-editor-title { font-family: var(--font) !important; color: var(--text) !important; }
.ml-list-meta, .ml-editor-desc, .ml-empty { color: var(--text-muted) !important; font-family: var(--font) !important; }
.ml-input, .ml-textarea {
  background: var(--surface) !important;
  border: 1px solid var(--border-strong) !important;
  color: var(--text) !important;
  font-family: var(--font) !important;
  border-radius: 6px !important;
}
.ml-input:focus, .ml-textarea:focus {
  border-color: var(--accent) !important;
  box-shadow: 0 0 0 2px var(--accent-soft) !important;
}
.ml-ph-chip {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  color: var(--text-muted) !important;
  font-family: var(--font) !important;
  border-radius: 4px !important;
}
.ml-ph-chip:hover {
  background: var(--accent) !important;
  color: #fff !important;
  border-color: var(--accent) !important;
}
.ml-placeholders { background: var(--surface) !important; border-color: var(--border) !important; }
.ml-placeholders-title { color: var(--text-muted) !important; font-family: var(--font) !important; }
.ml-editor-actions { border-color: var(--border) !important; }

/* Betaallinks */
.bl-card, .bl-result-head, .bl-url-wrap {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
  color: var(--text) !important;
}
.bl-card-title, .bl-result-bedrag, .bl-result-omschr {
  font-family: var(--font) !important;
  color: var(--text) !important;
}
.bl-result-bedrag { color: var(--accent) !important; }
.bl-url-input {
  background: var(--bg) !important;
  border: 1px solid var(--border) !important;
  color: var(--text) !important;
  font-family: var(--font) !important;
}
.bl-badge-ok { background: var(--success-soft) !important; color: var(--success) !important; }
.bl-badge-err { background: var(--danger-soft) !important; color: var(--danger) !important; }
.bl-badge-pending { background: var(--warning-soft) !important; color: var(--warning) !important; }
.bl-empty, .bl-result-hint, .bl-mail-bevestig { color: var(--text-muted) !important; font-family: var(--font) !important; }
.bl-mail-bevestig.bl-mail-warn { background: var(--warning-soft) !important; color: var(--warning) !important; border-color: rgba(184,147,90,.25) !important; }

/* Dagafsluiting */
.da-toolbar, .da-card, .da-grid {
  background: var(--panel) !important;
  border-color: var(--border) !important;
  color: var(--text) !important;
}
.da-card-title, .da-totaal, .da-kv dt, .da-kv dd {
  font-family: var(--font) !important;
  color: var(--text) !important;
}
.da-badge-ok { background: var(--success-soft) !important; color: var(--success) !important; border-color: rgba(74,155,127,.25) !important; }
.da-badge-pending { background: var(--warning-soft) !important; color: var(--warning) !important; border-color: rgba(184,147,90,.25) !important; }
.da-empty { color: var(--text-muted) !important; }

/* Scan */
.scan-match-badge {
  background: var(--success-soft) !important;
  color: var(--success) !important;
  font-family: var(--font) !important;
  border-radius: 6px !important;
}
.scan-action.is-warn .scan-match-badge { background: var(--warning-soft) !important; color: var(--warning) !important; }
.scan-row span { color: var(--text-muted) !important; font-family: var(--font) !important; }
.scan-row strong { color: var(--text) !important; font-family: var(--font) !important; }
.scan-no-match { color: var(--text-muted) !important; background: var(--surface) !important; border: 1px solid var(--border) !important; border-radius: 8px !important; }
.scan-inname-opt { color: var(--text) !important; font-family: var(--font) !important; font-size: calc(13px * var(--type-scale, 1.2)) !important; }
.scan-hint { color: var(--text-muted) !important; }

/* Booking flow info boxes */
.bk-mollie-info, .bk-ticket-info {
  background: var(--accent-soft) !important;
  border: 1px solid rgba(78,139,201,.22) !important;
  color: var(--text-muted) !important;
  border-radius: 8px !important;
  font-family: var(--font) !important;
  font-size: calc(12px * var(--type-scale, 1.2)) !important;
}
.bk-mollie-info svg, .bk-ticket-info svg { color: var(--accent) !important; }

/* Activity settings modal tiers */
.as-tier-row, .beheer-tier-row {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  border-radius: 6px !important;
}
.as-tier-add, .bh-tier-add, .bh-baan-add { color: var(--accent) !important; }
.as-tier-add:hover, .bh-tier-add:hover, .bh-baan-add:hover { background: var(--accent-soft) !important; }
.beheer-baan-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: 4px;
  background: var(--surface);
}
.beheer-baan-naam { font-size: calc(12px * var(--type-scale, 1.2)); font-weight: 600; min-width: 72px; color: var(--text); }
.beheer-baan-meta { font-size: calc(11px * var(--type-scale, 1.2)); color: var(--text-faint); flex: 1; }

/* BD meta rows in booking detail */
.bd-meta, .scan-row { color: var(--text) !important; }
.bd-meta .scan-row span, .bd-meta strong { font-family: var(--font) !important; }

/* Cron */
/* Cron-jobs was de enige plek in de backoffice met drie eigen lettertypes
   (League Spartan / Lora / Lekton) — restjes van vóór de Geist-rebrand. Deze
   remap greep op `.cr-card h4`, maar de echte kop is een <h3> met class
   .cr-title, en de paginakop/hint/labels hadden helemaal geen ingang. Nu op de
   werkelijke elementen. */
.cr-card h4, .cr-card p { color: var(--text) !important; font-family: var(--font) !important; }
.cr-card p { color: var(--text-muted) !important; }
.cr-shell-title, .cr-shell-hint, .cr-title, .cr-naam, .cr-doel,
.cr-raakt, .cr-chip, .cr-kv, .cr-kv dt, .cr-kv dd, .cr-tz {
  font-family: var(--font) !important;
  letter-spacing: 0 !important;
}
.cr-shell-title { font-size: calc(16px * var(--type-scale, 1)) !important; font-weight: 650 !important; color: var(--text) !important; }
.cr-shell-hint { font-size: calc(12.5px * var(--type-scale, 1)) !important; color: var(--text-muted) !important; }
.cr-title { font-size: calc(15px * var(--type-scale, 1)) !important; font-weight: 650 !important; color: var(--text) !important; }
.cr-naam { font-size: calc(11px * var(--type-scale, 1)) !important; color: var(--text-faint) !important; }
.cr-doel { font-size: calc(12.5px * var(--type-scale, 1)) !important; color: var(--text-muted) !important; }
.cr-raakt { font-size: calc(11px * var(--type-scale, 1)) !important; color: var(--text-muted) !important; }
.cr-chip { background: var(--surface) !important; border: 1px solid var(--border); border-radius: 100px; color: var(--text-muted) !important; font-size: calc(11px * var(--type-scale, 1)) !important; padding: 2px 8px !important; }
.cr-kv { font-size: calc(12px * var(--type-scale, 1)) !important; color: var(--text-muted) !important; }
.cr-kv dd { color: var(--text) !important; }
/* Alleen het cron-schema zelf blijft mono — dat ís code (`0 10 * * *`). */
.cr-kv code { font-family: var(--font-mono) !important; font-size: calc(11px * var(--type-scale, 1)) !important; background: var(--surface) !important; border: 1px solid var(--border); border-radius: 4px; color: var(--text) !important; }

/* ── Calendar / shared widgets (scoped to backoffice) ── */
.app-shell {
  --iselmar-primary: var(--accent);
  --iselmar-accent: var(--danger);
  --iselmar-text: var(--text);
  --iselmar-text-light: var(--text-muted);
  --iselmar-muted: var(--text-faint);
  --iselmar-border: var(--border-strong);
  --iselmar-border-soft: var(--border);
  --iselmar-cream: var(--surface);
  --iselmar-bg-soft: var(--bg);
  --radius: 6px;
  --radius-lg: 8px;
  --radius-xl: 10px;
  --radius-sm: 4px;
  --shadow-lg: var(--shadow);
  --shadow-sm: 0 2px 8px rgba(0,0,0,.08);
  --font-display: var(--font);
}
.app-shell .iselcal-trigger,
.bkflow-overlay .iselcal-trigger,
.app-shell .iselsel-trigger,
.bkflow-overlay .iselsel-trigger {
  background: var(--surface) !important;
  border: 1px solid var(--border-strong) !important;
  border-radius: 6px !important;
  color: var(--text) !important;
  font-family: var(--font) !important;
  font-size: calc(13px * var(--type-scale, 1.2)) !important;
  padding: 8px 12px !important;
  box-sizing: border-box;
}
.bkflow-overlay .booking-form .iselcal-root,
.bkflow-overlay .booking-form .bkf-datum-mount {
  width: 100%;
  display: block;
}
.bkflow-overlay .booking-form .iselcal-trigger {
  width: 100% !important;
  min-height: 41px;
  padding: 12px 14px !important;
}
.app-shell .iselcal-trigger:hover,
.bkflow-overlay .iselcal-trigger:hover,
.app-shell .iselsel-trigger:hover,
.bkflow-overlay .iselsel-trigger:hover,
.app-shell .iselcal-root.is-open .iselcal-trigger,
.bkflow-overlay .iselcal-root.is-open .iselcal-trigger {
  border-color: var(--accent) !important;
  box-shadow: 0 0 0 2px var(--accent-soft) !important;
}
.app-shell .iselcal-panel,
.bkflow-overlay .iselcal-panel,
.app-shell .iselsel-panel,
.bkflow-overlay .iselsel-panel {
  background: var(--panel) !important;
  border: 1px solid var(--border) !important;
  border-radius: 8px !important;
  box-shadow: var(--shadow) !important;
}
.app-shell .iselcal-title,
.bkflow-overlay .iselcal-title,
.app-shell .iselcal-day,
.bkflow-overlay .iselcal-day,
.app-shell .iselsel-option,
.bkflow-overlay .iselsel-option {
  font-family: var(--font) !important;
  color: var(--text) !important;
}
.app-shell .iselcal-label,
.bkflow-overlay .iselcal-label,
.login-shell .iselcal-label {
  font-size: calc(13px * var(--type-scale, 1.2)) !important;
}
.app-shell .iselcal-title,
.bkflow-overlay .iselcal-title {
  font-size: calc(16px * var(--type-scale, 1.2)) !important;
}
.app-shell .iselcal-daynames > div,
.bkflow-overlay .iselcal-daynames > div {
  font-size: calc(11px * var(--type-scale, 1.2)) !important;
}
.app-shell .iselcal-day,
.bkflow-overlay .iselcal-day {
  font-size: calc(13px * var(--type-scale, 1.2)) !important;
}
.app-shell .iselcal-input,
.bkflow-overlay .iselcal-input {
  font-size: calc(14px * var(--type-scale, 1.2)) !important;
}
.app-shell .iselcal-today,
.bkflow-overlay .iselcal-today {
  font-size: calc(12px * var(--type-scale, 1.2)) !important;
}
.app-shell .iselcal-daynames > div,
.bkflow-overlay .iselcal-daynames > div,
.app-shell .iselcal-nav,
.bkflow-overlay .iselcal-nav {
  color: var(--text-muted) !important;
}
.app-shell .iselcal-day:hover:not(:disabled):not(.is-selected),
.bkflow-overlay .iselcal-day:hover:not(:disabled):not(.is-selected) {
  background: var(--hover) !important;
}
.app-shell .iselcal-day.is-selected,
.bkflow-overlay .iselcal-day.is-selected,
.app-shell .iselcal-day.is-range-start,
.bkflow-overlay .iselcal-day.is-range-start,
.app-shell .iselcal-day.is-range-end,
.bkflow-overlay .iselcal-day.is-range-end {
  background: var(--accent) !important;
  color: #fff !important;
}
.app-shell .iselcal-day.is-today:not(.is-selected),
.bkflow-overlay .iselcal-day.is-today:not(.is-selected) {
  border-color: var(--accent) !important;
  color: var(--accent) !important;
}
.app-shell .iselcal-today,
.bkflow-overlay .iselcal-today,
.app-shell .iselcal-nav:hover,
.bkflow-overlay .iselcal-nav:hover {
  color: var(--accent) !important;
}
.app-shell .iselsel-option.is-selected,
.bkflow-overlay .iselsel-option.is-selected {
  background: var(--accent-soft) !important;
  color: var(--accent) !important;
}

/* Hide old header if any remnant */

/* ── Beheer → Modules ── */
.beheer-modules .mod-intro { max-width: 42rem; margin-bottom: 14px; }
.beheer-modules .mod-warn { color: var(--warning); }
.mod-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 10px;
}
.mod-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.mod-card--off { opacity: .72; }
.mod-card--soon { border-style: dashed; }
.mod-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.mod-card-head strong { font-size: calc(13px * var(--type-scale, 1.2)); font-weight: 600; }
.mod-card-hint { font-size: calc(11px * var(--type-scale, 1.2)); color: var(--text-muted); line-height: 1.4; }
.mod-card-note { font-size: calc(10px * var(--type-scale, 1.2)); color: var(--text-faint); }
/* "Beperkt"-module: directe ingang naar het scherm dat wél bestaat. */
.mod-card-lnk { align-self: flex-start; border: 0; background: none; padding: 0; font: inherit; font-size: calc(11.5px * var(--type-scale, 1)); font-weight: 600; color: var(--accent); cursor: pointer; }
.mod-card-lnk:hover { text-decoration: underline; text-underline-offset: 2px; }
.mod-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  margin-top: auto;
}
.mod-toggle--compact { margin-top: 0; }
.mod-toggle-chk, .mod-act-chk { position: absolute; opacity: 0; width: 0; height: 0; }
.mod-toggle-slider {
  width: 36px;
  height: 20px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  position: relative;
  flex-shrink: 0;
  transition: background .15s;
}
.mod-toggle-slider::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--text-muted);
  transition: transform .15s, background .15s;
}
.mod-toggle-chk:checked + .mod-toggle-slider,
.mod-act-chk:checked + .mod-toggle-slider {
  background: rgba(74,155,127,.25);
  border-color: rgba(74,155,127,.45);
}
.mod-toggle-chk:checked + .mod-toggle-slider::after,
.mod-act-chk:checked + .mod-toggle-slider::after {
  transform: translateX(16px);
  background: var(--success, #4A9B7F);
}
.mod-toggle-lbl { font-size: calc(11px * var(--type-scale, 1.2)); color: var(--text-muted); }
.mod-act-list { display: flex; flex-direction: column; gap: 6px; }
.mod-act-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 10px;
  align-items: center;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
}
.mod-act-row--off { opacity: .65; }
.mod-act-info strong { display: block; font-size: calc(12px * var(--type-scale, 1.2)); font-weight: 500; }
.mod-act-info span { font-size: calc(10px * var(--type-scale, 1.2)); color: var(--text-faint); }
.mod-act-config { font-size: calc(11px * var(--type-scale, 1.2)); padding: 4px 8px; white-space: nowrap; }
.beheer-item--off { opacity: .55; }
.beheer-item--off strong::after {
  content: ' · uit';
  font-weight: 400;
  color: var(--text-faint);
  font-size: calc(10px * var(--type-scale, 1.2));
}
@media (max-width: 640px) {
  .mod-act-row { grid-template-columns: 1fr; }
  .mod-act-config { justify-self: start; }
}

.app-header { display: none !important; }

/* ── Claude Design spec — accent is CHROME (focus-ring, subtiele indicatoren,
   randen): grey #3A3A3A, light #D4D4D4. De codebase hergebruikt --accent op
   sommige plekken als LEESBARE tekst/icoon; daar zou de neutrale accent
   onzichtbaar zijn (donker op donker / licht op wit). Hier alleen die KLEUR
   neutraliseren naar leesbaar grijs — in BEIDE thema's via [data-theme], met
   thema-eigen var-waarde. Geen layout-wijziging. ── */
[data-theme] .act-settings-btn,
[data-theme] .act-beheer-link,
[data-theme] .module-btn-scan:not(.is-active):hover,
[data-theme] .bk-mollie-info svg,
[data-theme] .bk-ticket-info svg,
[data-theme] .as-tier-add,
[data-theme] .bh-tier-add,
[data-theme] .bh-baan-add { color: var(--text-muted) !important; }

[data-theme] .blokkeer-toggle:hover,
[data-theme] .banen-tijd-clickable:hover,
[data-theme] .banen-hed-clickable:hover,
[data-theme] .ag-tijd-clickable:hover,
[data-theme] .bl-result-bedrag,
[data-theme] .bkflow-overlay .iselcal-day.is-today:not(.is-selected),
[data-theme] .bkflow-overlay .iselcal-nav:hover,
[data-theme] .bkflow-overlay .iselsel-option.is-selected { color: var(--text) !important; }

/* Geselecteerde slot/cel: leesbare chip i.p.v. onzichtbare accent-tekst. */
[data-theme] .banen-cell.is-selected,
[data-theme] .ag-slot.is-selected {
  color: var(--text) !important;
  outline-color: var(--text-muted) !important;
  background: var(--surface) !important;
}

/* Resterende hardcoded blauwe rand op info-boxen → neutraal in beide thema's. */
[data-theme] .bk-mollie-info,
[data-theme] .bk-ticket-info { border-color: var(--border) !important; }

/* Focus-ring volgt het groene accent (Claude Design handoff). */
[data-theme="light"] .field > input:focus,
[data-theme="light"] .field > select:focus,
[data-theme="light"] .field > textarea:focus { border-color: var(--accent) !important; box-shadow: 0 0 0 3px var(--accent-soft) !important; }

/* ── Fijn-afstemming navbar + activiteiten (gebruikers-tweaks) ── */
/* Datepicker-balk bovenaan: witte (panel) vulling i.p.v. grijze surface. */
.datum-cal-wrap .iselcal-trigger { background: var(--panel) !important; }

/* Nav-knop hover in light = #F3F3F3 (ook de geselecteerde knop bij hover). */
html[data-theme="light"] .module-btn:hover { background: #F3F3F3 !important; color: var(--text) !important; }

/* Hover-effect op de activiteiten-filterpills (surface=hover botst in de
   neutrale tokens, dus expliciete tint per thema + rand-accent). */
.act-tab:hover:not(.is-active) { border-color: var(--border-strong) !important; color: var(--text) !important; }
html[data-theme="light"] .act-tab:hover:not(.is-active) { background: #F3F3F3 !important; }
html[data-theme="grey"] .act-tab:hover:not(.is-active) { background: #2E2E2E !important; }

/* Verborgen kinderen-veld in de balie-boeking echt verbergen (de .field-regel
   zet display, dus het [hidden]-attribuut heeft een expliciete override nodig). */
#bkf-kind-wrap[hidden] { display: none !important; }

/* Multi-baan keuze in de balie-boeking (chips). */
#bkf-banen-wrap[hidden] { display: none !important; }
.bkf-banen-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.bkf-baan-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px;
  border-radius: 9px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text-muted);
  font-family: var(--font);
  font-size: calc(12px * var(--type-scale, 1.2));
  font-weight: 500;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}
.bkf-baan-chip:hover:not(.is-primary):not(.is-on) { border-color: var(--accent); color: var(--text); }
.bkf-baan-chip.is-on { background: var(--accent-soft); border-color: var(--accent); color: var(--text); font-weight: 600; }
.bkf-baan-chip.is-on::before { content: '\2713'; color: var(--accent); font-weight: 700; font-size: .92em; }
.bkf-baan-chip.is-primary { cursor: default; }
.bkf-baan-chip.is-primary.is-on::before { content: '\2605'; }
#bkf-banen-label.is-tekort { color: var(--danger); }

/* Verleden TIJD vandaag = grijs maar klikbaar (walk-in achteraf registreren).
   Verleden DATUM-cellen zijn dimmer en niet klikbaar. */
.ag-slot.is-verleden,
.banen-cell.banen-vrij.is-verleden {
  opacity: .45 !important;
  cursor: pointer !important;
  text-decoration: none !important;
}
/* Voorbije tijden vervagen volledig (geen doorstrepen — variant A, jul 2026);
   blijven klikbaar voor walk-in. Stip verdwijnt mee via de :not(.is-verleden). */
.ag-slot.is-verleden { border-color: transparent !important; background: none !important; }
.ag-slot.is-verleden:hover,
.banen-cell.banen-vrij.is-verleden:hover { opacity: .8 !important; }
.banen-cell.banen-vol.is-verleden { opacity: .35 !important; }

/* Info-melding in de balie-boeking (bv. multi-slot tijdvakken). */
.bkf-info-note {
  font-size: calc(11px * var(--type-scale, 1.2));
  color: var(--text-muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
}
.bkf-info-note[hidden] { display: none !important; }

/* Personen/kinderen steppers in de balie-boeking (webapp-stijl +/-). */
.bkf-stepper {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface);
  width: fit-content;
}
.bkf-step {
  width: 36px;
  height: 38px;
  border: none;
  background: transparent;
  color: var(--text);
  font-size: calc(16px * var(--type-scale, 1.2));
  line-height: 1;
  cursor: pointer;
}
.bkf-step:hover { background: var(--hover); }
/* Telefoon-veld staat nu naast de personen/kinderen-steppers — input even hoog
   maken zodat de drie kolommen netjes uitlijnen. */
#bkf-tel { min-height: 40px; }
.bkf-stepper input {
  width: 52px;
  text-align: center;
  border: none !important;
  background: transparent !important;
  box-shadow: none !important;
  -moz-appearance: textfield;
  font-family: var(--font);
  font-size: calc(14px * var(--type-scale, 1.2));
  color: var(--text);
  padding: 0 !important;
}
.bkf-stepper input::-webkit-outer-spin-button,
.bkf-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.bkf-info-note span { display: block; }
.bkf-extra-slots-btn {
  display: inline-block;
  margin-top: 8px;
  padding: 7px 12px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--panel);
  color: var(--text);
  font-family: var(--font);
  font-size: calc(12px * var(--type-scale, 1.2));
  font-weight: 500;
  cursor: pointer;
}
.bkf-extra-slots-btn:hover { background: var(--hover); }

/* Tijdvak-picker (Phase C, eerste versie): de modal-inhoud "vouwt in" naar een
   picker met hover-preview van de opeenvolgende reeks. */
.bkflow-card.is-picking .bkflow-scroll,
.bkflow-card.is-picking .bkflow-footer { display: none !important; }
.bkf-picker[hidden] { display: none !important; }
.bkf-picker { padding: 22px; }
.bkf-picker-inner { animation: bkfPickIn .2s ease; }
@keyframes bkfPickIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
/* Terug = icoon-knop (chevron) i.p.v. tekstlink — symmetrisch met de ×-sluitknop
   rechtsboven. */
.bkf-picker-back {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 50%;
  background: none; border: none; cursor: pointer;
  color: var(--text-muted); padding: 0; margin: 0 0 14px -6px;
}
.bkf-picker-back svg { width: 20px; height: 20px; }
.bkf-picker-back:hover { color: var(--text); background: var(--surface); }
.bkf-picker-title { font-size: calc(17px * var(--type-scale, 1.2)); font-weight: 600; color: var(--text); margin: 0 0 4px; }
.bkf-picker-sub { font-size: calc(12px * var(--type-scale, 1.2)); color: var(--text-muted); margin: 0 0 16px; line-height: 1.4; }
.bkf-pick-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; }
.bkf-pick-chip {
  padding: 12px 4px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--text-muted);
  font-family: var(--font); font-variant-numeric: tabular-nums;
  font-size: calc(12px * var(--type-scale, 1.2)); cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.bkf-pick-chip.is-disabled { opacity: .3; cursor: not-allowed; }
/* Vrij slot dat geen geldige starttijd is (geen volledig blok past), maar wél
   mee mag oplichten in een hover-preview. Niet gefaded, geen pointer. */
.bkf-pick-chip.is-inert { cursor: default; }
/* Preview = solide gevulde tegels zodat het opeenvolgende blok onmiskenbaar
   zichtbaar is. (In light is --surface == --active-bg, dus een subtiele bg-shift
   was onzichtbaar — daarom een echt contrasterende vulling met --text.) */
.bkf-pick-chip.is-preview { background: var(--text) !important; color: var(--panel) !important; border-color: var(--text) !important; }
.bkf-pick-chip.is-preview-start { box-shadow: inset 0 0 0 2px var(--panel); font-weight: 700; }

/* ═══════════════════════════════════════════════════════════════════════════
   LOGIN — de vormentaal van het activiteiten-eiland, in gewone HTML + CSS.

   Waarom géén React-eiland met shadcn-componenten: dit scherm rendert direct
   uit de HTML, vóór er een bundel geladen is. Een eiland zou hier een leeg
   scherm opleveren tot de bundel binnen is — precies op de plek waar dat het
   meest opvalt. Vandaar een exacte visuele match met de hand.

   De waarden hieronder zijn LETTERLIJK overgenomen uit de gebouwde eiland-CSS
   (public/receptiev2/activiteiten/assets/index-*.css → `:root` en `.dark`) en
   daarna in de browser nagemeten op het eiland zelf.

   Ze staan bewust LOGIN-SCOPED (--lg-*). De shell-tokens blijven onaangeroerd:
   die zetten --accent op #577C8E, en juist dát verschil met de primaire kleur
   van het eiland (#2f4157) viel op. #577C8E blijft wél de focus-ring, want dat
   ís de --ring van het eiland; alleen de knopvulling gaat naar --primary.
   ═══════════════════════════════════════════════════════════════════════════ */
.login-shell {
  --lg-bg: oklch(100% 0 0);            /* --background */
  --lg-card: oklch(100% 0 0);          /* --card       */
  --lg-border: oklch(92.2% 0 0);       /* --border     */
  --lg-input: oklch(92.2% 0 0);        /* --input      */
  --lg-input-bg: transparent;          /* bg-transparent */
  --lg-primary: #2f4157;               /* --primary    */
  --lg-primary-fg: oklch(98.5% 0 0);   /* --primary-foreground */
  --lg-ring: #577c8e;                  /* --ring       */
  --lg-fg: oklch(14.5% 0 0);           /* --foreground */
  --lg-muted-fg: oklch(55.6% 0 0);     /* --muted-foreground */
  --lg-success: oklch(57.7% .152 149.5);
  /* MELDINGSKLEUREN VOOR DE ALERT, in dezelfde oklch-grammatica als de rest
     hierboven en letterlijk gelijk aan de eiland-tokens (shell-src/src/index.css
     r95-116). Twee sporen, want de login toont twee soorten meldingen:
       destructive = er ging iets mis (verkeerd wachtwoord)
       warning     = let op, actie nodig, maar er is niets stuk (sessie verlopen)
     De -tekst-varianten zakken naar L=0.47 omdat L=0.577 op een lichte tint
     maar 3.5-4.0:1 haalt. Gemeten 31 aug 2026: theme.css' eigen --warning
     (#c2620d) op --warning-soft (#fbecdc) geeft 3.59:1 en zakt dus door de
     4.5:1-eis; oklch(0.47 0.12 70.08) haalt hem wél. */
  --lg-destructive: oklch(0.577 0.245 27.325);
  --lg-destructive-tekst: oklch(0.47 0.2 27.325);
  --lg-warning: oklch(0.577 0.144 70.08);
  --lg-warning-tekst: oklch(0.47 0.12 70.08);
  --lg-r-md: calc(0.625rem - 2px);     /* 8px  — rounded-md */
  --lg-r-lg: 0.625rem;                 /* 10px — rounded-lg (shadcn Alert) */
  --lg-r-xl: calc(0.625rem + 4px);     /* 14px — rounded-xl */
  --lg-shadow-xs: 0 1px 2px 0 rgb(0 0 0 / .05);
  --lg-shadow-card: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);

  --lg-veld-h: 40px;                   /* zie .lf-input */

  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 92px 20px 148px;            /* boven ruimte voor het paginamerk;
                                          onder MEER dan boven, zodat het blok
                                          net boven het midden hangt — optisch
                                          midden ligt hoger dan het rekenkundige */
  background: var(--lg-bg);
  position: relative;
  overflow-x: hidden;
}
html[data-theme="grey"] .login-shell {
  --lg-bg: oklch(14.5% 0 0);
  --lg-card: oklch(20.5% 0 0);
  --lg-border: oklch(100% 0 0 / .1);
  --lg-input: oklch(100% 0 0 / .15);
  --lg-input-bg: oklch(100% 0 0 / .045);
  --lg-primary: #7a9eb1;
  --lg-primary-fg: oklch(14.5% 0 0);
  --lg-ring: #7a9eb1;
  --lg-fg: oklch(98.5% 0 0);
  --lg-muted-fg: oklch(70.8% 0 0);
  --lg-success: oklch(70.4% .145 149.5);
  /* Donker: de tekstvariant is de kleur zélf — op een donkere ondergrond haalt
     L=0.704 ruim de 4.5:1 en zou verdonkeren juist tegenwerken. */
  --lg-destructive: oklch(0.704 0.191 22.216);
  --lg-destructive-tekst: oklch(0.704 0.191 22.216);
  --lg-warning: oklch(0.704 0.15 70.08);
  --lg-warning-tekst: oklch(0.704 0.15 70.08);
}
.login-shell::before { content: none; }

.login-main {
  width: 100%;
  /* 31 aug 2026 · Nick: "de invulvelden zijn te breed voor de invoertekst".
     Klopt, en dit is de meting waarop 320 gekozen is (Chromium, Geist 14px,
     het formulierlettertype zelf):
       "administratie@sporthoteliselmar.nl"  223px  ← langste realistische invoer
       "voorbeeld@iselmar.nl"                137px  ← de placeholder
       twintig wachtwoordbolletjes            87px
     Het veld draagt daar bovenop zijn eigen chroom: 2×14px binnenmarge, 8px
     tussenruimte en de vink/oog-knop van 16-20px — samen ~52px. De langste
     invoer vraagt dus ~275px. 320px (20rem = Tailwinds max-w-xs, dus een maat
     uit hetzelfde stelsel als de rest hier) laat 45px lucht en is 100px minder
     dan de 420 die hier stond.
     DE 2FA-RIJ LOOPT MEE, NIET APART. Zes vakjes met 6px ertussen: (320−30)/6
     = 48,3px per vakje bij 40px hoog. Dat is exact het ritme dat de telefoon
     vandaag al toont (49px), dus breed en smal gaan er niet meer op verschillen
     — waar 420px de vakjes op 61px zette en de rij uit de pas liet lopen. */
  max-width: 320px;
  min-height: 0;
  margin: 0 auto;
  padding: 0;
  display: flex;
  flex-direction: column;
  position: relative;
}

/* GEEN KAART MEER (Nick, 23 aug 2026, met een referentiebeeld erbij). De
   inhoud staat rechtstreeks op de achtergrond: geen rand, geen vulkleur, geen
   schaduw. De shadcn-vorm zit nog steeds in de ONDERDELEN — Input, Button,
   Alert, de tokens hierboven — alleen de omhullende Card is weg. `.login-card`
   houdt zijn naam omdat app.js en wachtwoord.html eraan hangen; hernoemen zou
   drie bestanden raken voor nul zichtbaar verschil. */
.login-card {
  width: 100%;
  max-width: none;
  min-height: 0;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  text-align: left;
  display: flex;
  flex-direction: column;
  animation: suCardIn .45s var(--su-ease) both;
}

/* Merk: linksboven op de PAGINA, buiten de kolom. Absoluut, zodat het
   formulier zuiver in het midden blijft staan en niet door de logo-hoogte
   omlaag wordt geduwd. */
.login-brand {
  position: absolute;
  top: 28px;
  left: 32px;
  display: flex;
  justify-content: flex-start;
  margin: 0;
}
.login-logo-img { height: 34px; width: auto; display: block; }
/* Smal scherm. HET MERK BLIJFT ABSOLUUT — en dat is geen detail.
   Hier stond tot 24 aug 2026 `position: static`, en dan wordt `.login-brand`
   een gewoon item in de flexrij van `.login-shell`. Die rij centreert zijn
   items, dus het logo duwde de hele kolom opzij: gemeten op een scherm van
   390px stond het veld op 101..377 — 101 pixels lucht links, 13 rechts. Exact
   de val waar de opmerking bij `.tpill.login-theme` verderop al voor
   waarschuwt. Op smal wordt alleen de hoek krapper, niet de techniek. */
@media (max-width: 520px) {
  .login-shell { padding: 84px 20px 64px; }
  .login-brand { top: 20px; left: 20px; }
  .login-logo-img { height: 28px; }
  /* 32px kop is fors op 390px; 27 leest hier rustiger en houdt "Welkom terug"
     op één regel. */
  .login-card h1 { font-size: 27px; }
  .login-card .sub { font-size: 14px; }
}
/* Donker thema: witte logo-variant, anders valt het navy logo weg op de
   donkere kaart. Zelfde swap als de zijbalk. */
html[data-theme="grey"] .login-logo-img { content: url(./iselmar-logo-white.png?v=5); }

/* Kop en subtitel staan GECENTREERD; de labels en velden eronder blijven
   links. Die breuk is opzet en komt uit de referentie: het bovenblok spreekt
   de bezoeker aan, het formulier eronder wordt gelezen en ingevuld. */
.login-card h1 {
  margin: 0 0 8px;
  font-family: var(--font);
  font-size: 30px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -.02em;
  text-align: center;
  color: var(--lg-fg);
}
.login-card .sub {
  margin: 0 0 24px;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.45;
  text-align: center;
  color: var(--lg-muted-fg);
}
/* Staat er een foutmelding, dan is DIE de onderrand van het bovenblok. */
.login-card .sub:has(+ #login-err.is-open) { margin-bottom: 12px; }

.login-form {
  display: flex;
  flex-direction: column;
  gap: 20px;
  text-align: left;
}
.lf-field { display: flex; flex-direction: column; gap: 8px; }
.lf-field label {
  display: block;
  margin: 0;
  font-family: var(--font);
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
  color: var(--lg-fg);
}

/* Invoerveld = shadcn Input, alleen ruimer: 40px i.p.v. h-9 (36px), verder
   ongewijzigd — rounded-md (8px), 1px --input,
   px-3, 14px, shadow-xs. De iconen staan ín het veld, dus de padding zit op
   de wrapper en het echte <input> is zelf randloos. */
.lf-input {
  display: flex;
  align-items: center;
  gap: 8px;
  height: var(--lg-veld-h, 40px);      /* 40 i.p.v. shadcn h-9, naar de referentie */
  padding: 0 14px;
  background: var(--lg-input-bg);
  border: 1px solid var(--lg-input);
  border-radius: var(--lg-r-md);
  box-shadow: var(--lg-shadow-xs);
  transition: border-color .15s, box-shadow .15s;
}
.lf-input > svg { width: 16px; height: 16px; flex: none; color: var(--lg-muted-fg); }
.lf-input input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  outline: 0;
  font-family: var(--font);
  font-size: 14px;
  font-weight: 400;
  color: var(--lg-fg);
}
.lf-input input::placeholder { color: var(--lg-muted-fg); opacity: 1; }
.lf-input .reveal {
  width: 20px; height: 20px; flex: none;
  padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--lg-muted-fg);
  display: grid; place-items: center;
}
.lf-input .reveal svg { width: 16px; height: 16px; }
.lf-input .reveal:hover { color: var(--lg-fg); }

/* Inlogknop = shadcn Button (default): bg-primary, h-9, rounded-md, 14px/500.
   Geen opacity op :disabled — de knop staat tijdens "Bezig…"/"Welkom!" bewust
   disabled, en de motion-laag verderop regelt die twee standen zelf. */
.lf-submit {
  margin-top: 8px;
  width: 100%;
  height: var(--lg-veld-h, 40px);      /* even hoog als de velden erboven */
  padding: 8px 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 0;
  border-radius: var(--lg-r-md);
  background: var(--lg-primary);
  color: var(--lg-primary-fg);
  font-family: var(--font);
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  cursor: pointer;
  transition: background-color .15s;
}
.lf-submit:hover { background: color-mix(in srgb, var(--lg-primary) 90%, transparent); }
.lf-submit:disabled { cursor: default; }
.lf-submit svg { width: 16px; height: 16px; }

/* Voettekst. Staat niet op de login zelf maar wél op wachtwoord.html, dat
   dezelfde .login-card/.lf-*-vorm deelt. */
.login-foot {
  margin: 20px 0 0;
  text-align: center;
  font-family: var(--font);
  font-size: 12px;
  line-height: 1.45;
  color: var(--lg-muted-fg);
}

/* 2FA: shadcn-InputOTP-vorm zonder pakket (input-otp is React-only en dit
   scherm is vanilla). #lf-2fa blijft het ECHTE veld — autocomplete
   one-time-code, plakken, submit — transparant óver de zes cellen; app.js
   tekent de cijfers en de actieve ring. */
.lf-input.lf-otp {
  position: relative; height: auto; padding: 0;
  border: 0; background: none; box-shadow: none;
}
.otp-rij { display: flex; gap: 6px; width: 100%; }
.otp-rij i {
  flex: 1;
  height: var(--lg-veld-h, 40px);
  border: 1px solid var(--lg-input);
  border-radius: var(--lg-r-md);
  background: var(--lg-input-bg);
  box-shadow: var(--lg-shadow-xs);
  display: grid;
  place-items: center;
  font-style: normal;
  font-family: var(--font);
  font-size: 14px;
  font-weight: 500;
  color: var(--lg-fg);
  font-variant-numeric: tabular-nums;
  transition: border-color .15s, box-shadow .15s;
}
.otp-rij i.otp-actief {
  border-color: var(--lg-ring);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lg-ring) 50%, transparent);
}
.lf-input.lf-otp input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; font-size: 16px; /* 16px: geen iOS-zoom */
}

/* ── DE MELDING OP HET INLOGSCHERM = EEN ECHTE shadcn Alert ────────────────
   31 aug 2026 · Nick, na een verlopen sessie: "die alert tekst moet even anders
   vormgegeven worden misschien met een component van shadcn".

   WAT ER MIS WAS. Sinds 23 aug stond hier gecentreerde rode tekst met een los
   rond uitroepteken ervoor, zónder vak. Dat leest als een systeemfout — terwijl
   de zin die er het vaakst in staat juist zegt dát er niets stuk is. Rood +
   gecentreerd + geen kader is de vorm van een crash, niet van een mededeling.

   DE VORM. shadcn's Alert, precies: grid met een 16px-icoonkolom en een
   tekstkolom, 12px ertussen (has-[>svg]:gap-x-3), px-4 py-3, rounded-lg, 1px
   rand, tekst LINKS. Het icoon staat op de EERSTE tekstregel — 2px omlaag
   (shadcn's translate-y-0.5) omdat een 16px-icoon in een 20px-regel anders een
   haartje te hoog hangt. Dit is vanilla, dus de vorm is nagebouwd met de
   bestaande --lg-tokens in plaats van met het React-component; het icoon blijft
   een masker zodat het de tekstkleur volgt.

   HET TEKSTKNOOPPUNT IS ZELF EEN GRID-ITEM. app.js zet `err.textContent = …`;
   die losse tekstnode wordt door de grid-container in een anoniem grid-item
   gewikkeld en landt dus vanzelf in kolom 2, náást het ::before. Geen extra
   markup nodig — en :empty blijft werken, want een pseudo-element telt niet
   als kind. Wie hier ooit een <span> omheen zet, breekt de :empty-regel
   hieronder en krijgt een lege balk terug tussen wachtwoord en inlogknop.

   TWEE KLEUREN, ÉÉN VORM. Zie de --lg-destructive/--lg-warning-tokens boven:
   een verkeerd wachtwoord is destructive, een verlopen sessie is warning. */
#login-err.lf-error {
  display: grid;
  grid-template-columns: 16px 1fr;
  column-gap: 12px;
  align-items: start;
  text-align: left;
  padding: 12px 16px;
  border: 1px solid color-mix(in oklab, var(--lg-destructive) 30%, transparent);
  border-radius: var(--lg-r-lg);
  background: color-mix(in oklab, var(--lg-destructive) 9%, transparent);
  font-family: var(--font); font-size: 14px; line-height: 1.45;
  color: var(--lg-destructive-tekst);
}
#login-err.lf-error::before {
  content: ""; flex: none; width: 16px; height: 16px;
  /* Uitlijnen op de eerste regel, niet op het vak: 14px/1.45 = 20.3px regel,
     16px icoon → (20.3−16)/2 ≈ 2px. Precies shadcn's translate-y-0.5. */
  margin-top: 2px;
  align-self: start;
  background: currentColor;
  -webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="10"/><path d="M12 8v4M12 16h.01"/></svg>') center/contain no-repeat;
  mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="10"/><path d="M12 8v4M12 16h.01"/></svg>') center/contain no-repeat;
}

/* ── DE VERLOPEN SESSIE IS GEEN FOUT ───────────────────────────────────────
   app.js zet `data-sessie-verlopen="1"` op dit vak vóórdat het de zin erin
   schrijft (r3756). Dát is de haak, en niet de tekst: de zin mag veranderen,
   het attribuut niet.

   WAAROM WARNING EN NIET DESTRUCTIVE. Destructive is de kleur van "er is iets
   misgegaan". De zin zegt letterlijk het omgekeerde — er is niets weg, je
   gegevens en meldingen staan er nog — en vraagt alleen om één handeling:
   opnieuw inloggen. Rood is dan geen accent maar een tegenspraak, en precies
   die tegenspraak las Nick op 28 aug twee keer als storing. Warning zegt "let
   op, doe iets" zonder "er is iets stuk". Een neutrale Alert (default) zou het
   ándere uiterste zijn: die vraagt niet om de handeling die wél nodig is.

   Het icoon wisselt mee: bij een fout een uitroepteken in een cirkel, hier een
   klok — het probleem is verstreken tijd, niet een fout. */
#login-err.lf-error[data-sessie-verlopen] {
  border-color: color-mix(in oklab, var(--lg-warning) 32%, transparent);
  background: color-mix(in oklab, var(--lg-warning) 10%, transparent);
  color: var(--lg-warning-tekst);
}
#login-err.lf-error[data-sessie-verlopen]::before {
  -webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>') center/contain no-repeat;
  mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>') center/contain no-repeat;
}
html[data-theme="grey"] #login-err.lf-error[data-sessie-verlopen] {
  background: color-mix(in oklab, var(--lg-warning) 16%, transparent);
}
html[data-theme="grey"] #login-err.lf-error {
  background: color-mix(in oklab, var(--lg-destructive) 15%, transparent);
}
/* Leeg foutvak = geen vak. Zonder dit reserveert het een zichtbare lege balk
   tussen wachtwoord en inlogknop. :empty werkt hier omdat de div in
   index.html letterlijk leeg is; JS vult textContent en dan verschijnt hij. */
.login-err:empty, .lf-error:empty { display: none !important; min-height: 0 !important; padding: 0 !important; margin: 0 !important; border: 0 !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   INLOGSCHERM — DE AFWERKINGSLAAG  ·  "licht boven water"
   Nick, 23 aug 2026: "maak hem oogstrelend prachtig".

   HET IDEE. De vorm ligt vast (zijn referentie: merk linksboven, kop
   gecentreerd, labels boven de velden, geen kaart). Schoonheid mag die vorm
   dus niet overrulen — ze moet eronder vandaan komen. Daarom is hier niet het
   FORMULIER versierd maar de RUIMTE waarin het staat: een zachte lichtval,
   een horizon, en korrel. Iselmar ligt aan het IJsselmeer; dit is dat licht,
   niet een plaatje ervan.

   WAAROM DIT NODIG IS EN GEEN SMAAK. Toen de kaart wegging (zie .login-card
   hierboven) verloren de velden hun ondergrond: een transparant veld op een
   vlakke witte pagina is alleen nog een dun lijntje. Deze laag geeft ze een
   vlak om op te liggen. Dat is de functionele helft; de rest is afwerking.

   ALLES SCHAALT MEE MET DE TOKENS. Geen enkele kleur hieronder is een losse
   hex: ze komen uit --lg-* en kantelen dus mee met het donkere thema, dat
   verderop zijn eigen waarden zet. Eén uitzondering, expliciet benoemd: de
   korrellaag is een grijswaarde-ruis en heeft in beide thema's dezelfde bron,
   alleen een andere dekking.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1 · de ondergrond ─────────────────────────────────────────────────────
   ÉÉN VLAKKE KLEUR (Nick, 23 aug 2026: "cleaner als de achtergrond gewoon
   1 kleur is, niet?" — ja). Hier stond tot vandaag een wassing met een gloed,
   twee deiningen en een korrellaag eroverheen. Dat is er allemaal uit.

   WAAROM DE KLEUR TOCH NIET ZUIVER WIT IS. Dit is geen restje sfeer maar het
   enige wat de velden nog overeind houdt. De kaart is weg (zie .login-card),
   dus een veld heeft geen omhullende ondergrond meer om zich van af te
   tekenen. Is de pagina zuiver wit én het veld zuiver wit, dan blijft van dat
   veld alleen zijn randlijn over. Drie procent staalblauw door het wit is
   genoeg om ze weer als vlak te laten lezen, en te weinig om als kleur op te
   vallen. Nog steeds één vlakke kleur: geen verloop, geen tweede laag.

   Bewaakt door scripts/verify-login-ontwerp.cjs: die meet dat er GEEN
   background-image staat (dus dat er geen verloop is teruggeslopen) en dat de
   veldvulling verschilt van de ondergrond. */
.login-shell {
  background: color-mix(in srgb, var(--lg-ring) 3%, var(--lg-bg));
}
/* Donker thema: daar is --lg-bg al donkerder dan de veldvulling
   (oklch(100% 0 0 / .05), sectie 2), dus daar hoeft niets bijgemengd. */
html[data-theme="grey"] .login-shell {
  background: var(--lg-bg);
}

/* De korrellaag is weg. Die had precies één taak — strepen in de
   kleurovergangen breken — en die overgangen bestaan niet meer. */
.login-shell::before { content: none; }

/* De kolom houdt zijn eigen laag, zodat een latere achtergrondlaag hem niet
   kan overdekken. LET OP voor wie hier iets bijzet: `.login-brand` mag GEEN
   `position` meekrijgen — dat element staat absoluut linksboven, en een
   `position: relative` draait dat stilletjes terug. Gemeten 23 aug 2026: toen
   `.login-brand` en `.login-main` samen `position: relative` kregen, landde
   het logo op y=485 in plaats van y=28, precies verticaal gecentreerd. */
.login-main { position: relative; z-index: 1; }

/* ── 2 · de velden krijgen een vlak ─────────────────────────────────────────
   Nu de kaart weg is, dragen de velden zelf de "papier"-rol. Wit (in het
   donkere thema: een lichte opklaring), een haarlijn, en een binnenrand van
   één pixel licht bovenaan — dat laatste is wat een veld laat lezen als een
   uitsparing in plaats van een rechthoekje. */
.login-shell {
  --lg-input-bg: var(--lg-card);
}
html[data-theme="grey"] .login-shell {
  --lg-input-bg: oklch(100% 0 0 / .05);
}
.lf-input:not(.lf-otp),
.otp-rij i {
  box-shadow:
    inset 0 1px 0 0 color-mix(in srgb, white 70%, transparent),
    0 1px 2px 0 rgb(0 0 0 / .045);
}
html[data-theme="grey"] .lf-input:not(.lf-otp),
html[data-theme="grey"] .otp-rij i {
  box-shadow:
    inset 0 1px 0 0 color-mix(in srgb, white 8%, transparent),
    0 1px 2px 0 rgb(0 0 0 / .25);
}
/* Focus tilt het veld een haar op. Twee pixels; genoeg om te voelen dat je
   ergens bént, te weinig om als beweging op te vallen. De ring zelf staat
   verderop (r3441) en blijft ongemoeid — die is al de --ring van het eiland. */
.lf-input:not(.lf-otp) { transition: border-color .15s, box-shadow .15s, transform .15s; }
.lf-input:not(.lf-otp):focus-within { transform: translateY(-1px); }

/* ── 3 · de knop ────────────────────────────────────────────────────────────
   Navy met een lichtval van boven en een schaduw die de knopkleur draagt in
   plaats van neutraal grijs — een grijze schaduw onder een gekleurde knop is
   waar "bijna goed" meestal vandaan komt. Indrukken zakt hem echt in. */
.lf-submit {
  background:
    linear-gradient(180deg,
      color-mix(in srgb, white 9%, var(--lg-primary)) 0%,
      var(--lg-primary) 100%);
  box-shadow:
    0 1px 2px 0 color-mix(in srgb, var(--lg-primary) 30%, transparent),
    0 6px 16px -6px color-mix(in srgb, var(--lg-primary) 55%, transparent);
  transition: background-color .15s, box-shadow .2s, transform .12s;
}
/* De hover-regel hierboven (r2980) zet een VLAKKE kleur; zonder de gradiënt
   hier te herhalen valt de lichtval bij hover weg. Twee regels die dezelfde
   knop beschilderen — de latere moet het hele verhaal vertellen. */
.lf-submit:hover {
  background:
    linear-gradient(180deg,
      color-mix(in srgb, white 14%, var(--lg-primary)) 0%,
      color-mix(in srgb, white 4%, var(--lg-primary)) 100%);
  box-shadow:
    0 1px 2px 0 color-mix(in srgb, var(--lg-primary) 34%, transparent),
    0 10px 22px -8px color-mix(in srgb, var(--lg-primary) 62%, transparent);
}
.lf-submit:active:not(:disabled) {
  transform: translateY(1px);
  box-shadow: 0 1px 2px 0 color-mix(in srgb, var(--lg-primary) 30%, transparent);
}

/* ── 4 · typografie ─────────────────────────────────────────────────────────
   De kop mag groter en strakker staan dan een kaartkop: hij heeft nu de hele
   pagina om zich heen. Optische correctie: bij deze grootte leest -.025em
   rustiger dan -.01em, omdat Inter bij 32px vanzelf al ruimer oogt. */
.login-card h1 { font-size: 32px; letter-spacing: -.025em; }
.login-card .sub { font-size: 15px; max-width: 34ch; margin-inline: auto; }

/* ── 5 · binnenkomst ────────────────────────────────────────────────────────
   Eén beweging, in volgorde van lezen: merk, kop, subtitel, velden, knop.
   Elk deel komt acht pixels omhoog. De trap is 55ms — kort genoeg om als één
   geheel te lezen, lang genoeg om richting te geven. `both` houdt de
   begintoestand vast, anders flitst alles eerst zichtbaar. */
@keyframes lgRijs { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

.login-brand,
.login-card h1,
.login-card .sub,
.login-form .lf-field,
.login-form .lf-submit {
  animation: lgRijs .5s cubic-bezier(.2,.7,.2,1) both;
}
.login-brand                    { animation-delay: .02s; }
.login-card h1                  { animation-delay: .09s; }
.login-card .sub                { animation-delay: .14s; }
.login-form .lf-field:nth-of-type(1) { animation-delay: .19s; }
.login-form .lf-field:nth-of-type(2) { animation-delay: .24s; }
.login-form .lf-submit          { animation-delay: .30s; }

/* De kaart zelf beweegt niet meer — anders schuift alles twee keer. */
.login-card { animation: none; }

/* Het 2FA-veld valt bewust buiten de trap: dat verschijnt later, op zijn eigen
   slide-down (#lf-2fa-field.is-open), en mag niet óók nog opkomen. */
#lf-2fa-field { animation: none !important; }

/* Wie beweging heeft uitgezet, krijgt het eindbeeld en verder niets. */
@media (prefers-reduced-motion: reduce) {
  .login-brand,
  .login-card h1,
  .login-card .sub,
  .login-form .lf-field,
  .login-form .lf-submit { animation: none !important; }
  .lf-input:not(.lf-otp):focus-within,
  .lf-submit:active:not(:disabled) { transform: none !important; }
}

/* ===================== VERHUUR per type (Fase 1 handoff) ===================== */
.rental { display: flex; flex-direction: column; }
.rental-bar { display: flex; align-items: center; gap: 14px; padding: 12px 18px; border-bottom: 1px solid var(--border); background: var(--rail); flex-wrap: wrap; }
.rental-summary { font-size: 13px; color: var(--text-muted); display: flex; align-items: center; gap: 6px; }
.rental-summary b { color: var(--text); font-weight: 700; }
.rent-meter { flex: 1; height: 8px; border-radius: 999px; background: var(--border); overflow: hidden; max-width: 320px; display: flex; }
.rent-meter i { display: block; height: 100%; background: var(--accent); }
.rental-viewtog { margin-left: auto; display: inline-flex; gap: 4px; background: var(--surface); border-radius: 10px; padding: 4px; }
.rental-viewtog button { padding: 7px 14px; border-radius: 7px; border: none; background: none; color: var(--text-muted); font-size: 13px; font-weight: 600; cursor: pointer; }
.rental-viewtog button.on { background: var(--panel); color: var(--text); box-shadow: var(--shadow); }
.btn-rent { display: inline-flex; align-items: center; gap: 6px; padding: 8px 13px; border-radius: 10px; border: 1px solid var(--accent); background: var(--accent); color: #fff; font-size: 13px; font-weight: 600; white-space: nowrap; cursor: pointer; }
[data-theme="grey"] .btn-rent { color: #0e0f0d; }
.btn-rent svg { width: 14px; height: 14px; }
.btn-rent:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn-rent[disabled] { background: var(--surface); border-color: var(--border); color: var(--text-faint); cursor: not-allowed; }
.rr-act { color: var(--text-faint); display: grid; place-items: center; width: 30px; height: 30px; border-radius: 8px; border: none; background: none; cursor: pointer; flex: none; }
.rr-act:hover { background: var(--hover); color: var(--text); }
.rr-act svg { width: 17px; height: 17px; }

/* Verhuur in dezelfde tokens als de rest (vkaart-familie): kop (naam) ·
   teller · balk · regels · voet. Lijst = één kolom (breed), Kaarten = raster —
   zelfde regel-anatomie, andere dichtheid. De optelling (vrij/verhuurd) staat
   al in de rental-bar en de zijbalk; de kop hier is alleen nog een naam. */
.nv-vlijst { display: flex; flex-direction: column; gap: 10px; padding: 12px 14px; }
.nv-vgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 10px; padding: 12px 14px; }
.nv-vkaart { border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px;
  background: var(--panel); display: flex; flex-direction: column; gap: 8px; }
.nv-vkop { display: flex; align-items: baseline; gap: 8px; }
.nv-vkop b { font-size: calc(11px * var(--type-scale, 1.2)); font-weight: 650; color: var(--text); }
/* Eén teller per type, pal boven de balk, zonder bijsluitertekst. */
.nv-vteller { margin: -4px 0 -2px; font-size: calc(10px * var(--type-scale, 1.2)); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.nv-vbar { height: 6px; border-radius: 999px; background: var(--surface); overflow: hidden; border: 1px solid var(--border); }
.nv-vbar i { display: block; height: 100%; background: var(--chip, var(--accent)); }
.nv-vvoet { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
.nv-vrij-rij { font-size: calc(9.5px * var(--type-scale, 1.2)); color: var(--text-muted);
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.nv-vrij-rij .wie { width: 22px; height: 22px; border-radius: 6px; background: var(--surface);
  display: grid; place-items: center; font-size: 9.5px; font-weight: 700; color: var(--text-muted); flex: none; }
.nv-vrij-tekst { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nv-vrij-tekst b { color: var(--text); font-weight: 600; }
.nv-vstatus { margin-left: auto; white-space: nowrap; font-weight: 600; }
.nv-vstatus.st-betaald { color: var(--success); }
.nv-vstatus.st-open { color: var(--warning); }
.nv-vstatus.st-import { color: var(--warning); }

/* ══ Dagweergave: één tijdlijn-grammatica (redesign, voorstel-activiteiten-dag) ══
   Alle tijdslot-activiteiten als rijen op één gedeelde as. Eén chip-taal
   (nv-chip), rustige vrij-knoppen (nv-vrij), stil verleden (nv-af, geen
   arcering), een rustig statusvlak voor blokkades (nv-blok), één nu-lijn (nv-nu).
   De klassen tl-block / tl-slot / is-vrij blijven op de elementen staan als
   gedrags- en testhaken (click/drag-binders, verify-scripts); hun oude
   visuele regels zijn vervangen door deze laag. */

/* Thema-tokens van de nieuwe taal (licht + grijs). */
html[data-theme="light"] {
  --chip: #2F4157; --chip-tekst: #fff;
  --af: rgba(28,29,26,.045);
  --blok-lijn: rgba(28,29,26,.10);
}
html[data-theme="grey"] {
  --chip: #3A5068; --chip-tekst: #f2f4f6;
  --af: rgba(255,255,255,.05);
  --blok-lijn: rgba(255,255,255,.11);
}
html { --lblw: 138px; }
@media (max-width: 760px) { html { --lblw: 104px; } }

/* Bij een verborgen module-nav (rol met één module) zit .app-main als
   niet-gestrekt flex-item in een kolom en meet hij zich aan zijn inhoud
   (shrink-to-fit tot de oude cap van 1100px). Met het brede plan erin liep
   de hele pagina dan horizontaal uit; de cap mag nooit boven de beschikbare
   breedte uitkomen — het plan scrolt in zijn eigen container. */
body.module-nav-leeg .app-main { max-width: min(1100px, 100%); }

.nv-kader { position: relative; }
.nv-kader.kan-rechts::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 44px;
  background: linear-gradient(to right, transparent, var(--panel) 85%);
  pointer-events: none; z-index: 9;
}
.nv-scroll { overflow-x: auto; background: var(--panel); -webkit-overflow-scrolling: touch; }
.nv-plan { position: relative; min-width: 100%; }
/* Secties in het gedeelde plan: geen eigen kaart (het plan is de kaart) en
   géén overflow:hidden of entree-transform — die breken position:sticky. */
.nv-plan .act-section {
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  margin: 0 !important;
  overflow: visible;
  animation: none;
}
/* Sectie-kop in het plan: sticky links, compacte regel met status ernaast. */
.nv-plan .act-section-head {
  position: sticky; left: 0; z-index: 7;
  display: inline-flex !important;
  width: max-content;
  max-width: var(--nv-klem, calc(100vw - 56px));
  align-items: center !important;
  justify-content: flex-start !important;
  flex-wrap: wrap;
  gap: 2px 9px;
  padding: 12px 16px 4px 14px !important;
  background: var(--panel);
  border-bottom: 0 !important;
  border-radius: 0 10px 10px 0;
}
.nv-st { font-size: calc(10.5px * var(--type-scale, 1.2)); color: var(--text-faint); }
.nv-st b { color: var(--text-muted); font-weight: 600; }

/* As-regel bovenaan het plan. */
.nv-axisrow { display: flex; border-bottom: 1px solid var(--border); }
.nv-hoek { width: var(--lblw); flex: none; position: sticky; left: 0; z-index: 8;
  background: var(--panel); border-right: 1px solid var(--border); }
.nv-axistrack { position: relative; flex: none; height: 30px; }
.nv-axistrack span { position: absolute; top: 7px; font-size: 11px; color: var(--text-faint);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.nv-axistrack i { position: absolute; bottom: 0; width: 1px; height: 5px; background: var(--border-strong); }

/* Baan-rijen op de gedeelde as. */
.nv-row { display: flex; align-items: stretch; }
.nv-rname { width: var(--lblw); flex: none; position: sticky; left: 0; z-index: 6;
  background: var(--panel); border-right: 1px solid var(--border);
  display: flex; flex-direction: column; justify-content: center;
  font-size: calc(10px * var(--type-scale, 1.2)); font-weight: 550; color: var(--text-muted); padding: 0 12px; }
.nv-rname small { display: block; font-weight: 400; font-size: calc(8.5px * var(--type-scale, 1.2)); color: var(--text-faint); line-height: 1.3; }
.nv-rtrack { position: relative; flex: none; border-top: 1px solid var(--border); }
.nv-row:last-of-type .nv-rtrack { border-bottom: 1px solid var(--border); }
.nv-row:last-of-type .nv-rname { border-bottom: 1px solid var(--border); }
.nv-venster { position: absolute; top: 0; bottom: 0; }
.nv-uurlijn { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--border); opacity: .6; }
/* Verstreken: één stil, vlak, leeg gebied — geen patroon, geen tekst. */
.nv-af { position: absolute; top: 0; bottom: 0; left: 0; background: var(--af); z-index: 1; }
/* Baan zonder tijden binnen een verder gevulde activiteit. */
.nv-rleeg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  font-size: calc(9px * var(--type-scale, 1.2)); color: var(--text-faint); white-space: nowrap; }

/* De ene boeking-chip (naam · Np). */
.nv-chip { position: absolute; top: 6px; bottom: 6px; z-index: 3;
  display: flex; align-items: center; gap: 6px;
  background: var(--chip); color: var(--chip-tekst);
  border: 0; border-radius: 8px; padding: 0 10px;
  font-family: var(--font); font-size: calc(10px * var(--type-scale, 1.2)); font-weight: 600;
  cursor: pointer; overflow: hidden; white-space: nowrap; text-align: left; min-width: 0; }
.nv-chip b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.nv-chip span { font-weight: 500; opacity: .75; font-variant-numeric: tabular-nums; flex: none; }
.nv-chip:hover { filter: brightness(1.15); }
.nv-chip.af { opacity: .5; }
.nv-chip.af:hover { opacity: .85; filter: none; }
/* Gast is nu online aan het boeken: pulserende lichte variant van dezelfde chip. */
.nv-chip.hold { background: var(--panel); color: var(--text-muted);
  border: 1.5px dashed var(--chip); cursor: help; animation: nv-puls 2s ease-in-out infinite; }
[data-theme="grey"] .nv-chip.hold { border-color: var(--accent); }
@keyframes nv-puls { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .nv-chip.hold { animation: none; opacity: .8; } }
/* Startraster-vakje (adventure golf): compacter zodat naam · Np past. */
.nv-chip.cel { padding: 0 6px; gap: 4px; font-size: calc(9px * var(--type-scale, 1.2)); }
.nv-chip.cel b { flex: 1 1 auto; min-width: 0; text-align: left; }

/* Vrij slot: een stil tijdstipje, geen doos (klus 8, punt 6).
   Gemeten aanleiding: op een lege dag staan er 228 vrij-knoppen tegenover 0
   boekingschips — het scherm besteedt bijna al zijn inkt aan lege tijd. Het
   externe voorstel wilde de knoppen wéghalen ("klik in een lege ruimte om te
   boeken"); dat kan niet, want een lege ruimte heeft geen starttijd (golf start
   elk kwartier, bowling elk half uur, squash elke 45 minuten). Dus: de knop
   blijft mét zijn tijdlabel, alleen de doos eromheen gaat weg. Bij hover én
   focus komt het kadertje terug, zodat het klikdoel even groot en even duidelijk
   blijft. Zelfde functie, veel minder inkt. */
.nv-vrij { position: absolute; top: 8px; bottom: 8px; z-index: 2;
  border: 1px solid transparent; background: transparent; border-radius: 8px;
  color: var(--text-faint); font-family: var(--font-mono); font-size: calc(9px * var(--type-scale, 1.2));
  font-variant-numeric: tabular-nums; cursor: pointer;
  display: flex; align-items: center; justify-content: center; padding: 0;
  transition: border-color .12s, background .12s, color .12s; }
.nv-vrij:hover, .nv-vrij:focus-visible { border-color: var(--accent); color: var(--text); background: var(--accent-soft); }
.nv-vrij.is-selected { border-color: var(--accent); background: var(--accent-soft); color: var(--text); font-weight: 650; }
/* Walk-in op een verstreken tijd van vandaag: zichtbaar maar stil — de
   functie blijft (registreren achteraf), de vorm is een gedempte knop.
   Dimmen mag, doodverklaren niet: walk-ins achteraf boeken is dagelijks werk. */
.nv-vrij.is-verleden { opacity: .5; }
.nv-vrij.is-verleden:hover, .nv-vrij.is-verleden:focus-visible { opacity: 1; background: var(--panel); }

/* Geblokkeerd: een rustig semantisch statusvlak in plaats van gevarentape.
   Het label is horizontaal sticky binnen de tijdlijn. Een lange blokkade kan
   dus vóór de zichtbare uren beginnen zonder dat reden en tijd uit beeld
   verdwijnen — precies wat bij Bowling Baan 4 gebeurde. */
.nv-blok { position: absolute; top: 8px; bottom: 8px; z-index: 2;
  border: 1px solid var(--warning); border-radius: 8px;
  border-color: color-mix(in srgb, var(--warning) 30%, var(--border));
  background: var(--warning-soft);
  background: color-mix(in srgb, var(--warning-soft) 72%, var(--panel));
  color: var(--warning); font-size: calc(9px * var(--type-scale, 1.2));
  display: block; padding: 0; overflow: clip; white-space: nowrap;
  cursor: help; container-type: inline-size; }
/* .nv-rname is content-box: --lblw + 24px horizontale padding + 1px rand.
   Daarna blijft 8px ademruimte over voor het statuslabel. */
.nv-blok-label { position: sticky; left: calc(var(--lblw) + 33px); width: max-content;
  max-width: calc(100% - 16px); height: 100%; padding: 0 2px;
  display: flex; align-items: center; gap: 6px; overflow: hidden; }
.nv-blok-label svg { width: 12px; height: 12px; flex: none; opacity: .9; }
.nv-blok-label b { flex: none; font-weight: 650; color: var(--warning); }
.nv-blok-reden { min-width: 0; overflow: hidden; text-overflow: ellipsis;
  color: var(--text); font-weight: 550; }
.nv-blok-reden::before, .nv-blok-tijd::before { content: '·';
  color: var(--warning); margin-right: 6px; opacity: .75; }
.nv-blok-tijd { flex: none; color: var(--text-muted); font-family: var(--font-mono);
  font-variant-numeric: tabular-nums; }
@container (max-width: 220px) { .nv-blok-tijd { display: none; } }
@container (max-width: 115px) { .nv-blok-label b { display: none; } }
@container (max-width: 58px) { .nv-blok-reden { display: none; } }
/* Volgeboekt zonder zichtbare boeking (databron elders): stil maar aanwezig. */
.nv-vol { position: absolute; top: 8px; bottom: 8px; z-index: 1;
  border-radius: 8px; background: var(--surface); opacity: .5; }

/* Groepskoppellijn (voorstel scherm 4): een groep is zichtbaar familie via een
   subtiele verticale lijn tussen de chips van aangrenzende banen — bewust
   GEEN accentring om de chips zelf. Hover/focus op een groepslid zet 'm aan
   (dikker, voluit) + een klein tipje met het groepstotaal (.nv-gtip). */
.nv-groeplijn { position: absolute; width: 2px; margin-left: -1px; border-radius: 2px;
  background: var(--chip); opacity: .45; z-index: 2; pointer-events: none;
  transition: opacity .12s, width .12s; }
.nv-groeplijn.fam { opacity: 1; width: 3px; margin-left: -1.5px; }
@media (prefers-reduced-motion: reduce) { .nv-groeplijn { transition: none; } }
.nv-gtip { position: fixed; z-index: 75; background: var(--text); color: var(--bg);
  font-size: 11px; font-weight: 600; border-radius: 7px; padding: 4px 9px;
  pointer-events: none; white-space: nowrap; box-shadow: 0 6px 20px rgba(0, 0, 0, .18); }
.nv-gtip[hidden] { display: none; }

/* De nu-lijn: tijdvlagje op de as (.nv-nu, anker zonder staart) + per sectie
   een lijnsegment (.nv-nu-sec) dat alleen het track-gebied bestrijkt — de
   lijn loopt dus nooit door sectiekoppen of samenvattingsregels heen. */
.nv-nu { position: absolute; top: 30px; height: 0; width: 2px; margin-left: -1px;
  z-index: 2; pointer-events: none; }
.nv-nu em { position: absolute; top: -24px; left: 50%; transform: translateX(-50%);
  font-style: normal; font-size: 10px; font-weight: 700; font-family: var(--font-mono);
  color: #fff; background: var(--danger); border-radius: 5px; padding: 1px 5px; opacity: 1; }
.nv-rows { position: relative; }
.nv-nu-sec { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px;
  background: var(--danger); opacity: .55; z-index: 2; pointer-events: none; }

/* Ingeklapte activiteit (leeg of voorbij): één stille regel. */
.nv-dicht { position: sticky; left: 0; z-index: 5; width: max-content;
  max-width: var(--nv-klem, calc(100vw - 56px));
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px;
  padding: 2px 16px 10px 14px; font-size: calc(10px * var(--type-scale, 1.2));
  color: var(--text-faint); background: var(--panel); border-radius: 0 10px 10px 0; }
/* Toon/Verberg tijdlijn: één toggle-knop met draaiende chevron. Ingeklapt
   staat 'ie in de samenvattingsregel, uitgeklapt in de sectiekop. */
.open-tl { display: inline-flex; align-items: center; gap: 5px;
  border: 0; background: none; padding: 3px 8px 3px 6px; border-radius: 100px;
  font: 500 calc(9.5px * var(--type-scale, 1.2)) var(--font); color: var(--text-muted);
  cursor: pointer; }
.open-tl:hover { color: var(--text); background: var(--hover); }
.open-tl svg { width: 12px; height: 12px; flex: none; transition: transform .16s ease; }
.open-tl.is-open svg { transform: rotate(-180deg); }
@media (prefers-reduced-motion: reduce) { .open-tl svg { transition: none; } }
.act-section-head .open-tl { margin-left: 2px; }
/* "Geen tijden"/"laden mislukt" binnen het plan: sticky zodat het in beeld blijft. */
.nv-vast { position: sticky; left: 0; z-index: 5; box-sizing: border-box;
  width: max-content; max-width: var(--nv-klem, calc(100vw - 56px)); }
.nv-vast .banen-empty { margin: 4px 14px 12px; }

/* ── Bowling drag&drop op de nieuwe chips/knoppen ─────────────────────────
   .is-sleepbaar  = chip is draggable (cursor + hint)
   .is-dragging   = chip wordt op dit moment versleept (halftransparant)
   .is-droptarget = vrij slot is een geldig drop-doel (streepjesrand)
   .is-dragover   = vrij slot zit onder de cursor tijdens slepen (highlight) */
.nv-chip.is-sleepbaar { cursor: grab; }
.nv-chip.is-sleepbaar:active { cursor: grabbing; }
.nv-chip.is-dragging { opacity: .35; }
.nv-vrij.is-droptarget { border-style: dashed; border-color: var(--accent); opacity: 1; }
.nv-vrij.is-dragover { background: var(--accent-soft); border-color: var(--accent);
  border-style: solid; color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }

/* ── Blokkade-popups (keuze + periode/verhuur) ─────────────────────────── */
.modal-sub { margin: -4px 0 14px; color: var(--text-muted); font-size: 14px; }
.blok-keuze-grid { display: grid; gap: 10px; }
.blok-keuze-opt { display: flex; flex-direction: column; gap: 3px; text-align: left;
  padding: 14px 16px; border: 1px solid var(--border-strong); border-radius: 12px;
  background: var(--surface); color: var(--text); cursor: pointer; transition: border-color .12s, background .12s; }
.blok-keuze-opt:hover { border-color: var(--accent); background: var(--hover); }
.blok-keuze-opt strong { font-size: 15px; }
.blok-keuze-opt span { font-size: 13px; color: var(--text-muted); }
.bp-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.bp-note { margin: 2px 0 6px; font-size: 12.5px; color: var(--text-muted); line-height: 1.4; }
/* Uniforme veldstijl voor alle inputs/selects in de blokkade-popups
   (date, time, number, select) — gelijk aan .field > input, zonder groen accent.
   appearance:none is cruciaal: anders rendert Safari/iPad de native date/time/
   number controls met OS-chrome en lijken ze ongestyled. */
.bp-field { -webkit-appearance: none !important; appearance: none !important;
  box-sizing: border-box; width: 100%; min-height: 42px;
  background: var(--surface) !important; border: 1px solid var(--border-strong) !important;
  border-radius: 6px !important; color: var(--text) !important; font-family: var(--font) !important;
  font-size: calc(13px * var(--type-scale, 1.2)) !important; padding: 10px 12px !important;
  accent-color: var(--text-muted); }
.bp-field:focus { border-color: var(--accent) !important; box-shadow: 0 0 0 2px var(--accent-soft) !important; outline: none !important; }
/* Native date/time popover-icoon themen (donker thema → wit icoon). */
.bp-field::-webkit-calendar-picker-indicator { opacity: .65; cursor: pointer; }
[data-theme="grey"] .bp-field::-webkit-calendar-picker-indicator { filter: invert(1); opacity: .8; }
.bp-field::-webkit-datetime-edit { color: var(--text); }
.bp-field::-webkit-inner-spin-button, .bp-field::-webkit-outer-spin-button { opacity: 1; height: 22px; }
/* Select-pijl terugzetten (appearance:none verbergt 'm) met een themable chevron. */
select.bp-field { padding-right: 34px !important;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>") !important;
  background-repeat: no-repeat !important; background-position: right 12px center !important; }
.bp-flabel { display: flex; flex-direction: column; gap: 6px; }
.bp-flabel > span { font-size: calc(11px * var(--type-scale, 1.2)); font-weight: 500; color: var(--text-muted); }
/* Van/Tot blokken */
.bp-vantot { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 4px; }
.bp-vt-col { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--panel); }
.bp-vt-head { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.bp-cal, .bp-cal .iselcal-root { width: 100%; display: block; }
.bp-cal .iselcal-trigger { width: 100% !important; min-height: 42px; box-sizing: border-box; }
/* Selectie: aantal per type / banen-chips */
.bp-section { display: flex; flex-direction: column; gap: 8px; margin-bottom: 4px; }
.bp-section-head { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.bp-unit-row { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); }
.bp-unit-name { font-size: 14px; }
.bp-unit-name small { color: var(--text-faint); font-size: 12px; }
.bp-unit-row .bp-field { width: 84px; }
/* Banen kiezen: gebrande toggle-knoppen (geen ruwe checkbox / groen vierkant). */
.bp-baan-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.bp-baan-chip { display: inline-flex; align-items: center; gap: 7px; padding: 8px 14px;
  border: 1px solid var(--border-strong); border-radius: 8px; background: var(--surface);
  color: var(--text-muted); font-size: 13.5px; font-weight: 500; cursor: pointer;
  user-select: none; transition: border-color .12s, background .12s, color .12s; }
.bp-baan-chip:hover { border-color: var(--accent); color: var(--text); }
.bp-baan-chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.bp-baan-chip:has(input:checked) { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
[data-theme="grey"] .bp-baan-chip:has(input:checked) { color: var(--text); }
.bp-baan-chip::before { content: ""; width: 15px; height: 15px; border-radius: 4px;
  border: 1.5px solid var(--border-strong); flex: none; transition: background .12s, border-color .12s; }
.bp-baan-chip:has(input:checked)::before { background: var(--accent); border-color: var(--accent); }

/* ── Verhuur-blokkade mini-banners ─────────────────────────────────────── */
.rent-blok-list { display: flex; flex-direction: column; gap: 8px; padding: 12px 18px 0; }
.rent-blok-banner { display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; border-radius: 10px; line-height: 1.35;
  background: var(--warning-soft, rgba(217,119,6,.12)); border: 1px solid var(--warning, #c2620d); }
.rent-blok-banner .rbb-ic { display: flex; flex: none; color: var(--warning, #c2620d); }
.rent-blok-banner .rbb-txt { flex: 1; min-width: 0; color: var(--text); font-size: 13.5px; }
.rent-blok-banner .rbb-txt b { color: var(--text); }
.rent-blok-banner .rbb-del { flex: none; padding: 6px 12px; border-radius: 7px;
  background: var(--panel); border: 1px solid var(--border-strong); color: var(--text-muted);
  font-size: 12.5px; cursor: pointer; transition: border-color .12s, color .12s; }
.rent-blok-banner .rbb-del:hover { border-color: var(--danger, #c0453b); color: var(--danger, #c0453b); }

/* ── Geen blauwe focus-box op invoervelden (overal) ─────────────────────────
   De gebruiker wil geen blauw vierkant/gloed bij het aanklikken van een veld.
   We tonen focus subtiel via een iets donkerdere grijze rand — geen accent,
   geen box-shadow-gloed, geen extra outline-rechthoek. */
input:focus, input:focus-visible,
textarea:focus, textarea:focus-visible,
select:focus, select:focus-visible,
.lf-input input:focus, .bp-field:focus {
  outline: none !important;
  box-shadow: none !important;
}
.lf-input:not(.lf-otp):focus-within {
  /* shadcn-focus van het eiland: focus-visible:border-ring +
     focus-visible:ring-ring/50 focus-visible:ring-[3px]. !important omdat
     oudere ongelaagde regels hier anders overheen komen. */
  border-color: var(--lg-ring) !important;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lg-ring) 50%, transparent) !important;
}
.field > input:focus, .field > select:focus, .field > textarea:focus,
.bp-field:focus, .ml-input:focus, .ml-textarea:focus, .ak-input:focus {
  border-color: var(--border-strong) !important;
  box-shadow: none !important;
}

/* ── Profiel-drawer (wachtwoord + 2FA) ─────────────────────────────────── */
.prof-acc { display: flex; align-items: center; gap: 12px; margin: 4px 0 18px; }
.prof-avatar { width: 46px; height: 46px; border-radius: 50%; background: var(--accent-soft);
  color: var(--accent); display: grid; place-items: center; font-weight: 700; font-size: 16px; flex: none; }
.prof-naam { font-size: 16px; font-weight: 600; color: var(--text); }
.prof-meta { font-size: 13px; color: var(--text-muted); margin-top: 2px; }
.prof-sec { border-top: 1px solid var(--border); padding-top: 16px; margin-top: 16px; }
.prof-sec-title { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-muted); margin: 0 0 12px; }
.prof-hint { font-size: 13px; color: var(--text-muted); line-height: 1.45; margin: 0 0 12px; }
.prof-badge-on { display: inline-block; font-size: 12.5px; font-weight: 600; color: var(--success);
  background: var(--success-soft); padding: 3px 10px; border-radius: 999px; }
.prof-qr { display: grid; place-items: center; padding: 14px; background: #fff; border: 1px solid var(--border);
  border-radius: 12px; margin: 12px auto; width: max-content; }
.prof-secret { font-size: 12.5px; color: var(--text-muted); margin: 0 0 12px; }
.prof-secret code { background: var(--surface); border: 1px solid var(--border); border-radius: 5px;
  padding: 2px 6px; font-family: var(--font-mono, monospace); color: var(--text); letter-spacing: 1px; }

/* ── Gebruikers: bewerkbaar e-mailadres + bevestig-knop ────────────────── */
.gb-email-edit { display: flex; align-items: center; gap: 6px; margin-top: 4px; }
.gb-email-inp {
  flex: 1; min-width: 0; max-width: 260px;
  -webkit-appearance: none; appearance: none;
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: 6px;
  color: var(--text-muted); font-family: var(--font); font-size: 12.5px; padding: 5px 8px;
}
.gb-email-inp:focus { border-color: var(--border-strong); outline: none; color: var(--text); }
.gb-email-save {
  flex: none; width: 28px; height: 28px; display: grid; place-items: center;
  border: 1px solid var(--accent); border-radius: 6px; background: var(--accent-soft);
  color: var(--accent); cursor: pointer; transition: background .12s;
}
.gb-email-save:hover { background: var(--accent); color: #fff; }
[data-theme="grey"] .gb-email-save:hover { color: #0e0f0d; }

/* ── Boeking-aangemaakt / betaallink-resultaat — branded ───────────────── */
.bl-result-card {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  border-radius: 14px !important;
  padding: 18px !important;
}
.bl-result-card .bl-card-title {
  font-family: var(--font) !important; font-size: 12px !important; font-weight: 700 !important;
  letter-spacing: .06em !important; text-transform: uppercase !important; color: var(--text-faint) !important; margin: 0 !important;
}
.bl-result-head { align-items: center !important; margin-bottom: 6px !important; }
.bl-result-card .bl-result-bedrag {
  font-family: var(--font) !important; font-weight: 750 !important; letter-spacing: -.02em !important;
  font-size: calc(34px * var(--type-scale, 1)) !important; color: var(--accent) !important; margin: 2px 0 2px !important;
}
.bl-result-card .bl-result-omschr {
  font-family: var(--font) !important; font-size: 14px !important; color: var(--text-muted) !important; margin-bottom: 14px !important;
}
.bl-result-card .bl-badge {
  border-radius: 999px !important; font-family: var(--font) !important; font-weight: 600 !important;
  font-size: 12px !important; letter-spacing: 0 !important; padding: 4px 11px !important;
}
.bl-result-card .bl-mail-bevestig {
  background: var(--success-soft) !important; border: 1px solid color-mix(in oklab, var(--success) 35%, transparent) !important;
  color: var(--success) !important; font-family: var(--font) !important; font-size: 13.5px !important;
  border-radius: 10px !important; padding: 10px 12px !important; margin-bottom: 14px !important;
}
.bl-result-card .bl-mail-bevestig.bl-mail-warn {
  background: var(--warning-soft) !important; border-color: color-mix(in oklab, var(--warning) 35%, transparent) !important; color: var(--warning) !important;
}
.bl-result-card .bl-url-wrap { gap: 8px !important; margin-bottom: 12px !important; }
.bl-result-card .bl-url-input {
  font-family: var(--font) !important; font-size: 13px !important; padding: 10px 12px !important;
  background: var(--panel) !important; border: 1px solid var(--border-strong) !important; border-radius: 8px !important; color: var(--text-muted) !important;
}
.bl-result-card .bl-btn-secondary { border-radius: 8px !important; padding: 10px 14px !important; font-family: var(--font) !important; font-weight: 600 !important; letter-spacing: 0 !important; }
.bl-result-card .bl-qr-details {
  background: var(--panel) !important; border: 1px solid var(--border) !important; border-radius: 10px !important; padding: 10px 14px !important; margin-bottom: 14px !important;
}
.bl-result-card .bl-qr-details summary { font-family: var(--font) !important; font-weight: 600 !important; color: var(--accent) !important; font-size: 13.5px !important; }
.bl-result-card .bl-qr { background: #fff !important; border: 1px solid var(--border) !important; border-radius: 10px !important; }
.bl-result-card .bl-result-hint { font-family: var(--font) !important; font-size: 12.5px !important; color: var(--text-muted) !important; line-height: 1.45 !important; }
.bl-result-card .bl-result-actions { gap: 8px !important; margin-bottom: 0 !important; }
.bl-result-card .bl-result-actions > * { flex: 1 1 0; min-width: 120px; }

/* ── Wachtwoord-instellen: rode fout-rand + eisen-checklist ────────────── */
.lf-input.is-error { border-color: var(--danger) !important; box-shadow: 0 0 0 3px var(--danger-soft) !important; }
.pw-req { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 4px; }
/* Niet voldaan = rood (✗), voldaan = groen (✓) — directe feedback. */
.pw-req li { font-size: 12.5px; color: var(--danger); padding-left: 20px; position: relative; }
.pw-req li::before { content: "✗"; position: absolute; left: 2px; color: var(--danger); font-weight: 700; }
.pw-req li.ok { color: var(--success) !important; }
.pw-req li.ok::before { content: "✓" !important; color: var(--success) !important; }
/* Overeenkomst-melding tweede wachtwoord */
.pw-match { font-size: 12.5px; margin: 8px 0 0; padding-left: 20px; position: relative; font-weight: 500; }
.pw-match::before { position: absolute; left: 2px; font-weight: 700; }
.pw-match.ok { color: var(--success); } .pw-match.ok::before { content: "✓"; }
.pw-match.bad { color: var(--danger); } .pw-match.bad::before { content: "✗"; }

/* Rode fout-rand op .bp-field (profiel-wachtwoord e.d.) */
.bp-field.is-error { border-color: var(--danger) !important; box-shadow: 0 0 0 2px var(--danger-soft) !important; }

/* Bron-label in het Betaallink-overzicht (Walk-in vs Boeking) */
.bl-bron { display: inline-block; font-size: 10.5px; font-weight: 600; padding: 1px 7px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--border-strong); color: var(--text-muted); vertical-align: middle; }
.bl-bron-boeking { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }

/* ── Betaallink-overzicht in huisstijl (Inter, witte kaart, nette tabel) ── */
.bl-recent-card {
  background: var(--panel) !important; border: 1px solid var(--border) !important;
  border-radius: 14px !important; box-shadow: var(--shadow) !important; padding: 18px 20px !important;
}
.bl-recent-card .bl-card-title {
  font-family: var(--font) !important; font-size: calc(17px * var(--type-scale, 1)) !important;
  font-weight: 650 !important; letter-spacing: -.01em !important; text-transform: none !important;
  color: var(--text) !important; margin: 0 0 4px !important;
}
.bl-recent-hint { font-family: var(--font) !important; font-size: 13.5px !important; color: var(--text-muted) !important; margin: 0 0 16px !important; line-height: 1.45 !important; }
.bl-table { font-family: var(--font) !important; font-size: 13.5px !important; }
.bl-table th {
  font-family: var(--font) !important; font-size: 11px !important; font-weight: 600 !important;
  letter-spacing: .04em !important; text-transform: uppercase !important; color: var(--text-faint) !important;
  border-bottom: 1px solid var(--border) !important; padding: 8px 10px !important;
}
.bl-table td { font-family: var(--font) !important; padding: 12px 10px !important; border-bottom: 1px solid var(--border) !important; color: var(--text) !important; font-variant-numeric: tabular-nums; }
.bl-table td.bl-num { font-family: var(--font) !important; font-weight: 600 !important; color: var(--text) !important; }
.bl-table tr:last-child td { border-bottom: none !important; }
/* Openstaande betalingen: twee losse tabellen (gast + het ingeklapte VIPS-blok)
   die onder elkaar moeten uitlijnen. `fixed` laat de <colgroup> uit
   openstaandTabel() (app.js) de kolombreedtes bepalen in plaats van de inhoud,
   zodat beide blokken dezelfde verdeling krijgen. Alleen op deze klasse, NIET
   op .bl-table: de betaallinks-tabel eronder heeft 6 kolommen en geen colgroup,
   en moet zelf blijven rekenen. `width: 100%` staat er expliciet bij — `fixed`
   zonder opgegeven breedte is niet betrouwbaar. */
.bl-table-open { table-layout: fixed !important; width: 100% !important; }
.bl-empty { font-family: var(--font) !important; }

/* ── Dagafsluiting in huisstijl (Inter i.p.v. Lekton/League Spartan) ───── */
.da-card-title, .da-table, .da-table th, .da-table td, .da-table td.da-num,
.da-kv, .da-kv dt, .da-kv dd, .da-totaal, .da-badge, .da-actions-hint,
.da-empty, .da-toolbar-label, .rp-toolbar-label {
  font-family: var(--font) !important;
}
.da-card-title { font-size: 12.5px !important; font-weight: 700 !important; text-transform: uppercase !important;
  letter-spacing: .05em !important; color: var(--text-muted) !important; }
.da-totaal { font-weight: 750 !important; letter-spacing: -.02em !important; color: var(--text) !important; }
.da-table th { font-size: 11px !important; font-weight: 600 !important; letter-spacing: .04em !important;
  text-transform: uppercase !important; color: var(--text-faint) !important; }
.da-table td { color: var(--text) !important; font-variant-numeric: tabular-nums; }
.da-table td.da-num { font-weight: 600 !important; color: var(--text) !important; }
.da-kv dt { color: var(--text-muted) !important; }
.da-kv dd { color: var(--text) !important; font-variant-numeric: tabular-nums; }
.da-actions-hint { color: var(--text-muted) !important; }

/* ── Grootboekrekeningen-pagina ────────────────────────────────────────── */
.gbk-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 14px; margin-top: 4px; }
.gbk-card { background: var(--panel); border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow); padding: 16px 18px; }
.gbk-card-title { font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--text-muted); margin: 0 0 12px; }
.gbk-grid { display: flex; flex-direction: column; gap: 12px; }
.gbk-save-bar { display: flex; align-items: center; justify-content: flex-end; gap: 14px; margin-top: 16px; }
.gbk-save-status { color: var(--text-muted); font-size: 13px; }
/* Brede kaart (per activiteit) over volle breedte, met meerdere kolommen velden */
.gbk-card-wide { grid-column: 1 / -1; }
.gbk-card-wide .gbk-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px 18px; }
.gbk-card-sub { color: var(--text-muted); font-size: 12.5px; margin: -6px 0 12px; }
.gbk-meta { font-style: normal; font-size: 11px; color: var(--text-muted); font-weight: 500; }
/* Per activiteit: reserverings- (17xx) + opbrengstrekening (85xx/86xx) + BTW-tarief */
.gbk-act-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 14px; }
.gbk-act-row { border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; }
.gbk-act-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-weight: 600; font-size: 13.5px; margin-bottom: 10px; }
.gbk-act-row .gbk-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; }
.gbk-act-badge { font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
.gbk-act-badge.hoog { background: rgba(217,119,6,.14); color: #B45309; }

/* ═══════════════════════════════════════════════════════════════════════════
   SQUARE-UI TOKEN-REMAP — backofficev2 redesign.
   Byte-exact palet uit square-ui templates/dashboard-3/app/globals.css
   (shadcn "neutral": monochroom, near-black primary, blauwe chart-schaal, radius 10px).
   Staat bewust ná de originele thema-blokken (zelfde specificiteit (0,1,1) → wint),
   en (0,1,1) > tenant-:root (0,1,0). Legacy-aliassen (--muted/--navy/--line…) verwijzen
   via var() naar deze basis-tokens en erven het nieuwe palet automatisch.
   ═══════════════════════════════════════════════════════════════════════════ */
html[data-theme="light"] {
  --su-chart-1: oklch(0.809 0.105 251.813);
  --su-chart-2: oklch(0.623 0.214 259.815);
  --su-chart-3: oklch(0.546 0.245 262.881);
  --su-chart-4: oklch(0.488 0.243 264.376);
  --su-chart-5: oklch(0.424 0.199 265.638);
  --accent-fg: oklch(0.985 0 0);
  --bg: oklch(1 0 0);
  --panel: oklch(1 0 0);
  --surface: oklch(0.97 0 0);
  --rail: oklch(0.985 0 0);
  --border: oklch(0.922 0 0);
  --border-strong: oklch(0.87 0 0);
  --text: oklch(0.145 0 0);
  --text-muted: oklch(0.556 0 0);
  --text-faint: oklch(0.708 0 0);
  --nav-link: oklch(0.556 0 0);
  --hover: oklch(0.97 0 0);
  --active-bg: oklch(0.97 0 0);
  --accent: #577C8E;           /* palet-B: logo-steel */
  --accent-hover: #46677C;
  --accent-soft: rgba(87,124,142,.14);
  --danger: oklch(0.577 0.245 27.325);
  --danger-soft: oklch(0.577 0.245 27.325 / 0.10);
  --modal-overlay: oklch(0.145 0 0 / 0.45);
  --shadow: 0 1px 3px oklch(0.145 0 0 / 0.08), 0 1px 2px oklch(0.145 0 0 / 0.05);
  --radius: 0.625rem;
  --radius-sm: calc(0.625rem - 4px);
  --radius-lg: calc(0.625rem + 4px);
  --radius-xl: calc(0.625rem + 8px);
}
html[data-theme="grey"] {
  --su-chart-1: oklch(0.809 0.105 251.813);
  --su-chart-2: oklch(0.623 0.214 259.815);
  --su-chart-3: oklch(0.546 0.245 262.881);
  --su-chart-4: oklch(0.488 0.243 264.376);
  --su-chart-5: oklch(0.424 0.199 265.638);
  --accent-fg: oklch(0.205 0 0);
  --bg: oklch(0.145 0 0);
  --panel: oklch(0.205 0 0);
  --surface: oklch(0.269 0 0);
  --rail: oklch(0.205 0 0);
  --border: oklch(1 0 0 / 0.10);
  --border-strong: oklch(1 0 0 / 0.15);
  --text: oklch(0.985 0 0);
  --text-muted: oklch(0.708 0 0);
  --text-faint: oklch(0.556 0 0);
  --nav-link: oklch(0.708 0 0);
  --hover: oklch(0.269 0 0);
  --active-bg: oklch(0.371 0 0);
  --accent: #7A9EB1;           /* palet-B: steel-licht op donker */
  --accent-hover: #8FB0C1;
  --accent-soft: rgba(122,158,177,.20);
  --danger: oklch(0.704 0.191 22.216);
  --danger-soft: oklch(0.704 0.191 22.216 / 0.16);
  --modal-overlay: oklch(0 0 0 / 0.55);
  --shadow: 0 1px 3px oklch(0 0 0 / 0.4), 0 1px 2px oklch(0 0 0 / 0.3);
  --radius: 0.625rem;
  --radius-sm: calc(0.625rem - 4px);
  --radius-lg: calc(0.625rem + 4px);
  --radius-xl: calc(0.625rem + 8px);
}

/* ═══════════════════════════════════════════════════════════════════════════
   SQUARE-UI SHELL + LOGIN — backofficev2 redesign (vanilla, CSP-veilig).
   Plain-class selectors, ná de originele regels → winnen op gelijke specificiteit.
   ═══════════════════════════════════════════════════════════════════════════ */
:root { --su-ease: cubic-bezier(.2,.6,.2,1); }

/* ── App-shell layout ── */
.app-shell { background: var(--bg); }
.app-body { display:flex; min-height:100vh; background: var(--bg); }
.app-sidebar {
  width:256px; flex:0 0 256px; background: var(--rail);
  border-right:1px solid var(--border); display:flex; flex-direction:column;
  padding:14px 12px; gap:2px; min-height:100vh;
}
.app-content { flex:1 1 auto; display:flex; flex-direction:column; min-width:0; background: var(--bg); }
.app-topbar {
  display:flex; align-items:center; gap:12px; min-height:56px;
  padding:10px 24px; border-bottom:1px solid var(--border); background: var(--bg);
  position:sticky; top:0; z-index:20;
}
.app-main { flex:1 1 auto; padding:24px; min-width:0; animation: suMainIn .3s var(--su-ease) both; }

/* ── Sidebar head + user ── */
.sidebar-head { padding:4px 6px 10px; }
.sidebar-logo { height:26px; width:auto; display:block; margin:2px 4px 12px; }
.sidebar-user {
  display:flex; align-items:center; gap:10px; padding:8px;
  border:1px solid var(--border); border-radius: var(--radius); background: var(--panel);
}
/* Initialen in de kleur van de zijbalk zelf (Nick, 3 aug): --panel is precies
   de achtergrond van het gebruikersblok waar het rondje in ligt, dus de letters
   lezen als uitgespaard. Omdat het een token is, wisselt de letterkleur vanzelf
   mee met het thema — wit op steel in licht, donker op steel-licht in grijs.

   LET OP de selector: `.sidebar-user .sidebar-avatar` (0,2,0), niet het kale
   `.sidebar-avatar` (0,1,0). Het avatar-vlakje is een <span> direct ín
   .sidebar-user, en `.sidebar-user span { color: var(--text-faint) }` (r510)
   is (0,1,1) — dát won, en dáárom stonden de initialen grijs. Volgorde in het
   bestand hielp niet; alleen meer specificiteit. Achtergrond/afmetingen kwamen
   hier al vandaan (die zet r510 niet), dus alleen `color` verandert echt. */
.sidebar-user .sidebar-avatar {
  width:30px; height:30px; flex:0 0 auto; border-radius:50%;
  background: var(--accent); color: var(--panel);
  display:flex; align-items:center; justify-content:center; font:600 12px var(--font); text-transform:uppercase;
}
.sidebar-user-text { display:flex; flex-direction:column; min-width:0; line-height:1.3; }
.sidebar-user-text strong { font:600 13px var(--font); color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.sidebar-user-text span { font-size:11.5px; color:var(--text-muted); }
.app-logout {
  margin-left:auto; flex:0 0 auto; width:30px; height:30px; border-radius: var(--radius-sm);
  border:0; background:transparent; color:var(--text-muted); cursor:pointer;
  display:flex; align-items:center; justify-content:center; transition:background .12s var(--su-ease), color .12s var(--su-ease);
}
.app-logout:hover { background: var(--hover); color: var(--text); }

/* ── Module nav ── */
.module-nav { display:flex; flex-direction:column; gap:2px; overflow-y:auto; padding-top:4px; }
.nav-label { font:600 11px var(--font); text-transform:uppercase; letter-spacing:.06em; color:var(--text-faint); padding:12px 10px 4px; }
.module-btn {
  display:flex; align-items:center; gap:10px; width:100%; text-align:left;
  padding:8px 10px; border:0; border-radius: var(--radius-sm); background:transparent;
  color:var(--nav-link); font:500 13.5px var(--font); cursor:pointer;
  transition: background .12s var(--su-ease), color .12s var(--su-ease);
}
.module-btn:hover { background: var(--hover); color: var(--text); }
.module-btn.is-active { background: var(--active-bg); color: var(--text); font-weight:600; }
.module-ico { width:18px; height:18px; flex:0 0 auto; opacity:.9; }
.nav-divider { height:1px; background: var(--border); margin:8px 4px; }

/* ── Topbar ── (zichtbaarheid van de toggle wordt door de bestaande
   drawer-CSS geregeld: zichtbaar < 1100px, verborgen daarboven) */
.sidebar-toggle { width:34px; height:34px; border:1px solid var(--border); border-radius: var(--radius-sm); background: var(--panel); color: var(--text); cursor:pointer; }
@media (max-width: 1099px) { .sidebar-toggle { display:inline-flex; align-items:center; justify-content:center; } }

/* ── Login (square-ui) ── verplaatst.
   De volledige login-vorm staat sinds de eiland-restyle in één blok
   ("LOGIN — de vormentaal van het activiteiten-eiland") hierboven. Losse
   lagen hier maakten de cascade onleesbaar: drie .login-card-regels, twee
   met !important, streden om dezelfde kaart. Alleen de generieke
   .theme-seg-knoppen blijven staan — die worden ook buiten de login
   gebruikt. ── */
.theme-seg { display:inline-flex; gap:2px; padding:3px; background: var(--surface); border:1px solid var(--border); border-radius: var(--radius); }
.theme-seg.login-theme { position:absolute; top:20px; right:20px; }
.theme-seg-btn { width:30px; height:28px; border:0; border-radius: var(--radius-sm); background:transparent; color:var(--text-muted); cursor:pointer; display:flex; align-items:center; justify-content:center; transition: background .12s, color .12s; }
.theme-seg-btn svg { width:16px; height:16px; }
.theme-seg-btn[aria-pressed="true"], .theme-seg-btn.is-active { background: var(--panel); color: var(--text); box-shadow: var(--shadow); }

/* ── Motion (subtiel, reduced-motion-veilig) ── */
@keyframes suCardIn { from { opacity:0; transform: translateY(8px); } to { opacity:1; transform:none; } }
@keyframes suMainIn { from { opacity:0; transform: translateY(6px); } to { opacity:1; transform:none; } }
/* (Mobiele drawer wordt door de bestaande .app-sidebar.is-open + #sidebar-backdrop
   afgehandeld — geen losse nav-open-drawer hier, dat botste met de z-index.) */
@media (prefers-reduced-motion: reduce) {
  .login-card, .app-main, .module-btn, .lf-input, .app-logout, .lf-submit, .app-sidebar, .sidebar-backdrop { animation:none !important; transition:none !important; }
}

/* ═══ SQUARE-UI GENERIEKE CONTROLS (form-velden + knoppen + spinner) ═══
   Lage specificiteit (element/één-klasse) → module-specifieke regels winnen waar
   ze bestaan; dit is de gedeelde basislaag voor alle 16 modules. */
/* `:not(:where([data-fl-skip] *))` — TOEGEVOEGD 10 aug 2026, en niet uit
   netheid. Deze regels staan ONGELAAGD, en ongelaagde CSS wint van alles in een
   `@layer`, ongeacht specificiteit. Een React-eiland levert zijn shadcn-stijlen
   in `@layer utilities` af, dus die verloren hier onvoorwaardelijk: gemeten op
   het QR-eiland kreeg het invoerveld `border-radius: var(--radius-sm)` (4px),
   `padding: 8px 11px` en `font: 13.5px` in plaats van de shadcn-maten 8px /
   4px 12px / 14px. De hoogte klopte wél, want daar zet deze regel niets.

   Waarom het nu pas opvalt: de boek-la en de zijbalk hangen aan `document.body`
   en staan dus buiten `.app-main`. Het QR-eiland is het eerste dat ERIN leeft.

   `[data-fl-skip]` is het bestaande merkteken voor "React bezit deze subtree"
   (app.js gebruikt het al om de label-verbeteraar buiten de deur te houden).
   `:where()` telt NUL specificiteit, dus de cascade voor elk ander element in
   de backoffice blijft exact zoals hij was — gemeten met een selector-diff in
   de browser: op de shell-schermen matchen oude en nieuwe selector precies
   dezelfde elementen, en het enige dat wegvalt is het invoerveld ván het
   eiland. */
.app-main input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not(:where([data-fl-skip] *)),
.app-main select:not(:where([data-fl-skip] *)),
.app-main textarea:not(:where([data-fl-skip] *)) {
  font: 400 13.5px var(--font); color: var(--text); background: var(--panel);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm); padding: 8px 11px;
  transition: border-color .14s var(--su-ease), box-shadow .14s var(--su-ease);
}
.app-main input:focus:not(:where([data-fl-skip] *)),
.app-main select:focus:not(:where([data-fl-skip] *)),
.app-main textarea:focus:not(:where([data-fl-skip] *)) {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
.app-main input:not(:where([data-fl-skip] *))::placeholder,
.app-main textarea:not(:where([data-fl-skip] *))::placeholder { color: var(--text-faint); }
/* Knoppen */
.btn { font: 500 13px var(--font); border-radius: var(--radius-sm); padding: 8px 14px; border: 1px solid var(--border-strong); background: var(--panel); color: var(--text); cursor: pointer; transition: background .12s var(--su-ease), border-color .12s var(--su-ease), opacity .12s; display:inline-flex; align-items:center; gap:7px; }
.btn:hover { background: var(--hover); }
.btn-primary { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); font-weight: 600; }
.btn-primary:hover { opacity: .9; background: var(--accent); }
.btn-ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
.btn-ghost:hover { background: var(--hover); color: var(--text); }
.btn-link { background: transparent; border: 0; color: var(--accent); padding: 4px 2px; font-weight: 500; }
.btn-link:hover { text-decoration: underline; }
.btn:disabled, .btn-primary:disabled { opacity: .45; cursor: not-allowed; }
/* Spinner */
.spin { border: 2px solid var(--border); border-top-color: var(--accent); }

/* ═══ SQUARE-UI RAPPORTAGE-/DATA-MODULES (rap-*, da-*, gbk-*) — blauwdruk ═══
   Dekt dagafsluiting, btw, toeristenbelasting, mous, grootboek in één keer. */
.rap-wrap { max-width: 1120px; }
.rap-h { font: 600 19px var(--font); color: var(--text); letter-spacing: -.015em; margin: 0 0 4px; }
.rap-intro { font: 400 13.5px var(--font); color: var(--text-muted); margin: 0 0 18px; max-width: 72ch; line-height: 1.55; }
/* Filterbar */
.rap-form, .da-toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; padding: 14px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 18px; }
.rap-form label { display: flex; flex-direction: column; gap: 5px; font: 500 12px var(--font); color: var(--text-muted); }
/* Stat-cards (rap-sum) */
.rap-sum { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin-bottom: 18px; }
.rap-sum > div { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 16px; display: flex; flex-direction: column; gap: 6px; transition: border-color .14s var(--su-ease); }
.rap-sum > div:hover { border-color: var(--border-strong); }
.rap-sum > div span { font: 500 12px var(--font); color: var(--text-muted); }
.rap-sum > div strong { font: 600 23px var(--font); color: var(--text); letter-spacing: -.02em; }
/* Datatable */
.rap-table, .da-table { width: 100%; border-collapse: collapse; font: 400 13px var(--font); background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.rap-table thead th, .da-table thead th { text-align: left; font: 600 11px var(--font); text-transform: uppercase; letter-spacing: .05em; color: var(--text-faint); padding: 10px 12px; border-bottom: 1px solid var(--border); background: var(--surface); }
.rap-table td, .da-table td { padding: 10px 12px; border-bottom: 1px solid var(--border); color: var(--text); }
.rap-table tbody tr:last-child td, .da-table tbody tr:last-child td { border-bottom: 0; }
.rap-table tbody tr:hover, .da-table tbody tr:hover { background: var(--hover); }
.rap-table .num, .da-table .num, .app-main td.num, .app-main th.num { text-align: right; font-variant-numeric: tabular-nums; }
.rap-toel { font: 400 12.5px var(--font); color: var(--text-muted); margin-top: 10px; }
/* Dagafsluiting + grootboek cards */
.da-card, .gbk-card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; }
.da-grid, .gbk-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; }
.da-card-title, .gbk-card-title { font: 600 14px var(--font); color: var(--text); margin: 0 0 10px; }
.da-kv { display: flex; justify-content: space-between; gap: 12px; padding: 6px 0; font: 400 13px var(--font); color: var(--text); border-bottom: 1px solid var(--border); }
.da-totaal { font-weight: 700; border-top: 2px solid var(--border-strong); margin-top: 4px; padding-top: 8px; }
.da-num { font-variant-numeric: tabular-nums; }
.da-badge, .da-badge-ok, .da-badge-pending { font: 600 10.5px var(--font); text-transform: uppercase; letter-spacing: .04em; padding: 2px 8px; border-radius: 999px; display: inline-block; }
.da-badge-ok { background: var(--success-soft); color: var(--success); }
.da-badge-pending { background: var(--warning-soft); color: var(--warning); }
.da-empty { color: var(--text-muted); font: 400 13px var(--font); padding: 18px; text-align: center; }
/* Errors */
.ak-err, .form-err { font: 500 12.5px var(--font); color: var(--danger); background: var(--danger-soft); border-radius: var(--radius-sm); padding: 9px 12px; margin-bottom: 14px; }

/* ═══ MODAL — mobiel hoogte-begrensd + scrollbaar, footer-knop altijd in beeld ═══ */
@media (max-width: 719px) {
  .modal { align-items: flex-end !important; justify-content: center !important; padding: 0 !important; }
  .modal-inner, .modal-inner.modal-slide {
    display: flex !important; flex-direction: column !important;
    width: 100% !important; max-width: 100% !important;
    max-height: 92dvh !important; padding: 0 !important;
    border-radius: var(--radius-xl) var(--radius-xl) 0 0 !important;
    border-bottom: 0 !important;
  }
  .modal-scroll { flex: 1 1 auto; overflow-y: auto; padding: 22px 18px 14px; -webkit-overflow-scrolling: touch; }
  .modal-footer { position: sticky; bottom: 0; flex-shrink: 0; padding: 12px 18px calc(14px + env(safe-area-inset-bottom)); }
}
/* Modal form-controls square-ui (modals staan buiten .app-main → eigen regels) */
.modal-inner input:not([type=checkbox]):not([type=radio]):not([type=range]), .modal-inner select, .modal-inner textarea {
  font: 400 14px var(--font); color: var(--text); background: var(--panel);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 9px 11px; width: 100%; box-sizing: border-box;
  transition: border-color .14s var(--su-ease), box-shadow .14s var(--su-ease);
}
.modal-inner input:focus, .modal-inner select:focus, .modal-inner textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.modal-inner input::placeholder, .modal-inner textarea::placeholder { color: var(--text-faint); }
.modal-inner label { font: 500 12.5px var(--font); color: var(--text); }
.modal-footer .btn-primary { min-width: 130px; justify-content: center; }

/* ═══ ACTIVITEITEN slot-grid square-ui (verving het grijs) ═══ */
.banen-vrij, .ag-slot {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm);
  color: var(--text); cursor: pointer;
  transition: border-color .12s var(--su-ease), background .12s var(--su-ease), box-shadow .12s var(--su-ease);
}
.banen-vrij:hover, .ag-slot:hover:not(.is-selected) { border-color: var(--accent); background: var(--hover); }
.banen-vrij.is-selected, .ag-slot.is-selected, .banen-cell.is-selected {
  border: 1px solid var(--accent) !important; background: var(--accent-soft) !important;
  box-shadow: none !important; color: var(--text) !important; font-weight: 600;
}
.banen-geboekt { background: var(--surface); border: 1px solid var(--border); color: var(--text-muted); border-radius: var(--radius-sm); }
.banen-vol { background: var(--surface); color: var(--text-faint); border: 1px solid var(--border); border-radius: var(--radius-sm); cursor: not-allowed; }
.banen-blok { background: repeating-linear-gradient(45deg, var(--surface), var(--surface) 6px, var(--hover) 6px, var(--hover) 12px); color: var(--text-faint); border: 1px solid var(--border); border-radius: var(--radius-sm); }
.banen-empty-cell { background: transparent; border: 0; }
.banen-hed { color: var(--text-muted); font: 600 11px var(--font); text-transform: uppercase; letter-spacing: .04em; }

/* Twee-staps boeken — actiebalk boven de planning */
.act-boekbar {
  position: sticky; top: 0; z-index: 15; display: flex; align-items: center; gap: 12px;
  margin: 0 0 14px; padding: 10px 14px; background: var(--panel);
  border: 1px solid var(--accent); border-radius: var(--radius);
  box-shadow: var(--shadow); animation: suMainIn .22s var(--su-ease) both;
}
.act-boekbar .abk-txt { font: 500 13px var(--font); color: var(--text); }
.act-boekbar .abk-txt b { font-weight: 700; }
.act-boekbar .btn-primary { margin-left: auto; }
/* Annuleer + Boeken even groot: gelijke breedte + gecentreerd, en de ghost een zichtbare
   rand zodat hij als even grote knop oogt naast de gevulde Boeken-knop. */
.act-boekbar .btn-ghost, .act-boekbar .btn-primary {
  min-width: 104px; justify-content: center;
  padding: 9px 14px; font-size: 13px; line-height: 1.2; min-height: 40px;
}
.act-boekbar .btn-ghost { border-color: var(--border-strong); color: var(--text); }
@media (prefers-reduced-motion: reduce) { .act-boekbar { animation: none !important; } .banen-vrij, .tl-slot, .ag-slot { transition: none !important; } }

/* ═══ BOEK-POPUP (.bkflow) — compacter + op mobiel sticky in beeld ═══ */
.bkflow.bkflow-card { max-width: min(480px, 100vw); }
@media (max-width: 719px) {
  .bkflow-overlay { align-items: flex-end !important; justify-content: center !important; padding: 0 !important; overflow: hidden !important; }
  .bkflow.bkflow-card {
    display: flex !important; flex-direction: column !important;
    width: 100% !important; max-width: 100% !important;
    min-height: 0 !important; max-height: 88dvh !important; margin: 0 !important;
    border-radius: var(--radius-xl) var(--radius-xl) 0 0 !important;
    border-bottom: 0 !important; overflow: hidden !important;
    animation: suSheetIn .24s var(--su-ease) both;
  }
  .bkflow-scroll { flex: 1 1 auto !important; overflow-y: auto !important; -webkit-overflow-scrolling: touch; padding: 18px 16px 12px !important; min-height: 0 !important; }
  .bkflow-footer {
    position: sticky !important; bottom: 0; flex-shrink: 0;
    background: var(--panel); border-top: 1px solid var(--border);
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom)) !important;
  }
  .bkflow-footer .bkf-submit, .bkflow-footer .btn-primary { width: 100%; justify-content: center; }
}
@keyframes suSheetIn { from { transform: translateY(14px); opacity: .85; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .bkflow.bkflow-card { animation: none !important; } }

/* ═══ RESTAURANT chrome (rp-*) square-ui — status-kleuren (--rest-*) blijven semantisch ═══ */
.rp-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-bottom: 16px; }
.rp-toolbar-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.rp-toolbar-left, .rp-toolbar-ks { display: flex; align-items: center; gap: 8px; }
.rp-segmented, .segmented { display: inline-flex; gap: 2px; padding: 3px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); }
.rp-segmented button, .segmented button { border: 0; background: transparent; color: var(--text-muted); font: 500 13px var(--font); padding: 6px 12px; border-radius: var(--radius-sm); cursor: pointer; transition: background .12s var(--su-ease), color .12s var(--su-ease); }
.rp-segmented button:hover, .segmented button:hover { color: var(--text); }
.rp-segmented button.is-active, .rp-segmented button[aria-selected="true"], .rp-segmented button.p,
.segmented button.is-active, .segmented button[aria-selected="true"], .segmented button.p {
  background: var(--panel); color: var(--text); box-shadow: var(--shadow); font-weight: 600;
}
.rp-icon-btn { width: 34px; height: 34px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--panel); color: var(--text-muted); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: background .12s var(--su-ease), color .12s, border-color .12s; }
.rp-icon-btn:hover { background: var(--hover); color: var(--text); border-color: var(--border-strong); }
.rp-icon-btn--danger:hover { color: var(--danger); border-color: var(--danger); }
.rp-empty, .rpg-empty { color: var(--text-muted); font: 400 13.5px var(--font); text-align: center; padding: 32px 16px; }
.rp-aside-title { font: 600 12px var(--font); text-transform: uppercase; letter-spacing: .05em; color: var(--text-faint); margin: 0 0 8px; }
.rp-lijst-row { display: flex; align-items: center; gap: 12px; padding: 11px 14px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); margin-bottom: 8px; transition: border-color .12s var(--su-ease); }
.rp-lijst-row:hover { border-color: var(--border-strong); }
.rp-lijst-bijz { color: var(--text-muted); font-size: 12.5px; }
.rp-stats-mini { display: flex; gap: 8px; flex-wrap: wrap; }
.rpg-kchip, .rpg-rg-count, .rpg-slot-count, .rpg-row-num { font: 600 11px var(--font); padding: 2px 8px; border-radius: 999px; background: var(--surface); color: var(--text-muted); }
.rpg-request-group-head, .rpg-row-head { font: 600 12.5px var(--font); color: var(--text); }
.rpg-request { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm); }

/* ═══ BETAALLINK (bp-/bl-) square-ui ═══ */
.bl-card, .bp-section { background: var(--panel) !important; border: 1px solid var(--border) !important; border-radius: var(--radius) !important; }
.bl-card-title, .bp-section-head { font: 600 14px var(--font) !important; color: var(--text) !important; }
.bp-field { display: flex; flex-direction: column; gap: 5px; }
.bp-flabel { font: 500 12.5px var(--font) !important; color: var(--text-muted) !important; }
.bl-btn-secondary { font: 500 13px var(--font) !important; border: 1px solid var(--border-strong) !important; background: var(--panel) !important; color: var(--text) !important; border-radius: var(--radius-sm) !important; padding: 8px 14px !important; cursor: pointer; }
.bl-btn-secondary:hover { background: var(--hover) !important; }
.bl-num { font-variant-numeric: tabular-nums; color: var(--text) !important; }
.bp-baan-chip, .blok-keuze-opt { border: 1px solid var(--border) !important; background: var(--panel) !important; color: var(--text) !important; border-radius: 999px !important; padding: 5px 12px !important; cursor: pointer; transition: border-color .12s, background .12s; }
.bp-baan-chip:hover, .blok-keuze-opt:hover { border-color: var(--accent) !important; }
.bp-baan-chip.is-active, .bp-baan-chip[aria-pressed="true"], .blok-keuze-opt.is-active { background: var(--accent-soft) !important; border-color: var(--accent) !important; color: var(--text) !important; font-weight: 600; }
.bp-note, .bl-mail-bevestig { color: var(--text-muted) !important; font-size: 12.5px !important; }

/* ═══ QR-SCANNER (scan-*) square-ui ═══ */
.scan-page-title { font: 600 19px var(--font) !important; color: var(--text) !important; letter-spacing: -.015em; }
.scan-page-hint, .scan-action-sub { color: var(--text-muted) !important; font: 400 13px var(--font) !important; }
.scan-page-host { background: var(--panel) !important; border: 1px solid var(--border) !important; border-radius: var(--radius) !important; }
.scan-row, .scan-match, .scan-no-match { background: var(--panel) !important; border: 1px solid var(--border) !important; border-radius: var(--radius) !important; }
.scan-match { border-color: color-mix(in oklch, var(--success) 40%, var(--border)) !important; }
.scan-no-match { border-color: color-mix(in oklch, var(--danger) 40%, var(--border)) !important; }
.scan-match-badge { font: 600 10.5px var(--font) !important; text-transform: uppercase; letter-spacing: .04em; padding: 2px 8px !important; border-radius: 999px !important; background: var(--success-soft) !important; color: var(--success) !important; }
.scan-inname-btn { background: var(--accent) !important; color: var(--accent-fg) !important; border: 0 !important; border-radius: var(--radius-sm) !important; font: 600 13px var(--font) !important; padding: 9px 16px !important; cursor: pointer; }
.scan-inname-err { color: var(--danger) !important; background: var(--danger-soft) !important; border-radius: var(--radius-sm) !important; padding: 8px 11px !important; }

/* ═══ ADMIN — beheer / api-keys / marketing (koppelingen) square-ui ═══ */
.beheer-section, .beheer-panel { background: var(--panel) !important; border: 1px solid var(--border) !important; border-radius: var(--radius) !important; margin-bottom: 14px; overflow: hidden; }
.beheer-section-head { font: 650 13.5px var(--font) !important; text-transform: none !important; letter-spacing: 0 !important; color: var(--text) !important; padding: 13px 16px !important; border-bottom: 1px solid var(--border) !important; background: var(--panel) !important; }
.beheer-section-body { padding: 16px !important; }
.beheer-section-body--flush { padding: 0 !important; }
.beheer-field-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px 16px; }
.beheer-table { width: 100%; border-collapse: collapse; font: 400 13px var(--font); }
.beheer-table th { text-align: left; font: 600 11px var(--font) !important; text-transform: uppercase; letter-spacing: .05em; color: var(--text-faint) !important; padding: 9px 14px !important; border-bottom: 1px solid var(--border) !important; background: var(--surface) !important; }
.beheer-table td { padding: 10px 14px !important; border-bottom: 1px solid var(--border) !important; color: var(--text) !important; }
.beheer-table tbody tr:hover { background: var(--hover) !important; }
.beheer-table-hint, .beheer-tiers-hint { color: var(--text-muted) !important; font-size: 12px !important; }
.beheer-row-btn { border: 1px solid var(--border-strong) !important; background: var(--panel) !important; color: var(--text) !important; border-radius: var(--radius-sm) !important; padding: 5px 10px !important; font: 500 12.5px var(--font) !important; cursor: pointer; }
.beheer-row-btn:hover { background: var(--hover) !important; }
.beheer-row-del:hover { color: var(--danger) !important; border-color: var(--danger) !important; }
.beheer-empty { color: var(--text-muted) !important; text-align: center; padding: 22px !important; font: 400 13px var(--font) !important; }
.beheer-num { font-variant-numeric: tabular-nums; }
.beheer-save-bar { position: sticky; bottom: 0; display: flex; align-items: center; justify-content: flex-end; gap: 10px; padding: 12px 16px calc(12px + env(safe-area-inset-bottom)) !important; background: var(--panel) !important; border-top: 1px solid var(--border) !important; }
.beheer-tiers-title { font: 600 13px var(--font) !important; color: var(--text) !important; }
.beheer-time-chips { display: flex; flex-wrap: wrap; gap: 6px; }
/* api-keys */
.ak-input { font: 400 13.5px var(--font) !important; color: var(--text) !important; background: var(--panel) !important; border: 1px solid var(--border-strong) !important; border-radius: var(--radius-sm) !important; padding: 8px 11px !important; }
.ak-err { color: var(--danger) !important; background: var(--danger-soft) !important; border-radius: var(--radius-sm) !important; padding: 8px 11px !important; }
.ak-rev { color: var(--text-muted) !important; cursor: pointer; }
/* marketing / e-mail-templates (ml-) */
.ml-shell { display: grid; grid-template-columns: 220px 1fr; gap: 16px; }
.ml-sidebar { background: var(--panel) !important; border: 1px solid var(--border) !important; border-radius: var(--radius) !important; padding: 8px; }
.ml-textarea, .ml-textarea-html { font: 400 13px var(--font-mono) !important; color: var(--text) !important; background: var(--panel) !important; border: 1px solid var(--border-strong) !important; border-radius: var(--radius-sm) !important; padding: 10px !important; }
.ml-empty { color: var(--text-muted) !important; text-align: center; padding: 22px !important; }
.ml-ph-chip { font: 500 11.5px var(--font-mono) !important; background: var(--surface) !important; color: var(--text-muted) !important; border: 1px solid var(--border) !important; border-radius: var(--radius-sm) !important; padding: 2px 7px !important; cursor: pointer; }
.ml-ph-chip:hover { border-color: var(--accent) !important; color: var(--text) !important; }
@media (max-width: 719px) { .ml-shell { grid-template-columns: 1fr; } }

/* ═══ Ingebedde module (payroll / arrangementen als iframe in de shell) ═══ */
.app-main--embed { padding: 0 !important; display: flex; }
.module-embed { width: 100%; flex: 1 1 auto; height: calc(100dvh - 57px); border: 0; display: block; background: var(--bg); }
.gbk-act-badge.laag { background: rgba(5,150,105,.14); color: #047857; }

/* ═══ Funnel-chart (Statistieken) — square-ui horizontale bars ═══ */
.fchart-card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-lg, 12px); padding: 18px 20px; margin: 4px 0 18px; }
.fchart-title { font-size: 12px; font-weight: 600; letter-spacing: .02em; color: var(--text-muted); text-transform: uppercase; margin: 0 0 14px; }
.fchart-row { display: grid; grid-template-columns: 150px 1fr 46px; align-items: center; gap: 12px; margin: 0 0 9px; }
.fchart-row:last-child { margin-bottom: 0; }
.fchart-lbl { font-size: 13px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fchart-track { position: relative; height: 26px; background: var(--surface, rgba(0,0,0,.04)); border-radius: 7px; overflow: hidden; }
.fchart-bar { height: 100%; min-width: 2px; background: var(--su-chart-2, #2563eb); border-radius: 7px; display: flex; align-items: center; justify-content: flex-end; padding-right: 8px; transform-origin: left center; animation: fchartGrow .55s cubic-bezier(.2,.6,.2,1) both; animation-delay: calc(var(--fc-i, 0) * 70ms); }
.fchart-val { font-size: 11px; font-weight: 600; color: #fff; font-variant-numeric: tabular-nums; opacity: .96; }
.fchart-pct { font-size: 12px; font-weight: 600; color: var(--text-muted); text-align: right; font-variant-numeric: tabular-nums; }
@keyframes fchartGrow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@media (max-width: 719px) { .fchart-row { grid-template-columns: 96px 1fr 40px; gap: 8px; } .fchart-lbl { font-size: 12px; } }
@media (prefers-reduced-motion: reduce) { .fchart-bar { animation: none !important; } }

/* ──────────────────────────────────────────────────────────────────────────
   MOTION-STARTER backoffice v2 (jun 2026) — subtiel, communiceert (waar komt
   dit vandaan / wat verandert / wat hoort bij wat). Alleen transform+opacity,
   ease-out-expo, micro 150ms / entrance ~320ms. Volledig uit bij
   prefers-reduced-motion (onderaan). ui-motion-skill-conform.
   ────────────────────────────────────────────────────────────────────────── */
:root { --bo-ease: cubic-bezier(0.16, 1, 0.3, 1); --bo-dur-enter: 320ms; --bo-dur-micro: 150ms; }

@keyframes boSheetUp { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
@keyframes boFade    { from { opacity: 0; } to { opacity: 1; } }
@keyframes boToastIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }

/* #1 Modal-enter — de boekform-sheet (.bkflow.bkflow-card) heeft al slideInRight
   + reduced-motion-guard; hier alleen de generieke modal: backdrop-fade + (mobiel)
   bottom-sheet-up, want die had op <720px nog geen entrance. */
.modal:not([hidden]) { animation: boFade 200ms ease both; }
@media (max-width: 719px) {
  .modal:not([hidden]) .modal-inner { animation: boSheetUp var(--bo-dur-enter) var(--bo-ease) both; }
}

/* #2 Toast/statuswissel — #iv-toast (hidden→zichtbaar). */
.iv-toast:not([hidden]) { animation: boToastIn 280ms var(--bo-ease) both; }

/* #3 Chip/segment-micro-interactie — tactiele press + zachte kleurtransitie. */
.bkf-baan-chip, .bk-seg-btn, .theme-seg-btn, .rp-seg-btn {
  transition: transform var(--bo-dur-micro) var(--bo-ease), background-color var(--bo-dur-micro) ease, color var(--bo-dur-micro) ease, border-color var(--bo-dur-micro) ease;
}
.bkf-baan-chip:active, .bk-seg-btn:active, .theme-seg-btn:active, .rp-seg-btn:active { transform: scale(.96); }

@media (prefers-reduced-motion: reduce) {
  .modal:not([hidden]), .modal:not([hidden]) .modal-inner, .iv-toast:not([hidden]) { animation: none !important; }
  .bkf-baan-chip, .bk-seg-btn, .theme-seg-btn, .rp-seg-btn { transition: none !important; }
  .bkf-baan-chip:active, .bk-seg-btn:active, .theme-seg-btn:active, .rp-seg-btn:active { transform: none !important; }
}

/* #59 Rittenkaart-knip-herinnering bij scan-uitgifte — opvallend, actie vereist. */
.scan-rittenkaart-check {
  margin: 10px 0 6px;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--accent-soft, rgba(33,167,205,0.14));
  color: var(--accent, #21A7CD);
  border: 1px solid var(--accent, #21A7CD);
  font-weight: 700;
  font-size: 15px;
  text-align: center;
}

/* ── Connector-dashboards (Jachthaven / Kamers) — read-only, backoffice-look ── */
.dash{ padding:22px 26px 48px; max-width:1120px; margin:0 auto; }
.dash-head{ margin:0 0 18px; }
.dash-head h1{ font:600 22px var(--font); color:var(--text); margin:0; }
.dash-head p{ color:var(--text-muted); font-size:13px; margin:4px 0 0; }
/* Peildatum-chip in de kop (Kamers): een momentopname verantwoordt zich in de
   kop zelf, niet alleen in een banner — amber zodra ouder dan een dag. */
.dash-peil{ display:inline-flex; align-items:center; gap:6px; vertical-align:2px; margin-left:10px; padding:3px 11px; border-radius:100px; font:600 12px var(--font); background:var(--accent-soft); color:var(--accent-hover); border:1px solid var(--accent); }
.dash-peil.is-oud{ background:var(--warning-soft); color:var(--warning); border-color:var(--warning); }
.dash-kpis{ display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:12px; margin:0 0 14px; }
.dash-kpi{ background:var(--panel); border:1px solid var(--border); border-radius:var(--radius); padding:14px 16px; }
.dash-kpi .v{ font:700 22px var(--font); letter-spacing:-.02em; color:var(--text); }
.dash-kpi .k{ color:var(--text-muted); font-size:12px; margin-top:3px; }
.dash-sub{ font:600 12px var(--font); letter-spacing:.05em; text-transform:uppercase; color:var(--text-faint); margin:18px 0 8px; }
.dash-card{ background:var(--panel); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden; margin:0 0 16px; }
.dash-card-h{ font:600 14px var(--font); color:var(--text); padding:13px 16px; border-bottom:1px solid var(--border); }
.dash-tbl-wrap{ overflow-x:auto; }
.dash-table{ width:100%; border-collapse:collapse; font-size:13px; }
.dash-table th{ text-align:left; font-weight:600; color:var(--text-muted); padding:9px 16px; border-bottom:1px solid var(--border); white-space:nowrap; background:var(--panel); }
.dash-table td{ padding:9px 16px; border-bottom:1px solid var(--border); color:var(--text); white-space:nowrap; }
.dash-table tr:last-child td{ border-bottom:0; }
.dash-err{ background:rgba(220,38,38,.10); color:var(--danger); border:1px solid var(--danger); border-radius:var(--radius); padding:14px 16px; }
.dash-foot{ color:var(--text-faint); font-size:12px; margin-top:8px; }
.dash-note{ display:flex; align-items:flex-start; gap:10px; background:var(--accent-soft); border:1px solid var(--accent); border-radius:var(--radius); padding:11px 14px; margin:0 0 18px; font-size:13px; color:var(--text); line-height:1.45; }
.dash-note--warn{ background:var(--warning-soft); border-color:var(--warning); }
.dash-note-ico{ flex:0 0 18px; width:18px; height:18px; border-radius:50%; background:var(--accent); color:#fff; font:700 11px var(--font); display:flex; align-items:center; justify-content:center; margin-top:1px; }
.dash-note--warn .dash-note-ico{ background:var(--warning); }
.dash-note strong{ font-weight:700; }
@media (max-width:760px){ .dash{ padding:16px 14px 80px; } .dash-table th,.dash-table td{ padding:8px 10px; } }

/* ── Verblijven: planbord + lijst (operationele VIPS-weergave) ── */
.vbx{ padding:22px 26px 60px; max-width:1180px; margin:0 auto; }
.vbx-toolbar{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin:4px 0 18px; }
.seg{ display:inline-flex; background:var(--surface); border:1px solid var(--border); border-radius:999px; padding:3px; }
.seg button{ font:inherit; font-size:13px; font-weight:600; color:var(--text-muted); background:none; border:0; padding:7px 16px; border-radius:999px; cursor:pointer; transition:color .15s, background .15s; }
.seg button.is-on{ background:var(--panel); color:var(--text); box-shadow:0 1px 3px rgba(0,0,0,.12); }
.vbx-weeknav{ display:inline-flex; align-items:center; gap:6px; }
.vbx-weeknav .wk{ font-size:13px; font-weight:600; color:var(--text); min-width:172px; text-align:center; }
.vbx-navbtn{ width:32px; height:32px; border-radius:9px; border:1px solid var(--border); background:var(--panel); color:var(--text); cursor:pointer; display:grid; place-items:center; }
.vbx-navbtn:hover{ background:var(--hover); }
.vbx-navbtn svg{ width:16px; height:16px; stroke:currentColor; stroke-width:2; fill:none; stroke-linecap:round; stroke-linejoin:round; }
.vbx-today{ font-size:12.5px; color:var(--accent); background:none; border:0; cursor:pointer; font-weight:600; padding:6px 8px; }
.vbx-search{ flex:1; min-width:200px; max-width:340px; font:inherit; font-size:13.5px; padding:9px 13px; border-radius:10px; border:1px solid var(--border); background:var(--panel); color:var(--text); }
.vbx-search::placeholder{ color:var(--text-faint); }
.vbx-spacer{ flex:1; }
.vbx-occ{ font-size:12.5px; color:var(--text-muted); white-space:nowrap; }
.vbx-occ b{ color:var(--text); font-weight:700; }
.vbx-legend{ display:inline-flex; gap:14px; font-size:12px; color:var(--text-muted); align-items:center; }
.vbx-legend i{ width:11px; height:11px; border-radius:3px; display:inline-block; margin-right:5px; vertical-align:-1px; }
.pb{ background:var(--panel); border:1px solid var(--border); border-radius:var(--radius,12px); overflow:hidden; }
.pb-scroll{ overflow-x:auto; }
.pb-grid{ min-width:680px; }
.pb-head, .pb-row{ display:grid; grid-template-columns:84px 1fr; }
.pb-head{ position:sticky; top:0; background:var(--rail); border-bottom:1px solid var(--border); z-index:2; }
.pb-corner{ padding:10px 12px; font-size:11px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--text-faint); border-right:1px solid var(--border); }
.pb-days{ display:grid; grid-template-columns:repeat(7,1fr); }
.pb-day{ padding:9px 4px; text-align:center; font-size:12px; color:var(--text-muted); border-right:1px solid var(--border); }
.pb-day:last-child{ border-right:0; }
.pb-day b{ display:block; color:var(--text); font-size:12.5px; }
.pb-day.is-weekend{ background:var(--hover); }
.pb-day.is-now b{ color:var(--accent); }
.pb-day.is-now{ box-shadow:inset 0 -2px 0 var(--accent); }
.pb-row{ border-bottom:1px solid var(--border); }
.pb-row:last-child{ border-bottom:0; }
.pb-room{ display:flex; align-items:center; padding:0 12px; font-size:13px; font-weight:600; color:var(--text); border-right:1px solid var(--border); background:var(--rail); }
.pb-track{ position:relative; height:40px; background:repeating-linear-gradient(to right, transparent 0, transparent calc(100%/7 - 1px), var(--border) calc(100%/7 - 1px), var(--border) calc(100%/7)); }
.pb-now{ position:absolute; top:0; bottom:0; background:var(--accent-soft); z-index:0; pointer-events:none; }
.pb-bar{ position:absolute; top:5px; bottom:5px; z-index:1; border-radius:7px; padding:0 9px; display:flex; align-items:center; font-size:12px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.pb-bar.s-in{ background:var(--success-soft); color:var(--text); box-shadow:inset 3px 0 0 var(--success); }
.pb-bar.s-exp{ background:var(--accent-soft); color:var(--text); box-shadow:inset 3px 0 0 var(--accent); }
.pb-bar.s-out{ background:var(--warning-soft); color:var(--text); box-shadow:inset 3px 0 0 var(--warning); }
.pb-bar .nn{ opacity:.6; font-weight:500; margin-left:6px; }
.vl-strip{ display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin:0 0 16px; }
.vl-kpi{ background:var(--panel); border:1px solid var(--border); border-radius:var(--radius,12px); padding:14px 16px; }
.vl-kpi .n{ font:700 22px var(--font); color:var(--text); }
.vl-kpi .l{ font-size:12.5px; color:var(--text-muted); margin-top:2px; }
.vl-kpi.is-in{ box-shadow:inset 3px 0 0 var(--success); } .vl-kpi.is-arr{ box-shadow:inset 3px 0 0 var(--accent); } .vl-kpi.is-dep{ box-shadow:inset 3px 0 0 var(--warning); }
.vl-card{ background:var(--panel); border:1px solid var(--border); border-radius:var(--radius,12px); overflow:hidden; }
.vl-table{ width:100%; border-collapse:collapse; font-size:13.5px; }
.vl-table th{ text-align:left; font-weight:600; color:var(--text-muted); font-size:12px; padding:11px 16px; border-bottom:1px solid var(--border); white-space:nowrap; }
.vl-table td{ padding:11px 16px; border-bottom:1px solid var(--border); color:var(--text); white-space:nowrap; }
.vl-table tr:last-child td{ border-bottom:0; }
.vl-pill{ display:inline-flex; align-items:center; gap:6px; font-size:12px; font-weight:600; padding:3px 10px; border-radius:999px; }
.vl-pill::before{ content:''; width:7px; height:7px; border-radius:50%; }
.vl-pill.s-in{ background:var(--success-soft); color:var(--success); } .vl-pill.s-in::before{ background:var(--success); }
.vl-pill.s-exp{ background:var(--accent-soft); color:var(--accent); } .vl-pill.s-exp::before{ background:var(--accent); }
.vl-pill.s-out{ background:var(--warning-soft); color:var(--warning); } .vl-pill.s-out::before{ background:var(--warning); }
.vl-empty{ padding:26px; text-align:center; color:var(--text-faint); font-size:13px; }
@media (max-width:680px){ .vbx{ padding:16px 12px 70px; } .vl-strip{ grid-template-columns:1fr; } .vbx-legend{ display:none; } }
/* Verfijning: sticky kamer-kolom + verdieping-groepering + lege-toggle + detail-modal */
.pb-head{ z-index:4; }
.pb-corner{ position:sticky; left:0; z-index:5; }
.pb-room{ position:sticky; left:0; z-index:2; }
.pb-bar{ cursor:pointer; }
.pb-bar:hover{ filter:brightness(1.05); }
.pb-grouprow{ background:var(--surface); border-bottom:1px solid var(--border); }
.pb-group{ position:sticky; left:0; display:inline-block; padding:6px 12px; font-size:11px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; color:var(--text-muted); }
.vbx-toggle{ font:inherit; font-size:12.5px; font-weight:600; color:var(--text-muted); background:var(--panel); border:1px solid var(--border); border-radius:999px; padding:7px 13px; cursor:pointer; white-space:nowrap; }
.vbx-toggle:hover{ background:var(--hover); }
.vbx-toggle.is-on{ background:var(--accent-soft); color:var(--accent); border-color:var(--accent); }
.vl-table tbody tr{ cursor:pointer; }
.vl-table tbody tr:hover{ background:var(--hover); }
.vbm-overlay{ position:fixed; inset:0; z-index:1000; display:flex; align-items:center; justify-content:center; padding:20px; background:var(--modal-overlay); }
.vbm{ background:var(--panel); border:1px solid var(--border); border-radius:14px; width:100%; max-width:420px; box-shadow:var(--shadow); overflow:hidden; }
.vbm-head{ display:flex; align-items:flex-start; justify-content:space-between; gap:12px; padding:16px 20px; border-bottom:1px solid var(--border); }
.vbm-head h3{ margin:0; font:600 17px var(--font); color:var(--text); }
.vbm-head .sub{ font-size:12.5px; color:var(--text-muted); margin-top:3px; }
.vbm-close{ background:none; border:0; color:var(--text-muted); cursor:pointer; font-size:22px; line-height:1; padding:0 4px; border-radius:8px; }
.vbm-close:hover{ background:var(--hover); color:var(--text); }
.vbm-body{ padding:6px 20px 16px; }
.vbm-row{ display:flex; justify-content:space-between; gap:16px; padding:9px 0; border-bottom:1px solid var(--border); font-size:13.5px; }
.vbm-row:last-child{ border-bottom:0; }
.vbm-row span{ color:var(--text-muted); } .vbm-row b{ color:var(--text); font-weight:600; text-align:right; }
/* Verfijning 2: scale-toggle, datumkiezer, status-filter, klikbare strip-kaarten, tabel-scroll */
.vbx-grp{ display:inline-flex; align-items:center; gap:10px; flex-wrap:wrap; }
.vbx-date, .vbx-select{ font:inherit; font-size:13px; padding:7px 10px; border-radius:9px; border:1px solid var(--border); background:var(--panel); color:var(--text); cursor:pointer; }
.vbx-date:hover, .vbx-select:hover{ background:var(--hover); }
button.vl-kpi{ display:block; width:100%; font:inherit; color:inherit; text-align:left; cursor:pointer; }
.vl-kpi:hover{ border-color:var(--border-strong); }
.vl-kpi.is-active{ outline:2px solid var(--accent); outline-offset:-1px; }
.vl-tablewrap{ overflow-x:auto; }
/* ── Module-linkernav (.bo-subnav) — connector-modules (Jachthaven, later Kamers) ── */
.bo-shell{ display:flex; align-items:flex-start; gap:0; }
.bo-subnav{ flex:0 0 196px; display:flex; flex-direction:column; gap:2px; padding:2px 8px 8px 0; border-right:1px solid var(--border); position:sticky; top:8px; }
.bo-subnav button{ text-align:left; font:inherit; font-size:13.5px; font-weight:500; color:var(--text-muted); background:none; border:0; padding:9px 14px; border-radius:9px; cursor:pointer; transition:background .15s, color .15s; }
.bo-subnav button:hover{ background:var(--hover); color:var(--text); }
.bo-subnav button.is-on{ background:var(--accent-soft); color:var(--accent); font-weight:600; }
.bo-content{ flex:1; min-width:0; padding:0 0 0 22px; }
/* De Jachthaven-CSS stond hier: 30 regels `jh-` (secbar, tellers, kaart,
   legenda, popover, statusbadges) plus de MapLibre-overrides die daarbij hoorden.
   Vervallen op 14 aug 2026 — de Jachthaven is een eigen shadcn-eiland geworden
   (haven-src/) en tekent zijn eigen chrome uit de gedeelde tokens. MapLibre
   draait sindsdien alléén nog in dát iframe, dus ook die overrides deden hier
   niets meer. */
@media (max-width:760px){
  .bo-shell{ flex-direction:column; align-items:stretch; }
  .bo-subnav{ flex:none; flex-direction:row; overflow-x:auto; -webkit-overflow-scrolling:touch; border-right:0; border-bottom:1px solid var(--border); padding:0 0 8px; position:static; max-width:100%; }
  .bo-subnav button{ white-space:nowrap; flex:0 0 auto; }
  .bo-content{ padding:14px 0 0; width:100%; }
}

/* ══ Login-motion (goedgekeurd voorstel, jul 2026) ═══════════════════
   Subtiel-professioneel: focus-ring+glow, oog-morph, shake-bij-fout,
   2FA-slide, knop-states. Knopkleuren blijven de bestaande tokens. */
.lf-input { transition: border-color .15s ease, box-shadow .15s ease; }
.lf-input > svg { transition: color .15s ease; }
.lf-input input { caret-color: var(--lg-ring); }
.lf-input input::placeholder { transition: opacity .18s ease; }
/* De ring zelf staat één keer, bij de focus-regel in het LOGIN-blok
   (.lf-input:not(.lf-otp):focus-within). Hier alleen het icoon, en bewust
   niet op de OTP-wrapper: die heeft geen eigen rand, de zes cellen wel. */
.lf-input:not(.lf-otp):focus-within > svg { color: var(--lg-ring); }
/* Floating-label velden: gé́én zichtbare placeholder — het label ís de placeholder
   (staat in rust in het veld, glijdt omhoog bij focus). Het placeholder-attribuut
   blijft bestaan voor de :placeholder-shown-detectie, maar is altijd onzichtbaar. */
.lf-float input::placeholder { opacity: 0; }
.lf-input input:-webkit-autofill { -webkit-box-shadow: 0 0 0 40px var(--panel) inset; -webkit-text-fill-color: var(--text); caret-color: var(--accent); }

/* Oog-morph (wachtwoord tonen/verbergen) */
.lf-input .reveal { display: grid; place-items: center; }
.lf-input .reveal svg { grid-area: 1 / 1; transition: opacity .15s ease, transform .15s ease; }
.lf-input .reveal .oog-uit { opacity: 0; transform: scale(.8); }
.lf-input .reveal.is-uit .oog-aan { opacity: 0; transform: scale(.8); }
.lf-input .reveal.is-uit .oog-uit { opacity: 1; transform: none; }

/* Fout: shake + rode ring-puls */
@keyframes lfShake { 10%,90%{transform:translateX(-1px)} 20%,80%{transform:translateX(2px)} 30%,50%,70%{transform:translateX(-4px)} 40%,60%{transform:translateX(4px)} }
.lf-field.is-fout .lf-input { border-color: var(--danger) !important; box-shadow: 0 0 0 3px var(--danger-soft, rgba(220,38,38,.16)) !important; animation: lfShake .32s cubic-bezier(.36,.07,.19,.97); }
.lf-field.is-fout .lf-input > svg { color: var(--danger); }

/* Foutmelding schuift in (class-gestuurd i.p.v. hidden-attribuut) */
/* Foutmelding schuift in (class-gestuurd i.p.v. hidden-attribuut).
   DICHT = NIETS: geen hoogte, geen vulling, geen rand — anders staat er een
   leeg streepje tussen subtitel en formulier. OPEN geeft de Alert-vorm terug
   die hierboven (r3119) is vastgelegd; deze regels staan later in het bestand
   en zouden hem anders stilletjes uitwissen. Vandaar `revert-layer` in plaats
   van vaste waarden: dat geeft precies de Alert-declaraties terug, ook als die
   later veranderen.

   HOE: DE DICHTE STAAT SCHRIJFT, DE OPEN STAAT ZWIJGT. Hier stond één regel die
   ALTIJD `padding: 0; border: 0; background: none` zette en een tweede die dat
   voor .is-open herhaalde. Zolang de melding losse tekst was gaf dat niets; nu
   het een omrand vak is, wiste die regel het vak uit — hij staat later in het
   bestand en heeft dezelfde specificiteit (#id + .class). Daarom hangt het
   uitwissen nu aan `:not(.is-open)`: dicht is niets, en open laat de
   Alert-declaraties van r3119 gewoon staan.
   (Niet met `revert-layer` doen: buiten een @layer valt dat terug op de
   browserstijl, niet op de eerdere regel in dit bestand.)

   MAX-HEIGHT 200 EN NIET 88. Gemeten 31 aug 2026, Chromium: het vak is 320px
   breed, de sessiezin loopt over drie regels en het geheel is 86,9px hoog —
   op 1440 én op 390, want de kolom is daar even breed. Dat PASTE nog net in de
   88px die hier stond: 1,1px over. Eén woord erbij, een langere melding of een
   grotere systeemletter en de laatste regel wordt afgeknipt zonder dat iets
   dat meldt. 200px is geen krappe maat meer maar nog steeds een klem: de
   hoogte blijft de inhoud volgen, alleen de bovengrens ligt buiten bereik. */
#login-err { overflow: hidden; text-align: left; transition: max-height .28s ease, opacity .28s ease, margin .28s ease, padding .28s ease; }
#login-err:not(.is-open) { max-height: 0; opacity: 0; margin: 0; padding: 0; min-height: 0; border-width: 0; }
#login-err.is-open { max-height: 200px; opacity: 1; margin: 0 0 20px; }

/* 2FA-veld schuift open zodra vereist */
#lf-2fa-field { overflow: hidden; max-height: 0; opacity: 0; margin: 0; transition: max-height .32s cubic-bezier(.2,.7,.2,1), opacity .28s ease, margin .28s ease; }
#lf-2fa-field.is-open { max-height: 120px; opacity: 1; }

/* Inlogknop-states: pijl-hover, spinner, ✓ (basiskleuren onaangeroerd) */
.lf-submit { position: relative; }
.lf-submit .lf-pijl { transition: transform .16s cubic-bezier(.2,.7,.2,1), opacity .15s; }
.lf-submit:hover .lf-pijl { transform: translateX(4px); }
.lf-submit .lf-spin, .lf-submit .lf-vink { position: absolute; right: 16px; width: 18px; height: 18px; opacity: 0; }
.lf-submit.is-loading { pointer-events: none; opacity: .92; }
.lf-submit.is-loading .lf-pijl { opacity: 0; }
.lf-submit.is-loading .lf-spin { opacity: 1; animation: lfSpin .7s linear infinite; }
@keyframes lfSpin { to { transform: rotate(360deg); } }
.lf-submit.is-success { pointer-events: none; }
.lf-submit.is-success .lf-pijl, .lf-submit.is-success .lf-spin { opacity: 0; }
.lf-submit.is-success .lf-vink { opacity: 1; }
.lf-submit.is-success .lf-vink path { stroke-dasharray: 26; stroke-dashoffset: 26; animation: lfVink .35s cubic-bezier(.65,0,.45,1) forwards; }
@keyframes lfVink { to { stroke-dashoffset: 0; } }

/* ══ Thema-pill (zon ⟷ maan) — login + launchpad ══ */
.tpill { position: relative; display: inline-flex; align-items: center; width: 68px; height: 34px; padding: 3px; border-radius: 99px; border: 1px solid var(--border-strong, var(--border)); background: var(--panel); cursor: pointer; }
.tpill:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Thumb + iconen op ABSOLUTE, symmetrische centra zodat het actieve icoon in
   beide standen exact in het rondje valt (was flex+margin → maan viel ernaast).
   Pill 68×34, padding 3, thumb 26 → licht-centrum 16px, donker-centrum 52px
   (translateX 36), icoon-centra idem (svg 15px → left 8.5 / 44.5, top 9.5). */
.tpill-thumb { position: absolute; top: 3px; left: 3px; width: 26px; height: 26px; border-radius: 50%; background: var(--accent-soft); border: 1px solid var(--accent); transition: transform .26s cubic-bezier(.34,1.4,.4,1); }
html[data-theme="grey"] .tpill-thumb { transform: translateX(36px); }
.tpill svg { position: absolute; top: 9.5px; z-index: 1; width: 15px; height: 15px; transition: opacity .25s ease, transform .35s cubic-bezier(.2,.7,.2,1); }
.tpill .tp-zon { left: 8.5px; color: var(--accent); }
.tpill .tp-maan { left: 44.5px; color: var(--text-faint); opacity: .55; transform: rotate(-30deg) scale(.85); }
html[data-theme="grey"] .tpill .tp-zon { color: var(--text-faint); opacity: .55; transform: rotate(90deg) scale(.85); }
html[data-theme="grey"] .tpill .tp-maan { color: var(--accent); opacity: 1; transform: none; }

/* Circle-reveal (View Transitions) — de wissel zelf */
::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
::view-transition-new(root) { z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  .lf-input, .lf-input > svg, .lf-input input::placeholder, .lf-submit .lf-pijl, .tpill-thumb, .tpill svg, #login-err, #lf-2fa-field { transition: none !important; }
  .lf-field.is-fout .lf-input, .lf-submit.is-loading .lf-spin, .lf-submit.is-success .lf-vink path { animation: none !important; }
}

/* Login-instantie van de pill: terug naar de vaste plek rechtsonder (zoals de
   oude theme-seg) en de generieke .login-theme-strip (r2905, !important)
   overstemmen — anders belandt de pill in de flexrij van .login-main en duwt
   'ie de login-kaart naar rechts (mobiel: pagina breder dan het scherm). */
.tpill.login-theme {
  position: fixed !important; right: 26px !important;
  top: calc(26px + env(safe-area-inset-top, 0px)) !important;
  bottom: auto !important; left: auto !important;
  z-index: 10;
  /* shadcn outline-button: bg-background, 1px --border, shadow-xs. */
  background: var(--lg-bg) !important;
  border: 1px solid var(--lg-border) !important;
  padding: 3px !important;
  box-shadow: var(--lg-shadow-xs);
}
/* ── Shadcn-vorm van de thema-schakelaar op het loginscherm (Nick, 9 aug):
   één vierkante outline-knop, zon en maan gestapeld, wissel met de
   draai-schaal-overgang uit shadcn's mode-toggle. De .tpill-mechaniek
   (klik-handler op de klasse, aria) blijft; alleen de vorm is om. */
.tpill.login-theme {
  width: 36px !important; height: 36px !important;
  border-radius: var(--lg-r-md, 8px) !important; padding: 0 !important;
  display: grid !important; place-items: center;
}
.tpill.login-theme:hover { background: var(--hover) !important; }
.tpill.login-theme .tpill-thumb { display: none; }
.tpill.login-theme .tp-zon, .tpill.login-theme .tp-maan {
  position: absolute; left: auto !important; top: auto !important;
  width: 18px; height: 18px; color: var(--text);
  transition: transform .3s ease, opacity .2s ease;
}
.tpill.login-theme .tp-zon  { opacity: 1; transform: rotate(0) scale(1); }
.tpill.login-theme .tp-maan { opacity: 0; transform: rotate(90deg) scale(.6); }
html[data-theme="grey"] .tpill.login-theme .tp-zon  { opacity: 0; transform: rotate(-90deg) scale(.6); color: var(--text); }
html[data-theme="grey"] .tpill.login-theme .tp-maan { opacity: 1; transform: rotate(0) scale(1); color: var(--text); }

/* Op een telefoon vecht rechtsonder met de Safari-balk (gemeten op Nicks
   toestel, 9 aug) — daar hoort de schakelaar rechtsboven. Staat hier, ná de
   regel hierboven, omdat beide !important dragen en dan de laatste wint. */
@media (max-width: 640px) {
  .tpill.login-theme, .login-theme.theme-seg, .login-theme {
    top: calc(14px + env(safe-area-inset-top, 0px)) !important;
    bottom: auto !important;
    right: 14px !important;
  }
}

/* ══ Floating-label (login) — 1-op-1 het gedrag van de formmotions-demo
   (effect 01): het label ís de placeholder, glijdt bij focus/invoer omhoog met
   een .3s expo-out-glijder (cubic-bezier(.16,1,.3,1)) en de véldrand kleurt
   direct mee bij focus én blijft gekleurd zolang het veld gevuld is. De .18s
   standaard-ease van de eerste versie las als "geen feedback" (melding 3 jul). */
.lf-input.lf-float { position: relative; height: 56px; }
.lf-input.lf-float > label {
  position: absolute; left: 37px; top: 50%; transform: translateY(-50%);
  margin: 0; font: 400 14.5px var(--font); color: var(--text-faint);
  pointer-events: none; transform-origin: left center; background: transparent;
  white-space: nowrap; max-width: calc(100% - 52px); overflow: hidden; text-overflow: ellipsis;
  transition: transform .3s cubic-bezier(.16,1,.3,1), color .3s cubic-bezier(.16,1,.3,1);
  will-change: transform;
}
.lf-input.lf-float input { padding-top: 10px; }
.lf-input.lf-float input:focus ~ label,
.lf-input.lf-float input:not(:placeholder-shown) ~ label {
  /* -50% behoudt de verticale centrering; -17px tilt 'm daarbovenuit. */
  transform: translateY(calc(-50% - 17px)) scale(.72);
  color: var(--accent);
  font-weight: 600;
}
/* Demo-gedrag: rand kleurt óók zolang het veld gevuld is (niet alleen focus). */
.lf-input.lf-float:has(input:not(:placeholder-shown)) { border-color: var(--accent) !important; }
@media (prefers-reduced-motion: reduce) {
  .lf-input.lf-float > label { transition: color .3s ease; }
}

/* ── Inline validatie op blur (demo effect 02): fout = rood + shake + hint,
   goed = groene vink die zich tekent. Fout-stijl hergebruikt .lf-field.is-fout. ── */
.lf-check { display: grid; place-items: center; width: 18px; height: 18px; flex: 0 0 auto; }
.lf-check svg { width: 16px; height: 16px; stroke: var(--lg-success, #059669); fill: none; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.lf-check svg path { stroke-dasharray: 26; stroke-dashoffset: 26; transition: stroke-dashoffset .4s cubic-bezier(.16,1,.3,1) .05s; }
.lf-input.is-geldig .lf-check svg path { stroke-dashoffset: 0; }
.lf-input.lf-float.is-geldig:has(input) { border-color: var(--lg-success, #059669) !important; }
.lf-input.is-geldig > svg:first-child { color: var(--lg-success, #059669); }
.lf-input.is-geldig ~ .lf-hint { color: var(--lg-success, #059669); }
.lf-hint { overflow: hidden; max-height: 0; opacity: 0; font: 400 12.5px var(--font); color: var(--danger); text-align: left; padding: 0 4px; transition: max-height .28s cubic-bezier(.16,1,.3,1), opacity .25s ease, margin .28s ease; }
.lf-hint.is-open { max-height: 40px; opacity: 1; margin-top: 6px; }
@media (prefers-reduced-motion: reduce) {
  .lf-check svg path, .lf-hint { transition: none; }
}

/* De Faciliteiten/Activiteiten-toggle (`.ot-toggle`) stond hier. Vervallen op
   15 aug 2026: Openingstijden is een eigen shadcn-eiland geworden en tekent die
   keuze nu als Tabs in zijn eigen document. */

/* ── Wachtwoordsterkte-balk (formmotions effect 05) ── */
.pw-bar { height: 5px; border-radius: 3px; background: var(--rail, var(--border)); overflow: hidden; margin-top: 8px; }
.pw-bar i { display: block; height: 100%; width: 0; border-radius: 3px; transition: width .4s cubic-bezier(.16,1,.3,1), background .4s ease; }
.pw-sterkte { font: 500 12.5px var(--font); color: var(--text-faint); margin-top: 5px; transition: color .3s ease; }
@media (prefers-reduced-motion: reduce) { .pw-bar i, .pw-sterkte { transition: none; } }

/* ══ Generieke floating-labels op alle backoffice-formulieren (3 jul 2026) ══
   Zelfde motion als het inlogscherm: bij een leeg, niet-gefocust veld ligt
   het Lekton-label groot ín het veld; bij focus/gevuld krimpt het (.3s
   expo-out) terug naar z'n vaste plek boven het veld. app.js zet per veld
   .fl-float (tekstvelden) of .fl-static (select/date/number: label blijft
   klein). Puur transform — geen layout-shift; zonder :has() (oude browsers)
   verandert er niets. Werkt in light + dark via de bestaande tokens. */
@supports selector(:has(*)) {
  .field.fl-float { position: relative; }
  .field.fl-float > span {
    transform-origin: left top;
    transition: transform .3s cubic-bezier(.16,1,.3,1), color .3s cubic-bezier(.16,1,.3,1);
    will-change: transform;
    pointer-events: none;
    /* Zo breed als de tekst — een 100%-brede span × de rust-scale duwde de
       popup 20px breder dan het scherm (zijwaarts scrollen). */
    width: fit-content;
  }
  /* Rust-staat (leeg + geen focus): label zakt het veld in — als een nétte
     placeholder: input-formaat (niet groter) en 12px ingesprongen zoals de
     login-velden (was scale 1.32 zonder inspringing: lomp en tegen de rand). */
  .field.fl-float:has(> input:placeholder-shown:not(:focus)) > span,
  .field.fl-float:has(> textarea:placeholder-shown:not(:focus)) > span {
    transform: translate(12px, 31px) scale(1.12);
    color: var(--text-faint);
  }
  .field.fl-float:has(> textarea:placeholder-shown:not(:focus)) > span { transform: translate(12px, 29px) scale(1.12); }
  /* Focus/gevuld: label klein (bestaande positie) + accent — login-gedrag. */
  /* !important: de Geist-basisregel (.field > span, r±344) zet color met
     !important — zonder gelijke kracht wint die altijd. */
  .field.fl-float:has(> input:focus) > span,
  .field.fl-float:has(> textarea:focus) > span,
  .field.fl-float:has(> input:not(:placeholder-shown)) > span,
  .field.fl-float:has(> textarea:not(:placeholder-shown)) > span {
    color: var(--accent) !important;
  }
  /* Autofill apart: een vendor-pseudo in de lijst hierboven zou de héle
     lijst ongeldig maken zodra de UA 'm binnen :has() afwijst. */
  .field.fl-float:has(> input:-webkit-autofill) > span { color: var(--accent) !important; }
  /* Rand kleurt óók zolang gevuld (niet alleen focus). */
  .field.fl-float > input:not(:placeholder-shown),
  .field.fl-float > textarea:not(:placeholder-shown) { border-color: var(--accent); }
  /* Placeholder-tekst is vervangen door het in-veld-label. */
  .field.fl-float > input::placeholder,
  .field.fl-float > textarea::placeholder { color: transparent; }
  /* Format-hint (oorspronkelijke placeholder) verschijnt klein bij focus. */
  .field.fl-float[data-ph]:has(> input:focus)::after,
  .field.fl-float[data-ph]:has(> textarea:focus)::after {
    content: attr(data-ph);
    font-size: 11px; color: var(--text-faint, var(--muted));
    margin-top: 2px;
  }
  /* Statische velden (select/date/number/…): alleen de focus-accentkleur. */
  .field.fl-static:has(> :focus) > span { color: var(--accent) !important; }
  .field.fl-static > span { transition: color .3s cubic-bezier(.16,1,.3,1); }
}
@media (prefers-reduced-motion: reduce) {
  .field.fl-float > span { transition: color .3s ease; }
}



/* (oude timeline-slot/nu-lijn-lagen verwijderd: de dagweergave tekent nu
   alles met de nv-* taal; tl-* is alleen nog een gedrags-/testhaak) */

/* ── Topbar in merk-navy + wit logo (definitief, 6 jul 2026) ── */
.app-topbar {
  background: #2F4157 !important;
  border-bottom: 1px solid rgba(255,255,255,.08) !important;
}
.app-topbar .app-brand { color: #fff !important; background: transparent !important; border: none !important; }
.app-topbar .app-brand .ab-logo { height: 34px; display: block; filter: brightness(0) invert(1); }
.app-topbar .sidebar-toggle,
.app-topbar .datum-arrow,
.app-topbar .cmd-trigger,
.app-topbar .topbar-actions > button {
  color: #fff !important;
  background: transparent !important;
  border-color: rgba(255,255,255,.22) !important;
}
.app-topbar .sidebar-toggle:hover,
.app-topbar .datum-arrow:hover,
.app-topbar .cmd-trigger:hover,
.app-topbar .topbar-actions > button:hover {
  background: rgba(255,255,255,.12) !important;
}
.app-topbar #datum-cal-mount > button { color: #fff !important; border-color: rgba(255,255,255,.22) !important; background: transparent !important; }
.app-topbar .cmd-trigger-label { color: rgba(255,255,255,.75) !important; }
.app-topbar .cmd-kbd { color: rgba(255,255,255,.75) !important; border-color: rgba(255,255,255,.3) !important; background: rgba(255,255,255,.08) !important; }

/* ── Databalk boven de planning (datum-nav verhuisde uit de navy topbar) ── */
.act-databalk {
  display: flex; align-items: center; gap: 10px;
  margin: 12px 16px 0; padding: 8px 14px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 1px 2px rgba(17,17,17,.04);
}
.act-databalk[hidden] { display: none; }
/* Mobiel: de datum-nav + Vandaag-knop passen niet naast elkaar op 390px —
   laten wrappen i.p.v. de body breed duwen. */
@media (max-width: 640px) {
  .act-databalk { flex-wrap: wrap; gap: 8px; margin: 10px 10px 0; padding: 8px 10px; }
}
.adb-lbl { color: var(--text-muted); font-size: calc(12px * var(--type-scale, 1.2)); display: inline-flex; align-items: center; gap: 6px; }
.adb-vandaag {
  height: 30px; padding: 0 12px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--panel);
  color: var(--text-muted); font: inherit; font-size: calc(11.5px * var(--type-scale, 1.2)); cursor: pointer;
}
.adb-vandaag:hover { background: var(--hover); color: var(--text); }
/* Databalk is helemaal wit (Nick 30 jul): de datum-nav bracht via het legacy
   --beige (= --bg) nog een grijs blok mee midden in de balk. Weg ermee; de
   balk onderscheidt zich van de pagina via rand + lichte schaduw. */
.act-databalk .datum-nav { display: flex; align-items: center; gap: 6px; background: transparent !important; padding: 0 !important; }
/* Datum-trigger in de witte databalk: wit i.p.v. het grijze --surface-vlak,
   zodat 'ie één geheel is met de balk (Nick 16 jul). Rand blijft voor affordance. */
.act-databalk .iselcal-trigger { background: var(--panel) !important; }

/* ── Subnav per activiteit in de sidebar ── */
.act-subnav { display: flex; flex-direction: column; gap: 2px; margin: 2px 8px 10px 26px; }
.asn-item {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 10px; border: none; background: none; border-radius: 8px;
  font: inherit; font-size: calc(12px * var(--type-scale, 1.2)); color: var(--text);
  cursor: pointer; text-align: left;
}
.asn-item:hover { background: var(--hover); }
/* Multiselect: aangevinkte activiteit (filter actief) */
.asn-item.is-aan { background: var(--accent-soft); font-weight: 600; }
.asn-item.is-aan .asn-dot { outline: 2px solid var(--accent); outline-offset: 1px; }
.asn-alles { color: var(--text-muted); }
.asn-alles .asn-dot { background: var(--text-faint, #d4d4d8); }
.asn-alles.is-aan { color: var(--text); }
.asn-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--success, #059669); flex: none; }
.asn-dot.is-leeg { background: var(--text-faint, #d4d4d8); }
.asn-tel { margin-left: auto; font-size: calc(10.5px * var(--type-scale, 1.2)); color: var(--text-muted); }
.act-vrij-badge { margin-left: 10px; font-size: calc(10.5px * var(--type-scale, 1.2)); font-weight: 700; color: var(--success, #059669); }
.act-vrij-badge.is-vol { color: var(--text-muted); }

/* ══════════════════════════════════════════════════════════════════════════
   KLUS 8 — wat we overnemen uit het externe redesign (2 augustus 2026)
   Contract: site/voorstel-redesign-activiteiten.html (b82f52c).
   Alles hieronder staat op tokens (--accent / --warning / --danger / --hover),
   niet op de letterlijke hexen van het voorstel: dat pakket zit in de "niet
   doen"-bak (#3d6c7c is niet de canon, en de vol-badge + stip zijn terracotta,
   wat in deze codebase verboden is). Zo klopt het ook in het grijze thema.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Zijbalk: teller mét noemer + bezettingsstrip (punt 1 + 2) ── */
.asn-item { flex-direction: column; align-items: stretch; gap: 5px; }
.asn-r1 { display: flex; align-items: center; gap: 8px; min-width: 0; }
.asn-nm { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.asn-tel { flex: none; font-variant-numeric: tabular-nums; }
/* De strip spreekt dezelfde taal als de tijdlijn en als de dagmarkering in de
   kalender: gevuld vlak = bezetting, 45°-arcering = blokkade (een TEXTUUR, dus
   ook zonder kleurwaarneming te onderscheiden), rode streep = nu, waas = voorbij.
   Je boekt er niet op — de strip vervangt de tijdlijn niet. */
.asn-strip {
  position: relative; display: block; height: 12px; border-radius: 4px;
  background: var(--surface); border: 1px solid var(--border); overflow: hidden;
}
.asn-strip i { position: absolute; top: 2px; bottom: 2px; border-radius: 2px; background: var(--accent); }
.asn-strip i.blk {
  top: auto; bottom: 1px; height: 3px; border-radius: 1px;
  background: repeating-linear-gradient(45deg,
    var(--warning-soft), var(--warning-soft) 3px, var(--warning) 3px, var(--warning) 4px);
}
.asn-strip .af { position: absolute; left: 0; top: 0; bottom: 0; background: var(--hover); }
.asn-strip .nu { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--danger); border-radius: 1px; }

/* ── De aandachtsregel (punt 5): ÉÉN regel, en alleen als er iets is ──
   Bewust geen drie permanente kaarten bovenaan: een vak dat er altijd staat,
   ook als er niets aan de hand is, wordt binnen een week meubilair — en dan
   genegeerd op het moment dat het wél iets zegt. Bij nul punten rendert
   nvAandachtHtml() niets, dus kost dit dan ook geen pixel. */
.nv-aandacht {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  margin: 12px 16px 0; padding: 9px 13px;
  border: 1px solid var(--warning); background: var(--warning-soft); color: var(--warning);
  border-radius: 10px; font-size: calc(11.5px * var(--type-scale, 1.2));
}
.nv-aandacht .na-ic { display: inline-flex; flex: none; }
.nv-aandacht b { font-weight: 700; flex: none; }
.nv-aandacht .na-txt { flex: 1 1 220px; min-width: 0; opacity: .95; }
.nv-aandacht .na-kn {
  flex: none; border: 1px solid currentColor; background: none; color: inherit;
  border-radius: 7px; padding: 4px 11px; font: inherit;
  font-size: calc(11px * var(--type-scale, 1.2)); font-weight: 600; cursor: pointer;
}
.nv-aandacht .na-kn:hover { background: rgba(0,0,0,.06); }
[data-theme="grey"] .nv-aandacht .na-kn:hover { background: rgba(255,255,255,.1); }

/* ── Overzichtsvenster achter "Bekijk" (Nick, 3 aug) ──
   Rijen in het bestaande modal-jasje: het venster zelf is .modal/.modal-inner,
   hier staat alleen wat de rijen eigen is. Het oranje is de bestaande
   waarschuwingskleur uit de regel hierboven — geen nieuwe kleur erbij. */
.aa-lijst { display: flex; flex-direction: column; gap: 8px; }
.aa-rij {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  padding: 11px 12px; border: 1px solid var(--border); border-radius: var(--radius, 10px);
  background: var(--panel); color: var(--text); font: inherit; cursor: pointer;
  transition: border-color .12s var(--su-ease), background .12s var(--su-ease);
}
.aa-rij:hover { border-color: var(--accent); background: var(--accent-soft); }
.aa-ic {
  flex: none; width: 32px; height: 32px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--warning-soft); color: var(--warning);
}
.aa-tekst { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.aa-wat { font-size: calc(12.5px * var(--type-scale, 1.2)); font-weight: 600; overflow-wrap: anywhere; }
.aa-actie { font-size: calc(10.5px * var(--type-scale, 1.2)); color: var(--text-muted); overflow-wrap: anywhere; }
.aa-chev { flex: none; color: var(--text-faint); font-size: calc(17px * var(--type-scale, 1.2)); line-height: 1; }
.aa-rij:hover .aa-chev { color: var(--accent); }

/* ── "Eerstvolgend" (punt 3): wie komt er zo? ──
   Als compacte band onder de datumbalk, niet als vaste derde kolom — die
   driekolomswerkbank staat in de "niet doen"-bak. Brede inhoud scrolt binnen
   z'n eigen container, nooit de pagina. */
.nv-next {
  display: flex; align-items: center; gap: 10px;
  margin: 12px 16px 0; padding: 7px 12px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
}
.nv-next .nx-kop {
  flex: none; font-size: calc(9px * var(--type-scale, 1.2)); letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-faint); font-weight: 600;
}
.nv-next .nx-rij { display: flex; gap: 6px; overflow-x: auto; min-width: 0; padding-bottom: 1px; }
.nv-next .nx-item {
  flex: none; display: inline-flex; align-items: baseline; gap: 7px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  border-radius: 8px; padding: 5px 10px; font: inherit;
  font-size: calc(10.5px * var(--type-scale, 1.2)); cursor: pointer; white-space: nowrap;
}
.nv-next .nx-item:hover { border-color: var(--accent); background: var(--accent-soft); }
.nv-next .nx-t { font-family: var(--font-mono, inherit); font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.nv-next .nx-n { font-weight: 600; }
.nv-next .nx-w { color: var(--text-faint); font-size: calc(9.5px * var(--type-scale, 1.2)); }

/* ── Zoom op de tijdas (punt 7) ──
   Niet één nieuwe vaste schaal (15 uur in 1022 px = 68 px/uur, en dan is een
   half-uursblok 34 px breed), maar een keuze die de balie zelf zet — met de
   bestaande schaal als beginstand. */
.nv-zoom { display: flex; align-items: center; justify-content: flex-end; gap: 9px; padding: 8px 16px 2px; flex-wrap: wrap; }
.nv-zoom .nvz-lbl { font-size: calc(9.5px * var(--type-scale, 1.2)); color: var(--text-faint); }
.nv-zoom .nvz-seg { display: inline-flex; border: 1px solid var(--border); border-radius: 9px; background: var(--panel); padding: 2px; gap: 2px; }
.nv-zoom .nvz-btn {
  border: 0; background: none; border-radius: 7px; padding: 4px 10px; font: inherit;
  font-size: calc(10px * var(--type-scale, 1.2)); font-weight: 600; color: var(--text-muted); cursor: pointer;
}
.nv-zoom .nvz-btn:hover { color: var(--text); background: var(--hover); }
.nv-zoom .nvz-btn.is-aan { background: var(--accent); color: #fff; }
[data-theme="grey"] .nv-zoom .nvz-btn.is-aan { color: var(--bg); }

@media (max-width: 640px) {
  .nv-aandacht, .nv-next { margin-left: 10px; margin-right: 10px; }
  .nv-zoom { padding: 8px 10px 2px; justify-content: flex-start; }
}

/* ── Shell v2: navy topbar over de volle breedte (boven sidebar + content) ── */
.app-shell { display: flex; flex-direction: column; min-height: 100dvh; }
.app-shell > .app-topbar { position: sticky; top: 0; z-index: 40; }
.app-topbar .app-brand { display: inline-flex !important; align-items: center; padding: 4px 8px; border-radius: 8px; cursor: pointer; border: none; }
.app-topbar .app-brand:hover { background: rgba(255,255,255,.12) !important; }
/* Mobiel/tablet: hamburger vóór het logo (Nick, 3 aug). Alleen de flex-volgorde
   draait om, de HTML blijft staan — dus de tabvolgorde blijft ongewijzigd
   (logo, dan hamburger) en niets anders in de balk verschuift mee. Boven
   1100px is de hamburger display:none (r682/r3648), dus daar verandert niets;
   op ≤1099px is de zijbalk een drawer en hóórt de knop die 'm opent vooraan. */
@media (max-width: 1099px) {
  .app-topbar .sidebar-toggle { order: -1; }
}
#act-tabs { display: none !important; }
.nav-module-titel { font-weight: 700; font-size: calc(14px * var(--type-scale, 1.2)); margin: 12px 6px 6px; color: var(--text); }
.nav-module-titel small { display: block; font-weight: 400; color: var(--text-muted); font-size: calc(11px * var(--type-scale, 1.2)); margin-top: 2px; }
.sidebar-foot { margin-top: auto; }
.sidebar-foot .sidebar-user { margin-bottom: 10px; }
@media (min-width: 1100px) {
  .app-sidebar { position: sticky; top: 64px; max-height: calc(100dvh - 88px); overflow-y: auto; }
}
@media (max-width: 1099px) {
  /* 900, niet 45. Onder 1100 px is de zijbalk een off-canvas drawer met een
     eigen backdrop (#sidebar-backdrop, z-index 850). Deze regel stond op 45 en
     overschreef de 900 uit het drawer-blok hierboven (regel ~700), waardoor de
     OPEN drawer áchter zijn eigen backdrop lag: op een telefoon was daarmee de
     hele zijnav onklikbaar — inclusief het activiteitenfilter en de
     module-knoppen. Gevonden doordat Playwright op 390×844 meldde dat
     #sidebar-backdrop de klik op .asn-item opving.
     900 blijft onder de modals (1000+) en boven de backdrop (850). */
  .app-sidebar { z-index: 900; }
}

/* Theme-toggle in de navy topbar: transparant met witte iconen */
.app-topbar .theme-seg { background: transparent !important; border: 1px solid rgba(255,255,255,.22) !important; margin-right: 6px; }
.app-topbar .theme-seg-btn { color: rgba(255,255,255,.75) !important; background: transparent !important; }
.app-topbar .theme-seg-btn.is-active { color: #fff !important; background: rgba(255,255,255,.18) !important; }
.app-topbar .theme-seg-btn:hover { color: #fff !important; }

/* ── QR-scanner: geen sidebar (lege nav) + nette veld-padding ── */
.app-body:has(.scan-page) .app-sidebar { display: none !important; }
.app-body:has(.scan-page) #act-databalk { display: none !important; }
.scan-page input { padding: 12px 14px !important; box-sizing: border-box; }
.scan-page { max-width: 720px; margin: 0 auto; }

/* ── Dark mode: topbar volgt het thema (navy is het light-merk) ── */
[data-theme="grey"] .app-topbar { background: var(--panel) !important; border-bottom: 1px solid var(--border) !important; }
[data-theme="grey"] .lp-top { background: var(--panel) !important; border-bottom: 1px solid var(--border); }

/* ════ Restaurant-template voor de hele backoffice (Nick, 7 jul) ════ */
/* 1) Zelfde lichtgrijze achtergrond als restaurant/payroll */
html[data-theme="light"] { --bg: #f6f6f4; --panel-2: #fbfbfa; }
html:not([data-theme="light"]) { --panel-2: rgba(255,255,255,.04); }

/* 2) Sidebar = platte panel-kolom (geen zwevende kaart), zoals restaurant */
@media (min-width: 1100px) {
  .app-sidebar {
    margin: 0 !important;
    border: none !important;
    border-right: 1px solid var(--border) !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    width: 212px !important;
    padding: 14px 10px !important;
    top: 52px !important;
    max-height: calc(100dvh - 52px) !important;
  }
}
.nav-module-titel { font-size: 16px !important; font-weight: 600 !important; margin: 12px 4px 2px !important; padding: 0 7px; }
.nav-module-titel small { font-size: 12px !important; }
.app-sidebar .module-btn, .app-sidebar .asn-item {
  font-size: calc(11.5px * var(--type-scale, 1.2)) !important;
  border-radius: 8px !important;
  padding: 8px 11px !important;
}
.app-sidebar .module-btn:hover, .app-sidebar .asn-item:hover { background: var(--panel-2) !important; }
.app-sidebar .module-btn.is-active { background: var(--accent-soft) !important; color: var(--accent) !important; font-weight: 600 !important; }

/* 3) QR-scanner: nette gecentreerde kaart + correct invulveld */
.scan-page { max-width: 560px !important; margin: 22px auto 0 !important; padding: 0 16px; }
.scan-page-title { font-size: 22px; letter-spacing: -.01em; margin: 0 0 4px; }
.scan-page-hint { color: var(--text-muted); margin: 0 0 14px; }
.scan-page-host, .scan-page-host > * { min-width: 0; }
.scan-page-host { background: var(--panel); border: 1px solid var(--border); border-radius: 14px; padding: 18px; display: flex; flex-direction: column; gap: 12px; }
.scan-page-host input {
  width: 100% !important;
  padding: 12px 14px !important;
  margin: 0 !important;
  border: 1px solid var(--border) !important;
  border-radius: 10px !important;
  background: var(--panel) !important;
  color: var(--text) !important;
  font: inherit !important;
  box-sizing: border-box !important;
}
.scan-page-host input:focus { outline: none !important; border-color: var(--accent) !important; box-shadow: 0 0 0 3px var(--accent-soft) !important; }
.scan-page-host button { border-radius: 10px !important; }

/* ── QR-scanner-ontwerp (7 jul): camera-vlak als hoofdknop ── */
.qr-cam { position: relative; aspect-ratio: 4/3; border-radius: 12px; background: #10161f; overflow: hidden; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.qr-cam .scan-video-wrap { position: absolute !important; inset: 0 !important; width: 100% !important; height: 100% !important; margin: 0 !important; }
.qr-cam video { width: 100% !important; height: 100% !important; object-fit: cover; }
.qr-cam #scan-toggle { display: none !important; }
.qr-vizier { position: absolute; inset: 0; margin: auto; width: 56%; aspect-ratio: 1; border-radius: 18px; z-index: 2; pointer-events: none; opacity: .9;
  background:
    linear-gradient(#fff,#fff) top left/26px 3px,    linear-gradient(#fff,#fff) top left/3px 26px,
    linear-gradient(#fff,#fff) top right/26px 3px,   linear-gradient(#fff,#fff) top right/3px 26px,
    linear-gradient(#fff,#fff) bottom left/26px 3px, linear-gradient(#fff,#fff) bottom left/3px 26px,
    linear-gradient(#fff,#fff) bottom right/26px 3px,linear-gradient(#fff,#fff) bottom right/3px 26px;
  background-repeat: no-repeat; }
.qr-lijn { display: none; position: absolute; left: 24%; right: 24%; height: 2px; background: var(--success, #059669); top: 34%; border-radius: 2px; box-shadow: 0 0 12px var(--success, #059669); z-index: 2; pointer-events: none; }
.qr-cam.is-actief .qr-lijn { display: block; animation: qrScan 2.2s ease-in-out infinite; }
.qr-cam.is-actief .qr-cta { display: none; }
@keyframes qrScan { 50% { top: 64%; } }
.qr-cta { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; gap: 8px; color: #fff; font-weight: 600; text-align: center; pointer-events: none; }
.qr-cta svg { width: 34px; height: 34px; opacity: .95; }
.qr-cta small { font-weight: 400; opacity: .65; }
.qr-of { display: flex; align-items: center; gap: 12px; color: var(--text-muted); font-size: calc(10.5px * var(--type-scale, 1.2)); margin: 4px 0 0; }
.qr-of::before, .qr-of::after { content: ''; flex: 1; height: 1px; background: var(--border); }
/* Zoekrij: veld + normale steel-knop naast elkaar i.p.v. de platte volle-
   breedte balk (Nick 16 jul, voorstel-bo-scanner). */
.scan-zoekrij { display: flex; gap: 8px; align-items: stretch; }
.scan-zoekrij input { flex: 1; min-width: 0; }
.scan-zoekrij .btn-primary { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; padding: 0 18px !important; }
/* Status-chip op het camera-vlak ("Camera staat uit" / actief). */
.qr-chip { position: absolute; top: 12px; left: 50%; transform: translateX(-50%); z-index: 3;
  background: rgba(255,255,255,.14); border-radius: 100px; padding: 5px 12px;
  font-size: calc(10.5px * var(--type-scale, 1.2)); color: rgba(255,255,255,.85); pointer-events: none; }
.qr-cam.is-actief .qr-chip { background: rgba(47,143,91,.35); }
/* Lege-staat onder "Zojuist gescand". */
.qr-recent-leeg { border: 1px dashed var(--border-strong); border-radius: 10px; padding: 14px;
  text-align: center; font-size: calc(11.5px * var(--type-scale, 1.2)); color: var(--text-faint); }
.scan-manual.qr-zoekrij { display: flex; gap: 10px; align-items: stretch; margin: 0 !important; }
.scan-manual.qr-zoekrij .field { flex: 1; margin: 0 !important; }
/* Het label stond hier op display:none, zodat het veld "Boeking-ID of code"
   het enige veld op de pagina was zónder zichtbaar label — de placeholder
   moest het alleen doen, en die verdwijnt zodra je typt. Sinds 10 aug staat
   het label er weer, bóven het veld (huisregel), met de info-knop ernaast. */
.scan-manual.qr-zoekrij .field { display: flex; flex-direction: column; gap: 6px; }
.scan-manual.qr-zoekrij .field > span:not(.scan-zoekrij) {
  display: inline-flex; align-items: center;
  font: 600 calc(11px * var(--type-scale, 1.2))/1.2 var(--font);
  color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em;
}
.scan-manual.qr-zoekrij .scan-zoekrij { display: flex; gap: 8px; }
.scan-manual.qr-zoekrij #scan-lookup { white-space: nowrap; border-radius: 10px !important; background: #2F4157 !important; border-color: #2F4157 !important; color: #fff !important; padding: 0 18px !important; }
.scan-manual.qr-zoekrij .form-err { flex-basis: 100%; }
.qr-veldhint { font-size: calc(10.5px * var(--type-scale, 1.2)); color: var(--text-muted); margin: 6px 2px 0; }
.qr-recent h3 { font-size: calc(10px * var(--type-scale, 1.2)); letter-spacing: .07em; text-transform: uppercase; color: var(--text-muted); margin: 10px 0 8px; }
.qr-r-item { display: flex; align-items: center; gap: 10px; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 10px 12px; margin-bottom: 8px; }
/* Status-rondje in de feed: kleur volgt het scanresultaat (ok/err/warn/laden). */
.qr-r-st { width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; font-size: 13px; flex: none; }
.qr-r-ok { background: var(--success-soft, #ecfdf5); color: var(--success, #059669); }
.qr-r-err { background: var(--danger-soft, #fdecea); color: var(--danger, #c0453b); }
.qr-r-warn { background: var(--warning-soft, #fbecdc); color: var(--warning, #c2620d); }
.qr-r-laden { background: var(--surface, #f0f0ee); color: var(--text-muted, #5b5d57); }
.qr-r-item b { font-size: calc(11px * var(--type-scale, 1.2)); }
.qr-r-item small { display: block; color: var(--text-muted); }

/* ── De scanuitkomst als Alert (10 aug 2026) ─────────────────────────────────
 * Icoon links, kop, regel eronder. Drie ernstgraden met eigen kleur én eigen
 * teken, zodat de melding ook zonder kleurwaarneming te lezen is: groen ✓ er
 * is iets gebeurd, amber ⚠ nu even niet, rood ✕ hier valt niets uit te geven.
 * De rand links is het snelste signaal op een iPad die schuin op de balie
 * staat — daar is een pastelvlak van een meter afstand niet te onderscheiden. */
.scan-alert {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 11px 13px; border-radius: 10px;
  border: 1px solid var(--border); border-left-width: 3px;
  background: var(--surface); margin: 2px 0 10px;
}
.scan-alert-ico { flex: none; width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; font-weight: 700; }
/* display:block ook op de spans: de camera-melding bouwt dezelfde Alert met
   <span>-elementen (ze zit in #scan-err, waar een <div> niet mag). */
.scan-alert-body { display: block; min-width: 0; }
.scan-alert-kop { display: block; font: 600 calc(12.5px * var(--type-scale, 1.2))/1.35 var(--font); color: var(--text); }
.scan-alert-tekst { display: block; margin: 3px 0 0; font: 400 calc(11.5px * var(--type-scale, 1.2))/1.45 var(--font); color: var(--text-muted); overflow-wrap: anywhere; }
/* #scan-err draagt zelf .form-err (rood vlak + padding). Zit er een Alert in,
   dan zou dat een kader in een kader geven — dus die laag uitzetten. */
#scan-err:has(.scan-alert) { background: none !important; border: 0 !important; padding: 0 !important; color: inherit !important; }
.scan-alert.is-ok   { border-color: color-mix(in oklch, var(--success) 45%, var(--border)); border-left-color: var(--success); background: var(--success-soft, #ecfdf5); }
.scan-alert.is-warn { border-color: color-mix(in oklch, var(--warning) 45%, var(--border)); border-left-color: var(--warning); background: var(--warning-soft, #fbecdc); }
.scan-alert.is-err  { border-color: color-mix(in oklch, var(--danger) 45%, var(--border));  border-left-color: var(--danger);  background: var(--danger-soft, #fdecea); }
.scan-alert.is-ok   .scan-alert-ico { background: var(--success); color: #fff; }
.scan-alert.is-warn .scan-alert-ico { background: var(--warning); color: #fff; }
.scan-alert.is-err  .scan-alert-ico { background: var(--danger);  color: #fff; }
/* De rode variant van de resultaatkaart bestond nog niet: er was alleen ok en
   warn, en een geannuleerde boeking viel daardoor terug op groen. */
.scan-action.is-err { border-color: color-mix(in oklch, var(--danger) 40%, var(--border)) !important; }
.scan-action.is-err .scan-match-badge { background: var(--danger-soft, #fdecea) !important; color: var(--danger) !important; }

/* ── Info-popover bij het zoekveld ───────────────────────────────────────────
 * Popover en met opzet géén tooltip: dit scherm draait op een iPad aan de
 * balie, en hover bestaat op een aanraakscherm niet. Opent op tik/klik/toets. */
.qr-info { position: relative; display: inline-flex; margin-left: 6px; vertical-align: middle; }
.qr-info-knop {
  width: 18px; height: 18px; border-radius: 50%; padding: 0;
  border: 1px solid var(--border-strong, var(--border)); background: var(--panel);
  color: var(--text-muted); font: 700 11px/1 var(--font); cursor: pointer;
  display: grid; place-items: center;
}
.qr-info-knop:hover { color: var(--text); border-color: var(--accent); }
.qr-info-knop:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.qr-info-pop {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 40;
  width: min(300px, calc(100vw - 48px));
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0,0,0,.14); padding: 12px 14px;
  display: flex; flex-direction: column; gap: 5px;
  font: 400 calc(11px * var(--type-scale, 1.2))/1.5 var(--font); color: var(--text-muted);
  text-transform: none; letter-spacing: 0;
}
.qr-info-pop[hidden] { display: none; }
.qr-info-pop strong { color: var(--text); font-weight: 600; }
/* In de boekingsla staat de i-knop rechts uitgelijnd aan het eind van de
   wanneer-regel. Met `left: 0` zou de popover vanaf daar 300px naar RECHTS
   lopen en de la uit steken; vanaf de rechterrand blijft hij binnen. */
.bd-sm-info .qr-info-pop { left: auto; right: 0; }

/* ── Zoekveld op maat ────────────────────────────────────────────────────────
 * Het veld is zo breed als zijn inhoud, niet zo breed als de rij: acht tekens
 * vragen geen halve pagina. `.qr-maat` is een onzichtbare kopie van de tekst
 * die de kolombreedte zet; het veld ligt er in dezelfde grid-cel overheen. */
.scan-manual.qr-zoekrij .scan-zoekrij { align-items: stretch; }
/* flex:0 1 auto — de kolom mag krimpen op een smal scherm, maar groeit niet
   mee tot de volle rijbreedte; dát is het hele punt van "op maat". */
.qr-veldmaat { display: grid; flex: 0 1 auto; min-width: 0; max-width: 100%; }
.qr-maat {
  grid-area: 1 / 1; visibility: hidden; height: 0; overflow: hidden;
  white-space: pre; padding: 0 30px; box-sizing: content-box;
  font: 400 calc(12.5px * var(--type-scale, 1.2)) var(--font); letter-spacing: .01em;
}
.qr-veldmaat #scan-input { grid-area: 1 / 1; width: 100%; min-width: 0; }
/* Op een telefoon is er geen ruimte over om te verdelen: daar knelt "op maat"
   de placeholder af ("Bijv. ISL-1024 of ARR…"). Onder 560px krijgt het veld
   dus gewoon de volle regel en zakt de knop eronder. */
@media (max-width: 560px) {
  .scan-manual.qr-zoekrij .scan-zoekrij { flex-wrap: wrap; }
  .qr-veldmaat { flex: 1 1 100%; }
  .qr-maat { padding: 0; }
  .scan-manual.qr-zoekrij #scan-lookup { flex: 1 1 auto; justify-content: center; }
}

/* Launchpad-toggle (tpill) op de navy balk: transparant met witte iconen */
.lp-top .tpill { background: transparent !important; border: 1px solid rgba(255,255,255,.25) !important; color: #fff !important; }
.lp-top .tpill:hover { background: rgba(255,255,255,.12) !important; }
.lp-top .tpill svg { color: #fff !important; stroke: #fff !important; }
.lp-top .tpill span, .lp-top .tpill i { background: rgba(255,255,255,.22) !important; color: #fff !important; }


/* ── Launchpad-balk exact even hoog als de app-topbar (logo verspringt niet) ── */
.app-topbar { min-height: 54px; box-sizing: border-box; }
.lp-top { padding: 8px 14px !important; min-height: 54px; box-sizing: border-box; }
.lp-top .theme-seg { background: transparent !important; border: 1px solid rgba(255,255,255,.22) !important; margin-right: 6px; }
.lp-top .theme-seg-btn { color: rgba(255,255,255,.75) !important; background: transparent !important; }
.lp-top .theme-seg-btn.is-active { color: #fff !important; background: rgba(255,255,255,.18) !important; }

/* ── Profiel-menu (voorstel 7 jul) ── */
#profiel-modal { z-index: 75 !important; }
.prof-h5 { margin: 12px 8px 4px; font-size: calc(9.5px * var(--type-scale, 1.2)); color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em; }
.prof-rij { display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px; border: none; background: none; border-radius: 10px; font: inherit; font-size: calc(11.5px * var(--type-scale, 1.2)); color: var(--text); cursor: pointer; text-align: left; }
.prof-rij:hover { background: var(--panel-2, var(--hover)); }
.prof-rij-stil { cursor: default; }
.prof-rij-stil:hover { background: none; }
.prof-ico { width: 28px; height: 28px; border-radius: 8px; background: var(--panel-2, var(--hover)); border: 1px solid var(--border); display: grid; place-items: center; color: var(--text-muted); flex: none; }
.prof-chev { margin-left: auto; color: var(--text-muted); }
.prof-badge-aan { margin-left: auto; color: var(--success, #059669); background: var(--success-soft, #ecfdf5); padding: 2px 8px; border-radius: 99px; font-size: calc(9.5px * var(--type-scale, 1.2)); font-weight: 600; }
.prof-mini-seg { margin-left: auto; display: flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.prof-mini-seg button { border: none; background: var(--panel); padding: 4px 10px; font: inherit; font-size: calc(10.5px * var(--type-scale, 1.2)); cursor: pointer; color: var(--text-muted); }
.prof-mini-seg button.on { background: #2F4157; color: #fff; }
.prof-voet { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--border); }
.prof-rij-uit { color: var(--danger, #DC2626); }
.prof-rij-uit .prof-ico { color: var(--danger, #DC2626); }
.prof-terug { border: none; background: none; color: var(--text-muted); font: inherit; font-size: calc(11px * var(--type-scale, 1.2)); cursor: pointer; padding: 4px 2px; margin: 2px 0 6px; }
.prof-terug:hover { color: var(--text); }
.prof-gg > div { display: flex; justify-content: space-between; gap: 12px; padding: 8px 2px; border-bottom: 1px solid var(--border); font-size: calc(11.5px * var(--type-scale, 1.2)); }
.prof-gg > div:last-child { border-bottom: none; }
.prof-gg span { color: var(--text-muted); }

/* Sidebar-kaart klikbaar + chevron; losse uitlog-knop weg (zit in de popup) */
.sidebar-foot .sidebar-user.is-klikbaar { cursor: pointer; border: 1px solid var(--border); border-radius: 12px; padding: 8px 10px; transition: border-color .12s, background .12s; }
.sidebar-foot .sidebar-user.is-klikbaar:hover { background: var(--panel-2, var(--hover)); border-color: var(--accent); }
.sidebar-foot .sidebar-user.is-klikbaar::after { content: '›'; color: var(--text-muted); margin-left: auto; }
.sidebar-foot .sidebar-user.is-klikbaar #app-logout { display: none; }

/* Launchpad-profielchip */
.lp-profchip { display: inline-flex; align-items: center; gap: 8px; padding: 4px 12px 4px 5px; border: 1px solid rgba(255,255,255,.25); border-radius: 999px; background: transparent; color: #fff; font: inherit; font-size: 13px; cursor: pointer; }
.lp-profchip:hover { background: rgba(255,255,255,.12); }
.lp-avatar { width: 26px; height: 26px; border-radius: 50%; background: rgba(255,255,255,.2); display: grid; place-items: center; font-weight: 700; font-size: 11px; }
[data-theme="grey"] .lp-profchip { border-color: var(--border); color: var(--text); }
[data-theme="grey"] .lp-avatar { background: var(--panel-2, rgba(255,255,255,.08)); }

/* ═══ Activiteiten-verzoeken 8 jul 2026 (Nick) ═══ */
/* 1. Baan-kop (Baan 1-4) blijft leesbaar boven de scrollende tijdlijn: dekkende
   achtergrond + z-index (was transparent → rijen schoven er zichtbaar doorheen). */
.banen-cell.banen-hed {
  position: sticky; top: 0; z-index: 4;
  background: var(--panel) !important;
  box-shadow: 0 1px 0 var(--border);
}
/* 2. Tijdvak-geselecteerd: dialoog ONDERAAN op een gedimde tijdlijn.
   Nick 1 aug 2026: "niet blurren maar gewoon shaden, en de popup beneden i.p.v.
   in het midden, maar wel de knoppen even groot". Dit blok vervángt de vorige
   twee generaties (gecentreerde blur-popup én de zwevende .act-boek-balk) —
   er hoort er maar één in dit bestand te staan.
   Dimmen boven blurren: de tijdlijn blijft scherp na te kijken, de laag vangt
   wél de klikken (dát is het verschil met de balk, die over een volledig
   aanklikbare tijdlijn zweefde), en backdrop-filter is duur op zwakke hardware. */
/* SHADCN-VORM, 9 aug 2026 — dezelfde grammatica als de nieuwe boek-la, die
   sinds vandaag de standaard is (`boeklaModus()` in app.js). Dit scherm is
   geen React en krijgt er ook geen build bij: de vorm is met de bestaande
   tokens nagebouwd.

   DE TOKENS ZIJN NIET OVERGESCHREVEN MAAR DOORVERWEZEN. boekla.css zet zijn
   shadcn-tokens op `#bkfla-root`; deze popup hangt aan <body> en staat daar
   dus buiten. theme.css draagt sinds de square-ui-remap byte-gelijke waarden,
   dus verwijst dit blok gewoon door:

     --panel      → --card        light oklch(1 0 0)     · dark oklch(.205 0 0)
     --border     → --border      light oklch(.922 0 0)  · dark oklch(1 0 0/.1)
     --surface    → --secondary   light oklch(.97 0 0)   · dark oklch(.269 0 0)
     --text       → --card-foreground
     --text-muted → --muted-foreground
     --radius     → --radius      .625rem, in beide bestanden

   Alleen wat theme.css NIET gelijk heeft staat hieronder letterlijk: primary
   (de la gebruikt merk-navy #2F4157 / steel-licht #7A9EB1, níét het
   accent-blauw van de backoffice), primary-foreground, secondary-foreground
   en ring. Zo dragen de twee schermen dezelfde knop, dezelfde kaart en
   dezelfde chip — meetbaar, zie verify-boekbar-shadcn.cjs.

   Wat NIET meekomt uit de la: `--type-scale` (1.2) wordt hier bewust NIET
   toegepast. De la rekent in absolute rem (text-xs 12 / text-sm 14 /
   text-base 16); een popup die daar 1,2× overheen zet, staat er naast. */
.act-boek-ov {
  position: fixed; inset: 0; z-index: 120;
  background: rgba(15, 23, 32, .46);
  display: grid; align-items: end; justify-items: center; padding: 20px;
  animation: abk-ov-in .16s ease-out;
  --abk-primary: #2F4157;
  --abk-primary-fg: oklch(0.985 0 0);
  --abk-secondary-fg: oklch(0.205 0 0);
  --abk-ring: #577C8E;
}
[data-theme="grey"] .act-boek-ov {
  background: rgba(0, 0, 0, .58);
  --abk-primary: #7A9EB1;
  --abk-primary-fg: oklch(0.145 0 0);
  --abk-secondary-fg: oklch(0.985 0 0);
  --abk-ring: #7A9EB1;
}
/* Card: rounded-xl (var(--radius)+4 = 14px), 1px --border, bg --card,
   padding als px-6/py-6, shadow-lg. */
.act-boek-pop {
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 4px);
  padding: 24px; width: min(420px, 100%); box-sizing: border-box;
  box-shadow: 0 10px 15px -3px rgba(0,0,0,.10), 0 4px 6px -4px rgba(0,0,0,.10);
  text-align: left; font-family: var(--font);
  animation: abk-pop-in .22s cubic-bezier(.2,.7,.2,1);
}
@keyframes abk-ov-in { from { opacity: 0; } to { opacity: 1; } }
/* Komt van onderen op — dezelfde kant als waar hij landt. */
@keyframes abk-pop-in { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .act-boek-ov, .act-boek-pop { animation: none; } }
/* text-xs + tracking-widest + muted-foreground — de eyebrow van de la. */
.act-boek-pop .abk-eyebrow { display: flex; align-items: center; gap: 6px; margin: 0 0 6px;
  font-size: 12px; line-height: 1.3333; font-weight: 500; text-transform: uppercase;
  letter-spacing: .1em; color: var(--text-muted); }
/* CardTitle: text-base, font-semibold, tracking-tight, leading-tight. */
.act-boek-pop .abk-titel { margin: 0 0 4px; font-size: 16px; line-height: 1.25;
  font-weight: 600; letter-spacing: -.025em; color: var(--text); }
/* De tijd is hier geen bijschrift maar het onderwerp van de dialoog, dus
   text-sm in de VOORGRONDkleur — niet muted zoals een CardDescription. */
.act-boek-pop .abk-wanneer { margin: 0 0 14px; font-size: 14px; line-height: 1.4286;
  color: var(--text); font-variant-numeric: tabular-nums; }
/* Badge `secondary`: rounded-full, px-2 py-0.5, text-xs, font-medium,
   border transparent, bg --secondary, kleur --secondary-foreground. */
.act-boek-pop .abk-feiten { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 16px; }
.act-boek-pop .abk-feit {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  width: fit-content; flex: none; overflow: hidden; white-space: nowrap;
  border: 1px solid transparent; border-radius: 9999px; padding: 2px 8px;
  font-size: 12px; line-height: 1.3333; font-weight: 500;
  background: var(--surface); color: var(--abk-secondary-fg);
  font-variant-numeric: tabular-nums;
}
/* Walk-in is een andere handeling, dus een eigen blok — geen woordwissel in een
   subregel maar een amber waarschuwing die uitlegt wát er anders is.
   Vorm van shadcn Alert: rounded-lg (var(--radius)), px-4 py-3, text-sm. */
.act-boek-pop .abk-let { display: flex; gap: 10px; align-items: flex-start; margin: 0 0 14px;
  border: 1px solid color-mix(in oklch, var(--warning) 30%, transparent);
  background: var(--warning-soft); border-radius: var(--radius); padding: 12px 16px;
  font-size: 14px; line-height: 1.4286; color: var(--text); }
.act-boek-pop .abk-let svg { flex: none; color: var(--warning); margin-top: 2px; }
.act-boek-pop .abk-let b { font-weight: 500; display: block; }
/* Voet van de la: `flex gap-2` met twee knoppen op `flex-1`. Hier een grid met
   auto-fit i.p.v. flex, om één reden die de la niet heeft: "Registreer als
   walk-in →" is bijna drie keer zo lang als "Boeken →", en met auto-fit +
   minmax stapelen ze vanzelf zodra twee kolommen niet meer passen — dan zijn
   ze allebei volle breedte, dus nog steeds even groot. gap-2 = 8px, als in de la. */
.act-boek-pop .abk-acts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px; }
/* Button, size `default`: h-9 (36px), rounded-md (var(--radius)-2 = 8px),
   px-4 py-2, text-sm, font-medium, gap-2. `min-height` in plaats van `height`
   omdat het walk-in-label mag afbreken; bij één regel meet dat exact 36px.
   Daarvoor staat de regelhoogte op 1.25 en niet op de 1.4286 van text-sm:
   met een vaste `height` (zoals h-9 in de la) mag de inhoud overlopen, met
   `min-height` groeit de knop mee — 20px regel + 16px padding + 2px rand is
   38px, en dan staat hij 2px naast de la. 17,5px regel landt precies op 36.
   Op aanraakschermen 44px — dezelfde afwijking en dezelfde haak als in de la
   (`@media (pointer: coarse)`, niet op schermbreedte: een iPad in liggende
   stand is 1024px breed en wordt met de vinger bediend). */
.act-boek-pop .abk-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 36px; width: 100%; box-sizing: border-box;
  border-radius: calc(var(--radius) - 2px); padding: 8px 16px;
  font-family: inherit; font-size: 14px; line-height: 1.25; font-weight: 500;
  cursor: pointer; text-align: center;
  border: 1px solid var(--border); background: var(--panel); color: var(--text);
  box-shadow: 0 1px 2px 0 rgba(0,0,0,.05);
  transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s;
}
@media (pointer: coarse) { .act-boek-pop .abk-btn { min-height: 44px; } }
/* Het lange walk-in-label als ÉÉN flex-item. Zonder deze buitenste span zijn
   het er twee — de losse tekst en de nowrap-span — en dan zet de knop ze naast
   elkaar met de gap ertussen ("Registreer als   walk-in →"). Binnen één item
   geldt gewone regelval, en houdt de binnenste span "walk-in →" bijeen. */
.act-boek-pop .abk-btn .abk-lbl { display: inline; }
.act-boek-pop .abk-btn .abk-nowrap { white-space: nowrap; }
/* Outline-knop in het donker: shadcn zet daar `dark:bg-input/30` +
   `dark:border-input` — anders valt hij samen met de kaart. */
[data-theme="grey"] .act-boek-pop .abk-btn { background: oklch(1 0 0 / .045); border-color: oklch(1 0 0 / .15); }
.act-boek-pop .abk-btn:hover { background: var(--surface); }
[data-theme="grey"] .act-boek-pop .abk-btn:hover { background: oklch(1 0 0 / .075); }
.act-boek-pop .abk-btn:focus-visible { outline: none; border-color: var(--abk-ring);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--abk-ring) 50%, transparent); }
.act-boek-pop .abk-btn.is-primair,
[data-theme="grey"] .act-boek-pop .abk-btn.is-primair {
  background: var(--abk-primary); border-color: var(--abk-primary);
  color: var(--abk-primary-fg); box-shadow: none;
}
.act-boek-pop .abk-btn.is-primair:hover,
[data-theme="grey"] .act-boek-pop .abk-btn.is-primair:hover {
  background: color-mix(in oklab, var(--abk-primary) 90%, transparent);
  border-color: color-mix(in oklab, var(--abk-primary) 90%, transparent);
}
/* Smal scherm: volwaardig bottom-sheet, vastgeplakt aan de onderrand.
   De veilige onderrand loopt via een var-haak met env() als terugval. Reden:
   in een emulator is env(safe-area-inset-bottom) altijd 0px, dus of de term
   meedoet in de GEBRUIKTE waarde is daar niet te zien. Met deze haak kan een
   meter er een echte waarde in schuiven en zien dat de padding meegroeit; op
   een toestel blijft het gedrag exact hetzelfde, want --abk-veilig is nergens
   gezet en de fallback wint. */
@media (max-width: 520px) {
  .act-boek-ov { padding: 0; }
  .act-boek-pop { width: 100%;
    border-radius: calc(var(--radius) + 4px) calc(var(--radius) + 4px) 0 0;
    border-bottom: 0;
    padding-bottom: calc(24px + var(--abk-veilig, env(safe-area-inset-bottom, 0px))); }
}
/* 3. Activiteit-instellingen als modal (tandwiel; admin-only). */
.actset-ov {
  position: fixed; inset: 0; z-index: 70;
  background: rgba(15, 23, 32, .38);
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.actset-kaart {
  background: var(--bg); border: 1px solid var(--border-strong); border-radius: 16px;
  width: min(680px, 94vw); max-height: 88vh; display: flex; flex-direction: column;
  box-shadow: 0 18px 50px rgba(0,0,0,.28); overflow: hidden;
}
.actset-kop { display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px; border-bottom: 1px solid var(--border); }
.actset-kop h3 { margin: 0; font-size: 15px; }
.actset-body { overflow: auto; padding: 16px 18px; }
.actset-body .beheer-detail { max-width: none; }
/* 4. Nieuwe-boeking-popup: nette invulvelden (zoals de login) + geen zijwaarts scrollen. */
.bkflow .field input, .bkflow .field select {
  padding: 9px 12px !important; font-size: 13.5px !important; box-sizing: border-box;
  width: 100% !important; min-width: 0 !important;
}
.bkflow .field input::placeholder { font-size: 13px; color: var(--text-faint); }
.bkflow-scroll { overflow-x: clip !important; }
.bkflow .field.fl-float > span { max-width: calc(100% - 24px); }
.bkflow .field-row { min-width: 0; display: flex; }
.bkflow .field-row > .field { flex: 1 1 0; }
.bkflow .field { min-width: 0; }
/* 5. "Alle modules"-terugknop uit de zijbalk (de app-switcher in de topbar is de terugweg). */
.nav-back { display: none !important; }
/* 6. Onderste zijbalk-item niet meer half buiten beeld. */
#module-nav { padding-bottom: 28px !important; }
.app-sidebar { overflow-y: auto !important; }
/* Datum-kiezer in de databalk: lichter vlak in het grijze thema (stond erg donker). */
html[data-theme="grey"] .act-databalk .iselcal-trigger,
[data-theme="grey"] .act-databalk .iselcal-trigger {
  background: var(--surface) !important;
  border-color: var(--border-strong) !important;
}

/* ── Kortingen-module (16 jul 2026): scope-chips + gast-code-resultaat ── */
.k-scope-veld{ grid-column:1/-1; display:flex; flex-direction:column; gap:6px; }
.k-scope-veld > span{ font-size:12px; font-weight:600; color:var(--muted); }
.k-scope-wrap{ display:flex; flex-wrap:wrap; gap:8px; }
.k-scope-chip{ display:inline-flex; align-items:center; gap:7px; padding:7px 12px;
  background:var(--surface); border:1px solid var(--border); border-radius:11px;
  font-size:13px; cursor:pointer; user-select:none; }
.k-scope-chip input{ accent-color:var(--accent); margin:0; }
.k-scope-chip:has(input:checked){ background:var(--panel); border-color:var(--accent);
  box-shadow:0 1px 4px rgba(15,25,40,.08); }
.k-gast-resultaat{ display:flex; flex-direction:column; gap:8px; align-items:flex-start; }
.k-gast-code{ font-family:ui-monospace,'SF Mono',Menlo,monospace; font-size:28px;
  font-weight:700; letter-spacing:.06em; color:var(--tekst);
  background:var(--surface); border:1.5px dashed var(--border); border-radius:12px;
  padding:12px 20px; }
.k-gast-sub{ font-size:13px; color:var(--muted); }
/* Kortingscode-veld in de nieuwe-boeking-sidebar */
.bkf-korting-veld{ display:flex; flex-direction:column; gap:6px; margin:2px 0 8px; }
.bkf-korting-rij{ display:flex; gap:8px; }
.bkf-korting-rij input{ flex:1 1 auto; min-width:0; text-transform:uppercase; }
.bkf-korting-status{ font-size:12.5px; color:var(--muted); }
.bkf-korting-status.is-ok{ color:var(--success,#059669); }
.bkf-korting-status.is-fout{ color:var(--danger,#DC2626); }

/* Detailpaneel geld-blok (review punt 3) */
.scan-row.bd-korting strong{ color:var(--accent); }
.scan-row.bd-link{ cursor:pointer; }
.scan-row.bd-link strong{ color:var(--accent); }
.scan-row.bd-link:hover strong{ text-decoration:underline; }
/* Sidebar prijsindicatie (review punt 4) */
.bkf-prijs{ display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; padding:10px 13px;
  background:var(--accent-soft, #EAF0F4); border:1px solid rgba(70,103,124,.25); border-radius:11px; margin-bottom:10px; }
.bkf-prijs span{ font-size:12px; font-weight:600; color:var(--text-muted); }
.bkf-prijs b{ font-size:16px; }
.bkf-prijs small{ flex-basis:100%; font-size:11.5px; color:var(--text-muted); }
/* In-modal annuleerstap (review punt 7) */
#bd-annuleer{ position:absolute; inset:0; background:var(--panel); z-index:5; border-radius:inherit;
  display:flex; align-items:flex-start; justify-content:center; overflow:auto; }
/* ══ ANNULEERKAART ══════════════════════════════════════════════════════
   Eén kolom, één ritme. De kaart bestaat uit blokken die allemaal even breed
   zijn en dezelfde afstand houden; alleen het "Let op" en de context krijgen
   een eigen vlak omdat ze gelezen moeten worden vóór er geklikt wordt.

   `.field` in deze kaart is expliciet een kolom: de app-brede .field-regels
   (r344) stylen alleen het label en het veld, niet de container — zonder dit
   staat elk label naast zijn invoerveld in plaats van erboven. */
.bd-ann-kaart{ width:100%; max-width:460px; padding:24px 22px 20px; display:flex; flex-direction:column; gap:14px;
  box-sizing:border-box; }
/* box-sizing hierboven is niet cosmetisch: zonder border-box telt de padding
   bij de max-width op en wordt de kaart 504px in plaats van 460px — dan steken
   het "Let op"-blok en de invoervelden rechts buiten het venster. De backoffice
   zet box-sizing niet globaal, dus elk los paneel moet het zelf doen. */
.bd-ann-kaart *, .bd-ann-kaart *::before, .bd-ann-kaart *::after{ box-sizing:border-box; }
.bd-ann-kaart h3{ margin:0; font-size:16.5px; font-weight:700; letter-spacing:-.01em; }

.bd-ann-kaart .field{ display:flex; flex-direction:column; gap:6px; margin:0; }
.bd-ann-kaart .field > span{ font-weight:600 !important; }
.bd-ann-kaart .field > input,
.bd-ann-kaart .field > textarea{ width:100%; box-sizing:border-box; padding:9px 11px; }
.bd-ann-kaart .field > textarea{ resize:vertical; min-height:62px; line-height:1.5; }
.bd-ann-kaart .field > small{ color:var(--text-muted); font-size:12px; line-height:1.5; }

/* De context: waar gaat dit over, en wat is er betaald. */
.bd-ann-context{ background:var(--surface-2); border:1px solid var(--border); border-radius:10px;
  padding:12px 14px; font-size:13px; line-height:1.6; margin:0; color:var(--text); }

/* Mail-vinkje en de rij "geen mailadres bekend" delen één vorm. */
.bd-ann-mail{ display:flex; gap:10px; align-items:flex-start; font-size:13.5px; margin:0; cursor:pointer; line-height:1.45; }
.bd-ann-mail input{ width:18px; height:18px; margin:1px 0 0; accent-color:var(--accent); flex:none; }
.bd-ann-mail small{ display:block; color:var(--text-muted); margin-top:1px; }
.bd-ann-geenmail{ font-size:12.5px; color:var(--text-muted); margin:0; }

/* Wanneer annuleerde de gast — een veld dat je meestal leeg laat, dus rustig. */
.bd-ann-moment > span small{ font-weight:400; color:var(--text-muted); }
.bd-ann-moment input{ max-width:250px; }

/* "Let op": groen als er geld terug gaat, oranje als er niets terug gaat. Dat
   laatste is het geval waar een gesprek met de gast uit volgt. */
.bd-ann-letop{ border-radius:10px; padding:12px 14px; font-size:13px; line-height:1.6; margin:0; }
.bd-ann-letop b{ display:block; font-size:13.5px; margin-bottom:3px; }
.bd-ann-letop span{ display:block; color:var(--text-muted); }
.bd-ann-letop i{ font-style:normal; opacity:.85; }
.bd-ann-letop.terug{ background:rgba(5,150,105,.09); border:1px solid rgba(5,150,105,.32); }
.bd-ann-letop.terug b{ color:#047857; }
.bd-ann-letop.niets{ background:rgba(217,119,6,.1); border:1px solid rgba(217,119,6,.38); }
.bd-ann-letop.niets b{ color:#B45309; }

/* Waaruit bestaat de reservering, en wat gaat eraf? */
.bd-ann-res{ border:1px solid var(--border); border-radius:10px; padding:13px 14px; background:var(--surface-2);
  display:flex; flex-direction:column; gap:2px; }
.bd-ann-res-kop{ margin:0 0 8px; font-size:13px; line-height:1.5; }
.bd-ann-keuze{ display:flex; gap:10px; align-items:flex-start; font-size:13.5px; padding:5px 0; cursor:pointer; line-height:1.4; }
.bd-ann-keuze input{ width:18px; height:18px; margin:1px 0 0; accent-color:var(--accent); flex:none; }
.bd-ann-keuze small{ display:block; color:var(--text-muted); font-size:12px; margin-top:2px; }
.bd-ann-eenheden{ margin:8px 0 0 28px; padding-top:10px; border-top:1px solid var(--border);
  display:flex; flex-direction:column; gap:8px; }
.bd-ann-eenheid{ display:flex; gap:10px; align-items:center; font-size:13px; cursor:pointer; }
.bd-ann-eenheid input{ width:17px; height:17px; margin:0; accent-color:var(--accent); flex:none; }
.bd-ann-eenheid small{ color:var(--text-muted); }
.bd-ann-pers{ margin-top:4px; }
.bd-ann-pers input{ max-width:120px; }

/* De knoppenrij sluit de kaart af; de gevaarlijke knop staat rechts. */
.bd-ann-acties{ display:flex; justify-content:space-between; align-items:center; gap:12px;
  margin-top:2px; padding-top:14px; border-top:1px solid var(--border); }

/* ── In-modal verschil-afhandeling (Nick 18 jul): betaallink/pin/contant ── */
#bd-verschil{ position:absolute; inset:0; background:var(--panel); z-index:6; border-radius:inherit;
  display:flex; align-items:flex-start; justify-content:center; overflow:auto; }
.bd-vs-context{ background:var(--accent-soft, #EAF0F4); border:1px solid rgba(70,103,124,.25); border-radius:11px;
  padding:11px 13px; font-size:13px; line-height:1.5; margin-bottom:14px; }
.bd-vs-opties{ display:flex; flex-direction:column; gap:9px; }
.bd-vs-opties .bd-vs-btn{ width:100%; justify-content:center; }
/* Openstaand-verschil-rij in het geld-blok: valt op als actiepunt.
   !important nodig: regel 2342 zet .scan-row strong met !important op --text. */
.scan-row.bd-openstaand strong{ color:var(--warning, #D97706) !important; }

/* ── Groepskoppeling (PROMPT-groepskoppeling.md): kandidatenlijst +
   personen-bevestiging + loskoppelen. Zelfde in-modal-paneel-patroon als
   #bd-annuleer/#bd-verschil (eigen z-index erboven). ── */
#bd-koppel-paneel, #bd-ontkoppel-paneel{ position:absolute; inset:0; background:var(--panel); z-index:7;
  border-radius:inherit; display:flex; align-items:flex-start; justify-content:center; overflow:auto; }
.bd-kand-lijst{ display:flex; flex-direction:column; gap:8px; max-height:280px; overflow:auto; margin-bottom:4px; }
/* `color` staat er expliciet bij: een <button> erft de tekstkleur niet, die
   valt terug op de systeemkleur `buttontext` (zwart). In het lichte thema
   viel dat niet op, in het grijze thema werd de naam zwart-op-donker en dus
   onleesbaar. Raakt ook de groepskoppeling-kandidatenlijst, die dezelfde
   klasse gebruikt. */
.bd-kand-item{ display:flex; flex-direction:column; gap:2px; width:100%; text-align:left;
  border:1px solid var(--border); background:var(--panel); border-radius:11px; padding:9px 12px;
  font:inherit; color:var(--text); cursor:pointer; }
.bd-kand-item:hover{ background:var(--surface); }
.bd-kand-item strong{ font-size:13.5px; }
.bd-kand-item span{ font-size:12px; color:var(--text-muted); }
.bd-kand-item.is-gekozen{ border-color:var(--accent); background:var(--accent-soft, #EAF0F4); }
.bd-kand-leeg{ font-size:13px; color:var(--text-muted); padding:8px 2px; }

/* ── Upgraden van een verhuurboeking (Nick 1 aug 2026): dezelfde kaart en
   dezelfde keuzelijst als de groepskoppeling, met één toevoeging — een
   bezette of te kleine eenheid blijft ZICHTBAAR maar is niet te kiezen.
   Weglaten zou de balie laten zoeken naar een boot die er wél is; grijs met
   reden erbij vertelt meteen waarom 't niet kan. ── */
#bd-upgrade-paneel{ position:absolute; inset:0; background:var(--panel); z-index:7;
  border-radius:inherit; display:flex; align-items:flex-start; justify-content:center; overflow:auto; }
/* Niet-kiesbaar, maar wél leesbaar. Geen `opacity` als dim-truc: die dooft
   óók de reden ("Al verhuurd in deze periode") en juist die moet de balie
   kunnen lezen — met opacity .55 kwam die regel in het grijze thema op
   2,9:1 uit. Nu doet de streepjesrand + het vlakke vlak het signaal, en
   houden beide tekstregels hun volle contrast. */
.bd-kand-item:disabled{ cursor:not-allowed; background:var(--surface); border-style:dashed; }
.bd-kand-item:disabled strong{ color:var(--text-muted); }
.bd-kand-item:disabled:hover{ background:var(--surface); }
/* De keuzelijst erft 280px van de groepskoppeling, waar hooguit een handvol
   kandidaten in staat. Bij FIETSEN zijn het er vijftien — tien damesfietsen
   (zelfde prijs, dus bovenaan) en dán pas de e-bikes. Juist die e-bike is de
   wissel waar FB-1005 om vraagt, en die stond onder de vouw terwijl er onder de
   kaart ~500px leeg bleef: het paneel is `inset:0` en dus zo hoog als de lade.
   Alleen hier ruimer, niet in de gedeelde klasse. */
#bd-upgrade-paneel .bd-kand-lijst{ max-height:min(52vh, 460px); }
/* Kopjes boven de drie groepen (ander product / zelfde soort / kan niet). Klein
   en rustig: ze ordenen de lijst, ze zijn zelf niet het nieuws. */
.bd-kand-kop{ font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.06em;
  color:var(--text-faint); margin:4px 0 -2px; }
.bd-kand-kop:first-child{ margin-top:0; }
.bd-upg-mail{ display:flex; align-items:center; gap:8px; font-size:12.5px; color:var(--text-muted);
  margin:10px 0 2px; cursor:pointer; }
.bd-upg-mail input[disabled]{ cursor:not-allowed; }
.bd-upg-mail:has(input[disabled]){ cursor:default; }

/* De inline actiebalk (.act-boek-balk, review punt 5) is 1 aug 2026 vervangen
   door de gedimde dialoog onderaan — zie .act-boek-ov / .act-boek-pop hierboven.
   Bewust niet ernaast laten staan: er stonden al twee generaties van dit ene
   component in dit bestand. */

/* ── Cel-legenda: de vlakjes zíjn de echte celstijlen (kan niet meer liegen) ── */
#act-legenda{ display:flex; gap:13px; flex-wrap:wrap; align-items:center; margin-left:auto;
  font-size:11.5px; color:var(--text-muted); }
#act-legenda .lg{ display:inline-flex; align-items:center; gap:6px; }
#act-legenda .lg i{ width:15px; height:13px; border-radius:4px; display:inline-block; }
#act-legenda .lg-chip i{ background:var(--chip); }
#act-legenda .lg-vrij i{ border:1px solid var(--border-strong); background:var(--panel); }
#act-legenda .lg-blok i{ background:var(--warning-soft); border:1px solid color-mix(in srgb, var(--warning) 30%, var(--border)); box-shadow:inset 3px 0 0 var(--warning); }
#act-legenda .lg-af i{ background:var(--af); }
#act-legenda .lg-hold i{ border:1.5px dashed var(--chip); background:var(--panel); }
/* Verstreken cellen in het klassieke blokkade-grid: gedimd, geen arcering meer
   (het streep-patroon is voortaan gereserveerd voor geblokkeerd). */
.banen-cell.is-verleden{ color:var(--text-faint) !important; border-color:transparent !important; opacity:.5; }

/* ── Drag-hint bowling (review punt 17): op de nieuwe chip ── */
.nv-chip.is-sleepbaar:hover::after{ content:'⋮⋮'; position:absolute; right:5px; top:50%;
  transform:translateY(-50%); font-size:11px; letter-spacing:-2px; color:var(--chip-tekst); opacity:.7; pointer-events:none; }

/* Link-knop in de activiteit-instellingen naar de Openingstijden-module (punt 14). */
.as-link{ background:none; border:0; padding:0; font:inherit; font-size:inherit;
  color:var(--accent); text-decoration:underline; cursor:pointer; }
.as-link:hover{ opacity:.8; }

/* Herkomst-regel in de zwemvest-modal (punt 16). */
.zwv-herkomst{ font-size:12.5px; color:var(--text-muted); background:var(--surface);
  border:1px solid var(--border); border-radius:9px; padding:8px 11px; margin:0 0 12px; }
.zwv-herkomst b{ color:var(--text); }

/* ── Polish-bundel (review 17 jul, punt 19) ── */
/* ⑦ De groene dot in élke vrije cel is ruis zodra alles vrij is — de
   omkadering + legenda vertellen "vrij" al; dots uit. */
.ag-slot:not(.geboekt):not(.geblokkeerd):not(.vol):not(.vastgehouden):not(.is-verleden):not(:disabled)::before,
.banen-cell.banen-vrij::before { content: none !important; }
/* ④ Subtiele verversings-flash na datum-wissel: de hele planning fade't kort
   in bij elke re-render, zodat zichtbaar is dat alles ververst is. */
@keyframes act-plan-in { from { opacity: .45; } to { opacity: 1; } }
.act-plan { animation: act-plan-in .3s ease; }
@media (prefers-reduced-motion: reduce) { .act-plan { animation: none; } }
/* ③/㊺ Badge-taal in sectiekoppen: schaars = amber, rustig = stil grijs. */
.act-vrij-badge.is-schaars { background: rgba(217,119,6,.12); color: #B45309; padding: 2px 9px; border-radius: 100px; }
.act-vrij-badge.is-rustig { color: var(--text-faint); font-weight: 500; }
.act-vrij-badge[hidden] { display: none; }
/* ㊴ Zoekveld in de kortingen-kop. */
.k-zoekveld{ margin-left:auto; font:inherit; font-size:12.5px; padding:6px 11px;
  border:1px solid var(--border-strong); border-radius:9px; background:var(--panel);
  color:var(--text); min-width:220px; }
.beheer-section-head{ display:flex; align-items:center; gap:12px; }
/* ㊵ Code-kolom blijft leesbaar bij horizontaal scrollen (kortingen-tabel). */
#beheer-panel-kortingen .beheer-table th:first-child,
#beheer-panel-kortingen .beheer-table td:first-child{
  position:sticky; left:0; background:var(--panel); z-index:1; }

/* De dirty-markering en de kopieerknop van Openingstijden (review 17 jul)
   stonden hier. Vervallen op 15 aug 2026 — beide leven nu in het eiland, als
   Badge en Button. */

/* ── Beheer-review 18 jul: shell-unificatie + puntenlijst ──────────────── */
/* ㉑ Inline bevestiging (vervangt native confirm) */
.bh-confirm { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap;
  background: rgba(217, 119, 6, .08); border: 1px solid rgba(217, 119, 6, .32);
  border-radius: 9px; padding: 5px 10px; font-size: 12px; color: var(--text); }
.bh-confirm-q { font-weight: 600; }
.bh-confirm-ja, .bh-confirm-nee { border: 0; border-radius: 7px; padding: 4px 10px;
  font: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer; }
.bh-confirm-ja { background: var(--accent); color: #fff; }
.bh-confirm-nee { background: transparent; color: var(--text-muted); border: 1px solid var(--border); }

/* ④ Legacy-rol-badge */
.gb-legacy { display: inline-block; font-size: 10px; font-weight: 700; letter-spacing: .02em;
  background: rgba(217, 119, 6, .12); color: #B45309; border: 1px solid rgba(217, 119, 6, .3);
  border-radius: 100px; padding: 2px 8px; margin-right: 6px; vertical-align: middle; cursor: help; }

/* ⑤ Welkomstmail-knop (was kaal vinkje) */
.gb-email-save { border: 1px solid var(--border); background: var(--surface); color: var(--text);
  border-radius: 7px; padding: 5px 9px; font: inherit; font-size: 11.5px; font-weight: 600;
  cursor: pointer; white-space: nowrap; }
.gb-email-save:hover { border-color: var(--accent); color: var(--accent); }

/* ⑥ Wachtwoordveld met oog-toggle */
.gb-pwveld { position: relative; }
.gb-pwveld .gb-oog { position: absolute; right: 8px; bottom: 7px; border: 0; background: none;
  cursor: pointer; font-size: 14px; opacity: .55; padding: 2px 4px; }
.gb-pwveld .gb-oog:hover { opacity: 1; }
.gb-pwveld input { padding-right: 34px; }

/* ⑧ Zoek/filter-balk gebruikerslijst */
.gb-filterbar { display: flex; gap: 10px; align-items: center; margin: 4px 0 12px; flex-wrap: wrap; }
.gb-filterbar input[type="search"] { flex: 1; min-width: 220px; max-width: 380px;
  padding: 8px 11px; border: 1px solid var(--border); border-radius: 9px; font: inherit;
  color: var(--text); background: var(--card); }
.gb-filterbar select { padding: 8px 11px; border: 1px solid var(--border); border-radius: 9px;
  font: inherit; color: var(--text); background: var(--card); }

/* ⑩ Live mailvoorbeeld */
.ml-preview-blok { margin: 4px 0 12px; }
.ml-preview-subject { font-size: 12.5px; color: var(--text-muted); margin: 6px 0; }
.ml-preview { width: 100%; height: 420px; border: 1px solid var(--border); border-radius: 10px;
  background: #fff; }

/* ⑭ Weektabel: uit-staande van/tot-velden dimmen */
.beheer-week-table input:disabled { opacity: .45; background: var(--surface); }

/* ⑯ Dirty-badge activiteit-detail */
.bh-dirty-badge { display: inline-block; font-size: 10.5px; font-weight: 700; color: #B45309;
  background: rgba(217, 119, 6, .12); border: 1px solid rgba(217, 119, 6, .3);
  border-radius: 100px; padding: 3px 10px; margin-right: 10px; }

/* ⑱ Verplicht-markering */
.veld-verplicht { color: var(--danger, #DC2626); font-weight: 700; }

/* ══ Zijbalk v2 — CRM-model (Geist + Lucide), 19 jul 2026 ══
   Actief in de lp-grouped-stand (module-context). De sectie-labels (.zb-label)
   en sub-items (.zb-sub) worden door renderZijbalkV2 in app.js gegenereerd. */
#module-nav.lp-grouped { padding: 6px 8px 14px; }
#module-nav.lp-grouped .nav-back {
  /* !important: een ouder restaurant-template-blok (r~4577) verbergt .nav-back
     globaal met !important — in de v2-schil is de terugweg juist vast onderdeel. */
  display: flex !important;
  font: 500 12px var(--font); color: var(--text-muted);
  gap: 7px; padding: 7px 10px; border-radius: 8px;
  border: 0; background: none; margin: 0 0 2px;
}
#module-nav.lp-grouped .nav-back:hover { background: var(--hover); color: var(--text); }
#module-nav.lp-grouped .nav-module-titel {
  padding: 2px 10px 12px; margin-bottom: 6px;
  border-bottom: 1px solid var(--border);
  font: 600 14.5px var(--font); letter-spacing: -0.015em;
}
#module-nav.lp-grouped .nav-module-titel small {
  display: block; font: 400 11.5px var(--font); color: var(--text-faint);
  margin-top: 1px; text-transform: none; letter-spacing: 0;
}
/* Sectie-labels: Geist Mono, caps — zichtbaar in de groepsstand. */
#module-nav.lp-grouped .zb-label {
  display: block;
  font: 500 9.5px var(--font-mono, ui-monospace, monospace);
  text-transform: uppercase; letter-spacing: 0.11em;
  color: var(--text-faint); padding: 14px 10px 5px;
}
/* Module-knoppen als CRM-items: pill, icoon gedempt. */
#module-nav.lp-grouped .module-btn {
  border-radius: 8px; padding: 7px 10px; gap: 10px;
  font: 450 13px var(--font);
}
#module-nav.lp-grouped .module-btn .module-ico,
#module-nav.lp-grouped .zb-ico {
  width: 15px; height: 15px; stroke-width: 1.8;
  color: var(--text-faint); stroke: currentColor; fill: none;
  stroke-linecap: round; stroke-linejoin: round; flex: none;
}
#module-nav.lp-grouped .module-btn.is-active {
  background: var(--accent-soft); color: var(--accent);
  font-weight: 600; border-radius: 8px;
}
#module-nav.lp-grouped .module-btn.is-active .module-ico { color: var(--accent) !important; }
/* Sub-navigatie (jachthaven/kamers/logboek/openingstijden). */
.zb-sub { display: flex; flex-direction: column; gap: 1px; margin: 0 0 4px; }
.zb-item {
  display: flex; align-items: center; gap: 10px;
  padding: 6.5px 10px 6.5px 12px; border: 0; background: none; cursor: pointer;
  border-radius: 8px; text-align: left;
  font: 450 13px var(--font); color: var(--text);
}
.zb-item:hover { background: var(--hover); }
.zb-item.is-on { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.zb-item.is-on .zb-ico { color: var(--accent); }
.zb-item .zb-ico { color: var(--text-faint); }
.zb-item.zb-arch { color: var(--text-faint); font-style: italic; }
/* Teller achter een filter (Feedback, 2 aug 2026): het aantal dat je wilt zien
   zonder te klikken. Tabulaire cijfers, zodat 2 en 12 onder elkaar uitlijnen. */
.zb-item .zb-tel { margin-left: auto; font-size: 11.5px; font-weight: 600;
  color: var(--text-faint); font-variant-numeric: tabular-nums; flex: none; }
.zb-item.is-on .zb-tel { color: var(--accent); }
.zb-item .zb-stip { width: 7px; height: 7px; border-radius: 50%; background: var(--danger);
  display: inline-block; flex: none; margin-left: auto; }
.zb-item .zb-stip + .zb-tel { margin-left: 6px; }
/* Module-knop met sub-navigatie eronder: knop wordt kop-achtig gedempt. */
#module-nav.lp-grouped .module-btn.zb-heeft-sub { display: none; }
/* De horizontale tab-rij verdwijnt zodra de zijbalk 'm vervangt. */
body[data-zb-verberg-subnav="1"] .bo-subnav { display: none !important; }
/* ── De module-eigen kolom wijkt voor de zijbalk (Nick, 10 aug 2026) ────────
   Klacht 1: Beheer, Restaurant, Kassa en Arrangementen toonden de zijbalk én
   hun eigen menukolom. Voor die modules zet `renderZijbalkV2` nu
   `data-zb-verberg-subnav` (net als bij Jachthaven en Kamers); hier wijkt
   Beheers eigen kolom daarvoor. De drie iframe-modules dragen hun kolom ín het
   frame en verbergen 'm daar zelf, op teken van de shell.

   DRIE VOORWAARDEN, en alle drie zijn nodig:
     · `min-width: 768px` — daaronder mount het eiland niet (`zijbalkPast()`);
     · `body.nav-zijbalk`  — die klasse komt er pas NADAT de eilandbundel
       geladen is, dus bij een 404 of `?nav=oud` verandert er geen pixel;
     · `[data-zb-verberg-subnav="1"]` — alleen voor de modules die hun
       navigatie daadwerkelijk aan de zijbalk hebben overgedragen.
   Valt één ervan weg, dan staat `.bh-nav` er gewoon weer: de terugval is
   zichtbare navigatie, nooit een leeg scherm. */
@media (min-width: 768px) {
  body.nav-zijbalk[data-zb-verberg-subnav="1"] .bh-nav { display: none !important; }
}
/* act-subnav (banen) in dezelfde taal: status via bestaande dots/tellers. */
#module-nav.lp-grouped .act-subnav { margin-left: 10px; }
/* VERWIJDERD 19 aug 2026: hier stonden de embed-uitzonderingen die de OUDE
   `.app-sidebar` als kolom terugzetten voor jachthaven/kamers/logboek/
   openingstijden/feedback (`display:flex !important`, 0-3-1 — die wonnen van
   elke kalere verbergregel). Ze bestonden voor de `?nav=oud`-terugval; die
   terugval is verwijderd en de oude kolom mag nooit meer renderen. De
   zijbalk van het eiland is op die schermen de navigatie. */

/* ══════════════════════════════════════════════════════════════════════════
   Activiteiten-module — Nick 30 jul 2026
   1) Kaartkop blijft wit, het contentvlak eronder krijgt het bestaande grijs
      (--surface). De item-kaarten (fietsen/sloepen) en slot-chips blijven wit
      en liggen dus zichtbaar óp dat grijs.
   2) De Lijst/Kaarten-switcher krijgt een 1px donkergrijze rand om de groep.
   3) Eerlijke lege dagweergave: "geen tijden" vs "laden mislukt".
   ══════════════════════════════════════════════════════════════════════════ */

/* 1) Contentvlak grijs, kop wit ------------------------------------------- */
.act-section { background: var(--surface) !important; }
.act-section-head { background: var(--panel) !important; }
/* Vlakken die zelf een (bijna-)witte vulling meebrachten en het grijs anders
   dichtplamuren: laat het sectie-grijs doorschijnen. */
.act-section .rental-bar,
.act-section .rent-type-head,
.act-section .rent-free-note { background: transparent !important; }

/* 1b) Statuskleuren tegen het nieuwe grijs. "Bezet" en "verstreken" hadden een
   lichtgrijze vulling die op een wit vlak nog las, maar op grijs wegvalt — en
   juist die statussen moeten zichtbaar blijven (de dagweergave toont álle
   slots, ook als alles bezet of verstreken is). Bezet volgt de legenda. */
.act-section .banen-cell.banen-vol,
.act-section .ag-slot.vol {
  background: var(--border) !important;
  border: 1px solid var(--border-strong) !important;
  color: var(--text-muted) !important;
  opacity: 1 !important;
}

/* 2) Lijst/Kaarten-switcher: rand om de hele groep ------------------------- */
.rental-viewtog {
  border: 1px solid var(--text-faint);
  background: var(--panel);
}
.rental-viewtog button.on { background: var(--surface); box-shadow: none; }

/* 3) Lege dagweergave ------------------------------------------------------ */
.banen-empty {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 26px 18px !important;
  background: transparent !important;
  border: 1px dashed var(--border-strong) !important;
  border-radius: 10px;
  margin: 12px !important;
  font-family: var(--font) !important;
  text-align: center;
}
.banen-empty b { color: var(--text); font-size: calc(12.5px * var(--type-scale, 1.2)); font-weight: 650; }
.banen-empty span { color: var(--text-muted); font-size: calc(11.5px * var(--type-scale, 1.2)); max-width: 46ch; line-height: 1.45; }
.banen-empty.is-fout { border-color: var(--warning) !important; border-style: solid !important; }
.banen-empty.is-fout b { color: var(--warning); }
.banen-empty-btn {
  margin-top: 4px; padding: 6px 14px; border-radius: 8px;
  border: 1px solid var(--border-strong); background: var(--panel);
  color: var(--text); font: inherit; font-size: calc(11.5px * var(--type-scale, 1.2)); cursor: pointer;
}
.banen-empty-btn:hover { background: var(--hover); }
/* Badge-varianten in de kop + zijbalk-teller. */
.act-vrij-badge.is-fout { color: var(--warning); }
/* Zijbalk-teller: één formaat, met schaarste-nadruk en stille eindedag-status. */
.asn-tel.is-schaars { color: var(--warning); background: var(--warning-soft);
  padding: 1px 8px; border-radius: 100px; font-weight: 650; }
.asn-tel.is-stil { color: var(--text-faint); }

/* ── Boeking-detailpaneel (redesign): kop met statuschip + ⋯-menu,
      knoppenrij die altijd past, één labelsysteem ── */
/* De kop leest van boven naar beneden: code + status, naam, subregel, acties.
   Vier regels bij élke boeking, dus één leespatroon. De handmatige
   margin-right:24px is vervallen — die hield alleen ruimte vrij voor de
   vroeger absoluut gepositioneerde .modal-close, die nu gewoon in de
   acties-kolom staat. Sticky: de kop draagt sinds die verhuizing óók het
   kruisje, dus hij moet in beeld blijven als het paneel scrollt. Bewust
   zonder z-index — de in-modal panelen (#bd-annuleer/#bd-verschil/
   #bd-koppel-paneel, z-index 5-7) moeten eroverheen kunnen liggen. */
.bd-kop { position: sticky; top: 0; margin: -24px -22px 12px; padding: 24px 22px 10px;
  background: var(--panel);
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 10px; align-items: start; }
.bd-kop .modal-title { grid-column: 1; margin: 0 !important; min-width: 0;
  font-size: calc(19px * var(--type-scale, 1.2)) !important; font-weight: 650 !important;
  letter-spacing: -.02em !important; line-height: 1.2; overflow-wrap: anywhere; }
.bd-eyebrow { grid-column: 1; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; min-width: 0; }
/* De code is geen titel meer, maar verdwijnt niet: klein monospace-label boven
   de naam, klikbaar om te kopiëren. De gast noemt 'm aan de telefoon. */
.bd-code { font-family: var(--font-mono, ui-monospace, monospace);
  font-size: calc(10.5px * var(--type-scale, 1.2)); font-weight: 600; letter-spacing: .02em;
  color: var(--text-muted); background: var(--surface); border: 1px solid var(--border);
  border-radius: 5px; padding: 1px 6px; cursor: copy; }
.bd-code:hover { border-color: var(--accent); color: var(--text); }
.bd-code[hidden] { display: none; }
/* Subregel: activiteit · baan(en) · dag · tijd · personen — de vijf dingen
   waarop de balie een boeking herkent, in één leesbare regel. */
.bd-groep-sub { grid-column: 1; font-size: calc(12.5px * var(--type-scale, 1.2));
  color: var(--text-muted); font-variant-numeric: tabular-nums; }
.bd-groep-sub[hidden] { display: none; }
.bd-status-chip { font-size: calc(10.5px * var(--type-scale, 1.2)); font-weight: 650;
  color: var(--success); background: var(--success-soft); border-radius: 100px;
  padding: 2px 9px; white-space: nowrap; line-height: 1.35; }
.bd-status-chip.is-wacht { color: var(--warning); background: var(--warning-soft); }
.bd-status-chip.is-geannuleerd { color: var(--danger); background: var(--danger-soft); }
.bd-status-chip.is-neutraal { color: var(--text-muted); background: var(--surface); border: 1px solid var(--border); }
/* Eén icoonknopvorm voor álle icoonacties in de kop: ⋯ en × delen maat, rand,
   radius, kleur én rasterkolom. Dat verschil (rand+vulling vs. randloos, 26 vs
   30px, radius 6 vs 7) was de kern van "de top is raar gedesignd". */
.bd-acts { grid-column: 2; grid-row: 1 / span 2; position: relative;
  display: flex; gap: 4px; align-items: center; }
.bd-ico { width: 30px; height: 30px; flex: none; display: grid; place-items: center;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-muted);
  border-radius: 8px; cursor: pointer; padding: 0; }
.bd-ico:hover { border-color: var(--text-faint); color: var(--text); }
.bd-ico svg { width: 15px; height: 15px; }
.bd-meer-menu { position: absolute; top: calc(100% + 5px); right: 0; z-index: 30;
  background: var(--panel); border: 1px solid var(--border-strong); border-radius: 11px;
  box-shadow: var(--shadow); padding: 5px; min-width: 214px; text-align: left; }
.bd-meer-menu[hidden] { display: none; }
/* Koppelen en annuleren delen één la; dan moet in elk geval zichtbaar zijn dat
   de onderste van een andere orde is. */
.bd-menu-scheiding { height: 1px; background: var(--border); margin: 4px 6px; }
.bd-menu-item { display: flex; align-items: center; gap: 9px; width: 100%;
  border: 0; background: none; border-radius: 8px; padding: 8px 10px;
  font: inherit; font-size: calc(10.5px * var(--type-scale, 1.2)); color: var(--text);
  cursor: pointer; text-align: left; }
.bd-menu-item:hover { background: var(--surface); }
.bd-menu-item svg { width: 14px; height: 14px; color: var(--text-faint); flex: none; }
.bd-menu-item.is-gevaar, .bd-menu-item.is-gevaar svg { color: var(--danger); }
/* ── DE VOET VAN DE BOEKINGLA — twee zones (voorstel A, Nick 26 aug 2026) ──

   WAAROM ALLES HIER OP #booking-detail-modal STAAT EN NIET OP .bd-actions.
   Lees dit vóór je een regel hieronder "vereenvoudigt" naar klasseniveau: de
   klasse `.modal-footer.bd-actions` wordt GEDEELD met #rest-detail-modal (de
   restaurant-reserveringsdetail, index.html r1199). Die modal heeft een eigen
   indeling en valt buiten dit ontwerp. Zet je deze regels op klasseniveau, dan
   herstructureer je ongemerkt ook die voet. Om diezelfde reden blijven de
   gedeelde regels r976 (.modal-footer.bd-actions { justify-content })
   en r1817 (.bd-idform-btn { margin-right: auto }) ONGEWIJZIGD staan — ze
   gelden nog voor de restaurantmodal; hieronder worden ze alleen voor dít
   paneel overschreven.

   Dit blok VERVANGT de vorige override op deze plek (flex-end + flex-wrap).
   Die won stil van elke nieuwe klasseregel, omdat id+klasse zwaarder weegt —
   laat 'm dus niet terugkomen naast het raster.

   HET PROBLEEM DAT DIT OPLOST: als één afbrekende flexrij niet op één regel
   past, verdeelt de browser de restruimte PER REGEL. Elke knop is zo breed als
   zijn tekst, dus regel 1 en regel 2 kregen andere kolomposities. Welke knoppen
   er staan verschilt per soort boeking, dus het was elke keer anders scheef. */
#booking-detail-modal .modal-footer.bd-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  flex-wrap: nowrap;
  gap: 0;
}
/* ZONE 1 · hulpacties op vaste verticale lijnen. `minmax(0,1fr)` (niet `1fr`)
   laat een cel smaller worden dan zijn inhoud, zodat het label afkapt in
   plaats van de kolom te verbreden. */
#booking-detail-modal #bd-hulpacties {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
/* De "Ander product"-melding krijgt een eigen regel bóven het raster in plaats
   van een rastercel; zonder deze marge plakt hij tegen de eerste knoprij. */
#booking-detail-modal .modal-footer.bd-actions > .bd-foot-noot:not([hidden]) {
  align-self: flex-start;
  margin-bottom: 8px;
}
@media (max-width: 560px) {
  #booking-detail-modal #bd-hulpacties { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Een verborgen knop mag GÉÉN lege cel achterlaten — anders verspringen de
   overblijvers per soort boeking, precies wat dit ontwerp wegneemt. Dit moet
   expliciet: de regel eronder zet `display` op de knoppen, en die zou het
   [hidden]-attribuut anders overstemmen. */
#booking-detail-modal #bd-hulpacties > [hidden] { display: none !important; }
#booking-detail-modal #bd-hulpacties > button {
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 100%;
  min-width: 0;
  margin: 0 !important;   /* neutraliseert de gedeelde margin-right:auto (r1817) */
  flex: none;             /* neutraliseert flex-shrink:0 uit de gedeelde .bd-idform-btn-regel */
  text-align: center;
}
#booking-detail-modal #bd-hulpacties > button > svg { flex: none; }
/* Het label kapt af; de knop houdt zijn celbreedte. */
#booking-detail-modal #bd-hulpacties > button > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* ZONE 2 · de beslisregel: annuleren links, opslaan rechts, breekt nooit af.
   De dunne bovenrand scheidt de gewone hulpacties van de beslissing. */
#booking-detail-modal #bd-beslis {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
/* Staat er geen enkele hulpknop, dan zou de scheidingslijn onder niets hangen. */
#booking-detail-modal #bd-hulpacties:not(:has(> button:not([hidden]))) { display: none; }
#booking-detail-modal #bd-hulpacties:not(:has(> button:not([hidden]))) + #bd-beslis {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
#booking-detail-modal #bd-beslis > button {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  margin: 0 !important;   /* neutraliseert .modal-footer .btn-danger { margin-right:auto } (r977) */
  flex: 0 1 auto;
}
#booking-detail-modal #bd-beslis > button > svg { flex: none; }
#booking-detail-modal #bd-beslis > button > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* De reden waarom "Ander product" er niet staat (2 aug 2026). Bewust géén
   waarschuwingskleur: er is niets misgegaan, er valt alleen nu even niets te
   kiezen. Rustige tekst met een klokje, op de plek waar de knop anders stond,
   zodat de balie het antwoord vindt waar ze de vraag stelt. Mag krimpen en
   afbreken — de knoppen rechts houden hun maat. */
.bd-foot-noot {
  display: inline-flex; align-items: center; gap: 6px;
  min-width: 0; flex: 0 1 auto;
  font-size: calc(10.5px * var(--type-scale, 1.2)); line-height: 1.35;
  color: var(--text-muted); text-wrap: pretty;
}
.bd-foot-noot svg { flex: none; color: var(--text-faint); }
.bd-foot-noot[hidden] { display: none; }
/* Invul-labels houden hun rustige vorm. De kijk-labels zaten hier vroeger bij
   in (.scan-row span) — precies dát maakte informatie en invoer ononderscheidbaar.
   Ze zijn nu .bd-info-rij > dt, met een eigen, andere vorm. */
#booking-detail-modal .field > span {
  font-size: calc(10px * var(--type-scale, 1.2)) !important;
  font-weight: 500 !important;
  letter-spacing: normal !important;
  text-transform: none !important;
  color: var(--text-muted) !important;
}
/* ── Informatie ≠ invoer (voorstel sectie 3) ──
   Alleen-lezen krijgt géén rand en géén vulling, alleen uitlijning en
   haarlijnen; invoer houdt de doos. Het sterkst mogelijke onderscheid met de
   minste inkt: je ziet in één oogopslag waar het scherm ophoudt met vertellen
   en begint met vragen. (De .scan-row-doosjes blijven in de QR-scanner, waar
   ze wél de enige inhoud van het scherm zijn.) */
.bd-info { margin: 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.bd-info-rij { display: flex; align-items: baseline; justify-content: space-between;
  gap: 14px; padding: 7px 2px; }
.bd-info-rij + .bd-info-rij { border-top: 1px solid var(--border); }
.bd-info-rij > dt { font-size: calc(11.5px * var(--type-scale, 1.2)); color: var(--text-muted); flex: none; }
.bd-info-rij > dd { margin: 0; font-size: calc(13px * var(--type-scale, 1.2)); color: var(--text);
  text-align: right; font-variant-numeric: tabular-nums; min-width: 0; }
.bd-info-rij > dd small { display: block; font-size: calc(11.5px * var(--type-scale, 1.2));
  color: var(--text-muted); font-weight: 400; }
/* Het bedrag is het enige getal waar de balie op afrekent, dus het enige dat
   groter is dan de rest. */
.bd-info-rij > dd .bd-bedrag { font-size: calc(15px * var(--type-scale, 1.2)); font-weight: 650; letter-spacing: -.01em; }
/* Klikbare regels (Betaallink, Openstaand verschil) houden de accentkleur: de
   enige regels in het blok die eruitzien alsof er iets gebeurt. */
.bd-info-rij.bd-link { cursor: pointer; }
.bd-info-rij.bd-link > dd { color: var(--accent); font-weight: 600; }
.bd-info-rij.bd-link:hover > dd { text-decoration: underline; }
.bd-info-rij.bd-korting > dd { color: var(--accent); }
.bd-info-rij.bd-openstaand > dd { color: var(--warning); }
/* Betaalstatus-woord: zelfde kleurtaal als de verhuurlijst (één geldbron, één vorm). */
#booking-detail-modal .bd-geldstatus { font-weight: 650; }
#booking-detail-modal .bd-geldstatus.st-betaald { color: var(--success); }
#booking-detail-modal .bd-geldstatus.st-open { color: var(--warning); }
#booking-detail-modal .bd-geldstatus.st-import { color: var(--warning); }
/* ── Ledenlijst bij loskoppelen (voorstel sectie 2, punt 3) ──
   Groepsleden dragen meestal dezelfde gastnaam (één gezelschap over twee
   banen), dus baan + boekingscode is het enige onderscheid. Per regel staat
   erbij of hij eruit gaat of blijft. */
.bd-leden { display: flex; flex-direction: column; gap: 5px; margin: 0 0 11px; }
.bd-lid { display: flex; align-items: center; gap: 8px; font-size: calc(12px * var(--type-scale, 1.2));
  border: 1px solid var(--border); background: var(--panel); border-radius: 8px;
  padding: 6px 9px; font-variant-numeric: tabular-nums; }
.bd-lid b { font-weight: 600; color: var(--text); }
.bd-lid .bd-lid-rest { color: var(--text-muted); flex: 1 1 auto; min-width: 0; }
.bd-lid .bd-lid-vlag { flex: none; font-size: calc(10.5px * var(--type-scale, 1.2)); font-weight: 650;
  border-radius: 100px; padding: 2px 8px; white-space: nowrap; }
.bd-lid.is-eruit { border-color: color-mix(in oklch, var(--warning) 45%, var(--border)); }
.bd-lid.is-eruit .bd-lid-vlag { color: var(--warning); background: var(--warning-soft); }
.bd-lid.is-blijft .bd-lid-vlag { color: var(--text-muted); background: var(--surface); }

/* ══ Welkom-tegel (sidebar-foot) altijd volledig in beeld — Nick 1 aug ══
   De zijbalk is een flex-kolom met een vaste hoogte: de module-nav erboven
   scrolt, de voet (Welkom-tegel + thema-toggle) blijft vastgepind onderaan.
   De SQUARE-UI-basis zette min-height:100vh op de kolom; samen met sticky
   top:52px duwde dat de voet onder de viewport uit (tegel half buiten beeld). */
.app-sidebar { min-height: 0; }
.module-nav { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
@media (min-width: 1100px) {
  .app-sidebar { height: calc(100dvh - 52px); overflow: hidden; }
}
@media (max-width: 1099px) {
  /* Drawer: zelfde patroon — de kolom zelf klipt, de nav erin scrolt. */
  .app-sidebar { overflow: hidden; }
}

/* ══════════════════════════════════════════════════════════════════════════
   FEEDBACK — widget + tegel (Nick 1 aug 2026, site/voorstel-feedback.html)
   De klassen komen 1:1 uit het voorstel. Twee verschillen met dat bestand:
   de widget en het venster zijn `position:fixed` (shell-niveau, ze zweven over
   élke module inclusief de iframe-embeds) i.p.v. `absolute` binnen een demo-
   paneel, en het detailpaneel hangt in het module-scherm .fb-scherm.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── De knop: het WOORD "Feedback", geen chatwolk. Een icoon moet je leren,
   een woord lees je meteen — op een balietablet dat vier mensen delen is dat
   het verschil tussen wél en niet melden. ── */
/* 25 aug 2026 (Nick): van tekst-pill naar rond bug-icoon. Dit is de
   TERUGVAL-knop (eiland laadt niet); hij hoort er hetzelfde uit te zien als de
   rest van de backoffice, niet als de oude paarse widget. Maat 44px = de
   aanraakmaat die de eilanden ook gebruiken. Verslepen en de stip blijven. */
.fb-fab {
  position: fixed; right: 18px; width: 44px; height: 44px; padding: 0; border-radius: 50%;
  background: var(--accent); color: #fff; border: 0; box-shadow: 0 8px 22px rgba(0,0,0,.28);
  display: inline-flex; align-items: center; justify-content: center;
  white-space: nowrap; cursor: pointer; touch-action: none; z-index: 70;
  transition: transform .15s ease, box-shadow .15s ease;
}
.fb-fab:hover { transform: translateY(-1px); box-shadow: 0 10px 26px rgba(0,0,0,.32); }
.fb-fab.is-open { transform: translateY(-1px); }
/* Staat de melding-lade open, dan wijkt de knop ernaast — anders ligt hij over
   het antwoordveld en de waarschuwing erboven. Op smalle schermen vult de lade
   het scherm; daar stapt de knop even helemaal opzij. */
body.fb-detail-open .fb-fab, body.fb-detail-open .fb-panel { right: calc(var(--fbd-breedte) + 18px); }
@media (max-width: 760px) {
  body.fb-detail-open .fb-fab, body.fb-detail-open .fb-panel { display: none; }
}
html[data-theme="grey"] .fb-fab { color: var(--accent-fg); }
/* Ongelezen-antwoord-stip: alleen voor een écht antwoord, nooit voor een kale
   statuswijziging — anders verliest rood z'n betekenis binnen een week. */
.fb-fab-dot {
  position: absolute; top: -4px; right: -4px; width: 13px; height: 13px; border-radius: 50%;
  background: var(--danger); border: 2px solid var(--panel); animation: fb-dot-pols 2.2s ease-in-out infinite;
}
.fb-fab-dot[hidden] { display: none; }
@keyframes fb-dot-pols { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.18); } }
@media (prefers-reduced-motion: reduce) { .fb-fab-dot { animation: none; } }

/* ── Het gespreksvenster ── */
.fb-panel {
  position: fixed; right: 18px; width: 296px; max-width: calc(100vw - 24px);
  max-height: calc(100vh - 24px); background: var(--panel); border: 1px solid var(--border);
  border-radius: 14px; box-shadow: var(--shadow), 0 20px 45px rgba(0,0,0,.2);
  z-index: 71; display: flex; flex-direction: column; overflow: hidden;
}
.fb-ph { display: flex; align-items: center; gap: 8px; padding: 10px 11px;
  border-bottom: 1px solid var(--border); background: var(--surface); }
.fb-ph .ico { width: 28px; height: 28px; border-radius: 8px; background: var(--accent-soft);
  color: var(--accent); display: grid; place-items: center; flex: none; }
.fb-ph .ico svg { width: 15px; height: 15px; }
.fb-ph .tt { flex: 1; min-width: 0; }
.fb-ph .tt b { display: block; font-size: calc(12.5px * var(--type-scale, 1)); line-height: 1.3; }
.fb-ph .tt span { font-size: calc(10.5px * var(--type-scale, 1)); color: var(--text-muted); }
.fb-x { border: 0; background: none; color: var(--text-muted); width: 24px; height: 24px;
  border-radius: 7px; cursor: pointer; display: grid; place-items: center; flex: none; }
.fb-x:hover { background: var(--hover); color: var(--text); }
.fb-x svg { width: 13px; height: 13px; }
.fb-body { padding: 11px; display: flex; flex-direction: column; gap: 9px; flex: 1; min-height: 0; overflow: auto; }
.fb-types { display: flex; gap: 6px; }
.fb-types button { flex: 1; border: 1px solid var(--border-strong); background: var(--panel);
  color: var(--text-muted); border-radius: 9px; padding: 7px 6px;
  font: inherit; font-size: calc(11.5px * var(--type-scale, 1)); font-weight: 650; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 5px; }
.fb-types button svg { width: 13px; height: 13px; flex: none; }
.fb-types button.on { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
.fb-ta { width: 100%; min-height: 60px; resize: vertical; border: 1px solid var(--border-strong);
  border-radius: 9px; padding: 8px 9px; font: inherit; font-size: calc(12.5px * var(--type-scale, 1));
  background: var(--panel); color: var(--text); }
.fb-ta::placeholder { color: var(--text-faint); }
.fb-lbl { font-size: calc(10.5px * var(--type-scale, 1)); font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-faint); margin: 0 0 5px; display: block; }
.fb-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.fb-chip { font-size: calc(10px * var(--type-scale, 1)); font-weight: 600; color: var(--text-muted);
  background: var(--surface); border: 1px solid var(--border); border-radius: 100px;
  padding: 3px 8px; white-space: nowrap; }
.fb-chip.err { color: var(--danger); background: var(--danger-soft); border-color: transparent; }
.fb-shot { border: 1px dashed var(--border-strong); border-radius: 9px; padding: 7px;
  display: flex; gap: 8px; align-items: center; }
.fb-shot .thumb { width: 52px; height: 36px; border-radius: 6px; border: 1px solid var(--border);
  background: var(--bg); overflow: hidden; flex: none; }
.fb-shot .thumb img { width: 100%; height: 100%; object-fit: cover; object-position: top left; display: block; }
.fb-shot .txt { flex: 1; min-width: 0; font-size: calc(10.5px * var(--type-scale, 1));
  color: var(--text-muted); line-height: 1.4; }
.fb-shot .txt b { color: var(--text); display: block; font-size: calc(11px * var(--type-scale, 1)); }
.fb-shot-tgl { display: inline-flex; align-items: center; gap: 6px;
  font-size: calc(10.5px * var(--type-scale, 1)); font-weight: 600; color: var(--text-muted);
  cursor: pointer; white-space: nowrap; flex: none; }
.fb-shot-tgl input { width: 13px; height: 13px; accent-color: var(--accent); }
.fb-foot { display: flex; gap: 8px; padding: 10px 11px; border-top: 1px solid var(--border); }
.fb-foot .btn { flex: 1; justify-content: center; padding: 8px 10px; border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text); border-radius: 9px; font: inherit;
  font-size: calc(13px * var(--type-scale, 1)); cursor: pointer; display: inline-flex; align-items: center; }
.fb-foot .btn:hover { border-color: var(--text-faint); }
.fb-foot .btn.primary { background: var(--accent); color: #fff; border-color: var(--accent); font-weight: 600; }
html[data-theme="grey"] .fb-foot .btn.primary { color: var(--accent-fg); }
.fb-foot .btn.ghost { color: var(--text-muted); background: none; }
.fb-foot .btn:disabled { opacity: .4; cursor: not-allowed; }
.fb-ok { padding: 24px 16px; text-align: center; display: flex; flex-direction: column;
  align-items: center; gap: 7px; }
.fb-ok .chk { width: 38px; height: 38px; border-radius: 50%; background: var(--success-soft);
  color: var(--success); display: grid; place-items: center; }
.fb-ok .chk svg { width: 19px; height: 19px; }
.fb-ok b { font-size: calc(13px * var(--type-scale, 1)); }
.fb-ok span { font-size: calc(11px * var(--type-scale, 1)); color: var(--text-muted); }
.fb-ok .antwoord-inline { width: 100%; text-align: left; margin-top: 4px; }

/* ── Antwoorden: het venster toont dit vóór de composer als er iets ongelezen is ── */
.fb-reply-view { padding: 11px; display: flex; flex-direction: column; gap: 9px; flex: 1;
  min-height: 0; overflow: auto; }
.fb-reply-kop { font-size: calc(10.5px * var(--type-scale, 1)); font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--danger); }
.fb-reply-item { border: 1px solid var(--border); border-radius: 10px; padding: 10px 11px; background: var(--surface); }
.fb-reply-item .origineel { font-size: calc(11px * var(--type-scale, 1)); color: var(--text-faint);
  margin: 0 0 8px; padding-left: 8px; border-left: 2px solid var(--border-strong); line-height: 1.4; }
.fb-reply-item .antwoord-kop { display: flex; align-items: center; gap: 6px; margin: 0 0 4px;
  font-size: calc(10.5px * var(--type-scale, 1)); font-weight: 700; color: var(--accent);
  text-transform: uppercase; letter-spacing: .03em; }
.fb-reply-item .antwoord-kop svg { width: 12px; height: 12px; flex: none; }
.fb-reply-item .antwoord-tekst { font-size: calc(13px * var(--type-scale, 1)); color: var(--text); line-height: 1.5; }
.fb-reply-tijd { font-size: calc(10.5px * var(--type-scale, 1)); color: var(--text-faint); margin-top: 4px; }
.fb-reply-acties { display: flex; gap: 7px; margin-top: 9px; }
.fb-reply-acties .btn { flex: 1; justify-content: center; font-size: calc(11.5px * var(--type-scale, 1));
  padding: 7px 6px; border: 1px solid var(--border-strong); background: var(--panel); color: var(--text);
  border-radius: 8px; font-family: inherit; cursor: pointer; display: inline-flex; align-items: center; }
.fb-reply-acties .btn:hover { border-color: var(--text-faint); }
.fb-reply-acties .btn.ghost { color: var(--text-muted); background: none; }

/* ══ Scherm 1 — beheeroverzicht (administrator): een tabel, want dit is triage ══ */
.fb-scherm { position: relative; border: 1px solid var(--border); border-radius: 14px;
  background: var(--panel); overflow: hidden; min-height: 220px; display: flex; flex-direction: column; }
/* ── Dagstaat-printkeuze ─────────────────────────────────────────────────
   Kleine popup op het bkflow-card-patroon. box-sizing expliciet: de
   backoffice zet dat niet globaal, en een kaart met padding + max-width
   groeit anders buiten zijn venster (de 504px-les van 7 aug). */
.pk-card, .pk-card * { box-sizing: border-box; }
.pk-lijst { display: flex; flex-direction: column; gap: 2px; margin: 4px 0 10px; }
.pk-rij { display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border-radius: 8px; cursor: pointer; }
.pk-rij:hover { background: var(--hover); }
.pk-rij input { width: 16px; height: 16px; accent-color: var(--accent); flex: none; }
.pk-rij span { font-size: calc(13.5px * var(--type-scale, 1)); }
.pk-rij small { margin-left: auto; color: var(--text-muted);
  font-size: calc(11px * var(--type-scale, 1)); font-variant-numeric: tabular-nums; }
.pk-toggle { font-size: calc(11.5px * var(--type-scale, 1)); }

.fbt-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 11px 14px;
  border-bottom: 1px solid var(--border); background: var(--panel); }
/* De statusfilters (.fbt-filters) stonden hier: een rij tabs boven de lijst. Ze
   wonen sinds 2 aug in de zijbalk, mét een teller per filter (Nicks keuze bij
   de lege Feedback-zijbalk). Wat in deze balk overblijft is de telling en de
   export — zie .zb-item .zb-tel hierboven. */
.fbt-telling { margin-left: auto; font-size: calc(11px * var(--type-scale, 1));
  color: var(--text-faint); white-space: nowrap; }
.fbt-wrap { overflow-x: auto; }
table.fbt { width: 100%; border-collapse: collapse; font-size: calc(12.5px * var(--type-scale, 1)); min-width: 640px; }
table.fbt th { text-align: left; font-size: calc(10.5px * var(--type-scale, 1)); text-transform: uppercase;
  letter-spacing: .05em; color: var(--text-faint); font-weight: 700; padding: 8px 12px;
  border-bottom: 1px solid var(--border); white-space: nowrap; background: var(--surface); }
table.fbt td { padding: 9px 12px; border-bottom: 1px solid var(--border); vertical-align: middle; }
table.fbt tr.row { cursor: pointer; }
table.fbt tr.row:hover td { background: var(--hover); }
/* "Wie" draagt naam én rol: het beheeroverzicht is de enige plek waar meldingen
   van verschillende mensen door elkaar staan. */
.fbt-wie { white-space: nowrap; line-height: 1.25; }
.fbt-wie b { display: block; font-weight: 600; }
.fbt-wie small { display: block; font-size: calc(10.5px * var(--type-scale, 1)); color: var(--text-muted); }
.fbt-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: none; }
.fbt-dot.nieuw { background: var(--accent); }
.fbt-dot.opgepakt { background: var(--warning); }
.fbt-dot.opgelost { background: var(--success); }
.fbt-dot.afgewezen { background: var(--text-faint); }
.fbt-badge { font-size: calc(10.5px * var(--type-scale, 1)); font-weight: 700; padding: 2px 9px;
  border-radius: 100px; white-space: nowrap; display: inline-block; }
.fbt-badge.nieuw { color: var(--accent); background: var(--accent-soft); }
.fbt-badge.opgepakt { color: #8a5211; background: var(--warning-soft); }
html[data-theme="grey"] .fbt-badge.opgepakt { color: #f3caa0; }
.fbt-badge.opgelost { color: var(--success); background: var(--success-soft); }
.fbt-badge.afgewezen { color: var(--text-faint); background: var(--surface); }
.fbt-type { font-size: calc(10px * var(--type-scale, 1)); font-weight: 700; padding: 2px 7px;
  border-radius: 6px; white-space: nowrap; }
.fbt-type.bug { color: var(--danger); background: var(--danger-soft); }
.fbt-type.idee { color: var(--accent); background: var(--accent-soft); }
.fbt-tekst { display: inline-block; max-width: 260px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--text); vertical-align: middle; }
.fbt-x { font-size: calc(10.5px * var(--type-scale, 1)); color: var(--text-faint); font-weight: 700; margin-left: 5px; }
/* Het meldingnummer. tabular-nums houdt de cijfers onder elkaar in de kolom, en
   user-select maakt hem te kopiëren — het nummer is waarmee je naar een melding
   verwijst in een mail of aan de telefoon. */
.fbt-nr { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap;
  color: var(--text-muted); user-select: text; }
tr.row.heeft-nieuw .fbt-nr { color: var(--text); }
[data-theme="grey"] #fb-export { background: var(--surface); color: var(--text); border-color: var(--border); }
.fbt-shot { display: inline-block; width: 14px; height: 14px; color: var(--text-faint); }
.fbt-shot svg { width: 14px; height: 14px; display: block; }
.fbt-beantwoord { display: inline-block; width: 12px; height: 12px; margin-left: 6px; color: var(--accent); vertical-align: middle; }
.fbt-beantwoord svg { width: 12px; height: 12px; display: block; }
.fbt-leeg { padding: 34px 20px; text-align: center; color: var(--text-faint);
  font-size: calc(12.5px * var(--type-scale, 1)); }

/* ══ Scherm 2 — mijn meldingen (medewerker): bewust GEEN tabel met een filter
   erover maar een korte kaartenlijst. Geen wie-kolom (alles is van jou), geen
   statusfilters, geen export. Het antwoord staat meteen ín de kaart. ══ */
.fbe-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 11px 14px;
  border-bottom: 1px solid var(--border); background: var(--panel); }
.fbe-wie b { display: block; font-size: calc(13px * var(--type-scale, 1)); }
.fbe-wie span { display: block; font-size: calc(11.5px * var(--type-scale, 1)); color: var(--text-muted); }
.fbe-telling { margin-left: auto; font-size: calc(11px * var(--type-scale, 1));
  color: var(--text-faint); white-space: nowrap; }
.fbe-lijst { padding: 12px 14px; display: flex; flex-direction: column; gap: 9px; }
.fbe-kaart { display: block; width: 100%; text-align: left; font: inherit; color: var(--text);
  border: 1px solid var(--border); border-radius: 11px; background: var(--panel);
  padding: 11px 13px; cursor: pointer; }
.fbe-kaart:hover { border-color: var(--text-faint); background: var(--hover); }
.fbe-kop { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 0 0 6px; }
.fbe-wanneer { margin-left: auto; font-size: calc(11px * var(--type-scale, 1));
  color: var(--text-faint); white-space: nowrap; }
/* POSTVAKREGEL (2 aug 2026, §8) — de kaart herhaalde wat zíj zelf typte en zei
   er "3 berichten" onder. Het aantal zegt niets; de laatste regel wel. Haar
   eigen tekst naar één regel, en daaronder het laatste bericht mét afzender —
   dát is de reden dat je de kaart aanklikt. */
.fbe-tekst { display: -webkit-box; -webkit-line-clamp: 1; line-clamp: 1; -webkit-box-orient: vertical;
  overflow: hidden; font-size: calc(12.5px * var(--type-scale, 1)); line-height: 1.5; color: var(--text-muted); }
.fbe-mod { display: block; font-size: calc(11px * var(--type-scale, 1)); color: var(--text-muted); margin-top: 4px; }
.fbe-laatste { display: flex; gap: 6px; align-items: baseline; margin-top: 5px;
  font-size: calc(12px * var(--type-scale, 1)); color: var(--text-muted); line-height: 1.45; }
.fbe-laatste b { color: var(--text); font-weight: 600; flex: none; }
.fbe-laatste .p { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fbe-kaart.heeft-nieuw { border-color: var(--border-strong); }
.fbe-kaart.heeft-nieuw .fbe-laatste { font-weight: 600; color: var(--text); }
.fbe-stip { width: 7px; height: 7px; border-radius: 50%; background: var(--danger); display: inline-block; flex: none; }
.fbe-leeg { padding: 34px 20px; text-align: center; color: var(--text-faint);
  font-size: calc(12.5px * var(--type-scale, 1)); }

/* ── Melding-detail: schuift van rechts open, zelfde chrome als het venster ──
   In het voorstel staat dit paneel `absolute` binnen een demo-doos van 340px
   hoog. In de echte module zou het daardoor op de onderrand van de tabel
   afgekapt worden (context + antwoordveld vallen dan buiten beeld), dus hier
   een schermvullende lade. Onder de launchpad (z 60) en onder de widget (70),
   zodat "melden over dit scherm" ook met de lade open blijft werken. */
.fbd-overlay { position: fixed; inset: 0; background: rgba(20,20,20,.32);
  display: flex; justify-content: flex-end; z-index: 58; }
.fbd-overlay[hidden] { display: none; }
/* Breedte op één plek, want de widget schuift er precies naast (zie
   `body.fb-detail-open .fb-fab`) — twee losse getallen lopen uit de pas.

   VLOER = het huisformaat. Elk ander zijpaneel in de backoffice (waaronder het
   boekingdetail) is `.modal-inner` en meet vanaf 720px `min(480px, 100vw)`.
   Deze lade stond op 340px: dat getal komt uit de demo-doos van
   voorstel-feedback.html, niet uit de backoffice. Vanaf 720px dus 480px —
   gelijk aan het boekingdetail, geen eigen breedte meer.

   BOVEN DE VLOER mag een gesprek breder, en dat is geen smaak: een
   formulierpaneel toont gelabelde velden onder elkaar, daar bepaalt het
   BREEDSTE VELD de maat. Een gesprek toont proza in bubbels die bovendien
   inspringen (86% van de kolom, links/rechts uitgelijnd), dus de leesbare
   tekstkolom is fors smaller dan het paneel. Uit de metingen hieronder volgt
   dat 480px op ±46 tekens uitkomt — de ONDERrand van de 45-75 die comfortabel
   leest. Daarom groeit de lade vanaf 1100px mee met het scherm.

   TWEE GRENZEN aan dat meegroeien. 40vw: een lade die meer dan twee vijfde van
   het scherm pakt, is geen lade meer maar een pagina — de lijst eronder moet
   context blijven. En 640px: daar haalt een regel 65 leestekens (gemeten), de
   bovenkant van wat comfortabel leest.

   Het PLAFOND daarboven ligt op de BUBBEL, niet op het paneel (.gsp-b
   hieronder): een regel die over een 1920-breed scherm doorloopt, leest net zo
   slecht als een kolom van vijf woorden. Boven dat plafond wordt extra breedte
   marge, en juist die marge houdt de chat-grammatica (ik rechts, de ander
   links) leesbaar.

   Gemeten op de echte lade (verify-gesprek-breedte.cjs), tekens per regel:
   340px oud = 30 · 1280 = 51 · 1440 = 58 · 1920 = 65. Was: onder het venster,
   is: er middenin. */
:root { --fbd-breedte: min(480px, 100vw); }
@media (min-width: 1100px) { :root { --fbd-breedte: clamp(480px, 40vw, 640px); } }
/* DRIE RIJEN, ÉÉN SCROLLER (2 aug 2026, site/voorstel-gesprek-ontwerp.html §7)
   Tot vandaag scrolde de lade zélf (`overflow:auto`) én de stroom erbinnen
   (`max-height:min(52vh,430px)`). Omdat de contextlijst ónder de composer hing,
   schoof het invoerveld uit beeld zodra je bovenaan het gesprek stond: het veld
   waar je hand naartoe gaat stond niet vast. Dat kon pas dicht toen de context
   (§4) uit de bodem naar de stroom verhuisde.
   Nu: kop (auto) — stroom (1fr, de enige scroller) — voet (auto).
   100dvh en niet 100vh: op iOS dekt de adresbalk anders precies de verzendknop
   af. De veilige zone onderin zit in .gsp-voet. */
.fbd { width: 100%; max-width: var(--fbd-breedte); background: var(--panel);
  height: 100dvh; overflow: hidden;
  box-shadow: -16px 0 34px rgba(0,0,0,.22); display: flex; flex-direction: column; }
/* De ladekop ís de gesprekskop geworden — één kop, geen doos in een doos. De
   opmaak komt uit .gsp-kop hieronder, die ook in het widgetvenster geldt. */
.fbd-h { flex: none; }
.fbd-b { padding: 0; flex: 1; min-height: 0; display: flex; flex-direction: column; }

/* ══════════════════════════════════════════════════════════════════════════
   HET GESPREK (Nick 1 aug 2026, site/voorstel-feedback-gesprek.html)

   Chat-grammatica: eigen berichten rechts, die van de ander links,
   systeemregels gecentreerd en zonder bubbel. Prefix .gsp-*. Geen nieuwe
   kleuren — alles op bestaande tokens (--surface, --accent-soft, --border),
   zodat licht én grijs vanzelf kloppen.
   ══════════════════════════════════════════════════════════════════════════ */
.gsp { display: flex; flex-direction: column; background: var(--panel);
  border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }

/* ── ÉÉN KOP (§1) ──
   Regel 1 zegt met wie je praat (bij de melder: waaróver), plus type en status.
   Regel 2 draagt het archiefspul: nummer, module › tab, wanneer. Het nummer
   stond hiervóór twee keer op het scherm — in de ladekop én hier. */
.gsp-kop { padding: 10px 12px; border-bottom: 1px solid var(--border); background: var(--surface);
  display: flex; align-items: flex-start; gap: 8px; position: relative; }
.gsp-kop .wie { flex: 1; min-width: 0; }
.gsp-kop .titel { display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: calc(13px * var(--type-scale, 1)); font-weight: 600; line-height: 1.3; }
.gsp-kop .titel .rol { font-weight: 400; color: var(--text-muted); }
.gsp-kop .meta { display: block; font-size: calc(10.5px * var(--type-scale, 1));
  color: var(--text-muted); margin-top: 2px; line-height: 1.4; overflow-wrap: anywhere; }
.gsp-kop .meta .nr { font-variant-numeric: tabular-nums; font-weight: 600; user-select: text; }
.gsp-x { border: 0; background: none; color: var(--text-muted); width: 26px; height: 26px;
  border-radius: 7px; cursor: pointer; display: grid; place-items: center; flex: none; }
.gsp-x:hover { background: var(--hover); color: var(--text); }
.gsp-x svg { width: 13px; height: 13px; }

/* ── DE BADGE IS DE KNOP (§5) ──
   Status is een eigenschap van het gesprek en hoort dus in de kop; status
   ómzetten gebeurt een paar keer per week en verdient geen vier permanente
   knoppen vóór de inhoud. Bij de melder is dit hetzelfde element, alleen geen
   knop: geen caret, geen menu, geen focusring. */
.gsp-status { display: inline-flex; align-items: center; gap: 5px; border: 1px solid transparent;
  border-radius: 100px; padding: 2px 8px 2px 9px; font: inherit;
  font-size: calc(10.5px * var(--type-scale, 1)); font-weight: 700; cursor: pointer;
  background: var(--surface); color: var(--text-faint); line-height: 1.5; white-space: nowrap; flex: none; }
.gsp-status .caret { width: 9px; height: 9px; opacity: .7; }
.gsp-status.nieuw { color: var(--accent); background: var(--accent-soft); }
.gsp-status.opgepakt { color: #8a5211; background: var(--warning-soft); }
html[data-theme="grey"] .gsp-status.opgepakt { color: #f3caa0; }
.gsp-status.opgelost { color: var(--success); background: var(--success-soft); }
.gsp-status.afgewezen { color: var(--text-faint); background: var(--surface); border-color: var(--border-strong); }
span.gsp-status { cursor: default; }
.gsp-menu { position: absolute; top: calc(100% - 4px); right: 10px; z-index: 20; background: var(--panel);
  border: 1px solid var(--border-strong); border-radius: 11px; box-shadow: var(--shadow);
  padding: 5px; width: min(280px, calc(100% - 20px)); }
.gsp-menu[hidden] { display: none; }
.gsp-menu button { display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  width: 100%; text-align: left; border: 0; background: none; border-radius: 8px;
  padding: 7px 9px; font: inherit; cursor: pointer; color: var(--text); }
.gsp-menu button:hover { background: var(--hover); }
.gsp-menu button b { font-size: calc(11.5px * var(--type-scale, 1)); font-weight: 650;
  display: flex; align-items: center; gap: 6px; }
.gsp-menu button b .vink { color: var(--accent); font-weight: 700; }
.gsp-menu button span { font-size: calc(10.5px * var(--type-scale, 1)); color: var(--text-muted); line-height: 1.4; }
.gsp-menu button.on { background: var(--accent-soft); }

.gsp-groepbalk { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: calc(11px * var(--type-scale, 1)); color: var(--text-muted);
  padding: 7px 12px; border-bottom: 1px solid var(--border); background: var(--surface); }
.gsp-groepbalk .t { flex: 1; min-width: 140px; line-height: 1.45; }
.gsp-groepbalk b { color: var(--danger); font-weight: 700; }
.gsp-groepbalk button { margin-left: auto; border: 1px solid var(--border-strong); background: var(--panel);
  color: var(--text); border-radius: 7px; padding: 4px 9px; font: inherit;
  font-size: calc(11px * var(--type-scale, 1)); font-weight: 600; cursor: pointer; white-space: nowrap; }

.gsp-stroom { padding: 12px 12px 14px; display: flex; flex-direction: column; gap: 10px;
  overflow-y: auto; overflow-x: hidden; background: var(--bg); scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { .gsp-stroom { scroll-behavior: auto; } }
/* ── BUBBELS GEGROEPEERD PER AFZENDER (§2) ──
   Elk bericht herhaalde naam én tijd: bij tien berichten twintig regels waar
   niets in staat. Nu één blok per beurt — naam boven, tijd onder, bubbels 2px
   uit elkaar, en alleen de láátste heeft een staart, want daar eindigt de beurt. */
.gsp-blok { display: flex; flex-direction: column; gap: 2px; max-width: 86%; }
.gsp-blok.mij { align-self: flex-end; align-items: flex-end; }
.gsp-blok.ander { align-self: flex-start; align-items: flex-start; }
.gsp-naam { font-size: calc(10.5px * var(--type-scale, 1)); font-weight: 650;
  color: var(--text-muted); padding: 0 3px 2px; line-height: 1.3; }
.gsp-naam .rol { font-weight: 400; color: var(--text-faint); }
/* De max-width is het plafond uit de kop van .fbd, hier toegepast: de bubbel
   stopt met groeien waar de regel te lang wordt om nog vlot terug te vinden
   naar het begin.

   Gemeten in chromium op de echte lade (niet geschat): deze bubbel staat op
   15px Inter, 1ch = 9,95px en een gemiddeld leesteken 7,31px. 57ch = 567px
   bubbel = 545px tekst = ±75 tekens — precies de bovenrand van de 45-75 die
   comfortabel leest.

   In `ch` en niet in px, zodat de grens meeschaalt met --type-scale: bij
   grotere letters hoort een bredere bubbel, niet dezelfde.

   Bij het huidige paneelplafond (640px) haalt de bubbel 502px / 65 tekens, dus
   het paneel raakt zijn grens eerst en deze regel bijt nog niet. Dat is de
   bedoeling: dít is het slot dat het meegroeien (40vw) veilig maakt, en het
   bijt zodra dat plafond omhoog gaat of het gesprek in een bredere doos wordt
   hergebruikt. Zonder dit slot loopt een regel op een 4K-scherm door tot ver
   voorbij wat je nog kunt lezen. */
.gsp-bub { max-width: 57ch;
  border-radius: 13px; padding: 8px 11px; font-size: calc(12.5px * var(--type-scale, 1));
  line-height: 1.5; overflow-wrap: anywhere; white-space: pre-wrap; }
.gsp-blok.ander .gsp-bub { background: var(--surface); border: 1px solid var(--border-strong);
  color: var(--text); border-bottom-left-radius: 5px; }
.gsp-blok.ander .gsp-bub:not(:last-of-type) { border-bottom-left-radius: 13px; }
/* DRIE lagen dezelfde token, niet twee. Gemeten op 2 aug: --surface (#f7f7f7) op
   --bg (#fff) is 1,5 % verschil, en de eigen bubbel op twee lagen bleef een
   zweem. Bij drie composeert .14 → .36 = #C2CFD6 op licht: een echt steel-vlak,
   contrast 9,5:1 voor de tekst erop. De rand vervalt — een vlak dat kleur heeft
   heeft geen omlijning nodig. Geen nieuwe kleurwaarde, alleen meer van dezelfde. */
.gsp-blok.mij .gsp-bub { background: linear-gradient(var(--accent-soft), var(--accent-soft)),
  linear-gradient(var(--accent-soft), var(--accent-soft)), var(--accent-soft);
  border: 1px solid transparent; color: var(--text); border-bottom-right-radius: 5px; }
.gsp-blok.mij .gsp-bub:not(:last-of-type) { border-bottom-right-radius: 13px; }
.gsp-tijd { font-size: calc(10px * var(--type-scale, 1)); color: var(--text-faint);
  padding: 3px 3px 0; line-height: 1.3; }
.gsp-tijd .naar { color: var(--accent); font-weight: 600; }

/* Het openingsbericht draagt beeld + context. De bubbel mag daar 100 % breed:
   een bijlage is geen proza, dus het inspringen dat het links/rechts-ritme
   draagt hoeft niet ten koste van het enige beeld in het gesprek te gaan. */
.gsp-blok.opening { max-width: 100%; }
.gsp-blok.opening .gsp-bub { width: 100%; }
/* Het beeld zit ín de bubbel, tegen de onderrand geplakt (negatieve marge tegen
   de bubbelpadding), met de ronding van de bubbel — dan leest het als bijlage
   bij dít bericht en niet als losse strook eronder. 150px i.p.v. 104: genoeg om
   te herkennen wáár het over gaat; lezen doe je op ware grootte. */
.gsp-bub.heeft-shot { border-bottom-left-radius: 13px; border-bottom-right-radius: 13px; }
.gsp-shot { border: 0; padding: 0; background: none; cursor: zoom-in; display: block;
  margin: 9px -11px -8px; width: calc(100% + 22px);
  border-radius: 0 0 12px 12px; overflow: hidden; position: relative; line-height: 0; }
.gsp-shot img { width: 100%; height: 150px; object-fit: cover; object-position: top left;
  border: 0; border-radius: 0; display: block; }
.gsp-shot .lup { position: absolute; right: 7px; bottom: 7px; background: rgba(20,20,20,.74);
  color: #fff; font-size: calc(10px * var(--type-scale, 1)); font-weight: 600; padding: 3px 9px;
  border-radius: 100px; line-height: 1.4; display: flex; align-items: center; gap: 4px; }
.gsp-shot .lup svg { width: 11px; height: 11px; }
.gsp-shot:hover .lup { background: rgba(20,20,20,.92); }
/* Geen beeld? Dan geen knop — een knop die niets opent is erger dan geen knop. */
.gsp-shot-leeg { margin-top: 9px; border: 1px dashed var(--border-strong); border-radius: 9px; padding: 9px;
  font-size: calc(10.5px * var(--type-scale, 1)); color: var(--text-faint); text-align: center;
  line-height: 1.45; white-space: normal; }

/* ── DE CONTEXT, ÉÉN KEER EN INGEKLAPT (§4) ──
   Stond twee keer in beeld: drie chips in de bubbel en een lijst van zes
   onderaan de lade. Hij beschrijft dát ene bericht — het scherm waar de melder
   op stond — dus hoort hij daar en niet onder de composer, waar hij de voet
   wegduwde. Dicht staat de kern er al in; open staat alles er, met een knop om
   het blok als platte tekst te kopiëren. */
.gsp-ctx { width: 100%; max-width: 57ch; margin-top: 6px; border: 1px solid var(--border);
  border-radius: 9px; background: var(--surface); overflow: hidden; white-space: normal; }
.gsp-ctx > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 7px;
  padding: 6px 9px; font-size: calc(10.5px * var(--type-scale, 1)); color: var(--text-muted); line-height: 1.4; }
.gsp-ctx > summary::-webkit-details-marker { display: none; }
.gsp-ctx > summary .chev { width: 9px; height: 9px; flex: none; transition: transform .15s; color: var(--text-faint); }
@media (prefers-reduced-motion: reduce) { .gsp-ctx > summary .chev { transition: none; } }
.gsp-ctx[open] > summary .chev { transform: rotate(90deg); }
.gsp-ctx > summary b { color: var(--text-muted); font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; font-size: calc(9.5px * var(--type-scale, 1)); }
.gsp-ctx > summary .kern { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gsp-ctx-body { padding: 2px 9px 9px; border-top: 1px solid var(--border); }
.gsp-dl { font-size: calc(11px * var(--type-scale, 1)); margin: 8px 0 0;
  display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; }
.gsp-dl dt { color: var(--text-faint); font-weight: 600; }
.gsp-dl dd { margin: 0; color: var(--text); overflow-wrap: anywhere; }
.gsp-ctx pre { font-family: var(--font-mono, ui-monospace, monospace);
  font-size: calc(10px * var(--type-scale, 1)); background: var(--panel); border: 1px solid var(--border);
  border-radius: 7px; padding: 7px 8px; margin: 8px 0 0; white-space: pre-wrap;
  overflow-wrap: anywhere; max-height: 120px; overflow: auto; }
.gsp-ctx-kopieer { margin-top: 8px; font: inherit; font-size: calc(10.5px * var(--type-scale, 1));
  font-weight: 600; color: var(--accent); background: none; border: 0; padding: 0; cursor: pointer; }

/* ── De vier gecentreerde regels: systeem, datum, nieuw, einde ── */
.gsp-sys, .gsp-dag, .gsp-nieuw, .gsp-eind { align-self: stretch; display: flex; align-items: center;
  gap: 8px; font-size: calc(10.5px * var(--type-scale, 1)); line-height: 1.4; text-align: center; }
.gsp-sys::before, .gsp-sys::after, .gsp-dag::before, .gsp-dag::after,
.gsp-nieuw::before, .gsp-nieuw::after, .gsp-eind::before, .gsp-eind::after {
  content: ""; height: 1px; flex: 1; min-width: 10px; background: var(--border); }
.gsp-sys > span, .gsp-dag > span, .gsp-nieuw > span, .gsp-eind > span {
  flex: none; max-width: calc(100% - 40px); display: inline-flex; align-items: center;
  gap: 6px; flex-wrap: wrap; justify-content: center; }
.gsp-sys { color: var(--text-faint); }
.gsp-sys b { color: var(--text-muted); font-weight: 600; }
/* Het statuswoord in de systeemregel is hetzelfde object als de badge in de kop:
   zelfde kleurfamilie, kleiner. Dan zie je in de stroom letterlijk terug wáár
   de stand die bovenin staat vandaan komt. */
.gsp-sys .mini { font-size: calc(9.5px * var(--type-scale, 1)); font-weight: 700;
  padding: 1px 7px; border-radius: 100px; white-space: nowrap; }
.gsp-sys .mini.nieuw { color: var(--accent); background: var(--accent-soft); }
.gsp-sys .mini.opgepakt { color: #8a5211; background: var(--warning-soft); }
html[data-theme="grey"] .gsp-sys .mini.opgepakt { color: #f3caa0; }
.gsp-sys .mini.opgelost { color: var(--success); background: var(--success-soft); }
.gsp-sys .mini.afgewezen { color: var(--text-faint); background: var(--surface); border: 1px solid var(--border-strong); }
.gsp-sys svg { width: 11px; height: 11px; flex: none; opacity: .8; }
/* Zodra een gesprek over de dagrand loopt staat "09:40" onder "11:48" en klopt
   de volgorde ogenschijnlijk niet. Vandaar de datumstreep. */
.gsp-dag { color: var(--text-muted); font-weight: 650; }
/* De scheidingslijn die elke chat kent. Eén stip, geen teller — maar bij het
   openen wél het hele staartje sinds je laatste bezoek, onder één streep. */
.gsp-nieuw { color: var(--danger); font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; font-size: calc(10px * var(--type-scale, 1)); }
.gsp-nieuw::before, .gsp-nieuw::after { background: var(--danger); opacity: .4; }
/* De eindmarkering zegt dat het gesprek híér ophoudt; de systeemregel erboven
   legt vast dat iemand de status omzette. Heropenen haalt de markering weg en
   laat de systeemregel staan — die handeling is wél gebeurd. */
.gsp-eind { color: var(--success); font-weight: 650; margin-top: 2px; }
.gsp-eind.af { color: var(--text-faint); }
.gsp-eind::before, .gsp-eind::after { background: currentColor; opacity: .35; }
.gsp-eind svg { width: 12px; height: 12px; flex: none; }

.gsp-voet { border-top: 1px solid var(--border); background: var(--surface);
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px)); }
/* De composer groeit mee (Nick 2 aug 2026). De hoogte komt van fbTaGroei() in
   app.js: die zet 'height' inline. Wat hier staat is het vangnet ervoor en
   eronder — rows="3" geeft zonder JS al drie regels, en `resize: vertical`
   blijft staan omdat de sleep-hoek mag blijven werken. Geen `max-height`: dat
   zou het handmatig groter slepen alsnog afknijpen, en dan vecht de hoek met
   het meegroeien. Het plafond zit daarom in JS, waar het los te laten is.

   De selector is `textarea.gsp-ta` en niet `.gsp-ta`, want de basislaag
   `.app-main textarea` (r3693) is specifieker dan één klasse en zette hier
   `font: 400 13.5px var(--font)` overheen. Die shorthand zet line-height op
   `normal`, en `normal` hangt aan de metriek van het lettertype dat op dat
   moment geladen is — de eerste meting viel dus op de vervangfont en werd
   daarna nooit meer bijgesteld. Vandaar een expliciete verhouding: 1.5, precies
   de regelafstand van de bubbels, zodat wat je typt eruitziet als wat er straks
   staat. In het widgetvenster (buiten .app-main) gold dit al.
   Op < 1100px zet style.css r70 font-size op 16px !important tegen de
   iOS-zoom; de regelhoogte schaalt daar netjes in mee omdat 1.5 een
   verhouding is en geen vaste pixelmaat. */
textarea.gsp-ta { width: 100%; display: block; resize: vertical; border: 1px solid var(--border-strong);
  border-radius: 9px; padding: 8px 9px; font: inherit; font-size: calc(12.5px * var(--type-scale, 1));
  line-height: 1.5; overflow-y: auto; background: var(--panel); color: var(--text); }
.gsp-ta::placeholder { color: var(--text-faint); }
.gsp-verzend { display: flex; align-items: center; gap: 8px; margin-top: 7px; flex-wrap: wrap; }
.gsp-verzend .btn { margin-left: auto; }
/* Enter doet sinds 2 augustus iets anders dan daarvoor; dat hoort te zien te
   zijn, niet ontdekt te worden. Vult de ruimte tot de knop, breekt zelf af op
   een smal venster in plaats van de knop naar de volgende regel te duwen. */
.gsp-toets { flex: 1 1 120px; min-width: 0; font-size: calc(10px * var(--type-scale, 1));
  line-height: 1.35; color: var(--text-faint); }
.gsp-toets b { font-weight: 650; color: var(--text-muted); }
.gsp-groep { display: inline-flex; align-items: center; gap: 6px;
  font-size: calc(11px * var(--type-scale, 1)); color: var(--text-muted); cursor: pointer; line-height: 1.35; }
.gsp-groep input { margin: 0; accent-color: var(--accent); }
.gsp-let { font-size: calc(11px * var(--type-scale, 1)); line-height: 1.45; border-radius: 8px;
  padding: 7px 9px; margin: 0 0 7px; }
.gsp-let.waarschuw { color: var(--warning); background: var(--warning-soft); }
html[data-theme="grey"] .gsp-let.waarschuw { color: #f3caa0; }
.gsp-let.rustig { color: var(--text-muted); background: var(--panel); border: 1px solid var(--border); }

/* Het veld verdwijnt niet stilletjes: er staat wát er dicht is en waarom — en
   de balk houdt de hoogte van de composer aan, zodat het paneel niet verspringt
   als de status omgaat. Het ziet er niet uit alsof er iets is weggevallen, maar
   alsof er iets anders staat. */
.gsp-dicht { display: flex; align-items: center; gap: 9px; min-height: 38px; }
.gsp-dicht .zin { flex: 1; min-width: 0; font-size: calc(11px * var(--type-scale, 1));
  color: var(--text-muted); margin: 0; line-height: 1.45; }
.gsp-dicht .zin b { color: var(--text); font-weight: 600; }
.gsp-dicht .btn { flex: none; width: auto; justify-content: center;
  font-size: calc(11.5px * var(--type-scale, 1)); padding: 7px 11px; }
/* Onder 480px zou de zin naast de knop een kolom van vier regels worden. */
@media (max-width: 480px) {
  .gsp-dicht { flex-direction: column; align-items: stretch; gap: 7px; }
  .gsp-dicht .btn { width: 100%; }
}

/* In de lade vult het gesprek de hoogte; in de widget is het een kaartje.
   De lade is sinds 2 aug een raster van drie rijen (zie .fbd hierboven): de kop
   zit in .fbd-h, dus het gesprek zelf is stroom (1fr) + voet (auto) en de stroom
   is de enige scroller. */
.gsp-detail { flex: 1; min-height: 0; display: grid; grid-template-rows: minmax(0, 1fr) auto;
  border: 0; border-radius: 0; background: var(--bg); }
.gsp-detail .gsp-stroom { max-height: none; min-height: 0; }
.gsp-mini { margin-bottom: 9px; }
.gsp-mini .gsp-stroom { max-height: 210px; padding: 10px; }
.gsp-mini .gsp-kop { padding: 8px 10px; }
.gsp-mini .gsp-voet { padding: 8px 10px; }
.gsp-mini .gsp-blok { max-width: 94%; }

/* ── Nieuw-bericht-stip: dezelfde betekenis als het widget-bolletje, andere plek ── */
.fbt-nieuw { width: 8px; height: 8px; border-radius: 50%; background: var(--danger);
  display: inline-block; flex: none; }
.fbt tr.row.heeft-nieuw td { font-weight: 600; }
/* .lp-tile staat in index.html en heeft daar geen position; hier zetten zodat
   de stip in de hoek blijft hangen zonder dat bestand aan te raken. */
.lp-tile { position: relative; }
.lp-tile .lp-stip { position: absolute; top: 10px; right: 10px; width: 9px; height: 9px;
  border-radius: 50%; background: var(--danger); }

/* ══════════════════════════════════════════════════════════════════════════
   Lightbox — de opname op ware grootte. Esc sluit, klik naast sluit, klik op
   het beeld wisselt tussen passend en 100 %. Boven de lade (58) en boven de
   widget (70), want hij hoort altijd bovenop.
   ══════════════════════════════════════════════════════════════════════════ */
.fb-lb { position: fixed; inset: 0; z-index: 90; background: rgba(15,15,15,.86);
  display: flex; flex-direction: column; }
.fb-lb[hidden] { display: none; }
.fb-lb-bar { display: flex; align-items: center; gap: 9px; padding: 9px 12px; color: #fff;
  flex: none; flex-wrap: wrap; }
.fb-lb-bar .t { font-size: calc(12px * var(--type-scale, 1)); font-weight: 600; flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb-lb-bar .t small { font-weight: 400; opacity: .66; }
.fb-lb-bar button { border: 1px solid rgba(255,255,255,.28); background: rgba(255,255,255,.08);
  color: #fff; border-radius: 8px; padding: 5px 11px; font: inherit;
  font-size: calc(12px * var(--type-scale, 1)); font-weight: 600; cursor: pointer; white-space: nowrap; }
.fb-lb-bar button:hover { background: rgba(255,255,255,.18); }
.fb-lb-bar button:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.fb-lb-scroll { flex: 1; min-height: 0; overflow: auto; display: flex;
  align-items: flex-start; justify-content: flex-start; padding: 12px; }
.fb-lb.passend .fb-lb-scroll { align-items: center; justify-content: center; overflow: hidden; }
.fb-lb-img { display: block; background: #fff; box-shadow: 0 18px 50px rgba(0,0,0,.5); cursor: zoom-in; }
.fb-lb.passend .fb-lb-img { max-width: 100%; max-height: 100%; width: auto; height: auto; }
/* 100 %: de opname is op maxBreedte 1400 gemaakt, dus dat is hier ware grootte. */
.fb-lb.echt .fb-lb-img { width: 1400px; max-width: none; height: auto; flex: none; cursor: zoom-out; }
/* De pagina eronder mag niet meebewegen terwijl je in de overlay scrollt. */
body.fb-lb-open { overflow: hidden; }

/* ── De meldingentabel op een telefoon ────────────────────────────────────
   Negen kolommen passen niet op 390px. Tot nu toe stond er een min-width van
   640px op de tabel met overflow-x eromheen: je kón alles zien, maar alleen
   door zijwaarts te slepen, en de statuskolom — juist de kolom waarop je
   scant — lag altijd buiten beeld.

   Onder 760px vervalt daarom de tabel-layout en wordt elke rij een kaart. De
   volgorde in de DOM blijft die van de tabel (dat is wat een schermlezer en
   de export lezen); `order` herschikt alleen wat het oog krijgt:

       ● FB-1024                            [opgepakt]
       als er 2 sloepen zijn gereserveerd en ik deze…
       Receptie receptie · 7 aug 08:46 · activiteiten · bug

   Nummer en status staan bovenaan omdat je daarop zoekt en scant; de melding
   krijgt de volle breedte omdat je daaraan herkent waar het over ging. */
@media (max-width: 760px) {
  .fbt-wrap { overflow-x: visible; }
  table.fbt { min-width: 0; display: block; font-size: calc(13px * var(--type-scale, 1)); }
  table.fbt thead { display: none; }
  table.fbt tbody { display: block; }
  /* Rustige lijst, geen omrande dozen: op mobiel verschilden kaart- en
     pagina-achtergrond nauwelijks, dus de rand rondom was het enige én het
     hardste element (Nicks foto, 7 aug 15:04). Alleen een divider eronder;
     een nieuw bericht krijgt een accentbalkje links in plaats van een
     gekleurde rand rondom.

     SPACING-POLISH (7 aug, avond) — Nick zag de lijst op prod (27 echte
     meldingen): rij-inhoud stond op 2px van de kaartrand, bijna plakkend, en
     de rijen oogden dicht op elkaar. Zijpadding nu 14px, gelijk aan
     .fbt-bar hierboven (ook 14px padding-links/rechts), zodat telling,
     export en rij-inhoud op dezelfde linkerlijn staan. Verticaal 16px zodat
     tekst en dividers ademen. */
  table.fbt tr.row {
    display: flex; flex-wrap: wrap; align-items: center; gap: 3px 8px;
    border: 0; border-bottom: 1px solid var(--border); border-radius: 0;
    padding: 16px 14px; margin: 0; background: none;
    box-sizing: border-box;
  }
  table.fbt tbody tr.row:last-child { border-bottom: 0; }
  table.fbt tr.row:hover td { background: none; }
  /* Accentbalkje zónder de inhoud te verschuiven: de box-shadow ligt bínnen
     de border-box en schuift zelf niets op. Geen eigen padding-left meer
     (was 10px toen de gewone rij 2px had, om de 11px-versprong uit de
     border-left-versie te vermijden) — nu gelijk aan de gewone rij, zodat
     .fbt-c-nr op precies dezelfde x staat, met of zonder accentbalkje. */
  table.fbt tr.row.heeft-nieuw {
    box-shadow: inset 3px 0 0 var(--accent);
  }
  table.fbt td { display: block; border-bottom: 0; padding: 0; }

  .fbt-c-stip   { order: 1; }
  .fbt-c-nr     { order: 2; }
  .fbt-c-status { order: 3; margin-left: auto; }
  /* De melding pakt een eigen regel: flex-basis 100% dwingt de wrap af. */
  .fbt-c-tekst  { order: 4; flex: 0 0 100%; margin: 2px 0 3px; }
  .fbt-c-wie    { order: 5; }
  .fbt-c-wanneer, .fbt-c-mod { order: 6; font-size: calc(11.5px * var(--type-scale, 1)); }
  /* Type-chip en beeld-icoon sluiten de regel rechts af — een chip die midden
     in de metaregel zweeft leest als een losse flard.

     SPACING-POLISH (7 aug, avond) — twee lagen. (1) Het beeld-icoon stond
     ná de chip, dus zónder screenshot bleef .fbt-c-beeld als lege,
     onzichtbare flex-item bestaan en at zijn gap ná de chip op: de chip
     eindigde 8px vóór de kaartrand terwijl de statusbadge op regel 1 wél
     tot de rand kwam. (2) Alleen margin-left:auto op .fbt-c-beeld vóór de
     chip zetten loste dat niet overal op: bij een langere modulenaam paste
     het lege .fbt-c-beeld nét nog op de wie/wanneer/mod-regel (zijn auto-
     margin werd dáár verbruikt) en woei de chip alléén naar een nieuwe
     regel, zonder eigen auto-margin — weer links uitgelijnd (gemeten met
     ≥8 proefmeldingen van wisselende lengte, niet zichtbaar bij een korte
     module). Daarom staat margin-left:auto nu op BEIDE: op welke regel de
     chip ook uitkomt, hij duwt zichzelf altijd naar de kaartrand. */
  .fbt-c-beeld  { order: 7; margin-left: auto; }
  .fbt-c-type   { order: 8; margin-left: auto; }

  /* Geen ·-separators: bij het wrappen kwam zo'n punt los aan een regelbegin
     te staan ("· Bug"). De gap plus de gedempte kleuren scheiden genoeg. */
  .fbt-c-wie b, .fbt-c-wie small { display: inline; }
  .fbt-c-wie small { color: var(--text-muted); margin-left: 5px; }
  .fbt-c-wanneer, .fbt-c-mod { color: var(--text-muted); }
  .fbt-c-tekst .fbt-tekst { white-space: normal; overflow: visible; max-width: none; }
  .fbt-c-beeld .fbt-geen { display: none; }

  .fb-panel { right: 12px; width: calc(100vw - 24px); }
  /* Kop-zone: telling links, export compact rechts — de knop domineerde de
     eerste rij terwijl de telling eronder bungelde. */
  .fbt-telling { margin-left: 0; order: 0; width: auto; margin-right: auto; }
  .fbe-telling { margin-left: 0; order: 9; width: 100%; }
  .fbt-bar #fb-export { font-size: calc(11.5px * var(--type-scale, 1)); padding: 5px 10px; }

  /* De intro duwde de lijst drie regels naar beneden. */
  .module-kop p { font-size: calc(12px * var(--type-scale, 1)) !important; margin: 2px 0 8px !important; }
  .fbe-wanneer { margin-left: 0; width: 100%; }
  .fbd { max-width: 100%; }
  /* De stroom houdt géén eigen max-height meer: in de lade is hij de 1fr-rij
     van het raster en dus precies wat er over is. Alleen het widgetvenster,
     waar meerdere gesprekken gestapeld staan, houdt een plafond. */
  .gsp-mini .gsp-stroom { max-height: min(46vh, 360px); }
  .gsp-blok { max-width: 94%; }
  .fb-lb-scroll { padding: 8px; }
}

/* ── Kijk-modus, tweede laag: openingstijden (Nick, 8 aug 2026) ────────────
   VERVALLEN OP 15 AUG 2026, en niet zomaar weggehaald: de grens is verhuisd,
   niet verdwenen.

   Hier stonden zes selectors die voor de rol `verificatie` de Opslaan-knop, de
   kopieerknop en de dirty-badge verborgen en de tijd- en notitievelden
   onbedienbaar maakten (`body.rol-leesalleen .ot-save` c.s.). Openingstijden is
   nu een eigen shadcn-eiland in een <iframe> met een EIGEN document — precies
   het geval dat de laatste alinea van deze uitleg beschreef als "dekt dit
   niet". `body.rol-leesalleen` staat op het document van de shell en bereikt
   dat frame dus nooit; deze regels zouden vanaf vandaag niets meer selecteren.

   De affordance zit nu ín het eiland: `useRechten().magMuteren` is false voor
   een beperkte leesrol en voor een rol-voorbeeldweergave, en dan tekent de
   kaart geen Opslaan- en geen kopieerknop en staan de velden op `disabled`
   (openingstijden-src/src/components/Kaarten.tsx). Zelfde grens, in het model
   in plaats van in de CSS van een ander document. De guard blijft waar hij
   stond: PATCH /api/openingstijden is een mutatie en valt onder de
   alleen-lezen-regel in requireAuth (403), los van het matrix-recht. */

/* ── Atomaire React-shell vóór de eerste app-paint ────────────────────────
   Alleen zichtbaar ná een geldige sessie en alleen zolang app.js de echte
   zijbalk op zichtbare geometrie toetst. Het vlak volgt al de uiteindelijke
   vorm (256px zijbalk + 48px neutrale kop), maar bevat bewust geen nepknoppen.
   Bij succes wisselen bootvlak en levende shell in één taak; bij fout wordt de
   complete legacy-shell zichtbaar. */
.nav-boot-surface { position:fixed; inset:0; z-index:18; display:flex; overflow:hidden; background:var(--bg); pointer-events:none; }
.nav-boot-surface[hidden] { display:none !important; }
/* Tijdens het bootvlak hoort er niets ÓVER het skelet te staan. De
   feedbackknop deed dat wel — gemeten 24 aug 2026 op 390px: hij stond over het
   derde actievierkantje van de skeletkop heen, dus je zag een echte knop in een
   nepbalk. Zelfde uitsluiting als tijdens de login (body.auth-login hierboven),
   nu ook tijdens het wachten op de zijbalk. app.js zet `nav-shell-wacht` in
   showApp en haalt hem weg zodra de balk aantoonbaar in beeld staat. */
body.nav-shell-wacht #fb-fab,
body.nav-shell-wacht #fb-knop-root,
body.nav-shell-wacht #fb-module-root,
body.nav-shell-wacht #fb-module-portaal { display:none !important; pointer-events:none !important; }
/* De pre-paintklasse wordt alleen gezet wanneer token én gebruiker al lokaal
   bestaan. Daarmee staat bij een refresh met sessie de definitieve vorm al in
   de allereerste paint; zonder sessie blijft de login onaangeraakt. */
html.nav-zijbalk-boot #login-shell { visibility:hidden !important; }
html.nav-zijbalk-boot .nav-boot-surface[hidden] { display:flex !important; }
.nav-boot-zijbalk { width:256px; flex:0 0 256px; padding:14px 16px; border-right:1px solid var(--border); background:var(--panel); display:flex; flex-direction:column; gap:12px; }
.nav-boot-zijbalk img { width:104px; height:auto; margin:0 0 12px; }
/* SKELETVULLING. Hier stond `var(--muted)`, en dat is in dit thema
   `var(--text-muted)` — een TEKSTkleur. Als vlak gebruikt geeft dat massieve
   donkergrijze balken in plaats van een skelet; Nick zag ze 24 aug op zijn
   telefoon. Een skelet hoort een lichte tint van de achtergrond te zijn, geen
   voorgrondkleur. */
.nav-boot-surface i { background: color-mix(in srgb, var(--text-muted) 16%, var(--bg)) !important; }
.nav-boot-zijbalk i { display:block; width:72%; height:12px; border-radius:6px; background:var(--muted); }
.nav-boot-zijbalk i:nth-of-type(2), .nav-boot-zijbalk i:nth-of-type(5) { width:88%; }
.nav-boot-zijbalk .nav-boot-zoek { width:100%; height:34px; margin-bottom:6px; border:1px solid var(--border); background:var(--bg); }
.nav-boot-inhoud { min-width:0; flex:1; display:flex; flex-direction:column; }
.nav-boot-kop { height:48px; flex:0 0 48px; border-bottom:1px solid var(--border); background:var(--bg); display:flex; align-items:center; padding:0 10px; }
.nav-boot-kop i { display:block; width:28px; height:28px; border-radius:8px; background:var(--muted); }
.nav-boot-vlak { flex:1; margin:16px; border:1px solid var(--border); border-radius:12px; background:var(--panel); padding:16px; display:flex; flex-direction:column; gap:12px; }
.nav-boot-vlak i { display:block; height:14px; border-radius:7px; }
.nav-boot-vlak i:nth-of-type(1) { width:46%; }
.nav-boot-vlak i:nth-of-type(2) { width:88%; }
.nav-boot-vlak i:nth-of-type(3) { width:74%; }
.nav-boot-vlak i:nth-of-type(4) { width:81%; }
.nav-boot-kop .nbk-titel { width:110px; height:13px; border-radius:7px; margin-left:10px; }
.nav-boot-kop .nbk-acties { margin-left:auto; display:flex; gap:10px; }
.nav-boot-kop .nbk-acties i { width:22px; height:22px; border-radius:6px; }
@media (max-width:767px) {
  /* De skeletrijen BLIJVEN staan op mobiel (23 aug 2026). Ze stonden hier op
     display:none, waardoor er onder 768px alleen een kopje en een leeg omrand
     vlak overbleef. Toen het herstelscherm na 3 s afsloeg viel dat niet op;
     sinds die klok pas begint als het laden echt begint, kijkt iemand op een
     trage lijn tot ~11 s naar dat lege vlak. Een skelet dat de vorm van de
     navigatie laat zien zegt "hij komt eraan"; een leeg kader zegt niets. */
  /* 24 aug 2026 — DE ZIJBALK GAAT ER OP MOBIEL WEER UIT, maar anders dan
     vóór 23 augustus. Toen was het "weg, en verder niets", en dan bleef er een
     leeg omrand vlak over dat niets zei. Daarom stond hij er weer in.

     Alleen: op een telefoon ís de navigatie geen vaste balk maar een lade. Een
     skelet van 256px belooft dus een vorm die nooit komt — op 390px vult hij
     twee derde van het scherm, en dat is wat Nick zag. Nu krijgt mobiel het
     skelet van de vorm die er wél aankomt: de kopbalk met hamburger, titel en
     acties, en daaronder rijen. Geen leeg kader, en geen valse belofte. */
  .nav-boot-zijbalk { display:none; }
  .nav-boot-kop { height:calc(48px + env(safe-area-inset-top, 0px)); flex-basis:calc(48px + env(safe-area-inset-top, 0px)); padding:0 12px; padding-top:env(safe-area-inset-top, 0px); }
  .nav-boot-kop > i:first-child { width:30px; height:30px; border-radius:8px; }
  .nav-boot-vlak { margin:12px; padding:14px; }
  .nav-boot-vlak i { height:16px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   ZIJBALK-EILAND — de shell maakt ruimte (PLAN-nav-implementatie.md stap 2)

   Alles hieronder hangt aan `body.nav-zijbalk`. `index.html` zet bij een
   bestaande sessie vóór de eerste paint `html.nav-zijbalk-boot`, die uitsluitend
   het neutrale bootvlak toont. `startZijbalk` zet de blijvende bodyklasse pas
   ná zichtbare geometrie; bij import-fout verdwijnt de bootklasse en blijft het
   vangnet (oude launchpad) zichtbaar.

   `--zijbalk-b` is de breedte van de balk; het eiland schrijft hem op
   <html> bij elke in-/uitklap (opInklap). De terugvalwaarde 256px is
   SIDEBAR_WIDTH van shadcn — als het eiland om welke reden dan ook nog niets
   geschreven heeft, staat de inhoud alsnog op de goede plek.
   ══════════════════════════════════════════════════════════════════════════ */
/* Dit blok regelt uitsluitend de vaste desktopvariant vanaf 768px. Dezelfde
   React-shell gebruikt daaronder een Sheet; de aparte mobiele regels direct
   na dit blok houden daarom nul permanente zijbalkbreedte aan. */
@media (min-width: 768px) {
  /* Overdrachtsstand: maak uitsluitend de NIEUWE balk zichtbaar/meetbaar.
     De oude `.app-sidebar` blijft in deze stand onaangeraakt en de shell krijgt
     nog geen marge. Pas nadat app.js levende geometrie + hit-testing ziet,
     wisselt de body atomair naar `nav-zijbalk`. */
  body.nav-zijbalk-kandidaat #zijbalk-root [data-slot="sidebar"] { display: block !important; }
  body.nav-zijbalk-kandidaat #zijbalk-root [data-slot="sidebar-container"] { display: flex !important; }
  body.nav-zijbalk .app-sidebar { display: none !important; }
  /* ── Twee navigatiekolommen naast elkaar (Nick, 10 aug 2026) ──────────────
     De regel hierboven is 0-2-1. De embed-uitzonderingen op r5552-5566
     (`body.bo-embed[data-zb="feedback|jachthaven|kamers|logboek|openingstijden"]
     .app-sidebar { display: flex !important }`) zijn 0-3-1 en wonnen dus, óók
     met het zijbalk-eiland aan: de oude kolom stond pal naast de nieuwe, mét
     terug-pijl naar de launchpad, een tweede moduletitel en nóg een
     "Welkom, Nick". Gemeten op dev, 1512px: zijbalk op x=0-256, oude kolom
     op x=266 (235 breed). Vijf modules, Beheer en Betalingen niet.

     Die uitzonderingen dateren van 2 aug, toen `.app-sidebar` daar de énige
     navigatie was; sinds het eiland is dat het eiland. Ze blijven staan omdat
     de terugval `?nav=oud` ze nog nodig heeft — hier alleen geneutraliseerd
     wanneer de zijbalk daadwerkelijk draait. 0-4-1 wint van 0-3-1; het
     `[data-zb]`-deel houdt de regel op precies dezelfde groep gericht. */
  body.nav-zijbalk.bo-embed[data-zb] .app-sidebar { display: none !important; }
  /* ── De zijbalk mag niet verdwijnen door een andere eilandbundel ──────────
     Gevonden 10 aug 2026, en dit verklaart de klacht "soms is de nav ineens
     helemaal weg". `feedback/feedback.css` is óók een Tailwind-bundel en bevat
     `@layer utilities{.hidden{display:none}}`. Landt hij ná `zijbalk.css`, dan
     wint die `.hidden` van de `md:block` van de shadcn-Sidebar: zelfde laag,
     zelfde gewicht, latere stylesheet. De zijbalk is dan wél gemount maar meet
     0 px breed. Wélke bundel als laatste binnenkomt hangt af van de volgorde
     waarin de imports terugkomen, dus het wisselt per laadbeurt — precies het
     grillige beeld dat gemeld werd.

     Deze regels staan in `theme.css` (ongelaagd) en winnen daarmee per definitie
     van álles in een `@layer`, ongeacht welke bundel later landt. Er zijn twee
     elementen met Tailwinds `.hidden`: de 0×0 layout-wrapper `sidebar` én de
     werkelijk getekende, fixed `sidebar-container`. Alleen de eerste forceren
     verklaarde het gemeten patroon van 10 aug: de balk was kort zichtbaar en
     verdween weer zodra feedback.css later binnenkwam. Daarom worden beide
     desktoplagen vastgezet. Alleen boven 768 px; mobiel gebruikt de Sheet. */
  body.nav-zijbalk #zijbalk-root [data-slot="sidebar"] { display: block !important; }
  body.nav-zijbalk #zijbalk-root [data-slot="sidebar-container"] { display: flex !important; }
  body.nav-zijbalk .app-shell {
    margin-left: var(--zijbalk-b, 256px);
    transition: margin-left .2s linear;
  }
}
/* Telefoon gebruikt dezelfde React-shell zonder permanente kolom. De vaste
   neutrale kop bevat de menutrigger; de navigatie opent als Shadcn Sheet. */
@media (max-width: 767px) {
  /* Atomaire overdracht op mobiel: de legacy-topbar is z-index 40 en blijft
     tijdens het meten bewust als vangnet aanwezig. Zet uitsluitend de
     kandidaatroot en zijn levende kop erboven; pas na de bestaande geometrie-
     én hit-test verwijdert app.js het vangnet. Een kapotte/ontbrekende bundel
     raakt deze regels dus nooit en houdt de oude navigatie volledig intact. */
  body.nav-zijbalk-kandidaat #zijbalk-root,
  body.nav-zijbalk-kandidaat #zijbalk-root [data-nav-shell-ready][data-nav-vorm="mobiel"] {
    z-index: 50;
  }
  /* De zichtbaarheidspoort eist terecht een raakvlak van minstens 40px. De
     Shadcn-trigger was buiten `pointer:coarse` slechts size-7 (28px), waardoor
     een telefoonbreed venster met muis/fine-pointer na drie seconden onterecht
     terugviel. Een mobiele menuknop is in elke invoermodus 44×44; de poort
     blijft ongewijzigd en meet nu het werkelijk aangeboden raakvlak. */
  #zijbalk-root [data-nav-shell-ready][data-nav-vorm="mobiel"] [data-nav-inklap] {
    width: 44px !important;
    min-width: 44px !important;
    height: 44px !important;
    min-height: 44px !important;
  }
  body.nav-zijbalk .app-sidebar,
  body.nav-zijbalk.bo-embed[data-zb] .app-sidebar { display:none !important; }
  body.nav-zijbalk .app-shell { margin-left:0 !important; }
  body.nav-zijbalk .app-topbar {
    min-height:calc(48px + env(safe-area-inset-top, 0px)) !important;
    height:calc(48px + env(safe-area-inset-top, 0px)) !important;
    padding:env(safe-area-inset-top, 0px) 8px 0 !important;
    gap:0 !important;
    background:var(--bg) !important;
    border-bottom:1px solid var(--border) !important;
    justify-content:flex-start !important;
  }
  body.nav-zijbalk .app-topbar .app-brand,
  body.nav-zijbalk .app-topbar .sidebar-toggle,
  body.nav-zijbalk .app-topbar #app-switcher,
  body.nav-zijbalk .app-topbar .cmd-trigger,
  body.nav-zijbalk .app-topbar #tb-scan,
  body.nav-zijbalk .app-topbar .theme-seg,
  body.nav-zijbalk .app-topbar .datum-nav,
  body.nav-zijbalk .app-topbar .topbar-actions { display:none !important; }
}
/* DE OUDE NAVIGATIE IS DEFINITIEF UIT BEELD (19 aug 2026). Nick zag op 18 aug
   de oude hamburger-nav terug op zijn iPhone: "Ik wil die niet meer zien. Ook
   niet als fallback." Het `nav-oud-vangnet`-pad is uit app.js verwijderd; dit
   slot is de laatste grendel. De `.module-btn`-DOM in `.app-sidebar` blijft
   bewust bestaan als rechtenbron (lpVisibleMods leest `hidden`/
   `data-roleHidden` — eigenschappen, geen geometrie), maar mag onder geen
   enkele klassestand meer in beeld komen — ook niet als een body-vlag ooit
   ontbreekt of te laat gezet wordt. Vandaar onvoorwaardelijk en !important.
   `#launchpad` wordt nergens meer aangemaakt; de regel hier vangt ook een
   oude shell die 'm nog uit eigen code zou bouwen. */
.app-sidebar,
#sidebar-backdrop,
#launchpad { display: none !important; }
@media (prefers-reduced-motion: reduce) {
  body.nav-zijbalk .app-shell { transition: none; }
}
/* De launchpad is `position:fixed; inset:0` en hoort de hele breedte te
   houden als hij tóch nog een keer wordt geopend (het merklogo in de balk
   gaat ernaartoe) — dus die schuift bewust NIET mee op. */
@media (min-width: 768px) {
  body.nav-zijbalk #launchpad { margin-left: calc(-1 * var(--zijbalk-b, 256px)); width: 100vw; }
}

/* ══════════════════════════════════════════════════════════════════════════
   ÉÉN GEHEEL — de topbalk krimpt tot een strook (Nick, 10 aug 2026)

   Wat hij zag toen de zijbalk op productie stond: "linksboven het logo zetten?
   En het oogt nu niet als 1 geheel. De topbalk is er ook nog, het is nu een
   rommeltje." Dat klopte: er stonden TWEE MERKDRAGERS (het logo in de navy
   topbalk én het letterblok in de zijbalkkop) en TWEE NAVIGATIELAGEN (de
   zijbalk, en in de topbalk het rastericoon naar de launchpad).

   Dit blok haalt die dubbeling weg volgens het shadcn-dashboardpatroon: de
   zijbalk draagt het merk (dat deel zit in het eiland), en van de topbalk
   blijft een strook van 48px over met de inklapknop, waar-je-bent en een paar
   acties.

   WAAR ELK ONDERDEEL GEBLEVEN IS — niets is onbereikbaar geworden:
     · logo `#app-brand`   → naar de zijbalkkop (het eiland tekent het daar).
                             Dezelfde klik: naar de launchpad, via `opMerk`.
     · `#app-switcher`     → vervalt: het merk in de zijbalk gaat naar dezelfde
                             launchpad. Twee knoppen, één bestemming.
     · `#cmd-trigger` ⌘K   → vervalt: de zoekrij in de zijbalkkop klikt deze
                             knop aan (`opZoek`). Blijft in de DOM, dus ⌘K en
                             de klik-doorgifte werken onveranderd.
     · `#theme-seg`        → vervalt hier: de thema-knop staat in de voet van de
                             zijbalk. LET OP de selector: alleen bínnen de
                             topbalk. Het segment verhuist bij het openen van de
                             launchpad naar `.lp-top-actions` en hoort daar
                             gewoon zichtbaar te blijven.
     · `.sidebar-toggle`   → vervalt: die klapt de OUDE `.app-sidebar` uit, en
                             die staat hierboven op `display:none`. Boven 1100px
                             was hij sowieso al verborgen (r675-677); tussen 768
                             en 1099px zou hij een lege lade opentrekken.
                             De inklapknop van de zijbalk staat ervoor in de
                             plaats.
     · `#tb-scan`          → vervalt óók (Nick, 10 aug 2026, ná de cutover:
                             "bij productie mag het qr scanner icoon rechtsboven
                             weg"). Hij bleef eerst staan als "enige actie" —
                             de balie scant de hele dag door — maar de QR-module
                             staat als eigen rij in de zijbalk, dus de snelknop
                             was een tweede ingang naar dezelfde plek. Zelfde
                             regel als de rest: uit beeld, NIET uit de DOM (zie
                             het commentaar bij de verbergregel hieronder).
     · `.datum-nav`        → onveranderd. Die verhuisde al in juli naar de witte
                             databalk boven de planning (`#adb-mount`, app.js);
                             hij zit dus allang niet meer in de topbalk.

   ALLES HANGT AAN `body.nav-zijbalk`, en dat is de hele afspraak: wie de vlag
   niet gebruikt, houdt de navy topbalk van 56px met logo, launchpad en zoekbalk
   precies zoals vandaag.

   HET BLOK ZIT BEWUST BINNEN `min-width: 768px`, net als de vaste desktopbalk.
   Mobiel krijgt dezelfde neutralisering in het afzonderlijke Sheet-blok.
   ══════════════════════════════════════════════════════════════════════════ */
@media (min-width: 768px) {
  body.nav-zijbalk .app-topbar {
    /* 48px = KOP_H in zijbalk-src/src/mount.tsx; daar hangt de inklapknop erin.
       De meter toetst niet dit getal maar of die knop binnen dit vlak valt. */
    min-height: 48px;
    height: 48px;
    padding: 0 16px;
    gap: 10px;
    /* Terug naar het neutrale vlak van r3647: dezelfde achtergrond als de
       inhoud eronder, met alleen een haarlijn ertussen. Een navy balk naast een
       bijna-witte zijbalk blíjft twee talen — dát is wat "geen 1 geheel" was.
       `!important` omdat r4459 de navy met `!important` oplegt. */
    background: var(--bg) !important;
    border-bottom: 1px solid var(--border) !important;
    /* `body.bo-embed .app-topbar` (index.html r200) zet `space-between`. Met
       nog maar één zichtbare groep zou dat niets uitmaken (`.topbar-actions`
       heeft `margin-left:auto`), maar expliciet is hier beter dan afhankelijk
       van een auto-marge die iemand later weghaalt. */
    justify-content: flex-start;
  }

  /* Verhuisd naar de zijbalk, of daar al aanwezig. Uit beeld, NIET uit de DOM:
     `beperkNavigatieAffordances` zet `hidden` op deze knoppen per rol en de
     rechtenmeting leest die eigenschap af. Zou ik ze hier weghalen of hun
     `hidden` aanraken, dan meet die toets een leegte in plaats van een recht.
     Dat geldt sinds 10 aug ook voor `#tb-scan` (zie het kopblok): de knop
     blijft in de DOM en `beperkNavigatieAffordances` blijft zijn `hidden` per
     rol zetten — deze regel haalt hem alleen uit beeld. `?nav=oud` (zonder de
     body-vlag) toont hem nog gewoon in de navy topbalk. */
  body.nav-zijbalk .app-topbar .app-brand,
  body.nav-zijbalk .app-topbar .sidebar-toggle,
  body.nav-zijbalk .app-topbar #app-switcher,
  body.nav-zijbalk .app-topbar .cmd-trigger,
  body.nav-zijbalk .app-topbar #tb-scan,
  body.nav-zijbalk .app-topbar .theme-seg {
    display: none !important;
  }

  /* Wat overblijft stond met witte iconen op navy (r4465-4478). Op het lichte
     vlak zou dat wit-op-wit zijn — onzichtbaar, niet "subtiel". */
  body.nav-zijbalk .app-topbar .datum-arrow,
  body.nav-zijbalk .app-topbar .topbar-actions > button {
    color: var(--text-muted) !important;
    background: transparent !important;
    border-color: var(--border) !important;
  }
  body.nav-zijbalk .app-topbar .datum-arrow:hover,
  body.nav-zijbalk .app-topbar .topbar-actions > button:hover {
    background: var(--hover) !important;
    color: var(--text) !important;
  }
}

/* ── QR-eiland (10 aug 2026) ─────────────────────────────────────────────────
 * Het React-eiland van de scanpagina mount met opzet ZONDER de klassen
 * `.scan-page`/`.scan-page-host`: die dragen hierboven `!important`-maten
 * (r4695 input-padding, r4749 knop-radius) en zouden de shadcn-maten van het
 * eiland overschrijven. Dat is precies de fout die de handgemaakte nabootsing
 * maat-vals maakte.
 *
 * De twee bijwerkingen van `.scan-page` die we WÉL willen, staan daarom hier
 * apart — letterlijk de spiegel van r4693-4694. Meer dan deze twee regels
 * hoort er niet te staan: al het andere komt uit de gescopeerde eiland-CSS. */
.app-body:has(#qrscan-eiland) .app-sidebar { display: none !important; }
.app-body:has(#qrscan-eiland) #act-databalk { display: none !important; }

/* ── Ontbrekende gegevens (Jachthaven → Ontbrekend) ──────────────────────────
   Eén blok per soort ontbrekend veld. Het aantal staat links en groot: dat is
   waar je op stuurt. Amber en niet rood — het is werk dat nog moet gebeuren,
   geen storing. */
.ont-groep { border: 1px solid var(--border); border-radius: 10px; padding: 14px 16px;
  margin-bottom: 12px; background: var(--surface); }
.ont-kop { display: flex; gap: 14px; align-items: flex-start; }
.ont-aantal { flex: none; min-width: 46px; text-align: center; font-size: 20px; font-weight: 700;
  color: #92400E; background: #FEF3C7; border: 1px solid #FCD34D; border-radius: 8px;
  padding: 4px 8px; font-variant-numeric: tabular-nums; }
.ont-gevolg { color: var(--text-muted); font-size: 13px; margin-top: 3px; max-width: 62ch; }
.ont-door { color: var(--text-faint); font-size: 12.5px; margin-top: 4px; }
.ont-lijst { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; padding-left: 60px; }
.ont-chip { font-size: 12.5px; padding: 3px 9px; border-radius: 999px;
  background: var(--hover); color: var(--text-muted); border: 1px solid var(--border); }
@media (max-width: 640px) { .ont-lijst { padding-left: 0; } }

/* ══════════════════════════════════════════════════════════════════════════
   MOBIEL: RUIMTE ONDER DE VASTE KOPBALK (Nick, 15 aug 2026)

   De mobiele kop van het zijbalk-eiland staat `position: fixed` en is 48px hoog
   (KOP_H in zijbalk-src/src/mount.tsx). Het inhoudsvlak eronder begon óók op 0,
   dus de bovenkant van elk scherm lag eronder. Gemeten op de Activiteiten-embed:
   de knop "Nieuwe boeking" begint op 16px en is 36px hoog, de kop loopt tot 48px
   — 32 van de 36px onzichtbaar. Je zag alleen een donker randje. Omhoog scrollen
   hielp niet: binnen dat kader stond de inhoud al bovenaan, er was niets om naar
   toe te scrollen.

   De hoogte staat hier hardgecodeerd om dezelfde reden als in het blok hierboven:
   de gate meet niet dit getal maar of de eerste knop vrij ligt.

   `!important` is nodig omdat `.app-main--embed` (r4010) de padding met
   `!important` op 0 zet — die regel is er voor het iframe dat zelf zijn randen
   bepaalt, en dat blijft zo; alleen de bovenkant krijgt zijn ruimte terug.

   De regel hangt aan `:has(...)` en niet aan een body-klasse: die klasse wordt
   pas gezet ná de zichtbaarheidscontrole, en dan is het te laat. Dit kijkt naar
   wat er werkelijk staat.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 47.999rem) {
  body:has(#zijbalk-root [data-nav-shell-ready][data-nav-vorm="mobiel"]) .app-main,
  body:has(#zijbalk-root [data-nav-shell-ready][data-nav-vorm="mobiel"]) .app-main--embed {
    padding-top: calc(48px + env(safe-area-inset-top, 0px)) !important;
  }
}
