/* ─── Design tokens ────────────────────────────────────────── */
:root, [data-theme="light"] {
    --bg: #f6f7f9;
    --bg-elevated: #ffffff;
    --panel: #ffffff;
    --panel-2: #f4f5f8;
    --panel-3: #ecedf1;
    --sidebar: rgba(255, 255, 255, 0.72);
    --topbar: rgba(255, 255, 255, 0.78);
    --border: #e5e7ec;
    --border-strong: #d5d8e0;
    --text: #0f1114;
    --text-2: #33363d;
    --muted: #6b7280;
    --muted-2: #9ca3af;
    --accent: #8b2331;
    --accent-2: #711a27;
    --accent-3: #a0273a;
    --accent-soft: rgba(139, 35, 49, 0.10);
    --accent-weak: rgba(139, 35, 49, 0.06);
    --accent-ring: rgba(139, 35, 49, 0.22);
    --ok: #1f8a4a;
    --ok-soft: rgba(31, 138, 74, 0.12);
    --ok-strong: #146b38;
    --info: #2c6cb0;
    --info-soft: rgba(44, 108, 176, 0.12);
    --warn: #b86e00;
    --warn-soft: rgba(184, 110, 0, 0.14);
    --danger: #b42a2a;
    --danger-soft: rgba(180, 42, 42, 0.10);
    --shadow-xs: 0 1px 2px rgba(15, 17, 20, 0.04);
    --shadow-sm: 0 1px 3px rgba(15, 17, 20, 0.05), 0 1px 2px rgba(15, 17, 20, 0.03);
    --shadow: 0 4px 12px rgba(15, 17, 20, 0.06), 0 1px 2px rgba(15, 17, 20, 0.04);
    --shadow-lg: 0 20px 48px -12px rgba(15, 17, 20, 0.18), 0 8px 16px -8px rgba(15, 17, 20, 0.08);
    --shadow-accent: 0 6px 20px -6px rgba(139, 35, 49, 0.35);
    --radius-sm: 8px;
    --radius: 10px;
    --radius-lg: 14px;
    --radius-xl: 18px;
    --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
}

[data-theme="dark"] {
    --bg: #0a1020;
    --bg-elevated: #141b2e;
    --panel: #141b2e;
    --panel-2: #1b2338;
    --panel-3: #232d45;
    --sidebar: rgba(16, 22, 38, 0.78);
    --topbar: rgba(16, 22, 38, 0.78);
    --border: #232d45;
    --border-strong: #32405e;
    --text: #eceef2;
    --text-2: #c8ccd4;
    --muted: #8d93a0;
    --muted-2: #6d7381;
    --accent: #d4576b;
    --accent-2: #e36b7e;
    --accent-3: #c74659;
    --accent-soft: rgba(212, 87, 107, 0.14);
    --accent-weak: rgba(212, 87, 107, 0.08);
    --accent-ring: rgba(212, 87, 107, 0.30);
    --ok: #4fbf7a;
    --ok-soft: rgba(79, 191, 122, 0.14);
    --ok-strong: #6fcf95;
    --info: #6ea3dc;
    --info-soft: rgba(110, 163, 220, 0.14);
    --warn: #e2a850;
    --warn-soft: rgba(226, 168, 80, 0.14);
    --danger: #e55050;
    --danger-soft: rgba(229, 80, 80, 0.14);
    --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.5), 0 1px 2px rgba(0, 0, 0, 0.35);
    --shadow: 0 6px 18px rgba(0, 0, 0, 0.45), 0 2px 4px rgba(0, 0, 0, 0.30);
    --shadow-lg: 0 24px 52px -14px rgba(0, 0, 0, 0.70), 0 10px 20px -10px rgba(0, 0, 0, 0.45);
    --shadow-accent: 0 10px 28px -10px rgba(212, 87, 107, 0.45);
}

/* ─── Subsidiary-driven accent ─────────────────────────────── */
/* The full accent palette derives from `--accent-raw` and
   `--accent-secondary-raw`, which the server sets as inline style on
   the <html> element (the only element that survives an `hx-boost`
   body-swap intact). A small JS hook in layout.rs reads the new
   values from `<body data-accent…>` on `htmx:afterSettle` and re-
   applies them to <html>'s inline style — that's a value-change on
   a stable element, which makes the @property transitions on
   :root actually fire. Without this indirection the body-style
   block is replaced wholesale on swap and browsers treat the new
   sheet as an initial application (pop, no transition).
   The `var(…, fallback)` keeps the original static palette working
   when --accent-raw isn't set (e.g. CSS-only previews). */
:root, [data-theme="light"] {
    --accent: var(--accent-raw, #8b2331);
    --accent-2: color-mix(in oklab, var(--accent-raw, #8b2331) 82%, black 18%);
    --accent-3: color-mix(in oklab, var(--accent-raw, #8b2331) 85%, white 15%);
    --accent-soft: color-mix(in srgb, var(--accent-raw, #8b2331) 10%, transparent);
    --accent-weak: color-mix(in srgb, var(--accent-raw, #8b2331) 6%, transparent);
    --accent-ring: color-mix(in srgb, var(--accent-raw, #8b2331) 22%, transparent);
    --accent-secondary: var(--accent-secondary-raw, #475569);
    --accent-secondary-soft: color-mix(in srgb, var(--accent-secondary-raw, #475569) 10%, transparent);
    --accent-secondary-weak: color-mix(in srgb, var(--accent-secondary-raw, #475569) 6%, transparent);
}
[data-theme="dark"] {
    --accent: color-mix(in oklab, var(--accent-raw, #8b2331) 55%, white 45%);
    --accent-2: color-mix(in oklab, var(--accent-raw, #8b2331) 48%, white 52%);
    --accent-3: color-mix(in oklab, var(--accent-raw, #8b2331) 62%, white 38%);
    --accent-soft: color-mix(in srgb, var(--accent-raw, #8b2331) 14%, transparent);
    --accent-weak: color-mix(in srgb, var(--accent-raw, #8b2331) 8%, transparent);
    --accent-ring: color-mix(in srgb, var(--accent-raw, #8b2331) 30%, transparent);
    --accent-secondary: color-mix(in oklab, var(--accent-secondary-raw, #475569) 55%, white 45%);
    --accent-secondary-soft: color-mix(in srgb, var(--accent-secondary-raw, #475569) 18%, transparent);
    --accent-secondary-weak: color-mix(in srgb, var(--accent-secondary-raw, #475569) 10%, transparent);
}

/* ─── Basis ────────────────────────────────────────────────── */
* { box-sizing: border-box; }
html, body {
    margin: 0; padding: 0; min-height: 100%;
    background: var(--bg); color: var(--text);
    font: 14px/1.55 -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", "Segoe UI", sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    font-feature-settings: "cv11", "ss01";
}
html {
    transition: background-color .2s var(--ease), color .2s var(--ease);
    /* `hx-boost` body-swap resets the scroll to the top of the new
       page; without smooth scrolling that lands as a hard jump that
       masks the 0.2s accent transition. With `smooth` the jump
       becomes a glide so the colour vervaging is visible against
       a moving page. */
    scroll-behavior: smooth;
}
body {
    background-image:
        radial-gradient(1200px 700px at 90% -200px, var(--accent-soft), transparent 65%),
        radial-gradient(900px 600px at -100px 110%, var(--accent-weak), transparent 65%);
    background-attachment: fixed;
}
[data-theme="dark"] body {
    background-image:
        radial-gradient(1200px 800px at 85% -150px, rgba(139, 35, 49, 0.18), transparent 60%),
        radial-gradient(900px 700px at -100px 120%, rgba(44, 108, 176, 0.10), transparent 60%),
        radial-gradient(700px 500px at 50% 50%, rgba(139, 35, 49, 0.04), transparent 70%);
}
a { color: var(--text); text-decoration: none; transition: color .15s var(--ease); }
a:hover { color: var(--accent); }
::selection { background: var(--accent-soft); color: var(--accent); }

/* ─── App shell ──────────────────────────────────────────── */
.app {
    display: grid;
    grid-template-columns: 248px 1fr;
    min-height: 100vh;
}

/* Sidebar — expanded with footer -------------------------- */
.sidebar {
    background: var(--sidebar);
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    border-right: 1px solid var(--border);
    padding: 16px 14px 16px;
    position: sticky; top: 0; align-self: start;
    height: 100vh; overflow-y: auto;
    display: flex; flex-direction: column;
}
.sidebar .brand {
    display: flex; align-items: center; gap: 12px;
    padding: 6px 10px 18px;
}
.sidebar .brand-text { display: flex; flex-direction: column; gap: 1px; }
/* Admin-supplied logo. Fits the same 40px slot as the old coloured
   badge; the SVG's own viewBox controls its aspect ratio and we scale
   it down smoothly instead of cropping. */
.brand-logo {
    width: 40px; height: 40px;
    object-fit: contain;
    display: block;
    flex-shrink: 0;
}
.sidebar .brand-text { display: flex; flex-direction: column; gap: 1px; }
.sidebar .brand-name {
    font-weight: 700; font-size: 14.5px; color: var(--text);
    letter-spacing: -.1px;
}
.sidebar .brand-vendor {
    font-size: 10.5px; color: var(--muted);
    letter-spacing: 0.2px; font-weight: 500;
    font-style: italic;
    margin-top: -1px;
}
.sidebar .brand-sub {
    font-size: 11.5px; color: var(--muted);
    text-transform: uppercase; letter-spacing: .5px; font-weight: 600;
    margin-top: 2px;
}

/* Tenant-strip: aparte block onder het brand-blok. Toont voor welke
   dochter de admin op dit moment werkt. Visueel los van Cortex/Theremin
   zodat het duidelijk is dat dit klant-context is, niet product-context. */
.sidebar .tenant-strip {
    margin: 4px 12px 14px;
    padding: 10px 12px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.sidebar .tenant-label {
    font-size: 10.5px;
    color: var(--muted-2);
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 600;
}
.sidebar .tenant-name {
    font-size: 13px;
    font-weight: 700;
    color: var(--text);
    letter-spacing: -.1px;
    line-height: 1.2;
}
/* Collapsed-sidebar: tenant-strip volledig verbergen (geen ruimte voor
   tekst, en de subsidiary-switcher in side-footer toont de naam toch). */
:root[data-sidebar-collapsed] .sidebar .tenant-strip {
    display: none;
}

/* Auth-pagina brand: gecentreerd, naam + "by Theremin" eronder */
.auth-shell .auth-brand .brand-text .brand-name {
    font-size: 18px; font-weight: 700; color: var(--text);
}
.auth-shell .auth-brand .brand-text .brand-vendor {
    font-size: 12px; color: var(--muted); font-style: italic;
    margin-top: 1px;
}

.nav-section-label {
    font-size: 10.5px; color: var(--muted-2);
    text-transform: uppercase; letter-spacing: 1.2px; font-weight: 700;
    padding: 16px 12px 8px;
}
.nav-item {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 12px; border-radius: 10px;
    color: var(--text-2); font-size: 13.5px; font-weight: 500;
    margin-bottom: 2px;
    position: relative;
    transition: all .12s var(--ease);
    letter-spacing: -.05px;
}
.nav-item .nav-label { flex: 1; }
.nav-item:hover {
    background: var(--panel-2); color: var(--text);
}
.nav-item:active { transform: scale(0.985); }
.nav-item.active {
    background: linear-gradient(135deg, var(--accent) 0%, var(--accent-3) 100%);
    color: #fff; font-weight: 600;
    box-shadow: var(--shadow-accent), inset 0 1px 0 rgba(255,255,255,0.15);
}
/* 20×20 with stroke-width 2 gives a denser, more uniform look across
   the icon set than the old 18×18 / stroke 1.8 — every icon now has
   roughly the same visual weight, which matters in the collapsed
   sidebar where the icons stand alone with no labels next to them. */
.nav-item .icon { width: 20px; height: 20px; flex-shrink: 0; opacity: .95; }
.nav-item.active .icon { opacity: 1; }

/* Count badge on nav items (e.g. pending approvals). */
.nav-badge {
    margin-left: auto;
    background: var(--accent);
    color: #fff;
    font-size: 11px; font-weight: 700;
    padding: 1px 7px; border-radius: 999px;
    min-width: 20px; text-align: center;
    box-shadow: var(--shadow-accent);
    flex-shrink: 0;
}
.nav-item.active .nav-badge {
    background: rgba(255, 255, 255, 0.22);
    color: #fff;
    box-shadow: none;
}

/* Sidebar footer: subsidiary switcher, user chip, logout --- */
.sidebar .side-footer {
    margin-top: auto; padding-top: 14px;
    border-top: 1px solid var(--border);
    display: flex; flex-direction: column; gap: 10px;
}
.sidebar .side-switch {
    display: flex; flex-direction: column; gap: 5px;
    padding: 2px 4px;
}
.sidebar .side-switch-label {
    font-size: 10px; color: var(--muted-2);
    text-transform: uppercase; letter-spacing: 1px; font-weight: 700;
    padding: 0 8px;
}
.sidebar .side-switch select {
    appearance: none; -webkit-appearance: none;
    background: var(--panel-2); color: var(--text);
    border: 1px solid var(--border); border-radius: 9px;
    padding: 8px 30px 8px 12px;
    font: inherit; font-size: 13px; font-weight: 500;
    cursor: pointer; width: 100%;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='none' stroke='%236b7280' stroke-width='1.6' stroke-linecap='round' d='M1 1l4 4 4-4'/></svg>");
    background-repeat: no-repeat;
    background-position: right 10px center;
    transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
.sidebar .side-switch select:hover { border-color: var(--accent); }
.sidebar .side-switch select:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

/* Inline switcher in de "Overzicht"-card op het dashboard. Compactere
   horizontale variant van .side-switch zodat een user die voor
   meerdere bedrijven werkt zonder zijbalk-omweg van context kan
   wisselen. */
.dash-switcher {
    display: inline-flex; align-items: center; gap: 8px;
    cursor: pointer;
}
.dash-switcher-label {
    font-size: 10px; color: var(--muted-2);
    text-transform: uppercase; letter-spacing: 1px; font-weight: 700;
}
.dash-switcher select {
    appearance: none; -webkit-appearance: none;
    background: var(--panel-2); color: var(--text);
    border: 1px solid var(--border); border-radius: 9px;
    padding: 6px 28px 6px 10px;
    font: inherit; font-size: 13px; font-weight: 500;
    cursor: pointer;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='none' stroke='%236b7280' stroke-width='1.6' stroke-linecap='round' d='M1 1l4 4 4-4'/></svg>");
    background-repeat: no-repeat;
    background-position: right 9px center;
    transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
.dash-switcher select:hover { border-color: var(--accent); }
.dash-switcher select:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

.sidebar .side-user {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 10px;
    color: inherit; text-decoration: none;
    transition: border-color .12s var(--ease), background .12s var(--ease);
}
.sidebar a.side-user:hover {
    border-color: var(--accent); background: var(--accent-weak);
}
.sidebar .side-user .side-avatar {
    width: 32px; height: 32px; border-radius: 10px;
    background: linear-gradient(135deg, var(--accent) 0%, var(--accent-3) 100%);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .5px;
    flex-shrink: 0;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.15);
}
.sidebar .side-user .side-user-meta {
    display: flex; flex-direction: column; min-width: 0; flex: 1;
}
.sidebar .side-user .side-user-email {
    font-size: 12.5px; font-weight: 600; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sidebar .side-user .side-user-role {
    font-size: 10.5px; color: var(--muted); font-weight: 600;
    text-transform: uppercase; letter-spacing: .6px;
}

.sidebar .side-logout button {
    width: 100%; justify-content: center;
    background: transparent; border: 1px solid var(--border);
    color: var(--muted); box-shadow: none;
    padding: 8px 12px; font-size: 12.5px;
}
.sidebar .side-logout button:hover {
    background: var(--panel-2); color: var(--danger); border-color: var(--danger);
    transform: none;
}

/* Topbar --------------------------------------------------- */
.topbar {
    display: flex; align-items: center; gap: 16px;
    padding: 14px 32px; min-height: 64px;
    background: var(--topbar);
    backdrop-filter: saturate(180%) blur(18px);
    -webkit-backdrop-filter: saturate(180%) blur(18px);
    border-bottom: 1px solid var(--border);
    position: sticky; top: 0; z-index: 10;
}
.breadcrumb {
    display: flex; align-items: center; gap: 10px;
    font-size: 13px; color: var(--muted);
}
.breadcrumb .crumb-badge {
    width: 24px; height: 24px; border-radius: 7px;
    background: linear-gradient(135deg, var(--accent-soft), var(--accent-weak));
    color: var(--accent);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 10px; letter-spacing: .4px;
    border: 1px solid var(--accent-weak);
}
.breadcrumb .crumb-sep { color: var(--muted-2); font-weight: 300; }
.breadcrumb .crumb-current { color: var(--text); font-weight: 600; font-size: 14px; letter-spacing: -.1px; }
.breadcrumb .crumb-back {
    display: inline-flex; align-items: center; gap: 4px;
    color: var(--muted); font-size: 13px; text-decoration: none;
    padding: 4px 8px; border-radius: 6px;
    transition: color .12s var(--ease), background .12s var(--ease);
}
.breadcrumb .crumb-back:hover { color: var(--text); background: var(--panel-2); }
.breadcrumb .crumb-back svg { width: 14px; height: 14px; }

.topbar .right {
    margin-left: auto; display: flex; align-items: center; gap: 10px;
}
.topbar .right .token-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 12px; border-radius: 999px;
    background: var(--accent-soft); color: var(--accent);
    border: 1px solid transparent;
    font-size: 12.5px; font-weight: 600; text-decoration: none;
    transition: background .12s var(--ease), border-color .12s var(--ease);
}
.topbar .right .token-chip:hover {
    background: var(--accent-weak); border-color: var(--accent);
}
.topbar .right .token-chip svg { width: 14px; height: 14px; }
.topbar .right .token-chip-value { font-variant-numeric: tabular-nums; }
.topbar .right .token-chip-label { color: var(--muted); font-weight: 500; }
/* Subsidiary switcher in the topbar */
.topbar .right form.inline select {
    appearance: none; -webkit-appearance: none;
    background: var(--panel-2); color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: 8px; padding: 7px 30px 7px 12px;
    font: inherit; font-size: 12.5px; font-weight: 500;
    cursor: pointer;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='none' stroke='%236b7280' stroke-width='1.6' stroke-linecap='round' d='M1 1l4 4 4-4'/></svg>");
    background-repeat: no-repeat;
    background-position: right 10px center;
    transition: border-color .12s var(--ease);
}
.topbar .right form.inline select:hover { border-color: var(--accent); }
.topbar .right form.inline select:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

/* Theme toggle --------------------------------------------- */
.theme-toggle {
    width: 36px; height: 36px; padding: 0;
    background: var(--panel-2); border: 1px solid var(--border); border-radius: 9px;
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer; color: var(--text); position: relative; overflow: hidden;
    line-height: 1;
    transition: all .15s var(--ease);
}
.theme-toggle:hover {
    border-color: var(--accent); color: var(--accent); background: var(--panel);
    transform: translateY(-1px); box-shadow: var(--shadow-sm);
}
.theme-toggle .theme-icon {
    font-size: 15px; line-height: 1; position: absolute;
    transition: transform .3s var(--ease), opacity .15s ease;
}
[data-theme="light"] .theme-toggle .sun  { transform: translateY(0);    opacity: 1; }
[data-theme="light"] .theme-toggle .moon { transform: translateY(28px); opacity: 0; }
[data-theme="dark"]  .theme-toggle .sun  { transform: translateY(-28px); opacity: 0; }
[data-theme="dark"]  .theme-toggle .moon { transform: translateY(0);     opacity: 1; }

/* User chip ------------------------------------------------ */
.user-chip {
    display: flex; align-items: center; gap: 8px;
    padding: 7px 12px; border-radius: 9px; background: var(--panel-2);
    border: 1px solid var(--border);
    font-size: 12px; color: var(--muted);
}
.user-chip strong { color: var(--text); font-weight: 600; }

/* Content area --------------------------------------------- */
.content { padding: 32px 40px 72px; max-width: 1180px; margin: 0 auto; }
.content > .page-header { margin-bottom: 24px; }
.page-header h1 {
    margin: 0 0 4px; font-size: 26px; font-weight: 700;
    letter-spacing: -.5px; line-height: 1.2;
}
.page-header .page-sub { color: var(--muted); font-size: 14px; margin: 0; }

/* Hero block (dashboard welcome) --------------------------- */
.hero {
    padding: 8px 0 20px;
    margin-bottom: 18px;
}
.hero-kicker {
    margin: 0 0 6px; font-size: 11px; color: var(--muted);
    text-transform: uppercase; letter-spacing: 1.2px; font-weight: 700;
}
.hero-title {
    margin: 0 0 10px;
    font-size: clamp(34px, 4.2vw, 48px);
    font-weight: 700;
    letter-spacing: -1.2px;
    line-height: 1.1;
    background: linear-gradient(135deg, var(--text) 0%, var(--muted) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}
.hero-sub {
    margin: 0; max-width: 640px;
    font-size: 14.5px; color: var(--muted); line-height: 1.6;
}

/* Tile grid for dashboard quick actions -------------------- */
.tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 14px;
    margin: 0 0 18px;
}
.tile {
    display: flex; align-items: flex-start; gap: 14px;
    padding: 18px 20px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xs);
    color: var(--text);
    transition: all .15s var(--ease);
    position: relative;
    overflow: hidden;
}
.tile::before {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(135deg, var(--accent-weak), transparent 60%);
    opacity: 0; transition: opacity .2s var(--ease);
    pointer-events: none;
}
.tile:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow);
    border-color: var(--border-strong);
    color: var(--text);
}
.tile:hover::before { opacity: 1; }
.tile-accent {
    background: linear-gradient(135deg, var(--accent-soft) 0%, var(--panel) 70%);
    border-color: var(--accent-weak);
}
.tile-accent:hover { box-shadow: var(--shadow), var(--shadow-accent); }

.tile-badge {
    flex-shrink: 0;
    width: 44px; height: 44px; border-radius: 12px;
    display: flex; align-items: center; justify-content: center;
    position: relative; z-index: 1;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14);
}
.tile-badge.t-accent {
    background: linear-gradient(135deg, var(--accent) 0%, var(--accent-3) 100%);
    color: #fff;
}
.tile-badge.t-info {
    background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
    color: #fff;
}
.tile-badge.t-ok {
    background: linear-gradient(135deg, #22c77e 0%, #16a063 100%);
    color: #fff;
}
.tile-badge.t-warn {
    background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
    color: #fff;
}
.tile-body { display: flex; flex-direction: column; gap: 4px; position: relative; z-index: 1; }
.tile-title {
    margin: 0; font-size: 15px; font-weight: 700; color: var(--text);
    letter-spacing: -.1px;
    text-transform: none; /* override h3 default */
}
.tile-sub { margin: 0; font-size: 12.5px; color: var(--muted); line-height: 1.45; }

h1 { margin: 0 0 12px; font-size: 22px; font-weight: 700; letter-spacing: -.3px; }
h2 { margin: 0 0 12px; font-size: 16px; font-weight: 600; letter-spacing: -.1px; }
h3 { margin: 20px 0 10px; font-size: 10.5px; color: var(--muted); text-transform: uppercase; letter-spacing: 1px; font-weight: 700; }
.sub, .hint { color: var(--muted); margin: 0 0 14px; font-size: 13px; line-height: 1.55; }
.muted { color: var(--muted); }
code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px; color: var(--text-2);
    background: var(--panel-2); padding: 1.5px 6px; border-radius: 4px;
    border: 1px solid var(--border);
}

.notice {
    background: var(--ok-soft); color: var(--ok-strong);
    padding: 12px 16px; border-radius: 10px; margin: 0 0 16px;
    font-size: 13px; font-weight: 500;
    border: 1px solid rgba(31, 138, 74, 0.2);
}
.error {
    background: var(--danger-soft); color: var(--danger);
    padding: 12px 16px; border-radius: 10px; margin: 0 0 16px;
    font-size: 13px; font-weight: 500;
    border: 1px solid rgba(180, 42, 42, 0.2);
}

/* Cards ---------------------------------------------------- */
.card {
    background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-lg);
    /* Méér ruimte rechts dan vroeger (was 22px 24px) — input-velden
       liepen anders zo goed als tegen de rechterrand. Op kleinere
       schermen zakken we terug naar het oorspronkelijke compactere
       formaat. */
    padding: 22px 28px 22px 24px; margin-bottom: 18px; box-shadow: var(--shadow-xs);
    transition: box-shadow .15s var(--ease), transform .1s var(--ease);
}
@media (max-width: 720px) {
    .card { padding: 18px 18px 18px 16px; }
}
.card-narrow { max-width: 600px; }
.card-row {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    margin-bottom: 12px;
}
.card-row h1, .card-row h2 { margin: 0; }

/* Item cards with colored left border ---------------------- */
.item-card {
    background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-lg);
    border-left: 3px solid var(--border-strong);
    padding: 18px 20px; margin-bottom: 12px; box-shadow: var(--shadow-xs);
    transition: all .15s var(--ease);
}
.item-card:hover {
    box-shadow: var(--shadow);
    transform: translateY(-1px);
    border-color: var(--border-strong);
}
.item-card.b-ok     { border-left-color: var(--ok); }
.item-card.b-info   { border-left-color: var(--info); }
.item-card.b-warn   { border-left-color: var(--warn); }
.item-card.b-accent { border-left-color: var(--accent); }

.item-card .item-head {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
    margin-bottom: 6px;
}
.item-card .item-meta {
    display: flex; align-items: center; gap: 8px;
    font-size: 10.5px; color: var(--muted); text-transform: uppercase; letter-spacing: 1px; font-weight: 700;
}
.item-card .item-title {
    font-size: 15.5px; font-weight: 600; color: var(--text);
    margin: 2px 0 6px; line-height: 1.35; letter-spacing: -.1px;
}
.item-card .item-title:hover { color: var(--accent); }
.item-card .item-sub { font-size: 13px; color: var(--muted); margin: 0 0 8px; }

/* Grid of item cards --------------------------------------- */
.grid-cards {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 14px;
}

/* Buttons -------------------------------------------------- */
button, .button {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    background: var(--panel); color: var(--text);
    border: 1px solid var(--border-strong);
    padding: 8px 14px; border-radius: 9px; cursor: pointer;
    font: inherit; font-size: 13px; font-weight: 500;
    letter-spacing: -.05px;
    transition: all .12s var(--ease);
    box-shadow: var(--shadow-xs);
    user-select: none;
}
button:hover, .button:hover {
    background: var(--panel-2); border-color: var(--muted-2); color: var(--text);
    transform: translateY(-1px); box-shadow: var(--shadow-sm);
}
button:active, .button:active { transform: translateY(0); }

/* Supporting-action buttons (non-primary / danger / ghost) pick up the
   admin-set secondary accent — subtle tint on hover so brand identity
   carries across without making every button look "coloured". */
button:not(.primary):not(.danger):not(.ghost):hover,
.button:not(.primary):not(.danger):not(.ghost):hover {
    border-color: var(--accent-secondary);
    color: var(--accent-secondary);
    background: var(--accent-secondary-weak);
}
button:not(.primary):not(.danger):not(.ghost):focus-visible,
.button:not(.primary):not(.danger):not(.ghost):focus-visible {
    outline: none;
    border-color: var(--accent-secondary);
    box-shadow: 0 0 0 3px var(--accent-secondary-soft);
}
button.primary, .button.primary {
    background: linear-gradient(135deg, var(--accent) 0%, var(--accent-3) 100%);
    border-color: transparent; color: #fff; font-weight: 600;
    box-shadow: var(--shadow-accent);
}
button.primary:hover, .button.primary:hover {
    background: linear-gradient(135deg, var(--accent-2) 0%, var(--accent) 100%);
    border-color: transparent; color: #fff;
    transform: translateY(-1px);
    box-shadow: var(--shadow-accent), 0 2px 8px rgba(0, 0, 0, 0.08);
}
button.danger, .button.danger {
    color: var(--danger); border-color: var(--border-strong); background: var(--panel);
}
button.danger:hover {
    background: var(--danger-soft); border-color: var(--danger); color: var(--danger);
}
button.ghost {
    background: transparent; border-color: transparent; color: var(--muted);
    box-shadow: none;
}
button.ghost:hover { background: var(--panel-2); color: var(--text); box-shadow: none; }

.btn-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

/* Inline memberships toggle in the team table — the <details> collapses
   to match the height of the sibling "Verwijderen" button when closed,
   and expands to full row width when opened. The default disclosure
   triangle is suppressed so the summary reads as a normal button. */
.user-memberships { padding: 0; background: transparent; border: none; }
.user-memberships[open] { flex: 1 1 100%; padding: 10px 12px;
    background: var(--panel-2); border: 1px solid var(--border-strong); }
.user-memberships > summary.button {
    margin: 0; cursor: pointer; list-style: none;
}
.user-memberships > summary.button::-webkit-details-marker { display: none; }
.user-memberships > summary.button::marker { content: ""; }

/* Row-action cells inside tables (planning, drafts, etc.). A flex
   container keeps multiple buttons on the same visual axis with a
   predictable gap instead of relying on whitespace between inline
   elements, and gives each action a matching min-width so "Opstellen"
   and "Beheren" feel like the same control — just different intent. */
.actions-cell { white-space: nowrap; vertical-align: middle; }
.actions-inline {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}
.actions-inline > .button,
.actions-inline > form.inline > button {
    min-width: 96px;
}
/* Nested form wrappers shouldn't disturb the flex layout. */
.actions-inline > form.inline { display: inline-flex; margin: 0; }

/* Forms ---------------------------------------------------- */
/* `form.vstack` is de standaard wrapper, maar genest binnen een
   <details>/uitgebreide-briefing-blok hebben we soms enkel een
   `div.vstack` — die telt voor de form-styling ook mee zodat de
   inputs daar dezelfde max-width + padding krijgen en niet helemaal
   tegen de rechterrand van de card botsen. */
form.vstack, .form-fields.vstack { display: flex; flex-direction: column; gap: 16px; }
form.vstack label,
.form-fields.vstack label {
    display: flex; flex-direction: column; gap: 7px;
    font-size: 12px; color: var(--text-2); font-weight: 600;
    letter-spacing: .1px;
}
form.vstack input[type="text"],
form.vstack input[type="email"],
form.vstack input[type="number"],
form.vstack input[type="date"],
form.vstack input[type="time"],
form.vstack input[type="week"],
form.vstack input[type="url"],
form.vstack input[type="search"],
form.vstack input[type="password"],
form.vstack input[type="tel"],
form.vstack input[type="file"],
form.vstack select,
form.vstack textarea,
.form-fields.vstack input[type="text"],
.form-fields.vstack input[type="email"],
.form-fields.vstack input[type="number"],
.form-fields.vstack input[type="date"],
.form-fields.vstack input[type="time"],
.form-fields.vstack input[type="url"],
.form-fields.vstack input[type="tel"],
.form-fields.vstack textarea {
    background: var(--bg-elevated); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: 9px;
    padding: 12px 16px; font-size: 14px; font: inherit;
    font-weight: 400;
    /* Predictable sizing so max-width + siblings align to the pixel —
       fixes the "Kleur" swatch + hex text input height mismatch and
       keeps 2-column form layouts from drifting. */
    box-sizing: border-box;
    width: 100%;
    /* Keep single-line inputs at a readable length on wide screens;
       textarea gets its own rule below so long copy can use the space. */
    max-width: 520px;
    min-height: 46px;
    /* Force the browser-native form-control theme to follow the page
       theme rather than the OS setting — without this, a user on macOS
       dark mode sees a black week/date picker even on our light theme. */
    color-scheme: light;
    transition: border-color .12s var(--ease), box-shadow .12s var(--ease), background-color .12s var(--ease);
}
/* Textareas can breathe further — content is multi-line so a wider box
   actually helps. Keep min-width aligned with single-line inputs. */
form.vstack textarea,
.form-fields.vstack textarea { max-width: 720px; min-height: 110px; }
[data-theme="dark"] form.vstack input[type="text"],
[data-theme="dark"] form.vstack input[type="email"],
[data-theme="dark"] form.vstack input[type="number"],
[data-theme="dark"] form.vstack input[type="date"],
[data-theme="dark"] form.vstack input[type="week"],
[data-theme="dark"] form.vstack input[type="url"],
[data-theme="dark"] form.vstack input[type="search"],
[data-theme="dark"] form.vstack input[type="password"],
[data-theme="dark"] form.vstack input[type="tel"],
[data-theme="dark"] form.vstack input[type="file"],
[data-theme="dark"] form.vstack select,
[data-theme="dark"] form.vstack textarea {
    color-scheme: dark;
}
/* Form.vstack matcht de globale select-padding zodat de chevron op
   exact dezelfde positie staat als elders in het platform. */
form.vstack select { padding-right: 38px; }
form.vstack input::placeholder,
form.vstack textarea::placeholder { color: var(--muted-2); }
form.vstack textarea { font-family: inherit; resize: vertical; min-height: 110px; line-height: 1.55; }
form.vstack input:hover, form.vstack select:hover, form.vstack textarea:hover {
    border-color: var(--muted-2);
}
form.vstack input:focus, form.vstack select:focus, form.vstack textarea:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 4px var(--accent-ring);
    background: var(--panel);
}
form.vstack .check {
    flex-direction: row; align-items: center; gap: 8px;
    font-size: 13px; color: var(--text); font-weight: 400;
    cursor: pointer;
}
form.vstack .check input { margin: 0; accent-color: var(--accent); }
form.vstack .actions {
    display: flex; gap: 10px; align-items: center;
    margin-top: 6px; padding-top: 16px; border-top: 1px solid var(--border);
}
/* Split-actions: primary + back on the left, destructive on the right.
   Used on admin edit pages where Save and Delete share a row. */
form.vstack .actions.actions-split { justify-content: space-between; flex-wrap: wrap; }
.actions-split .actions-left { display: flex; gap: 10px; align-items: center; }
form.inline { display: inline; margin: 0; }

/* In-row selects (status-dropdowns inside a table cell, bedrijf-switcher,
   etc.). By default a bare <select> picks up the OS theme, which in
   macOS dark mode paints the control black even when the page is light.
   Give them the same neutral chrome as the buttons next to them so a row
   with [select] + [Bewerken] + [Verwijderen] reads as one coherent strip. */
form.inline select,
form.inline input[type="text"],
form.inline input[type="number"],
form.inline input[type="search"],
form.inline input[type="date"],
form.inline input[type="email"],
form.inline input[type="url"],
.btn-row select {
    background: var(--bg-elevated); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: 8px;
    padding: 7px 12px; font: inherit; font-size: 13px;
    color-scheme: light;
    transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
form.inline select,
.btn-row select { padding-right: 30px; cursor: pointer; }
/* In een `.btn-row` rij wil je dat een select naast Bewerken/
   Verwijderen exact dezelfde maat heeft als de knoppen — zelfde
   padding, radius, font-weight, font-size en subtiele shadow. De
   `min-height: 0` wint van de globale `select:not(.theme-toggle)`
   regel die 46px afdwingt; we laten de hoogte volgen uit padding +
   line-height zodat het 1-op-1 matcht met de naast-knoppen. */
.btn-row > select,
.btn-row > form.inline > select {
    padding: 8px 30px 8px 14px;
    border-radius: 9px;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: -.05px;
    /* `<select>` negeert `line-height` op user-agent niveau in
       sommige browsers — daarom expliciete `min-height: 38px` zodat
       hij hetzelfde rendert als de naast-staande knoppen (8px pad +
       20.15px line-height + 2px border = 38px). */
    min-height: 38px;
    line-height: 1.55;
    box-shadow: var(--shadow-xs);
}
[data-theme="dark"] form.inline select,
[data-theme="dark"] form.inline input,
[data-theme="dark"] .btn-row select { color-scheme: dark; }
form.inline select:hover,
form.inline input:hover,
.btn-row select:hover { border-color: var(--muted-2); }
form.inline select:focus,
form.inline input:focus,
.btn-row select:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

/* Section card with stacked content that needs an even 14px rhythm
   between direct children — used on /profile, /admin/settings, and
   other pages where a card mixes labels/details/forms/notices that
   would otherwise collide. Opt in per card. */
section.card.card-stack {
    display: flex; flex-direction: column; gap: 14px;
}
section.card.card-stack > h1:first-child,
section.card.card-stack > h2:first-child,
section.card.card-stack > h3:first-child { margin: 0; }

/* Read-only "copy this value" input — feed URL, webhook endpoint, etc.
   Styled like a proper form control so it doesn't inherit the OS
   dark-mode default chrome (which renders as dark-on-dark on macOS). */
.input-copy {
    width: 100%;
    background: var(--bg-elevated); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: 9px;
    padding: 10px 14px; font: inherit; font-size: 13px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    color-scheme: light;
    cursor: text;
    transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
[data-theme="dark"] .input-copy { color-scheme: dark; }
.input-copy:hover { border-color: var(--muted-2); }
.input-copy:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

/* Orange/amber attention callout — use for messages that need to stand
   out without being destructive (e.g. "pending review", "token-review"). */
.notice-warn, .pill.pill-warn {
    background: color-mix(in srgb, #f59e0b 14%, transparent);
    border: 1px solid color-mix(in srgb, #f59e0b 40%, transparent);
    color: #b45309;
}
[data-theme="dark"] .notice-warn,
[data-theme="dark"] .pill.pill-warn {
    background: color-mix(in srgb, #f59e0b 20%, transparent);
    border-color: color-mix(in srgb, #f59e0b 55%, transparent);
    color: #fbbf24;
}

/* Inline row-expand disclosure — used inside a table cell to keep the
   first-view quiet while still letting the user open a long description
   without leaving the page. Intentionally minimal so the toggle reads
   as secondary text next to the title, not as a button. */
details.row-expand {
    margin-top: 4px;
}
details.row-expand > summary {
    cursor: pointer;
    list-style: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--muted);
    font-size: 12px;
    font-weight: 500;
    user-select: none;
}
details.row-expand > summary::-webkit-details-marker { display: none; }
details.row-expand > summary::marker { content: ""; }
details.row-expand > summary::before {
    content: "▸";
    font-size: 9px;
    transition: transform .12s var(--ease);
    display: inline-block;
}
details.row-expand[open] > summary::before {
    transform: rotate(90deg);
}
details.row-expand > summary:hover { color: var(--text); }
details.row-expand[open] > summary { color: var(--text); }
/* Twee labels staan naast elkaar in de summary; de open-state wisselt
   welk van de twee zichtbaar is. Eén DOM-knop, twee teksten. */
details.row-expand .row-expand-hide { display: none; }
details.row-expand[open] .row-expand-show { display: none; }
details.row-expand[open] .row-expand-hide { display: inline; }
details.row-expand > .row-expand-body {
    margin-top: 6px;
    color: var(--muted);
    font-size: 13px;
    white-space: pre-wrap;
    max-width: 640px;
}

/* Sortable table headers (table_sort.js). `<th data-sort="text|number">`
   gets a pointer cursor + a subtle arrow that fills in once a sort is
   active. Non-sortable headers (e.g. actions column) are untouched. */
th.sortable {
    cursor: pointer;
    user-select: none;
    position: relative;
    padding-right: 22px;
}
th.sortable:hover { color: var(--text); }
th.sortable::after {
    content: "";
    position: absolute;
    right: 8px; top: 50%;
    width: 0; height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-bottom: 5px solid var(--muted-2);
    opacity: .35;
    transform: translateY(-70%);
    transition: opacity .12s var(--ease), transform .12s var(--ease);
}
th.sortable:hover::after { opacity: .65; }
th.sortable[aria-sort="ascending"]::after {
    opacity: 1;
    border-bottom-color: var(--accent);
}
th.sortable[aria-sort="descending"]::after {
    opacity: 1;
    border-bottom-color: var(--accent);
    transform: translateY(-30%) rotate(180deg);
}
th.sortable:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

/* Right-align the last actions column inside generic tables so action
   buttons (Bewerken / Planning / Verwijderen) hug the right edge. Opt
   in via `td.td-actions` / `th.th-actions` on both cells. */
th.th-actions, td.td-actions { text-align: right; }

/* Live-filter bar above a table — client-side JS (table_filter.js)
   wires a <input data-filter-table="#id"> to hide non-matching rows. */
.table-filter {
    display: flex; align-items: center; gap: 12px;
    margin-bottom: 12px; flex-wrap: wrap;
}
.table-filter input[type="search"] {
    flex: 1 1 260px; max-width: 420px;
    background: var(--bg-elevated); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: 8px;
    padding: 9px 14px; font: inherit; font-size: 13.5px;
    color-scheme: light;
    transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
[data-theme="dark"] .table-filter input[type="search"] { color-scheme: dark; }
.table-filter input[type="search"]:hover { border-color: var(--muted-2); }
.table-filter input[type="search"]:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.table-filter [data-filter-count-for] {
    color: var(--muted); font-size: 12px;
    white-space: nowrap;
}

/* Tables --------------------------------------------------- */
table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
th, td { text-align: left; padding: 13px 12px; border-bottom: 1px solid var(--border); vertical-align: middle; }
th {
    color: var(--muted); font-weight: 600; text-transform: uppercase;
    font-size: 10.5px; letter-spacing: .8px;
    position: sticky; top: 0;
    background: var(--panel); z-index: 1;
    white-space: nowrap;
}
tr:last-child td { border-bottom: 0; }
tbody tr {
    transition: background-color .1s var(--ease);
}
tbody tr:hover td { background: var(--panel-2); }
tr.row-accent td { background: var(--accent-soft); }
tr.row-accent:hover td { background: var(--accent-soft); filter: brightness(0.97); }
td.kw, td code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
td.kw { max-width: 280px; overflow-wrap: anywhere; }

/* Status pills --------------------------------------------- */
.pill {
    display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 999px;
    background: var(--panel-2); color: var(--muted);
    font-size: 11px; font-weight: 600; letter-spacing: .3px;
    border: 1px solid var(--border);
    white-space: nowrap;
}
.pill.status-ready     { background: var(--info-soft); color: var(--info); border-color: transparent; }
.pill.status-chosen    { background: var(--warn-soft); color: var(--warn); border-color: transparent; }
.pill.status-published { background: var(--ok-soft); color: var(--ok-strong); border-color: transparent; }
.pill.pill-accent      { background: var(--accent-soft); color: var(--accent); border-color: transparent; }

/* Top-of-page progress bar --------------------------------- */
#topbar-progress {
    position: fixed; top: 0; left: 0; right: 0; height: 3px;
    pointer-events: none; z-index: 9999;
    opacity: 0; transition: opacity .15s ease;
    background: transparent;
}
#topbar-progress.active { opacity: 1; }
#topbar-progress .bar {
    height: 100%; width: 30%;
    background: linear-gradient(90deg, transparent 0%, var(--accent) 50%, transparent 100%);
    animation: topbar-slide 1.4s ease-in-out infinite;
    filter: drop-shadow(0 0 6px var(--accent-ring));
}
@keyframes topbar-slide {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(400%); }
}
#topbar-progress-label {
    position: fixed; top: 14px; left: 50%; transform: translateX(-50%);
    background: var(--panel); color: var(--text); border: 1px solid var(--border);
    padding: 7px 16px; border-radius: 999px; font-size: 12px; font-weight: 600;
    box-shadow: var(--shadow-lg); z-index: 9998;
    opacity: 0; transform: translate(-50%, -10px);
    transition: opacity .2s var(--ease), transform .2s var(--ease);
    pointer-events: none;
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
}
#topbar-progress-label.active { opacity: 1; transform: translate(-50%, 0); }
button[type=submit]:disabled, input[type=submit]:disabled {
    opacity: .7; cursor: progress;
}

/* Option cards on draft page ------------------------------- */
.option {
    border-left: 3px solid var(--border-strong);
}
.option.picked { border-left-color: var(--accent); }
.option h2 {
    color: var(--muted); font-size: 10.5px; text-transform: uppercase;
    letter-spacing: 1px; margin-bottom: 10px; font-weight: 700;
}
.option .body,
.option pre.body {
    display: block;
    background: var(--panel-2); color: var(--text);
    padding: 16px 18px; border-radius: 10px;
    white-space: pre-wrap;
    word-break: break-word;
    overflow-wrap: anywhere;
    font-family: inherit; font-size: 14px; line-height: 1.65;
    margin: 0 0 10px; border: 1px solid var(--border);
    width: 100%;
    max-width: 100%;
    min-width: 0;
    box-sizing: border-box;
}
/* Safety net: cards may contain very long lines (post bodies, URLs). Let
   the card itself shrink below its intrinsic width so `.content`'s
   max-width/overflow-x cap actually clips anything that overflows. Don't
   cascade `overflow-wrap: anywhere` here — that would break words inside
   buttons and table cells. Only the elements that explicitly opt in (see
   `.option .body`) do aggressive word-breaking. */
.card { min-width: 0; }
/* `overflow-x: clip` instead of `hidden` — same visual containment
   but no scroll context, which means descendant `position: sticky`
   actually sticks. (`hidden` creates a scroll container even when
   nothing scrolls, and that disables sticky on every child.) */
.content { min-width: 0; overflow-x: clip; }

/* Never break the label across lines inside a button. */
button, .button { white-space: nowrap; }

/* Periode-kolom (jaar + weeknummer) past altijd op één regel. */
table td:first-child, table th:first-child { white-space: nowrap; }
.option .picked-label { color: var(--ok-strong); font-weight: 600; font-size: 13px; }
.published { border-left: 3px solid var(--ok); }
.published code { color: var(--accent); }

/* Image preview ------------------------------------------- */
img.preview {
    max-width: 100%; max-height: 280px; border-radius: 12px;
    border: 1px solid var(--border); margin: 12px 0;
    background: var(--panel-2);
    box-shadow: var(--shadow-sm);
}

/* Empty state --------------------------------------------- */
.empty {
    padding: 48px 24px; text-align: center; color: var(--muted);
    border: 1px dashed var(--border-strong); border-radius: 14px;
    background: var(--panel-2); font-size: 14px; line-height: 1.6;
}

/* Auth pages ---------------------------------------------- */
.auth-shell {
    min-height: 100vh;
    display: flex; align-items: center; justify-content: center;
    padding: 40px 20px; background: var(--bg);
    background-image:
        radial-gradient(800px 500px at 50% -100px, var(--accent-soft), transparent 70%),
        radial-gradient(600px 400px at 50% 120%, var(--accent-weak), transparent 70%);
}
.auth-shell .auth-box {
    width: 100%; max-width: 440px;
    background: var(--panel); border: 1px solid var(--border);
    border-radius: var(--radius-xl); box-shadow: var(--shadow-lg);
    padding: 32px 32px 28px;
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
}
.auth-shell .auth-brand {
    display: flex; align-items: center; gap: 14px; margin-bottom: 20px;
}
.auth-shell .auth-brand .brand-logo {
    /* A touch larger than the sidebar version — it's the only branding
       element on the sign-in screen, so give it more presence. */
    width: 56px; height: 56px;
}
.auth-shell .auth-brand .brand-text {
    font-weight: 700; color: var(--text); font-size: 16px; letter-spacing: -.2px;
}

/* Details/summary (collapsibles) -------------------------- */
/* Skip if details already has its own style class like .card. */
details:not(.card) {
    background: var(--panel-2); border: 1px solid var(--border);
    border-radius: 10px; padding: 12px 14px;
    transition: border-color .12s var(--ease);
}
details:not(.card)[open] { border-color: var(--border-strong); background: var(--panel); }
details summary {
    cursor: pointer; font-weight: 600; font-size: 13px; color: var(--text);
    list-style: none; display: flex; align-items: center; gap: 8px;
}
details summary::-webkit-details-marker { display: none; }
details summary::before {
    content: "›"; display: inline-block; transition: transform .15s var(--ease);
    color: var(--muted); font-size: 16px; line-height: 1; font-weight: 700;
}
details[open] > summary::before { transform: rotate(90deg); }

/* Misc ----------------------------------------------------- */
.hstack { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.hstack.between { justify-content: space-between; }
/* Primary-knoppen die direct in een title-row staan (typisch
   "+ Nieuwe X" naast een h2) krijgen een gedempte drop-shadow en
   iets compactere padding. Anders 'zweven' ze visueel boven de
   card uit door de heavy box-shadow + standaard button-padding. */
.hstack.between > button.primary,
.hstack.between > .button.primary,
.hstack.between > form.inline > button.primary,
.hstack.between > form.inline > .button.primary {
    box-shadow: none;
    padding: 8px 14px;
    font-size: 13px;
}

/* ---------------------------------------------------------------
   Spacing — semantische regels + smalle utility-set.
   Eerst de semantische regels (kosten geen markup-aanpassing,
   vervangen 100+ inline `style="margin:0"` cases): kop-elementen
   die direct in een flex-rij zitten verliezen hun default browser-
   margin, zodat de rij netjes uitlijnt zonder `style="margin:0"`
   per heading. Idem voor de eerste heading in een `.card`.
   --------------------------------------------------------------- */
.hstack > h1, .hstack > h2, .hstack > h3, .hstack > h4,
.hstack > p,
.between > h1, .between > h2, .between > h3, .between > h4,
.between > p {
    margin: 0;
}
.card > h1:first-child, .card > h2:first-child, .card > h3:first-child {
    margin-top: 0;
}

/* Utility-classes voor de losse offsets die niet onder een
   semantische regel passen. Schaal volgt 4/8/12/18/24px om de
   bestaande inline-waarden in één-op-één te kunnen vervangen. */
.m-0  { margin: 0; }
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: 4px; }
.mt-2 { margin-top: 8px; }
.mt-3 { margin-top: 12px; }
.mt-4 { margin-top: 18px; }
.mt-5 { margin-top: 24px; }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: 4px; }
.mb-2 { margin-bottom: 8px; }
.mb-3 { margin-bottom: 12px; }
.mb-4 { margin-bottom: 18px; }
.mb-5 { margin-bottom: 24px; }

/* Scrollbar — thin, modern ---------------------------------- */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--border-strong); border-radius: 999px;
    border: 2px solid var(--bg);
}
::-webkit-scrollbar-thumb:hover { background: var(--muted-2); }

/* AI-inspiration modal shown once per draft ----------------- */
.ai-modal-backdrop {
    position: fixed; inset: 0; z-index: 10000;
    background: rgba(8, 10, 16, 0.55);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    display: flex; align-items: center; justify-content: center;
    padding: 24px;
    animation: ai-modal-fade .18s var(--ease);
}
@keyframes ai-modal-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.ai-modal {
    background: var(--panel); border: 1px solid var(--border);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
    max-width: 480px; width: 100%;
    padding: 28px;
    animation: ai-modal-rise .2s var(--ease);
}
@keyframes ai-modal-rise {
    from { transform: translateY(12px) scale(.98); opacity: 0; }
    to   { transform: translateY(0) scale(1); opacity: 1; }
}
.ai-modal-icon {
    width: 44px; height: 44px; border-radius: 12px;
    background: linear-gradient(135deg, var(--warn), #d97706);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-weight: 900; font-size: 22px; line-height: 1;
    margin-bottom: 14px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.2);
}
.ai-modal h2 {
    margin: 0 0 10px; font-size: 18px; font-weight: 700;
    letter-spacing: -.3px; color: var(--text);
}
.ai-modal p { margin: 0 0 10px; font-size: 14px; line-height: 1.6; color: var(--text-2); }
.ai-modal .actions { margin-top: 18px; display: flex; justify-content: flex-end; }
body.ai-modal-open { overflow: hidden; }

/* Compose — two-column editor + live preview ---------------- */
.compose-split {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: 20px;
    /* Both columns stretch to the same row height so the preview's
       sticky position has the full form-column scroll-distance to
       work with. With `align-items: start` the preview's grid cell
       was only as tall as the preview itself — once the user
       scrolled past that cell the sticky lock released and the
       preview disappeared off-screen. */
    align-items: stretch;
}
.compose-editor { padding: 24px 26px; }
.compose-editor .field {
    display: flex; flex-direction: column; gap: 8px;
    margin-bottom: 18px;
}
.compose-editor label.field { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; }
.compose-editor .field-label {
    font-size: 11px; color: var(--text-2); font-weight: 700;
    letter-spacing: .8px; text-transform: uppercase;
}
.compose-editor input[type="text"],
.compose-editor input[type="email"],
.compose-editor input[type="number"],
.compose-editor input[type="date"],
.compose-editor textarea {
    background: var(--bg-elevated); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: 10px;
    padding: 11px 14px; font: inherit; font-size: 14px; font-weight: 400;
    width: 100%; min-width: 0;
    transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
.compose-editor input:hover, .compose-editor textarea:hover {
    border-color: var(--muted-2);
}
.compose-editor input:focus, .compose-editor textarea:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 4px var(--accent-ring);
    background: var(--panel);
}
/* `<select>` in compose moet hetzelfde voelen als de `.format-trigger`-
   knop ernaast — een label + chevron op één lijn. We strippen de
   native chevron (`appearance: none`) en injecteren hetzelfde
   chevron-icoon via background-image als de format-trigger SVG.
   Zelfde radius, border, padding, hover/focus zodat het paar
   (kanaal + formaat) visueel identiek leest. ID-prefix `body`
   bumpt de specificity zodat we de globale `select:not(.theme-
   toggle)` regel verderop in deze stylesheet winnen. */
body .compose-editor select,
body #vacature-form select {
    appearance: none;
    -webkit-appearance: none;
    background: var(--panel); color: var(--text);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");
    background-repeat: no-repeat;
    background-position: right 14px center;
    border: 1px solid var(--border); border-radius: 9px;
    padding: 10px 38px 10px 14px;
    font: inherit; font-size: 14px; font-weight: 500;
    min-height: 46px;
    width: 100%; min-width: 0;
    cursor: pointer;
    transition: border-color .15s var(--ease), background-color .15s var(--ease),
                box-shadow .15s var(--ease);
}
body .compose-editor select:hover,
body #vacature-form select:hover { border-color: var(--accent); }
body .compose-editor select:focus-visible,
body #vacature-form select:focus-visible {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.compose-editor textarea {
    resize: vertical; min-height: 140px; line-height: 1.55;
    font-family: inherit;
}

/* Segmented channel picker */
.channel-seg {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
}
/* Tab-pill voor compose-mode keuze (AI / zelf / marketing).
   Block layout + text-align center is bewust eenvoudig: geen flex,
   dus geen edge cases met de `position: absolute` radio-input die
   in sommige browsers nog een flex-static-position-slot reserveert
   en de span een paar pixels naar links duwde. De input zelf is
   visually onzichtbaar maar blijft in de tab-volgorde — clicks op
   de label togglen 'm via de native label↔input link. */
.channel-opt {
    position: relative; cursor: pointer;
    display: block;
    padding: 12px; border-radius: 10px;
    border: 1.5px solid var(--border); background: var(--panel-2);
    font-size: 13px; font-weight: 600; color: var(--text-2);
    text-align: center;
    transition: all .12s var(--ease);
}
.channel-opt:hover { border-color: var(--muted-2); color: var(--text); }
/* `display: none` op de radio: volledig uit render-tree, geen static-
   position-reservatie meer in welke layout dan ook. Het label blijft
   gewoon werken — clicks togglen de radio via de native label↔input
   parent-binding. Trade-off: keyboard tab-cycling tussen de radios
   gaat verloren, maar de tab-pill UX is bewust click-driven. */
.channel-opt input {
    display: none;
}
.channel-opt:has(input:checked) {
    /* Active state: alleen achtergrond-tint + accent tekstkleur, geen
       accent-border. Een feller gekleurde border maakte het "visuele
       frame" zwaarder dan bij de inactieve buttons en trok het oog —
       de tekst zat wiskundig op pixel-perfect midden (26.37 / 26.37
       links/rechts gemeten), maar oogde links omdat de bright border
       het optische gewicht naar links scheef trok. */
    background: linear-gradient(135deg, var(--accent-soft), var(--accent-weak));
    color: var(--accent);
}
.channel-opt svg { flex-shrink: 0; }

/* Cost-catalog chips (opdracht-aanmaakflow). Grotere chips dan
   .channel-opt want elk catalogus-item heeft een label, een
   tokenprijs en optioneel een korte omschrijving. */
.cost-catalog-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 10px;
    margin-bottom: 8px;
}
.cost-chip {
    position: relative; cursor: pointer;
    display: block; padding: 12px 14px;
    border: 1.5px solid var(--border); border-radius: 10px;
    background: var(--panel-2);
    transition: all .12s var(--ease);
}
.cost-chip:hover { border-color: var(--muted-2); }
.cost-chip input { position: absolute; opacity: 0; pointer-events: none; }
.cost-chip:has(input:checked) {
    border-color: var(--accent); background: var(--accent-weak);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.cost-chip-body { display: flex; flex-direction: column; gap: 2px; }
.cost-chip-body strong { font-size: 13.5px; color: var(--text); }
.cost-chip-body small { font-size: 12px; color: var(--muted); font-weight: 500; }
.cost-chip-desc { font-size: 11.5px; color: var(--muted-2); margin-top: 6px; line-height: 1.4; }
.cost-chip-quote {
    /* Visueel onderscheiden van catalogus-items: stippellijn ipv vol */
    border-style: dashed;
    background: var(--panel);
}
.cost-chip-quote:has(input:checked) {
    border-style: solid;
}

/* Text-editor-style toolbar for the text-overlay controls (positie /
   grootte / uitlijning). Small square icon buttons grouped with a thin
   divider between categories, same radio semantics as .channel-seg. */
/* Text-overlay controls row: 9-point anchor picker on the left, size
   toolbar on the right. Both aligned on a single line. */
.text-overlay-controls {
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.anchor-picker {
    display: grid; grid-template-columns: repeat(3, 1fr);
    gap: 4px; padding: 5px;
    background: var(--panel-2); border: 1px solid var(--border);
    border-radius: 10px;
    width: fit-content;
}
.anchor-dot {
    position: relative; cursor: pointer;
    width: 22px; height: 22px; border-radius: 5px;
    display: flex; align-items: center; justify-content: center;
    background: var(--panel); border: 1px solid var(--border);
    transition: background .1s var(--ease), border-color .1s var(--ease);
}
.anchor-dot:hover { border-color: var(--muted-2); }
.anchor-dot input { position: absolute; opacity: 0; pointer-events: none; }
.anchor-dot-inner {
    width: 6px; height: 6px; border-radius: 999px;
    background: var(--muted);
    transition: background .1s var(--ease), transform .1s var(--ease);
}
.anchor-dot:has(input:checked) {
    background: var(--accent-soft); border-color: var(--accent);
}
.anchor-dot:has(input:checked) .anchor-dot-inner {
    background: var(--accent); transform: scale(1.5);
}
.text-overlay-toolbar {
    /* Block-flex met auto-margins zodat de toolbar gecentreerd staat
       binnen z'n parent. `width: fit-content` + auto-margins centreren.
       Geen eigen border/bg meer — de tool-btns zijn al volwaardige
       knoppen met eigen border + shadow, een buitenste pill zou er
       dubbel-omkadering rond zetten. */
    display: flex; flex-wrap: nowrap; gap: 0;
    padding: 0;
    width: fit-content; max-width: 100%;
    margin-left: auto; margin-right: auto;
    justify-content: center;
}
.text-overlay-toolbar .tool-group {
    display: inline-flex; gap: 8px;
    padding: 0;
    justify-content: center;
}
.tool-btn {
    /* Zelfde maten/look als een gewone .button: 38px hoog, 9px
       radius, panel-bg met border-strong en subtiele shadow. Vierkant
       (38×38) want de inhoud is een icoon (SVG met letter "A"). */
    position: relative; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px;
    border: 1px solid var(--border-strong);
    border-radius: 9px;
    color: var(--text); background: var(--panel);
    box-shadow: var(--shadow-xs);
    transition: background .12s var(--ease), color .12s var(--ease),
                border-color .12s var(--ease), box-shadow .12s var(--ease),
                transform .12s var(--ease);
}
.tool-btn:hover {
    background: var(--panel-2); border-color: var(--muted-2);
    color: var(--text);
    transform: translateY(-1px); box-shadow: var(--shadow-sm);
}
.tool-btn:active { transform: translateY(0); }
/* `input[type="radio"]` heeft een globale regel onderaan (`position:
   relative`, 16×16 cirkel) die deze tool-btn-input zou laten meedoen
   in de flex-flow en zo de SVG-glyph wegduwt. Attribute-selector hier
   bumpt de specificity zodat we het radio-bolletje volledig uit de
   layout halen — alleen de SVG bepaalt nog het visuele midden. */
.tool-btn input[type="radio"] {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    margin: 0;
    border: none; background: transparent;
    opacity: 0;
    pointer-events: none;
}
.tool-btn input[type="radio"]::after { display: none; }
.tool-btn:has(input:checked) {
    background: var(--accent-soft); color: var(--accent);
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);
    transform: none;
}

/* ─── Compose live check (taal + waarheden) ─────────────────────────
   Panel onder de zelf-schrijven textarea. Toont twijfel-meldingen die
   de LLM teruggeeft via `/api/compose/check`. Elke melding heeft een
   kind-label (spelling/grammatica/stijl/feit), korte boodschap, een
   optionele suggestie en een "Toon"-knop die de selectie in de
   textarea op de problematische passage zet. */
.compose-check-panel {
    margin-top: 10px;
    padding: 10px 12px;
    border-radius: 9px;
    border: 1px solid var(--border);
    background: var(--panel-2);
    font-size: 13px;
}
.compose-check-header {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px;
    margin-bottom: 6px;
}
.compose-check-title {
    font-weight: 600; font-size: 12px; color: var(--text);
    letter-spacing: .02em;
}
#compose-check-status[data-kind="loading"] { color: var(--muted); }
#compose-check-status[data-kind="ok"] { color: var(--accent); }
#compose-check-status[data-kind="error"] { color: var(--danger); }
.compose-check-list {
    margin: 0; padding: 0; list-style: none;
    display: flex; flex-direction: column; gap: 6px;
}
.compose-check-item {
    display: grid;
    grid-template-columns: max-content 1fr max-content;
    align-items: baseline;
    column-gap: 10px; row-gap: 2px;
    padding: 6px 8px;
    border-radius: 7px;
    background: var(--panel);
    border: 1px solid var(--border);
}
.compose-check-kind {
    font-size: 10.5px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .08em;
    color: var(--muted-2);
}
.compose-check-item-spelling .compose-check-kind,
.compose-check-item-grammar  .compose-check-kind { color: var(--accent); }
.compose-check-item-style    .compose-check-kind { color: var(--accent-secondary); }
.compose-check-item-factual  .compose-check-kind { color: var(--danger); }
.compose-check-msg { color: var(--text); line-height: 1.4; }
.compose-check-suggestion {
    grid-column: 2 / 3;
    font-size: 12px; color: var(--muted);
    font-style: italic;
}
.compose-check-jump {
    /* Kleine secundaire knop. Hoogte 26px zodat hij netjes naast de
       eenregelige melding past; iets kleinere font dan de hoofd-
       buttons. */
    min-height: 26px;
    padding: 3px 10px;
    font-size: 11.5px; font-weight: 500;
    border-radius: 7px;
    border: 1px solid var(--border-strong);
    background: var(--panel-2); color: var(--muted);
    cursor: pointer;
    box-shadow: none;
}
.compose-check-jump:hover {
    border-color: var(--accent);
    color: var(--accent);
    background: var(--accent-soft);
}
/* Twee knoppen naast elkaar in de panel-rij: Toepassen + Negeren. */
.compose-check-actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    grid-column: 3 / 4;
}
.compose-check-ignore {
    min-height: 26px;
    padding: 3px 10px;
    font-size: 11.5px; font-weight: 500;
    border-radius: 7px;
    border: 1px solid var(--border);
    background: transparent; color: var(--muted);
    cursor: pointer;
    box-shadow: none;
}
.compose-check-ignore:hover {
    border-color: var(--muted-2);
    color: var(--text);
    background: var(--panel-2);
}

/* ─── Inline taalcheck-marks (LanguageTool-stijl) ───────────────────
   De textarea zit BOVEN een `<div>` die dezelfde tekst bevat met
   problematische passages als `<mark>` — de textarea heeft een
   transparante achtergrond zodat de wavy underlines doorschemeren.
   Padding/font/line-height moeten exact matchen anders staan de
   marks niet onder de juiste woorden. */
.lt-textarea-wrap {
    position: relative;
}
.lt-textarea-wrap > textarea {
    /* Semi-transparante background zodat de marks eronder leesbaar
       blijven, terwijl de gebruiker nog steeds de cursor + selectie
       ziet. `position: relative` + `z-index: 1` om te tronen op de
       overlay-div. */
    position: relative;
    z-index: 1;
    background: transparent;
}
.lt-highlights {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    z-index: 0;
    margin: 0;
    overflow: hidden;
    pointer-events: none;
    color: transparent;
    background: var(--panel);
    /* `white-space: pre-wrap` matcht de textarea-default zodat
       newlines + word-wrap exact gelijk vallen. `word-wrap: break-
       word` zorgt dat lange woorden niet uit de container puilen. */
    white-space: pre-wrap;
    word-wrap: break-word;
    overflow-wrap: break-word;
    border-radius: 9px;
}
.lt-mark {
    background: transparent;
    color: transparent;
    text-decoration: underline wavy 1.5px var(--lt-color, #d92626);
    text-underline-offset: 2px;
    pointer-events: auto;
    cursor: pointer;
}
.lt-mark.lt-mark-spelling { --lt-color: #d92626; }
.lt-mark.lt-mark-grammar  { --lt-color: #d92626; }
.lt-mark.lt-mark-style    { --lt-color: #2196f3; }
.lt-mark.lt-mark-factual  { --lt-color: #f59e0b; }

/* ─── Popup voor één marker ────────────────────────────────────────
   Verschijnt onder de aangeklikte mark. Toont kind + uitleg + een
   "Toepassen"-knop (vervangt de marker met de suggestion) en een
   "Sluiten"-knop. Sluit ook bij klik buiten de popup. */
.lt-popup {
    position: absolute;
    z-index: 50;
    min-width: 240px;
    max-width: 360px;
    padding: 10px 12px;
    background: var(--panel);
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    font-size: 13px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.lt-popup-kind {
    font-size: 10px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .08em;
    color: var(--muted);
}
.lt-popup-kind-spelling, .lt-popup-kind-grammar { color: #d92626; }
.lt-popup-kind-style { color: #2196f3; }
.lt-popup-kind-factual { color: #f59e0b; }
.lt-popup-msg {
    color: var(--text);
    line-height: 1.4;
}
.lt-popup-apply {
    align-self: flex-start;
    padding: 6px 10px;
    font-size: 12px;
    background: var(--accent-soft);
    color: var(--accent);
    border: 1px solid var(--accent);
    border-radius: 7px;
    cursor: pointer;
    box-shadow: none;
}
.lt-popup-apply:hover {
    background: var(--accent);
    color: #fff;
}
.lt-popup-ignore {
    align-self: flex-start;
    padding: 5px 10px;
    font-size: 12px;
    color: var(--muted);
    background: var(--panel-2);
    border: 1px solid var(--border-strong);
    border-radius: 7px;
    cursor: pointer;
    box-shadow: none;
}
.lt-popup-ignore:hover {
    color: var(--text);
    border-color: var(--muted-2);
}
.lt-popup-dismiss {
    align-self: flex-end;
    padding: 4px 8px;
    font-size: 11.5px;
    color: var(--muted);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 7px;
    cursor: pointer;
    box-shadow: none;
}

/* ─── Schedule-card op /drafts/{id} (slice 2: auto-plan voorstel) ───
   Drie suggestion-cards naast elkaar (responsief 2 → 1 kol op smalle
   viewports) met heatmap+clustering-score, plus een details voor de
   "eigen tijd"-picker. Geen accent-overdose: enkel de score en de
   "Kies dit tijdstip"-knop pakken de accentkleur. */
.schedule-card { display: flex; flex-direction: column; gap: 12px; }
.schedule-suggestions {
    list-style: none; margin: 0; padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 10px;
}
.schedule-suggestion {
    display: flex; flex-direction: column; gap: 6px;
    padding: 12px;
    border: 1px solid var(--border);
    border-radius: 9px;
    background: var(--panel-2);
}
.schedule-suggestion-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px;
}
.schedule-suggestion-time {
    font-weight: 700; font-size: 14px;
    color: var(--text);
    letter-spacing: -.05px;
}
.schedule-suggestion-score {
    font-size: 11px; font-weight: 700;
    color: var(--accent);
    text-transform: uppercase; letter-spacing: .08em;
}
.schedule-suggestion-reason {
    margin: 0;
    font-size: 12.5px; color: var(--muted);
    line-height: 1.4;
}
.schedule-pick {
    align-self: flex-start;
    margin-top: 2px;
}
.schedule-custom > summary {
    cursor: pointer;
    font-size: 13px; color: var(--muted);
    font-weight: 600;
    padding: 4px 0;
    list-style: none;
}
.schedule-custom > summary::-webkit-details-marker { display: none; }
.schedule-custom > summary::before {
    content: "+ ";
    font-weight: 700; color: var(--accent);
}
.schedule-custom[open] > summary::before { content: "− "; }

/* ─── Form-accordion: lichte uitklap-sectie binnen een form ──────────
   Gebruikt voor optionele velden in een create/edit-form (bv. AutoCapture
   + Bijlage bij planning-item create). Bewust minder dominant dan
   `.admin-section`: kleinere padding, lichter contrast, géén gap-0
   override op de omhullende form.vstack (zodat label-velden hun ritme
   houden). */
details.form-accordion {
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--panel-2);
    overflow: hidden;
}
details.form-accordion > summary {
    list-style: none;
    cursor: pointer;
    padding: 10px 12px;
    display: flex; align-items: center; gap: 8px;
    font-size: 13px;
    font-weight: 500;
    color: var(--muted);
    user-select: none;
    transition: background .12s var(--ease), color .12s var(--ease);
}
details.form-accordion > summary::-webkit-details-marker { display: none; }
details.form-accordion > summary::marker { content: ''; display: none; }
details.form-accordion > summary::before { content: none; }
details.form-accordion > summary:hover {
    background: var(--panel);
    color: var(--text);
}
details.form-accordion > summary::after {
    content: '';
    margin-left: auto;
    width: 7px; height: 7px;
    border-right: 2px solid var(--muted);
    border-bottom: 2px solid var(--muted);
    transform: rotate(45deg) translateY(-1px);
    transition: transform .15s var(--ease);
}
details.form-accordion[open] > summary {
    color: var(--text);
    border-bottom: 1px solid var(--border);
    background: var(--panel);
}
details.form-accordion[open] > summary::after {
    transform: rotate(-135deg) translateY(2px);
}
.form-accordion-body {
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.form-accordion-body > label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 13px;
    font-weight: 500;
    color: var(--text);
}
.form-accordion-body .field-row {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 12px;
}
@media (max-width: 520px) {
    .form-accordion-body .field-row {
        grid-template-columns: 1fr;
    }
}

/* ─── Per-bedrijf admin: compacte settings-list ─────────────────────
   Gebruikt op /admin/subsidiaries/{id}. Elke `<details.admin-section>`
   voelt aan als een rij in een lijst (zoals iOS Settings) — een hair-
   line border tussen items, geen kaart-shadow per item, zacht hover-
   effect zodat duidelijk is dat het hele rij-oppervlak klikbaar is. */
details.admin-section {
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--panel);
    /* Eén consistent ritme tussen secties — werkt zowel binnen als
       buiten het brand-edit form. We zetten hieronder de form.vstack
       gap op 0 wanneer het admin-sections bevat, zodat alleen deze
       margin de afstand bepaalt en je niet de optelsom van twee
       mechanismen krijgt.

       NB: bewust géén `:last-child { margin-bottom: 0 }` — de echt
       laatste section ZIT WEL als laatste kind van zijn flex-container
       (het brand-edit form), maar daar staat ze precies op de overgang
       naar de admin-sections die NA het form komen (PPT-templates, …).
       Stripten we daar de margin, dan plakt Vrije richtlijnen aan
       PPT-templates. De extra 16px onderaan de allerlaatste sectie
       valt sowieso binnen .content's padding-bottom van 72px, dus
       visueel niet storend. */
    margin-bottom: 16px;
    overflow: hidden;
}
/* Het autosave-form (op /admin/subsidiaries/{id}) functioneert als
   settings-list, niet als input-form: wanneer het rechtstreeks
   admin-sections bevat zetten we het vstack-gap-mechanisme uit zodat
   de margin-bottom van details.admin-section het ritme bepaalt
   (16px overal, ook tussen secties die buiten het form zitten).
   Andere autosave-forms (compose-opts, overlay-edit) bevatten form-
   fields en behouden de 16px-gap. */
form.vstack:has(> details.admin-section) {
    gap: 0;
}
details.admin-section > summary {
    /* Beide native disclosure-indicators (Webkit `details-marker` én
       de standaard `::marker`) wegduwen + `list-style: none` voor
       browsers die geen van beide ondersteunen. Onze eigen ::after
       chevron rechts vervangt 'm. */
    list-style: none;
    cursor: pointer;
    padding: 11px 14px;
    display: flex; align-items: center; gap: 10px;
    font-weight: 600; font-size: 14px;
    color: var(--text);
    user-select: none;
    transition: background .12s var(--ease);
}
details.admin-section > summary::-webkit-details-marker { display: none; }
details.admin-section > summary::marker { content: ''; display: none; }
/* Override de globale `details summary::before` regel die overal een
   "›" toevoegt — onze admin-section heeft een eigen ::after-chevron
   rechts en wil geen tweede aan de linkerkant. */
details.admin-section > summary::before { content: none; }
details.admin-section > summary:hover { background: var(--panel-2); }
details.admin-section > summary::after {
    /* Chevron rechts. `margin-left: auto` duwt 'm naar de
       rechterkant; de title-tekst (anoniem flex-item) houdt links. */
    content: '';
    margin-left: auto;
    width: 8px; height: 8px;
    border-right: 2px solid var(--muted);
    border-bottom: 2px solid var(--muted);
    transform: rotate(45deg) translateY(-2px);
    transition: transform .15s var(--ease);
}
details.admin-section[open] > summary::after {
    transform: rotate(-135deg) translateY(2px);
}
details.admin-section[open] > summary {
    border-bottom: 1px solid var(--border);
}
.admin-section-body {
    padding: 12px 14px 14px;
    display: flex; flex-direction: column; gap: 12px;
}
.admin-section-body > .hint:first-child,
.admin-section-body > p.hint:first-child {
    margin-top: 0;
}

/* Gevarenzone: rode header zodat de admin meteen ziet dat dit
   destructive is (delete subsidiary, wipe content). De body-styling
   blijft normaal — enkel de header-rij is gekleurd. */
details.admin-section.danger {
    border-color: var(--danger);
}
details.admin-section.danger > summary {
    background: var(--danger-soft);
    color: var(--danger);
}
details.admin-section.danger > summary:hover {
    background: color-mix(in srgb, var(--danger-soft) 70%, var(--danger) 30%);
}
details.admin-section.danger > summary::after {
    border-color: var(--danger);
}
details.admin-section.danger[open] > summary {
    border-bottom-color: var(--danger);
}
/* Compactere form-velden binnen een settings-rij — 36px ipv 46px. */
.admin-section-body label > input[type="text"],
.admin-section-body label > input[type="url"],
.admin-section-body label > input[type="email"],
.admin-section-body label > select {
    min-height: 36px;
    padding: 7px 12px;
    font-size: 13px;
}

/* Auto-save status indicator. Verschijnt naast (of bovenaan via
   `data-form`-koppeling) een form.autosave en geeft 4 toestanden
   weer: pending (debounce telt af), saving (fetch loopt), saved
   (vervaagt na 2.2s), error (blijft staan tot volgende save). */
.autosave-status {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .03em;
    color: var(--muted);
    padding: 3px 10px;
    border-radius: 999px;
    background: transparent;
    transition: background .15s var(--ease), color .15s var(--ease);
}
.autosave-status:empty {
    padding: 0;
    min-height: 0;
}
.autosave-status.is-pending {
    color: var(--muted);
    background: var(--panel-2);
}
.autosave-status.is-saving {
    color: var(--accent);
    background: var(--accent-soft);
}
.autosave-status.is-saved {
    color: var(--accent);
    background: var(--accent-soft);
}
.autosave-status.is-error {
    color: var(--danger);
    background: var(--danger-soft);
}

/* Verberg de submit-knoppen binnen een autosave-form — niet meer
   nodig nu de save automatisch gebeurt. De `.autosave-status` bovenaan
   (of inline) communiceert de save-state. */
form.autosave button[type="submit"],
form.autosave .button[type="submit"] {
    display: none;
}
form.autosave .actions:empty,
form.autosave > div.actions {
    display: none;
}

/* Moderne iOS-stijl toggle. Een `<label class="pill-switch">` wraps een
   `<input type="checkbox">` (visueel verstopt) + een track met thumb +
   de begeleidende tekst. Klik op de hele label togglet de checkbox.
   Werkt los van de admin-section maar is hier toegevoegd. */
.pill-switch {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 10px 12px;
    border-radius: 10px;
    cursor: pointer;
    user-select: none;
    transition: background .12s var(--ease);
    margin: 0;
    font-weight: 400;
    font-size: 13.5px;
    line-height: 1.45;
    color: var(--text);
}
.pill-switch:hover { background: var(--panel-2); }
.pill-switch input[type="checkbox"] {
    /* Native checkbox volledig verstopt — de track + thumb hieronder
       nemen de visuele rol over. Specificity-bumped op attribute zodat
       de globale `input[type="checkbox"]` regel niet wint. */
    position: absolute;
    width: 1px; height: 1px;
    margin: 0; padding: 0; border: 0;
    opacity: 0;
    pointer-events: none;
    overflow: hidden;
    clip: rect(0 0 0 0);
}
.pill-switch-track {
    flex-shrink: 0;
    position: relative;
    display: inline-block;
    width: 38px; height: 22px;
    background: var(--border-strong);
    border-radius: 999px;
    margin-top: 2px;
    transition: background .15s var(--ease), box-shadow .15s var(--ease);
}
.pill-switch-thumb {
    position: absolute;
    top: 2px; left: 2px;
    width: 18px; height: 18px;
    background: #fff;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.22);
    transition: transform .15s var(--ease);
}
/* Sibling-combinator i.p.v. `:has()` — sommige Chromium-builds
   herinvalideren `:has(input:checked)` niet wanneer `.checked` via een
   property-set (i.p.v. een echte click) verandert. `input:checked ~ ...`
   is een directe sibling-selector die in alle browsers reactief is. */
.pill-switch input[type="checkbox"]:checked ~ .pill-switch-track {
    background: var(--accent);
}
.pill-switch input[type="checkbox"]:checked ~ .pill-switch-track > .pill-switch-thumb {
    transform: translateX(16px);
}
.pill-switch input[type="checkbox"]:focus-visible ~ .pill-switch-track {
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.pill-switch-text {
    display: flex; flex-direction: column; gap: 2px;
    min-width: 0;
}
.pill-switch-text strong {
    font-weight: 700; color: var(--text);
    font-size: 13.5px;
}
.pill-switch-text small {
    color: var(--muted);
    font-size: 12.5px;
    line-height: 1.4;
}

/* Overlay-grid: compacte tiles met thumbnail + naam + toggle in de
   hoek. Veel efficiënter qua schermgebruik dan de oude lijst — past
   3 à 5 templates per rij in i.p.v. 1 per regel. */
.overlay-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 10px;
}
.overlay-tile {
    display: flex; flex-direction: column; gap: 6px;
    cursor: pointer;
    user-select: none;
    margin: 0;
    /* Native checkbox volledig verstoppen — de tile zelf is de UI. */
    position: relative;
}
.overlay-tile > input[type="checkbox"] {
    position: absolute;
    width: 1px; height: 1px;
    margin: 0; padding: 0; border: 0;
    opacity: 0;
    pointer-events: none;
    overflow: hidden;
    clip: rect(0 0 0 0);
}
.overlay-tile-thumb {
    /* Vierkante tegel met de overlay-PNG als achtergrond. Een
       lichte panel-2 fallback voorkomt een zwart vlak voor overlays
       met transparante achtergrond. */
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: 9px;
    background: var(--panel-2);
    background-size: contain;
    background-position: center;
    background-repeat: no-repeat;
    border: 2px solid var(--border);
    box-shadow: var(--shadow-xs);
    transition: border-color .15s var(--ease), transform .12s var(--ease);
}
.overlay-tile:hover .overlay-tile-thumb {
    transform: translateY(-1px);
    border-color: var(--muted-2);
}
.overlay-tile > input:checked ~ .overlay-tile-thumb {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.overlay-tile-toggle {
    /* Pill-switch direct op de thumbnail — geen extra wrapper-vlak
       eromheen. Kleine subtiele drop-shadow zodat hij leesbaar blijft
       op een lichte foto. */
    position: absolute;
    top: 6px; right: 6px;
    width: 32px; height: 18px;
    margin: 0;
    background: var(--border-strong);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
    pointer-events: none;
}
.overlay-tile-toggle > .pill-switch-thumb {
    width: 14px; height: 14px;
    top: 2px; left: 2px;
}
.overlay-tile > input:checked ~ .overlay-tile-thumb > .overlay-tile-toggle {
    background: var(--accent);
}
.overlay-tile > input:checked ~ .overlay-tile-thumb > .overlay-tile-toggle > .pill-switch-thumb {
    transform: translateX(14px);
}
.overlay-tile-name {
    font-weight: 600; font-size: 13px;
    color: var(--text);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: 0 2px;
}
.overlay-tile-meta {
    font-size: 11.5px;
    color: var(--muted);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: 0 2px;
}
.overlay-tile-badge {
    /* Klein origin-pillje linksboven op de thumb. Onderscheid tussen
       seeded marketing-templates ("standaard") en eigen uploads
       ("eigen"). */
    position: absolute;
    top: 6px; left: 6px;
    padding: 2px 7px;
    font-size: 9.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    background: rgba(255, 255, 255, 0.85);
    color: var(--muted);
    border-radius: 999px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
    pointer-events: none;
}
.overlay-tile-badge.is-upload {
    background: var(--accent-soft);
    color: var(--accent);
}
.overlay-tile-edit {
    /* Subtiele "Bewerken" knop onder de uploaded tile. Vol-breed
       zodat hij visueel matcht met de tile-grid. */
    margin-top: 4px;
    padding: 6px 10px !important;
    font-size: 11.5px;
    font-weight: 600;
    width: 100%;
    min-height: 30px;
    border-radius: 7px;
}

/* Dialog-body voor "Eigen overlay bewerken": grote thumb links,
   form rechts (verticaal gestackt op smalle viewports). */
.uploaded-overlay-dialog-body {
    display: grid;
    grid-template-columns: 140px 1fr;
    gap: 16px;
    align-items: start;
}
@media (max-width: 560px) {
    .uploaded-overlay-dialog-body {
        grid-template-columns: 1fr;
    }
}
.uploaded-overlay-dialog-body .uploaded-overlay-thumb {
    width: 140px; height: 140px;
}

/* Uploaded-overlay editable rows: thumbnail links, naam + pijler-
   select + allows-text toggle in een grid, save + delete rechts. */
.uploaded-overlay-list {
    display: flex; flex-direction: column; gap: 10px;
}
.uploaded-overlay-row {
    display: grid;
    grid-template-columns: 72px 1fr auto;
    gap: 14px;
    align-items: center;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 9px;
    background: var(--panel-2);
}
.uploaded-overlay-thumb {
    width: 72px; height: 72px;
    border-radius: 8px;
    background: var(--panel);
    background-size: contain;
    background-position: center;
    background-repeat: no-repeat;
    border: 1px solid var(--border);
    flex-shrink: 0;
}
.uploaded-overlay-form {
    display: grid;
    grid-template-columns: minmax(160px, 1.4fr) minmax(160px, 1fr) minmax(220px, 1.6fr) auto;
    gap: 10px;
    align-items: end;
    margin: 0;
}
@media (max-width: 920px) {
    .uploaded-overlay-form {
        grid-template-columns: 1fr 1fr;
    }
    .uploaded-overlay-form .uploaded-overlay-toggle {
        grid-column: 1 / -1;
    }
    .uploaded-overlay-form .uploaded-overlay-actions {
        grid-column: 1 / -1;
        justify-self: end;
    }
}
.uploaded-overlay-form label {
    margin: 0;
}
.uploaded-overlay-form .field-label {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--muted);
    font-weight: 700;
    display: block;
    margin-bottom: 4px;
}
.uploaded-overlay-form input[type="text"],
.uploaded-overlay-form select {
    min-height: 36px;
    padding: 7px 12px;
    font-size: 13px;
    width: 100%;
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    background: var(--panel);
    color: var(--text);
}
.uploaded-overlay-form .pill-switch.uploaded-overlay-toggle {
    /* De toggle past al binnen de grid-cel; reset de border/padding
       die `.pill-switch` standaard zet zodat hij niet uit de rij
       puilt. */
    padding: 6px 8px;
}
.uploaded-overlay-actions {
    display: flex; align-items: center; justify-content: flex-end;
}
.uploaded-overlay-actions button.primary {
    min-height: 36px;
    padding: 7px 14px;
    font-size: 13px;
}
.uploaded-overlay-delete {
    margin: 0;
    align-self: center;
}
.uploaded-overlay-delete button {
    font-size: 12.5px;
    padding: 6px 10px;
    min-height: 32px;
}

.char-counter {
    display: block; margin-top: 4px;
    font-size: 11.5px; color: var(--muted);
    font-variant-numeric: tabular-nums;
}
.char-counter.char-counter-warn {
    color: var(--warn, #b45309); font-weight: 600;
}

/* Content-request detail — structured briefing + chat panel. */
.briefing-grid {
    display: grid; grid-template-columns: 180px 1fr;
    gap: 10px 18px;
    margin: 10px 0 0;
}
.briefing-grid dt {
    font-size: 11.5px; color: var(--muted);
    text-transform: uppercase; letter-spacing: .05em;
    font-weight: 600;
}
.briefing-grid dd {
    margin: 0; font-size: 14px; color: var(--text); white-space: pre-wrap;
    word-break: break-word;
}
@media (max-width: 600px) {
    .briefing-grid { grid-template-columns: 1fr; gap: 4px 0; }
    .briefing-grid dd { margin-bottom: 10px; }
}

.chat-list {
    list-style: none; margin: 0 0 14px; padding: 0;
    display: flex; flex-direction: column; gap: 10px;
}
.chat-msg {
    background: var(--panel-2); border: 1px solid var(--border);
    border-radius: 10px; padding: 10px 14px;
}
.chat-msg-mine {
    background: var(--accent-weak); border-color: var(--accent-soft);
}
.chat-msg-head {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    margin-bottom: 4px;
}
.chat-msg-head .chat-role {
    font-size: 10px; padding: 1px 8px;
}
.chat-msg-head .chat-time {
    margin-left: auto; font-size: 11.5px;
    font-variant-numeric: tabular-nums;
}
.chat-msg-body {
    font-size: 14px; line-height: 1.55;
    white-space: pre-wrap; word-break: break-word;
}

/* Bynder asset picker — modal + search + grid. Replaces the dropped
   Compact View widget; backed by /api/bynder/search. */
.bynder-modal {
    position: fixed; inset: 0; z-index: 1000;
    background: rgba(10, 16, 32, 0.65);
    display: flex; align-items: center; justify-content: center;
    padding: 24px;
}
.bynder-modal[hidden] { display: none; }
.bynder-modal-inner {
    background: var(--panel); border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    width: min(960px, 100%); max-height: 86vh;
    display: flex; flex-direction: column;
    box-shadow: 0 20px 60px rgba(0,0,0,0.45);
    overflow: hidden;
}
.bynder-modal-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 18px; border-bottom: 1px solid var(--border);
    font-size: 14px;
}
.bynder-modal-header button { font-size: 18px; padding: 4px 10px; }
.bynder-modal-search { padding: 12px 18px; border-bottom: 1px solid var(--border); }
.bynder-modal-search input {
    width: 100%; height: 38px; padding: 0 12px;
    border: 1px solid var(--border-strong); border-radius: 8px;
    background: var(--panel-2); color: var(--text);
    font-size: 13.5px;
}
.bynder-modal-body {
    padding: 14px 18px 18px; overflow-y: auto; min-height: 220px;
}
#bynder-modal-status.error { color: var(--danger); }
.bynder-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 12px;
}
.bynder-cell {
    cursor: pointer; padding: 0;
    background: var(--panel-2); border: 1px solid var(--border);
    border-radius: 10px; overflow: hidden;
    display: flex; flex-direction: column;
    transition: border-color .12s var(--ease), transform .12s var(--ease);
    box-shadow: none; text-align: left;
}
.bynder-cell:hover {
    border-color: var(--accent); transform: translateY(-1px);
}
.bynder-thumb {
    display: block; width: 100%; height: 140px;
    object-fit: cover;
    background: var(--panel);
}
.bynder-thumb-empty { background: var(--panel-2); }
.bynder-cell-name {
    padding: 8px 10px; font-size: 12px; color: var(--text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Multi-select: a small green check appears on picked cells. Hidden
   by default; flipped on via the is-selected class. */
.bynder-cell { position: relative; }
.bynder-cell-check {
    position: absolute; top: 6px; right: 6px;
    width: 22px; height: 22px; border-radius: 999px;
    display: none; align-items: center; justify-content: center;
    background: var(--accent); color: #fff;
    font-size: 13px; font-weight: 700;
    box-shadow: 0 1px 4px rgba(0,0,0,.25);
}
.bynder-cell.is-selected { border-color: var(--accent); }
.bynder-cell.is-selected .bynder-cell-check { display: flex; }
.bynder-modal-footer {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 18px; border-top: 1px solid var(--border);
    background: var(--panel);
}
.bynder-modal-count {
    font-size: 12.5px; color: var(--muted); margin-right: auto;
}
.bynder-modal-footer button:disabled { opacity: .5; cursor: not-allowed; }

/* Drop-zone */
.dropzone {
    display: flex; flex-direction: column; align-items: center; gap: 8px;
    padding: 28px 20px;
    border: 2px dashed var(--border-strong); border-radius: 12px;
    background: var(--panel-2); color: var(--muted);
    cursor: pointer; text-align: center;
    transition: all .15s var(--ease);
}
.dropzone:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-weak); }
.dropzone.is-dragging {
    border-color: var(--accent); color: var(--accent);
    background: var(--accent-soft); transform: scale(1.01);
}
.dropzone-icon { opacity: .7; }
.dropzone:hover .dropzone-icon { opacity: 1; }
.dropzone-title { font-size: 13.5px; font-weight: 600; color: var(--text-2); }
.dropzone:hover .dropzone-title { color: var(--accent); }
.dropzone-sub { font-size: 11.5px; color: var(--muted-2); letter-spacing: .3px; }
.dropzone.is-disabled {
    opacity: 0.5; pointer-events: none;
    border-style: solid;
}
.dropzone.is-disabled:hover { border-color: var(--border-strong); background: transparent; color: var(--muted); }

/* Bynder brand mark — PNG logo served from static/images/bynder.png. */
.bynder-mark {
    width: 20px; height: 20px; border-radius: 5px;
    display: inline-block; flex-shrink: 0;
    object-fit: contain;
}

/* SharePoint mark — Office blue rounded badge with "SP". */
.sharepoint-mark {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 20px; border-radius: 5px;
    background: #0078d4;
    color: #fff; font-weight: 800; font-size: 10.5px;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", Inter, sans-serif;
    line-height: 1; letter-spacing: 0;
    flex-shrink: 0;
}

.selected-media {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 14px; border-radius: 10px;
    background: var(--panel-2); border: 1px solid var(--border);
}
.selected-media img {
    width: 64px; height: 64px; object-fit: cover;
    border-radius: 8px; border: 1px solid var(--border);
}
.selected-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.selected-name {
    font-size: 13px; font-weight: 600; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.selected-hint { font-size: 11px; }

/* Compose-page gallery — strip of draggable tiles for every selected
   file. Index 0 carries a "Cover" badge; the rest get a "Cover"-button
   that promotes them on click. Drag-and-drop reorders the carousel
   sequence before the form submits; the JS mirrors the order back to
   fileInput.files via DataTransfer so the multipart payload follows. */
.selected-extras {
    display: flex; flex-wrap: wrap; gap: 8px;
    margin-top: 10px;
}
/* Individuele thumbnails in de extras-strip — anders vallen <img>-
   tags terug op intrinsic-size (bv. 4K capture-foto's vullen het
   hele scherm). Vaste 80×80 vierkant met cover-fit, matched aan de
   gallery-tile-stijl elders. */
.selected-extras img.selected-extra,
.selected-extras .selected-extra {
    width: 80px;
    height: 80px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--border);
    background: var(--panel-2);
    display: block;
}
/* Video-marker krijgt een leesbare placeholder ipv een broken img. */
.selected-extras .gallery-video-mark {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 28px;
    color: #fff;
    background: #1a1d24;
}
.gallery-tile {
    position: relative;
    width: 92px; height: 92px;
    border-radius: 10px;
    border: 1px solid var(--border-strong);
    background: var(--panel-2);
    overflow: hidden;
    cursor: grab;
    user-select: none;
    transition: border-color .12s var(--ease), transform .12s var(--ease),
                box-shadow .12s var(--ease);
}
.gallery-tile:hover {
    border-color: var(--accent);
    transform: translateY(-1px);
    box-shadow: var(--shadow-sm);
}
.gallery-tile.is-cover {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-ring);
}
.gallery-tile.is-dragging {
    opacity: 0.4;
    cursor: grabbing;
}
.gallery-tile.is-drop-target {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft);
    transform: translateY(-2px);
}
.gallery-tile .gallery-thumb {
    display: block;
    width: 100%; height: 100%;
    object-fit: cover;
    pointer-events: none;
}
.gallery-tile .gallery-handle {
    position: absolute;
    top: 4px; left: 4px;
    width: 18px; height: 18px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(15, 17, 20, 0.55);
    color: #fff;
    font-size: 10px; line-height: 1;
    border-radius: 4px;
    pointer-events: none;
    letter-spacing: -1px;
}
.gallery-tile .gallery-video-mark {
    position: absolute;
    inset: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: 28px;
    color: var(--text);
    background: var(--panel-2);
    pointer-events: none;
}
.gallery-tile .gallery-actions {
    position: absolute;
    bottom: 0; left: 0; right: 0;
    display: flex; justify-content: space-between; align-items: center;
    padding: 4px 6px;
    background: linear-gradient(to top, rgba(0,0,0,0.6), rgba(0,0,0,0));
    gap: 6px;
}
.gallery-tile .gallery-cover-badge {
    background: var(--accent);
    color: #fff;
    font-size: 9.5px; font-weight: 800;
    padding: 2px 6px; border-radius: 4px;
    text-transform: uppercase; letter-spacing: .5px;
}
.gallery-tile .gallery-action {
    /* Reset global button styling on the tile actions. */
    background: rgba(255, 255, 255, 0.92);
    color: var(--text);
    border: none;
    border-radius: 5px;
    padding: 2px 7px;
    font-size: 10.5px; font-weight: 700;
    cursor: pointer;
    box-shadow: none;
    line-height: 1.4;
    transition: background .12s var(--ease), color .12s var(--ease);
}
.gallery-tile .gallery-action:hover {
    background: var(--accent);
    color: #fff;
    transform: none;
    box-shadow: none;
    border: none;
}
.gallery-tile .gallery-action.gallery-action-remove {
    width: 22px; height: 22px;
    padding: 0;
    border-radius: 50%;
    font-size: 14px;
    display: inline-flex; align-items: center; justify-content: center;
}

.overlay-block {
    margin: 10px 0 18px;
}

/* Two stacked action columns: each button sits above its own caption.
   Right-aligned end = primary path so the reading eye lands on the
   expected action last. Wraps cleanly on narrow screens because each
   option is self-contained — the caption never breaks across buttons. */
.compose-submit {
    margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border);
    display: flex; align-items: flex-start;
    gap: 14px 16px; flex-wrap: nowrap;
}
.compose-submit-option {
    display: flex; flex-direction: column; align-items: stretch;
    gap: 6px;
    flex: 1 1 0; min-width: 0;
}
/* Very narrow forms (e.g. mobile) can still stack the two options. */
@media (max-width: 520px) {
    .compose-submit { flex-wrap: wrap; }
    .compose-submit-option { flex-basis: 100%; }
}
.compose-submit-option button {
    width: 100%;
}
/* "Schrijf zelf" panel — body textarea, full width. Schrijfhulp lives
   in a <dialog> popup (see .app-dialog below) opened via the ? icon
   next to the field label. */
.compose-self-write {
    margin: 0 0 4px;
}
.field-label-with-help {
    display: inline-flex; align-items: center; gap: 8px;
}
.help-icon-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px;
    padding: 0; border-radius: 999px;
    background: var(--panel-2);
    border: 1px solid var(--border-strong);
    color: var(--muted);
    font-size: 12px; font-weight: 700; line-height: 1;
    cursor: pointer;
    transition: all .12s var(--ease);
}
.help-icon-btn:hover {
    background: var(--accent-weak);
    border-color: var(--accent);
    color: var(--accent);
}

/* Inline help-popover die hoort bij een `.help-icon-btn` met
   `data-help="<id>"`. Geen vlak, geen titel — gewoon een klein
   accent-getint blokje onder het veld dat verschijnt op klik. */
.field-help {
    margin: 0; padding: 10px 12px;
    background: var(--panel-2);
    border-left: 3px solid var(--accent);
    border-radius: 6px;
    font-size: 12.5px; line-height: 1.5; color: var(--muted);
}
.field-help[hidden] { display: none; }
.field-help code {
    font-size: 11.5px; padding: 1px 6px; border-radius: 4px;
    background: var(--panel); color: var(--text);
}

/* Generic <dialog> styling for app-wide popups. Dark backdrop, rounded
   panel, native ESC-to-close. Schrijfhulp uses this; future popups can
   re-use the same skin by adding `class="app-dialog"`. */
dialog.app-dialog {
    border: 0; padding: 0;
    border-radius: 14px;
    background: var(--panel);
    color: var(--text);
    box-shadow: 0 30px 80px rgba(0,0,0,.35);
    max-width: 560px; width: calc(100vw - 32px);
}
dialog.app-dialog::backdrop {
    background: rgba(8, 12, 20, .55);
    backdrop-filter: blur(2px);
}
.app-dialog-inner { padding: 20px 22px; }
.app-dialog-header {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; margin-bottom: 8px;
}
.app-dialog-header > h2 { margin: 0; }
.app-dialog-close {
    width: 28px; height: 28px; padding: 0;
    border-radius: 999px;
    background: transparent; border: 1px solid var(--border);
    color: var(--muted); font-size: 18px; line-height: 1;
    cursor: pointer;
}
.app-dialog-close:hover { background: var(--panel-2); color: var(--text); }
.app-dialog-actions {
    display: flex; justify-content: flex-end; gap: 10px;
    margin-top: 16px;
}

/* ─── Playlist Designer (drag-drop tijdlijn) ───────────────────────
   Eén rij per item: handle links, thumb middenlinks, meta in het
   midden, acties rechts. `draggable=true` op elke rij; CSS-classes
   voor de drag-states komen van de JS-handler. */
.playlist-timeline {
    display: flex; flex-direction: column;
    gap: 6px;
    margin-top: 4px;
}
.playlist-row {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 14px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 10px;
    cursor: grab;
    transition: background .12s var(--ease), box-shadow .12s var(--ease),
                transform .12s var(--ease);
}
.playlist-row:hover { background: var(--panel-2); }
.playlist-row.is-dragging {
    opacity: 0.5;
    cursor: grabbing;
    box-shadow: 0 8px 24px rgba(0,0,0,.18);
}
/* Drop-target-markers — een blauwe lijn boven of onder de hoover-rij
   om aan te geven waar de drop terechtkomt. */
.playlist-row.is-drop-target-above {
    box-shadow: 0 -2px 0 0 var(--accent);
}
.playlist-row.is-drop-target-below {
    box-shadow: 0 2px 0 0 var(--accent);
}
.playlist-handle {
    color: var(--muted-2);
    font-size: 18px;
    line-height: 1;
    user-select: none;
    cursor: grab;
}
.playlist-thumb {
    flex: 0 0 64px;
    width: 64px; height: 48px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--panel-2);
    display: flex; align-items: center; justify-content: center;
    font-size: 24px;
    color: var(--muted);
}
.playlist-thumb img {
    width: 100%; height: 100%; object-fit: cover;
}
.playlist-meta {
    flex: 1 1 auto; min-width: 0;
}
.playlist-title {
    font-size: 14px; font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.playlist-sub {
    font-size: 12px;
    margin-top: 2px;
}
.playlist-actions {
    flex: 0 0 auto;
    display: flex; gap: 6px;
}

/* ─── Live screen-preview-modal ────────────────────────────────────
   Breder dan de standaard 560px-dialog zodat een 16:9-iframe nog
   lekker afleesbaar blijft op een laptop. De .frame-wrap dwingt de
   aspect-ratio af zodat de kiosk-pagina niet wordt uitgerekt. */
dialog.app-dialog#screen-preview-dialog {
    max-width: 960px;
}
.screen-preview-frame-wrap {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #000;
    border-radius: 10px;
    overflow: hidden;
    border: 1px solid var(--border);
}
.screen-preview-frame-wrap iframe {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    border: 0;
}
/* Schrijfhulp popup — richer card grid + gradient hero. The hero
   stretches edge-to-edge so we override the default .app-dialog-inner
   padding for the dialog top half. */
dialog.schrijfhulp-dialog {
    max-width: 640px;
    overflow: hidden;
}
dialog.schrijfhulp-dialog .app-dialog-inner { padding: 0; }
.schrijfhulp-hero {
    display: flex; align-items: center; gap: 14px;
    padding: 22px 22px 18px;
    background: linear-gradient(135deg, var(--accent-weak), var(--panel-2));
    border-bottom: 1px solid var(--border);
    position: relative;
}
.schrijfhulp-hero-icon {
    flex: 0 0 auto;
    width: 48px; height: 48px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 14px;
    background: var(--accent);
    color: #fff;
    box-shadow: 0 6px 14px rgba(0,0,0,.12);
}
.schrijfhulp-hero-text { flex: 1 1 auto; min-width: 0; }
.schrijfhulp-hero-text h3 {
    margin: 0 0 4px;
    font-size: 18px; font-weight: 700;
    color: var(--text);
}
.schrijfhulp-hero-text p {
    margin: 0;
    font-size: 13px; color: var(--muted);
    line-height: 1.45;
}
.schrijfhulp-hero .app-dialog-close {
    position: absolute; top: 14px; right: 14px;
}

.schrijfhulp-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    padding: 18px 22px;
}
@media (max-width: 560px) {
    .schrijfhulp-grid { grid-template-columns: 1fr; }
}
.schrijfhulp-card {
    display: flex; gap: 12px; align-items: flex-start;
    padding: 14px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 12px;
    transition: border-color .12s var(--ease), transform .12s var(--ease),
                box-shadow .12s var(--ease);
}
.schrijfhulp-card:hover {
    border-color: var(--border-strong);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0,0,0,.06);
}
.schrijfhulp-card-icon {
    flex: 0 0 auto;
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 10px;
    color: #fff;
}
.schrijfhulp-card-icon.t-accent { background: var(--accent); }
.schrijfhulp-card-icon.t-info   { background: #3b82f6; }
.schrijfhulp-card-icon.t-ok     { background: #16a34a; }
.schrijfhulp-card-icon.t-warn   { background: #f59e0b; }
.schrijfhulp-card-icon.t-purple { background: #8b5cf6; }
.schrijfhulp-card-icon.t-blue   { background: #0ea5e9; }
.schrijfhulp-card-body { flex: 1 1 auto; min-width: 0; }
.schrijfhulp-card-body h4 {
    margin: 0 0 4px;
    font-size: 14px; font-weight: 600;
    color: var(--text);
}
.schrijfhulp-card-body p {
    margin: 0;
    font-size: 13px; color: var(--muted-2, var(--muted));
    line-height: 1.5;
}
.schrijfhulp-card-body code {
    background: var(--panel);
    padding: 1px 6px;
    border-radius: 4px;
    font-size: 12px;
    color: var(--text);
}

dialog.schrijfhulp-dialog .app-dialog-actions {
    padding: 0 22px 22px;
    margin: 0;
    border-top: none;
}

/* Subtle entrance animation for the schrijfhulp popup. */
@keyframes schrijfhulp-pop {
    from { opacity: 0; transform: translateY(6px) scale(.98); }
    to   { opacity: 1; transform: translateY(0)   scale(1); }
}
dialog.schrijfhulp-dialog[open] {
    animation: schrijfhulp-pop .18s var(--ease, ease-out);
}

.compose-submit-caption {
    font-size: 12.5px; color: var(--muted);
    line-height: 1.4; text-align: center;
}
.compose-submit-option.is-primary .compose-submit-caption {
    color: var(--text);
}
button.big, .button.big {
    padding: 11px 22px; font-size: 14.5px; font-weight: 600;
    border-radius: 11px;
}

/* Preview panel — sticky on the right of the form so it tracks the
   page scroll. Pins below the topbar (which is itself sticky on
   top:0 with min-height:64px + 1px border, so we offset by 80px to
   keep the preview from sliding underneath it) and stays
   top-aligned with the form on first paint via align-self:start.
   No internal overflow — the preview reads as a single visible
   card at all times. */
.compose-preview {
    position: sticky;
    top: 80px;
    /* Drop align-self:start; we want the grid cell to stretch to the
       form column so sticky tracks the full scroll. `align-self:
       stretch` is the default with `align-items: stretch` on the
       parent, but we re-state it here to be explicit + future-proof
       (any change to the grid wrapper won't accidentally break the
       sticky lock). `height: fit-content` keeps the preview's
       content height while the cell itself stretches via grid;
       without it some browsers compute the sticky element's own
       height as the full cell height and the user sees an empty
       white slab below the preview chrome. */
    align-self: stretch;
    height: fit-content;
}
.preview-shell {
    background: var(--panel); border: 1px solid var(--border);
    border-radius: var(--radius-lg); overflow: hidden;
    box-shadow: var(--shadow);
    max-width: 480px; margin: 0 auto;
}
.preview-header {
    display: flex; align-items: center; gap: 12px;
    padding: 14px 16px; border-bottom: 1px solid var(--border);
}
.preview-avatar {
    width: 40px; height: 40px; border-radius: 12px;
    background: linear-gradient(135deg, var(--accent) 0%, var(--accent-3) 100%);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 13px; letter-spacing: .5px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.15);
}
.preview-meta { flex: 1; min-width: 0; }
.preview-name { font-weight: 700; font-size: 14px; color: var(--text); letter-spacing: -.1px; }
.preview-sub { font-size: 12px; color: var(--muted); }
.preview-channel-icon {
    width: 30px; height: 30px; border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    background: var(--panel-2); color: var(--text-2);
    border: 1px solid var(--border);
}

.preview-media {
    /* Default = 1:1 square, matching LinkedIn + Facebook feed defaults and
       the overlay templates generated for those channels (1200×1200). */
    background: var(--panel-2); position: relative;
    aspect-ratio: 1 / 1;
    display: flex; align-items: center; justify-content: center;
    color: var(--muted); overflow: hidden;
}
/* Per-(channel, format) aspect ratios. The shell carries both
   data-channel and data-format; CSS picks the most specific match.
   The defaults above (1:1 square + Instagram 4:5) are the safe
   fallback for anything not listed here. */

/* Vertical short-form across providers: 9:16 portrait. */
.preview-shell[data-format="reel"] .preview-media,
.preview-shell[data-format="story"] .preview-media,
.preview-shell[data-format="short"] .preview-media {
    aspect-ratio: 9 / 16;
}
/* In-feed video (LinkedIn / Facebook) and YouTube long-form: 16:9. */
.preview-shell[data-format="video"] .preview-media,
.preview-shell[data-format="long_video"] .preview-media {
    aspect-ratio: 16 / 9;
}
/* LinkedIn document: portrait A4-ish. */
.preview-shell[data-channel="linkedin"][data-format="document"] .preview-media {
    aspect-ratio: 3 / 4;
}
/* LinkedIn article: landscape cover. */
.preview-shell[data-channel="linkedin"][data-format="article"] .preview-media {
    aspect-ratio: 1.91 / 1;
}
/* Facebook link share preview. */
.preview-shell[data-channel="facebook"][data-format="link"] .preview-media {
    aspect-ratio: 1.91 / 1;
}
/* Instagram single image: 4:5 portrait remains the default for the
   Instagram channel; carousel and poll keep the same shape. */
.preview-shell[data-channel="instagram"][data-format="carousel"] .preview-media,
.preview-shell[data-channel="instagram"][data-format="poll"] .preview-media {
    aspect-ratio: 4 / 5;
}
/* Text-only / poll on LinkedIn + Facebook: hide the media frame
   entirely so the chrome reads as a pure-text post. */
.preview-shell[data-format="text"] .preview-media,
.preview-shell[data-channel="linkedin"][data-format="poll"] .preview-media,
.preview-shell[data-channel="facebook"][data-format="poll"] .preview-media {
    display: none;
}

/* Pan-zoom cover container. Fills the .preview-media aspect-ratio
   box; the image inside is a plain 100%×100% cover-fit element. JS
   sets `transform: translate(x,y) scale(s)` on top of that to give
   the user pan/zoom — `transform-origin: 50% 50%` makes the math
   simple (translate range = wrap-dim × (scale-1) / 2). */
.preview-pan-wrap {
    position: absolute; inset: 0;
    overflow: hidden;
    user-select: none;
    touch-action: pan-y;
    /* default = nothing to drag at scale 1; cursor switches to grab
       only once the user has zoomed in (.is-pannable). */
    cursor: default;
}
.preview-pan-wrap.is-pannable { cursor: grab; }
.preview-pan-wrap.is-dragging { cursor: grabbing; }
.preview-pan-wrap.is-modified {
    box-shadow: inset 0 0 0 2px var(--accent-ring);
}
.preview-media img,
.preview-media video.preview-video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: none;
    transform-origin: 50% 50%;
    will-change: transform;
}
/* Browser-native video controls krijgen een dunne strip onderaan zonder
   de aspect-ratio van de preview te breken. */
.preview-media video.preview-video { background: #0f0f12; }
/* Reset-zoom badge — sits on top of the preview media area and only
   appears once the user has actually moved the image. Right-aligned
   so it doesn't compete with platform chrome on the left. */
.preview-reset-zoom {
    position: absolute;
    top: 8px; right: 8px;
    padding: 4px 9px;
    background: rgba(15, 17, 20, 0.78);
    color: #fff;
    border: none;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .3px;
    cursor: pointer;
    box-shadow: none;
    opacity: 0;
    pointer-events: none;
    transition: opacity .15s var(--ease), background .15s var(--ease);
    z-index: 2;
}
.preview-reset-zoom.is-visible {
    opacity: 1;
    pointer-events: auto;
}
.preview-reset-zoom:hover {
    background: var(--accent);
    color: #fff;
    transform: none;
    box-shadow: none;
    border: none;
}

/* Zoom slider — sits below the preview card as its own row so it
   doesn't sit on top of the cover photo. Hidden until a cover image
   is loaded (.has-cover toggled on .compose-preview). Styled like a
   pill control: small icon, slider, percentage label. */
.preview-zoom-bar {
    display: none;
    align-items: center;
    gap: 10px;
    margin: 12px 4px 0;
    padding: 8px 14px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 999px;
    color: var(--text-2);
}
.compose-preview.has-cover .preview-zoom-bar {
    display: flex;
}
.preview-zoom-bar svg { flex-shrink: 0; color: var(--muted); }
.preview-zoom-value {
    font-size: 12px;
    font-weight: 600;
    color: var(--muted);
    min-width: 38px;
    text-align: right;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}
.preview-zoom-bar input[type="range"] {
    flex: 1;
    -webkit-appearance: none; appearance: none;
    background: transparent;
    height: 18px; min-height: 0;
    margin: 0;
    cursor: pointer;
}
.preview-zoom-bar input[type="range"]::-webkit-slider-runnable-track {
    height: 3px;
    background: var(--border-strong);
    border-radius: 999px;
}
.preview-zoom-bar input[type="range"]::-moz-range-track {
    height: 3px;
    background: var(--border-strong);
    border-radius: 999px;
}
.preview-zoom-bar input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 14px; height: 14px;
    background: var(--accent);
    border-radius: 50%;
    margin-top: -5.5px;
    box-shadow: 0 1px 3px rgba(0,0,0,.18);
    cursor: pointer;
    transition: background .12s var(--ease);
}
.preview-zoom-bar input[type="range"]:hover::-webkit-slider-thumb {
    background: var(--accent-2);
}
.preview-zoom-bar input[type="range"]::-moz-range-thumb {
    width: 14px; height: 14px;
    background: var(--accent);
    border: none;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0,0,0,.18);
    cursor: pointer;
}
/* Overlay PNG stacked on top of the base image in the compose preview.
   Absolutely positioned so it doesn't push anything around; pointer-events
   off so clicks fall through to the empty-state placeholder behind it. */
#preview-overlay {
    position: absolute; inset: 0;
    pointer-events: none;
}

/* Custom text overlay preview — mirrors the server-side render
   (services/text_overlay.rs). The @font-face is injected per-page by the
   compose view (so each subsidiary sees their own font), and the accent
   background colour comes from --text-overlay-bg, also set per-page. */
#preview-text-overlay {
    position: absolute; inset: 0;
    /* Auto so the user can drag the text inside the photo. The image
       pan handler stops propagation when the mousedown lands on this
       element, so dragging the text doesn't also pan the image. */
    pointer-events: none;
    display: none;
    font-family: "Text Overlay", system-ui, sans-serif;
    font-weight: 800;
    line-height: 1;
    /* Container-query units scale with the preview frame so the 12% / 8.5%
       image-height values in the server renderer land in roughly the same
       spot here. `container-type: size` enables both cqw and cqh; the
       `.preview-media` aspect-ratio keeps the proportions coherent across
       Instagram portrait and LinkedIn square. */
    container-type: size;
    /* Drag offsets driven by JS — percentage of the preview frame so
       they survive aspect-ratio changes when the format switches. */
    transform: translate(var(--text-tx, 0%), var(--text-ty, 0%));
}
#preview-text-overlay.is-visible {
    display: block;
    /* Capture pointer events on the inner blocks so the drag works. */
    pointer-events: auto;
    cursor: move;
}
#preview-text-overlay.is-dragging { cursor: grabbing; }
#preview-text-overlay {
    /* --text-overlay-size is swapped per size preset below; red block
       padding + caption shadow are derived from it so they scale together
       with the text. */
    --text-overlay-size: 12cqh;
}
#preview-text-overlay[data-size="small"]  { --text-overlay-size: 9cqh; }
#preview-text-overlay[data-size="medium"] { --text-overlay-size: 12cqh; }
#preview-text-overlay[data-size="large"]  { --text-overlay-size: 15cqh; }
#preview-text-overlay .red-block {
    position: absolute;
    /* The brand-configured alpha (0..1) lives in --text-overlay-bg-opacity;
       wrapping the swatch in `color-mix` lets the photo behind shine
       through at intermediate values. */
    background: color-mix(in srgb,
        var(--text-overlay-bg, #c41e2d)
        calc(var(--text-overlay-bg-opacity, 1) * 100%),
        transparent);
    color: #fff;
    font-size: var(--text-overlay-size);
    padding: calc(var(--text-overlay-size) * 0.12) calc(var(--text-overlay-size) * 0.35);
    white-space: nowrap;
    max-width: 88%;
    overflow: hidden; text-overflow: ellipsis;
}
/* Transparent line 1 — when the brand opted out of the coloured block
   the headline renders in the same white-with-shadow style as line 2.
   The `data-no-bg="1"` flag on the overlay container is set server-side
   from the resolved brand settings, so the CSS preview matches exactly
   what the server will bake in. Padding drops to zero so the position
   math still lines up with the renderer. */
#preview-text-overlay[data-no-bg="1"] .red-block {
    background: transparent;
    padding: 0;
    text-shadow: calc(var(--text-overlay-size) * 0.04) calc(var(--text-overlay-size) * 0.04) 0 rgba(0,0,0,0.55);
}
#preview-text-overlay .rest {
    position: absolute;
    color: #fff;
    font-size: var(--text-overlay-size);
    line-height: 0.98;
    width: 88%;
    text-shadow: calc(var(--text-overlay-size) * 0.04) calc(var(--text-overlay-size) * 0.04) 0 rgba(0,0,0,0.55);
    white-space: pre-wrap;
    word-wrap: break-word;
}
/* Horizontal alignment — center is the historical default. Left/right
   sit 6% from the relevant edge to match the server-side margin. */
#preview-text-overlay[data-align="center"] .red-block,
#preview-text-overlay[data-align="center"] .rest {
    left: 50%; transform: translateX(-50%);
}
#preview-text-overlay[data-align="center"] .rest { text-align: center; }
#preview-text-overlay[data-align="left"] .red-block,
#preview-text-overlay[data-align="left"] .rest {
    left: 6%;
}
#preview-text-overlay[data-align="left"] .rest { text-align: left; }
#preview-text-overlay[data-align="right"] .red-block,
#preview-text-overlay[data-align="right"] .rest {
    right: 6%;
}
#preview-text-overlay[data-align="right"] .rest { text-align: right; }
/* Default vertical anchors (top mode) — red block upper third, caption
   immediately below it. Caption position derives from the size so the
   gap stays consistent at small/medium/large. */
#preview-text-overlay[data-position="top"] .red-block { top: 22cqh; }
#preview-text-overlay[data-position="top"] .rest      {
    top: calc(22cqh + var(--text-overlay-size) + 3.8cqh);
}
/* Middle mode: stack centred around the vertical midline of the frame. */
#preview-text-overlay[data-position="middle"] .red-block {
    top: calc(50cqh - var(--text-overlay-size) - 1.9cqh);
}
#preview-text-overlay[data-position="middle"] .rest {
    top: calc(50cqh + 1.9cqh);
}
/* Bottom mode: mirror the composition so it sits in the lower third. */
#preview-text-overlay[data-position="bottom"] .red-block {
    bottom: calc(22cqh + var(--text-overlay-size) + 3.8cqh);
}
#preview-text-overlay[data-position="bottom"] .rest { bottom: 22cqh; }
#preview-video-placeholder {
    display: none; flex-direction: column; align-items: center; gap: 8px;
    color: var(--muted); font-size: 13px; font-weight: 600;
}
#preview-empty {
    display: flex; align-items: center; justify-content: center;
    padding: 0 20px; text-align: center; font-size: 13px;
}

.preview-body { padding: 16px; }
.preview-body-label {
    font-size: 10px; color: var(--muted-2); font-weight: 700;
    text-transform: uppercase; letter-spacing: 1px; margin-bottom: 8px;
}
.preview-keywords {
    font-size: 14px; color: var(--text); line-height: 1.55;
    white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere;
    min-height: 60px;
}

.preview-footer {
    display: flex; gap: 14px; padding: 10px 16px 14px;
    border-top: 1px solid var(--border);
    font-size: 12px; color: var(--muted); font-weight: 500;
}

/* Collapse preview under the form on narrow screens */
@media (max-width: 980px) {
    .compose-split { grid-template-columns: minmax(0, 1fr); }
    .compose-preview { position: static; }
}

/* Calendar ------------------------------------------------- */
.cal-header {
    display: flex; justify-content: space-between; align-items: center; gap: 16px;
    margin-bottom: 16px; flex-wrap: wrap;
}
.cal-nav { display: flex; align-items: center; gap: 14px; }
.cal-nav > h2 { margin: 0; }
.cal-legend { display: flex; gap: 8px; flex-wrap: wrap; }
.cal-grid {
    display: grid; grid-template-columns: repeat(7, 1fr);
    gap: 6px;
}
.cal-wd {
    text-align: center; font-size: 10.5px; font-weight: 700;
    color: var(--muted); text-transform: uppercase; letter-spacing: 1px;
    padding: 4px 0 10px;
}
.cal-cell {
    min-height: 104px;
    padding: 8px 8px 10px; border-radius: 10px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    display: flex; flex-direction: column; gap: 5px;
    overflow: hidden;
}
.cal-cell.cal-out { background: transparent; border-color: transparent; color: var(--muted-2); }
.cal-cell.cal-out .cal-daynum { color: var(--muted-2); }
.cal-cell.cal-today {
    background: var(--accent-weak);
    border-color: var(--accent);
}
.cal-cell.cal-today .cal-daynum { color: var(--accent); font-weight: 700; }
.cal-daynum { font-size: 12px; font-weight: 600; color: var(--text-2); }
.cal-pill {
    display: block;
    padding: 3px 8px; border-radius: 6px;
    font-size: 11px; font-weight: 600; letter-spacing: .1px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    border: 1px solid transparent;
    transition: filter .12s var(--ease);
}
.cal-pill:hover { filter: brightness(1.08); color: inherit; }
.cal-planned   { background: var(--panel-3); color: var(--text-2); }
.cal-scheduled { background: var(--info-soft); color: var(--info); }
.cal-published { background: var(--ok-soft); color: var(--ok-strong); }

/* Report stat tiles ---------------------------------------- */
.stat-tile {
    display: flex; align-items: center; gap: 12px;
    padding: 16px 18px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xs);
}
.stat-badge {
    width: 8px; height: 40px; border-radius: 4px; flex-shrink: 0;
}
.stat-badge.t-accent { background: linear-gradient(180deg, var(--accent) 0%, var(--accent-3) 100%); }
.stat-badge.t-info   { background: linear-gradient(180deg, #3b82f6 0%, #2563eb 100%); }
.stat-badge.t-ok     { background: linear-gradient(180deg, #22c77e 0%, #16a063 100%); }
.stat-badge.t-warn   { background: linear-gradient(180deg, #f59e0b 0%, #d97706 100%); }
.stat-label {
    font-size: 10.5px; color: var(--muted);
    text-transform: uppercase; letter-spacing: 1px; font-weight: 700;
    margin-bottom: 4px;
}
.stat-value {
    font-size: 24px; font-weight: 700; color: var(--text); letter-spacing: -.5px;
    font-variant-numeric: tabular-nums;
}

.period-selector {
    display: flex; justify-content: space-between; align-items: center; gap: 14px;
    flex-wrap: wrap;
}

/* Dashboard overview counters ------------------------------ */
.stats-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 12px;
    margin-bottom: 16px;
}
.pillar-grid {
    display: flex; flex-direction: column; gap: 6px;
    padding-top: 14px; border-top: 1px solid var(--border);
}
.pillar-row {
    display: flex; justify-content: space-between; align-items: center;
    gap: 12px; padding: 8px 2px; flex-wrap: wrap;
}
.pillar-row + .pillar-row { border-top: 1px dashed var(--border); }
.pillar-name {
    font-size: 13px; font-weight: 600; color: var(--text);
    letter-spacing: -.05px;
}
.pillar-stats { display: flex; gap: 6px; flex-wrap: wrap; }
.pillar-stats strong { font-weight: 700; margin-left: 3px; }

/* Responsive ----------------------------------------------- */
@media (max-width: 640px) {
    .app { grid-template-columns: 64px 1fr; }
    .sidebar { padding: 10px 6px 20px; }
    .nav-item { width: 44px; height: 44px; }
    .content { padding: 20px 16px 48px; }
    .topbar { padding: 12px 16px; }
    .grid-2 { grid-template-columns: 1fr; }
    .tile-grid { grid-template-columns: 1fr; }
    .hero-title { font-size: 32px; letter-spacing: -.6px; }
}

/* Live related-content suggestions shown under the compose-page keywords box. */
.related-content {
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 10px 12px;
}
.related-content .related-header-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; margin-bottom: 8px; flex-wrap: wrap;
}
.related-content .related-header {
    font-size: 12px;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .06em;
}
.related-content .related-empty {
    padding: 10px 8px; font-size: 13px; color: var(--muted);
    font-style: italic;
}
.related-mode-seg {
    display: inline-flex;
    border: 1px solid var(--border);
    border-radius: 999px;
    overflow: hidden;
    background: var(--panel);
}
.related-mode-opt {
    background: transparent;
    border: 0;
    padding: 4px 12px;
    font-size: 12px; line-height: 1.4;
    color: var(--muted);
    cursor: pointer;
    transition: background .12s var(--ease), color .12s var(--ease);
}
.related-mode-opt:hover { color: var(--text); }
.related-mode-opt.is-active {
    background: var(--accent);
    color: #fff;
}
.related-content .related-list { list-style: none; padding: 0; margin: 0; }
.related-content .related-row + .related-row { margin-top: 4px; }
.related-content .related-row-btn {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 10px;
    align-items: center;
    width: 100%;
    padding: 8px 10px;
    border-radius: 8px;
    background: transparent;
    border: 1px solid transparent;
    color: var(--text);
    text-align: left;
    cursor: pointer;
    transition: background .1s var(--ease), border-color .1s var(--ease);
}
.related-content .related-row-btn:hover {
    background: var(--accent-weak);
    border-color: var(--accent);
}
.related-content .related-body { display: flex; flex-direction: column; min-width: 0; }
.related-content .related-title {
    font-size: 13.5px; line-height: 1.35;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.related-content .related-company {
    font-size: 11.5px; color: var(--muted-2);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    margin-top: 2px;
}
.related-content .related-sub {
    font-size: 12px; color: var(--muted);
    text-align: right; white-space: nowrap;
}
.related-chip {
    font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
    padding: 2px 6px; border-radius: 999px;
    background: var(--panel); color: var(--muted); border: 1px solid var(--border);
    display: inline-block;
}
.related-chip-planning { color: var(--accent); border-color: var(--accent); }
.related-chip-draft { color: var(--muted-2); }

/* Preview modal opened when a related row is clicked. */
.related-preview-backdrop {
    position: fixed; inset: 0; z-index: 1000;
    background: rgba(3, 7, 18, .55);
    display: flex; align-items: center; justify-content: center;
    padding: 20px;
    backdrop-filter: blur(4px);
    animation: related-fade .12s var(--ease);
}
@keyframes related-fade { from { opacity: 0; } to { opacity: 1; } }
.related-preview {
    position: relative;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 14px;
    max-width: 600px; width: 100%;
    max-height: 80vh; overflow: auto;
    padding: 22px 22px 18px;
    box-shadow: 0 20px 50px rgba(0,0,0,.45);
}
.related-preview-close {
    position: absolute; top: 10px; right: 12px;
    background: transparent; border: 0;
    color: var(--muted); font-size: 22px; line-height: 1;
    cursor: pointer; padding: 4px 8px;
}
.related-preview-close:hover { color: var(--text); }
.related-preview-meta {
    display: flex; align-items: center; gap: 8px;
    margin-bottom: 8px;
}
.related-preview-sub { font-size: 12.5px; color: var(--muted); }
.related-preview-title {
    margin: 0 0 12px; font-size: 18px; font-weight: 600;
    color: var(--text); line-height: 1.3;
}
.related-preview-body {
    white-space: pre-wrap;
    font-size: 14px; line-height: 1.55;
    color: var(--text);
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 12px 14px;
    margin-bottom: 16px;
    max-height: 50vh; overflow: auto;
}
.related-preview-actions {
    display: flex; justify-content: flex-end; gap: 8px;
}

/* Planning page: prominent "Download Word-template" card. Sits between
   the page header and the planning table (user view) or just above the
   import block (admin view). */
.template-download {
    padding: 14px 18px;
    background: linear-gradient(
        135deg,
        color-mix(in oklab, var(--accent) 8%, var(--panel)),
        var(--panel)
    );
    border: 1px solid color-mix(in oklab, var(--accent) 25%, var(--border));
}
.template-download-inner {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}
.template-download-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    border-radius: 10px;
    background: color-mix(in oklab, var(--accent) 15%, var(--panel));
    color: var(--accent);
    flex-shrink: 0;
}
.template-download-text {
    flex: 1 1 260px;
    min-width: 0;
    color: var(--text);
}
.template-download-text strong { font-size: 14.5px; }
.template-download-btn { flex-shrink: 0; }

/* Branding admin — accent-color pickers stacked vertically so each hex
   input gets the same breathing room as the rest of the forms (520px
   max-width matching the global form-control sizing). Two columns
   looked tidy on first glance but squeezed the hex field into ~200px
   which drifted from every other input in the tool. */
.branding-picker {
    display: flex;
    flex-direction: column;
    gap: 20px;
}
.branding-field { display: flex; flex-direction: column; gap: 8px; margin: 0; }
.branding-input-row {
    display: flex; align-items: center; gap: 10px;
}
.branding-input-row input[type="color"] {
    /* Strip the default inset appearance so the swatch looks integrated
       with the rest of the form controls. Height matches the 46px
       text-input min-height so the pair aligns perfectly. */
    appearance: none;
    -webkit-appearance: none;
    width: 56px; height: 46px;
    padding: 0;
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    background: transparent;
    cursor: pointer;
    flex-shrink: 0;
}
.branding-input-row input[type="color"]::-webkit-color-swatch-wrapper {
    padding: 4px; border-radius: 8px;
}
.branding-input-row input[type="color"]::-webkit-color-swatch {
    border: none; border-radius: 6px;
}
.branding-input-row input[type="text"] {
    flex: 1 1 auto;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    text-transform: lowercase;
    letter-spacing: 0.5px;
}
/* When the "transparant" toggle is on, fade the colour picker + hex
   field so the admin sees at a glance that the colour value is
   ignored in that mode. The toggle itself stays at full opacity. */
.text-overlay-bg-field[data-transparent="1"] .branding-input-row,
.text-overlay-bg-field[data-transparent="1"] .text-overlay-opacity-row {
    opacity: 0.45;
    filter: grayscale(0.5);
    pointer-events: none;
}
.text-overlay-bg-toggle {
    margin: 0;
}
/* Houd de opacity-slider en de "Geen blok"-pill op één lijn — was
   eerst onder elkaar, kostte extra hoogte zonder reden. */
.text-overlay-controls-row {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    margin-top: 6px;
}
.text-overlay-controls-row .text-overlay-opacity-row {
    margin-top: 0;
}
/* `form.vstack label` zet alle labels op `display: flex; flex-direction:
   column` (label boven input). Dat klopt voor klassieke field-labels,
   maar de overlay-toggle pill IS de label én bevat de checkbox + tekst
   die naast elkaar moeten staan. Override met hogere specificity. */
form.vstack label.overlay-toggle,
.form-fields.vstack label.overlay-toggle {
    display: inline-flex;
    flex-direction: row;
    gap: 8px;
    align-items: center;
    width: max-content;
    max-width: 100%;
    font-size: 13px;
    color: var(--text-2);
    letter-spacing: 0;
}
/* Compact single-line opacity control — label, narrow slider, live %.
   Capped at ~360px so it sits visually under the colour picker without
   stretching across the whole card. */
.text-overlay-opacity-row {
    display: flex; align-items: center; gap: 12px;
    margin-top: 6px;
    max-width: 380px;
    font-size: 12.5px;
    color: var(--muted);
}
.text-overlay-opacity-row > label {
    flex: 0 0 auto;
}
.text-overlay-opacity-value {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    color: var(--text);
    font-weight: 600;
    min-width: 40px;
    text-align: right;
}

/* Cross-browser slim slider: 4px track, 14px round thumb in the brand
   accent. Smaller and tidier than the chunky native control. */
.text-overlay-opacity-row input[type="range"] {
    flex: 1 1 auto;
    -webkit-appearance: none;
    appearance: none;
    height: 18px;
    background: transparent;
    cursor: pointer;
    margin: 0;
}
.text-overlay-opacity-row input[type="range"]:focus { outline: none; }
.text-overlay-opacity-row input[type="range"]::-webkit-slider-runnable-track {
    height: 4px;
    background: var(--border-strong);
    border-radius: 999px;
}
.text-overlay-opacity-row input[type="range"]::-moz-range-track {
    height: 4px;
    background: var(--border-strong);
    border-radius: 999px;
}
.text-overlay-opacity-row input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 14px; height: 14px;
    margin-top: -5px;
    border-radius: 999px;
    background: var(--accent);
    border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(0,0,0,.2);
    transition: transform .12s var(--ease);
}
.text-overlay-opacity-row input[type="range"]::-moz-range-thumb {
    width: 14px; height: 14px;
    border-radius: 999px;
    background: var(--accent);
    border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(0,0,0,.2);
    transition: transform .12s var(--ease);
}
.text-overlay-opacity-row input[type="range"]:hover::-webkit-slider-thumb,
.text-overlay-opacity-row input[type="range"]:focus-visible::-webkit-slider-thumb {
    transform: scale(1.1);
}
.text-overlay-opacity-row input[type="range"]:hover::-moz-range-thumb,
.text-overlay-opacity-row input[type="range"]:focus-visible::-moz-range-thumb {
    transform: scale(1.1);
}
.branding-preview-card {
    display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
    padding: 16px; border-radius: 12px;
    background: var(--panel-2);
    border: 1px solid var(--border);
}

/* Global-branding form accepts two pickers side-by-side. */
.branding-picker {
    grid-template-columns: 1fr 1fr;
}
.branding-preview-wrap {
    display: flex; flex-direction: column; gap: 8px;
    margin-top: 4px;
}

/* Per-subsidiary branding — each row is a two-zone card:
   ┌──────────────────────┬───────────────────────────────────┐
   │ [swatches] name      │ [primary] [secondary]  [save]     │
   │           status     │                         [reset]   │
   └──────────────────────┴───────────────────────────────────┘
   Uses CSS grid so the zones never overlap, even when the name
   wraps onto two lines. */
/* Per-bedrijf list — collapsible <details> rows. The summary shows
   the bedrijfsnaam + colour swatches + override pills so the admin
   can spot at a glance which subsidiaries deviate from the default.
   Click to expand into the full edit forms. */
.sub-branding-list {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-direction: column; gap: 8px;
}
details.sub-branding-row {
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--panel-2);
    overflow: hidden;
    transition: border-color .12s var(--ease);
}
details.sub-branding-row[open] {
    border-color: var(--accent);
    background: var(--panel);
}
.sub-branding-summary {
    list-style: none;
    display: flex; align-items: center; gap: 14px;
    padding: 12px 14px;
    cursor: pointer;
    user-select: none;
}
.sub-branding-summary::-webkit-details-marker { display: none; }
.sub-branding-summary::marker { content: ''; }
.sub-branding-summary:hover { background: var(--panel-2); }
details[open] .sub-branding-summary { background: transparent; }
.sub-branding-swatches {
    display: inline-flex; gap: 4px;
    flex-shrink: 0;
}
.sub-branding-swatch {
    display: inline-block;
    width: 20px; height: 20px;
    border-radius: 5px;
    border: 1px solid var(--border-strong);
}
.sub-branding-name {
    font-weight: 600;
    color: var(--text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sub-branding-tags {
    margin-left: auto;
    display: inline-flex; gap: 6px;
    flex-shrink: 0;
}
.sub-branding-chevron {
    flex-shrink: 0;
    color: var(--muted);
    transition: transform .2s var(--ease);
}
details[open] .sub-branding-chevron {
    transform: rotate(180deg);
    color: var(--accent);
}
.sub-branding-body {
    padding: 6px 14px 16px;
    border-top: 1px solid var(--border);
    display: flex; flex-direction: column; gap: 12px;
}
.sub-branding-body h4 {
    margin: 8px 0 4px;
    font-size: 13px; font-weight: 700;
    color: var(--text);
    letter-spacing: -.05px;
}
.sub-branding-form {
    display: inline-flex; align-items: flex-start; gap: 12px;
    margin: 0; flex-wrap: wrap;
}
.sub-branding-field {
    display: flex; flex-direction: column; gap: 4px;
    margin: 0;
}
.sub-branding-field-label {
    font-size: 11px; color: var(--muted);
    text-transform: uppercase; letter-spacing: .5px;
    font-weight: 700;
}
.sub-branding-field input[type="color"] {
    appearance: none;
    -webkit-appearance: none;
    width: 56px; height: 46px;
    padding: 0;
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    background: transparent;
    cursor: pointer;
    flex-shrink: 0;
}
.sub-branding-field input[type="color"]::-webkit-color-swatch-wrapper {
    padding: 3px; border-radius: 6px;
}
.sub-branding-field input[type="color"]::-webkit-color-swatch {
    border: none; border-radius: 4px;
}
.sub-branding-field input[type="number"],
.sub-branding-field select,
.sub-branding-field input[type="file"] {
    min-height: 46px;
}
.sub-branding-field-hint {
    font-size: 11px; color: var(--muted);
    margin-top: 2px;
}
.sub-branding-actions {
    display: inline-flex; align-items: center; gap: 8px;
    align-self: flex-end;
    margin-left: auto;
}

/* Two file-pickers side-by-side under the group-default text-overlay. */
.branding-fonts-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
}
@media (max-width: 540px) {
    .branding-fonts-row { grid-template-columns: 1fr; }
}

/* Draft gallery — grid of thumbnails with "Maak cover" / "Verwijder"
   actions stacked below each. The cover tile gets a highlighted border
   and a pill-badge so the hierarchy is obvious at a glance. */
.draft-gallery {
    list-style: none; margin: 0; padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 14px;
}
.draft-gallery-item {
    position: relative;
    display: flex; flex-direction: column; gap: 8px;
    padding: 10px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 12px;
    transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
.draft-gallery-item.is-cover {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.draft-gallery-item img {
    width: 100%; aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: 8px;
    background: #0001;
}
.draft-gallery-badge {
    position: absolute; top: 14px; left: 14px;
    padding: 4px 10px;
    background: var(--accent); color: #fff;
    border-radius: 999px;
    font-size: 11px; font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
}
.draft-gallery-actions {
    display: flex; gap: 6px; flex-wrap: wrap;
}
.draft-gallery-actions button { flex: 1 1 auto; font-size: 12px; padding: 6px 10px; }
.draft-gallery-item[draggable="true"] { cursor: grab; }
.draft-gallery-item.is-dragging { opacity: .4; }
.draft-gallery-drag {
    position: absolute; top: 14px; right: 14px;
    background: rgba(0, 0, 0, .55); color: #fff;
    padding: 2px 8px; border-radius: 999px;
    font-size: 11px; line-height: 1; letter-spacing: .5px;
    user-select: none;
    pointer-events: none;
}
.draft-gallery-alt {
    width: 100%;
    padding: 6px 10px;
    font-size: 12px;
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    background: var(--bg-elevated);
    color: var(--text);
    color-scheme: light;
}
[data-theme="dark"] .draft-gallery-alt { color-scheme: dark; }
.draft-gallery-alt:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}

/* Modal dialogs — native <dialog> element with showModal(). Used for
   the budget/entry forms so the primary overview isn't cluttered with
   input fields by default. Click-outside-to-close is wired below. */
dialog.app-dialog {
    padding: 0;
    border: 1px solid var(--border-strong);
    border-radius: 14px;
    background: var(--panel);
    color: var(--text);
    max-width: min(560px, calc(100vw - 32px));
    width: 100%;
    box-shadow: 0 20px 50px rgba(0, 0, 0, .25);
}
dialog.app-dialog::backdrop {
    background: rgba(0, 0, 0, .45);
    backdrop-filter: blur(2px);
}
dialog.app-dialog > form {
    padding: 18px 20px 20px;
    gap: 14px;
}
.app-dialog-header {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border);
}
.app-dialog-close {
    background: transparent; border: none;
    font-size: 22px; line-height: 1;
    color: var(--muted); cursor: pointer;
    padding: 4px 8px; border-radius: 8px;
    box-shadow: none;
}
.app-dialog-close:hover { color: var(--text); background: var(--panel-2); }
.app-dialog-actions {
    display: flex; gap: 10px; justify-content: flex-end;
    padding-top: 14px; margin-top: 4px;
    border-top: 1px solid var(--border);
}

/* Print stylesheet — browser "Save as PDF" becomes the PDF-export
   feature. Strips the app chrome so the budget page prints as a clean
   one-off report. Also hides every interactive control (filters,
   forms, action buttons) so the PDF reads as a snapshot. */
@media print {
    body { background: #fff; color: #000; }
    .app { display: block; }
    .sidebar, .topbar, .page-header p.page-sub, .template-download,
    .table-filter, .btn-row, form.inline, form.vstack, .actions,
    .notice, .empty, .td-actions, th.th-actions {
        display: none !important;
    }
    main.content {
        padding: 0;
        max-width: 100%;
    }
    section.card, section.card.card-stack {
        break-inside: avoid;
        box-shadow: none;
        border: 1px solid #ddd;
        padding: 12px 16px;
        margin-bottom: 12px;
    }
    .budget-stat { border: 1px solid #ddd; box-shadow: none; background: #f9f9f9; }
    .budget-trend { min-height: 120px; }
    .budget-trend-bars { height: 90px; }
    a { color: inherit; text-decoration: none; }
    /* Expanded details in print so long descriptions aren't truncated. */
    details.row-expand[open] > summary { display: none; }
    details.row-expand { display: block; }
    details.row-expand > .row-expand-body { margin-top: 0; }
}

/* Budget overview — summary stats + breakdown bars + 12-month trend.
   Shared visual language with the token-pool and reports cards. */
.budget-stat-row {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px;
}
@media (max-width: 720px) { .budget-stat-row { grid-template-columns: 1fr; } }
.budget-stat {
    padding: 14px 16px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 12px;
    display: flex; flex-direction: column; gap: 6px;
}
.budget-stat.is-over {
    background: color-mix(in srgb, var(--danger) 10%, var(--panel-2));
    border-color: color-mix(in srgb, var(--danger) 40%, transparent);
}
.budget-stat.is-ok { border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.budget-stat-label { font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.budget-stat-value { font-size: 22px; font-weight: 600; }
.budget-stat.is-over .budget-stat-value { color: var(--danger); }

.budget-progress {
    height: 8px;
    background: var(--panel-2);
    border-radius: 4px;
    overflow: hidden;
    border: 1px solid var(--border);
}
.budget-progress-bar {
    height: 100%;
    border-radius: 4px;
    transition: width .2s var(--ease);
}

.budget-breakdown {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-direction: column; gap: 10px;
}
.budget-breakdown-row {
    display: grid;
    grid-template-columns: minmax(140px, 180px) 1fr max-content;
    gap: 14px; align-items: center;
}
.budget-breakdown-bar {
    height: 10px;
    background: var(--panel-2);
    border-radius: 5px; overflow: hidden;
    border: 1px solid var(--border);
}
.budget-breakdown-fill {
    height: 100%;
    background: var(--accent);
    border-radius: 5px;
}
.budget-breakdown-amount {
    font-variant-numeric: tabular-nums;
    font-weight: 500;
}

.budget-trend {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: 6px;
    padding: 12px 0;
    align-items: end;
    min-height: 160px;
}
.budget-trend-col {
    display: flex; flex-direction: column; gap: 6px;
    align-items: center;
}
.budget-trend-bars {
    display: flex; gap: 3px; align-items: end;
    width: 100%; height: 120px;
}
.budget-trend-budget, .budget-trend-spent {
    flex: 1 1 50%;
    border-radius: 3px 3px 0 0;
    min-height: 1px;
}
.budget-trend-budget { background: var(--accent-secondary); opacity: .6; }
.budget-trend-spent  { background: var(--accent); }
.budget-trend-label  { font-size: 11px; color: var(--muted); }

.budget-legend {
    display: inline-block;
    width: 10px; height: 10px;
    border-radius: 2px;
    vertical-align: middle;
    margin-right: 4px;
}
.budget-legend-budget { background: var(--accent-secondary); opacity: .6; }
.budget-legend-spent  { background: var(--accent); }

/* Token pool admin — one card per subsidiary, two side-by-side forms
   (allowance + bonus grant) beneath a shared header row. */
.token-pool-list {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-direction: column; gap: 14px;
}
.token-pool-row {
    padding: 14px 16px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 12px;
}
.token-pool-header {
    display: flex; align-items: center; gap: 14px;
    flex-wrap: wrap;
    cursor: pointer;
    list-style: none;
    /* Accommodates a caret via ::after; keeps space on the right so the
       stats row doesn't bump against it. */
    padding-right: 28px;
    position: relative;
}
.token-pool-header::-webkit-details-marker { display: none; }
.token-pool-header::marker { content: ""; }
.token-pool-header::after {
    content: "";
    position: absolute;
    right: 8px; top: 50%;
    width: 0; height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 6px solid var(--muted-2);
    transform: translateY(-50%);
    transition: transform .12s var(--ease);
}
details.token-pool-details[open] > .token-pool-header::after {
    transform: translateY(-50%) rotate(180deg);
}
details.token-pool-details[open] > .token-pool-header {
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 14px;
}
.token-pool-header strong { font-size: 15px; }
.token-pool-stats {
    display: inline-flex; align-items: center; gap: 8px;
    font-size: 12.5px; color: var(--muted); flex-wrap: wrap;
}
.token-pool-stats .sep { color: var(--muted-2); }
.token-pool-body {
    display: grid; grid-template-columns: 1fr 1fr; gap: 20px;
}
.token-pool-body form.vstack { gap: 12px; }
.token-pool-body form.vstack .actions { padding-top: 10px; }
@media (max-width: 720px) {
    .token-pool-body { grid-template-columns: 1fr; }
}
/* Text-overlay rows carry a file input in addition to the colour picker,
   which makes the 2-column layout too cramped. Stack header on top and
   push the form to the full width below — same visual rhythm, but more
   breathing room for the file input. */
.sub-branding-row-stacked {
    grid-template-columns: 1fr;
}
.sub-branding-row-stacked .sub-branding-form {
    /* Clean grid: colour | font | actions. Stacks on narrow screens. */
    display: grid;
    grid-template-columns: max-content 1fr max-content;
    gap: 16px;
    align-items: end;
    justify-content: unset;
    align-self: stretch;
    width: 100%;
    padding-top: 10px;
    margin-top: 10px;
    border-top: 1px solid var(--border);
}
@media (max-width: 720px) {
    .sub-branding-row-stacked .sub-branding-form {
        grid-template-columns: 1fr;
    }
}

/* File-input variant of the per-subsidiary branding field. The header is
   a short label ("Font"); the currently-loaded filename moves to a muted
   hint under the input so the row header and the form controls share the
   same visual rhythm as the global settings above. */
.sub-branding-field-file .sub-branding-field-label {
    text-transform: uppercase; letter-spacing: .05em;
    color: var(--muted); font-size: 11px;
    white-space: nowrap;
}
.sub-branding-field-file input[type="file"] {
    font-size: 13px;
    padding: 10px 12px;
    min-height: 46px;
    box-sizing: border-box;
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    color: var(--text);
    cursor: pointer;
}
[data-theme="dark"] .sub-branding-field-file input[type="file"] { color-scheme: dark; }
.sub-branding-field-file input[type="file"]::file-selector-button {
    margin-right: 10px;
    padding: 6px 10px;
    background: var(--panel-2);
    border: 1px solid var(--border-strong);
    border-radius: 6px;
    color: var(--text);
    font-size: 12px;
    cursor: pointer;
}
.sub-branding-field-file input[type="file"]::file-selector-button:hover {
    border-color: var(--muted-2);
}
.sub-branding-field-hint {
    display: block;
    font-size: 11.5px;
    color: var(--muted);
    margin-top: 4px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Pillars admin — one row per pillar with a label-over-input field and a
   compact icon delete button to the right. Mirrors the rest of the app's
   form styling (inputs inherit the global text-input look) instead of
   trying to reimplement it inline. */
.pillar-form .pillar-row {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 12px;
    align-items: end;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--panel-2);
    margin-bottom: 10px;
}
.pillar-form .pillar-row:hover { border-color: var(--muted-2); }
.pillar-form .pillar-row-label {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0;
    min-width: 0;
}
.pillar-form .pillar-row-title {
    font-size: 12.5px; font-weight: 500;
    color: var(--muted);
    display: inline-flex; align-items: center; gap: 10px;
}
.pillar-form .pillar-row-slot {
    font-size: 11px; font-weight: 400;
    color: var(--muted-2);
    background: var(--panel);
    padding: 1px 6px; border-radius: 999px;
    border: 1px solid var(--border);
}
.pillar-form .pillar-row-label input {
    width: 100%;
}
.pillar-form .pillar-row-delete {
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px;
    padding: 0; border-radius: 8px;
    color: var(--muted);
    flex-shrink: 0;
    align-self: end;
    margin-bottom: 0;
}
.pillar-form .pillar-row-delete:hover {
    color: #c8344a;
    border-color: #c8344a;
    background: rgba(200, 52, 74, 0.08);
}
.pillar-form h2 {
    font-size: 15px;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .05em;
    margin: 0 0 10px;
}

/* Language segmented control on the draft page. Uses the same .channel-seg
   look as the compose channel picker for visual continuity. */
.language-card form { margin-top: 6px; }
.language-card .channel-seg button.channel-opt {
    cursor: pointer;
}

/* Compose keywords toolbar — sits under the textarea for translate status
   + the "Verrijken met web-search" action. */
.keywords-toolbar {
    display: flex; align-items: center; gap: 10px;
    margin-top: 8px; flex-wrap: wrap;
}
.keywords-toolbar button {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 13px; padding: 6px 12px;
}
.keywords-toolbar-status {
    font-size: 12.5px; color: var(--muted);
    min-height: 1em;
}
.keywords-toolbar-status[data-kind="ok"] { color: var(--accent); }
.keywords-toolbar-status[data-kind="err"] { color: #c8344a; }

/* Web-search "Verrijken" modal. Re-uses the related-preview-backdrop
   positioning / dismiss behaviour; body specifics below. */
.web-search-preview { max-width: 640px; }
.web-search-query { margin: 0 0 12px; font-size: 13px; }
.web-search-body { max-height: 55vh; overflow: auto; }
.web-search-loading {
    padding: 20px; text-align: center; color: var(--muted); font-style: italic;
}
.web-search-empty {
    padding: 16px; color: var(--muted); line-height: 1.5;
    background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px;
}
.web-search-empty code {
    background: var(--panel); padding: 1px 5px; border-radius: 4px;
    font-size: 12px;
}
.web-search-list { list-style: none; margin: 0; padding: 0; }
.web-search-row + .web-search-row { margin-top: 6px; }
.web-search-row {
    position: relative;
}
.web-search-row a {
    display: block; padding: 10px 12px; padding-right: 96px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 10px;
    color: var(--text); text-decoration: none;
    transition: border-color .1s var(--ease), background .1s var(--ease);
}
.web-search-row a:hover { border-color: var(--accent); background: var(--accent-weak); }
.web-search-row-copy {
    position: absolute; top: 8px; right: 8px;
    font-size: 12px; padding: 4px 10px;
    border-radius: 6px;
}
.web-search-row-copy.is-copied {
    color: var(--ok, #1f7a3a);
}

/* -------------------------------------------------------------------
   Inline tags — #hashtags and @mentions inside rendered post bodies.
   Keep the styling lightweight: a tint of blue/purple, no background
   block, so it reads as one paragraph with highlighted tokens. */
.tag-hash {
    color: #2563eb;
    font-weight: 500;
}
.tag-mention {
    color: #8b5cf6;
    font-weight: 500;
}
a.tag-mention.is-linked {
    text-decoration: none;
    border-bottom: 1px dashed currentColor;
    cursor: pointer;
}
a.tag-mention.is-linked:hover {
    border-bottom-style: solid;
    color: #6d28d9;
}
/* Fallback when no LinkedIn URL is curated for this @mention — links
   to the LinkedIn company-search results so the author can verify
   manually. Visually subtler (dotted) than a curated link. */
a.tag-mention.is-search {
    text-decoration: none;
    border-bottom: 1px dotted currentColor;
    cursor: pointer;
    opacity: 0.95;
}
a.tag-mention.is-search:hover {
    border-bottom-style: dashed;
    color: #6d28d9;
}
/* Plain external URLs typed in a post body render as clickable links
   in the preview. Subtle blue underline so it reads like a regular
   web link without competing visually with #/@ tokens. */
a.tag-link {
    color: #2563eb;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
    word-break: break-word;
}
a.tag-link:hover { color: #1d4ed8; }
:root[data-theme="dark"] a.tag-link { color: #60a5fa; }
:root[data-theme="dark"] a.tag-link:hover { color: #93c5fd; }
:root[data-theme="dark"] .tag-hash { color: #60a5fa; }
:root[data-theme="dark"] .tag-mention { color: #c4b5fd; }
:root[data-theme="dark"] a.tag-mention.is-linked:hover { color: #ddd6fe; }

/* Autocomplete popup floating under the textarea caret. Fixed width so
   keyboard navigation feels stable even as items come and go. */
.tag-autocomplete {
    position: absolute;
    z-index: 1100;
    min-width: 240px; max-width: 320px;
    max-height: 260px; overflow-y: auto;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0,0,0,.18);
    padding: 4px;
    display: block;
}
.tag-autocomplete[hidden] { display: none; }
.tag-autocomplete-row {
    display: flex; flex-direction: column; align-items: flex-start;
    gap: 2px;
    width: 100%; padding: 8px 10px;
    background: transparent; border: 0; border-radius: 7px;
    text-align: left; cursor: pointer;
    color: var(--text);
    font: inherit;
}
.tag-autocomplete-row:hover,
.tag-autocomplete-row.is-active {
    background: var(--accent-weak);
}
.tag-autocomplete-label {
    font-size: 13px; font-weight: 600;
}
.tag-autocomplete-hint {
    font-size: 11.5px; color: var(--muted);
}
.web-search-row-title {
    font-size: 14px; font-weight: 500; line-height: 1.35;
    color: var(--accent);
}
.web-search-row-url {
    font-size: 12px; color: var(--muted); margin-top: 2px;
}
.web-search-row-desc {
    font-size: 13px; color: var(--text); margin-top: 6px;
    line-height: 1.45;
}

/* -------------------------------------------------------------------
   Werklast — assignment dropdowns + filter pills + dashboard widgets.
   Een dunne laag bovenop het bestaande card-systeem zodat de pagina
   visueel aansluit bij /admin/branding en de overige admin-views. */

/* Filter row above the queues — knoppen zelf gebruiken de globale
   `.button` / `.button.primary` stijl; hier blijft enkel de layout-
   helper + de kleine count-badge die binnenin de knop staat. */
.queue-filter-row {
    display: flex; flex-wrap: wrap; gap: 8px;
    margin: 0 0 14px;
}
.queue-filter-count {
    font-size: 11px; font-weight: 700;
    padding: 1px 6px; border-radius: 999px;
    background: rgba(0,0,0,.12);
}
.button.primary .queue-filter-count {
    background: rgba(255,255,255,.22);
}

/* Per-row "Toewijzen aan …" select. Inline form, native select with
   our usual border + radius. */
.assignee-form select {
    min-height: 38px;
    min-width: 200px;
    padding: 4px 28px 4px 10px;
    font-size: 12.5px;
    border-radius: 8px;
}

/* Workload dashboard grid. Two-column layout with two wide rows
   underneath; collapses to single column on narrow viewports. */
.workload-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 16px;
}
.workload-widget-wide { grid-column: 1 / -1; }
@media (max-width: 900px) {
    .workload-grid { grid-template-columns: 1fr; }
    .workload-widget-wide { grid-column: 1; }
}
.workload-widget {
    display: flex; flex-direction: column; gap: 14px;
}
.workload-widget-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
}
.workload-widget-head h2 {
    margin: 0; font-size: 16px; font-weight: 700;
}
.workload-pill {
    font-size: 11.5px; font-weight: 600;
    color: var(--muted);
    padding: 3px 10px; border-radius: 999px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    text-decoration: none;
}

/* Status bar chart container — inline SVG sized via viewBox so it
   fills the widget naturally. */
.workload-chart svg {
    width: 100%; max-height: 200px;
    display: block;
    color: var(--text);
}

/* Stacked horizontal bar (per-bedrijf) */
.workload-stacked {
    display: flex; flex-direction: column; gap: 12px;
}
.workload-stacked-bar {
    display: flex; height: 14px;
    border-radius: 999px; overflow: hidden;
    background: var(--panel-2);
    border: 1px solid var(--border);
}
.workload-stacked-seg { display: block; height: 100%; }
.workload-legend {
    list-style: none; margin: 0; padding: 0;
    display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 6px 12px;
    font-size: 12.5px;
}
.workload-legend li {
    display: flex; align-items: center; gap: 8px;
    color: var(--text);
}
.workload-legend-dot {
    width: 10px; height: 10px; border-radius: 999px;
    flex: 0 0 auto;
}
.workload-legend-label {
    flex: 1 1 auto;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.workload-legend-count {
    color: var(--muted); font-size: 11.5px;
    flex: 0 0 auto;
}

/* Per-team table */
.workload-team-table {
    width: 100%;
}
.workload-team-table tr.is-unassigned td {
    background: var(--panel-2);
}
.workload-team-table strong { font-weight: 600; }
.workload-bar-track {
    position: relative;
    height: 16px; min-width: 80px;
    background: var(--panel-2);
    border-radius: 999px;
    overflow: hidden;
    border: 1px solid var(--border);
}
.workload-bar-fill {
    position: absolute; left: 0; top: 0; bottom: 0;
    background: var(--accent);
    transition: width .3s var(--ease);
}
.workload-bar-label {
    position: relative;
    display: block;
    text-align: right;
    padding: 0 10px;
    line-height: 14px;
    font-size: 11.5px; font-weight: 700;
    color: var(--text);
    mix-blend-mode: difference;
    color: #fff;
}

/* Deadlines list */
.workload-deadlines {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-direction: column; gap: 8px;
}
.workload-deadlines a {
    display: grid;
    grid-template-columns: 110px minmax(0, 1fr);
    grid-template-rows: auto auto;
    column-gap: 14px; row-gap: 2px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--panel-2);
    text-decoration: none;
    color: var(--text);
    transition: border-color .12s var(--ease);
}
.workload-deadlines a:hover { border-color: var(--accent); }
.workload-deadlines-date {
    grid-row: 1 / 3; grid-column: 1;
    font-size: 13px; font-weight: 700;
    color: var(--accent);
    align-self: center;
    font-variant-numeric: tabular-nums;
}
.workload-deadlines-title {
    grid-column: 2;
    font-size: 13.5px; font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.workload-deadlines-meta {
    grid-column: 2;
    font-size: 11.5px; color: var(--muted);
}

/* Role pills on /admin/users — colour-codes the three audience groups
   (marketing-team / bedrijfsgebruiker / partner) so the table reads
   at a glance instead of relying on a 1-word "central"/"local" cell. */
.role-pill {
    font-weight: 600;
    letter-spacing: .15px;
}
.role-pill-central {
    background: var(--accent-weak);
    color: var(--accent);
    border-color: transparent;
}
.role-pill-local {
    background: var(--panel-2);
    color: var(--text);
    border-color: var(--border);
}
.role-pill-partner {
    background: rgba(245, 158, 11, .14);
    color: #b45309;
    border-color: transparent;
}
:root[data-theme="dark"] .role-pill-partner {
    color: #fbbf24;
}

/* Clickable workload widgets — every chart element is wrapped in
   <a>, the styling here gives them subtle hover affordance without
   overriding the chart colours. */
a.workload-chart-bar { cursor: pointer; }
a.workload-chart-bar rect:not([fill="transparent"]) {
    transition: opacity .12s var(--ease);
}
a.workload-chart-bar:hover rect:not([fill="transparent"]) { opacity: 1; }

a.workload-legend-link {
    display: contents;
    text-decoration: none;
    color: inherit;
}
.workload-legend li { transition: opacity .12s var(--ease); }
.workload-legend li:hover { opacity: 0.75; }

a.workload-team-name,
a.workload-cell-link {
    display: block;
    text-decoration: none;
    color: inherit;
    padding: 2px 0;
    border-radius: 6px;
    transition: background .12s var(--ease);
}
a.workload-team-name:hover,
a.workload-cell-link:hover {
    background: var(--accent-weak);
}
.workload-team-table td { padding: 8px 10px; }

/* Super-admin pill — staat naast de gewone rol-pill op /admin/users
   wanneer de gebruiker tenant-instellingen mag wijzigen. */
.role-pill-super {
    background: #1f2937;
    color: #fbbf24;
    border-color: transparent;
    font-size: 10.5px;
    letter-spacing: .25px;
}
:root[data-theme="dark"] .role-pill-super {
    background: #fbbf24;
    color: #111827;
}

/* Status chart click-through chips — staan onder de SVG-bars en
   bieden de eigenlijke navigatie naar de matching queue. SVG zelf
   blijft pure data-visualisatie (geen <a> erin, dat blanked de
   render in sommige browsers). */
.workload-status-chips {
    list-style: none; margin: 14px 0 0; padding: 0;
    display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 6px 12px;
}
.workload-status-chip {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 10px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    text-decoration: none;
    color: var(--text);
    font-size: 12.5px;
    transition: border-color .12s var(--ease), background .12s var(--ease);
}
.workload-status-chip:hover {
    border-color: var(--accent);
    background: var(--accent-weak);
}
.workload-status-chip-dot {
    width: 8px; height: 8px; border-radius: 999px;
    flex: 0 0 auto;
}
.workload-status-chip-label {
    flex: 1 1 auto;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.workload-status-chip-count {
    font-weight: 700;
    color: var(--muted);
}
.workload-status-chip:hover .workload-status-chip-count { color: var(--accent); }

/* Per-subsidiary legend buttons (in de "Per bedrijf"-widget). Geen
   <a href> meer — de knop opent een <dialog> met openstaand werk
   van die dochter. */
button.workload-legend-link {
    display: flex; align-items: center; gap: 8px;
    width: 100%;
    padding: 4px 6px; margin: 0;
    background: transparent; border: 0;
    color: inherit; font: inherit; text-align: left;
    border-radius: 6px;
    cursor: pointer;
    transition: background .12s var(--ease);
}
button.workload-legend-link:hover { background: var(--accent-weak); }
.workload-legend-link.is-static { cursor: default; pointer-events: none; }

/* Workload sub-dialog body styling. Reuses .app-dialog skeleton from
   the schrijfhulp popup but adds list-specific bits. */
dialog.workload-sub-dialog { max-width: 640px; }
.workload-sub-list {
    list-style: none; margin: 12px 0 0; padding: 0;
    display: flex; flex-direction: column; gap: 6px;
    max-height: 60vh; overflow-y: auto;
}
.workload-sub-list a {
    display: grid;
    grid-template-columns: 80px minmax(0, 1fr);
    grid-template-rows: auto auto;
    column-gap: 12px; row-gap: 2px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--panel-2);
    color: var(--text); text-decoration: none;
    transition: border-color .12s var(--ease);
}
.workload-sub-list a:hover { border-color: var(--accent); }
.workload-sub-kind {
    grid-row: 1 / 3; grid-column: 1;
    align-self: center;
    padding: 4px 8px;
    border-radius: 999px;
    font-size: 11px; font-weight: 700;
    text-align: center;
    text-transform: uppercase;
    letter-spacing: .3px;
}
.workload-sub-kind-draft   { background: var(--accent-weak); color: var(--accent); }
.workload-sub-kind-request { background: rgba(245, 158, 11, .14); color: #b45309; }
:root[data-theme="dark"] .workload-sub-kind-request { color: #fbbf24; }
.workload-sub-title {
    grid-column: 2;
    font-size: 13.5px; font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.workload-sub-meta {
    grid-column: 2;
    font-size: 11.5px; color: var(--muted);
}

/* ─── Brand-color transitions ────────────────────────────── */
/* Register the accent custom properties so the browser knows
   they are colors and can interpolate them. Without @property the
   value would simply pop to the new colour when a subsidiary is
   switched. With it, each property animates and any background /
   border / colour / gradient that references it animates along. */
@property --accent              { syntax: '<color>'; inherits: true; initial-value: #8b2331; }
@property --accent-2            { syntax: '<color>'; inherits: true; initial-value: #711a27; }
@property --accent-3            { syntax: '<color>'; inherits: true; initial-value: #a0273a; }
@property --accent-soft         { syntax: '<color>'; inherits: true; initial-value: rgba(139,35,49,.10); }
@property --accent-weak         { syntax: '<color>'; inherits: true; initial-value: rgba(139,35,49,.06); }
@property --accent-ring         { syntax: '<color>'; inherits: true; initial-value: rgba(139,35,49,.22); }
@property --accent-secondary       { syntax: '<color>'; inherits: true; initial-value: #2c6cb0; }
@property --accent-secondary-soft  { syntax: '<color>'; inherits: true; initial-value: rgba(44,108,176,.10); }
@property --accent-secondary-weak  { syntax: '<color>'; inherits: true; initial-value: rgba(44,108,176,.06); }

:root {
    transition:
        --accent .2s var(--ease),
        --accent-2 .2s var(--ease),
        --accent-3 .2s var(--ease),
        --accent-soft .2s var(--ease),
        --accent-weak .2s var(--ease),
        --accent-ring .2s var(--ease),
        --accent-secondary .2s var(--ease),
        --accent-secondary-soft .2s var(--ease),
        --accent-secondary-weak .2s var(--ease);
}

/* ─── Collapsible sidebar ────────────────────────────────── */
/* Override the global `button` rule's padding/border-radius/box-shadow —
   without `padding: 0` the 16px chevron is clipped down to ~2px and the
   button looks empty. */
.sidebar-toggle {
    margin-left: auto;
    width: 30px; height: 30px;
    padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text-2);
    cursor: pointer;
    flex-shrink: 0;
    box-shadow: none;
    transition: background .15s var(--ease), color .15s var(--ease),
                border-color .15s var(--ease), transform .2s var(--ease);
}
.sidebar-toggle:hover {
    background: var(--panel-2); color: var(--accent);
    border-color: var(--accent);
    transform: none;
    box-shadow: none;
}
.sidebar-toggle .toggle-icon { width: 16px; height: 16px; display: block; }

.app {
    transition: grid-template-columns .2s var(--ease);
}
.sidebar {
    transition: padding .2s var(--ease);
    overflow-x: hidden;
}
.sidebar .brand,
.sidebar .nav-item,
.sidebar .nav-section-label,
.sidebar .side-footer,
.sidebar .side-switch,
.sidebar .side-user,
.sidebar .side-logout {
    transition: padding .2s var(--ease), gap .2s var(--ease),
                opacity .15s var(--ease);
}
.sidebar .brand-name,
.sidebar .brand-sub,
.sidebar .nav-label,
.sidebar .nav-section-label,
.sidebar .side-switch,
.sidebar .side-user-meta,
.sidebar .side-logout button {
    transition: opacity .15s var(--ease);
}

/* Collapsed state: 64px rail with icons only. Driven by an attribute
   on <html> so the CSS applies before first paint (the inline init
   script in `head()` reads localStorage synchronously). */
:root[data-sidebar-collapsed] .app {
    grid-template-columns: 64px 1fr;
}
:root[data-sidebar-collapsed] .sidebar {
    padding: 16px 8px 16px;
}
/* In collapsed state the brand row stacks vertically so the toggle sits
   centred underneath the logo, on the same horizontal axis as the nav
   icons (instead of crowding next to the logo). */
:root[data-sidebar-collapsed] .sidebar .brand {
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 6px 0 14px;
}
/* `display: none` (not just opacity:0+width:0) so the label doesn't
   keep claiming space via `flex: 1` and stretch the nav-item beyond
   the 40px square. */
:root[data-sidebar-collapsed] .sidebar .brand-text,
:root[data-sidebar-collapsed] .sidebar .nav-label,
:root[data-sidebar-collapsed] .sidebar .nav-section-label,
:root[data-sidebar-collapsed] .sidebar .side-switch,
:root[data-sidebar-collapsed] .sidebar .side-user-meta {
    display: none;
}
/* Each nav-item becomes a fixed 40×40 square so the active state's
   gradient tile lines up with the inactive icons instead of dwarfing
   them. `margin: 8px auto` (was 2px) gives elke icoon visuele lucht
   in de collapsed kolom — eerder plakten ze tegen elkaar. */
:root[data-sidebar-collapsed] .sidebar .nav-item {
    justify-content: center;
    padding: 0;
    width: 40px;
    height: 40px;
    margin: 8px auto;
    gap: 0;
}
/* Sectie-spacing: extra ademruimte boven de Beheer-sectie en tussen
   de drie nav-secties zodat de logische groepering ook in collapsed
   state visueel leest. */
:root[data-sidebar-collapsed] .sidebar .nav-section + .nav-section,
:root[data-sidebar-collapsed] .sidebar .collapsible-trigger {
    margin-top: 16px;
}
:root[data-sidebar-collapsed] .sidebar .nav-badge {
    position: absolute;
    top: 4px; right: 4px;
    margin: 0;
    padding: 0 5px;
    font-size: 9.5px;
    min-width: 14px;
    line-height: 14px;
}
:root[data-sidebar-collapsed] .sidebar .side-user {
    justify-content: center;
    padding: 8px;
}
:root[data-sidebar-collapsed] .sidebar .side-logout button {
    width: 100%;
    padding: 8px 4px;
    font-size: 11px;
}
/* Toggle when collapsed: arrow flips to point right (= "expand"), and
   the button widens to match the icon column of the nav items so it
   visually lines up with them. */
:root[data-sidebar-collapsed] .sidebar-toggle {
    transform: rotate(180deg);
    margin: 0;
    width: 40px;
    height: 30px;
}

/* ─── Collapsible nav-section (Beheer) ───────────────────── */
/* Reset the global `button` rule and match the look of a regular
   nav-section-label so the trigger blends in. */
.collapsible-trigger {
    background: transparent;
    border: none;
    box-shadow: none;
    padding: 16px 12px 8px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font: inherit;
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 1.2px;
    font-weight: 700;
    color: var(--muted-2);
    cursor: pointer;
    text-align: left;
    border-radius: 0;
    transition: color .15s var(--ease);
}
.collapsible-trigger:hover {
    background: transparent;
    border: none;
    color: var(--text);
    transform: none;
    box-shadow: none;
}
.collapsible-trigger .chevron {
    width: 10px; height: 10px;
    flex-shrink: 0;
    transition: transform .2s var(--ease);
}

/* Collapsed: animate items away. `max-height` is the boring-but-
   works-everywhere alternative to the grid-template-rows trick we
   tried first; the latter only animates correctly in very recent
   browsers. 800px is a generous ceiling for any plausible nav
   list. */
.nav-section-items {
    overflow: hidden;
    max-height: 800px;
    transition: max-height .25s var(--ease);
}
:root[data-beheer-collapsed] .beheer-section .nav-section-items {
    max-height: 0;
}
:root[data-beheer-collapsed] .beheer-section .collapsible-trigger .chevron {
    transform: rotate(-90deg);
}

/* In the collapsed sidebar mode the section label is hidden anyway,
   and the items are always shown — collapsing the section while the
   sidebar is collapsed would hide every item with no way to find
   them back. */
:root[data-sidebar-collapsed] .collapsible-trigger { display: none; }
:root[data-sidebar-collapsed] .nav-section-items {
    max-height: 800px !important;
}

/* ─── Compose: channel + format row ──────────────────────── */
/* Two equal columns on the form's content width; collapses to one
   column under 540px so the labels still read on mobile. */
.field-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
    align-items: start;
}
/* Zorgen dat een `<label>` binnen een grid-rij zijn input over de volle
   breedte van zijn kolom strekt — anders krimpt bv. type="number" op
   z'n intrinsieke breedte en oogt asymmetrisch naast een datetime-local. */
.field-row > label {
    display: flex; flex-direction: column; gap: 4px;
    min-width: 0;
}
.field-row > label > input,
.field-row > label > select,
.field-row > label > textarea {
    width: 100%;
}
@media (max-width: 540px) {
    .field-row { grid-template-columns: 1fr; }
}

/* The format trigger looks like a select but renders a two-up layout:
   "Kies formaat" on the left as the action verb, the current pick on
   the right as the visible state. The chevron mirrors a native select
   so the affordance is unambiguous. */
.format-trigger {
    /* Reset global button styling. Mirror de naburige <select> (LinkedIn
       kanaal-kiezer): tekst links, chevron rechts. Native selects zijn
       default left-aligned, dus deze knop moet hetzelfde aanvoelen. */
    width: 100%;
    background: var(--panel);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 9px;
    padding: 10px 14px;
    min-height: 46px;
    font: inherit;
    font-size: 14px;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    box-shadow: none;
    display: flex; align-items: center; justify-content: flex-start; gap: 12px;
    transition: border-color .15s var(--ease), background .15s var(--ease),
                box-shadow .15s var(--ease);
}
.format-trigger:hover {
    background: var(--panel);
    color: var(--text);
    border-color: var(--accent);
    transform: none;
    box-shadow: none;
}
.format-trigger:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
/* Default "Kies formaat" placeholder is muted; once the author commits
   a choice JS adds .is-chosen and the label switches to the strong
   text colour. Same element either way so there's no ghost gap. */
.format-trigger-current {
    /* `flex: 1` zodat de label-span de breedte vult. Tekst-kleur en
       font-weight zijn identiek aan een geselecteerde waarde in een
       <select>: `var(--text)` + 500 — dat matcht het naburige
       LinkedIn-select-veld zodat het paar als één control leest.
       Placeholder vs chosen onderscheidt zich nu enkel door de
       chevron + dialog-affordance, niet meer door tekst-grijs. */
    flex: 1;
    color: var(--text);
    font-weight: 500;
    font-size: 14px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    min-width: 0;
}
.format-trigger-current.is-chosen {
    color: var(--text);
    font-weight: 500;
}
.format-trigger-chevron {
    color: var(--muted-2);
    flex-shrink: 0;
}

/* Dialog layout. */
.format-dialog .app-dialog-inner {
    max-width: 760px;
}
.format-dialog-header {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 10px; margin-bottom: 16px;
}
.format-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 10px;
}
/* Tiles. Hover lifts subtly, selected tile carries the active accent.
   `min-width: 0` is the grid-item escape hatch — without it long
   bodies push the tile past its column. `overflow-wrap: anywhere` on
   the body breaks long unbroken stretches (URLs, em-dashes-without-
   space, ASCII heart emoji etc.) instead of letting them spill out. */
.format-tile {
    background: var(--panel);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 14px 16px;
    text-align: left;
    cursor: pointer;
    box-shadow: none;
    display: flex; flex-direction: column; gap: 6px;
    min-width: 0;
    transition: border-color .15s var(--ease), background .15s var(--ease),
                box-shadow .15s var(--ease), transform .15s var(--ease);
}
.format-tile:hover {
    border-color: var(--accent);
    background: var(--panel-2);
    transform: translateY(-1px);
    box-shadow: var(--shadow-sm);
}
.format-tile.is-selected {
    border-color: var(--accent);
    background: var(--accent-weak);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
/* The global `button` rule sets `align-items: center` + `white-space:
   nowrap` — neither is wanted on a tile (which has a column layout
   with a wrapping body underneath). Override here so the description
   wraps inside the tile and both lines start from the left edge. */
.format-tile {
    align-items: stretch;
    white-space: normal;
    text-align: left;
}
.format-tile-title {
    font-size: 14px; font-weight: 700; letter-spacing: -.05px;
    white-space: normal;
}
.format-tile-body {
    margin: 0;
    color: var(--muted);
    font-size: 12.5px;
    line-height: 1.45;
    overflow-wrap: anywhere;
    white-space: normal;
}

/* Overlay-mode is now two independent checkboxes (template + custom
   text) instead of a 3-way radio set. They can both be on so a
   template PNG layers under a custom text overlay. Styled like
   compact toggle pills that play nicely next to each other. */
.overlay-toggle-row {
    display: flex; gap: 8px; flex-wrap: wrap;
}
.overlay-toggle {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 8px 14px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: 13px; font-weight: 600; color: var(--text-2);
    cursor: pointer;
    transition: background .12s var(--ease), border-color .12s var(--ease),
                color .12s var(--ease);
}
.overlay-toggle:hover {
    border-color: var(--accent);
}
/* Custom checkbox: hide the native control and draw a small rounded
   square that fills with the accent + a white check on `:checked`. */
.overlay-toggle input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    width: 16px; height: 16px;
    margin: 0;
    border: 1.5px solid var(--border-strong);
    border-radius: 4px;
    background: var(--panel);
    cursor: pointer;
    position: relative;
    flex-shrink: 0;
    transition: background .12s var(--ease), border-color .12s var(--ease);
}
.overlay-toggle input[type="checkbox"]:hover {
    border-color: var(--accent);
}
.overlay-toggle input[type="checkbox"]:checked {
    background: var(--accent);
    border-color: var(--accent);
}
.overlay-toggle input[type="checkbox"]:checked::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 70%;
}
.overlay-toggle:has(input:checked) {
    background: var(--accent-weak);
    border-color: var(--accent);
    color: var(--accent);
}
/* Disabled state: gebruikt wanneer de gekozen template `allows_text_
   overlay = false` heeft. De toggle is niet klikbaar en visueel
   gedimd zodat duidelijk is waarom hij weigert. */
.overlay-toggle.is-disabled,
.overlay-toggle:has(input:disabled) {
    opacity: .5;
    cursor: not-allowed;
}
.overlay-toggle.is-disabled input[type="checkbox"],
.overlay-toggle input[type="checkbox"]:disabled {
    cursor: not-allowed;
}

/* ═════════════════════════════════════════════════════════════════
   CANONICAL FORM-CONTROL STYLING — single source of truth
   ═════════════════════════════════════════════════════════════════
   Elke `<input>`, `<select>` of `<textarea>` in het platform krijgt
   automatisch deze look — de Kanaal-dropdown op /compose is het
   referentie-uiterlijk. Specs:

       background:    var(--panel)         (wit in light, donker-blauw
                                            in dark — volgt --panel)
       border:        1px solid var(--border-strong)
       border-radius: 9px
       padding:       12px 16px            (NIET tweaken zonder reden,
                                            zorgt voor uitgelijnde rij-
                                            hoogtes met buttons)
       min-height:    46px                 (idem)
       font-size:     14px

   Toepassing: zonder enige class krijgen alle form-controls dit auto-
   matisch. Voor nieuwe componenten: gewoon `<select>...</select>` en
   `<input type="text">` — geen extra class nodig.

   Compacte varianten bestaan voor specifieke in-row contexten
   (`form.inline`, `.btn-row`, `.dash-switcher`, `.topbar`, …) zodat
   selectie-knopjes naast Bewerken/Verwijderen niet het hele rij-rythme
   doorbreken. Die overrides zijn LOKAAL gescope'd; voeg er geen toe
   buiten een aantoonbaar tight-row context.
   ═════════════════════════════════════════════════════════════════ */
input[type="text"]:not(.format-trigger):not([role="switch"]),
input[type="email"],
input[type="number"],
input[type="date"],
input[type="datetime-local"],
input[type="time"],
input[type="week"],
input[type="url"],
input[type="search"]:not(.bynder-search),
input[type="password"],
input[type="tel"],
select:not(.theme-toggle),
textarea {
    background: var(--panel);
    color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: 9px;
    /* 12 16 padding houden we identiek aan `form.vstack input`-regel
       hieronder zodat inputs binnen én buiten een vstack-form exact
       dezelfde grootte hebben. Avoiding "subtle drift" als platform-
       wide rule. */
    padding: 12px 16px;
    font: inherit;
    font-size: 14px;
    box-sizing: border-box;
    min-height: 46px;
    color-scheme: light;
    transition: border-color .12s var(--ease), box-shadow .12s var(--ease),
                background .12s var(--ease);
}
[data-theme="dark"] input[type="text"],
[data-theme="dark"] input[type="email"],
[data-theme="dark"] input[type="number"],
[data-theme="dark"] input[type="date"],
[data-theme="dark"] input[type="datetime-local"],
[data-theme="dark"] input[type="time"],
[data-theme="dark"] input[type="week"],
[data-theme="dark"] input[type="url"],
[data-theme="dark"] input[type="search"],
[data-theme="dark"] input[type="password"],
[data-theme="dark"] input[type="tel"],
[data-theme="dark"] select,
[data-theme="dark"] textarea {
    color-scheme: dark;
}
/* Globale select-stijl: strip de native chevron en zet onze eigen
   SVG-chevron op `right 14px center` zodat hij niet tegen de border
   plakt. Padding-right schuift de optie-tekst weg van de chevron.
   Specifieke contexten (.compose-editor, .admin-jump, .side-switch,
   .dash-switcher, …) bouwen hierop voort met hun eigen padding/
   font-size, maar erven de chevron + appearance gratis. Resultaat:
   één visuele taal voor elke `<select>` in het platform. */
select:not(.theme-toggle) {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 38px;
    cursor: pointer;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");
    background-repeat: no-repeat;
    background-position: right 14px center;
}
textarea { font-family: inherit; resize: vertical; min-height: 96px; line-height: 1.55; }
input:hover:not(:disabled),
select:not(.theme-toggle):hover,
textarea:hover { border-color: var(--muted-2); }
input:focus-visible,
select:not(.theme-toggle):focus-visible,
textarea:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
::placeholder { color: var(--muted-2); }

/* File inputs — custom-style the file-selector button so it lines up
   with the rest of the form. Affects every <input type="file">; the
   surrounding control still uses the global border + border-radius. */
input[type="file"] {
    background: var(--panel);
    color: var(--text-2);
    border: 1px solid var(--border-strong);
    border-radius: 9px;
    padding: 6px 14px 6px 6px;
    font: inherit;
    font-size: 13px;
    box-sizing: border-box;
    min-height: 46px;
    cursor: pointer;
    transition: border-color .12s var(--ease);
}
input[type="file"]:hover { border-color: var(--accent); }
input[type="file"]::-webkit-file-upload-button,
input[type="file"]::file-selector-button {
    background: var(--accent-weak);
    color: var(--accent);
    border: 1px solid var(--accent-ring);
    border-radius: 6px;
    padding: 6px 12px;
    margin-right: 12px;
    font: inherit;
    font-size: 12.5px;
    font-weight: 700;
    cursor: pointer;
    transition: background .12s var(--ease), color .12s var(--ease);
}
input[type="file"]:hover::-webkit-file-upload-button,
input[type="file"]:hover::file-selector-button {
    background: var(--accent);
    color: #fff;
}

/* Checkbox default — the same custom rounded square + white check
   we use on the .overlay-toggle pills, applied globally so any
   plain <input type="checkbox"> looks native to the app. Specific
   contexts that draw their own box (e.g. .overlay-toggle) keep
   winning by selector specificity. */
input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    width: 16px; height: 16px;
    margin: 0;
    border: 1.5px solid var(--border-strong);
    border-radius: 4px;
    background: var(--panel);
    cursor: pointer;
    position: relative;
    flex-shrink: 0;
    vertical-align: middle;
    transition: background .12s var(--ease), border-color .12s var(--ease);
}
input[type="checkbox"]:hover { border-color: var(--accent); }
input[type="checkbox"]:checked {
    background: var(--accent);
    border-color: var(--accent);
}
input[type="checkbox"]:checked::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 70%;
}

/* Radio default — circle with accent dot when checked. */
input[type="radio"] {
    appearance: none;
    -webkit-appearance: none;
    width: 16px; height: 16px;
    margin: 0;
    border: 1.5px solid var(--border-strong);
    border-radius: 50%;
    background: var(--panel);
    cursor: pointer;
    position: relative;
    flex-shrink: 0;
    vertical-align: middle;
    transition: background .12s var(--ease), border-color .12s var(--ease);
}
input[type="radio"]:hover { border-color: var(--accent); }
input[type="radio"]:checked {
    border-color: var(--accent);
}
input[type="radio"]:checked::after {
    content: '';
    position: absolute;
    inset: 3px;
    border-radius: 50%;
    background: var(--accent);
}

/* Admin-jump dropdown — slots into the topbar breadcrumb on every
   /admin/* page so the admin can hop pages without going back to the
   sidebar. The select carries the heavy lifting; the label is just a
   prefix tag. */
.admin-jump {
    margin-left: 12px;
    display: inline-flex; align-items: center; gap: 8px;
    padding-left: 12px;
    border-left: 1px solid var(--border);
}
.admin-jump-label {
    font-size: 11px;
    color: var(--muted-2);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .8px;
}
.admin-jump select {
    /* Override the global form select height — breadcrumbs stay on
       one line so the picker has to be compact. Padding-right ruim
       genoeg voor de gedeelde chevron (op `right 14px`) zodat de
       tekst hem niet raakt. */
    min-height: 32px;
    padding: 4px 34px 4px 10px;
    font-size: 12.5px;
    font-weight: 600;
    border-radius: 7px;
    cursor: pointer;
}

/* ─── Activity-page tabs (Publicaties / Beheer / Sessies) ───────── */
/* Pill-row die direct onder de pagina-intro hangt. Geen aria-tabs-
   dance: elke tab is gewoon een `<a>` naar `?tab=…`, dus de browser
   history werkt en hx-boost swap't enkel de body. Active-pill krijgt
   accent-soft achtergrond + accent-tekst (zelfde toon als de actieve
   nav-item in de sidebar). */
.activity-tabs {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 14px;
}
.activity-tab-pill {
    display: inline-flex;
    align-items: center;
    padding: 8px 14px;
    border-radius: 999px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-2);
    background: var(--panel-2);
    border: 1px solid var(--border);
    text-decoration: none;
    transition: background-color .12s var(--ease), color .12s var(--ease),
                border-color .12s var(--ease);
}
.activity-tab-pill:hover {
    border-color: var(--muted-2);
    color: var(--text);
}
.activity-tab-pill.active {
    background: var(--accent-soft);
    color: var(--accent);
    border-color: var(--accent-ring);
}

/* Beheer-tab: filter-bar bovenaan + audit-table met expandable detail
   rows. Filter is één compacte horizontale rij in de stijl van de
   format-trigger knop (panel bg, 1px border, accent op hover/focus,
   9px radius). Twee redenen voor de hogere specificity (`form.audit-
   filter` ipv `.audit-filter`): de globale `form.inline { display:
   inline }` regel zou anders winnen en alle velden onder elkaar
   stapelen, en we willen consistent winnen van de globale input/
   select stijling die `min-height: 46px` zet. */
.audit-filter-row { padding: 4px 0 14px; }
form.audit-filter {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    align-items: flex-end;
    margin: 0;
}
.audit-filter-field {
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
}
.audit-filter-field .field-label {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--muted);
    font-weight: 600;
}
.audit-filter-field.audit-filter-search { flex: 1 1 220px; }
form.audit-filter input,
form.audit-filter select {
    min-height: 36px;
    height: 36px;
    padding: 6px 12px;
    font-size: 13px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 9px;
    transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
form.audit-filter input:hover,
form.audit-filter select:hover {
    border-color: var(--accent);
}
form.audit-filter input:focus-visible,
form.audit-filter select:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
form.audit-filter select { width: 180px; }
.audit-filter-actions {
    display: flex;
    gap: 6px;
    align-items: center;
}
/* Knoppen in de filter-bar volgen het format-trigger patroon: panel
   bg, 1px border, 9px radius. De primary "Filter" knop houdt een
   accent-border + accent-tekst zodat hij visueel pop't tussen de
   neutrale velden zonder een zwaar gevuld vlak te worden. */
form.audit-filter button.primary,
form.audit-filter a.ghost,
form.audit-filter button {
    height: 36px;
    min-height: 36px;
    padding: 6px 16px;
    font-size: 13px;
    font-weight: 600;
    border-radius: 9px;
    border: 1px solid var(--border);
    background: var(--panel);
    color: var(--text);
    cursor: pointer;
    text-decoration: none;
    display: inline-flex; align-items: center; justify-content: center;
    transition: border-color .15s var(--ease), color .15s var(--ease),
                box-shadow .15s var(--ease);
}
form.audit-filter button.primary {
    border-color: var(--accent);
    color: var(--accent);
    background: var(--accent-soft);
}
form.audit-filter button:hover,
form.audit-filter a.ghost:hover {
    border-color: var(--accent);
    color: var(--accent);
}
form.audit-filter button:focus-visible,
form.audit-filter a.ghost:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.audit-table { width: 100%; }
.audit-table td.audit-summary {
    /* Lange samenvattingen kunnen wrap'en zonder dat de regelhoogte
       de hele tabel oprekt. */
    white-space: normal;
    line-height: 1.45;
}
.audit-table td.audit-detail-cell {
    width: 96px;
    text-align: right;
}
.audit-detail-toggle {
    font-size: 12px;
    padding: 4px 10px;
}
.audit-entity {
    background: var(--panel-2);
    padding: 2px 6px;
    border-radius: 4px;
    font-size: 11.5px;
}
.audit-entity-id {
    margin-left: 6px;
    font-size: 11.5px;
    font-family: var(--font-mono, ui-monospace, monospace);
}
.audit-detail-row td {
    background: var(--panel-2);
    padding: 0;
}
.audit-detail-row > td > div {
    padding: 14px 18px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 18px;
}
/* Native `hidden` op de detail-div wordt anders overstemd door de
   `display: grid` regel hierboven. Expliciet teruggeven. */
.audit-detail-row > td > div[hidden] { display: none; }
@media (max-width: 720px) {
    .audit-detail-row > td > div {
        grid-template-columns: minmax(0, 1fr);
    }
}
.audit-snapshot h4 {
    margin: 0 0 6px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--muted);
}
.audit-snapshot pre {
    margin: 0;
    padding: 12px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: auto;
    max-height: 360px;
    font-size: 12px;
    line-height: 1.45;
}
.audit-retention {
    margin-top: 10px;
    color: var(--muted);
    font-size: 12px;
}

/* ─── Marketing-tegels rail (top of /opdrachten) ─────────────────── */
/* Compacte tegels die van links naar rechts vloeien; horizontaal
   scrolbaar als er meer tegels zijn dan op één rij passen. Flex
   bewust gekozen boven grid: een `repeat(5, …)` grid liet lege
   trailing tracks zien wanneer marketing minder dan 5 tegels
   gepubliceerd had — flexbox laat 1, 2 of 3 tegels gewoon links
   uitlijnen zonder gaten en blijft toch op één rij. */
.marketing-tiles-rail {
    display: flex;
    flex-wrap: nowrap;
    gap: 10px;
    margin: 0 0 24px;
    overflow-x: auto;
    overflow-y: visible;
    scrollbar-width: thin;
    padding-bottom: 4px;
}
@media (max-width: 640px) {
    .marketing-tiles-rail {
        scroll-snap-type: x mandatory;
    }
}
.marketing-tiles-rail::-webkit-scrollbar {
    height: 8px;
}
.marketing-tiles-rail::-webkit-scrollbar-thumb {
    background: var(--border-strong);
    border-radius: 999px;
}
.marketing-tile {
    /* 4:5 portrait tegel. Foto vult de hele tegel (`inset: 0`); het
       tekst-paneel ligt als een vlak band onderaan over een stuk
       van de foto — geen gradient, geen border, gewoon panel-bg
       met donkere tekst. */
    position: relative;
    flex: 0 0 220px;
    aspect-ratio: 4 / 5;
    border-radius: var(--radius);
    overflow: hidden;
    background: var(--panel);
    border: 0;
    color: var(--text);
    text-decoration: none;
    box-shadow: var(--shadow-xs);
    scroll-snap-align: start;
    transition: transform .15s var(--ease), box-shadow .15s var(--ease);
    min-width: 0;
    display: block;
}
@media (max-width: 640px) {
    .marketing-tile { flex-basis: 80%; }
}
.marketing-tile:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-sm);
    color: var(--text);
}
.marketing-tile-image {
    /* Absolute fill: de foto vult de hele tegel. Het tekst-paneel
       onderaan dekt een strook af; daar zie je dus geen foto meer. */
    display: block;
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
.marketing-tile-image-fallback {
    background: linear-gradient(135deg,
        var(--accent) 0%,
        var(--accent-3) 60%,
        var(--accent-2) 100%);
}
/* Token-prijs floats top-right over de tegel-foto. Inset zodat hij
   niet de hoek raakt; backdrop-filter geeft 'm leesbaarheid bovenop
   beelden van willekeurige helderheid. Verbergt zich zelf wanneer
   de marketing-rol geen token_cost invulde (zie view: pill wordt
   alleen gerenderd als Some(cost)). */
.marketing-tile-tokens {
    position: absolute;
    top: 8px;
    right: 8px;
    padding: 4px 9px;
    background: rgba(15, 17, 20, 0.72);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .2px;
    border-radius: 999px;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
    pointer-events: none;
}
.marketing-tile-content {
    /* Geen achtergrond — de tekst staat direct op de foto. De
       leesbaarheid hangt af van de foto-keuze; format-hint vraagt
       de marketeer een rustig onderkant te kiezen. */
    position: absolute;
    inset: auto 0 0 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px 12px 12px;
    background: transparent;
    color: #1a2238;
}
/* Live-tegel typografie scoped onder `.marketing-tile`. Hardgecodeerde
   donkere tinten (i.p.v. theme-tokens) zodat de tekst altijd leesbaar
   blijft op de lichte frosted-glass strook — ook in dark-mode waar
   `--text` licht is. */
.marketing-tile .marketing-tile-title {
    font-size: 13px; font-weight: 700; letter-spacing: -.05px;
    color: #1a2238;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.marketing-tile .marketing-tile-body {
    font-size: 11.5px;
    color: rgba(26, 34, 56, 0.74);
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.marketing-tile .marketing-tile-cta {
    display: inline-flex; align-items: center; gap: 4px;
    margin-top: 2px;
    font-size: 10.5px; font-weight: 700;
    color: var(--accent);
    text-transform: uppercase; letter-spacing: .6px;
}
.marketing-tile .marketing-tile-cta svg { width: 11px; height: 11px; }

/* ─── Marketing-tegels admin (collapsible per tegel) ──────────────── */
.marketing-tiles-list {
    /* 3-koloms grid voor compacte browse-view. Een geopende rij blijft
       op kolom-breedte (geen full-span) — het formulier eronder stackt
       zijn velden vertikaal binnen die smalle kolom. */
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px;
}
@media (max-width: 980px) {
    .marketing-tiles-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
    .marketing-tiles-list { grid-template-columns: 1fr; }
}
.marketing-tile-card {
    /* Klikbare card — opent een <dialog> met het bewerk-formulier.
       Reset de native button-styling (border, bg, font, alignment)
       zodat het visueel een card blijft, niet een knop met chrome. */
    appearance: none;
    -webkit-appearance: none;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 12px 14px;
    color: var(--text);
    font: inherit;
    text-align: left;
    cursor: pointer;
    display: flex; align-items: center; gap: 14px;
    width: 100%;
    transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.marketing-tile-card:hover,
.marketing-tile-card:focus-visible {
    border-color: var(--accent);
    box-shadow: var(--shadow-sm);
    outline: none;
}
.marketing-tile-thumb {
    width: 64px; height: 48px;
    border-radius: 8px;
    background-size: cover; background-position: center;
    background-color: var(--panel-2);
    flex-shrink: 0;
}
.marketing-tile-thumb-empty {
    background-image: linear-gradient(135deg, var(--accent-soft), var(--accent-weak));
}
.marketing-tile-meta {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; gap: 4px;
}
.marketing-tile-name {
    font-weight: 700; font-size: 14px; color: var(--text);
}
.marketing-tile-sub {
    display: flex; align-items: center; gap: 8px;
    font-size: 12px;
}
/* ─── Marketing-tile bewerk-dialog (popup met form) ───────────────── */
.marketing-tile-dialog .app-dialog-inner {
    display: flex; flex-direction: column; gap: 14px;
}
/* Actie-balk onderaan: Verwijder-knop links, primary submit rechts.
   De twee zitten in aparte <form>-elementen (delete is urlencoded,
   edit is multipart) — de submit-knop in deze balk is via
   `form="tile-form-X"` gekoppeld aan de edit-form bovenin. */
.marketing-tile-action-bar {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 10px;
    padding-top: 12px;
    border-top: 1px solid var(--border);
}
.marketing-tile-action-bar > .marketing-tile-delete-form {
    margin: 0 auto 0 0;
    display: inline-flex;
}
/* Compacte form-styling scoped op de marketing-tile dialog: kleinere
   labels (uppercase mini-cap), 36px input-height, 9px radius. Override't
   bewust de globale `form.vstack label` (bigger labels + 16px gap). */
.marketing-tile-dialog form.vstack { gap: 10px; }
.marketing-tile-dialog form.vstack label { gap: 4px; }
.marketing-tile-dialog form.vstack .field-label {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--muted);
    font-weight: 600;
}
.marketing-tile-dialog form.vstack input[type="text"],
.marketing-tile-dialog form.vstack input[type="number"],
.marketing-tile-dialog form.vstack textarea,
.marketing-tile-dialog form.vstack select {
    min-height: 36px;
    padding: 7px 12px;
    font-size: 13px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 9px;
    max-width: none;
}
.marketing-tile-dialog form.vstack textarea {
    min-height: 64px;
    padding: 8px 12px;
    line-height: 1.45;
}
.marketing-tile-dialog form.vstack input:hover,
.marketing-tile-dialog form.vstack textarea:hover,
.marketing-tile-dialog form.vstack select:hover {
    border-color: var(--accent);
}
.marketing-tile-dialog form.vstack input:focus,
.marketing-tile-dialog form.vstack textarea:focus,
.marketing-tile-dialog form.vstack select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
}
/* File-input: native chrome behoudt browser-default look. */
.marketing-tile-dialog form.vstack input[type="file"] {
    min-height: 36px;
    padding: 5px 8px;
    font-size: 12px;
    cursor: pointer;
}
.marketing-tile-meta-row {
    /* Volgorde + Token-prijs naast elkaar (smalle number-inputs), de
       Actief-toggle eronder over de volle breedte. Werkt binnen de
       ~280px kolom van een geopende admin-rij. */
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    align-items: end;
}
.marketing-tile-meta-row > .overlay-toggle {
    grid-column: 1 / -1;
}
/* Preset-fieldset: groep velden die als "vaste zaken" doorgegeven
   worden naar /opdrachten/nieuw zodra een lokale gebruiker op de
   tegel klikt. Visueel afgezet met een subtiele border zodat de
   admin meteen ziet welk gedeelte op de opdracht-form gelocked
   wordt. */
.marketing-tile-preset {
    border: 1px solid var(--border);
    border-radius: 9px;
    padding: 12px 14px;
    margin: 4px 0 0;
    display: flex; flex-direction: column; gap: 10px;
    background: var(--panel-2);
}
.marketing-tile-preset > legend {
    padding: 0 6px;
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--muted);
    font-weight: 700;
}
/* Preset-banner bovenaan /opdrachten/nieuw — toont welke voorbeeld-
   opdracht actief is en welke velden daardoor gelocked zijn. */
.preset-banner {
    border-left: 3px solid var(--accent);
    background: var(--accent-soft);
    color: var(--text);
}
/* Locked partner/content_type select: visueel gedimd zodat duidelijk
   is dat hij niet aanpasbaar is. De native `disabled`-styling per
   browser is te grijs/onleesbaar; deze override geeft dezelfde look
   als een gewone select maar met een subtiele dim + lock-cursor. */
form.vstack select[data-locked][disabled] {
    opacity: .8;
    cursor: not-allowed;
    background: var(--panel-2);
}
form.vstack textarea[readonly] {
    background: var(--panel-2);
    cursor: default;
}
.marketing-tile-current {
    display: flex; align-items: center; gap: 10px;
    margin-bottom: 4px;
}
.marketing-tile-current img {
    width: 72px; height: 48px;
    object-fit: cover;
    border-radius: 7px;
    border: 1px solid var(--border);
}
.marketing-tile-current .hint { font-size: 11.5px; color: var(--muted); }
/* Mini-info banner net boven de file-input. Geeft de admin het
   verwachte aspect-ratio + dimensies mee zodat hij niet zomaar een
   tall portrait-screenshot upload't dat dan vreemd gecropped wordt. */
.marketing-tile-format-hint {
    margin: 0 0 6px;
    padding: 7px 10px;
    background: var(--accent-soft);
    border: 1px solid var(--accent-ring);
    border-radius: 7px;
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--text-2);
}
.marketing-tile-format-hint strong {
    color: var(--accent);
    font-weight: 700;
}

/* Knoppen in de admin-form: format-trigger pattern. Primary
   ("Wijzigingen opslaan" / "Tegel aanmaken") krijgt accent-border +
   accent-tekst + accent-soft fill zodat hij pop't zonder te zwaar
   te worden; secondary ("Verwijder tegel") blijft neutraal totdat
   je hover't en kantelt dan naar danger-rood. */
.marketing-tile-row > .marketing-tile-body form .actions {
    margin-top: 4px;
}
.marketing-tile-row > .marketing-tile-body form button {
    height: 36px;
    min-height: 36px;
    padding: 6px 16px;
    font-size: 13px;
    font-weight: 600;
    border-radius: 9px;
    border: 1px solid var(--border);
    background: var(--panel);
    color: var(--text);
    cursor: pointer;
    box-shadow: none;
    display: inline-flex; align-items: center; justify-content: center;
    transition: border-color .15s var(--ease), color .15s var(--ease),
                background .15s var(--ease), box-shadow .15s var(--ease);
}
.marketing-tile-row > .marketing-tile-body form button.primary {
    border-color: var(--accent);
    color: var(--accent);
    background: var(--accent-soft);
}
.marketing-tile-row > .marketing-tile-body form button:hover {
    border-color: var(--accent);
    color: var(--accent);
    transform: none;
}
.marketing-tile-row > .marketing-tile-body form button.danger:hover,
.marketing-tile-row > .marketing-tile-body form button.danger.ghost:hover {
    border-color: var(--danger, #c4423a);
    color: var(--danger, #c4423a);
}
.marketing-tile-row > .marketing-tile-body form button:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--accent-ring);
}
.marketing-tile-delete-form {
    margin: 0;
    align-self: flex-end;
    /* Verwijder-knop rechts uitlijnen op een eigen rij onder de
       primary save zodat hij niet visueel even prominent is. */
    text-align: right;
}

/* ═════════════════════════════════════════════════════════════════
   PLUGIN-TOGGLE PANEL (admin/subsidiaries/{id} > Plugins-sectie)
   ═════════════════════════════════════════════════════════════════
   Eén row per plugin. Toggle links (pill-switch), naam + omschrijving
   rechts. Per-categorie wordt gegroepeerd onder een h4 + omschrijving.
   Status-pills onderscheiden Stabiel / Beta / Binnenkort visueel zodat
   admin in één oogopslag ziet wat klikbaar is en wat roadmap.
   ═════════════════════════════════════════════════════════════════ */

/* Categorie-blok: titel + body met de plugin-rows. Tussen categorieën
   18px lucht zodat de visuele groepering duidelijk is. */
.plugin-category {
    margin-top: 14px;
}
.plugin-category:first-child { margin-top: 0; }
.plugin-category-title {
    margin: 0 0 4px;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--muted);
}
.plugin-category-desc {
    margin: 0 0 10px;
    font-size: 12.5px;
    color: var(--muted-2);
    max-width: 70ch;
    line-height: 1.5;
}

/* Container voor de rows binnen één categorie. */
.plugin-rows {
    display: flex; flex-direction: column;
    gap: 8px;
}

/* Eén plugin-row: toggle + meta naast elkaar. */
.plugin-row {
    display: flex; align-items: flex-start; gap: 14px;
    padding: 12px 14px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 9px;
    transition: background .18s var(--ease), border-color .18s var(--ease);
}
/* Korte flash na een succesvolle toggle (gezet door PLUGIN_TOGGLE_JS,
   verwijderd na 1200ms). Subtiel groen-getint zodat admin weet dat de
   actie geland is, zonder de aandacht te kapen. */
.plugin-row.is-saved {
    background: color-mix(in srgb, var(--panel-2) 75%, #22a56e 25%);
    border-color: color-mix(in srgb, var(--border) 50%, #22a56e 50%);
}
.plugin-row-toggle {
    flex: 0 0 auto;
    margin: 2px 0 0;
}
.plugin-toggle[aria-disabled="true"] { opacity: .55; cursor: not-allowed; }

.plugin-row-meta {
    flex: 1 1 auto; min-width: 0;
}
.plugin-row-head {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    margin-bottom: 3px;
}
.plugin-row-name {
    font-size: 14px; font-weight: 600;
    color: var(--text);
}
.plugin-row-desc {
    margin: 0;
    font-size: 12.5px;
    color: var(--muted);
    line-height: 1.5;
}

/* Status-pills per plugin-fase. Bewust zacht-gekleurd zodat ze niet
   met de primaire CTA-knoppen concurreren — info-laag, geen actie. */
.plugin-status-stable {
    background: rgba(34, 165, 110, 0.16);
    color: #1b6f4a;
    font-size: 11px; font-weight: 600;
}
.plugin-status-beta {
    background: rgba(217, 145, 0, 0.16);
    color: #8a5a00;
    font-size: 11px; font-weight: 600;
}
.plugin-status-planned {
    background: var(--panel-3);
    color: var(--muted);
    font-size: 11px; font-weight: 600;
}
[data-theme="dark"] .plugin-status-stable {
    background: rgba(60, 200, 130, 0.18); color: #67e0a3;
}
[data-theme="dark"] .plugin-status-beta {
    background: rgba(255, 180, 60, 0.18); color: #ffce6b;
}

/* ═════════════════════════════════════════════════════════════════
   MARKETING-PREP UI (compose-page bij marketing_only planning-items)
   ═════════════════════════════════════════════════════════════════ */

/* Blokkerende banner voor lokale gebruikers — vervangt de hele editor.
   Zacht-blauwe info-styling, niet rood (geen fout, gewoon "wacht op
   marketing"). Pakt visueel ruimte zodat 't duidelijk is dat dit de
   eindstaat is voor de gebruiker, niet een tussenstap. */
.marketing-prep-blocker {
    background: linear-gradient(135deg, var(--panel) 0%,
                color-mix(in srgb, var(--panel) 80%, var(--accent) 20%) 100%);
    border-left: 4px solid var(--accent);
}
.marketing-prep-blocker h2 {
    color: var(--accent);
}

/* Sub-banner voor marketing zelf — kleinere strip bovenaan de editor,
   herinnert eraan dat de submit naar approval gaat ipv direct
   publiceren. Bewust opvallend zodat marketing niet per ongeluk denkt
   dat het een gewone post is. */
.marketing-prep-notice {
    margin: 0 0 16px;
    padding: 10px 14px;
    background: color-mix(in srgb, var(--panel) 70%, var(--accent) 30%);
    color: var(--accent);
    border-radius: 9px;
    border: 1px solid color-mix(in srgb, var(--border) 50%, var(--accent) 50%);
    font-size: 13.5px;
    line-height: 1.55;
}
.marketing-prep-notice strong { color: var(--text); }
.marketing-prep-notice code {
    background: var(--panel-2);
    padding: 1px 6px; border-radius: 4px;
    font-size: 12px;
}

/* ═════════════════════════════════════════════════════════════════
   CAPTURE ADMIN — /admin/capture
   ═════════════════════════════════════════════════════════════════
   Drie sub-secties (stijl-profielen / foto-types / video-scenario's)
   met elk een lijst van kaart-achtige rijen + een create-form
   onderaan. Layout volgt de algemene admin-section styling; alleen
   de kaart-grid is hier nieuw.
   ═════════════════════════════════════════════════════════════════ */

.capture-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 12px;
    margin-top: 14px;
}

.capture-card {
    padding: 14px 16px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 10px;
}

.capture-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 6px;
}

.capture-card-title {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
}

.capture-card-desc {
    margin: 0 0 8px;
    font-size: 12.5px;
    color: var(--muted);
    line-height: 1.5;
}

.capture-card-meta {
    margin: 8px 0 0;
    padding: 0;
    list-style: none;
    font-size: 12px;
    color: var(--muted);
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.capture-card-meta li code {
    font-size: 11px;
    background: var(--panel-3);
    padding: 1px 5px;
    border-radius: 3px;
}
/* Bewerken-link onderaan elke kaart. Mat-knop-stijl zodat het visueel
   minder dwingend leest dan de primary CTAs in de forms eronder. */
.capture-card-actions {
    margin-top: 10px;
    display: flex;
    gap: 8px;
}

/* Stijl-instructie + AI-interpretatie blok op /admin/capture.
   Visueel afgegrensd van de gewone form-velden zodat duidelijk is
   dat hier iets "magisch" gebeurt (LLM-aanroep). */
.style-interpret {
    margin-top: 4px;
    padding: 12px 14px;
    background: var(--accent-weak);
    border: 1px solid var(--accent-ring);
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.style-interpret-input {
    width: 100%;
    min-height: 60px;
    resize: vertical;
}
.style-interpret-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.style-interpret-status {
    font-size: 12.5px;
    color: var(--muted);
    min-height: 1.1em;
}
.style-interpret-status.is-error { color: var(--accent-3, #c92a2a); }
.style-interpret-status.is-success { color: var(--accent); }
.style-interpret-preview {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 8px 12px;
}
.style-interpret-preview-pre {
    margin: 8px 0 0;
    font-size: 11.5px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    white-space: pre-wrap;
    word-break: break-word;
    color: var(--text-2);
}

/* ─── Plugin-access matrix op /admin/users/{id}/access ──────────────
   Eén rij per plugin met links de naam + omschrijving, rechts een
   drie-staps pill-group (Default / Wel / Niet). Radio's onder de
   pills zijn verstopt; het label wordt zelf de klikbare pill. */
.access-rows {
    list-style: none;
    margin: 14px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.access-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px;
    padding: 12px 14px;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 10px;
}
.access-row-meta {
    flex: 1 1 auto;
    min-width: 0;
}
.access-row-head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.access-row-desc {
    margin: 4px 0 0;
    color: var(--muted);
    font-size: 12.5px;
    line-height: 1.45;
}
.access-row-choice {
    display: inline-flex;
    flex-shrink: 0;
    background: var(--panel-3);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 3px;
    gap: 2px;
}
.access-pill {
    padding: 6px 12px;
    border-radius: 999px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--muted);
    cursor: pointer;
    transition: background-color .12s var(--ease), color .12s var(--ease);
}
.access-pill input[type="radio"] {
    /* Radio onzichtbaar maken — het label IS de visuele control. */
    position: absolute;
    opacity: 0;
    pointer-events: none;
    width: 0;
    height: 0;
}
.access-pill:hover { color: var(--text); }
.access-pill.checked {
    background: var(--accent);
    color: #fff;
}

/* ═════════════════════════════════════════════════════════════════
   Channel-picker — strategie-wizard
   ─────────────────────────────────────────────────────────────────
   Vervangt de oude native-checkbox-rij die in dark mode kaduuk
   renderde (4 dunne pinky verticale streepjes). Pattern: label wraps
   een hidden native checkbox + zichtbare tegel met icon + tekst.
   `:has(input:checked)` doet de checked-styling zonder JS. Vereist
   moderne browsers (Safari 15.4+, Chrome 105+) — voor Cortex gebruik
   ruim voldoende, fallback in oude browsers = unchecked-look maar de
   checkbox blijft submittable.
   ═════════════════════════════════════════════════════════════════ */
.ch-fieldset {
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 14px 16px 18px;
    margin: 0;
}
.ch-legend {
    padding: 0 8px;
    font-size: 13px;
    font-weight: 600;
    color: var(--muted);
}
.ch-group-label {
    margin: 8px 0 6px;
    font-size: 12px;
    font-weight: 600;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.ch-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
    gap: 10px;
    margin-bottom: 4px;
}
.ch-card {
    /* CSS-var `--ch-accent` wordt per-tegel inline gezet vanuit Rust
       (kanaal-merkkleur). Default = platform-accent als de variabele
       ontbreekt — beschermt tegen typo's. */
    --ch-accent: var(--accent, #2563eb);
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 14px 8px 12px;
    min-height: 84px;
    border: 2px solid var(--border);
    border-radius: 12px;
    background: var(--panel);
    color: var(--text);
    cursor: pointer;
    transition: border-color .12s var(--ease, ease-out),
                background .12s var(--ease, ease-out),
                transform .08s var(--ease, ease-out);
    user-select: none;
    -webkit-user-select: none;
}
.ch-card:hover {
    border-color: var(--border-strong, var(--border));
    background: var(--panel-2, var(--panel));
}
.ch-card:active { transform: scale(0.98); }

/* Native input volledig verbergen — de label-tegel IS de visuele
   knop. `width:1px;height:1px;opacity:0` houdt 'm submittable + a11y-
   accessible, in tegenstelling tot `display:none`. */
.ch-card input[type="checkbox"] {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    opacity: 0;
    margin: 0;
    cursor: pointer;
}
.ch-card-icon {
    font-size: 22px;
    font-weight: 700;
    line-height: 1;
    width: 36px; height: 36px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 8px;
    background: color-mix(in srgb, var(--ch-accent) 14%, transparent);
    color: var(--ch-accent);
    transition: background .12s var(--ease, ease-out),
                color .12s var(--ease, ease-out);
}
.ch-card-label {
    font-size: 13px;
    font-weight: 500;
    line-height: 1.2;
    text-align: center;
    color: var(--muted);
    transition: color .12s var(--ease, ease-out);
}

/* Checked-state — :has() lift de styling op de label-zelf. */
.ch-card:has(input[type="checkbox"]:checked) {
    border-color: var(--ch-accent);
    background: color-mix(in srgb, var(--ch-accent) 8%, var(--panel));
}
.ch-card:has(input[type="checkbox"]:checked) .ch-card-icon {
    background: var(--ch-accent);
    color: #fff;
}
.ch-card:has(input[type="checkbox"]:checked) .ch-card-label {
    color: var(--text);
    font-weight: 600;
}

/* Focus-ring voor toetsenbordgebruikers. */
.ch-card input[type="checkbox"]:focus-visible ~ .ch-card-icon {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--ch-accent) 35%, transparent);
}
