/* Tombeton Portaal: designtokens 27 Automations (bron: colors_and_type.css van het
   design system, gekopieerd per playbook-regel "kopieer tokens, herbouw ze niet")
   plus portaal-chrome. Geen inline hex buiten deze tokens. */

@font-face {
  font-family: 'Outfit';
  src: url('../fonts/Outfit-VariableFont_wght.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --brand-deep-blue: #0F2EA3;
  --brand-off-black: #050A30;
  --brand-azure-blue: #2458EA;
  --brand-bright-blue: #1D58FF;
  --brand-sky-blue: #28AFF9;
  --brand-lemon-lime: #D1F24C;
  --brand-warm-white: #F7F3EA;
  --brand-ink: #050A30;
  --brand-gradient: linear-gradient(100deg, #0F2EA3 0%, #2458EA 45%, #28AFF9 100%);

  --neutral-0: #FFFFFF;  --neutral-50: #F7F3EA; --neutral-100: #EFEADD;
  --neutral-200: #DFD9C8; --neutral-300: #C4BEAC; --neutral-400: #8E8979;
  --neutral-500: #5E5A4F; --neutral-600: #3D3A33; --neutral-900: #050A30;

  --bg: var(--brand-warm-white);
  --bg-elevated: #FFFDF8;
  --bg-subtle: var(--neutral-100);
  --bg-inverse: var(--brand-deep-blue);
  --bg-ink: var(--brand-off-black);
  --fg: var(--brand-ink);
  --fg-muted: var(--neutral-500);
  --fg-subtle: var(--neutral-400);
  --fg-on-blue: var(--brand-warm-white);
  --fg-on-lime: var(--brand-off-black);
  --border: var(--neutral-200);
  --border-strong: var(--neutral-300);

  --link: var(--brand-azure-blue);
  --link-hover: var(--brand-deep-blue);
  --focus-ring: var(--brand-azure-blue);

  --success-bg: #F4FBDB; --success-fg: #4A6B0E;
  --info-bg: #E0F1FD;    --info-fg: #0F2EA3;
  --warning-bg: #FBF1D9; --warning-fg: #6B4D04;
  --danger-bg: #F7E0DB;  --danger-fg: #6E2218;
  /* De accentlijn van "let op". Deze stond nergens, terwijl .intern en de
     taakblokken storten/vullen er wel naar verwezen. Een var() die niet bestaat
     maakt de HELE declaratie ongeldig: die border en die border-left-color
     vielen dus stil weg. Zelfde amber als SOORT_KLEUR.storten in
     views-planning.js, zodat kalender en kaarten dezelfde kleur spreken. */
  --warning: #C99410;

  /* Vandaag markeren zoals de hub het doet (shared/cal-kit.js): een zachte tint
     op de dag zelf en een gevulde blauwe pil rond de datum. NOOIT een outline:
     die valt buiten de layout en snijdt dwars door een raster heen. */
  --vandaag-tint: #F4F7FF;
  --vandaag-merk-bg: var(--brand-azure-blue);

  --font-sans: 'Outfit', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: ui-monospace, 'SF Mono', Menlo, monospace;
  --fw-light: 300; --fw-regular: 400; --fw-medium: 500; --fw-semibold: 600;

  --fs-h1: clamp(28px, 3.4vw, 40px);
  --fs-h2: clamp(22px, 2.6vw, 30px);
  --fs-h3: 20px; --fs-h4: 17px;
  --fs-body: 15px; --fs-body-sm: 13px; --fs-caption: 12px;

  --r-xs: 6px; --r-sm: 10px; --r-md: 14px; --r-lg: 20px;
  --r-xl: 24px; --r-2xl: 28px; --r-3xl: 40px; --r-pill: 999px;

  --shadow-card: 0 4px 24px -8px rgba(5, 10, 48, 0.06);
  --shadow-md: 0 10px 30px -10px rgba(5, 10, 48, 0.08);
  --shadow-lg: 0 24px 50px -18px rgba(5, 10, 48, 0.12);
  /* Zwaarste trap, voor wat echt boven de pagina zweeft: het meldingenpaneel en
     het modale paneel op desktop. Beide vroegen er al naar terwijl de token
     nergens stond, en een ongeldige var() gooit de hele declaratie weg: die
     panelen zweefden dus zonder enige schaduw boven de inhoud. */
  --shadow-xl: 0 32px 70px -22px rgba(5, 10, 48, 0.22);

  --ease-standard: cubic-bezier(0.2, 0.8, 0.2, 1);
  --dur-fast: 140ms; --dur-base: 220ms;

  /* z-index-schaal, gedocumenteerd en vast (playbook hfst. 9) */
  --z-pop: 50; --z-menu: 60; --z-panel: 120; --z-modal: 130;

  --s27-topbar-h: 56px;
  --s27-bottomnav-h: 62px;

  /* Knopmaten op EEN plek. De COMPACT-sectie onderaan zet deze drie waarden
     opnieuw; elke .knop-variant rekent eruit, zodat een rij knoppen naast
     elkaar altijd dezelfde hoogte heeft, met of zonder pijlbox. */
  --knop-h: 44px;          /* hoogte van elke knopvariant */
  --knop-pijl: 30px;       /* het vierkante pijlboxje rechts in de knop */
  --knop-pad: 18px;        /* ademruimte links en rechts van het label */
  --knop-lucht: calc((var(--knop-h) - var(--knop-pijl)) / 2);  /* rand rond de pijlbox */
}

/* Mobiel fundament (playbook hfst. 10): vanaf dag 1, geen afwerking achteraf. */

/* border-box overal, net als in de hub. Zonder deze regel telt een <input> zijn
   padding en rand BOVEN op min-height (36 + 14 + 2 = 52px) terwijl een <select>
   ernaast wel op 36px uitkomt: dat was de scheve filterbalk en de scheve
   formulierrijen. Elke maat in dit bestand is op border-box gerekend. */
*, *::before, *::after { box-sizing: border-box; }

html { color-scheme: light; }
/* hidden wint ALTIJD, ook van klassen met een eigen display-waarde. */
[hidden] { display: none !important; }
html, body { overflow-x: clip; }             /* clip, NIET hidden (breekt sticky) */
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-weight: var(--fw-light);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  padding-top: calc(var(--s27-topbar-h) + env(safe-area-inset-top));
  padding-bottom: calc(var(--s27-bottomnav-h) + env(safe-area-inset-bottom));
}
body.kb-open #tb-bottomnav { display: none; }  /* onderbalk weg bij open toetsenbord */

h1 { font-size: var(--fs-h1); font-weight: var(--fw-light); letter-spacing: -0.02em; margin: 0; }
h2 { font-size: var(--fs-h2); font-weight: var(--fw-light); letter-spacing: -0.015em; margin: 0; }
h3 { font-size: var(--fs-h3); font-weight: var(--fw-medium); margin: 0; }
h4 { font-size: var(--fs-h4); font-weight: var(--fw-medium); margin: 0; }
a { color: var(--link); text-decoration: none; font-weight: var(--fw-medium); }
a:hover { color: var(--link-hover); text-decoration: underline; }

/* Class look: kaarten */
.kaart {
  background: var(--bg-elevated);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-card);
  padding: 24px;
  transition: transform var(--dur-base) var(--ease-standard), box-shadow var(--dur-base) var(--ease-standard);
}
.kaart:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
/* Een kaart met een lijst erin mag NIET liften. Een transform maakt van de kaart
   het containing block voor position:fixed, en dan landen het kolommenmenu, de
   periodekiezer en de klik-buiten-laag van S27Table verschoven of onbereikbaar. */
.kaart:has(.s27-bleed):hover, .kaart:has([data-s27lijst]):hover { transform: none; }

/* Knoppen: label + arrow-box rechts (merk-signatuur).
   Zonder pijlbox is de knop SYMMETRISCH; alleen een knop MET pijlbox houdt de
   smallere rechterrand, want daar vult het vierkantje de ruimte op. */
.knop {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  box-sizing: border-box;
  min-height: var(--knop-h); padding: var(--knop-lucht) var(--knop-pad);
  border: 0; border-radius: var(--r-md);
  font: var(--fw-semibold) var(--fs-body) var(--font-sans);
  line-height: 1.2;
  cursor: pointer;
  transition: filter var(--dur-fast) var(--ease-standard);
}
.knop:has(.pijlbox) { padding-right: var(--knop-lucht); }
.knop .pijlbox {
  width: var(--knop-pijl); height: var(--knop-pijl); border-radius: var(--r-sm);
  display: inline-flex; align-items: center; justify-content: center; flex: none;
}
.knop-lime { background: var(--brand-lemon-lime); color: var(--fg-on-lime); }
.knop-lime .pijlbox { background: var(--brand-off-black); color: #fff; }
.knop-lime:hover { filter: brightness(0.96); }
.knop-navy { background: var(--brand-off-black); color: #fff; }
.knop-navy .pijlbox { background: #fff; color: var(--brand-off-black); }
.knop-navy:hover { filter: brightness(1.15); }
.knop-outline { background: transparent; color: var(--fg); box-shadow: inset 0 0 0 1px var(--border-strong); }

/* Statuspills: klikbaar, ook op mobiel de handigste tap-target */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 12px; border-radius: var(--r-pill);
  font-size: var(--fs-body-sm); font-weight: var(--fw-medium);
  min-height: 28px; cursor: pointer;
}
.pill-info { background: var(--info-bg); color: var(--info-fg); }
.pill-ok { background: var(--success-bg); color: var(--success-fg); }
.pill-warn { background: var(--warning-bg); color: var(--warning-fg); }
.pill-danger { background: var(--danger-bg); color: var(--danger-fg); }
/* Afwachtend, niet fout: de wachtstand van een planningstaak ("In te plannen").
   Zonder deze regel stond die status als kale tekst zonder pilvorm tussen de
   gekleurde pills. Neutraal grijs op beige haalt ruim het contrastminimum. */
.pill-neutraal { background: var(--neutral-100); color: var(--neutral-600); }

/* Gedeelde chrome: LEEFT OP document.body, buiten #app-root (playbook hfst. 8). */
#tb-topbar {
  position: fixed; top: 0; left: 0; right: 0;
  height: calc(var(--s27-topbar-h) + env(safe-area-inset-top));
  padding-top: env(safe-area-inset-top);
  display: flex; align-items: center; gap: 14px;
  padding-left: 16px; padding-right: 16px;
  background: rgba(255, 253, 248, 0.72);
  backdrop-filter: blur(16px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.6);
  z-index: var(--z-menu);
  transition: transform var(--dur-base) var(--ease-standard);
}
body.tb-hidden #tb-topbar { transform: translateY(-100%); } /* verbergt bij omlaag scrollen */
#tb-topbar img.logo { height: 26px; }
#tb-topbar .titel { font-weight: var(--fw-medium); font-size: var(--fs-body); }

#tb-bottomnav {
  position: fixed; bottom: 0; left: 0; right: 0;
  height: calc(var(--s27-bottomnav-h) + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  display: flex; align-items: stretch; justify-content: space-around;
  background: var(--bg-elevated);
  border-top: 1px solid var(--border);
  z-index: var(--z-menu); /* onderbalk blijft ALTIJD zichtbaar */
}
/* .bn-item is de nette haak op ditzelfde item; de maten blijven hier staan,
   want een id-selector weegt zwaarder dan een klasse en zou een losse
   .bn-item-regel toch overschrijven. */
#tb-bottomnav a, #tb-bottomnav .bn-item {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; min-height: 44px; min-width: 0; padding: 4px 2px;
  color: var(--fg-muted); font-size: var(--fs-caption); font-weight: var(--fw-medium);
  text-decoration: none;
}
/* Houder van het pictogram: vaste hoogte, zodat alle vijf de labels op dezelfde
   lijn staan ook als het ene pictogram hoger tekent dan het andere. De pilvorm
   staat er al klaar voor de actieve toestand hieronder. */
#tb-bottomnav .bn-icoon {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  height: 24px; min-width: 24px; padding: 0 9px; border-radius: var(--r-pill);
  transition: background var(--dur-fast) var(--ease-standard);
}
/* Kleiner dan de 12px van het item, en nooit over twee regels: vijf items op
   375px betekent 75px per item, en "Dashboard" past daar maar op een regel in
   als het label krimpt en desnoods afkapt. */
#tb-bottomnav .bn-label {
  font-size: 11px; line-height: 1.15; white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
#tb-bottomnav a.actief { color: var(--brand-azure-blue); }
/* Actief leunt niet alleen op kleur: het pictogram krijgt een gevulde pil en
   het label wordt zwaarder. Zo blijft de actieve tab leesbaar voor wie het
   kleurverschil niet ziet. */
#tb-bottomnav a.actief .bn-icoon { background: rgba(36, 88, 234, 0.14); }
#tb-bottomnav a.actief .bn-label { font-weight: var(--fw-semibold); }

/* Overlays boven de bottom-nav met bottom-inset (playbook hfst. 10) */
.overlay-backdrop {
  position: fixed; inset: 0; z-index: var(--z-modal);
  background: rgba(5, 10, 48, 0.5); backdrop-filter: blur(3px);
  display: flex; align-items: flex-end; justify-content: center;
}
/* Drie paneelmaten, en niets ertussen (zie TB.paneel in ui.js):
   standaard = een kolom velden of een bevestiging,
   .paneel-midden = twee kolommen velden (sp-6 + sp-6),
   .paneel-breed = drie kolommen, een tabel of een kalender ernaast. */
.overlay-paneel {
  background: var(--bg-elevated); border-radius: var(--r-xl) var(--r-xl) 0 0;
  width: min(560px, 100%); max-height: 85dvh; overflow-y: auto;
  overscroll-behavior: contain;
  padding: 24px; padding-bottom: calc(24px + env(safe-area-inset-bottom));
}
.overlay-paneel.paneel-midden { width: min(760px, 100%); }
.overlay-paneel.paneel-breed { width: min(1100px, 100%); }

/* Lege staten: duidelijke reden, nooit nepdata (playbook #6). */
.leeg {
  padding: 40px 24px; text-align: center; color: var(--fg-muted);
  background: var(--bg-subtle); border-radius: var(--r-lg);
}

.scherm { padding: 16px; max-width: 1200px; margin: 0 auto; }
@media (min-width: 900px) { .scherm { padding: 24px 32px; } }

/* ---------- componenten ---------- */
.kop-met-actie { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }

.tb-input {
  font: var(--fw-regular) var(--fs-body) var(--font-sans);
  padding: 10px 12px; border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  background: #fff; color: var(--fg); width: 100%; min-height: 44px;
}
.tb-veld { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 140px; margin-top: 10px; }
.tb-veld-label { font-size: var(--fs-caption); font-weight: var(--fw-semibold); color: var(--fg-muted); text-transform: uppercase; letter-spacing: 0.08em; }
.veld-rij { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-start; }
.tb-check { display: flex; align-items: center; gap: 8px; margin-top: 8px; min-height: 32px; cursor: pointer; }
.tb-check input { width: 18px; height: 18px; }

.tb-tabel-wrap { overflow-x: auto; margin-top: 12px; }
.tb-tabel { width: 100%; border-collapse: collapse; background: var(--bg-elevated); border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--shadow-card); }
.tb-tabel th { text-align: left; font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-muted); padding: 12px 14px; border-bottom: 1px solid var(--border); }
.tb-tabel td { padding: 12px 14px; border-bottom: 1px solid var(--neutral-100); vertical-align: middle; }
.tb-tabel tr:last-child td { border-bottom: 0; }
.tb-tabel tr.klikbaar { cursor: pointer; }
.tb-tabel tr.klikbaar:hover td { background: var(--bg-subtle); }
.tb-tabel th.r, .tb-tabel td.r { text-align: right; }

.paneel-kop { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
/* 40px en niet 32: het kruisje is op een gsm vaak de enige uitweg uit een paneel,
   en dat mag geen mikoefening zijn. Op desktop blijft het rustig ogen omdat de
   achtergrond licht is en het teken zelf niet meegroeit. */
.sluitknop {
  width: 40px; height: 40px; border-radius: 11px; border: 0;
  background: var(--bg-subtle); font-size: 20px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; flex: none;
}

.tb-toast {
  position: fixed; left: 50%; bottom: calc(var(--s27-bottomnav-h) + env(safe-area-inset-bottom) + 14px);
  transform: translate(-50%, 20px); opacity: 0; transition: all var(--dur-base) var(--ease-standard);
  background: var(--brand-off-black); color: #fff; padding: 12px 18px; border-radius: var(--r-md);
  z-index: 2147483000; max-width: min(480px, 92vw); box-shadow: var(--shadow-lg); font-size: var(--fs-body-sm);
}
.tb-toast.zichtbaar { transform: translate(-50%, 0); opacity: 1; }
.tb-toast-fout { background: var(--danger-fg); }
.tb-toast-ok { background: #12652F; }

.kpi-raster { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px; margin-top: 16px; }
.kpi .kpi-waarde { font-size: 28px; font-weight: var(--fw-light); }
.kpi-label { font-weight: var(--fw-medium); margin-top: 4px; }
.kpi-sub { font-size: var(--fs-body-sm); color: var(--fg-muted); }
.melding { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--neutral-100); flex-wrap: wrap; }
.melding:last-child { border-bottom: 0; }

.regelrij { border: 1px solid var(--neutral-100); border-radius: var(--r-sm); padding: 10px 12px; margin-top: 8px; background: #fff; }
.regelrij.kopregel { background: var(--bg-subtle); font-weight: var(--fw-semibold); }
.regelrij.optioneel { border-style: dashed; color: var(--fg-muted); }
.regel-hoofd { display: flex; align-items: center; gap: 10px; }
.regel-aantal { min-width: 34px; color: var(--fg-muted); }
.regel-titel { flex: 1; }
.regel-prijs { font-weight: var(--fw-semibold); white-space: nowrap; }
.regel-specs { font-size: var(--fs-body-sm); color: var(--fg-muted); white-space: pre-wrap; margin-top: 6px; }
.regel-acties { display: flex; gap: 4px; }
.mini { width: 30px; height: 30px; border: 0; border-radius: 8px; background: var(--bg-subtle); cursor: pointer; font-size: 14px; }
.mini.rood { color: var(--danger-fg); }
/* Knopvariant voor iets dat NIET terug te draaien is. Bewust een outline en geen
   volvlak: dit mag opvallen als je ernaar zoekt, maar niet uitnodigen tot klikken
   zoals de lime hoofdknop dat doet. Gebruikt dezelfde danger-tokens als de pills,
   zodat rood in het hele portaal hetzelfde rood is. */
.knop.knop-gevaar {
  color: var(--danger-fg); border-color: var(--danger-fg); background: transparent;
}
.knop.knop-gevaar:hover { background: var(--danger-bg); }
.totaalbalk { margin-top: 14px; text-align: right; font-size: 17px; }
/* "Enkel intern": vroeger een hele kaart, nu een apart blok BINNEN een kaart.
   Padding en ronding staan hier zodat views-offerte.js ze niet meer inline hoeft
   mee te geven; .intern wordt nergens anders meer gebruikt, dus dit raakt niets.
   De stippellijn werkte tot nu toe niet: var(--warning) bestond niet en een
   ongeldige var() gooit de hele border-declaratie weg. Nu staat de token er. */
.intern {
  background: #FDF9EC; border: 1px dashed var(--warning);
  padding: 16px 18px; border-radius: var(--r-lg);
}
.intern-tekst { color: var(--warning-fg); }
.custom-regel { display: inline-flex; align-items: center; gap: 8px; background: var(--bg-subtle); border-radius: var(--r-pill); padding: 4px 6px 4px 14px; margin: 4px 6px 0 0; font-size: var(--fs-body-sm); }
.stap-rij { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.stap-naam { flex: 1; min-width: 160px; }
.calc-uitkomst { background: var(--bg-subtle); border-radius: var(--r-sm); padding: 12px 14px; margin-top: 12px; }
.calc-rij { font-size: var(--fs-body-sm); margin-top: 2px; }
.calc-totaal { font-weight: var(--fw-semibold); font-size: 16px; margin-top: 8px; }

.week-raster { display: grid; grid-template-columns: repeat(7, minmax(150px, 1fr)); gap: 8px; margin-top: 14px; overflow-x: auto; }
@media (max-width: 900px) { .week-raster { display: flex; flex-direction: column; } }
.dag-kolom { background: var(--bg-elevated); border-radius: var(--r-lg); padding: 10px; min-height: 120px; box-shadow: var(--shadow-card); }
/* Vandaag: een zachte tint op de kolom, geen rand. Een outline valt buiten de
   layout, dus hij liep over de gap heen en sneed dwars door de kolom ernaast.
   Het echte merkteken staat in de dagkop (.vandaag-merk), net als in de hub. */
.dag-kolom.vandaag { background: var(--vandaag-tint); }
.dag-kop { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }
/* De datum in de kop van een dagkolom. Draagt zelf niets, hij is er als haakje
   voor .vandaag-merk. */
.dag-datum { min-width: 0; }
/* De markering op de datum zelf: gevulde blauwe pil met witte vette tekst,
   exact zoals shared/cal-kit.js vandaag tekent. Hij hangt op een <strong> in de
   dagkop, op een <span> in een maandcel en in een bezet-cel, en op de dagnaam
   in een bezet-rij; inline-flex staat in alle vier even goed.
   De tweede selector is nodig omdat .bezet-rij .dag zwaarder weegt dan een
   losse klasse en daar anders de grijze tekstkleur wint. */
.vandaag-merk,
.bezet-rij .dag.vandaag-merk {
  display: inline-flex; align-items: center;
  background: var(--vandaag-merk-bg); color: #fff;
  font-weight: var(--fw-semibold);
  border-radius: var(--r-pill);
  padding: 1px 8px; min-height: 20px;
}
.chips { display: flex; gap: 3px; flex-wrap: wrap; }
.initialen { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%; color: #fff; font-size: 11px; font-weight: var(--fw-semibold); }
.initialen.klein { width: 22px; height: 22px; font-size: 9px; }
.initialen.afwezig { background: var(--neutral-300) !important; text-decoration: line-through; }
.taak-blok { border-radius: var(--r-sm); padding: 8px 10px; margin-top: 6px; cursor: pointer; background: var(--info-bg); border-left: 4px solid var(--brand-sky-blue); min-height: 44px; }
.taak-blok.klaar { opacity: 0.55; }
.taak-blok.soort-bekisten { background: #E5EBFB; border-left-color: var(--brand-deep-blue); }
.taak-blok.soort-storten, .taak-blok.soort-vullen { background: var(--warning-bg); border-left-color: var(--warning); }
.taak-blok.soort-polieren { background: #F3E8FA; border-left-color: #9441DB; }
.taak-blok.soort-ontkisten, .taak-blok.soort-afwerken { background: var(--success-bg); border-left-color: var(--success-fg); }
.taak-blok.soort-inmeten, .taak-blok.soort-bespreking { background: var(--bg-subtle); border-left-color: var(--neutral-400); }

.instelling-rij { display: flex; align-items: center; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--neutral-100); flex-wrap: wrap; }
.instelling-rij > span:first-child { flex: 1; min-width: 220px; }

/* ---------- bugmeldingen: de leeslijst en het leespaneel ---------- */
/* De ene rustige zin voor wie alleen mag lezen. Een <p> brengt zijn eigen
   marge van 1em mee; die zetten we recht zodat er lucht onder staat en niet
   zowel boven als onder. */
.bug-leesregel { margin: 6px 0 16px; max-width: 68ch; }
/* Een sectie in het leespaneel. De marge erboven houdt de twee blokken (wat
   gaat er mis / gewenste oplossing) duidelijk uit elkaar. */
.bug-blok { margin-top: 16px; }
/* Het kopje van zo'n sectie: compact en gedempt, zodat de tekst eronder de
   aandacht krijgt en niet de kop. h4 staat portaalbreed al op margin 0. */
.bug-blok-kop {
  margin-bottom: 4px; font-size: var(--fs-body-sm); font-weight: var(--fw-semibold);
  color: var(--fg-muted); text-transform: uppercase; letter-spacing: 0.06em;
}
/* De tekst zelf. overflow-wrap breekt ook een lange route of een URL zonder
   spaties af, anders duwt zo'n woord het paneel op een gsm buiten beeld. */
.bug-blok-tekst { line-height: 1.55; overflow-wrap: anywhere; }
/* "De intake loopt nog": bewust rustiger dan de blokken eronder, dus geen kader
   en geen kleur, alleen de gedempte kpi-sub-tekst met ruimte onder zich. */
.bug-intake-loopt { margin: 0 0 12px; }
/* Technische reden waarom de intake oversloeg. Alleen Studio 27 krijgt dit veld
   mee, dus het mag er technisch uitzien; de waarschuwingskleur maakt duidelijk
   dat hier iets stukstaat en niet dat de melder niets invulde. */
.bug-intake-fout {
  margin: 0 0 12px; padding: 8px 10px; border-radius: var(--r-sm);
  background: var(--warning-bg, #FBF3DE); color: var(--fg);
  border-left: 3px solid var(--warning, #C99410);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
  overflow-wrap: anywhere;
}

/* =============================================================
   HUB-CHROME (1-op-1 naar hub.studio27.be): donkere topbar 64px,
   donkere linkerrail 64px met uitklapmenu, content met linkermarge.
   Mobiel (<900px): rail weg, onderbalk blijft.
   ============================================================= */
:root { --hub-bar: 64px; --hub-rail: 64px; --hub-rail-open: 248px; }

body {
  padding-top: calc(var(--hub-bar) + env(safe-area-inset-top));
}
@media (min-width: 900px) {
  body { padding-left: var(--hub-rail); padding-bottom: 24px; }
  #tb-bottomnav { display: none; }
  .tb-bugknop { display: none; }
}

#tb-topbar {
  height: calc(var(--hub-bar) + env(safe-area-inset-top));
  background: var(--brand-off-black);
  border-bottom: 0; backdrop-filter: none;
  color: #fff; gap: 18px; z-index: 60;
}
body.tb-hidden #tb-topbar { transform: none; } /* hub-topbar blijft altijd staan */
#tb-topbar .titel { color: rgba(247, 243, 234, 0.85); font-weight: var(--fw-medium); }
#tb-topbar img.logo { display: none; }
.hub-logo {
  font: 800 22px/1 var(--font-sans); letter-spacing: -0.5px; text-decoration: none;
  background: var(--brand-gradient); -webkit-background-clip: text; background-clip: text; color: transparent;
  padding: 4px 2px; flex-shrink: 0;
}
.hub-zoek {
  flex: 1; max-width: 420px; display: flex; align-items: center; gap: 8px;
  background: rgba(247, 243, 234, 0.08); border: 1px solid rgba(247, 243, 234, 0.12);
  border-radius: var(--r-pill); padding: 0 16px; height: 40px; color: rgba(247, 243, 234, 0.6);
}
.hub-zoek input {
  flex: 1; background: transparent; border: 0; outline: none; color: #fff;
  font: var(--fw-regular) var(--fs-body-sm) var(--font-sans); min-width: 0;
}
.hub-zoek input::placeholder { color: rgba(247, 243, 234, 0.45); }
.hub-topacties { display: flex; gap: 8px; margin-left: auto; }
.hub-topknop {
  width: 40px; height: 40px; border-radius: 12px; border: 1px solid rgba(247, 243, 234, 0.14);
  background: rgba(247, 243, 234, 0.06); color: #fff; cursor: pointer; position: relative;
  display: inline-flex; align-items: center; justify-content: center;
}
.hub-topknop:hover { background: rgba(247, 243, 234, 0.14); }
.hub-topknop .badge {
  position: absolute; top: -4px; right: -4px; min-width: 17px; height: 17px; border-radius: 9px;
  background: var(--brand-lemon-lime); color: var(--brand-off-black);
  font: var(--fw-semibold) 11px/17px var(--font-sans); padding: 0 4px;
}

#tb-rail {
  position: fixed; top: calc(var(--hub-bar) + env(safe-area-inset-top)); bottom: 0; left: 0;
  width: var(--hub-rail); background: var(--brand-off-black); z-index: 55;
  display: flex; flex-direction: column; overflow: hidden;
  transition: width var(--dur-base) var(--ease-standard);
}
@media (max-width: 899px) { #tb-rail { display: none; } }
#tb-rail:hover, #tb-rail.open { width: var(--hub-rail-open); box-shadow: 24px 0 60px -30px rgba(5, 10, 48, 0.5); }
.rail-kop {
  padding: 14px 12px 6px; font: var(--fw-semibold) 10px/1 var(--font-sans);
  letter-spacing: 0.14em; text-transform: uppercase; color: rgba(247, 243, 234, 0.4);
  white-space: nowrap; opacity: 0; transition: opacity var(--dur-fast);
}
#tb-rail:hover .rail-kop, #tb-rail.open .rail-kop { opacity: 1; }
.rail-lijst { flex: 1; overflow-y: auto; overflow-x: hidden; padding-bottom: 8px; }
.rail-item {
  display: flex; align-items: center; gap: 12px; height: 44px; padding: 0 14px;
  color: rgba(247, 243, 234, 0.75); text-decoration: none; white-space: nowrap;
  font: var(--fw-medium) var(--fs-body-sm) var(--font-sans); border-left: 3px solid transparent;
}
.rail-item:hover { background: rgba(247, 243, 234, 0.07); color: #fff; text-decoration: none; }
/* Actief staat niet alleen in de kleur: naast het blauwe vlak en het streepje
   links wordt ook de letter zwaarder en het icoonvlak gevuld (zie .ri-icoon
   hieronder). Zo blijft de actieve rij leesbaar zonder kleurwaarneming.
   font-weight apart, want .rail-item zet zijn letter met de font-shorthand. */
.rail-item.actief { background: rgba(36, 88, 234, 0.22); color: #fff; border-left-color: var(--brand-sky-blue); font-weight: var(--fw-semibold); }
.rail-item .ri-icoon {
  width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.rail-item.actief .ri-icoon { background: rgba(40, 175, 249, 0.25); }
.rail-item .ri-label { opacity: 0; transition: opacity var(--dur-fast); }
#tb-rail:hover .ri-label, #tb-rail.open .ri-label { opacity: 1; }
.rail-voet { border-top: 1px solid rgba(247, 243, 234, 0.1); padding: 6px 0; }

/* ---------- lijstscherm (strategielijst-stijl) ---------- */
.ls-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 4px 0 14px; }

/* Weergavewissel (Lijst, Kalender, Kaart, Projecten en Dag, Week, Maand).
   Stond als inline stijl in views-planning.js, maar met vier knoppen is die op
   een gsm breder dan het scherm en duwde hij de hele pagina scheef. Hier kan hij
   wel meebuigen: op smal springt hij naar een eigen regel over de volle breedte
   en verdelen de knoppen zich, in plaats van rechts uit beeld te lopen. */
.tb-wissel {
  display: flex; gap: 4px; background: #EFEADD; border-radius: 999px;
  padding: 4px; flex: none; margin-left: auto; max-width: 100%;
}
@media (max-width: 559px) {
  .tb-wissel { margin-left: 0; width: 100%; flex: 1 1 100%; }
  .tb-wissel .tap { flex: 1 1 0; min-width: 0; padding-left: 8px; padding-right: 8px; }
}
/* Pilvormige variant; zelfde hoogte als elke andere knop, alleen ronder. */
.knop-donker {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  box-sizing: border-box; background: var(--brand-off-black); color: #fff;
  border: 0; border-radius: var(--r-pill); padding: 0 20px; height: var(--knop-h);
  font: var(--fw-semibold) var(--fs-body-sm) var(--font-sans); line-height: 1.2; cursor: pointer;
}
.knop-donker:hover { filter: brightness(1.25); }
.cel-edit { cursor: pointer; border-bottom: 1px dashed var(--border-strong); }
.cel-edit:hover { border-bottom-color: var(--brand-azure-blue); color: var(--brand-azure-blue); }
.soort-stip { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 7px; }

/* .tap is de merker die shared/ op elke tikbare knop zet (lijstbalk, groepskop,
   de periodeknoppen van de teamagenda). In de hub geeft de globale stijl daar
   een indrukgevoel bij; hier bestond die regel niet, dus voelden die knoppen
   dood aan. Bewust GEEN transform en GEEN filter: beide maken van de knop het
   containing block voor position:fixed, en dan landen de popovers van
   filter-kit en day-picker verschoven (shared/filter-kit.js en member-pick.js
   waarschuwen daar met zoveel woorden voor, en .kaart:hover hierboven liep al
   in dezelfde val). Opacity doet dat niet en verplaatst de hitbox niet. */
.tap { cursor: pointer; }
.tap:active { opacity: 0.6; }

/* De trechter en de groepeerknop in de mobiele lijstbalk zijn 38px rond. De
   ::after rekt het klikgebied 3px naar buiten (38 + 2x3 = 44px) zonder dat het
   knopje zelf groter wordt. Het vlak zit binnen de knop, dus elke tik erop
   telt gewoon als een tik op de knop. */
.tb-tapdoel { position: relative; }
.tb-tapdoel::after { content: ''; position: absolute; inset: -3px; border-radius: inherit; }

/* De band achter een groepskop in de lijst. Achtergrond, bovenrand en hoogte
   staan inline in lijst.js zodat de kop exact aansluit op de rijen eronder; die
   raken we hier NIET aan. Alleen een accent bij hover en toetsenbordfocus, zodat
   zichtbaar is dat de kop open- en dichtklapt. */
.tb-groepkop:hover, .tb-groepkop:focus-within { box-shadow: inset 3px 0 0 var(--brand-azure-blue); }

/* ---------- modals: gecentreerde kaart zoals de hub (mobiel blijft bottom sheet) ---------- */
@media (min-width: 700px) {
  .overlay-backdrop { align-items: center; padding: 24px; }
  .overlay-paneel { border-radius: var(--r-lg); max-height: 88dvh; box-shadow: var(--shadow-xl); }
}
.tb-input { border-radius: var(--r-sm); }
.tb-input:focus { border-color: var(--brand-azure-blue); box-shadow: 0 0 0 3px rgba(36, 88, 234, 0.12); outline: none; }

/* meldingenpaneel onder de topbar-bel */
.meldingen-paneel {
  position: fixed; top: calc(var(--hub-bar) + 8px); right: 12px; width: min(400px, 94vw);
  max-height: 70dvh; overflow-y: auto; background: var(--bg-elevated); border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl); z-index: 120; padding: 16px;
}
/* Kop van het paneel: titel links, "Alles gelezen" rechts. Hij blijft plakken
   bovenaan het scrollende paneel, want bij twintig meldingen moet die knop
   bereikbaar blijven zonder terug te scrollen. De negatieve marge met dezelfde
   padding erin laat de plakkende achtergrond tot aan de paneelrand lopen; in
   rust ziet de gebruiker nog altijd dezelfde 16px lucht als voorheen.
   Op een heel smal scherm mag de knop onder de titel vallen (flex-wrap). */
.meldingen-kop {
  /* top MOET gelijk zijn aan de negatieve marge hieronder, niet 0. Sticky rekent
     vanaf de scrollrand (de padding-rand), terwijl de marge de kop 16px hoger
     legt. Met top:0 pinde sticky hem dus 16px LAGER dan waar hij hoort, en door
     die strook schoof de inhoud zichtbaar boven de kop langs: de pushknop kwam
     boven "Meldingen" te staan. Met -16px vallen rustpositie en plakpositie samen. */
  position: sticky; top: -16px; z-index: 1;
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  background: var(--bg-elevated);
  margin: -16px -16px 6px; padding: 16px 16px 10px;
  border-bottom: 1px solid var(--border);
}
/* De lijst zelf draagt GEEN eigen overflow: het paneel hierboven scrollt al, en
   twee schuifbakken in elkaar zetten de plakkende kop juist vast. Wat hij wel
   doet is de rijen losmaken van de push-knop erboven. */
.meldingen-lijst { margin-top: 4px; }
/* Compacte variant van .knop: lager en met minder binnenmarge, maar op een gsm
   toch 44px hoog, want dit paneel wordt met een duim bediend. De lettergrootte
   blijft die van elke andere knop (13px, zie de COMPACT-sectie onderaan). */
.meldingen-alles { flex: none; min-height: 32px; padding: 4px 12px; }
@media (max-width: 699px) {
  .meldingen-alles { min-height: 44px; padding: 6px 14px; }
}

/* Staat boven de "+ Nieuw"-knop van de lijsten (S27Table-FAB: 56px hoog,
   14px boven de onderbalk). Beide zweven rechtsonder; deze houdt afstand. */
.tb-bugknop {
  position: fixed; right: 18px; bottom: calc(var(--s27-bottomnav-h) + env(safe-area-inset-bottom) + 84px);
  width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--border);
  background: var(--bg-elevated); color: var(--fg-muted);
  font-size: 16px; font-weight: var(--fw-semibold); cursor: pointer; z-index: var(--z-pop); box-shadow: var(--shadow-card);
}

:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; border-radius: var(--r-xs); }
::selection { background: var(--brand-lemon-lime); color: var(--brand-off-black); }

/* =============================================================
   COMPACT: globale verdichting naar hub-dichtheid (hub.studio27.be,
   rijen van ±40px en 13px tekst). Deze sectie staat bewust onderaan
   en overschrijft de ruimere waarden hierboven.
   ============================================================= */

h1 { font-size: clamp(24px, 2.6vw, 32px); }
.scherm { padding: 14px; }
@media (min-width: 900px) { .scherm { padding: 20px 28px; } }
.kaart { padding: 16px; border-radius: var(--r-lg); }
.kpi-raster { gap: 10px; margin-top: 12px; }
.kpi .kpi-waarde { font-size: 22px; }

/* invoervelden: 36px hoog, 13px tekst; textarea's houden hun eigen hoogte */
.tb-input, select.tb-input { min-height: 36px; padding: 7px 10px; font-size: 13px; }
textarea.tb-input { min-height: auto; }
.tb-veld { margin-top: 6px; gap: 3px; }
.tb-veld-label { font-size: 10px; }
.veld-rij { gap: 8px; }

/* tabellen: compacte rijen zoals de hub */
.tb-tabel th { padding: 8px 10px; font-size: 10px; }
.tb-tabel td { padding: 7px 10px; font-size: 13px; }
.initialen { width: 24px; height: 24px; font-size: 10px; }
.initialen.klein { width: 20px; height: 20px; font-size: 8px; }
.pill { min-height: 22px; padding: 2px 10px; font-size: 12px; }

/* knoppen: alleen de maten wisselen, de vorm blijft die van hierboven */
:root { --knop-h: 36px; --knop-pijl: 24px; --knop-pad: 14px; }
.knop { font-size: 13px; }

/* panelen en detailregels */
.overlay-paneel { padding: 18px; padding-bottom: calc(18px + env(safe-area-inset-bottom)); }
.paneel-kop { margin-bottom: 8px; }
.regelrij { padding: 8px 10px; }
.regel-specs { font-size: 12px; }
.stap-rij { min-height: 34px; margin-top: 2px; gap: 8px; }
.stap-rij .tb-input { min-height: 30px; padding: 4px 8px; }
.calc-uitkomst { padding: 10px 12px; font-size: 12px; margin-top: 10px; }
.melding { padding: 7px 0; }
.instelling-rij { padding: 6px 0; }

/* mobiel blijft tikbaar: velden en knoppen terug naar 42px onder 700px, zodat
   een knop naast een veld ook daar op dezelfde lijn eindigt */
@media (max-width: 699px) {
  .tb-input, select.tb-input, .stap-rij .tb-input { min-height: 42px; }
  :root { --knop-h: 42px; }
}

/* ---------- COMPACT: configurator, tweekolomslayout ---------- */
.cfg-grid { display: grid; grid-template-columns: 2fr 1fr; gap: 16px; align-items: start; margin-top: 10px; }
.cfg-kop { margin: 12px 0 2px; font-size: 11px; font-weight: var(--fw-semibold); text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-muted); }
.stap-naam { font-size: 13px; }
.stap-x { color: var(--fg-muted); font-size: 12px; }
/* Kolomkoppen boven de taakregels: zelfde flexmaten als de rijen eronder, zodat
   "uren", "pers." en "ritten" exact boven hun invoerveld staan. */
.stap-kop { font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--fg-muted); min-height: 0; margin-top: 8px; }
.stap-kop span { text-align: center; }
.stap-kop .stap-naam { text-align: left; }
.cfg-opties { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.cfg-opties .tb-check { margin-top: 2px; min-height: 26px; font-size: 12px; gap: 6px; }
.cfg-opties .tb-check input { width: 15px; height: 15px; }
/* Een optieregel draagt dezelfde kolommen als een taakregel; het vinkje zit in
   de naamkolom zodat alles wat erachter komt uitlijnt met de taken erboven. */
.cfg-stappen .stap-rij .tb-check.stap-naam { flex: 1; min-width: 160px; margin: 0; gap: 6px; font-size: 13px; }
.cfg-stappen .stap-rij .tb-check.stap-naam input { width: 15px; height: 15px; flex: 0 0 15px; }
.cfg-samenvatting { background: var(--bg-subtle); border-radius: var(--r-md); padding: 14px; }
@media (min-width: 900px) { .cfg-samenvatting { position: sticky; top: 0; } }
.sv-rij { display: flex; justify-content: space-between; gap: 10px; font-size: 12px; padding: 2px 0; }
.sv-rij .sv-label { color: var(--fg-muted); }
.sv-berekend { margin-top: 10px; font-size: 15px; font-weight: var(--fw-medium); }
.sv-voorstel { font-size: 21px; font-weight: var(--fw-semibold); letter-spacing: -0.01em; }
.sv-waarschuwing { margin-top: 8px; }
@media (max-width: 899px) {
  .cfg-grid { grid-template-columns: 1fr; }
  .cfg-samenvatting { order: -1; position: static; }
}

/* =============================================================
   PLANNING VOLLER: de weekkalender als volwaardige werkdag-kolommen.
   Bewust onderaan als override; de basisregels hierboven (sectie
   week-raster/dag-kolom/taak-blok) blijven ongewijzigd staan.
   ============================================================= */

/* Dag-kolommen op desktop hoog genoeg om als echte dagkolom te ogen. */
@media (min-width: 900px) {
  .dag-kolom { min-height: 420px; }
}

/* Taakblokjes iets ruimer: meer padding en een duidelijke 13px titel. */
.taak-blok { padding: 10px; }
.taak-blok strong { font-size: 13px; }

/* Maandraster: elke dagcel minstens 96px hoog. */
.maand-cel { min-height: 96px; }
/* Vandaag in het maandraster: dezelfde zachte tint als de dagkolom, zonder rand.
   De cel krijgt zijn achtergrond INLINE mee vanuit views-planning.js, en inline
   wint van elke klasse; een gewone background-regel zou hier dus niets doen.
   Een inset box-shadow met een grote spread legt de tint alsnog over die witte
   ondergrond, netjes binnen de border en onder de inhoud, en volgt vanzelf de
   afgeronde hoeken. Zo blijft het zonder !important. */
.maand-cel.vandaag { box-shadow: inset 0 0 0 999px var(--vandaag-tint); }
.maand-datum { min-width: 0; }   /* haakje voor .vandaag-merk, verder niets eigen */

/* =============================================================
   FORMULIERGRID: een 12-koloms grid voor ALLE formulieren en panelen,
   zodat velden overal strak uitlijnen (feedback Vincent, ronde 4).
   Gebruik: TB.frm(TB.veld('Naam', input, 8), TB.veld('Nr', input, 4), ...)
   ============================================================= */
.frm { display: grid; grid-template-columns: repeat(12, 1fr); gap: 10px 12px; margin-top: 8px; align-items: start; }
.frm .tb-veld { margin-top: 0; min-width: 0; grid-column: span 12; flex: none; }
.frm .tb-input { width: 100%; max-width: none !important; box-sizing: border-box; }
.frm .tb-check { grid-column: 1 / -1; margin-top: 2px; }
/* Elk label is precies EEN regel hoog. Anders begint het veld naast een lang
   label lager en staat een rij sp-7 + sp-5 scheef; de volle tekst blijft in de
   title-tooltip staan (TB.veld zet die mee). */
.frm .tb-veld-label {
  min-height: 14px; line-height: 14px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.frm .sp-2 { grid-column: span 2; } .frm .sp-3 { grid-column: span 3; } .frm .sp-4 { grid-column: span 4; }
.frm .sp-5 { grid-column: span 5; } .frm .sp-6 { grid-column: span 6; } .frm .sp-7 { grid-column: span 7; }
.frm .sp-8 { grid-column: span 8; } .frm .sp-9 { grid-column: span 9; } .frm .sp-10 { grid-column: span 10; }
.frm .sp-11 { grid-column: span 11; } .frm .sp-12 { grid-column: span 12; }
.frm-acties { grid-column: 1 / -1; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.frm-acties.rechts { justify-content: flex-end; }
@media (max-width: 559px) {
  /* mobiel: alles onder elkaar, behalve echt smalle velden (sp-2/sp-3/sp-4 half) */
  .frm .tb-veld, .frm .tb-veld[class*="sp-"] { grid-column: span 12; }
  .frm .tb-veld.sp-2, .frm .tb-veld.sp-3, .frm .tb-veld.sp-4 { grid-column: span 6; }

  /* Gestapelde actierij: elke knop op een eigen volle regel. flex-basis 100%
     dwingt de wikkeling af, dus geen brede knop meer alleen op rij 1 met twee
     halve eronder (op 375px: 220px alleen, daaronder 143 + 79).
     .werf-status is dezelfde stapeling in de teamagenda; hij staat hier mee in
     de selector zodat er maar EEN regel bestaat die dit doet. Wat .werf-status
     verder eigen heeft (de scheidingslijn) staat in de werf-sectie. */
  .frm-acties.acties-stapel > .knop,
  .frm-acties.werf-status > .knop { flex: 1 1 100%; width: 100%; }
}

/* Meldingen: tekst links (afgekapt), actie rechts, nooit onder elkaar. */
.melding { flex-wrap: nowrap; align-items: center; }
.melding > div:first-child { flex: 1; min-width: 0; }
.melding .mini { flex-shrink: 0; }

/* Zoek-dropdown: categoriechips bovenaan. */
.zoek-chips { display: flex; gap: 6px; flex-wrap: wrap; padding: 8px 10px 6px; border-bottom: 1px solid rgba(15, 20, 40, 0.08); }
.zoek-chip {
  border: 1px solid var(--border-strong); background: #fff; border-radius: var(--r-pill);
  padding: 3px 12px; font: var(--fw-medium) 12px var(--font-sans); cursor: pointer; color: var(--fg-muted);
}
.zoek-chip.actief { background: var(--brand-off-black); border-color: var(--brand-off-black); color: #fff; }

/* Kalenderfilters: initialen-chips klikbaar aan/uit. */
.kalfilter-chip { cursor: pointer; opacity: 1; transition: opacity var(--dur-fast), outline var(--dur-fast); outline: 2px solid transparent; outline-offset: 1px; }
.kalfilter-chip.uit { opacity: 0.3; }
.kalfilter-chip.aan { outline-color: var(--brand-off-black); }

/* Drag & drop in de kalender. */
.taak-blok[draggable="true"], .maand-taak[draggable="true"] { cursor: grab; }
.taak-blok.sleept, .maand-taak.sleept { opacity: 0.4; }
.dag-kolom.drop-doel, .maand-cel.drop-doel { outline: 2px dashed var(--brand-azure-blue); outline-offset: -2px; background: var(--info-bg) !important; }
/* Sleep je een taak naar de dag van vandaag, dan moet het sleepdoel winnen. De
   vandaag-tint van een maandcel zit in een inset box-shadow (zie boven) en die
   zou over dat sleepvlak heen schilderen; hier zetten we hem even uit. */
.maand-cel.vandaag.drop-doel { box-shadow: none; }

/* Dagen waarop niet gewerkt wordt: zaterdag, zondag en de tien Belgische
   feestdagen. Ze blijven in de kalender staan (je wil de week zien zoals ze
   is) maar zijn zichtbaar gedempt, en een sleep erheen wordt geweigerd. */
.dag-kolom.geen-werkdag, .maand-cel.geen-werkdag {
  background: repeating-linear-gradient(135deg,
    var(--bg-subtle) 0 6px, transparent 6px 12px);
  color: var(--fg-subtle);
}
.dag-kolom.drop-weiger, .maand-cel.drop-weiger {
  outline: 2px dashed var(--danger-fg);
  outline-offset: -2px;
  cursor: not-allowed;
}

/* Kaartweergave van de werven. */
.kaart-wrap { position: relative; margin-top: 12px; }
#tb-kaart { height: min(64dvh, 640px); min-height: 380px; border-radius: var(--r-lg); box-shadow: var(--shadow-card); z-index: 1; }
.kaart-legende { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; font-size: 12px; color: var(--fg-muted); margin-top: 10px; }
.kaart-popup { font: var(--fw-regular) 13px/1.45 var(--font-sans); min-width: 200px; }
.kaart-popup h4 { margin: 0 0 2px; font-size: 14px; }
.leaflet-container { font-family: var(--font-sans); }

/* Bekijk-als-banner (alleen Studio 27): altijd zichtbaar zolang de weergave actief is. */
.actas-banner {
  position: fixed; left: 50%; bottom: calc(14px + env(safe-area-inset-bottom)); transform: translateX(-50%);
  background: var(--brand-off-black); color: #fff; border-radius: var(--r-pill);
  padding: 8px 8px 8px 18px; display: flex; align-items: center; gap: 12px;
  font: var(--fw-medium) 13px var(--font-sans); box-shadow: var(--shadow-lg); z-index: 1500;
  max-width: min(94vw, 560px);
}
.actas-banner .stip { width: 8px; height: 8px; border-radius: 50%; background: var(--brand-lemon-lime); flex-shrink: 0; }
.actas-banner button {
  border: 0; border-radius: var(--r-pill); background: var(--brand-lemon-lime); color: var(--brand-off-black);
  font: var(--fw-semibold) 12px var(--font-sans); padding: 6px 14px; cursor: pointer; flex-shrink: 0;
}
@media (max-width: 899px) { .actas-banner { bottom: calc(var(--s27-bottomnav-h) + env(safe-area-inset-bottom) + 12px); } }

/* Suggestievelden (zoekbare select en Google-adresveld).
   De wrapper is een FLEXBOX, geen blok: een blok om een inline input erft de
   regelhoogte eronder en wordt daardoor hoger dan de select ernaast. */
.sug-wrap { position: relative; min-width: 0; display: flex; align-items: stretch; }
.sug-wrap > .tb-input { flex: 1 1 auto; min-width: 0; }
.sug-drop {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 140;
  background: var(--bg-elevated); border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  box-shadow: var(--shadow-md); max-height: 260px; overflow-y: auto; padding: 4px;
}
.sug-item { padding: 8px 10px; border-radius: 7px; cursor: pointer; font-size: 13px; display: flex; flex-direction: column; gap: 1px; }
.sug-item:hover { background: var(--info-bg); }
.sug-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sug-sub { font-size: 11px; color: var(--fg-muted); }
.sug-status { font-size: 12px; color: var(--fg-muted); margin-top: 4px; }
.sug-ok { color: var(--success-fg); font-weight: var(--fw-medium); }

/* Compacte ploegkiezer: klein zwevend paneel met initialen-chips. */
.ploeg-pop {
  position: fixed; z-index: 135; background: var(--bg-elevated); border-radius: var(--r-md);
  box-shadow: var(--shadow-lg); border: 1px solid var(--border); padding: 12px; width: 240px;
}
.ploeg-pop h4 { font-size: 12px; margin: 0 0 8px; color: var(--fg-muted); font-weight: var(--fw-semibold); text-transform: uppercase; letter-spacing: 0.06em; }
.ploeg-pop .chips { gap: 6px; }
.ploeg-pop .initialen { width: 32px; height: 32px; font-size: 12px; cursor: pointer; opacity: 0.35; outline: 2px solid transparent; outline-offset: 1px; transition: opacity var(--dur-fast); }
.ploeg-pop .initialen.aan { opacity: 1; outline-color: var(--brand-off-black); }
.ploeg-pop .waarschuw { margin-top: 8px; font-size: 11px; color: var(--warning-fg); }

/* Taakblok in de kalender: initialen altijd zichtbaar. */
.taak-blok .chips { margin-top: 4px; }
.maand-taak .initialen { width: 16px; height: 16px; font-size: 7px; flex: 0 0 auto; }

/* Bezettingsoverzicht bij het kiezen van een datum. */
.bezet-lijst { max-height: 320px; overflow-y: auto; border: 1px solid var(--neutral-100); border-radius: var(--r-sm); padding: 6px 10px; background: #fff; }
.bezet-rij { display: flex; align-items: center; gap: 8px; padding: 4px 0; border-bottom: 1px solid var(--neutral-100); font-size: 12px; }
.bezet-rij:last-child { border-bottom: 0; }
.bezet-rij .dag { width: 92px; flex-shrink: 0; color: var(--fg-muted); }
.bezet-rij.weekend { opacity: 0.5; }
/* Vandaag in het inplanvenster: zachte tint, zelfde vorm als .gekozen. Deze
   regel staat BEWUST voor .gekozen: beide wegen even zwaar, dus wint de laatste
   en blijft de dag die je aanklikt herkenbaar boven de dag van vandaag. Met
   .weekend botst hij niet, dat is alleen doorzichtigheid. */
.bezet-rij.vandaag { background: var(--vandaag-tint); border-radius: 6px; padding-left: 6px; padding-right: 6px; }
.bezet-rij.gekozen { background: var(--info-bg); border-radius: 6px; padding-left: 6px; padding-right: 6px; }
.bezet-raster { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 5px; }
.bezet-cel { border: 1px solid var(--neutral-100); border-radius: 8px; background: #fff; padding: 4px 5px; min-height: 52px; font-size: 11px; }
/* Zelfde verhaal als bij de dagkolom: zachte tint in plaats van de outline, die
   met zijn negatieve offset over de celrand heen sneed. */
.bezet-cel.vandaag { background: var(--vandaag-tint); }
.bezet-cel .chips { gap: 2px; margin-top: 2px; }
.bezet-cel .initialen { width: 16px; height: 16px; font-size: 7px; }
.bezet-datum { min-width: 0; }   /* haakje voor .vandaag-merk, verder niets eigen */

/* ---------- inplanvenster (datum kiezen + wie staat waar) ---------- */
/* Het keten-vinkje staat in een .tb-veld naast het datumveld en moet dus even
   hoog zijn als een .tb-input, met het label erboven en geen extra bovenmarge.
   Zonder deze regel wint ".frm .tb-check" hierboven met zijn margin-top van 2px
   en zakt het vinkje een halve regel onder het datumveld. Even zwaar, maar deze
   staat later, dus deze wint. */
.frm .inplan-keten { margin-top: 0; min-height: 36px; }
@media (max-width: 699px) {
  /* Onder 700px staat een .tb-input op 42px; het vinkje volgt mee. */
  .frm .inplan-keten { min-height: 42px; }
}
/* Het blok "Wie staat waar": kop strak bovenaan, uitleg klein en dicht eronder,
   en daaronder lucht voor de filterchips. */
.inplan-bezet { margin-top: 4px; }
.inplan-bezet h4 { font-size: var(--fs-body); font-weight: var(--fw-semibold); }
.inplan-bezet > p { margin: 2px 0 0; }
/* De filterchips krijgen eigen ruimte tussen de uitlegregel en de bezet-lijst;
   voorheen plakten ze tegen de lijst aan. */
.inplan-filterchips { margin: 8px 0 10px; }

/* Bestandenkaart: nette uploadknop (gsm-camera en galerij via accept). */
.bestand-knop input[type="file"] { display: none; }

/* ---------- gedeelde uploadcomponent (TB.uploadVeld in uploads.js) ---------- */
/* .tb-upload zelf heeft alleen in de bezig-toestand stijl nodig: een lichte
   demping terwijl een reeks aan het uploaden is. .tb-upload-knop staat er enkel
   als aanknopingspunt naast "knop knop-outline" en krijgt bewust niets. */
.tb-upload.bezig { opacity: 0.7; }
/* Knop, extra veld en statusmelding op EEN rij. align-items:flex-end en niet
   center: met center zakt het veld een paar pixels onder de knop, omdat de knop
   en de .tb-input net niet even hoog zijn. Op een gsm wikkelt de rij vanzelf. */
.tb-upload-rij { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; }
/* De plek van het extra veld (bijvoorbeeld de Soort-keuze). min-width:0 laat een
   select krimpen in plaats van de rij open te breken. */
.tb-upload-extra { flex: 1 1 200px; min-width: 0; }
.tb-upload-extra .tb-input { width: 100%; }
/* De voortgangs- en foutregel houdt daarnaast de klasse kpi-sub voor de kleine
   grijze tekst. Op een gsm over de volle breedte onder de rij, vanaf 640px
   naast de knop. */
.tb-upload-status { flex: 1 1 100%; }
@media (min-width: 640px) {
  .tb-upload-status { flex: 1 1 auto; min-width: 160px; }
}
/* Het uploadblok onder de bestandentabel op het projectdetail: ruimte, zodat het
   niet tegen de tabel of tegen het lege-blok plakt. */
.kaart-upload { margin-top: 14px; }

/* ---------- werfvenster in de teamagenda ----------
   Dit venster wordt op een werf gebruikt, op een telefoon, met een vuile hand:
   grote raakvlakken, weinig tekst en alles onder elkaar. */
.werfvenster { display: flex; flex-direction: column; gap: 10px; }
.werf-titel { font-size: 19px; }                 /* de projectnaam, iets groter dan de rest */
/* Tussenkopje (Plannen en foto's): klein, gedempt en met wat lucht erboven. */
.werf-kop {
  margin-top: 6px; font-size: 11px; font-weight: var(--fw-semibold);
  color: var(--fg-muted); text-transform: uppercase; letter-spacing: 0.08em;
}
/* Losse informatieregel; de tussenruimte komt van de gap van .werfvenster, dus
   de eigen marge van een <p> of <div> moet eruit. */
.werf-regel { margin: 0; line-height: 1.45; }
/* Knop of link over de volle breedte. Links uitgelijnd in plaats van gecentreerd
   en afbrekend over meerdere regels, want een werfadres is lang. Minstens 48px
   hoog: dit is de knop die met een werkhandschoen geraakt moet worden.
   height:auto is nodig omdat .knop een vaste regelhoogte meebrengt. */
.werf-actie {
  width: 100%; justify-content: flex-start; text-align: left;
  min-height: 48px; height: auto;
  white-space: normal; overflow-wrap: anywhere;
  padding-top: 10px; padding-bottom: 10px;
}
/* De sleutelkluiscode moet buiten leesbaar zijn: klein label erboven, de code
   zelf fors, vet en met letterafstand, in een kadertje. */
.werf-code {
  display: flex; flex-direction: column; gap: 2px;
  background: var(--bg-subtle); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 10px 14px;
}
.werf-code strong { font-size: 26px; font-weight: var(--fw-semibold); letter-spacing: 0.12em; line-height: 1.15; }
/* De instructies van Tom vallen op, met behoud van zijn regelafbrekingen. */
.werf-notitie {
  white-space: pre-line; line-height: 1.5; font-size: var(--fs-body-sm);
  background: var(--warning-bg); color: var(--warning-fg);
  border-left: 3px solid var(--warning); border-radius: var(--r-sm);
  padding: 10px 12px;
}
/* Het uploadblok in het werfvenster staat los van wat erboven hangt. */
.werf-upload { margin-top: 4px; padding-top: 12px; border-top: 1px solid var(--border); }
/* De terugmeldknoppen onderaan. Duidelijke scheidingslijn erboven; het stapelen
   op een gsm doet de gedeelde regel bij .frm-acties.acties-stapel hierboven. */
.frm-acties.werf-status { margin-top: 4px; padding-top: 12px; border-top: 1px solid var(--border); }

/* Datumveld in huisstijl (TB.datumVeld): een trigger die eruitziet als een
   gewone .tb-input, met de kalender van de hub in een popover erboven. */
/* align-self werkt op de KRUISAS van de ouder, en die as verschilt per context:
   - ouder is een RIJ (display:flex, richting row): de kruisas staat verticaal.
     Zonder align-self rekt het veld uit tot de rijhoogte naast een hoog
     tekstblok (gemeten: 112px). Daar hoort dus 'center': eigen hoogte, netjes
     op de middenlijn van de rij.
   - ouder is een KOLOM, en dat is elke .tb-veld uit TB.veld(): de kruisas staat
     horizontaal. Datzelfde 'center' laat het veld dan krimpen tot zijn inhoud
     en midden onder een linksstaand label hangen. Daar hoort 'stretch': volle
     breedte, precies zoals een .tb-input ernaast.
   Vandaar een basisregel voor de rij en een zwaardere regel voor de kolom. */
.dv-veld { position: relative; min-width: 0; display: flex; align-items: stretch; align-self: center; }
.tb-veld > .dv-veld { align-self: stretch; }
.dv-trigger {
  flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: center; gap: 8px;
  justify-content: space-between; text-align: left; cursor: pointer;
  height: var(--knop-h);
}
.dv-trigger .dv-tekst { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dv-trigger .dv-tekst.dv-leeg { color: var(--fg-subtle); }
.dv-trigger .tb-icoon { color: var(--fg-muted); flex: none; }
.dv-trigger:hover { border-color: var(--brand-azure-blue); }
/* Zelfde laag als .sug-drop: boven een open paneel (--z-modal), nooit erachter. */
.tb-datumpop { position: fixed; z-index: 140; width: min(300px, calc(100vw - 20px)); }

/* Teamrol op desktop: geen rail, wel de onderbalk als navigatie. */
@media (min-width: 900px) {
  body.rol-team { padding-left: 0; padding-bottom: calc(var(--s27-bottomnav-h) + env(safe-area-inset-bottom)); }
  body.rol-team #tb-bottomnav { display: flex; }
  body.rol-team .tb-bugknop { display: block; }
}

/* ── Testomgeving ─────────────────────────────────────────────────────────
   Bewust een zwevend label en geen balk bovenaan: de topbar staat vast op
   top:0 en alles eronder rekent met die hoogte, dus een balk erboven zou de
   hele pagina verschuiven. Dit hangt er los overheen en raakt geen enkele
   maat. Boven de onderbalk, zodat hij op de gsm niets wegduwt. */
#tb-testbalk {
  position: fixed;
  left: 12px;
  bottom: calc(var(--s27-bottomnav-h) + env(safe-area-inset-bottom) + 12px);
  z-index: 9999;
  max-width: calc(100vw - 24px);
  padding: 8px 14px;
  border-radius: 999px;
  background: #B3261E;
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.35;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.28);
  pointer-events: none;   /* mag nooit een knop eronder blokkeren */
}
@media (min-width: 700px) {
  /* Op groot scherm is er geen onderbalk. */
  #tb-testbalk { bottom: 12px; }
}
