/* ============================================================================
   Nubos · Recruit Enrich — component layer
   Plain CSS (no build needed) layered on top of Tailwind utilities.
   All surfaces/text/borders are driven by CSS vars that flip in `.dark`.
   ============================================================================ */

:root {
  /* Theme-aware tokens — LIGHT */
  --surface:      #F6F8F9;
  --surface-2:    #EEF2F4;
  --card:         #FFFFFF;
  --raised:       #FFFFFF;
  --line:         #E8E8E8;
  --line-strong:  #D7DDE2;
  --fg-1:         #1A1A1A;
  --fg-2:         #555555;
  --fg-3:         #8A93A0;
  --heading:      #00B889;

  /* Accent (tweakable). accent-contrast = readable text on accent fill. */
  --accent:           #00F6B8;
  --accent-contrast:  #06231B;
  --accent-soft:      #E6FDF8;
  --accent-ring:      rgba(0,246,184,0.35);

  /* Density + radius (tweakable) */
  --density-y:   12px;   /* vertical cell/control padding */
  --density-x:   16px;
  --radius:      14px;
  --radius-sm:   8px;

  /* Always-navy sidebar */
  --sb:        #091A2E;
  --sb-fg:     #C8D3E0;
  --sb-muted:  #7E93AC;
  --sb-hover:  rgba(255,255,255,0.05);
  --sb-active: rgba(0,246,184,0.12);
  --sb-border: rgba(255,255,255,0.07);
}

.dark {
  --surface:      #06182B;
  --surface-2:    #0A2138;
  --card:         #0E2744;
  --raised:       #123053;
  --line:         #1C3858;
  --line-strong:  #294B71;
  --fg-1:         #FFFFFF;
  --fg-2:         #C8D3E0;
  --fg-3:         #7E93AC;
  --heading:      #00F6B8;
  --accent-soft:  rgba(0,246,184,0.10);
}

/* Sidebar light variant (tweak) — keeps brand but lifts the rail to white */
.sidebar-light {
  --sb:        #FFFFFF;
  --sb-fg:     #535353;
  --sb-muted:  #8A93A0;
  --sb-hover:  #F2F5F7;
  --sb-active: var(--accent-soft);
  --sb-border: #E8E8E8;
}

* { box-sizing: border-box; }
html { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }
body {
  margin: 0;
  font-family: 'Roboto', system-ui, sans-serif;
  background: var(--surface);
  color: var(--fg-1);
}
::selection { background: var(--accent); color: var(--accent-contrast); }

/* ---------- Density scale ---------- */
.density-compact { --density-y: 8px; --density-x: 12px; }

/* ---------- App shell ---------- */
.app-shell { display: flex; min-height: 100vh; }
.app-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.app-content { padding: 28px 32px 48px; max-width: 1320px; width: 100%; margin: 0 auto; }

/* ---------- Sidebar ---------- */
.sidebar {
  width: 256px; flex-shrink: 0;
  background: var(--sb); color: var(--sb-fg);
  border-right: 1px solid var(--sb-border);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}
.sidebar-brand { display: flex; align-items: center; gap: 10px; padding: 22px 20px 18px; }
.sidebar-brand img { height: 26px; width: auto; }
.sidebar-brand .pname { font-size: 11px; font-weight: 500; letter-spacing: 0.04em; color: var(--accent); }
.sidebar-section { padding: 14px 12px 6px; }
.sidebar-section .lbl { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.12em; color: var(--sb-muted); padding: 0 10px 6px; }
.nav-link {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 10px; margin: 1px 0; border-radius: 10px;
  color: var(--sb-fg); text-decoration: none; font-size: 13.5px; font-weight: 400;
  transition: background .14s, color .14s;
}
.nav-link:hover { background: var(--sb-hover); color: var(--sb-fg); }
.sidebar-light .nav-link:hover { color: var(--fg-1); }
.nav-link.active { background: var(--sb-active); color: var(--accent); font-weight: 500; }
.sidebar-light .nav-link.active { color: var(--nubos-green, #00B889); }
.nav-link svg { width: 17px; height: 17px; stroke-width: 1.75; flex-shrink: 0; }
.nav-link .nl-badge { margin-left: auto; font-size: 10px; font-weight: 700; padding: 1px 7px; border-radius: 999px; background: var(--accent); color: var(--accent-contrast); }
.sidebar-foot { margin-top: auto; border-top: 1px solid var(--sb-border); padding: 12px; display: flex; align-items: center; gap: 10px; }
.sidebar-foot .av { width: 30px; height: 30px; border-radius: 999px; background: var(--accent); color: var(--accent-contrast); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 12px; flex-shrink: 0; }
.sidebar-foot .nm { font-size: 12.5px; color: var(--sb-fg); line-height: 1.3; }
.sidebar-foot .rl { font-size: 11px; color: var(--sb-muted); }

/* ---------- Topbar ---------- */
.topbar {
  height: 64px; flex-shrink: 0;
  background: var(--card); border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 16px; padding: 0 24px;
  position: sticky; top: 0; z-index: 30;
}
.crumbs { font-size: 13px; color: var(--fg-3); display: flex; align-items: center; gap: 8px; }
.crumbs .sep { opacity: .5; }
.crumbs b { color: var(--fg-1); font-weight: 500; }
.topbar-search {
  flex: 1; max-width: 400px; display: flex; align-items: center; gap: 9px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  padding: 8px 13px; color: var(--fg-3); font-size: 13px; cursor: text;
}
.topbar-search svg { width: 16px; height: 16px; stroke-width: 1.75; }
.topbar-search kbd { margin-left: auto; font-family: 'JetBrains Mono', monospace; font-size: 10px; background: var(--card); border: 1px solid var(--line); border-radius: 5px; padding: 1px 5px; color: var(--fg-3); }
.topbar-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: inherit; font-size: 13px; font-weight: 500; line-height: 1;
  padding: 10px 16px; border-radius: var(--radius-sm); border: 1.5px solid transparent;
  cursor: pointer; white-space: nowrap; transition: background .14s, border-color .14s, color .14s; text-decoration: none;
}
.btn svg { width: 15px; height: 15px; stroke-width: 2; }
.btn-primary { background: var(--accent); color: var(--accent-contrast); }
.btn-primary:hover { filter: brightness(1.05); }
/* Hierarchy: one .btn-primary per card, the one thing the card is for. .btn-secondary is the
   quiet neutral next to it (it used to be solid black and competed with the primary for the eye),
   .btn-outline and .btn-ghost are for the rest, and .btn-danger-text is how a destructive action
   (verbreken, verwijderen) looks until the two-step confirmation arms it: confirm-submit.js then
   adds .btn-danger, which is declared after it and so wins. */
.btn-secondary { background: var(--surface-2); color: var(--fg-1); border-color: var(--line); }
.btn-secondary:hover { background: var(--line); border-color: var(--line-strong); }
.btn-danger-text { background: transparent; color: #C53030; }
.btn-danger-text:not(.btn-danger):hover { background: var(--danger-wash, #FFF5F5); }
.dark .btn-danger-text:not(.btn-danger) { color: #FF8A8A; }
.dark .btn-danger-text:not(.btn-danger):hover { background: rgba(229,62,62,0.14); }
.btn-outline { background: transparent; color: var(--fg-1); border-color: var(--line-strong); }
.btn-outline:hover { border-color: var(--fg-1); }
.btn-ghost { background: transparent; color: var(--fg-2); }
.btn-ghost:hover { background: var(--surface-2); color: var(--fg-1); }
.btn-danger { background: var(--danger, #E53E3E); color: #fff; }
.btn-icon { display: inline-flex; align-items: center; justify-content: center; padding: 9px; background: transparent; border: 1px solid var(--line); color: var(--fg-2); border-radius: 10px; cursor: pointer; }
.btn-icon:hover { border-color: var(--accent); color: var(--heading); }
.btn-icon svg { width: 16px; height: 16px; stroke-width: 2; }
.btn-sm { padding: 7px 12px; font-size: 12px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
/* A visible ring for keyboard focus only, on every control that can be tabbed to. A mouse click
   does not draw it, a Tab always does. On a light surface the ring is dark, because the mint
   accent on white is about 1.4:1 and all but invisible; the 2px gap between control and ring is
   filled with the card colour so a green button does not melt into it. On dark surfaces (dark
   mode, the navy sidebar) the accent has the contrast and stays. */
.btn:focus-visible, .btn-icon:focus-visible, .nav-link:focus-visible, .tab:focus-visible,
.stat-link:focus-visible, details.disclosure > summary:focus-visible, .menu-btn:focus-visible,
.topbar-mark:focus-visible, .sidebar-brand:focus-visible {
  outline: 2px solid var(--fg-1); outline-offset: 2px; box-shadow: 0 0 0 2px var(--card);
}
.dark .btn:focus-visible, .dark .btn-icon:focus-visible, .dark .tab:focus-visible,
.dark .stat-link:focus-visible, .dark details.disclosure > summary:focus-visible,
.dark .menu-btn:focus-visible, .dark .topbar-mark:focus-visible { outline-color: var(--accent); }
.sidebar .nav-link:focus-visible, .sidebar .btn-icon:focus-visible, .sidebar .sidebar-brand:focus-visible {
  outline-color: var(--accent); box-shadow: 0 0 0 2px var(--sb);
}
.sidebar-light .nav-link:focus-visible, .sidebar-light .btn-icon:focus-visible, .sidebar-light .sidebar-brand:focus-visible { outline-color: var(--fg-1); }

/* WhatsApp-stijl gesprek (profiel-detail) */
.chat { display: flex; flex-direction: column; gap: 8px; background: #e5ddd5; border-radius: var(--radius-md); padding: 16px; max-height: 540px; overflow-y: auto; }
.dark .chat { background: #0b141a; }
.chat-row { display: flex; }
.chat-row.out { justify-content: flex-end; }
.chat-row.sys { justify-content: center; }
.chat-bubble { max-width: 78%; padding: 7px 10px 5px; border-radius: 8px; font-size: 13.5px; line-height: 1.45; color: #111b21; white-space: pre-wrap; word-wrap: break-word; box-shadow: 0 1px .5px rgba(0,0,0,.13); }
.chat-row.in .chat-bubble { background: #fff; border-top-left-radius: 2px; }
.chat-row.out .chat-bubble { background: #d9fdd3; border-top-right-radius: 2px; }
.dark .chat-row.in .chat-bubble { background: #202c33; color: #e9edef; }
.dark .chat-row.out .chat-bubble { background: #005c4b; color: #e9edef; }
.chat-time { display: block; text-align: right; font-size: 10.5px; color: #667781; margin-top: 3px; }
.dark .chat-time { color: #8696a0; }
.chat-sys-note { background: rgba(0,0,0,.06); color: #54656f; font-size: 11.5px; padding: 4px 10px; border-radius: 8px; text-align: center; }
.dark .chat-sys-note { background: rgba(255,255,255,.08); color: #8696a0; }

/* ---------- Cards ---------- */
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); }
.card-p { padding: 22px; }
.card-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; padding: 18px 22px; border-bottom: 1px solid var(--line); }
.card-head h3 { margin: 0; font-size: 15px; font-weight: 700; color: var(--fg-1); }
.card-head .sub { font-size: 12px; color: var(--fg-3); margin-top: 2px; }

/* ---------- Eyebrow / headings ---------- */
.eyebrow { font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.14em; color: var(--heading); }
.page-title { font-size: 24px; font-weight: 700; letter-spacing: -0.015em; color: var(--fg-1); margin: 4px 0 0; }
.page-lead { font-size: 14px; color: var(--fg-2); margin: 6px 0 0; }

/* ---------- KPI ---------- */
.kpi { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 20px; }
.kpi .kl { font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-3); display: flex; align-items: center; gap: 8px; }
.kpi .kl svg { width: 15px; height: 15px; stroke-width: 1.75; color: var(--heading); }
.kpi .kv { font-size: 30px; font-weight: 700; letter-spacing: -0.02em; color: var(--fg-1); line-height: 1; margin-top: 14px; font-variant-numeric: tabular-nums; }
.kpi .kd { font-size: 12px; margin-top: 10px; display: inline-flex; align-items: center; gap: 5px; }
.kpi .kd.up { color: #00B889; }
.kpi .kd.down { color: #E53E3E; }
.kpi .kd svg { width: 13px; height: 13px; stroke-width: 2.5; }

/* ---------- Chips / badges ---------- */
.chip { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border-radius: 999px; font-size: 11px; font-weight: 500; line-height: 1.4; }
.chip .dot { width: 6px; height: 6px; border-radius: 999px; background: currentColor; }
.chip svg { width: 12px; height: 12px; stroke-width: 2.25; flex-shrink: 0; }
.chip-success { background: var(--accent-soft); color: var(--heading); }
.chip-neutral { background: var(--surface-2); color: var(--fg-2); }
.chip-warn    { background: #FFF6D6; color: #8A6D00; }
.dark .chip-warn { background: rgba(255,226,67,0.14); color: #FFE243; }
.chip-danger  { background: var(--danger-wash, #FFF5F5); color: #E53E3E; }
.dark .chip-danger { background: rgba(229,62,62,0.14); color: #FF8A8A; }
.chip-info    { background: #ECF3FF; color: #3B6DB7; }
.dark .chip-info { background: rgba(128,184,255,0.14); color: #A5D7FB; }
/* The demo account's marker next to its name: a dashed outline and no fill, the one chip in the
   product that looks unfinished on purpose. In the sidebar it takes the sidebar's quiet colour and
   keeps its own case inside the upper-case label. */
.chip-demo { background: transparent; color: var(--fg-2); border: 1px dashed var(--line-strong); padding: 1px 8px; margin-left: 8px; vertical-align: 2px; cursor: help; }
.sidebar .chip-demo { color: var(--sb-muted); border-color: var(--sb-muted); font-size: 10px; letter-spacing: 0.04em; text-transform: none; padding: 0 7px; margin-left: 6px; vertical-align: 1px; }
.page-title .chip-demo { font-size: 12px; vertical-align: 4px; }

/* ---------- Forms ---------- */
.label { display: block; font-size: 12.5px; font-weight: 500; color: var(--fg-1); margin-bottom: 7px; }
.label .req { color: #E53E3E; }
.hint { font-size: 11.5px; color: var(--fg-3); margin-top: 6px; }
/* This file loads after the Tailwind build, so .hint's grey beats the text-danger utility on
   the same element. An error sentence styled as a hint has to stay red. */
.hint.text-danger { color: var(--nubos-danger, #E53E3E); }
.input, .select, .textarea {
  width: 100%; font-family: inherit; font-size: 13.5px; color: var(--fg-1);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: var(--density-y) var(--density-x); outline: none; transition: border-color .14s, box-shadow .14s;
}
.input::placeholder, .textarea::placeholder { color: var(--fg-3); }
.input:focus, .select:focus, .textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }
.select-sm { width: auto; font-size: 12.5px; padding: 5px 26px 5px 9px; }
.input-group { display: flex; align-items: stretch; }
.input-group .addon { display: flex; align-items: center; padding: 0 12px; background: var(--surface-2); border: 1px solid var(--line); color: var(--fg-3); font-size: 13px; }
.input-group .addon:first-child { border-right: 0; border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.input-group .input { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
/* A colour field is a swatch, not a text field: the browser draws a small box with a lot of
   chrome around it, so it gets the height of the fields next to it and room for the colour
   itself. The rule lives here and not as utility classes on the form type, because Tailwind only
   scans the templates and would never generate classes named in PHP. */
.input[type="color"] { height: 40px; padding: 4px; cursor: pointer; }
/* A file field: the browser's own button drawn as a quiet secondary button inside the field. */
.input[type="file"] { padding: 7px; cursor: pointer; color: var(--fg-2); }
.input[type="file"]::file-selector-button {
  margin-right: 12px; padding: 6px 12px; border: 1px solid var(--line); border-radius: 7px;
  background: var(--surface-2); color: var(--fg-1); font: inherit; font-size: 12.5px; font-weight: 500; cursor: pointer;
}
.field-error .input, .field-error .select { border-color: #E53E3E; }
.field-error .msg { font-size: 11.5px; color: #E53E3E; margin-top: 6px; display: flex; align-items: center; gap: 5px; }
.field-error .msg svg { width: 13px; height: 13px; }

/* Toggle */
.switch { position: relative; display: inline-flex; width: 40px; height: 22px; flex-shrink: 0; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .track { position: absolute; inset: 0; background: var(--line-strong); border-radius: 999px; transition: background .16s; cursor: pointer; }
.switch .track::before { content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; background: #fff; border-radius: 999px; transition: transform .16s; }
.switch input:checked + .track { background: var(--accent); }
.switch input:checked + .track::before { transform: translateX(18px); }

/* Segmented control */
.segmented { display: inline-flex; background: var(--surface-2); border: 1px solid var(--line); border-radius: 10px; padding: 3px; gap: 2px; }
.segmented button { border: 0; background: transparent; color: var(--fg-2); font-family: inherit; font-size: 12.5px; font-weight: 500; padding: 6px 14px; border-radius: 7px; cursor: pointer; }
.segmented button.active { background: var(--card); color: var(--fg-1); }

/* ---------- Tabs ---------- */
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); }
.tab { padding: 11px 16px; font-size: 13.5px; font-weight: 500; color: var(--fg-3); text-decoration: none; border-bottom: 2px solid transparent; margin-bottom: -1px; cursor: pointer; }
.tab:hover { color: var(--fg-1); }
.tab.active { color: var(--fg-1); border-bottom-color: var(--accent); }
/* Tabs met een actie ernaast (bv. de kolomkiezer); de onderlijn loopt door onder beide. */
.tabs-bar { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; padding: 6px 22px 0; border-bottom: 1px solid var(--line); }
.tabs-bar .tabs { border-bottom: 0; flex: 1; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.tabs-bar .tabs::-webkit-scrollbar { display: none; }

/* ---------- Kolomkiezer ---------- */
.colpick { position: relative; margin-bottom: 8px; }
.colpick > summary { list-style: none; user-select: none; }
.colpick > summary::-webkit-details-marker { display: none; }
.colpick-panel { position: absolute; right: 0; top: calc(100% + 8px); z-index: 30; width: 300px; max-height: 70vh; overflow-y: auto; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-md); box-shadow: 0 12px 32px rgba(0,0,0,.12); padding: 14px; }
.colpick-hint { font-size: 11.5px; line-height: 1.5; color: var(--fg-3); margin: 0 0 10px; }
.colpick-list { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; }
.colpick-list li { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 5px 0; }
.colpick-list label { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--fg-1); cursor: pointer; min-width: 0; }
.colpick-fixed { font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: var(--fg-3); }
.colpick-move { display: flex; gap: 4px; flex-shrink: 0; }
.colpick-move .btn-icon { padding: 4px; border-radius: 7px; }
.colpick-move .btn-icon svg { width: 13px; height: 13px; }
.colpick-actions { display: flex; gap: 8px; border-top: 1px solid var(--line); padding-top: 12px; }

/* ---------- Table ---------- */
/* A table in a card cannot be narrower than its widest column, so on a phone it pushes the whole
   page wider and scrolls the navigation out of reach. Inside this wrapper only the table itself
   scrolls. Every `.tbl` belongs in one. */
/* position: relative so a .sr-only label inside a cell is placed within the scroller; without it
   the label is positioned against the page and widens the page by the width of the table. */
.tbl-wrap { position: relative; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.tbl thead th { text-align: left; font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.07em; color: var(--fg-3); padding: 11px var(--density-x); border-bottom: 1px solid var(--line); white-space: nowrap; }
.tbl tbody td { padding: var(--density-y) var(--density-x); border-bottom: 1px solid var(--line); color: var(--fg-2); vertical-align: middle; }
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr { transition: background .12s; }
.tbl tbody tr:hover { background: var(--surface-2); }
.tbl .t-name { font-weight: 500; color: var(--fg-1); }
.tbl .t-sub { font-size: 11.5px; color: var(--fg-3); }
.tbl .num { font-variant-numeric: tabular-nums; }
.row-check { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }
/* Alleen voor schermlezers: label van een kolom zonder zichtbare kop. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* `.tbl thead th` zet text-align hard op left en overrulet daarmee de utility-class, waardoor
   een rechts uitgelijnde kolom een links uitgelijnde kop kreeg. */
.tbl thead th.text-right { text-align: right; }
/* Rij-actie (archiveren e.d.): smalle kolom die niet met de inhoud meegroeit. */
.tbl th.row-act, .tbl td.row-act { width: 1%; white-space: nowrap; padding-left: 0; }
.tbl td.row-act .btn-icon { padding: 6px; border-radius: 8px; }
.tbl td.row-act .btn-icon svg { width: 15px; height: 15px; }
/* The buttons of one row on one line. In a cell that is 1% wide a wrapping flex row shrinks to
   its narrowest word and stacks every button; only a phone may wrap them. */
.row-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
@media (max-width: 639px) { .row-actions { flex-wrap: wrap; } }
/* On a phone a row with three buttons does not fit next to the content, so the action cell may
   wrap there rather than make the table wider still. */
@media (max-width: 639px) {
  .tbl th.row-act, .tbl td.row-act { white-space: normal; }
}

/* Avatar */
.avatar { width: 32px; height: 32px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; flex-shrink: 0; }
.av-green { background: var(--accent-soft); color: var(--heading); }
.av-blue  { background: #ECF3FF; color: #3B6DB7; }
.av-peach { background: #FFF1E6; color: #CA6B28; }
.av-pink  { background: #FFECF5; color: #C44E8E; }
.dark .av-blue { background: rgba(128,184,255,.14); color: #A5D7FB; }
.dark .av-peach { background: rgba(255,176,135,.14); color: #FFB087; }
.dark .av-pink { background: rgba(251,153,204,.14); color: #FB99CC; }


/* ---------- Funnel and sparkline (Resultaten) ---------- */
/* Reactions are blue on every screen, so the funnel is the blue tone in deepening steps for the
   path that goes somewhere, and grey for the one that ended. No second hue: five colours next to
   each other read as five categories, and these are five stations on one road. The steps are
   mixed with the card colour, so they stay steps in dark mode too. A hairline of card between
   two segments keeps them apart like the meter's; the track shows what has no place, the
   reactions closed with their vacancy. The widths are inline because a share is computed per
   render. */
.funnel { display: flex; height: 14px; border-radius: 999px; overflow: hidden; background: var(--surface-2); }
.funnel > span { display: block; height: 100%; min-width: 3px; }
.funnel > span + span { box-shadow: inset 2px 0 0 var(--card); }
.funnel .good-1, .funnel-legend .good-1 .sw { background: color-mix(in srgb, var(--tone-strong) 28%, var(--card)); }
.funnel .good-2, .funnel-legend .good-2 .sw { background: color-mix(in srgb, var(--tone-strong) 52%, var(--card)); }
.funnel .good-3, .funnel-legend .good-3 .sw { background: color-mix(in srgb, var(--tone-strong) 76%, var(--card)); }
.funnel .good-4, .funnel-legend .good-4 .sw { background: var(--tone-strong); }
.funnel .ended,  .funnel-legend .ended .sw  { background: var(--line-strong); }
.funnel-legend { display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 14px 0 0; padding: 0; }
.funnel-legend li { display: flex; align-items: baseline; gap: 7px; font-size: 12.5px; color: var(--fg-2); list-style: none; }
.funnel-legend .sw { width: 10px; height: 10px; border-radius: 3px; flex: none; align-self: center; }
.funnel-legend .n { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--fg-1); }
.funnel-legend .pct { font-variant-numeric: tabular-nums; color: var(--fg-3); }
/* Reactions per day, small enough to sit in a table cell and never a chart with axes: it says
   "busy at the start" or "nothing after the third day", which is all a row has space for. Blue,
   because it counts reactions. */
.spark { display: block; width: 72px; height: 22px; overflow: visible; }
.spark polyline { fill: none; stroke: var(--tone-strong, var(--accent)); stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.spark .flat { stroke: var(--line-strong); }

/* ---------- Resultaten ---------- */
/* The big figure first and the four around it after: on a phone the hero on top and the stats
   under it, from a width that fits them side by side the hero on the left and the stats in two
   columns next to it. Container queries, because the sidebar takes a different share of the
   window at every size. */
.results-kpis { container-type: inline-size; }
.results-kpis-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.results-stats { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
@container (min-width: 520px) { .results-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@container (min-width: 700px) { .results-kpis-grid { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); } }
/* The table's own touches: channel icons after a name, and a thin bar under a count that says
   what share of the reactions it is. */
.results-tbl .t-name .channels, .results-page .channels { margin-left: 6px; }
.results-tbl .results-name { min-width: 150px; }
/* A page name and its channel icons are one thing and wrap as one. */
.results-page { white-space: nowrap; }
.results-share { display: inline-flex; flex-direction: column; align-items: flex-end; gap: 5px; }
.results-share .progress { width: 48px; }
.results-tbl .flag { margin-top: 5px; }
/* Thirteen columns have to fit next to the sidebar on a laptop. Tighter cells, and headings that
   may break over two lines ("Per bruikbare / kandidaat"), are what buys the room: a heading on
   one line was wider than every figure under it. The arrow of the active sort stays with its
   word. On a phone the card still scrolls sideways inside .tbl-wrap. */
.results-tbl { --density-x: 7px; }
/* Only between cells: the first and the last keep the card's own inset, or the names and the
   sparklines hug the edge of the card. */
.results-tbl th:first-child, .results-tbl td:first-child { padding-left: 16px; }
.results-tbl th:last-child, .results-tbl td:last-child { padding-right: 16px; }
.results-tbl thead th { white-space: normal; vertical-align: bottom; line-height: 1.35; letter-spacing: 0; }
.results-tbl thead th a { display: inline-block; }
/* A figure never breaks, or "€ 149,57" puts its euro sign on a line of its own. */
.results-tbl tbody td.num { white-space: nowrap; }
.results-tbl .results-th-sep { margin: 0 2px; }
/* The benchmark line under a vacancy belongs to that row: no border between the two, a tighter
   gap, and one hover over both whichever of the two the pointer is on. */
.results-tbl tbody tr.has-benchmark td { border-bottom: 0; }
.results-tbl tbody tr.results-benchmark td { padding-top: 0; font-size: 11.5px; color: var(--fg-3); }
/* On a phone the table scrolls sideways and this cell is as wide as the whole table, so the
   sentence would run off screen. It stays in the visible part of the card instead: pinned to its
   left edge and no wider than the card, which the wrapper measures as a container. */
.results-tbl-wrap { container-type: inline-size; }
.results-benchmark-text { position: sticky; left: 16px; max-width: calc(100cqw - 32px); }
.results-tbl tbody tr.has-benchmark:hover + tr.results-benchmark,
.results-tbl tbody tr.has-benchmark:has(+ tr.results-benchmark:hover) { background: var(--surface-2); }

/* Dropdown / popover */
.popover { background: var(--raised); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--pop, 0 8px 28px -8px rgba(9,26,46,0.22)); padding: 6px; min-width: 180px; }
.popover a, .popover button { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; padding: 8px 10px; border-radius: 8px; font-size: 13px; color: var(--fg-2); background: transparent; border: 0; cursor: pointer; font-family: inherit; text-decoration: none; }
.popover a:hover, .popover button:hover { background: var(--surface-2); color: var(--fg-1); }
.popover svg { width: 15px; height: 15px; stroke-width: 1.75; }
.popover .sep { height: 1px; background: var(--line); margin: 5px 0; }

/* Code */
code, .mono { font-family: 'JetBrains Mono', monospace; }
.code-chip { font-family: 'JetBrains Mono', monospace; font-size: 12px; background: var(--accent-soft); color: var(--heading); padding: 2px 7px; border-radius: 6px; word-break: break-all; min-width: 0; max-width: 70%; text-align: left; }

/* Misc */
.divider { height: 1px; background: var(--line); border: 0; margin: 0; }
.skeleton { background: linear-gradient(90deg, var(--surface-2) 25%, var(--line) 37%, var(--surface-2) 63%); background-size: 400% 100%; animation: sk 1.4s ease infinite; border-radius: 6px; }
@keyframes sk { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }

/* Theme toggle button */
.theme-toggle .moon { display: none; }
.dark .theme-toggle .sun { display: none; }
.dark .theme-toggle .moon { display: block; }

/* Tweaks FAB + panel */
.tweaks-fab { position: fixed; right: 20px; bottom: 20px; z-index: 60; width: 46px; height: 46px; border-radius: 999px; background: var(--nubos-navy, #091A2E); color: var(--accent); border: 1px solid var(--sb-border); display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 8px 28px -8px rgba(9,26,46,0.4); }
.tweaks-fab svg { width: 20px; height: 20px; }
.tweaks-panel { position: fixed; right: 20px; bottom: 78px; z-index: 60; width: 280px; background: var(--raised); border: 1px solid var(--line); border-radius: 16px; box-shadow: 0 16px 48px -12px rgba(9,26,46,0.3); padding: 16px; display: none; }
.tweaks-panel.open { display: block; animation: fade-up .2s cubic-bezier(.2,.6,.2,1) both; }
@keyframes fade-up { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
.tweaks-panel h4 { margin: 0 0 2px; font-size: 13px; font-weight: 700; color: var(--fg-1); }
.tweaks-panel .tw-sub { font-size: 11px; color: var(--fg-3); margin-bottom: 14px; }
.tw-row { margin-bottom: 14px; }
.tw-row .tw-lbl { font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.07em; color: var(--fg-3); margin-bottom: 7px; }
.tw-swatches { display: flex; gap: 8px; }
.tw-swatch { width: 28px; height: 28px; border-radius: 8px; cursor: pointer; border: 2px solid transparent; }
.tw-swatch.sel { border-color: var(--fg-1); }

/* ---------- Updates (changelog) ---------- */
/* Meldingsbalk boven de topbar: rustig, wegklikbaar, nooit een venster over het werk heen. */
.whatsnew {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 24px; background: var(--accent-soft); color: var(--heading);
  border-bottom: 1px solid var(--line); font-size: 13px;
}
.whatsnew svg { width: 17px; height: 17px; stroke-width: 1.75; flex-shrink: 0; }
.whatsnew a { color: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.whatsnew .wn-close { margin-left: auto; background: transparent; border: 0; color: inherit; opacity: .55; cursor: pointer; font-family: inherit; padding: 4px; line-height: 1; }
.whatsnew .wn-close:hover { opacity: 1; }


.segmented a { display: inline-flex; align-items: center; gap: 6px; color: var(--fg-2); text-decoration: none; font-size: 12.5px; font-weight: 500; padding: 6px 14px; border-radius: 7px; }
.segmented a.active { background: var(--card); color: var(--fg-1); }
.segmented .cl-count { font-size: 10.5px; color: var(--fg-3); }

.cl-day { margin-bottom: 26px; }
.cl-date { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-3); margin: 0 0 10px 2px; }
.cl-item { padding: 20px 22px; }
.cl-item + .cl-item { border-top: 1px solid var(--line); }
.cl-item-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.cl-title { margin: 0; font-size: 15px; font-weight: 600; color: var(--fg-1); }
.cl-new { font-size: 10.5px; font-weight: 600; color: var(--accent); text-transform: uppercase; letter-spacing: 0.06em; }
.cl-body { margin: 0 0 8px; font-size: 13.5px; line-height: 1.65; color: var(--fg-2); max-width: 68ch; }
.cl-body:last-child { margin-bottom: 0; }
.cl-divider { display: flex; align-items: center; gap: 12px; margin: 4px 0 26px; color: var(--fg-3); font-size: 11.5px; }
.cl-divider::before, .cl-divider::after { content: ''; height: 1px; background: var(--line); flex: 1; }
.cl-pager { display: flex; gap: 10px; justify-content: center; padding: 8px 0 24px; }

/* Onboarding: a choice that reads as a card, and a row that pairs a check with its explanation.
   --wash and --cta do not exist in this design system, so the nearest defined variables are used:
   --accent-soft for the tinted surface of a selected card, --heading for the summary link. */
.radio-card { display: flex; gap: 10px; align-items: flex-start; padding: 12px; border: 1px solid var(--line); border-radius: 8px; margin-bottom: 8px; cursor: pointer; }
.radio-card.is-selected { border-color: var(--accent); background: var(--accent-soft); }
.radio-card .hint { display: block; }
.check-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 12px; }
/* Two single-button forms that read as one row of buttons. Separate forms because they post to
   different routes, and a form cannot be nested inside another. */
.form-inline { display: inline-block; }
.form-inline + .form-inline { margin-left: 8px; }
.check-row details { flex-basis: 100%; }
.check-row summary { cursor: pointer; color: var(--heading); }

/* The vertical stepper of the Nubos customer detail page. The wizard itself uses .steps (see
   "Steps as links" below). Same substitutions as the rules above: --accent-soft for the tinted
   surface, and the --danger fallback the buttons already use. */
.stepper { display: flex; flex-direction: column; gap: 4px; width: 230px; flex: none; }
.stepper-item { display: flex; gap: 10px; align-items: flex-start; padding: 8px 10px; border-radius: 6px; text-decoration: none; color: inherit; }
.stepper-item.is-current { background: var(--accent-soft); font-weight: 600; }
.stepper-mark { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; flex: none; border-radius: 50%; border: 1px solid var(--line); font-size: 12px; }
.stepper-mark svg { width: 13px; height: 13px; }
.stepper-item.is-done .stepper-mark { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }
.stepper-item.is-stalled .stepper-mark { border-color: var(--danger, #E53E3E); color: var(--danger, #E53E3E); }
.stepper-item.is-stalled .hint { color: var(--danger, #E53E3E); }
@media (max-width: 720px) { .stepper { width: 100%; } }

/* Nubos customer list: the problem chips under a customer's name, and the stepper on the detail
   page, which is the whole width of its card there instead of a column next to the content. */
.chip-row { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.stepper.stepper-wide { width: 100%; }

/* An amount that is not the whole story: a row in which one advertisement has not been read back
   yet. The hint class has to be said again, because the table sets its own colour on every cell
   and that is more specific than .hint on its own. */
.tbl tbody td.hint { color: var(--fg-3); }

/* ---------- Help ---------- */
.help-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 24px; align-items: start; }
@media (max-width: 960px) { .help-layout { grid-template-columns: minmax(0, 1fr); } }
.help-aside { display: flex; flex-direction: column; gap: 16px; }
.help-aside-title { margin: 0 0 10px; font-size: 13px; font-weight: 700; color: var(--fg-1); }
.help-aside-text { margin: 0 0 12px; font-size: 13px; line-height: 1.6; color: var(--fg-2); }
.help-aside-text:last-child { margin-bottom: 0; }
.help-aside-text a, .help-aside-list a, .help-back a { color: var(--heading); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.help-aside-list { margin: 0 0 14px; padding: 0; list-style: none; font-size: 13px; line-height: 1.5; display: flex; flex-direction: column; gap: 8px; }
.help-aside-list:last-child { margin-bottom: 0; }
.help-aside-list b { color: var(--fg-1); font-weight: 600; }
.help-section { margin-bottom: 26px; }
.help-row { display: block; padding: 16px 22px; text-decoration: none; transition: background .12s; }
.help-row + .help-row { border-top: 1px solid var(--line); }
.help-row:hover { background: var(--surface-2); }
.help-row-title { display: block; font-size: 14.5px; font-weight: 600; color: var(--fg-1); }
.help-row-sub { display: block; margin-top: 3px; font-size: 13px; line-height: 1.55; color: var(--fg-2); }
.help-back { margin: 16px 2px 0; font-size: 13px; }
.help-prose { font-size: 14px; line-height: 1.7; color: var(--fg-2); max-width: 76ch; }
.help-prose > :first-child { margin-top: 0; }
.help-prose > :last-child { margin-bottom: 0; }
.help-prose p, .help-prose ul, .help-prose ol { margin: 0 0 14px; }
.help-prose h2 { margin: 26px 0 8px; font-size: 16px; font-weight: 700; color: var(--fg-1); }
.help-prose h3 { margin: 20px 0 6px; font-size: 14.5px; font-weight: 600; color: var(--fg-1); }
.help-prose ul, .help-prose ol { padding-left: 22px; }
.help-prose ul { list-style: disc; }
.help-prose ol { list-style: decimal; }
.help-prose li + li { margin-top: 4px; }
.help-prose strong { color: var(--fg-1); font-weight: 600; }
.help-prose a { color: var(--heading); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }

/* ============================================================================
   Building blocks. The macros are in templates/admin/_ui.html.twig; what each one is for is
   written at the top of that file. The rules here are the whole look, so a screen that uses a
   macro never needs a class of its own to make it right.
   ============================================================================ */

/* ---------- Tones ---------- */
/* Colour carries meaning, and the same meaning on every screen: green is vacancies and ads, blue
   reactions, yellow budget and money, peach "let op", sky channels and connections, pink the
   team. --tone is the pastel of the icon tile; --tone-strong is the same hue dark enough to be a
   bar on a white card, because the pastels themselves (yellow above all) all but disappear
   against the grey track. In dark mode the pastel is strong enough on its own. */
.tone-green   { --tone: var(--nubos-icon-green, #57ECBE);  --tone-strong: #00C494; }
.tone-blue    { --tone: var(--nubos-icon-blue, #A5D7FB);   --tone-strong: #4A9BE8; }
.tone-yellow  { --tone: var(--nubos-icon-yellow, #FFF16A); --tone-strong: #F2C200; }
.tone-peach   { --tone: var(--nubos-icon-peach, #FFB087);  --tone-strong: #F47B3C; }
.tone-sky     { --tone: var(--nubos-icon-sky, #9FC3FF);    --tone-strong: #5B8FEF; }
.tone-pink    { --tone: var(--nubos-icon-pink, #FB99CC);   --tone-strong: #E7609F; }
.tone-danger  { --tone: #FFC9C9;                           --tone-strong: #E53E3E; }
.tone-neutral { --tone: var(--surface-2);                  --tone-strong: var(--line); }
.dark .tone-green   { --tone-strong: var(--tone); }
.dark .tone-blue    { --tone-strong: var(--tone); }
.dark .tone-yellow  { --tone-strong: var(--tone); }
.dark .tone-peach   { --tone-strong: var(--tone); }
.dark .tone-sky     { --tone-strong: var(--tone); }
.dark .tone-pink    { --tone-strong: var(--tone); }
.dark .tone-danger  { --tone: #FF8A8A; --tone-strong: #FF6B6B; }

/* ---------- Tile ---------- */
.tile {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 40px; height: 40px; border-radius: 12px;
  background: var(--tone, var(--surface-2)); color: var(--nubos-navy, #091A2E);
}
.tile svg { width: 20px; height: 20px; stroke-width: 1.75; }
.tile-sm { width: 32px; height: 32px; border-radius: 10px; }
.tile-sm svg { width: 16px; height: 16px; }
.tile-lg { width: 48px; height: 48px; border-radius: 14px; }
.tile-lg svg { width: 24px; height: 24px; }
.tile.tone-neutral { color: var(--fg-2); }
.dark .tile { background: color-mix(in srgb, var(--tone) 16%, transparent); color: var(--tone); }
.dark .tile.tone-neutral { background: var(--surface-2); color: var(--fg-2); }

/* ---------- Card head with a tile ---------- */
.card-head-main { display: flex; align-items: center; gap: 12px; min-width: 0; }
.card-head-main > div { min-width: 0; }
.card-head-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }

/* ---------- Empty state ---------- */
.empty { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 44px 24px; }
.empty-title { margin: 16px 0 0; font-size: 15px; font-weight: 700; color: var(--fg-1); }
.empty-text { margin: 6px 0 0; max-width: 46ch; font-size: 13.5px; line-height: 1.6; color: var(--fg-2); }
.empty .btn { margin-top: 18px; }

/* ---------- Stat ---------- */
/* Not .kpi: that one is the big tile of the Nubos screens, with an all-caps label.
   A stat is the small one that sits above a table and reads as a sentence. The row answers to
   the width it gets and not to the window, because the sidebar takes a different share of the
   window at every size. */
.stat-row { container-type: inline-size; }
.stat-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
@container (min-width: 560px) { .stat-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.stat {
  display: flex; align-items: center; gap: 14px; min-width: 0;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px 16px; color: inherit; text-decoration: none;
}
.stat-body { min-width: 0; }
.stat-label, .stat-value, .stat-hint { display: block; }
.stat-label { font-size: 12.5px; color: var(--fg-2); line-height: 1.3; }
.stat-value { font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--fg-1); line-height: 1.2; margin-top: 2px; font-variant-numeric: tabular-nums; }
.stat-hint { font-size: 11.5px; color: var(--fg-3); margin-top: 2px; }
a.stat-link { transition: border-color .14s; }
a.stat-link:hover { border-color: var(--line-strong); }

/* ---------- Hero stat ---------- */
/* The one figure a screen exists for. The same frame as a stat with a wash of its tone running
   into the card, the value twice the size, and a pill for the change against the period before
   it, in the tone of the judgement and not of the direction. */
.stat-hero {
  display: flex; flex-direction: column; align-items: flex-start; min-width: 0;
  padding: 20px 22px 22px; border-radius: var(--radius);
  border: 1px solid color-mix(in srgb, var(--tone-strong) 45%, var(--line));
  background: linear-gradient(135deg, color-mix(in srgb, var(--tone) 38%, var(--card)) 0%, var(--card) 75%);
}
.dark .stat-hero { background: linear-gradient(135deg, color-mix(in srgb, var(--tone) 14%, var(--card)) 0%, var(--card) 75%); }
.stat-hero-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.stat-hero-label { font-size: 14px; font-weight: 600; color: var(--fg-1); line-height: 1.3; }
.stat-hero-value { display: block; margin-top: 18px; font-size: 40px; font-weight: 700; letter-spacing: -0.03em; line-height: 1; color: var(--fg-1); font-variant-numeric: tabular-nums; }
@media (min-width: 640px) { .stat-hero-value { font-size: 48px; } }
.stat-hero-hint { display: block; margin-top: 10px; max-width: 42ch; font-size: 12.5px; line-height: 1.5; color: var(--fg-2); }
.stat-hero-change {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 16px;
  padding: 4px 10px; border-radius: 999px; font-size: 12.5px; font-weight: 600; line-height: 1.4;
  background: color-mix(in srgb, var(--tone) 45%, var(--card)); color: var(--nubos-navy, #091A2E);
}
.stat-hero-change svg { width: 13px; height: 13px; stroke-width: 2.25; flex: none; }
.dark .stat-hero-change { background: color-mix(in srgb, var(--tone) 18%, transparent); color: var(--tone); }
.dark .stat-hero-change.tone-neutral { color: var(--fg-2); }

/* ---------- Toolbar ---------- */
/* A row of filters and their button, for a toolbar next to a page title or above a list. On a
   phone every field gets its own line and the controls the full width, so nothing is squeezed. */
.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.toolbar-field { display: flex; align-items: center; gap: 8px; min-width: 0; }
.toolbar-field .label { margin: 0; white-space: nowrap; }
/* In the page header the toolbar sits in .page-actions, which is only as wide as its content;
   on a phone it takes the whole line, so a long page name shortens its select instead of
   pushing the page sideways. */
.page-actions { min-width: 0; max-width: 100%; }
@media (max-width: 639px) {
  .page-actions:has(> .toolbar) { width: 100%; }
  .toolbar { flex-direction: column; align-items: stretch; }
  .toolbar-field { justify-content: space-between; }
  .toolbar-field .select { flex: 1; min-width: 0; max-width: 75%; }
}

/* ---------- Picker ---------- */
/* The searchable choice of _ui.picker(): a text field with a search icon, a clear button and a
   list of at most twenty choices below it, each a label with one grey line under it. */
.picker { position: relative; min-width: 0; }
.picker-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); display: inline-flex; color: var(--fg-3); pointer-events: none; }
.picker-icon svg { width: 15px; height: 15px; stroke-width: 1.75; }
.picker-input { padding-left: 32px; padding-right: 30px; }
.picker-clear { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); display: inline-flex; padding: 4px; border: 0; border-radius: 6px; background: transparent; color: var(--fg-3); cursor: pointer; }
.picker-clear:hover { color: var(--fg-1); background: var(--surface-2); }
.picker-clear:focus-visible { outline: 2px solid var(--fg-1); outline-offset: 1px; }
.picker-clear svg { width: 13px; height: 13px; stroke-width: 2; }
.picker-clear[hidden] { display: none; }
.picker-list {
  position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 40; min-width: 260px;
  max-height: 320px; overflow-y: auto; margin: 0; padding: 6px; list-style: none;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-md);
  box-shadow: 0 12px 32px rgba(9,26,46,.14);
}
.picker-list[hidden] { display: none; }
.picker-option { display: flex; flex-direction: column; gap: 1px; padding: 8px 10px; border-radius: 8px; cursor: pointer; }
.picker-option.is-active { background: var(--accent-soft); }
.picker-label { font-size: 13px; font-weight: 500; color: var(--fg-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker-detail { font-size: 11.5px; color: var(--fg-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker-empty { padding: 10px; font-size: 12.5px; color: var(--fg-3); }
/* The chosen option carries a check on the right, so the short list on focus shows where you are. */
.picker-option.is-chosen { position: relative; padding-right: 30px; }
.picker-option.is-chosen::after {
  content: ''; position: absolute; right: 13px; top: 50%; width: 5px; height: 10px; margin-top: -6px;
  border: solid var(--heading); border-width: 0 2px 2px 0; transform: rotate(45deg);
}
/* A group of the list (the ad pages: the default and recent ones, then the rest) under a small
   heading in the style of the table heads; the line above it only between groups. */
.picker-group { margin: 0; padding: 0; list-style: none; }
.picker-heading { padding: 8px 10px 4px; font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.07em; color: var(--fg-3); cursor: default; }
li + li > .picker-group { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--line); }
.picker-more { margin-top: 4px; padding: 9px 10px 5px; border-top: 1px solid var(--line); font-size: 12px; color: var(--fg-3); cursor: default; }

/* ---------- Filter chips ---------- */
/* The chips above a list that say which part of it is shown, each with its count: links, so the
   state is in the address and survives a reload. They scroll sideways on a phone rather than
   wrap into a block. */
.chip-filters { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
.chip-filters::-webkit-scrollbar { display: none; }
.chip-filter {
  display: inline-flex; align-items: center; gap: 8px; flex: none; padding: 7px 14px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--fg-2);
  font-size: 13px; font-weight: 500; text-decoration: none; transition: border-color .14s, background .14s;
}
.chip-filter:visited { color: var(--fg-2); }
.chip-filter:hover { border-color: var(--line-strong); color: var(--fg-1); }
.chip-filter svg { width: 14px; height: 14px; stroke-width: 1.75; }
.chip-filter .n { font-size: 11.5px; font-weight: 600; color: var(--fg-3); font-variant-numeric: tabular-nums; }
.chip-filter.is-current, .chip-filter.is-current:visited { border-color: var(--accent); background: var(--accent-soft); color: var(--fg-1); }
.chip-filter.is-current .n { color: var(--fg-1); }
.chip-filter:focus-visible { outline: 2px solid var(--fg-1); outline-offset: 2px; }
.dark .chip-filter:focus-visible { outline-color: var(--accent); }

/* ---------- Bulk bar ---------- */
/* The row above a table with checkboxes: how many are selected and what can be done with them.
   It stays in view under the topbar (64px) while the list scrolls, and its buttons wait until
   something is selected. */
.bulk-bar {
  position: sticky; top: 64px; z-index: 20; display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
  padding: 12px 22px; background: var(--card); border-bottom: 1px solid var(--line);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.bulk-bar.has-selection { background: color-mix(in srgb, var(--accent-soft) 70%, var(--card)); }
.bulk-count { display: inline-flex; align-items: center; gap: 10px; font-size: 13px; color: var(--fg-2); font-weight: 500; margin-right: auto; }
.bulk-count label { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; }
.bulk-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.bulk-link { display: flex; align-items: center; gap: 8px; }
.bulk-link .picker { width: 240px; }
.tbl th.col-check, .tbl td.col-check { width: 1%; padding-right: 0; }
/* On a phone the bar wraps to three lines; kept sticky it would cover half the list. */
@media (max-width: 767px) { .bulk-bar { position: static; } }
@media (max-width: 639px) {
  .bulk-bar { padding: 12px 16px; }
  .bulk-actions, .bulk-link { width: 100%; }
  .bulk-link .picker { flex: 1; width: auto; }
}

/* ---------- Formulieren filter ---------- */
/* Search wide, page and sort narrower, the buttons at the end of the line; one field per line on
   a phone. */
.forms-filter { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1.5fr) minmax(0, 1fr) auto; gap: 12px 16px; align-items: end; }
.forms-filter-field { min-width: 0; }
.forms-filter .input, .forms-filter .select { height: 42px; }
.forms-filter-field .label { display: block; margin-bottom: 6px; }
.forms-filter-actions { display: flex; gap: 8px; }
@media (max-width: 899px) {
  .forms-filter { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .forms-filter-search { grid-column: 1 / -1; }
}
@media (max-width: 639px) {
  .forms-filter { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Koppelingen: search and chips above the pages table ---------- */
.pages-filter { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 16px; border-bottom: 1px solid var(--line); }
.pages-filter-search { display: flex; gap: 8px; flex: 1 1 280px; max-width: 420px; }
.pages-filter-search .input { height: 38px; }
@media (max-width: 639px) { .pages-filter-search { max-width: none; } }

/* ---------- Reacties filter ---------- */
/* Two rows on a wide screen: the search and the three pickers, then status, period, the own days
   and the buttons. The own days show only while "Eigen periode" is chosen. */
.leads-filter { display: grid; grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr)); gap: 12px 16px; align-items: end; }
.leads-filter-field { min-width: 0; }
.leads-filter .input, .leads-filter .select { height: 42px; }
.leads-filter-field .label { display: block; margin-bottom: 6px; }
.leads-filter-actions { display: flex; align-items: center; gap: 8px; min-height: 42px; }
.leads-filter-day { display: none; }
.leads-filter-error { grid-column: 1 / -1; margin: -4px 0 0; font-size: 12.5px; }
.leads-search { position: relative; }
.leads-search .input { padding-right: 34px; }
.leads-search-clear { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); display: inline-flex; padding: 4px; border: 0; border-radius: 6px; background: transparent; color: var(--fg-3); cursor: pointer; }
.leads-search-clear:hover { color: var(--fg-1); background: var(--surface-2); }
.leads-search-clear:focus-visible { outline: 2px solid var(--fg-1); outline-offset: 1px; }
.leads-search-clear svg { width: 13px; height: 13px; stroke-width: 2; }
.leads-filter:has(#leads-period option[value="eigen"]:checked) .leads-filter-day { display: block; }
@media (max-width: 1099px) {
  .leads-filter { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .leads-filter-search { grid-column: 1 / -1; }
}
/* On a phone the search and the three pickers take the width; status and period, and the two
   days, sit side by side. */
@media (max-width: 639px) {
  .leads-filter { gap: 12px; }
  .leads-filter > .leads-filter-field:nth-child(-n+4), .leads-filter-actions { grid-column: 1 / -1; }
}

.forms-synced { display: flex; align-items: flex-start; gap: 6px; line-height: 1.45; margin: -4px 0 12px; font-size: 12px; color: var(--fg-3); }
.forms-synced svg { width: 13px; height: 13px; stroke-width: 1.75; flex: none; margin-top: 2px; }

/* ---------- Pager ---------- */
.pager { display: flex; align-items: center; justify-content: center; gap: 6px; flex-wrap: wrap; }
.pager-pages { display: flex; align-items: center; gap: 4px; list-style: none; margin: 0; padding: 0; }
.pager-page, .pager-step {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px; min-width: 34px; height: 34px;
  padding: 0 10px; border-radius: 9px; border: 1px solid transparent; font-size: 13px; font-weight: 500;
  color: var(--fg-2); text-decoration: none; font-variant-numeric: tabular-nums;
}
.pager-page:visited, .pager-step:visited { color: var(--fg-2); }
.pager-page:hover, .pager-step:hover { border-color: var(--line); background: var(--card); color: var(--fg-1); }
.pager-page.is-current, .pager-page.is-current:visited { background: var(--accent); color: var(--accent-contrast, #fff); }
.pager-step svg { width: 15px; height: 15px; stroke-width: 2; }
.pager-step.is-disabled { color: var(--fg-3); opacity: .5; pointer-events: none; }
.pager-gap { min-width: 20px; text-align: center; color: var(--fg-3); }
.pager a:focus-visible { outline: 2px solid var(--fg-1); outline-offset: 1px; }
.dark .pager a:focus-visible { outline-color: var(--accent); }
@media (max-width: 639px) {
  .pager-step span { display: none; }
  .pager-page, .pager-step { min-width: 32px; height: 32px; padding: 0 8px; }
}

/* ---------- Meter ---------- */
/* Segments side by side with a hairline of card between them, so "spent" and "promised" read as
   two amounts and not as one bar in two shades. The legend under it is the text equivalent; the
   bar itself is hidden from screen readers. Widths are inline, because a share is computed per
   render. */
.meter-bar { display: flex; gap: 3px; height: 12px; border-radius: 999px; overflow: hidden; }
.meter-seg { display: block; height: 100%; min-width: 3px; background: var(--tone-strong); }
.meter-seg.is-soft { background: color-mix(in srgb, var(--tone-strong) 42%, var(--card)); }
.meter-legend { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px 18px; }
.meter-legend li { display: flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--fg-2); }
.meter-legend .sw { width: 9px; height: 9px; border-radius: 3px; flex: none; background: var(--tone-strong); }
.meter-legend .sw.is-soft { background: color-mix(in srgb, var(--tone-strong) 42%, var(--card)); }
.meter-legend .tone-neutral .sw { box-shadow: inset 0 0 0 1px var(--line-strong); }
.meter-legend .n { font-weight: 600; color: var(--fg-1); font-variant-numeric: tabular-nums; }

/* ---------- Progress ---------- */
.progress { height: 4px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.progress > span { display: block; height: 100%; border-radius: inherit; background: var(--tone-strong, var(--accent)); }
.dark .progress { background: var(--line); }

/* ---------- Steps ---------- */
/* Vertical by default, a row from 640px with .steps-row. The line between two marks is the
   ::before of the step it leaves from, green once that step is done. */
.steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.step { position: relative; display: flex; align-items: flex-start; gap: 12px; padding-bottom: 18px; min-width: 0; }
.step:last-child { padding-bottom: 0; }
.step::before { content: ''; position: absolute; left: 13px; top: 32px; bottom: 4px; width: 2px; border-radius: 2px; background: var(--line); }
.step:last-child::before { display: none; }
.step.is-done::before { background: var(--accent); }
.step-mark {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 28px; height: 28px; border-radius: 999px; border: 2px solid var(--line-strong);
  background: var(--card); color: var(--fg-2); font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.step-mark svg { width: 14px; height: 14px; stroke-width: 2.75; }
.step.is-done .step-mark { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }
.step.is-current .step-mark { border-color: var(--accent); color: var(--fg-1); box-shadow: 0 0 0 4px var(--accent-ring); }
.step.is-locked .step-mark { border-style: dashed; color: var(--fg-3); }
.step-body { min-width: 0; padding-top: 4px; }
.step-title { font-size: 13.5px; font-weight: 600; color: var(--fg-1); }
.step.is-locked .step-title { font-weight: 500; color: var(--fg-3); }
.step-text { margin-top: 2px; font-size: 12.5px; line-height: 1.5; color: var(--fg-3); }
@media (min-width: 640px) {
  .steps-row { flex-direction: row; }
  .steps-row .step { flex: 1; flex-direction: column; gap: 10px; padding: 0 12px 0 0; }
  .steps-row .step::before { left: 38px; right: 10px; top: 13px; bottom: auto; width: auto; height: 2px; }
  .steps-row .step-body { padding-top: 0; }
}

/* ---------- Disclosure ---------- */
/* A card that opens. The summary is a flex row, which drops the native marker in Chrome, and
   the other browsers' marker is removed on purpose: the chevron on the right is the one marker. */
details.disclosure > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 18px 22px; cursor: pointer; list-style: none; border-radius: var(--radius);
  font-size: 15px; font-weight: 700; color: var(--fg-1);
}
details.disclosure > summary::-webkit-details-marker { display: none; }
details.disclosure > summary::after {
  content: ''; flex: none; width: 8px; height: 8px; margin-right: 4px;
  border-right: 2px solid var(--fg-3); border-bottom: 2px solid var(--fg-3);
  transform: translateY(-2px) rotate(45deg); transition: transform .18s cubic-bezier(.2,.6,.2,1);
}
details.disclosure > summary:hover::after { border-color: var(--fg-1); }
details.disclosure[open] > summary { border-bottom: 1px solid var(--line); border-radius: var(--radius) var(--radius) 0 0; }
details.disclosure[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
details.disclosure .sub { font-size: 12px; font-weight: 400; color: var(--fg-3); margin-top: 2px; }
.disclosure-body { padding: 18px 22px 22px; }

/* ---------- Chips and marks for a table that reads at a glance ---------- */
/* A flag looks like a chip but is not one: .chip is the advertisement's status in the table, and
   a test or a script that asks for the first chip of a row means that one. */
.flag { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 500; line-height: 1.4; white-space: nowrap; }
.flag svg { width: 12px; height: 12px; stroke-width: 2.25; flex-shrink: 0; }
.flag .dot { width: 6px; height: 6px; border-radius: 999px; background: currentColor; }
/* A status chip with what belongs to it (channels, a flag, a link) in one table cell. Wrapping
   starts the next line at the cell's edge, not at a margin that was meant for the chip beside it. */
.status-line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.flag-attn { background: #FFF1E6; color: #B4541B; }
.dark .flag-attn { background: rgba(255,176,135,0.14); color: #FFB087; }
.days { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; white-space: nowrap; }
.days .unit { color: var(--fg-3); }
.channels { display: inline-flex; align-items: center; gap: 5px; color: var(--fg-3); vertical-align: middle; }
.channels svg { width: 14px; height: 14px; stroke-width: 1.75; }
/* The channels' own logos (ui.brands). The badges keep their brand colours in dark mode too. */
.brands { display: inline-flex; align-items: center; gap: 6px; }
.brand { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 7px; }
.brand svg { width: 13px; height: 13px; }
.brand-facebook svg { width: 22px; height: 22px; }
.brand-instagram { background: radial-gradient(circle at 30% 107%, #fdf497 0%, #fdf497 5%, #fd5949 45%, #d6249f 60%, #285aeb 90%); }
.brand-tiktok { background: #000; }
/* A black badge on the navy of dark mode needs an edge to stay a badge. */
.dark .brand-tiktok { box-shadow: 0 0 0 1px rgba(255, 255, 255, .2); }
/* The Facebook mark is a blue disc with the f cut out; on navy the cutout would be navy too. */
.dark .brand-facebook svg { border-radius: 50%; background: #fff; }
.reach { display: flex; flex-direction: column; gap: 6px; min-width: 72px; }
.reach .progress { width: 72px; }

/* ---------- Budget (Vacatures) ---------- */
.budget { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; padding: 20px 22px 22px; }
@media (min-width: 900px) { .budget { grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 32px; } }
.budget-figure { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px; margin-bottom: 14px; }
.budget-figure .big { font-size: 28px; font-weight: 700; letter-spacing: -0.02em; color: var(--fg-1); line-height: 1.1; font-variant-numeric: tabular-nums; }
.budget-figure .of { font-size: 15px; font-weight: 500; color: var(--fg-3); font-variant-numeric: tabular-nums; }
.budget-figure .left { font-size: 13px; color: var(--fg-2); }
.budget-note { margin: 14px 0 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12.5px; color: var(--fg-3); }
.budget-side { padding-top: 16px; border-top: 1px solid var(--line); }
/* The stat next to the meter is part of this card, so it drops its own frame. */
.budget-side .stat { background: transparent; border: 0; padding: 0; }
@media (min-width: 900px) { .budget-side { padding: 0 0 0 28px; border-top: 0; border-left: 1px solid var(--line); } }

/* ---------- Callout ---------- */
/* A light wash of the tone with a bar in its strong colour on the left, so a warning looks like
   one at a glance and in the right colour. The action stands on the right and drops under the
   text on a phone, lined up with it and not with the tile. */
.callout {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px 14px; margin-bottom: 20px;
  padding: 14px 18px; border-radius: 12px; border: 1px solid color-mix(in srgb, var(--tone-strong) 22%, transparent);
  border-left: 4px solid var(--tone-strong); background: color-mix(in srgb, var(--tone) 20%, var(--card));
}
.dark .callout { background: color-mix(in srgb, var(--tone) 10%, var(--card)); }
.callout-body { flex: 1 1 240px; min-width: 0; }
.callout-title { margin: 0; font-size: 14px; font-weight: 700; color: var(--fg-1); }
.callout-text { margin: 2px 0 0; font-size: 13px; line-height: 1.55; color: var(--fg-2); }
.callout-action { flex: none; }
.callout-action .btn-outline { background: var(--card); }
@media (max-width: 639px) { .callout-action { flex-basis: 100%; padding-left: 46px; } }
/* Somebody else's words inside a callout, such as the reason a channel gives for rejecting an
   ad: set apart with a thin bar in the callout's own colour, so it reads as a quote and not as
   ours. A callout that holds one aligns its tile to the top, because the text runs longer. */
.callout:has(.callout-quote) { align-items: flex-start; }
.callout-quote {
  margin: 8px 0; padding: 2px 0 2px 12px; border-left: 2px solid color-mix(in srgb, var(--tone-strong) 50%, transparent);
  font-size: 13px; line-height: 1.55; font-style: italic; color: var(--fg-1); overflow-wrap: anywhere;
}
/* A callout or a button that a script shows starts hidden, and their own display would show it
   anyway: the hidden attribute loses to any class that sets display. */
.callout[hidden], .btn[hidden], .chip[hidden] { display: none; }

/* ---------- Facts ---------- */
/* The fields of one record as a definition list: label above value on a phone, side by side from
   640px. A <div> around each pair keeps the line between them. */
.facts { margin: 0; }
.facts > div { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; padding: 11px 0; border-bottom: 1px solid var(--line); }
.facts > div:first-child { padding-top: 0; }
.facts > div:last-child { padding-bottom: 0; border-bottom: 0; }
.facts dt { font-size: 12.5px; color: var(--fg-3); }
.facts dd { margin: 0; min-width: 0; font-size: 13.5px; line-height: 1.5; color: var(--fg-1); overflow-wrap: anywhere; }
.facts dd .t-sub { font-size: 12px; color: var(--fg-3); }
@media (min-width: 640px) { .facts > div { grid-template-columns: 190px minmax(0, 1fr); gap: 16px; align-items: baseline; } }

/* ---------- Channel tile ---------- */
/* The icons of a channel inside a tile, for a card that stands for a page: two icons for Meta, so
   they shrink to fit the small tile and take the tile's colour instead of the grey of a row. */
.tile .channels { color: inherit; gap: 2px; }
.tile .channels svg { width: 13px; height: 13px; }

/* ---------- Choice card ---------- */
/* label.radio-card.choice-card: a radio or checkbox that reads as a tile you pick. The input is
   visually hidden (.sr-only) and stays in the tab order, so arrow keys still move the choice; the
   ring shows where keyboard focus is and the check in the corner shows what is chosen, from
   .is-selected (server and script) or from the checked input itself. .choice-card-stack puts the
   tile above the text from 640px, for three or more choices side by side. */
.choice-card { position: relative; gap: 12px; padding: 14px 44px 14px 14px; border-radius: 12px; background: var(--card); transition: border-color .14s, background-color .14s, box-shadow .14s; }
.choice-card:hover { border-color: var(--line-strong); }
.choice-card.is-selected, .choice-card:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); box-shadow: 0 0 0 1px var(--accent); }
.choice-card:has(input:focus-visible) { outline: 2px solid var(--fg-1); outline-offset: 2px; }
.dark .choice-card:has(input:focus-visible) { outline-color: var(--accent); }
.choice-card.is-disabled { cursor: default; }
.choice-card.is-disabled:not(.is-selected) { opacity: .6; }
.choice-title { display: block; font-size: 13.5px; font-weight: 600; color: var(--fg-1); line-height: 1.35; }
.choice-check {
  position: absolute; top: 12px; right: 12px; display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 999px; border: 2px solid var(--line-strong); background: var(--card); color: transparent;
}
.choice-check svg { width: 12px; height: 12px; stroke-width: 3; }
.is-selected > .choice-check, .choice-card:has(input:checked) > .choice-check,
[aria-pressed="true"] > .choice-check { border-color: var(--accent); background: var(--accent); color: var(--accent-contrast); }
@media (min-width: 640px) {
  .choice-card-stack { flex-direction: column; align-items: flex-start; gap: 10px; padding: 16px; }
}

/* ---------- Ad screen (Advertentie aanzetten) ---------- */
/* The preview column follows the scroll from lg up, just under the sticky top bar, but only on a
   window tall enough to show the whole preview; on a lower one it scrolls with the page, because a
   sticky column taller than the window hides its own bottom. */
@media (min-width: 1024px) and (min-height: 900px) { .ad-preview-col { position: sticky; top: 88px; align-self: start; } }
/* A field's character count as a small chip under it, on the right. */
.field-count { display: flex; justify-content: flex-end; margin: 6px 0 16px; }
/* A short line that says why something cannot change, with its lock. */
.ad-note {
  display: flex; align-items: flex-start; gap: 8px; margin: 0 0 16px; padding: 10px 12px;
  border-radius: var(--radius-sm); background: var(--surface-2); font-size: 12.5px; line-height: 1.5; color: var(--fg-2);
}
.ad-note svg { width: 15px; height: 15px; stroke-width: 1.75; flex: none; margin-top: 1px; color: var(--fg-3); }
/* Budget: what the three numbers add up to, the one figure of the card. */
.ad-cost {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--nubos-icon-yellow, #FFF16A) 70%, var(--line));
  background: color-mix(in srgb, var(--nubos-icon-yellow, #FFF16A) 18%, var(--card));
}
.dark .ad-cost { border-color: var(--line); background: color-mix(in srgb, var(--nubos-icon-yellow, #FFF16A) 7%, var(--card)); }
.ad-cost.hidden { display: none; }
.ad-cost-text { margin: 0; font-size: 13.5px; color: var(--fg-2); line-height: 1.4; }
.ad-cost-amount { font-size: 18px; font-weight: 700; letter-spacing: -0.01em; color: var(--fg-1); font-variant-numeric: tabular-nums; margin: 0 2px; }
.ad-cost + .hint { margin-top: 10px; }
/* Images: a thumbnail in a frame, and the library as a grid of photos to pick one from. */
.ad-thumb { border-radius: 10px; border: 1px solid var(--line); object-fit: cover; background: var(--surface-2); }
.media-pick {
  position: relative; display: block; padding: 0; overflow: hidden; cursor: pointer; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: 10px; transition: border-color .14s, box-shadow .14s;
}
.media-pick img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; }
.media-pick:hover { border-color: var(--line-strong); }
.media-pick[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.media-pick .choice-check { top: 6px; right: 6px; opacity: 0; }
.media-pick[aria-pressed="true"] .choice-check { opacity: 1; }
.media-pick:focus-visible { outline: 2px solid var(--fg-1); outline-offset: 2px; }
.dark .media-pick:focus-visible { outline-color: var(--accent); }
.media-pick:disabled { cursor: default; }
.ad-range { width: 100%; accent-color: var(--heading); cursor: pointer; }
/* A disclosure head that says what is set inside it, on the right before the chevron. */
details.disclosure > summary .card-head-main { flex: none; }
.disclosure-value { margin-left: auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 400; color: var(--fg-3); }
.disclosure-value.hidden { display: none; }
/* On a phone the summary gets its own line under the title instead of being cut to a few
   letters; the chevron stays on the title line. */
@media (max-width: 639px) {
  details.disclosure > summary:has(.disclosure-value) { flex-wrap: wrap; row-gap: 4px; }
  details.disclosure > summary .card-head-main { flex: 1; }
  details.disclosure > summary::after { order: 1; }
  .disclosure-value { order: 2; flex-basis: 100%; margin-left: 44px; white-space: normal; }
}
.ad-question-list { list-style: none; margin: 0 0 14px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.ad-question-list li { display: flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--fg-1); }
.ad-question-list svg { width: 14px; height: 14px; stroke-width: 2.25; color: var(--heading); flex: none; }
/* Insights: a blue callout that holds a list, so the tile stays at the top. */
.ad-insights { align-items: flex-start; }
.ad-insights .btn-outline { background: var(--card); }
.ad-insight-list { list-style: none; margin: 10px 0 0; padding: 0; }
.ad-insight-list li + li { margin-top: 12px; padding-top: 12px; border-top: 1px solid color-mix(in srgb, var(--tone-strong) 22%, var(--line)); }
/* The preview: the advertisement in a feed frame. Instagram puts the text under the image,
   Facebook above it; the frame attribute is set by public/js/ad-page.js. */
.segmented button { display: inline-flex; align-items: center; gap: 6px; }
.segmented button svg { width: 14px; height: 14px; stroke-width: 1.75; }
.segmented button.active { box-shadow: 0 1px 2px rgba(9,26,46,0.08); }
.ad-preview-col .segmented button { padding: 6px 8px; gap: 5px; }
/* A link inside a callout's sentence, such as the way to the screen that fixes it. */
.callout-text a { color: var(--heading); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.segmented button:focus-visible { outline: 2px solid var(--fg-1); outline-offset: 1px; }
.dark .segmented button:focus-visible { outline-color: var(--accent); }
.ad-mock {
  display: flex; flex-direction: column; max-width: 360px; margin: 0 auto; overflow: hidden;
  border: 1px solid var(--line); border-radius: 14px; background: var(--card);
  box-shadow: 0 12px 32px -18px rgba(9,26,46,0.35);
}
.ad-mock-head { display: flex; align-items: center; gap: 10px; padding: 12px; }
.ad-mock-text { margin: 0; padding: 0 12px 12px; font-size: 13.5px; line-height: 1.5; color: var(--fg-1); white-space: pre-line; overflow-wrap: anywhere; }
.ad-mock-cta { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 12px; background: var(--surface-2); }
.ad-mock[data-ad-preview-frame="instagram"] .ad-mock-cta { order: 3; }
.ad-mock[data-ad-preview-frame="instagram"] .ad-mock-text { order: 4; padding-top: 12px; }
.ad-mock[data-ad-preview-frame="instagram"] .ad-mock-media { order: 2; }
.ad-mock-tiktok {
  position: relative; max-width: 270px; margin: 0 auto; overflow: hidden; aspect-ratio: 9 / 16;
  border-radius: 18px; background: var(--nubos-navy, #091A2E); box-shadow: 0 12px 32px -18px rgba(9,26,46,0.5);
}
.ad-mock-note { display: flex; align-items: center; justify-content: center; gap: 6px; margin: 14px 0 0; text-align: center; font-size: 12px; line-height: 1.5; color: var(--fg-3); }
.ad-mock-note svg { width: 14px; height: 14px; stroke-width: 2.25; color: var(--heading); flex: none; }
/* The actions: a row on a phone, and from lg a bar that sticks to the bottom of the window while
   the form is in view. Publiceren and Opslaan on the left, the way out on the right. */
.ad-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 4px; }
.ad-actions-end { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-left: auto; }
/* Keyboard focus and a jump to an anchor keep clear of the sticky top bar and of this bar: without
   it a focused field right above the bar, or right under the top bar, sits behind it. */
@media (min-width: 1024px) { html { scroll-padding-top: 80px; scroll-padding-bottom: 104px; } }
@media (min-width: 1024px) {
  .ad-actions {
    position: sticky; bottom: 16px; z-index: 20; padding: 12px 14px; border-radius: var(--radius);
    border: 1px solid var(--line); background: color-mix(in srgb, var(--card) 92%, transparent);
    backdrop-filter: blur(8px); box-shadow: 0 16px 36px -20px rgba(9,26,46,0.45);
  }
}
/* What Publiceren sends, or why it cannot yet: a line of its own under the buttons. */
.ad-actions-note {
  order: 99; flex-basis: 100%; display: flex; align-items: center; gap: 6px;
  font-size: 12.5px; line-height: 1.4; color: var(--fg-2);
}
.ad-actions-note svg { width: 14px; height: 14px; stroke-width: 2; flex: none; color: var(--heading); }
.ad-actions-note.is-blocked svg { color: var(--fg-3); }

/* ---------- Variants on the ad screen ---------- */
/* A tab per variant: on a phone a list of rows, the number, the name and the angle, the state on
   the right; from a width that fits them, side by side as equal cards. A container query, because
   the preview column takes a different share of the window at every size. */
.variant-body { container-type: inline-size; }
.variant-tabs { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
@container (min-width: 520px) {
  .variant-tabs[data-count="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .variant-tabs[data-count="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.variant-tab {
  position: relative; display: flex; align-items: center; gap: 12px; min-width: 0;
  padding: 12px 14px; border-radius: 12px; border: 1px solid var(--line); background: var(--card);
  color: inherit; text-decoration: none; transition: border-color .14s, box-shadow .14s, background-color .14s;
}
.variant-tab:hover { border-color: var(--line-strong); }
.variant-tab.is-active {
  border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, var(--card));
}
.variant-tab:focus-visible { outline: 2px solid var(--fg-1); outline-offset: 2px; }
.dark .variant-tab:focus-visible { outline-color: var(--accent); }
.variant-tab .chip { margin-left: auto; flex: none; }
.variant-num {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 28px; height: 28px; border-radius: 999px; font-size: 13px; font-weight: 700;
  font-variant-numeric: tabular-nums; background: var(--surface-2); color: var(--fg-2);
}
.variant-tab.is-active .variant-num { background: var(--accent); color: var(--accent-contrast); }
.variant-tab-text, .vr-name { display: flex; flex-direction: column; min-width: 0; }
.variant-tab-text b, .vr-name b { font-size: 13.5px; font-weight: 600; color: var(--fg-1); line-height: 1.3; }
.variant-tab-text span, .vr-name span { font-size: 12px; color: var(--fg-3); line-height: 1.35; }
@container (min-width: 520px) {
  .variant-tabs:not([data-count="1"]) .variant-tab { flex-wrap: wrap; align-items: flex-start; row-gap: 10px; }
  .variant-tabs:not([data-count="1"]) .variant-tab .chip { margin-left: 40px; flex-basis: auto; }
}
/* Why a button is off, or a note about the numbers: a quiet line with its icon. */
.variant-why {
  display: flex; align-items: flex-start; gap: 8px; margin: 12px 0 0; padding: 10px 12px;
  border-radius: var(--radius-sm); background: var(--surface-2); font-size: 12.5px; line-height: 1.5; color: var(--fg-2);
}
.variant-why svg { width: 15px; height: 15px; stroke-width: 1.75; flex: none; margin-top: 1px; color: var(--fg-3); }
.variant-why-info { margin: 0 0 14px; }
.variant-callout { margin: 14px 0 0; align-items: flex-start; }
.variant-foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px;
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line);
}
.variant-foot-text { margin: 0; flex: 1 1 260px; font-size: 12.5px; line-height: 1.5; color: var(--fg-2); }
.variant-foot-text b { color: var(--fg-1); font-weight: 600; }

/* Results per variant: a row per variant, the name on top and five figures under it, two to a
   line on a phone and all five side by side where they fit. */
.vr-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; container-type: inline-size; }
.vr-row { padding: 14px 16px; border-radius: 12px; border: 1px solid var(--line); background: var(--card); }
.vr-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.vr-head .chip { margin-left: auto; flex: none; }
.vr-chips { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; margin-left: auto; min-width: 0; }
.vr-chips .chip { margin-left: 0; }
.vr-note { display: flex; align-items: center; gap: 6px; margin: 10px 0 0; font-size: 12.5px; color: var(--fg-2); }
.vr-note svg { width: 14px; height: 14px; stroke-width: 1.75; flex: none; color: var(--fg-3); }
.vr-note a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.vr-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 16px; margin: 14px 0 0; }
@container (min-width: 480px) { .vr-stats { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.vr-stats dt { font-size: 11.5px; color: var(--fg-3); line-height: 1.3; }
.vr-stats dd { margin: 2px 0 0; font-size: 16px; font-weight: 700; letter-spacing: -0.01em; color: var(--fg-1); font-variant-numeric: tabular-nums; white-space: nowrap; }
.vr-share { display: flex; align-items: center; gap: 10px; margin-top: 12px; font-size: 11.5px; color: var(--fg-3); white-space: nowrap; }
.vr-share .progress { flex: 1 1 auto; max-width: 220px; }

@media (prefers-reduced-motion: reduce) {
  .choice-card, .media-pick, .variant-tab { transition: none !important; }
}

/* ---------- Account (Koppelingen, onboarding) ---------- */
/* The account a connection works with, one look for every channel: a light panel with a round mark
   of initials, the name and a line under it, and the actions on the right. The actions wrap under
   the name as soon as they do not fit next to it, which on a phone is always. Two single-button
   forms next to each other keep the gap of the row and not the margin of .form-inline. */
.account {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px 20px;
  padding: 16px; border-radius: 12px; border: 1px solid var(--line);
  background: color-mix(in srgb, var(--surface-2) 60%, var(--card));
}
.account-main { display: flex; align-items: center; gap: 12px; min-width: 0; flex: 1 1 240px; }
.account-body { min-width: 0; }
.account-avatar {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 40px; height: 40px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--card); color: var(--fg-1); font-size: 13px; font-weight: 700; letter-spacing: .02em;
}
.account-avatar svg { width: 18px; height: 18px; stroke-width: 1.75; color: var(--fg-2); }
.account-name { margin: 0; font-size: 14px; font-weight: 700; color: var(--fg-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-line { margin: 2px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--fg-3); }
.account-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.account-actions form { margin: 0; }
.account-actions .form-inline + .form-inline { margin-left: 0; }

/* ---------- Checks ---------- */
/* The checks of a connection under its account, one line each: the chip says how it stands, and a
   chip that is not green carries "Wat moet ik doen" on the line under it. A sentence from the
   channel itself (the last error) reads as body text under its chip. */
.checks { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
.checks .check-row { margin-bottom: 0; }
.card-p > .checks:first-child { margin-top: 0; }
.check-row > p { margin: 0; flex-basis: 100%; font-size: 13px; line-height: 1.55; color: var(--fg-2); }
.check-row > p.hint { font-size: 12px; color: var(--fg-3); }
.check-row summary { font-size: 12.5px; font-weight: 600; }
.check-row details > p { margin: 8px 0 0; max-width: 72ch; font-size: 13px; line-height: 1.55; color: var(--fg-2); }
.check-row details > form, .check-row details > p > .btn { margin-top: 8px; }

/* A callout that ends a card needs no space under it: the card has its own padding. */
.card .callout:last-child { margin-bottom: 0; }

/* A tab strip wider than a phone scrolls sideways on its own instead of widening the page. The
   line under the tabs is on the wrapper, as in .tabs-bar, because a scroller clips what sticks out
   of it: the active underline would lose the pixel it lays over the line, and the focus ring its
   outer edge. So below 768px the tabs keep their underline inside the scroller, sit on the line
   of the wrapper, and get room around them for the ring. From 768px nothing scrolls. */
.tabs-scroll { border-bottom: 1px solid var(--line); }
.tabs-scroll > .tabs { border-bottom: 0; }
@media (max-width: 767px) {
  .tabs-scroll > .tabs { overflow-x: auto; scrollbar-width: none; padding: 4px 4px 0; margin: -4px -4px 0; }
  .tabs-scroll > .tabs::-webkit-scrollbar { display: none; }
  .tabs-scroll .tab { flex: none; white-space: nowrap; margin-bottom: 0; }
  .tabs-scroll .tab:focus-visible { outline-offset: -2px; box-shadow: none; }
}

/* ---------- Usage bar (Koppelingen) ---------- */
/* How many ads a page runs against its limit: the count on top and a thin bar under it. */
.usage { display: inline-flex; flex-direction: column; gap: 6px; min-width: 88px; }
.usage .progress { width: 88px; }

/* ---------- Choice tiles ---------- */
/* A radio card whose input is checked is the chosen one without a class, so a choice made before
   any script runs, or with none at all, still looks chosen. The keyboard ring goes around the
   whole card, because the input inside it is small. */
.radio-card:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.radio-card:has(input:focus-visible) { outline: 2px solid var(--fg-1); outline-offset: 2px; }
.dark .radio-card:has(input:focus-visible) { outline-color: var(--accent); }
.choice-grid .radio-card input { accent-color: var(--nubos-green, #00B889); margin-top: 3px; flex: none; }
.radio-card { transition: border-color .14s, background .14s; }
.radio-card:hover { border-color: var(--line-strong); }
.choice-grid .radio-card .tile { margin-top: -2px; }
.choice-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.choice-grid .radio-card { margin-bottom: 0; padding: 16px; border-radius: 12px; gap: 12px; }
@media (min-width: 640px) { .choice-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.choice-grid .check-row { margin: 8px 0 0 16px; }
.choice-title { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px; font-size: 13.5px; font-weight: 700; color: var(--fg-1); }

/* ---------- Swatches (Huisstijl) ---------- */
/* The logo and the two colours as chips, so the style reads at a glance before the fields. The
   colour of a dot is inline because it is the customer's own. */
.swatch-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 18px; }
.swatch {
  display: inline-flex; align-items: center; gap: 8px; min-height: 34px; padding: 4px 12px 4px 4px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--card); font-size: 12px; color: var(--fg-2);
}
.swatch-dot { width: 24px; height: 24px; border-radius: 999px; flex: none; box-shadow: inset 0 0 0 1px rgba(9,26,46,.12); }
.swatch-hex { font-family: 'JetBrains Mono', monospace; font-size: 11.5px; font-weight: 500; color: var(--fg-1); text-transform: uppercase; }
.swatch-logo { padding: 4px 12px; border-radius: 10px; }
.swatch-logo img { display: block; height: 26px; width: auto; max-width: 140px; object-fit: contain; }
.dark .swatch-logo { background: #FFFFFF; }

/* ---------- Steps as links (onboarding) ---------- */
/* Each step of the wizard is a link around its mark and its label, laid out the way the step
   itself would be. */
.step-link { display: flex; flex: 1; min-width: 0; gap: inherit; flex-direction: inherit; align-items: inherit; color: inherit; text-decoration: none; border-radius: 10px; }
.step-link:hover .step-title { color: var(--heading); }
.step-link:focus-visible { outline: 2px solid var(--fg-1); outline-offset: 3px; }
.dark .step-link:focus-visible { outline-color: var(--accent); }
.step.is-stalled .step-mark { border-color: #F47B3C; }
/* The step on the screen, apart from the step the wizard waits on (the ring): its label is
   underlined in the accent, and on a phone, where the labels are not shown, a bar under its mark. */
.step.is-on-screen .step-title { color: var(--fg-1); text-decoration: underline; text-decoration-color: var(--accent); text-decoration-thickness: 2px; text-underline-offset: 5px; }
.step-body .flag { margin-top: 6px; }
@media (max-width: 639px) {
  .steps-compact { flex-direction: row; }
  .steps-compact .step { flex: 1; padding-bottom: 0; }
  .steps-compact .step::before { left: 34px; right: 6px; top: 13px; bottom: auto; width: auto; height: 2px; }
  /* 28px marks with 6px around them: a tap target of 40px that does not move the row. */
  .steps-compact .step-link { position: relative; padding: 6px; margin: -6px; }
  .steps-compact .step.is-on-screen .step-link::after { content: ''; position: absolute; left: 6px; bottom: -3px; width: 28px; height: 3px; border-radius: 3px; background: var(--accent); }
  .steps-compact .step-body { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
}
.onboarding-steps { padding: 18px 22px 20px; margin-bottom: 20px; }
.onboarding-steps-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.onboarding-steps-count { margin: 0; font-size: 13.5px; font-weight: 700; color: var(--fg-1); }
.onboarding-steps .progress { margin-bottom: 18px; }
/* A card of form rows: every row brings its own margin under it, so the card leaves it off. */
.card-fields { padding: 22px 22px 2px; }
.card-foot {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px 16px;
  padding: 14px 22px; border-top: 1px solid var(--line);
}
.card-foot form { margin: 0; }

/* ---------- Motion ---------- */
@media (prefers-reduced-motion: reduce) {
  details.disclosure > summary::after, .sidebar, a.stat-link, .radio-card { transition: none !important; }
}

/* ---------- Shell below the md breakpoint ---------- */
/* On a phone the sidebar is a drawer: off the screen and out of the tab order until the menu
   button in the top bar opens it (public/js/nav-drawer.js). visibility is switched after the
   slide on the way out, so the links cannot be tabbed to while the drawer is closed. From 768px
   up none of this applies and the shell is exactly what it was. */
.menu-btn, .topbar-mark, .nav-overlay { display: none; }
@media (max-width: 767px) {
  .app-content { padding: 20px 16px 40px; }
  .topbar { height: 56px; padding: 0 12px 0 8px; gap: 6px; }
  .topbar .crumbs { display: none; }
  .whatsnew { padding: 10px 16px; }
  .menu-btn {
    display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px;
    background: transparent; border: 0; border-radius: 10px; color: var(--fg-1); cursor: pointer;
  }
  .menu-btn:hover { background: var(--surface-2); }
  .menu-btn svg { width: 22px; height: 22px; stroke-width: 2; }
  .topbar-mark { display: inline-flex; align-items: center; gap: 8px; min-width: 0; text-decoration: none; color: var(--fg-1); font-size: 15px; font-weight: 700; white-space: nowrap; }
  .topbar-mark img { height: 24px; width: auto; }
  .sidebar {
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 50; height: 100dvh; width: min(280px, 86vw);
    overflow-y: auto; transform: translateX(-100%); visibility: hidden;
    transition: transform .22s cubic-bezier(.2,.6,.2,1), visibility 0s linear .22s;
  }
  .nav-open .sidebar { transform: none; visibility: visible; transition: transform .22s cubic-bezier(.2,.6,.2,1); }
  .nav-open, .nav-open body { overflow: hidden; }
  .nav-overlay { display: block; position: fixed; inset: 0; z-index: 45; background: rgba(9,26,46,0.5); }
  .nav-overlay[hidden] { display: none; }
}

/* ---------- ATS meter ---------- */
/* The share of reactions with a status in the customer's ATS (templates/admin/optimiser/_meter):
   a big figure, a bar with a marker where the interview rung starts, and the four rungs of the
   ladder as steps. The marker is a line across the track, so it reads on a bar that is past it
   as well as on one that is not. */
.ats-meter-figure { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; }
.ats-meter-value { font-size: 34px; font-weight: 700; letter-spacing: -0.03em; line-height: 1; color: var(--fg-1); font-variant-numeric: tabular-nums; }
.ats-meter-caption { font-size: 13.5px; color: var(--fg-2); }
.ats-meter-bar { position: relative; height: 12px; margin-top: 14px; border-radius: 999px; background: var(--surface-2); }
.dark .ats-meter-bar { background: var(--line); }
.ats-meter-fill { display: block; height: 100%; border-radius: inherit; background: var(--tone-strong); }
.ats-meter-mark { position: absolute; top: -4px; bottom: -4px; width: 2px; margin-left: -1px; border-radius: 2px; background: var(--fg-1); }
.ats-meter-scale { position: relative; height: 18px; margin: 6px 0 0; font-size: 11.5px; color: var(--fg-3); }
.ats-meter-scale span { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap; }
.ladder { list-style: none; margin: 18px 0 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
@media (min-width: 900px) { .ladder { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.ladder-step { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 10px 12px; border-radius: var(--radius-md); border: 1px solid var(--line); background: var(--card); color: var(--fg-3); font-size: 12.5px; line-height: 1.35; }
.ladder-mark { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 22px; height: 22px; border-radius: 999px; background: var(--surface-2); font-size: 11.5px; font-weight: 700; color: var(--fg-3); }
.ladder-mark svg { width: 12px; height: 12px; stroke-width: 2.5; }
.ladder-step.is-reached { color: var(--fg-2); }
.ladder-step.is-reached .ladder-mark { background: var(--accent-soft); color: var(--heading); }
.ladder-step.is-current { border-color: var(--tone-strong, #4A9BE8); background: color-mix(in srgb, #A5D7FB 28%, var(--card)); color: var(--fg-1); font-weight: 600; }
.ladder-step.is-current .ladder-mark { background: #4A9BE8; color: #fff; }
.dark .ladder-step.is-current { border-color: #A5D7FB; background: color-mix(in srgb, #A5D7FB 12%, var(--card)); }
.dark .ladder-step.is-current .ladder-mark { background: #A5D7FB; color: var(--nubos-navy, #091A2E); }
.ats-meter-now { margin: 16px 0 0; font-size: 13.5px; line-height: 1.6; color: var(--fg-2); }
.ats-meter-now b { color: var(--fg-1); font-weight: 600; }
.ats-meter-next { display: flex; align-items: flex-start; gap: 8px; }
.ats-meter-next svg { width: 14px; height: 14px; flex: none; margin-top: 2px; stroke-width: 2; }

/* ---------- Optimiser logbook ---------- */
/* One line per step of the system (templates/admin/optimiser/_action): a tile for the kind, the
   title with its chips and the day on the right, the change as "from → to", the reason in full,
   and the numbers as a row of small facts. A line somebody undid is dimmed but stays readable. */
.op-list { list-style: none; margin: 0; padding: 0; }
.op-item { display: flex; gap: 14px; padding: 16px 22px; border-top: 1px solid var(--line); }
.op-list > .op-item:first-child { border-top: 0; }
.op-body { flex: 1; min-width: 0; }
.op-context { margin: 0 0 4px; font-size: 12.5px; color: var(--fg-3); overflow-wrap: anywhere; }
.op-context a, .op-context .op-vacancy { color: var(--fg-1); font-weight: 600; text-decoration: none; }
.op-context a:hover { text-decoration: underline; text-underline-offset: 2px; }
.op-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
.op-title { font-size: 14px; font-weight: 600; color: var(--fg-1); }
.op-when { margin-left: auto; font-size: 12px; color: var(--fg-3); white-space: nowrap; }
.op-change { display: flex; align-items: center; gap: 6px; margin: 6px 0 0; font-size: 13.5px; color: var(--fg-2); font-variant-numeric: tabular-nums; }
.op-change span { text-decoration: line-through; text-decoration-color: var(--fg-3); }
.op-change b { color: var(--fg-1); font-weight: 700; }
.op-change svg { width: 14px; height: 14px; stroke-width: 2; color: var(--fg-3); }
/* A paused variant: its name, then its state from running to paused; the name wraps above the
   state on a narrow line instead of squeezing it. */
.op-change-variant { flex-wrap: wrap; row-gap: 2px; }
/* Another channel is a new ad, so nothing is struck through: "Nieuw op", the channel's icons and
   name, and the new ad's budget. Under it, once taken over, the ad it made. */
.op-change-new { flex-wrap: wrap; row-gap: 2px; }
.op-change-new span { text-decoration: none; }
.op-change-new .channels { color: var(--fg-2); }
.op-created { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 8px 0 0; font-size: 13px; color: var(--fg-2); }
.op-created a { color: var(--link); font-weight: 600; text-underline-offset: 2px; }
.op-variant { margin-right: 6px; font-style: normal; font-weight: 600; color: var(--fg-1); }
.op-item.is-reverted .op-variant { color: var(--fg-3); }
.op-reason { margin: 6px 0 0; font-size: 13.5px; line-height: 1.6; color: var(--fg-1); }
.op-facts { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 0; padding: 0; }
.op-facts li { padding: 3px 9px; border-radius: 999px; background: var(--surface-2); font-size: 11.5px; line-height: 1.4; color: var(--fg-2); font-variant-numeric: tabular-nums; }
.op-facts .op-confidence.is-high { background: var(--accent-soft); color: var(--heading); }
.op-facts .op-confidence.is-low { background: #FFF6D6; color: #8A6D00; }
.dark .op-facts .op-confidence.is-low { background: rgba(255,226,67,0.14); color: #FFE243; }
.op-item.is-reverted .op-title, .op-item.is-reverted .op-reason, .op-item.is-reverted .op-change { color: var(--fg-3); }
@media (max-width: 639px) {
  .op-item { padding: 14px 16px; gap: 12px; }
  .op-when { margin-left: 0; width: 100%; }
}
.op-failure { display: flex; align-items: flex-start; gap: 8px; margin: 8px 0 0; padding: 8px 10px; border-radius: var(--radius-md); background: var(--danger-wash, #FFF5F5); font-size: 12.5px; line-height: 1.5; color: #C53030; }
.dark .op-failure { background: rgba(229,62,62,0.14); color: #FF8A8A; }
.op-failure svg { width: 14px; height: 14px; flex: none; margin-top: 2px; stroke-width: 2; }
.op-item.is-failed .op-change b { text-decoration: line-through; text-decoration-color: var(--fg-3); }
.op-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 12px 0 0; }
.op-actions-hint { font-size: 12px; color: var(--fg-3); }
.op-note { display: flex; align-items: center; gap: 6px; margin: 10px 0 0; font-size: 12.5px; color: var(--fg-3); }
.op-note svg { width: 14px; height: 14px; flex: none; stroke-width: 2; }
.op-pinned { padding: 16px 22px 0; }
/* The ad screen's logbook card is a link target (a paused variant points to it): clear of the sticky topbar. */
#wat-het-systeem-deed { scroll-margin-top: 88px; }
.op-pinned .callout { margin-bottom: 0; }
.op-pinned + .op-list { margin-top: 4px; }
@media (max-width: 639px) { .op-pinned { padding: 14px 16px 0; } }

/* Reactieformulier on Standaarden: the fields, with a small phone-like preview of the thank-you
   screen beside them on a wide screen and under them on a narrow one. */
.thanks-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px 32px; }
@media (min-width: 1024px) { .thanks-layout { grid-template-columns: minmax(0, 1fr) 300px; align-items: start; } }
.thanks-buttons { border: 0; margin: 0; padding: 0; min-width: 0; }
.thanks-buttons legend { padding: 0; }
.thanks-preview { margin: 0; }
.thanks-preview-caption { font-size: 11.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--fg-3); margin-bottom: 8px; }
.thanks-preview-screen { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px; padding: 28px 20px 20px; border: 1px solid var(--line); border-radius: 18px; background: var(--surface); box-shadow: 0 1px 2px rgba(9,26,46,.04); }
.thanks-preview-check { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 999px; background: var(--accent-soft); color: var(--heading); }
.thanks-preview-check svg { width: 20px; height: 20px; stroke-width: 2.25; }
.thanks-preview-title { font-size: 15px; line-height: 1.35; color: var(--fg-1); }
.thanks-preview-body { margin: 0; font-size: 13px; line-height: 1.55; color: var(--fg-2); overflow-wrap: anywhere; }
.thanks-preview-button { display: block; width: 100%; margin-top: 10px; padding: 9px 12px; border-radius: 8px; background: #1877F2; color: #FFFFFF; font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }

/* Vacatures, a vacancy on both channels (channel choice decision 14): a line per ad, the vacancy's
   own cells span them. The line between the two ads is lighter than the one between vacancies, and
   hovering either line lights up the pair, so the two read as one vacancy. */
.tbl tbody tr.ad-line-first > td:not([rowspan]) { border-bottom-style: dashed; }
.tbl tbody tr.ad-line-first:has(+ tr.ad-line-next:hover),
.tbl tbody tr.ad-line-first:hover + tr.ad-line-next { background: var(--surface-2); }

/* Kanalen on the ad screen: this ad, the vacancy's ad on the other channel or the button that puts
   it there. On a phone the chip and the button drop under the text, lined up with it. */
.ad-channels-reason { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 14px; font-size: 13px; line-height: 1.55; color: var(--fg-1); }
.ad-channels-reason svg { width: 16px; height: 16px; stroke-width: 2; flex: none; margin-top: 2px; color: var(--heading); }
.ad-channels { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.ad-channel { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 12px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--card); }
.ad-channel.is-offer { border-style: dashed; background: var(--surface-2); }
.ad-channel-body { display: flex; flex-direction: column; gap: 2px; flex: 1 1 200px; min-width: 0; font-size: 13.5px; color: var(--fg-1); }
.ad-channel-end { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 0; }
@media (max-width: 639px) { .ad-channel-end { flex-basis: 100%; padding-left: 40px; } }
.ad-channel-body .nowrap { white-space: nowrap; }
