/*****************************************************
 theme.css — MIT app design tokens & component basis
 WP1: tokens & generieke component-stijl. WP2: applicatieschil
 (navbar, footer, flash, dropdowns, #themeToggle).
 Laadvolgorde = no.css → Bulma → theme.css (laatste); het oude
 inline dark-mode-blok uit layout.html is hierin opgegaan (WP2).
 Alle component-stijlen gebruiken uitsluitend tokens, zodat licht
 en donker automatisch correct zijn (§33, §37).
 Overgangen alleen op toestandsverandering — geen permanente animatie (§32).
 *****************************************************/

/* =====================================================
   1. Design tokens — licht (default)
   ===================================================== */
:root {
  /* Achtergrondlagen */
  --bg-page:   #f3f5f8;
  --bg-card:   #ffffff;
  --bg-subtle: #eef1f5;

  /* Tekst */
  --text-primary:   #1f2937;
  --text-secondary: #475569;
  --text-muted:     #6b7280;
  --text-inverse:   #f8fafc;

  /* Accent */
  --accent:        #2563eb;
  --accent-hover:  #1d4ed8;
  --accent-soft:   rgba(37, 99, 235, 0.12);
  --accent-contrast: #ffffff;

  /* Semantische kleuren (basis) */
  --success: #15803d;
  --success-contrast: #ffffff;
  --warning: #b45309;
  --danger:  #dc2626;
  --info:    #0369a1;

  /* Contrastparen voor de Bulma-kleurknoppen (is-warning/is-danger) */
  --warning-contrast: #20160a;
  --danger-contrast:  #ffffff;

  /* Semantische tinten (voor alerts/badges) */
  --success-bg:      #ecfdf3;
  --success-border:  #86d99f;
  --warning-bg:      #fff8eb;
  --warning-border:  #ecc94b;
  --danger-bg:       #fef2f2;
  --danger-border:   #f3a6a6;
  --info-bg:         #eff8ff;
  --info-border:     #93c5fd;

  /* Lijnen */
  --border:        #e2e8f0;
  --border-strong: #cbd5e1;

  /* Schaduwen */
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.05), 0 1px 3px rgba(15, 23, 42, 0.07);
  --shadow-md: 0 2px 4px rgba(15, 23, 42, 0.06), 0 6px 16px -4px rgba(15, 23, 42, 0.10);
  --shadow-up-sm: 0 -2px 8px rgba(15, 23, 42, 0.06);

  /* Radius-schaal */
  --radius-sm:   5px;
  --radius-md:   8px;
  --radius-lg:   12px;
  --radius-full: 999px;

  /* Spacing-schaal */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Typografie-schaal */
  --font-body: "Roboto", Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --text-xs:   0.75rem;
  --text-sm:   0.875rem;
  --text-md:   1rem;
  --text-lg:   1.15rem;
  --text-xl:   1.35rem;
  --text-2xl:  1.6rem;

  /* Focus-ring */
  --focus-ring: 0 0 0 3px rgba(37, 99, 235, 0.22);
}

/* =====================================================
   2. Design tokens — donker
   Geen puur zwart/wit: zachte grijstinten, voldoende contrast.
   ===================================================== */
:root[data-theme='dark'] {
  --bg-page:   #12161d;
  --bg-card:   #1b212b;
  --bg-subtle: #232a35;

  --text-primary:   #e4e8ef;
  --text-secondary: #b3bccb;
  --text-muted:     #8a95a7;
  --text-inverse:   #12161d;

  --accent:        #5b9dff;
  --accent-hover:  #7db1ff;
  --accent-soft:   rgba(91, 157, 255, 0.16);
  --accent-contrast: #0d1420;

  --success: #4ade80;
  --success-contrast: #10241a;
  --warning: #fbbf24;
  --danger:  #f87171;
  --info:    #38bdf8;

  --success-bg:      #17251c;
  --success-border:  #2f5e43;
  --warning-bg:      #29210f;
  --warning-border:  #6b5a1e;
  --danger-bg:       #2b1719;
  --danger-border:   #7a3b3e;
  --info-bg:         #14202e;
  --info-border:     #2f5a7a;

  --border:        #2a323f;
  --border-strong: #3c4656;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35), 0 1px 3px rgba(0, 0, 0, 0.30);
  --shadow-md: 0 2px 4px rgba(0, 0, 0, 0.35), 0 6px 16px -4px rgba(0, 0, 0, 0.45);
  --shadow-up-sm: 0 -2px 8px rgba(0, 0, 0, 0.35);

  --focus-ring: 0 0 0 3px rgba(91, 157, 255, 0.28);

  /* Contrastparen voor de Bulma-kleurknoppen (is-warning/is-danger):
     donker krijgt een donkere tekst op de lichtere token-kleuren */
  --warning-contrast: #20160a;
  --danger-contrast:  #ffffff;
}

/* =====================================================
   2b. no.css dark-neutralisatie — centraal (WP8-consolidatie)
   no.css bevat een legacy [data-theme='dark']-blok met hardcoded
   kleuren (#111/#000/#222/#333/#444/#4da3ff) dat met hogere
   specificiteit wint van de gewone token-regels. no.css is gedeeld
   en wordt niet bewerkt (§3): hier koppelen we die selectors centraal —
   direct ná de tokens en vóór alle component-secties — weer aan de
   tokens, zodat donker automatisch klopt (§37) én component-regels
   verderop in dit bestand bij gelijke specificiteit kunnen winnen.
   (Deze stond voorheen onderaan sectie 18; alleen verplaatst/verheven,
   de projectregels zelf zijn ongewijzigd.)
   ----------------------------------------------------- */
:root[data-theme='dark'] a {
  color: var(--accent);
}

:root[data-theme='dark'] nav.black a {
  color: var(--text-primary);
}

:root[data-theme='dark'] button,
:root[data-theme='dark'] input[type='button'],
:root[data-theme='dark'] input[type='reset'],
:root[data-theme='dark'] input[type='submit'] {
  background-color: var(--accent);
  color: var(--accent-contrast);
}

:root[data-theme='dark'] [role='button'] {
  background-color: var(--bg-card);
  color: var(--text-primary);
}

:root[data-theme='dark'] input,
:root[data-theme='dark'] select,
:root[data-theme='dark'] textarea {
  background-color: var(--bg-card);
  color: var(--text-primary);
  border-color: var(--border-strong);
}

:root[data-theme='dark'] table thead tr {
  background-color: var(--bg-subtle);
}

:root[data-theme='dark'] tbody tr:hover {
  background-color: var(--bg-subtle);
}

:root[data-theme='dark'] header,
:root[data-theme='dark'] footer.black,
:root[data-theme='dark'] nav.black {
  background-color: var(--bg-card);
  color: var(--text-primary);
}

:root[data-theme='dark'] .dropdown-menu,
:root[data-theme='dark'] .dropdown-content {
  background-color: var(--bg-card);
  border-color: var(--border);
}

:root[data-theme='dark'] .dropdown-item {
  background-color: var(--bg-card);
  color: var(--text-primary);
}

:root[data-theme='dark'] .dropdown-item:hover {
  background-color: var(--bg-subtle);
  color: var(--text-primary);
}

:root[data-theme='dark'] .dropdown-divider {
  background-color: var(--border);
}

:root[data-theme='dark'] [role='alert'] {
  background-color: var(--bg-card);
  color: var(--text-primary);
}

/* =====================================================
   3. Basis / typografie-hiërarchie (§41: rust, leesbaarheid)
   ===================================================== */
:root[data-theme='dark'] body,
body {
  background-color: var(--bg-page);
  color: var(--text-primary);
  line-height: 1.65;
}

body > center > main {
  max-width: 1200px;
}

/* Justified-tekst leest zwaar; links uitlijnen (§41) */
p {
  text-align: left;
}

h1, h2, h3, h4, h5, h6 {
  color: var(--text-primary);
  font-weight: 650;
  line-height: 1.25;
  letter-spacing: -0.01em;
}

/* no.css heeft extreme heading-groottes; kalmeren */
h1 { font-size: var(--text-2xl); margin: 0.8em 0 0.4em; }
h2 { font-size: var(--text-xl);  margin: 0.9em 0 0.4em; }
h3 { font-size: var(--text-lg);  margin: 0.8em 0 0.35em; }
h4 { font-size: var(--text-md);  margin: 0.8em 0 0.3em; }
h5 { font-size: var(--text-sm);  margin: 0.7em 0 0.3em; }
h6 { font-size: var(--text-sm);  margin: 0.7em 0 0.3em; opacity: 0.9; }

/* =====================================================
   4. Links
   ===================================================== */
a {
  color: var(--accent);
  transition: color 0.15s ease;
}

a:hover {
  color: var(--accent-hover);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* =====================================================
   5. Cards — .section + .box
   ===================================================== */
.section {
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--space-5);
  margin-bottom: var(--space-5);
}

/* Bulma's .box legt een hardcoded witte achtergrond en #4a4a4a tekst vast, en
   het legacy [data-theme='dark']-blok in no.css kent .box niet. Zonder deze
   regel staat in donker mode álle inhoud van een box — labels, placeholders,
   checkbox-tekst — lichtgrijs op dat wit, terwijl de velden erin wél donker
   zijn gethemd. De tokens winnen, net als bij de tabellen in sectie 8. */
.box {
  background-color: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

/* =====================================================
   6. Buttons — Bulma verfijnen, niet vervangen (§37)
   ===================================================== */
.button,
button,
input[type='button'],
input[type='reset'],
input[type='submit'],
[role='button'] {
  border-radius: var(--radius-sm);
  height: auto;
  min-height: 2.25rem;
  line-height: 1.4;
  transition: background-color 0.15s ease, border-color 0.15s ease,
              box-shadow 0.15s ease, color 0.15s ease;
}

/* no.css-kleurt alle knoppen blauw; token-basis houden, rustig */
button,
input[type='button'],
input[type='reset'],
input[type='submit'] {
  background-color: var(--accent);
  color: var(--accent-contrast);
  border: 1px solid transparent;
  padding: 0.4em 0.9em;
}

/* Subtiele hover i.p.v. zware box-shadow */
.button:hover,
button:hover,
input[type='button']:hover,
input[type='reset']:hover,
input[type='submit']:hover,
[role='button']:hover {
  box-shadow: none;
}

button:hover,
input[type='button']:hover,
input[type='reset']:hover,
input[type='submit']:hover {
  background-color: var(--accent-hover);
}

.button:focus,
.button:focus-visible,
button:focus,
button:focus-visible,
input[type='button']:focus,
input[type='reset']:focus,
input[type='submit']:focus,
[role='button']:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* Bulma-kleurknoppen: border volgt token, hover subtiel */
.button {
  border: 1px solid var(--border-strong);
  background-color: var(--bg-card);
  color: var(--text-primary);
}

.button:hover {
  border-color: var(--border-strong);
  background-color: var(--bg-subtle);
  color: var(--text-primary);
}

.button.is-primary,
.button.is-info {
  background-color: var(--accent);
  border-color: transparent;
  color: var(--accent-contrast);
}

.button.is-primary:hover,
.button.is-info:hover {
  background-color: var(--accent-hover);
  color: var(--accent-contrast);
}

.button.is-success {
  background-color: var(--success);
  border-color: transparent;
  color: var(--accent-contrast);
}

.button.is-success:hover {
  filter: brightness(1.08);
  color: var(--accent-contrast);
}

.button.is-warning {
  background-color: var(--warning);
  border-color: transparent;
  color: var(--warning-contrast);
}

.button.is-danger {
  background-color: var(--danger);
  border-color: transparent;
  color: var(--danger-contrast);
}

.button.is-danger:hover {
  filter: brightness(1.08);
  color: var(--danger-contrast);
}

/* Inactief: duidelijk gedempt */
.button[disabled],
button[disabled],
input[type='submit'][disabled] {
  opacity: 0.55;
}

/* =====================================================
   7. Formulieren
   Focus met accent; textarea-groei (.grow-wrap) blijft werken:
   padding van de textarea blijft 0.5em (match met .grow-wrap::after
   uit autoresize.js) zodat de replica exact meeschaalt.
   ===================================================== */
input[type='color'], input[type='date'], input[type='datetime'], input[type='time'],
input[type='datetime-local'], input[type='email'], input[type='month'],
input[type='number'], input[type='password'], input[type='search'],
input[type='tel'], input[type='text'], input[type='url'], input[type='week'],
input:not([type]), textarea, select {
  background-color: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}

input[type='color']:focus, input[type='date']:focus, input[type='time']:focus,
input[type='datetime']:focus, input[type='datetime-local']:focus,
input[type='email']:focus, input[type='month']:focus, input[type='number']:focus,
input[type='password']:focus, input[type='search']:focus, input[type='tel']:focus,
input[type='text']:focus, input[type='url']:focus, input[type='week']:focus,
input:not([type]):focus, textarea:focus, select:focus,
.input:focus, .textarea:focus {
  border-color: var(--accent);
  outline: none;
  box-shadow: var(--focus-ring);
}

/* Selectie in inputs leesbaar in beide thema's */
::selection {
  background: var(--accent-soft);
}

/* Label-spacing: label hoort duidelijk bij zijn veld */
.field .label,
.label {
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: 600;
  margin-bottom: var(--space-1);
}

.help {
  color: var(--text-muted);
  font-size: var(--text-xs);
}

/* Placeholder niet te luidruchtig */
input::placeholder, textarea::placeholder {
  color: var(--text-muted);
  opacity: 0.8;
}

/* py4web-validatiefout (voorheen inline in layout.html, WP8-consolidatie):
   kleur via het danger-token zodat beide thema's kloppen (§37) */
.py4web-validation-error {
  margin-top: -16px;
  font-size: 0.8em;
  color: var(--danger);
}

/* Bulma negeert het rows-attribuut van textarea (voorheen inline in
   layout.html) — height:auto dwingt af dat rows meeweegt; de
   textarea-groei (.grow-wrap) bouwt hierop voort */
textarea {
  height: auto !important;
}

/* =====================================================
   8. Tabellen (index-grid en overige)
   Bulma .table dwingt een witte achtergrond af — tokens winnen.
   ===================================================== */
table,
.table {
  color: var(--text-primary);
  background-color: var(--bg-card);
}

thead tr,
.table thead th {
  background-color: var(--bg-subtle);
}

thead th,
.table thead th {
  color: var(--text-secondary);
  font-weight: 600;
  border-bottom: 1px solid var(--border-strong);
}

tbody tr {
  border-bottom: 1px solid var(--border);
}

tbody tr:last-child {
  border-bottom: none;
}

tbody tr:hover {
  background-color: var(--bg-subtle);
}

td, th {
  padding: var(--space-2) var(--space-3);
  vertical-align: top;
}

/* Bulma tabel-varianten opnieuw koppelen aan tokens */
.table.is-bordered td,
.table.is-bordered th {
  border-color: var(--border);
}

.table.is-striped tbody tr:not(.is-selected):nth-child(even) {
  background-color: transparent;
}

/* is-striped+wisselende specificiteit: Bulma heeft ook de gecombineerde
   variant (.is-hoverable.is-striped) met hogere specificiteit — die moet mee,
   anders blijft de bijna-witte #fafafa-hover doorlekken (dark mode) */
.table.is-hoverable tbody tr:not(.is-selected):hover,
.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover,
.table.is-hoverable.is-striped tbody tr:not(.is-selected):hover:nth-child(even) {
  background-color: var(--bg-subtle);
}

.table.is-hoverable tbody tr:not(.is-selected):hover *,
.table.is-striped tbody tr:not(.is-selected):nth-child(even) * {
  color: inherit;
}

/* =====================================================
   9. Code
   ===================================================== */
code {
  background-color: var(--bg-subtle);
  color: var(--text-primary);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: 0.9em;
  padding: 0.15em 0.4em;
}

pre {
  background-color: var(--bg-subtle);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  overflow-x: auto;
}

pre code {
  background: none;
  padding: 0;
  white-space: inherit;
}

/* =====================================================
   10. Flash-alerts / [role="alert"]
   py4web geeft class mee: success / warning / error / info (§33:
   kleur wordt ondersteund door positionering — linkerbalk + tint).
   ===================================================== */
[role='alert'] {
  background-color: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  border-left: 4px solid var(--info);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  /* Boven de content, uitgelijnd met main (max-width 1200px) */
  margin: var(--space-2) auto;
  padding: var(--space-3) var(--space-4);
  padding-right: var(--space-7);
  width: calc(100% - 2 * var(--space-4));
  max-width: 1200px;
  position: relative;
  font-size: var(--text-sm);
}

[role='alert'].success { border-left-color: var(--success); background-color: var(--success-bg); }
[role='alert'].warning { border-left-color: var(--warning); background-color: var(--warning-bg); }
[role='alert'].error   { border-left-color: var(--danger);  background-color: var(--danger-bg); }
[role='alert'].info    { border-left-color: var(--info);    background-color: var(--info-bg); }

[role='alert'] .close {
  background-color: transparent;
  opacity: 0.6;
  transition: opacity 0.15s ease;
}

[role='alert'] .close:hover {
  opacity: 1;
}

/* no.css tekent het kruisje als zwart SVG — in donker omkeren */
:root[data-theme='dark'] [role='alert'] .close {
  filter: invert(1);
}

/* =====================================================
   11. .warning (bookmark-links + foutteksten)
   Generiek en rustig — geen geel-blok (WP4 herontwerpt de bookmarks).
   ===================================================== */
.warning {
  color: var(--warning);
  background-color: transparent;
  font-weight: 500;
}

/* =====================================================
   12. Overige details
   ===================================================== */
hr {
  border: none;
  border-top: 1px solid var(--border);
}

/* Bulma progress: vaste lichte kleuren → tokens */
progress.progress,
.progress {
  background-color: var(--bg-subtle);
}

.progress::-webkit-progress-bar {
  background-color: var(--bg-subtle);
}

.progress::-webkit-progress-value {
  background-color: var(--accent);
}

.progress::-moz-progress-bar {
  background-color: var(--accent);
}

/* =====================================================
   13. Applicatieschil — navbar, dropdowns, theme-toggle, footer (WP2)
   no.css geeft nav.black/footer.black #111 + blauwe hover en een
   blauwe [role=button]-pill; alles wordt kalm via tokens.
   De .black-klassen blijven in de HTML (contract), CSS restyled ze.
   ===================================================== */

/* --- Navbar: rustige product-balk (§11) --- */
nav.black {
  background-color: var(--bg-card);
  color: var(--text-primary);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}

nav.black a,
nav.black > label {
  color: var(--text-primary);
  text-decoration: none;
}

/* Logo: herkenbaar maar subtiel */
nav.black > a {
  font-weight: 650;
  letter-spacing: 0.01em;
}

/* Strakkere menu-spacing (was 1.5em 0.5em in no.css) */
nav.black > ul > li {
  padding: 0.6em 0.6em;
}

/* Hover: gedempt accent i.p.v. felblauw (§11: normaal is stil) */
nav.black li:hover {
  background-color: var(--bg-subtle);
}

nav.black li:hover > a {
  color: var(--text-primary);
}

/* --- B19 (WP11b): gebruikersmenu uiterst rechts ---
   no.css maakt van nav een tabel (kinderen = table-cells) en float de LAATSTE
   <ul> rechts. Sinds de themeToggle-<ul> dat was, hing het gebruikersmenu in
   het midden. Op desktop (>600px) wordt nav.black daarom flex:
   [logo][linkermenu] …(vrijruimte)… [🌓 theme-toggle][gebruikersmenu].
   De toggle krijgt de auto-marge: hij opent het rechts-cluster en het
   gebruikersmenu kwijnt daardoor uiterst rechts (B19). Op mobiel (<600px)
   geldt geen van dit: de #hamburger-checkbox laat de <ul>s gewoon tonen/
   verbergen zoals no.css dat doet. */
@media (min-width: 600px) {
  nav.black {
    display: flex;
    align-items: center;
  }

  /* no.css float + table-cell neutraliseren binnen nav.black — maar de
     hamburger-label/checkbox blijven WEG (no.css verbergt ze op desktop;
     een generieke `> * { display: block }` ontketende ze weer). */
  nav.black > a,
  nav.black > ul {
    display: block;
  }
  nav.black > input[type=checkbox],
  nav.black > label {
    display: none;
  }

  nav.black > ul:last-child {
    float: none;
  }

  /* rechts-cluster: theme-toggle eerst, gebruikersmenu uiterst rechts.
     Anker op de toggle-ul via :has() — robuust op paginas ZÓNDER een
     page_left_menu (project-scherm), waar nth-of-type verschuift. */
  nav.black > ul:has(#themeToggle) {
    margin-left: auto;
  }

  /* ademruimte tussen toggle en gebruikersmenu (was de 1em inline-marge) */
  nav.black > ul:last-child {
    margin-left: 0.35em;
  }
}

/* Dropdown van het gebruikersmenu rechts uitgelijnd, zodat deze bij de
   rechts-ankering niet buiten de viewport valt (no.css zet left:-20px) */
nav.black > ul:last-child li > ul {
  left: auto;
  right: 0;
}

/* --- Dropdown-menu's in de nav (no.css ul ul): tokens bg/border/shadow --- */
nav.black ul ul {
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}

nav.black ul ul a {
  color: var(--text-primary);
  font-weight: 500;
}

nav.black ul ul li:hover {
  background-color: var(--bg-subtle);
}

nav.black ul ul li:hover > a {
  color: var(--accent);
}

/* --- #themeToggle: rustige ghost-knop i.p.v. blauwe pill --- */
nav #themeToggle {
  background-color: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-full);
  min-width: 0;
  height: auto;
  min-height: 1.7rem;
  line-height: 1.3;
  padding: 0.1em 0.55em;
  margin: 0;
  font-size: 0.95rem;
  box-shadow: none;
}

nav #themeToggle:hover {
  background-color: var(--bg-subtle);
  color: var(--text-primary);
  box-shadow: none;
}

nav #themeToggle:focus-visible {
  box-shadow: var(--focus-ring);
}

/* --- Footer: klein en gedempt (§11) --- */
footer.black {
  background-color: var(--bg-subtle);
  color: var(--text-muted);
  border-top: 1px solid var(--border);
}

footer.black.padded {
  padding: var(--space-2) var(--space-4);
}

footer.black p {
  margin: 0;
  font-size: var(--text-xs);
  text-align: center;
}

/* --- Bulma-dropdown (o.a. model-zoek in controllers.py) op tokens --- */
.dropdown-content {
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}

.dropdown-item {
  color: var(--text-primary);
}

.dropdown-item:hover {
  background-color: var(--bg-subtle);
  color: var(--text-primary);
}

.dropdown-divider {
  background-color: var(--border);
}

/* =====================================================
   14. Projectscherm — statusbalk (WP3)
   #debug-footer was een zwevende debug-box rechtsboven; het is nu
   een viewport-fixed balk onderaan, volle breedte, onderdeel van de
   applicatieschil (§7/§8/§10). Layout-ruimte: body krijgt onderaan
   padding zodat de balk niets bedekt.
   JS-contracten (2.3.3) blijven leidend: de JS zet inline
   background/boxShadow/opacity op de LED-spans en inline kleuren op
   #floating-save-btn bij dirty-state — deze CSS maakt alleen de
   omringende balk en rust die uit met tokens.
   ===================================================== */
:root {
  --statusbar-height: 44px;
}

/* Layout-ruimte voor de vaste balk (§8): niets wordt bedekt */
body:has(#debug-footer) {
  padding-bottom: calc(var(--statusbar-height) + 4px);
}

#debug-footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  background-color: var(--bg-card);
  border-top: 1px solid var(--border);
  box-shadow: var(--shadow-up-sm);
}

.statusbar-inner {
  max-width: 1200px;               /* gelijk aan main — balk voelt bij de schil */
  margin: 0 auto;
  min-height: var(--statusbar-height);
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-1) var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.statusbar-spacer {
  flex: 1;
}

/* --- Verbindingsstatus: stil in rust (§11), tekst erbij in gebruikerstaal --- */
.statusbar-conn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}

.statusbar-conn-text {
  color: var(--text-secondary);
}

.statusbar-conn.is-degraded .statusbar-conn-text {
  color: var(--warning);
  font-weight: 600;
}

/* LED-spans: JS zet background/boxShadow inline (contract); dit is de omringende vorm */
.statusbar-led {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #888;
  box-shadow: 0 0 4px #0003;
  vertical-align: middle;
  flex: none;
}

/* Activiteit-flikker: subtiel middelste detail (§17); JS bestuurt opacity/background */
#sio-activity-led.statusbar-led-activity {
  width: 7px;
  height: 7px;
  margin-left: 2px;
  opacity: 0.4;
  background: #665c00;
  box-shadow: none;
  transition: opacity 0.12s ease, background-color 0.12s ease;
}

/* --- AI-taken in gebruikerstaal (§18/§34): "0 taken bezig" --- */
.statusbar-queue {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  color: var(--text-muted);
  white-space: nowrap;
  transition: opacity 0.2s ease;
}

/* Nul taken: sterk teruggenomen (§18), maar aanwezig en door JS bij te werken */
.statusbar-queue.is-idle {
  opacity: 0.55;
}

/* WP12/§34: bij nul taken verdwijnt het cijfer — de tekst is "Geen taken bezig" */
.statusbar-queue.is-idle #ai-queue-length {
  display: none;
}

/* --- #other_activity: rustig, standaard ingeklapt detail (§20) --- */
.statusbar-activity {
  position: relative;
  min-width: 0;
}

.statusbar-activity summary {
  list-style: none;
  cursor: pointer;
  color: var(--text-muted);
  font-size: var(--text-xs);
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  transition: color 0.15s ease;
}

.statusbar-activity summary::-webkit-details-marker {
  display: none;
}

.statusbar-activity summary::after {
  content: '▸';
  font-size: 0.8em;
  transition: transform 0.15s ease;
}

.statusbar-activity[open] summary::after {
  transform: rotate(90deg);
}

.statusbar-activity summary:hover,
.statusbar-activity[open] summary {
  color: var(--text-primary);
}

/* Paneel opent BOVEN de balk, als card — de balk zelf verandert niet van hoogte */
.statusbar-activity[open] .statusbar-panel {
  position: absolute;
  left: 0;
  bottom: calc(100% + 10px);
  width: min(520px, 92vw);
  max-height: min(40vh, 320px);
  overflow-y: auto;
  z-index: 45;
}

.statusbar-panel {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

/* De JS injecteert <dd>-regels (innerHTML-replace, contract) — netjes als regels tonen */
.statusbar-panel dd {
  margin: 0;
  padding: var(--space-1) 0;
  border-bottom: 1px solid var(--border);
}

.statusbar-panel dd:last-child {
  border-bottom: none;
}

/* WP12: de dl is niet langer zélf de card (wrapper is dat) — alleen marge-reset */
.statusbar-activity-list {
  margin: 0;
}

/* WP12/§35: debug-paneel binnen de activiteit-card — regels in mono, gedempt,
   deels buiten beeld te scrollen; [hidden]-guard expliciet zodat de card-styling
   het verbergen niet overruled */
.statusbar-debug {
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px dashed var(--border);
  max-height: 18vh;
  overflow-y: auto;
}

.statusbar-debug[hidden] {
  display: none;
}

.statusbar-debug .dbg-line {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
  line-height: 1.55;
  overflow-wrap: anywhere;
}

/* --- Dirty-state: status-tekst + #floating-save-btn rechts --- */
.statusbar-save-state {
  color: var(--text-muted);
  font-size: var(--text-xs);
  white-space: nowrap;
}

.statusbar-save-state.is-dirty {
  color: var(--warning);
  font-weight: 600;
}

/* Prominente hoofd-save (§16): opslagstatus en opslagknop horen bij elkaar.
   Rust-uitstraling = success-token; dirty komt als class binnen (WP11,
   contract-conversie 2.3.3: geen inline styles meer — tokens regelen
   licht/donker, geen isDark-ifje in JS). */
#floating-save-btn.statusbar-save-btn {
  pointer-events: auto;
  cursor: pointer;
  background-color: var(--success);
  color: var(--success-contrast);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 0.4em 1em;
  font-size: var(--text-sm);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
  flex: none;
}

#floating-save-btn.statusbar-save-btn:hover {
  background-color: var(--success);
  filter: brightness(1.08);
  color: var(--success-contrast);
}

#floating-save-btn.statusbar-save-btn:focus-visible {
  box-shadow: var(--focus-ring);
}

/* WP11: dirty-state als class (was inline #ff9800/#b58900 met isDark-check) */
#floating-save-btn.statusbar-save-btn.is-dirty {
  background-color: var(--warning);
  color: var(--warning-contrast);
  border-color: var(--warning);
  font-weight: 700;
  animation: pulse 1.5s infinite;
}

/* Pulse bij dirty-state (JS zet animation inline): subtiel gedempt (§32) */
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.8; }
}

/* --- Smal scherm (§36): compact, betekenis blijft gelijk --- */
@media (max-width: 720px) {
  .statusbar-inner {
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
    font-size: var(--text-xs);
    padding: var(--space-2) var(--space-3);
  }

  body:has(#debug-footer) {
    padding-bottom: 72px;   /* balk kan op twee regels uitkomen */
  }
}

/* =====================================================
   15. Projectscherm — veldnavigatie (WP4 + WP7b, besluit B8)
   De bookmark-links bovenaan (gegenereerd door controllers.py als
   DIV > A per groep, class "warning" voor lege velden) zijn een
   samenvouwbare chip-navigatie: één sticky balk, standaard UITGEKLAPT
   (voorkeur open/dicht staat per project en tab in sessionStorage en
   wint daarna van de default), uitgeklapt groepen chips op natuurlijke hoogte — de
   groepen ("Voorblad", "Thema 1" …) staan naast elkaar en breken af,
   en de enige navigatie van het scherm (de WP15-sectie-strip is
   vervallen; de chips markeren ook welke sectie zichtbaar is).
   GEEN max-height en GEEN overflow: muis-scroll boven de balk
   scrollt altijd de pagina (besluit B8). Lege velden krijgen het
   waarschuwingsaccent in kleur + icoon + tekst samen (§33);
   gevulde velden zijn neutraal stil (§11). De DIV-wrappers blijven
   staan maar doen visueel niet mee (display: contents).
   ===================================================== */
:root {
  /* Ruimte die doelvelden bovenin nodig hebben zodat ze niet achter
     de sticky balk verdwijnen (§8) — afgestemd op de samengevouwen
     balkhoogte (≈ 2.25rem + sticky-offset) + ademruimte. */
  --fieldnav-clearance: 4.5rem;
  /* Dezelfde ruimte voor de UITGEKLAPTE balk (de default): samenvatting +
     groepsrijen (Voorblad + 6 bijsluiter-secties), gemeten op project.html
     (1440px, donker + licht) ≈ 163px + sticky-offset + ademruimte. */
  --fieldnav-clearance-open: 12rem;
}

/* Smooth-scroll alleen voor het projectscherm, en niet als de gebruiker
   beweging heeft uitgezet (§32) */
@media (prefers-reduced-motion: no-preference) {
  html:has(.bookmark-nav) { scroll-behavior: smooth; }
}

/* no.css zet overflow-x: hidden op html/body — dat maakt beide assen tot
   scroll-container (hidden forceert overflow-y: auto) en dat breekt
   position: sticky. `clip` werkt hetzelfde visueel maar maakt géén
   scroll-container, waardoor de sticky veldnavigatie wél plakt. */
html, body {
  overflow-x: clip;
}

.bookmark-nav {
  position: sticky;
  top: var(--space-2);
  z-index: 30;
  /* compacter dan de gewone .section — dit is een balk, geen card */
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-4);
}

/* Samengevouwen toestand: één regel, stil (§11). De browser-marker
   vervangen we door een eigen caret. */
.bookmark-nav-summary {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  cursor: pointer;
  list-style: none;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  user-select: none;
}

.bookmark-nav-summary::-webkit-details-marker { display: none; }

.bookmark-nav-title {
  font-weight: 600;
  color: var(--text-primary);
}

.bookmark-nav-teller {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

/* Aantallen in de samenvattingsbalk worden door het kleine inline-script
   in project.html gezet (counters in een gesloten <details> tellen niet
   mee: de content is dan niet gerenderd) */

/* ⚠-telling alleen zichtbaar als er lege velden zijn: icoon + kleur +
   aantal samen (§33), en geen "0 leeg"-ruis in de ruststand (§11) */
.bookmark-nav:not(:has(.bookmark-list a.warning)) .bookmark-nav-warn {
  display: none;
}

.bookmark-nav-warn {
  color: var(--warning);
  background-color: var(--warning-bg);
  border: 1px solid var(--warning-border);
  border-radius: var(--radius-full);
  padding: 0.1em 0.6em;
}

/* B21: bucket-link in de ToC-summary — neutraal en rustig (§11);
   geen kleuraccent, het is een navigatielink geen waarschuwing */
.bookmark-nav-bucket {
  color: var(--text-secondary);
  background-color: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  padding: 0.1em 0.6em;
  text-decoration: none;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.bookmark-nav-bucket:hover,
.bookmark-nav-bucket:focus-visible {
  background-color: var(--accent-soft);
  color: var(--accent);
}

.bookmark-nav-bucket:focus-visible {
  box-shadow: var(--focus-ring);
}

/* Eigen caret; draait alleen bij toestandsverandering (§32) */
.bookmark-nav-caret {
  margin-left: auto;
  color: var(--text-muted);
  transition: transform 0.15s ease;
}

.bookmark-nav[open] .bookmark-nav-caret { transform: rotate(90deg); }

/* Uitgeklapt: groepen chips, natuurlijke hoogte — de pagina scrollt
   gewoon door, er is geen intern scrollmoment (besluit B8).
   Groepering komt uit controllers.py (bookmarkable_field + toc_groep_voor):
   "Voorblad" (status/productgegevens/brainstorm) en daarna één groep per
   bijsluiter-sectie (A t/m F);
   elke groep is één cluster dat op een regel blijft (titel + chips),
   zodat de balk compact genoeg blijft om sticky te zijn. */
.bookmark-list {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px dashed var(--border);
}

/* Groep = titel + chips als één blok; de DIV-wrappers rond de losse
   links doen visueel niet mee in de flex-rij. Binnen een groep mag
   afgebroken worden (smalle schermen), tussen groepen breekt de lijst. */
.bookmark-groep {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.bookmark-groep > div { display: contents; }

.bookmark-groep-titel {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
}

/* Actieve sectie: de chips dragen al de onderstreping; de groepstitel
   licht mee op (kleur alleen is nooit de enige drager, §33) */
.bookmark-groep:has(a.is-sectie-actief) .bookmark-groep-titel {
  color: var(--text-primary);
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

.bookmark-nav a {
  display: inline-block;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--text-secondary);
  background-color: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  padding: 0.25em 0.7em;
  text-decoration: none;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.bookmark-nav a:hover,
.bookmark-nav a:focus-visible {
  color: var(--text-primary);
  border-color: var(--border-strong);
  text-decoration: none;
}

.bookmark-nav a:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* Leeg veld: waarschuwingsaccent op token-basis, klein en lokaal —
   geen geel-vul-blok; icoon + kleur + tekst dragen de betekenis samen */
.bookmark-nav a.warning {
  color: var(--warning);
  background-color: var(--warning-bg);
  border-color: var(--warning-border);
}

.bookmark-nav a.warning::before {
  content: '⚠';
  margin-right: 4px;
  font-size: 0.85em;
}

.bookmark-nav a.warning:hover,
.bookmark-nav a.warning:focus-visible {
  color: var(--warning);
  border-color: var(--warning);
}

/* B31: aftelindicator naast het pijltje — een taartdiagram (conic-gradient) dat
   leegloopt zolang de inhoud zichtbaar is; bevriest tot een ringetje met
   pauzeteken zolang de muis (of focus) erop staat. currentColor houdt het in
   beide thema's correct. */
.bookmark-nav-timer {
  position: relative;
  width: .8rem;
  height: .8rem;
  flex: 0 0 auto;
  border-radius: 50%;
  color: var(--text-muted);
  background: conic-gradient(currentColor calc(var(--pct, 100) * 1%), transparent 0);
  opacity: .75;
}

.bookmark-nav-timer.is-pauze {
  background: none;
  border: 1px solid currentColor;
  opacity: .5;
}

.bookmark-nav-timer.is-pauze::after {
  content: '⏸';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .45rem;
  line-height: 1;
}

/* B32: de Voorblad-groep toont alleen een titel en die titel is de link naar
   het eerste veld. Ziet eruit als de andere groepstitels (geen chip-vulling,
   rand of padding), maar is wel een echte <a> zodat sectieNavigatie hem als
   chip voor de Algemeen-sectie kan markeren. */
a.bookmark-groep-titel {
  max-width: none;
  padding: 0;
  background: none;
  border: 0;
  color: var(--text-muted);
}

a.bookmark-groep-titel:hover,
a.bookmark-groep-titel:focus-visible {
  color: var(--text-primary);
}

/* Doelvelden: genoeg ruimte bovenin zodat het doel niet achter de
   sticky balk verdwijnt (§6/§8). Open klappen = de balk is dan een
   stuk hoger, dus grotere marge — :has() wint hier op specificiteit
   van de basisregel hierboven. */
div.field[id^='bm_'] {
  scroll-margin-top: var(--fieldnav-clearance);
}

html:has(#fieldnav[open]) div.field[id^='bm_'] {
  scroll-margin-top: var(--fieldnav-clearance-open);
}

/* --- WP15 (herzien): sectie-navigatie via de ToC-chips ---------------------
   De aparte sectie-strip (statuschip + Algemeen/Thema-pills) is vervallen —
   één balk, en de bestaande bookmark-chips doen het werk: ze openen de
   juiste sectie, markeren de zichtbare sectie en dragen het AI-wandsignaal
   van een verborgen sectie. Kleur draagt nooit alleen de betekenis (§33):
   onderstreping + vet, náást de sectie-inhoud zelf. */
.bookmark-list a.is-sectie-actief {
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

/* Lopende AI-wand op een verborgen sectie: korte pulssignalering (§18/§23 —
   de toestand verhuist mee naar de navigatie) */
.bookmark-list a.heeft-signal {
  border-color: var(--accent);
  animation: sectie-signal 1s ease-in-out infinite;
}

@keyframes sectie-signal {
  50% { opacity: 0.35; }
}

/* [hidden]-guard (zelfde valkuil als .statusbar-debug): author-regels — en die
   van Bulma zet `section` op display:block — winnen altijd van de UA-[hidden]-
   regel, dus hier expliciet zodat alleen de actieve sectie rendert */
.sectie-pane[hidden] {
  display: none;
}

/* --- Bijlagen: zelfde rustige sectie-stijl (kleine opruiming) --- */
.attachment-list {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
}

.attachment-list li {
  padding: var(--space-1) 0;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border);
}

.attachment-list li:last-child {
  border-bottom: none;
}

.attachment-list a {
  margin-left: var(--space-2);
  font-size: var(--text-xs);
}

/* =====================================================
   16. Projectscherm — AI-widget toolbar & tab-pills (WP5)
   De toolbar per veld: wand + status-pills links, "Update Status"
   rechts (besluit B1: de per-veld "Alles opslaan"-submits zijn uit
   de code verwijderd; opslaan loopt via de statusbalk-knop en de
   formulier-submit onderaan). Alle inline <style>-regels uit
   project.html zijn hierheen verhuisd en op tokens gezet, zodat
   licht en donker automatisch beide kloppen (§33, §37).
   Label-emoji-contract (2.3.1): pills stýlen alleen — de tekst
   blijft beginnen met de emoji + (n)-telling, JS leest slice(0,2).
   ===================================================== */

/* --- Toolbar per veld: één vaste rij, consistente hoogtes --- */
.ai-tab-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-2);
  margin: var(--space-2) 0;
}

/* --- Woordteller (backlog "word-count"): live teller onder AI-tekstvelden;
   overschrijden mag, maar de teller kleurt rood met waarschuwingsteken --- */
.word-counter {
  margin: 2px 0 var(--space-2);
  font-size: var(--text-sm);
  color: var(--text-secondary);
}
.word-counter.is-over {
  color: var(--danger);
  font-weight: 600;
}
.word-counter .word-counter-icon {
  margin-right: 4px;
}

/* Bulma geeft <a>/<input>/<button> verschillende paddings: normaliseren */
.ai-tab-row .button,
.ai-tab-row .tab-label {
  height: 2rem;
  padding: 0 0.8em;
  line-height: 1;
  display: inline-flex;
  align-items: center;
}

/* B23: de "Onderzoek verbeteringen"-knop staat op de wand-rij, links —
   direct ná de pills, op dezelfde regel als het 🪄-icoon (geen losse
   regel meer). De fase-1-"rechts"-uitlijning (margin-left: auto) is
   hiermee vervallen. Gedempte outline-stijl (§11): stiller dan de
   gevulde accent-knop */
.ai-tab-row > .button {
  margin-left: 0;
}

.ai-tab-row > .button.is-info {
  background-color: var(--bg-card);
  color: var(--text-secondary);
  border: 1px solid var(--border-strong);
  font-weight: 500;
}

.ai-tab-row > .button.is-info:hover {
  background-color: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-hover);
}

/* --- Tab-pills: rustige chips; actieve tab krijgt subtiel accent (§11) --- */
.ai-tab-row .tab-label {
  margin: 0;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-secondary);
  background-color: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  cursor: pointer;
  user-select: none;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.ai-tab-row .tab-label:hover {
  color: var(--text-primary);
  border-color: var(--border-strong);
}

.ai-tab-row .tab-label:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* Actieve tab (ook de invert-uit de oude dark-blokken: tokens regeren nu).
   De wand (.always-active) hoort hier NIET bij: die is geen status-tab maar
   een actie-knop en blijft in ruststand (§11). */
.ai-tab-row .tab-label.active {
  color: var(--text-primary);
  background-color: var(--accent-soft);
  border-color: var(--accent);
}

/* Wand-knop: rustige, duidelijke knopvorm, iets steviger dan de pills */
.ai-tab-row .tab-label.always-active {
  background-color: var(--bg-card);
  border-color: var(--border-strong);
}

.ai-tab-row .tab-label.always-active:hover {
  border-color: var(--accent);
}

/* --- Wand-knop: rustige, duidelijke knopvorm (§32: beweging alleen
   tijdens verwerking — de spinner toont zich alleen bij ai-running) --- */
.ai-wand .ai-spinner {
  display: none;
  margin-left: 4px;
}

.ai-wand.ai-running .ai-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  vertical-align: middle;
}

/* --- Tab-content: strak, kalm, kleine padding (WP6 breidt dit uit) --- */
.tab-content {
  display: none;
  margin-top: var(--space-1);
  padding: var(--space-2) var(--space-3);
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: var(--text-sm);
}

.tab-content.active {
  display: block;
}

/* B16: item-regels gelden uitsluitend voor de top-level resultaat-items
   (> ol > li) — nooit voor geneste markdown-lijsten in de uitklap
   (.dod-layer-*), anders krijgen die een eigen LED-anker/marker-stijl */
.tab-content > ol {
  margin: 0;
  padding-left: 1.25rem;
}

.tab-content > ol > li {
  padding: var(--space-1) 0;
  line-height: 1.5;
}

/* --- Status-LED: klein, naast de tekst, duidelijke regelafstand (§33) --- */
.status-light {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin: 0 6px 0 0;
  vertical-align: middle;
}

.status-light.red    { background-color: var(--danger); }
.status-light.orange { background-color: var(--warning); }
.status-light.green  { background-color: var(--success); }
.status-light.dimmed { background-color: var(--border-strong); }

/* --- Veld-lock zolang de AI-wand dat veld genereert (monochroom, geen invoer) --- */
textarea.ai-field-locked,
input.ai-field-locked,
select.ai-field-locked {
  filter: grayscale(1);
  opacity: 0.6;
}

/* WP11: collega-lock — het veld staat vast zolang een ander erin typt (§14:
   toestand hoort bij het veld zelf). Was 3× dezelfde inline-styles-set in
   de focus/locked/blur-handlers (met hardcoded #f14668) — nu één class;
   het uitzetten/activeren van `disabled` en de title 🔒 blijven in de JS. */
input.field-locked,
textarea.field-locked,
select.field-locked {
  pointer-events: none;
  opacity: 0.5;
  border-color: var(--danger);
}

/* --- Socket onbereikbaar bij het laden: banner + gedempte, niet-klikbare knoppen
   (B20: de kwaliteits-knop woont in de kop-regel, daarom óók .dod-header-row) --- */
body.sio-down .ai-wand,
body.sio-down .ai-tab-row .button,
body.sio-down .dod-header-row .button,
body.sio-down .ai-tab-row .tab-label,
body.sio-down #floating-save-btn {
  pointer-events: none;
  filter: grayscale(1);
  opacity: 0.6;
}

/* Sio-meldingen (project.html): Bulma .notification kleurt hardcoded —
   koppel de twee app-meldingen terug aan de alert-tokens (§37), zelfde
   linkerbalk- plus tinttaal als de flash-alerts (sectie 10) */
#sio-unavailable,
#wand-melding {
  background-color: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  border-left: 4px solid var(--info);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

#sio-unavailable {
  border-left-color: var(--danger);
  background-color: var(--danger-bg);
}

#wand-melding {
  border-left-color: var(--warning);
  background-color: var(--warning-bg);
}

/* Tijdelijke melding bij een mislukte wand-aanroep — boven de statusbalk
   zodat ze niet overlappen (JS toont/verbergt via display) */
#wand-melding {
  position: fixed;
  bottom: 60px;
  left: 20px;
  z-index: 1000;
  max-width: 420px;
  display: none;
}

/* =====================================================
   17. Projectscherm — kwaliteitsresultaten binnen tabs (WP6)
   Presentatie-only (§21, §23, §33): de data (msg + rule via
   status_led_update) en de structuur (ol > li > span) blijven;
   alleen CSS geeft rust en hiërarchie.
   Belangrijk gedrag: de JS verplaatst het <li> (led_id) tussen de
   tab-content-<ol>'s. Vanaf WP9 bouwt de JS de item-inhoud opnieuw op
   (LED-span behouden, ruststand + uitklap, sectie 17b); dit CSS-anker
   (::before) geldt daardoor alleen nog voor items zonder LED-span
   (backwards-compat), zodat beide item-vormen consistent blijven.
   Pending (dimmed) is geen vierde stoplichtkleur maar processtatus
   (§23): grijs, gedempt, placeholder-stijl, geen animatie (§32).
   Rijen zijn ruim genoeg voor fase-2-detail (§25–§28) inline onder
   het item.
   ===================================================== */

/* --- Tab-content-omgeving: kalm, strak, leesbare typografie --- */
.tab-content {
  padding: var(--space-3) var(--space-4);
  line-height: 1.55;
  /* Fase-1 presentatie: lange beoordelingen (volledige AI-output, §28) zijn
     nu al zichtbaar, maar scrollen binnen de kaart i.p.v. de pagina opdrukken;
     fase 2 vervangt dit door details-on-demand per item (§25–§28) */
  max-height: 24rem;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}

.tab-content::-webkit-scrollbar {
  width: 6px;
}

.tab-content::-webkit-scrollbar-thumb {
  background-color: var(--border-strong);
  border-radius: var(--radius-full);
}

/* Nummering 1..n is geen inhoudelijke info: de LED / het anker is het
   visuele beginpunt (CSS-only; de ol-structuur blijft voor de JS) */
/* B16: zie boven — item-regels alleen voor top-level items (> ol > li);
   geneste markdown-li's in de uitklap erven géén LED-anker, hanging
   indent of itemscheiding */
.tab-content > ol {
  list-style: none;
  margin: 0;
  padding: 0;
}

.tab-content > ol > li {
  position: relative;
  margin: 0;
  padding: 6px 0 6px 18px;
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--text-secondary);
  overflow-wrap: break-word;
  /* de sioserver-msg bevat newlines (markdown-achtige toelichting);
     die behouden voor leesbaarheid */
  white-space: pre-wrap;
}

/* Hairline-scheiding tussen items: scandeerbaar en rustig; fase-2
   (details on-demand) kan later inline onder elk item openen */
.tab-content > ol > li + li {
  border-top: 1px solid var(--border);
}

.tab-content > ol > li:last-child {
  padding-bottom: 2px;
}

/* --- LED-anker --- */

/* Items met een eigen LED-span (initiële pending-items, en alles wat de
   JS eraan laat hangen): LED als absoluut anker links, tekst blijft
   op de hanging indent — dezelfde regelmaat voor beide item-vormen */
.tab-content > ol > li > .status-light {
  position: absolute;
  left: 0;
  top: 0.45em;
  margin: 0;
}

/* Items die hun LED-span kwijt zijn (na textContent = msg): CSS-anker
   in de kleur van het tabblad waar de JS het item heeft geplaatst */
.tab-content > ol > li:not(:has(> .status-light))::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 10px;
  height: 10px;
  border-radius: 50%;
}

[id$='_green_content'] > ol > li:not(:has(> .status-light))::before  { background-color: var(--success); }
[id$='_orange_content'] > ol > li:not(:has(> .status-light))::before { background-color: var(--warning); }
[id$='_red_content'] > ol > li:not(:has(> .status-light))::before    { background-color: var(--danger); }
/* Dimmed: grijs via de basis (border-strong), zie hieronder */

/* --- Pending (dimmed) als processtatus (§23): geen vierde kleur --- */
[id$='_dimmed_content'] > ol > li {
  color: var(--text-muted);
  font-style: italic;
}

[id$='_dimmed_content'] > ol > li:not(:has(> .status-light))::before {
  background-color: var(--border-strong);
}

/* De initiële pending-LED draagt inline background dimgray (controllers,
   contract) — gedempt presenteren via opacity, geen CSS-kleur-strijd */
[id$='_dimmed_content'] > ol > li > .status-light {
  opacity: 0.55;
}

/* De "..."-placeholder: rustig, proces-achtig */
[id$='_dimmed_content'] > ol > li > span:not(.status-light) {
  color: var(--text-muted);
  letter-spacing: 1px;
}

/* --- Lege tab: één rustige regel in gebruikerstaal (§34), CSS-only --- */
.tab-content ol:empty::after {
  content: 'Nog geen beoordelingen';
  display: block;
  padding: 4px 0 2px;
  color: var(--text-muted);
  font-style: italic;
  font-size: var(--text-sm);
}

/* =====================================================
   17b. Kwaliteitsresultaten — progressive disclosure (WP9)
   Ruststand (§21): LED (kleur, fase-1-stijl) + rule als
   contextlabel + kern (één regel, platte tekst). Details
   klappen lokaal binnen het item uit (§25): toelichting,
   tips, antwoord, bron (alleen bij aanwezigheid, §26) en
   de volledige beoordeling (§28, verder gedempt).
   Markdown wordt eerst geëscapet en dan geformatteerd (B6);
   de gegenereerde <p>/<ul>-structuur moet daarom de li-
   pre-wrap uitzetten. Bij rood/oranje krijgt Verbeteren
   meer nadruk dan Antwoord (§27). Animatie alleen op
   toestandsverandering (§32) — alleen de toggle-richting.
   ===================================================== */

/* item-body hangt onder de absolute LED (hanging indent van sectie 17);
   white-space normal i.v.m. de markdown-whitespace tussen blokelementen */
.dod-item-body {
  white-space: normal;
}

/* B27: bewaarde vorige beoordeling tijdens een herwaardering — rustig
   gemute zodat de ⏳-placeholder de aandacht heeft, maar leesbaar blijft */
.dod-item-prev {
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px dashed var(--border);
  opacity: 0.72;
  font-size: 0.92em;
}

.dod-item-prev-label {
  display: block;
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-bottom: 0.2em;
}

/* B42: tijd + wie onder de kopregel. Bewaard én live resultaat dragen
   dezelfde regel (assessed_on/assessed_by), zodat een oude beoordeling nooit
   als "net gemaakt" gelezen wordt en een verversing niets verandert aan de
   weergave. Rustig en klein (§11). */
.dod-item-meta {
  display: block;
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-top: 2px;
}

/* --- Ruststand: kopregel met rule-contextlabel + kern --- */
.dod-item-rule {
  display: block;
  font-size: var(--text-xs);
  color: var(--text-muted);
  letter-spacing: 0.02em;
  margin-bottom: 1px;
}

.dod-item-kern {
  display: block;
  color: var(--text-primary);
  font-size: var(--text-sm);
  /* één regel: de toelichting hoort in de uitklap (§21) */
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

/* --- WP13/B15: per-DoD herwaardering (⟳) ---
   Rustig klein en permanent zichtbaar (§11): niet hover-only, want
   ontdekbaarheid is hier het punt van de feature én touch heeft geen
   hover; de gedempte muted-tinctuur (60% opacity) houdt de ruststand
   kalm. Geen permanente animatie (§32) — alleen een rustige hover/focus-
   tint. Betekenis met tekst via title/aria-label (§33). Het glyph ⟳
   sluit aan bij de kop-regelknop (B20), die eromheen dezelfde ⟳ via
   CSS ::before draagt. */
.dod-item-head {
  position: relative;
  /* ruimte voor het rechtsboven zwevende ⟳-icoontje, óók naast de kern */
  padding-right: 1.6em;
}

/* Selector verheven (.dod-item-head .dod-refresh + expliciete dark-variant):
   no.css zet op <button> width 100px / display block / height 1.8rem en
   theme.css vult in donker álle buttons met accent (`:root[data-theme='dark']
   button`, (0,2,1)) — hier geneutraliseerd zodat het icoontje een klein,
   gedempt glyph blijft (§11), zelfde patroon als .copy-btn */
.dod-item-head .dod-refresh,
:root[data-theme='dark'] .dod-item-head .dod-refresh {
  position: absolute;
  top: -1px;
  right: 0;
  width: auto;
  height: auto;
  /* no.css (min-width 100px) en de theme.css-button-basis (min-height
     2.25rem) mogen het kleine glyph niet opblazen */
  min-width: 0;
  min-height: 0;
  display: inline-block;
  appearance: none;
  background: none;
  border: none;
  padding: 0 2px;
  margin: 0;
  font: inherit;
  font-size: 0.95em;
  line-height: 1;
  color: var(--text-muted);
  opacity: 0.6;
  cursor: pointer;
  border-radius: var(--radius-sm);
  box-shadow: none;
}

.dod-item-head .dod-refresh:hover,
.dod-item-head .dod-refresh:focus-visible,
:root[data-theme='dark'] .dod-item-head .dod-refresh:hover,
:root[data-theme='dark'] .dod-item-head .dod-refresh:focus-visible {
  color: var(--accent-hover);
  opacity: 1;
  background-color: var(--accent-soft);
  box-shadow: none;
}

.dod-item-head .dod-refresh:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* Fallback-weergave (oude emit, msg als platte tekst): pre-wrap behouden */
.dod-item-plain {
  display: block;
  white-space: pre-wrap;
  color: var(--text-secondary);
}

/* --- Uitklap-toggle: klein, gedempt, driehoek draait bij openen (§32) --- */
.dod-item-details {
  margin-top: 2px;
}

.dod-item-details > summary {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  list-style: none;
  user-select: none;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.dod-item-details > summary::-webkit-details-marker {
  display: none;
}

.dod-item-details > summary:hover {
  color: var(--text-secondary);
}

.dod-toggle-icon {
  display: inline-block;
  transition: transform 0.15s ease;
}

.dod-item-details[open] > summary .dod-toggle-icon {
  transform: rotate(180deg);
}

/* --- Informatielagen binnen de uitklap --- */
.dod-layer {
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px dashed var(--border);
}

.dod-layer-label {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-bottom: 2px;
}

.dod-layer-content {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

/* markdown-blokelementen (uit de escape→format-rendering) kalm vormgeven */
.dod-layer-content p {
  margin: 0 0 6px;
}

.dod-layer-content p:last-child {
  margin-bottom: 0;
}

.dod-layer-content ul,
.dod-layer-content ol {
  margin: 0;
  padding-left: 1.1rem;
}

/* B16: eigen markers voor gerenderde markdown — de top-level tab-ol is
   marker-loos (de LED is het beginpunt), maar die stijl mag niet door-
   lekken in de uitklap: een tips-lijst leest alleen met zichtbare
   bullets/nummers (kleur draagt de betekenis hier niet, §33) */
.dod-layer-content ul {
  list-style: disc;
}

.dod-layer-content ol {
  list-style: decimal;
}

.dod-layer-content li::marker {
  color: var(--text-muted);
}

.dod-layer-content li {
  margin: 0 0 3px;
  padding: 0;
  /* items binnen markdown: geen hanging indent van de li-niveaus erboven */
  white-space: normal;
}

.dod-layer-content code {
  font-family: inherit;
  font-size: 0.95em;
  background-color: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0 4px;
}

.dod-layer-content pre {
  margin: 0 0 6px;
  padding: 6px 8px;
  background-color: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow-x: auto;
}

.dod-layer-content pre code {
  background: none;
  border: none;
  padding: 0;
}

.dod-layer-content a {
  color: var(--text-secondary);
  text-decoration: underline;
}

/* --- Rood/oranje: Verbeteren krijgt de nadruk (§27) --- */
.dod-item[data-color='red'] .dod-layer-tips {
  border-left: 3px solid var(--danger);
  padding-left: 8px;
}

.dod-item[data-color='orange'] .dod-layer-tips {
  border-left-color: var(--warning);
}

.dod-item[data-color='red'] .dod-layer-tips > .dod-layer-label {
  color: var(--danger);
}

.dod-item[data-color='orange'] .dod-layer-tips > .dod-layer-label {
  color: var(--warning);
}

/* --- Volledige beoordeling: verder gedempt (§28) --- */
.dod-layer-full {
  margin-top: 8px;
  font-size: var(--text-xs);
}

.dod-layer-full > summary {
  cursor: pointer;
  list-style: none;
  color: var(--text-muted);
}

.dod-layer-full > summary::-webkit-details-marker {
  display: none;
}

.dod-layer-full > summary::before {
  content: '▾ ';
}

.dod-layer-full > .dod-layer-content {
  margin-top: 4px;
  padding-top: 6px;
  border-top: 1px dashed var(--border);
  color: var(--text-muted);
  font-size: var(--text-xs);
}

/* =====================================================
   18. Overige pagina's (WP7) — index, prompts, output,
   auth, dod, upload, single_prompt, generic (§37)
   Alleen CSS/HTML-presentatie; de py4web Grid-classes
   (.grid-table, .grid-cell-*, .grid-button) worden gestyled,
   niet vervangen.
   ===================================================== */

/* Bulma kleurt <b>/<strong> hardcode #363636 — leesbaar in licht,
   bijna onleesbaar in donker; erven van de tekstkleur zodat de
   tokens regeren (§37, beide thema's eerste klas) */
b, strong {
  color: inherit;
}

/* Bulma .title/.subtitle hardcode #363636 — zelfde probleem in donker */
.title, .subtitle {
  color: var(--text-primary);
}

/* (De no.css-dark-neutralisatie is in WP8 verplaatst naar sectie 2b,
    direct na de design-tokens.) */

/* -----------------------------------------------------
   Upload-formulier: de file-input moet in ELKE browser de native
   pickerdialoog kunnen openen — geen verhulling, geen overlay,
   geen 0-breedte. Chrome-fail-silent-tegenmaatregel.
   ----------------------------------------------------- */
form input[type="file"] {
  position: static !important;
  opacity: 1 !important;
  visibility: visible !important;
  pointer-events: auto !important;
  width: auto !important;
  height: auto !important;
}

/* -----------------------------------------------------
   18.1 Index-grid — rustige tabel met card-omkadering
   Kolomvolgorde (controllers.py, read-only): id, status,
   title, Contact, Progress, actieknoppen.
   ----------------------------------------------------- */
.grid-header {
  margin-bottom: var(--space-3);
}

.grid-table {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  border-collapse: separate;  /* voor de afgeronde hoeken */
  border-spacing: 0;
  overflow: clip;
}

/* is-bordered van Bulma vervangen door rustige rij-scheiding */
.grid-table th,
.grid-table td {
  border: none;
}

.grid-table tbody td {
  border-bottom: 1px solid var(--border);
}

.grid-table tbody tr:last-child td {
  border-bottom: none;
}

/* Strakke, gedempte kopregel */
.grid-table thead th {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: var(--space-2) var(--space-3);
}

/* Ruimere cellen (§41: leesbaarheid) */
.grid-table td {
  padding: var(--space-3);
}

/* --- Statuskolom als rustig label (§11/§33): klein, semibold,
   secundair. Echte semantische badges per status (010-concept
   e.d.) vergen een data-attribuut in de Grid-rendering — fase 2. --- */
.grid-table td.grid-col-project_status {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text-secondary);
  white-space: nowrap;
}

/* --- Voortgangsbalk: subtiel, compact, accent-token --- */
.grid-table progress.progress {
  height: 0.65rem;
  width: min(10rem, 100%);
  border-radius: var(--radius-full);
  overflow: hidden;
}

.grid-table progress.progress::-webkit-progress-value {
  background-color: var(--accent);
}

.grid-table progress.progress::-moz-progress-bar {
  background-color: var(--accent);
}

/* --- Actieknoppen (Edit/Output/Bucket): rustige outline-stijl (§11).
   GridActionButton rendert <a role="button"> zonder .button-class —
   no.css kleurt die blauw; hier terug naar kalm outline. --- */
.grid-table [role='button'] {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background-color: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  padding: 0.3em 0.75em;
  text-decoration: none;
}

.grid-table [role='button']:hover {
  background-color: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-hover);
  text-decoration: none;
}

/* --- Footer/paginering gedempt --- */
.grid-footer {
  color: var(--text-muted);
  font-size: var(--text-sm);
}

/* -----------------------------------------------------
   18.2 Prompts-overzicht — per veld een blok (§20, §34)
   Structuur: dl.prompt-list > (dt + dd), DoD-items als
   ul.dod-items > dl.dod-list.
   ----------------------------------------------------- */
.prompt-list {
  margin: 0;
}

.prompt-list > dt {
  margin: 0;
  padding: var(--space-2) var(--space-4);
  background-color: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  font-size: var(--text-md);
}

.prompt-list > dd {
  margin: 0 0 var(--space-5);
  padding: var(--space-3) var(--space-4) var(--space-2) calc(2 * var(--space-4));
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
}

/* "Behoort bij" / "Template gebruikt": gedempt, klein (§34) —
   de code zelf volgt de code-tokens (sectie 9) */
.prompt-meta {
  margin: 0 0 var(--space-2);
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-family: var(--font-mono);
}

.prompt-meta i {
  font-style: normal;
  color: var(--text-muted);
}

.prompt-meta code {
  font-size: 0.9em;
}

/* --- DoD-regels als nette lijstitems --- */
.dod-items {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
}

.dod-items > li {
  padding: var(--space-2) 0;
  border-top: 1px solid var(--border);
}

.dod-list {
  margin: 0;
}

.dod-list dt {
  font-size: var(--text-sm);
  line-height: 1.6;
}

.dod-list dd {
  margin: 0 0 0 var(--space-4);
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-family: var(--font-mono);
}

.dod-list dd i {
  font-style: normal;
}

/* --- "voeg definition of done toe": neutrale toevoeg-actie --- */
.dod-add {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
  font-size: var(--text-sm);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-full);
  padding: 0.25em 0.9em;
  text-decoration: none;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.dod-add:hover {
  color: var(--accent);
  border-color: var(--accent);
  text-decoration: none;
}

/* --- PlantUML: inklapbaar (§20, besluit B5: default ingeklapt) --- */
.plantuml-details {
  margin-top: var(--space-5);
}

.plantuml-details summary {
  cursor: pointer;
  color: var(--text-secondary);
  font-weight: 500;
  font-size: var(--text-sm);
}

.plantuml-details summary:hover {
  color: var(--text-primary);
}

.plantuml-details img {
  display: block;
  max-width: 100%;
  margin-top: var(--space-3);
  padding: var(--space-3);
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

/* --- Model-zoekbox + resultaten (contract #model_search_box /
   #model_search_results / .dropdown-item blijft exact) --- */
[id^='model_search_results'] {
  max-height: 240px;
  overflow-y: auto;
  margin-top: var(--space-2);
  display: block;
  width: 100%;
}

/* Binnen de container: htmx levert direct .dropdown-content; de
   HTMXModelWidget-formulieren wijken .dropdown-menu/.dropdown-content */
[id^='model_search_results'] .dropdown-menu {
  position: static;
  display: block;
  min-width: 0;
  box-shadow: none;
  padding: 0;
}

[id^='model_search_results'] .dropdown-content {
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-1) 0;
}

[id^='model_search_results'] .dropdown-content:empty {
  display: none;
}

.dropdown-item {
  display: block;
  padding: 0.4em 1em;
  cursor: pointer;
  font-size: var(--text-sm);
  color: var(--text-primary);
}

.dropdown-item:hover {
  background-color: var(--bg-subtle);
}

/* -----------------------------------------------------
   18.3 Output — field-blokken als cards met header-scheiding
   De markdown-rendering van de waarden blijft ongewijzigd.
   ----------------------------------------------------- */
.section.field-list-section {
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
}

.field-container {
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-5);
}

.field-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--border);
}

.field-label {
  font-weight: 600;
  color: var(--text-primary);
}

.field-name {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-left: var(--space-2);
  font-family: var(--font-mono);
}

/* Copy-knop: rustige outline-stijl (§11). Selector verheven boven de
   no.css-dark-neutralisatie (`:root[data-theme='dark'] button`),
   anders is de knop in donker gevuld accent i.p.v. outline */
.button.is-small.copy-btn {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  background-color: var(--bg-card);
  border: 1px solid var(--border-strong);
}

.button.is-small.copy-btn:hover {
  background-color: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-hover);
}

/* Markdown-output leesbaar binnen de card */
.field-container p {
  margin: 0 0 var(--space-3);
}

.field-container p:last-child {
  margin-bottom: 0;
}

.field-container ul,
.field-container ol {
  margin: 0 0 var(--space-3);
  padding-left: 1.5rem;
}

.field-container h1, .field-container h2 {
  font-size: var(--text-lg);
}

.field-container h3, .field-container h4 {
  font-size: var(--text-md);
}

.field-container blockquote {
  margin: 0 0 var(--space-3);
  padding-left: var(--space-4);
  border-left: 3px solid var(--border-strong);
  color: var(--text-secondary);
}

.field-container table {
  margin-bottom: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
}

/* -----------------------------------------------------
   18.4 Auth — centrale card met witruimte
   ----------------------------------------------------- */
.auth-container {
  max-width: 480px;
  min-width: 0;
  margin: var(--space-6) auto;
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: var(--space-6);
}

/* -----------------------------------------------------
   18.5 Overige pagina's — dod / generic / overige cards
   ----------------------------------------------------- */
/* dod.html: veldcomment als pre (tokens, sectie 9) en de DoD-
   regels als kalme lijst */
.dod-rules {
  margin: var(--space-4) 0;
  padding: 0;
  list-style: none;
  max-width: 720px;
}

.dod-rules li {
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border);
}

.dod-rules li:last-child {
  border-bottom: none;
}

/* generic.html — vars-samenvatting */
.vars {
  padding: var(--space-2) var(--space-5);
  text-align: center;
}

.vars th:after {
  content: ': ';
}

.vars th, .vars td, .vars li {
  padding: 2px 5px;
}

/* =====================================================
   19. Projectscherm — stoplicht-navigator (WP10, §22/§23)
   Verticale teller-knoppenkolom (🔴/🟠/🟢) links van de
   kwaliteitsfeedback van elk AIWidget-veld. Klik filtert de
   zichtbare resultaten op kleur (items met een andere kleur
   worden in álle vier content-divs verborgen); tweede klik
   heft het filter op. Pending (dimmed) hoort níét bij het
   stoplicht (§23) — die is processtatus en krijgt geen
   navigator-knop. Groen blijft beschikbaar maar gedempt
   (§22); kleur draagt nooit alleen de betekenis (§33):
   emoji + aantal + woord. Alleen toestandsverandering als
   beweging (§32) — de knoppen pulsen of schuiven niet.
   ===================================================== */

/* --- Omsluitende rij: navigator-kolom + tab-content naast elkaar --- */
.dod-feedback-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
}

/* De tab-content-div naast de kolom: zelfde breedte-gedrag als vóór de
   navigator (vult de resterende rij); zonder expliciete flex-sizing
   maalt max-content van lange AI-teksten de rij op */
.dod-feedback-row > div:not(.dod-navigator) {
  flex: 1 1 auto;
  min-width: 0;
}

/* Verticale kolom: vaste, smalle breedte (de knoppen bepalen niet de
   kolombreedte); pas zichtbaar zodra er beoordelingen zijn (is-empty):
   een lege kolom naast "Nog geen beoordelingen" is ruis */
.dod-navigator {
  display: none;
  flex-direction: column;
  gap: 4px;
  width: 9rem;
  /* no.css heeft een globale nav-bar-regel (`nav { display:table;
     width:100vw; height:40px }`) — hier geneutraliseerd, anders krijgt
     de kolom viewport-breedte en een 40px-hoogte waarin de knoppen
     over de eronder liggende velden heen lopen */
  height: auto;
  flex-shrink: 0;
  padding: var(--space-1);
  background-color: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.dod-navigator:not(.is-empty) {
  display: flex;
}

/* --- Navigator-knop: emoji + aantal + woord (§33), tweeregelig --- */
.dod-nav-btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  min-width: 7.5rem;
  /* no.css <button>: height 1.8rem + margin 10px — geneutraliseerd,
     de knop hoort zijn tweeregelige inhoud omvatten */
  height: auto;
  margin: 0;
  padding: 4px 8px;
  font: inherit;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  text-align: left;
  background-color: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.dod-nav-btn:hover {
  color: var(--text-primary);
  border-color: var(--border-strong);
}

.dod-nav-btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* no.css zet een zware drop-shadow op button:hover — hier ongedaan gemaakt
   (§11: de kolom is een navigatiehulpje, geen actie-knop) */
.dod-nav-btn:hover,
:root[data-theme='dark'] .dod-nav-btn:hover {
  box-shadow: none;
}

.dod-nav-main {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-sm);
}

.dod-nav-count {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.dod-nav-word {
  color: var(--text-muted);
}

/* Kleur-hint aan de linkerrand (extra laag naast emoji+tekst, §33) */
.dod-nav-red    { border-left: 3px solid var(--danger); }
.dod-nav-orange { border-left: 3px solid var(--warning); }
.dod-nav-green  { border-left: 3px solid var(--success); }

/* §22: groen beschikbaar maar gedempt; nul-stand nog rustiger */
.dod-nav-green {
  opacity: 0.85;
}

.dod-nav-btn.is-zero {
  opacity: 0.55;
}

/* Actieve filter (§22): zachte accent-tint, geen felle invert (§11) */
.dod-nav-btn[aria-pressed='true'] {
  background-color: var(--accent-soft);
  border-color: var(--accent);
  color: var(--text-primary);
  opacity: 1;
}

/* no.css/theme.css neutraliseren <button> met hogere specificiteit
   (`:root[data-theme='dark'] button`, (0,2,1)) — hier verheven zodat de
   navigator-knoppen in donker óók de token-vorm dragen (§37) */
:root[data-theme='dark'] .dod-nav-btn {
  background-color: var(--bg-card);
  color: var(--text-secondary);
  border-color: var(--border);
}

:root[data-theme='dark'] .dod-nav-btn:hover {
  color: var(--text-primary);
  border-color: var(--border-strong);
}

:root[data-theme='dark'] .dod-nav-btn[aria-pressed='true'] {
  background-color: var(--accent-soft);
  border-color: var(--accent);
  color: var(--text-primary);
}

/* --- Filter actief: items met een andere kleur verdwijnen uit alle
   vier de content-divs; tellingen blijven de totalen tonen --- */
.tab-content li.dod-filter-hidden {
  display: none !important;
}

/* =====================================================
   19b. Projectscherm — B11 zandloper tijdens lopende DoD-processen
   Het dimmed-tab-pill toont ⏳ + gebruikerstaal zolang er
   minstens één controle van dat veld loopt; het echte
   resultaat- of error-event haalt de toestand per led_id weg
   (error telt als opgelost). Geen permanente animatie (§32):
   de zandloper is statisch en verdwijnt wanneer alles is
   opgelost — terug naar de as-is grijze stip.
   ===================================================== */

.ai-tab-row .tab-label.is-running {
  color: var(--text-primary);
  background-color: var(--warning-bg);
  border-color: var(--warning);
}

/* Item-niveau: de lopende controle in het dimmed-tabblad (§23:
   processtatus, geen kwaliteitsoordeel — daarom niet italic/muted
   maar gewoon leesbaar, met de ⏳ uit de JS-placeholder) */
[id$='_dimmed_content'] li.dod-running > span:not(.status-light) {
  color: var(--text-secondary);
  font-style: normal;
  letter-spacing: 0.3px;
}

/* --- B18: kleur-pills (🟢🟠🔴) alleen tijdens het controleproces ---
   Na afloop toont de navigator (§22) de tellingen; de pills zijn dan
   duplicatie en verdwijnen (reversibel via class — bij een nieuwe run
   komen ze gewoon terug). De ⚫️-pill (historie/resultaten) en de
   🪄-wand-pill blijven altijd zichtbaar; de knop woont in de kop-regel
   (B20). Geen display-wijziging op de rij zelf, geen ID-contract-raken. */
.ai-tab-row .tab-label.dod-pill-hidden {
  display: none;
}

/* =====================================================
   19c. Projectscherm — B20 kop-regel kwaliteits-sectie
   De "Controleer kwaliteit"-knop is de kop van de
   kwaliteits-zone: één rustige regel tussen de pill-rij
   (.ai-tab-row) en de feedback-zone (navigator + tab-content),
   links uitgelijnd. De JS verplaatst de knop client-side uit
   de pill-rij (controllers/AIWidget ongewijzigd); het
   onclick-contract (requestStatusUpdate-keten) blijft. De
   regel bestaat vanaf de eerste render — vóór de eerste run
   alleen de knop. Rustige stijl op tokens (§11); geen
   permanente animatie (§32).
   ===================================================== */

.dod-header-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  margin: var(--space-1) 0 var(--space-2);
  font-size: var(--text-sm);
}

/* De verplaatste knop: zelfde gedempte outline-stijl als in de
   pill-rij (§11) — actie zichtbaar maar geen fel accent in rust */
.dod-header-row .button {
  height: 2rem;
  padding: 0 0.8em;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  margin: 0;
  font-size: var(--text-sm);
  font-weight: 500;
}

/* ⟳-icoon: decoratie via CSS, de DOM-tekst (en daarmee het
   contract) blijft ongewijzigd */
.dod-header-row .button::before {
  content: '⟳ ';
  opacity: 0.7;
}

/* tokens regeren de kleur, ook in donker (verheven tegen
   no.css/Bulma-basisregels, zelfde tinctuur als de pill-rij) */
.dod-header-row .button.is-info,
:root[data-theme='dark'] .dod-header-row .button.is-info {
  background-color: var(--bg-card);
  color: var(--text-secondary);
  border: 1px solid var(--border-strong);
  box-shadow: none;
}

.dod-header-row .button.is-info:hover,
:root[data-theme='dark'] .dod-header-row .button.is-info:hover {
  background-color: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-hover);
  box-shadow: none;
}

.dod-header-row .button.is-info:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* ⏳-teller (WP10/B11) gespiegeld in de kop-regel: processtatus
   direct naast de actie die haar start; onzichtbaar zolang er
   niets loopt (hidden-attribuut uit de JS) */
.dod-header-row .dod-header-pending {
  color: var(--text-secondary);
  font-size: var(--text-sm);
}

.dod-header-row .dod-header-pending[hidden] {
  display: none;
}

/* =====================================================
   20. Toasts — tijdelijke notificaties (§13, WP11/F1)
   Toasts zijn voor gebeurtenissen ("er is iets gebeurd"),
   niet voor toestanden: verschijnen, enkele seconden
   zichtbaar, weg (§13). Noodzakelijke info staat nooit
   uitsluitend in een toast (§14); meldingen die actie
   vereisen blijven staan en krijgen de error-variant (§15).
   Container (.toast-stack) in layout.html; helper Q.showToast
   in utils.js; hooks op het projectscherm (project.html).
   De py4web flash-alerts blijven voor server-flash/auth.
   ===================================================== */

.toast-stack {
  position: fixed;
  /* net onder de navbar; de navbar is sticky (fase 1) */
  top: 3.5rem;
  right: var(--space-3);
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: 21rem;
  max-width: calc(100vw - 2 * var(--space-3));
  /* de stack vangt geen clicks; de kaarten zelf wel */
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  pointer-events: auto;
  background-color: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border);
  /* kleurenstreep links als betekenisdrager (tinttaal, §11/§10) */
  border-left: 3px solid var(--success);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-2) var(--space-3);
  font-size: 0.9rem;
  /* animatie alleen bij binnenkomst en vertrek (§32) */
  animation: toast-in 0.18s ease;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

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

.toast.toast-out {
  opacity: 0;
  transform: translateY(-4px);
}

.toast-icon {
  flex: none;
  color: var(--success);
  line-height: 1.3;
}

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

.toast-title {
  font-weight: 600;
}

.toast-sub {
  display: block;
  margin-top: 0.15rem;
  color: var(--text-secondary);
  font-size: 0.82rem;
}

.toast-action {
  display: inline-block;
  margin-top: 0.4rem;
  color: var(--accent);
  text-decoration: underline;
  cursor: pointer;
  font-size: 0.82rem;
}

/* Varianten: alleen de streep + het icoontje kleuren (§10 tinttaal) */
.toast.toast-info { border-left-color: var(--info); }
.toast.toast-info .toast-icon { color: var(--info); }

/* Klikbare toast (WP11): sprong naar het bijgewerkte veld via #anchor */
.toast.toast-clickable {
  cursor: pointer;
}

.toast.toast-clickable:hover {
  background-color: var(--bg-subtle);
}

.toast.toast-error { border-left-color: var(--danger); }
.toast.toast-error .toast-icon { color: var(--danger); }

/* Sluitkruisje — selector verheven (.toast .toast-close + expliciete
   dark-variant): no.css zet op <button> width/min-width en theme.css
   vult in donker álle buttons met accent (`:root[data-theme='dark']
   button`) — hier geneutraliseerd, zelfde patroon als .dod-refresh */
.toast .toast-close,
:root[data-theme='dark'] .toast .toast-close {
  flex: none;
  width: auto;
  height: auto;
  min-width: 0;
  min-height: 0;
  display: inline-block;
  appearance: none;
  background: none;
  border: none;
  padding: 0 0.15rem;
  margin: 0;
  font: inherit;
  font-size: 0.85rem;
  line-height: 1.3;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
  box-shadow: none;
}

.toast .toast-close:hover,
.toast .toast-close:focus-visible,
:root[data-theme='dark'] .toast .toast-close:hover,
:root[data-theme='dark'] .toast .toast-close:focus-visible {
  color: var(--text-primary);
  background-color: var(--bg-subtle);
  box-shadow: none;
}

.toast .toast-close:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* =====================================================
   21. Tags & lichte knoppen — Bulma's hardcoded kleuren → tokens
   .tag en .is-light hebben geen donkere variant en ploffen in donker mode om
   als felle lichte chips (of licht-roze knoppen) op een donkere pagina. Ze
   krijgen hier dezelfde achtergrond-tinten als de flash-alerts (sectie 10),
   zodat ze in beide thema's kloppen.
   ===================================================== */
.tag {
  background-color: var(--bg-subtle);
  color: var(--text-secondary);
  border: 1px solid var(--border);
}

/* Bulma zet de .tag-is-* kleuren met !important; die moeten dus ook zo worden
   overschreven — net als de has-text-* helpers hieronder. */
.tag.is-info    { background-color: var(--info-bg) !important;    color: var(--info) !important; }
.tag.is-success { background-color: var(--success-bg) !important; color: var(--success) !important; }
.tag.is-warning { background-color: var(--warning-bg) !important; color: var(--warning) !important; }
.tag.is-danger  { background-color: var(--danger-bg) !important;  color: var(--danger) !important; }

/* Sectie 2b kleurt élke <button> in donker mode als accent-knop; daar moet de
   lichte knopvariant onderdoor. De `:root`-prefix is bewust: zonder die is de
   specificiteit (0,2,0) en verliest het van :root[data-theme='dark'] button
   (0,2,1) — dan wordt de neutrale knop alsnog blauw. */
.button.is-light,
:root .button.is-light {
  background-color: var(--bg-subtle);
  border-color: var(--border-strong);
  color: var(--text-secondary);
}

.button.is-light:hover,
:root .button.is-light:hover {
  background-color: var(--bg-card);
  color: var(--text-primary);
}

.button.is-info.is-light    { background-color: var(--info-bg);    color: var(--info);    border-color: var(--info-border); }
.button.is-success.is-light { background-color: var(--success-bg); color: var(--success); border-color: var(--success-border); }
.button.is-warning.is-light { background-color: var(--warning-bg); color: var(--warning); border-color: var(--warning-border); }
.button.is-danger.is-light  { background-color: var(--danger-bg);  color: var(--danger);  border-color: var(--danger-border); }

/* Bulma's has-text-* helpers zijn hardcoded én !important en volgen het thema
   niet; naar de tekst-tokens zodat ze in beide thema's leesbaar blijven. */
.has-text-grey { color: var(--text-muted) !important; }

