@import url('https://fonts.googleapis.com/css2?family=Source+Sans+3:wght@300;400;500;600;700&display=swap');

*,
*::before,
*::after {
    box-sizing: border-box;
}

.required-asterisk {
    color: var(--danger);
}

:root {
    --card: #ffffff;
    --border: #e5e7eb;
    --foreground: #000000;
    --muted: #f2f4f2;
    --muted-foreground: #6b7280;

    /* Brand green (primary) — the app's one accent color, used for buttons,
       links, active/selected states, and every "success/done" surface. */
    --primary: #52a875;
    --primary-hover: #46915f;
    --primary-foreground: #ffffff;
    --primary-link: #2f7a54;
    /* Pale-green "info/done" surface (status-badge--done, config-card,
       chapter-intro, submit-box, uitvraag-info, etc.) and its own text pair
       — same relationship to each other as --foreground/--muted-foreground,
       just scoped to this tinted surface instead of the plain white card. */
    --primary-subtle-bg: #eaf5ef;
    --primary-subtle-border: #bfe3d0;
    --primary-subtle-strong-foreground: #1c2b1c;
    --primary-subtle-muted-foreground: #6b7b6b;

    /* Amber "pending/waiting" surface (status-badge--pending) plus one
       separate, more saturated solid amber for the small deadline dot —
       intentionally not derived from the pale trio above (different use:
       a small solid indicator vs. a pale badge background). */
    --warning-bg: #fdf1d6;
    --warning-border: #f0d9a0;
    --warning-foreground: #92650a;
    --warning-solid: #f0b429;

    /* 017-fase-tracker: blue "awaiting someone else's action" surface —
       status-badge--info / a school that has submitted and is now waiting on
       its Bestuur to accordate. Deliberately a new hue, not a shade of
       --warning: --warning already means "in_behandeling" (the respondent is
       still actively working on it, nothing to review yet), a distinct state
       from "submitted, sits in your queue" that this app had no way to show
       differently from --primary-subtle ("done") before now. */
    --info-bg: #e8f0fb;
    --info-border: #bcd6f2;
    --info-foreground: #2f5d92;
    --info-solid: #4a7fc4;

    /* Red "error/required" surface and text. */
    --danger: #b91c1c;
    --danger-bg: #fdf1f1;
    --danger-border: #f3c6c6;
    --danger-foreground: #7a1c1c;
    --danger-muted-foreground: #8a4a4a;

    /* One-off neutrals — each used in exactly one place today, kept as named
       tokens for the same reason as everything above (a hardcoded hex in the
       middle of a rule gives no hint what it means or where else it's used). */
    --placeholder-foreground: #b0b6bd;
    --select-option-foreground: #1a1a1a;
    /* Deliberately lighter than --muted (see .data-share-table__row--
       subcategory's own comment) — this shade covers much more area at once,
       so a stronger gray would read as heavier than intended. */
    --subtle-hover-bg: #f8f9f8;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
    --shadow-md: 0 4px 10px rgba(0, 0, 0, 0.06);
    --shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);

    /* Semi-transparent overlays — grouped separately from the solid colors
       above since these are computed as "X% white/black over whatever sits
       underneath" rather than a fixed hex, so they only make sense named by
       role, not shade. */
    --overlay-backdrop: rgba(0, 0, 0, 0.5);
    --overlay-on-light-hover: rgba(0, 0, 0, 0.15);
    /* White-over-primary family — every one of these sits on the green
       .page-header bar (background: var(--primary)); named by role since
       "white at N% opacity" means something different depending on whether
       it's a hover fill, an avatar background, or body text. */
    --overlay-on-primary-hover: rgba(255, 255, 255, 0.15);
    --overlay-on-primary-avatar: rgba(255, 255, 255, 0.2);
    --overlay-on-primary-faint: rgba(255, 255, 255, 0.6);
    --overlay-on-primary-muted: rgba(255, 255, 255, 0.7);

    /* Type scale — every font-size in this file goes through one of these
       ten steps (1px/0.0625rem apart from --font-size-2xs through
       --font-size-xl, matching this UI's existing granularity), rather than
       a raw rem value repeated at each call site. Two values that appeared
       exactly once each (0.7rem, 0.8rem, on .role-switcher's own label/
       select) were off by 0.0125rem from the nearest real step here and
       have been snapped onto it (--font-size-sm/--font-size-base) as a
       byproduct of centralizing — imperceptible, not a value anyone chose
       on purpose to be exactly 0.0125rem off from a name-worthy step. */
    --font-size-2xs: 0.5625rem;
    --font-size-xs: 0.625rem;
    --font-size-sm: 0.6875rem;
    --font-size-md: 0.75rem;
    --font-size-base: 0.8125rem;
    --font-size-lg: 0.875rem;
    --font-size-xl: 0.9375rem;
    --font-size-2xl: 1rem;
    --font-size-3xl: 1.375rem;
    --font-size-4xl: 1.5rem;

    /* --font-family-base is set once on body and inherited everywhere else
       (every other rule already says font-family: inherit, never repeating
       the value) — named here for the same reason as everything else in
       this block. --font-family-mono is the deliberate exception, used only
       for tabular numeric/code alignment (BRIN/bestuursnummer codes, phone
       numbers, currency inputs). */
    --font-family-base: "Source Sans 3", sans-serif;
    --font-family-mono: monospace;

    /* Fully round (avatars, pills, badges) — was split between 9999px (7
       uses) and 999px (1 use, html::-webkit-scrollbar-thumb) with no visual
       difference intended; unified onto one value/token. */
    --radius-full: 9999px;

    /* One shared hover-affordance speed — was split between 0.15s ease (7
       uses) and 0.2s ease (17 uses) across otherwise-identical
       color/border/transform hover transitions, with nothing distinguishing
       which components got which speed (organic drift, not a deliberate
       two-tier system). Unified onto the majority value. Not used for the
       two distinct-property, single-use transitions elsewhere (width 0.4s,
       max-height 0.25s) — those are larger visual changes on different
       properties, plausibly deliberate, and don't repeat anywhere. */
    --transition-base: 0.2s ease;

    /* Uppercase-label letter-spacing — two real tiers already existed
       (0.03em for table/category column headers, 0.05em for standalone
       small-caps labels like eyebrows/brand name); 0.04em
       (.role-switcher__label) was a single stray value sitting between them
       and has been snapped onto --letter-spacing-wider, matching its
       "prominent standalone label" role. --letter-spacing-tight is the one
       remaining non-uppercase use (.page-header__title). */
    --letter-spacing-tight: 0.02em;
    --letter-spacing-wide: 0.03em;
    --letter-spacing-wider: 0.05em;
}

html {
    /* Reserves the vertical scrollbar's width up front so pages whose content
       height straddles the viewport (e.g. toggling scholen/besturen on
       Contactgegevens) don't shift centered content sideways when the
       scrollbar appears/disappears. Styled to blend into the background below
       so the reserved space doesn't read as a bare grey bar when it's not
       actually needed for scrolling. */
    scrollbar-gutter: stable;
    scrollbar-width: thin; /* Firefox */
    scrollbar-color: transparent transparent; /* Firefox: thumb, track */
}

html::-webkit-scrollbar {
    width: 10px;
}

html::-webkit-scrollbar-track {
    background: transparent;
}

html::-webkit-scrollbar-thumb {
    background: transparent;
    border-radius: var(--radius-full);
}

html:hover::-webkit-scrollbar-thumb {
    background: var(--overlay-on-light-hover);
}

body {
    font-family: var(--font-family-base);
    margin: 0;
    background: var(--muted);
    color: var(--foreground);
}

.page-header {
    position: sticky;
    top: 0;
    z-index: 10;
    height: 3.25rem;
    background: var(--primary);
    color: var(--primary-foreground);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0 1.25rem;
    box-shadow: var(--shadow-sm);
}

.page-header__left {
    display: flex;
    align-items: center;
    gap: 1.5rem;
}

.page-header__brand {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.page-header__brand--switchable {
    cursor: pointer;
    text-decoration: none;
    color: inherit;
    padding: 0.25rem 0.375rem;
    margin: -0.25rem -0.375rem;
    border-radius: 0.375rem;
    transition: background-color var(--transition-base);
}

.page-header__brand--switchable:hover {
    background: var(--overlay-on-primary-hover);
}

.page-header__brand-text {
    display: flex;
    flex-direction: column;
    line-height: 1.1;
}

.page-header__brand-name {
    font-weight: 700;
    font-size: var(--font-size-md);
    letter-spacing: var(--letter-spacing-wider);
    text-transform: uppercase;
}

.page-header__brand-sub {
    font-size: var(--font-size-md);
    letter-spacing: var(--letter-spacing-wide);
    text-transform: uppercase;
    color: var(--overlay-on-primary-muted);
}

.page-header__back {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    color: var(--overlay-on-primary-muted);
    font-size: var(--font-size-lg);
    font-weight: 500;
    text-decoration: none;
}

.page-header__back:hover {
    color: var(--primary-foreground);
}

.page-header__title {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    font-weight: 600;
    font-size: var(--font-size-lg);
    letter-spacing: var(--letter-spacing-tight);
    white-space: nowrap;
}

.page-header__right {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.page-header__user {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.page-header__help-button {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
    border-radius: 0.375rem;
    background: var(--overlay-on-primary-hover);
    color: var(--overlay-on-primary-muted);
    border: none;
    font-family: inherit;
    font-size: var(--font-size-md);
    font-weight: 600;
    cursor: pointer;
    transition: background-color var(--transition-base), color var(--transition-base);
}

.page-header__help-button:hover {
    background: var(--overlay-on-primary-avatar);
    color: var(--primary-foreground);
}

.page-header__divider {
    flex-shrink: 0;
    width: 1px;
    height: 1.25rem;
    background: var(--overlay-on-primary-hover);
}

.page-header__avatar {
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--radius-full);
    background: var(--overlay-on-primary-avatar);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.page-header__user-text {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1.2;
}

.page-header__user-name {
    font-weight: 500;
    font-size: var(--font-size-lg);
}

.page-header__user-org {
    font-size: var(--font-size-md);
    color: var(--overlay-on-primary-faint);
}

.landing-content {
    max-width: 42rem;
    margin: 0 auto;
    padding: 2.5rem 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 2.5rem;
}

.page-title-block__title {
    margin: 0;
    font-size: var(--font-size-4xl);
    font-weight: 600;
    color: var(--foreground);
}

.page-title-block__subtitle {
    margin: 0.25rem 0 0;
    font-size: var(--font-size-lg);
    color: var(--muted-foreground);
}

.landing-section__title {
    margin: 0 0 1rem;
    font-size: var(--font-size-2xl);
    font-weight: 600;
    color: var(--foreground);
}

.landing-section__title + .landing-section__subtitle {
    margin-top: -0.75rem;
}

.landing-section__subtitle {
    margin: 0 0 1rem;
    font-size: var(--font-size-base);
    color: var(--muted-foreground);
}


.landing-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    overflow: hidden;
    box-shadow: var(--shadow-sm);
}

.landing-card--list .landing-card__row + .landing-card__row {
    border-top: 1px solid var(--border);
}

/* var(--subtle-hover-bg), not var(--muted) -- .landing-card itself is white
   (var(--card)), and var(--muted) is the page's own background, so that
   used to make a hovered row blend into/disappear against the page instead
   of highlighting it. Same fix already applied to .portaal-table's own
   row hover below. */
.landing-card--list .landing-card__row:hover {
    background: var(--subtle-hover-bg);
}

.landing-card__row {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1rem 1.25rem;
    transition: background-color var(--transition-base);
}

.landing-card__icon {
    flex-shrink: 0;
    width: 2.25rem;
    height: 2.25rem;
    /* Square, not round — matches .setup-card__icon's treatment of this same
       file_text_icon() glyph elsewhere (portaal.html's "Uitvraag aanpassen"
       card); round is reserved for person/avatar and step-marker icons only
       (.page-header__avatar, .sidebar__chapter-number), never a content
       icon like this one. */
    border-radius: 0.375rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.landing-card__icon--pending {
    background: var(--primary-subtle-bg);
    color: var(--primary);
}

.landing-card__icon--done {
    background: var(--muted);
    color: var(--muted-foreground);
}

.landing-card__text {
    flex: 1;
    min-width: 0;
}

.landing-card__title {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: 600;
    color: var(--foreground);
}

.landing-card__title--done {
    font-weight: 500;
}

.landing-card__meta {
    margin: 0.125rem 0 0;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

.landing-card__deadline {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    margin: 0.125rem 0 0;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

.landing-card__deadline-dot {
    flex-shrink: 0;
    width: 0.375rem;
    height: 0.375rem;
    border-radius: var(--radius-full);
    background: var(--warning-solid);
}

/* Custom tooltip -- for any hover text worth actually reading (a disabled
   button's "why", a locked field's explanation), not the browser's native
   `title` bubble: small, plain, OS-styled, slow to appear, and fixed-width
   in a way that wraps long Dutch sentences awkwardly. Pure CSS (:hover/
   :focus-visible), no JS: give any element `data-tooltip="..."` instead of
   `title="..."` and it gets this wider, app-styled bubble instead. Works
   directly on a disabled button/input too -- Chrome/Firefox still match
   :hover on a disabled form control for CSS purposes (only JS mouse events
   are suppressed there), which is exactly the majority of this app's own
   use cases (a disabled "why" explanation). */
[data-tooltip] {
    position: relative;
}

/* A <form> used as a tooltip anchor is block-level by default -- it
   stretches to fill its container's full width (a whole .config-card, a
   table cell wider than its own content), not just its own actual content.
   [data-tooltip]::after centers itself on ITS OWN element's box (left: 50%
   of that box, not of the visible field inside it), so an un-shrunk form
   puts the bubble somewhere off to the side of the real field instead of
   above it. Shrinking it to its own content here fixes every current and
   future form used this way in one place, instead of a one-off fix per
   template. (A <td> used the same way needs its own fix, not this one --
   display: inline-block would break its table-cell layout entirely.) */
form[data-tooltip] {
    display: inline-block;
}

[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 0.5rem);
    left: 50%;
    transform: translateX(-50%) translateY(0.25rem);
    width: max-content;
    max-width: 18rem;
    padding: 0.5rem 0.75rem;
    background: var(--card);
    color: var(--foreground);
    border: 1px solid var(--border);
    font-size: var(--font-size-sm);
    font-weight: 400;
    line-height: 1.4;
    text-align: left;
    white-space: normal;
    border-radius: 0.375rem;
    box-shadow: var(--shadow-md);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--transition-base), transform var(--transition-base);
    z-index: 40;
}

[data-tooltip]::before {
    content: "";
    position: absolute;
    bottom: calc(100% + 0.125rem);
    left: 50%;
    transform: translateX(-50%) translateY(0.25rem);
    border: 5px solid transparent;
    border-top-color: var(--card);
    filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.08));
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--transition-base), transform var(--transition-base);
    z-index: 40;
}

[data-tooltip]:hover::after,
[data-tooltip]:hover::before,
[data-tooltip]:focus-visible::after,
[data-tooltip]:focus-visible::before {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}

.btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    font-weight: 600;
    line-height: 1;
    border-radius: 0.25rem;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base);
}

.btn svg {
    flex-shrink: 0;
}

/* The loader-circle icon shown in place of a button's own icon (or
   prepended, for a text-only button) while a one-shot async action is in
   flight -- withButtonLoading()/loginFormLoading() in app.js,
   _icon_loader.html's own comment. First @keyframes in this file: nothing
   else needed a continuous animation before this. */
@keyframes icon-spin {
    to {
        transform: rotate(360deg);
    }
}

.icon-spin {
    /* display: inline (the <svg> default) makes the rotation pivot land
       slightly off the visual center in some browsers -- inline elements get
       baseline/vertical-align-driven box quirks that a transform's default
       50% 50% origin then inherits, which reads as a wobble rather than a
       clean spin-in-place. display: block on a fixed-size, already-centered
       icon removes that ambiguity outright. */
    display: block;
    animation: icon-spin 0.8s linear infinite;
}

.btn--md {
    padding: 0.625rem 1.25rem;
    font-size: var(--font-size-lg);
}

.btn--sm {
    padding: 0.5rem 0.875rem;
    font-size: var(--font-size-base);
}

.btn--primary {
    background: var(--primary);
    color: var(--primary-foreground);
    border: 1px solid var(--primary);
}

.btn--primary:hover:not(:disabled) {
    background: var(--primary-hover);
    border-color: var(--primary-hover);
}

.btn--primary:disabled {
    /* var(--muted) is the page's own background (body { background:
       var(--muted); }) -- a disabled button using it as its own fill
       reads fine sitting inside a white card, but disappears entirely
       once nothing white is behind it (e.g. portaal.html/landing.html's
       "Uitvraag verzenden" buttons, or questions.html's "Uitvraag
       indienen", which never had a card wrapper to begin with). A plain
       white/card fill with a visible border gives it its own contrast
       regardless of what it's sitting on. */
    background: var(--card);
    border-color: var(--border);
    color: var(--muted-foreground);
    cursor: not-allowed;
}

.btn--outline {
    background: transparent;
    color: var(--muted-foreground);
    border: 1px solid var(--border);
}

.btn--outline:hover:not(:disabled) {
    border-color: var(--primary);
    color: var(--primary);
}

.btn--outline:disabled {
    color: var(--muted-foreground);
    border-color: var(--border);
    opacity: 0.6;
    cursor: not-allowed;
}

/* 018-vragenlijst-vrijgave: a one-time "versturen" action's own completed
   state — the button stays in place (same text slot, past tense) rather
   than disappearing, using the same pale-green "done" surface as
   .status-badge--done/.config-card so it reads as "finished", not merely
   "disabled". Always rendered disabled — there's nothing left to click. */
.btn--done {
    background: var(--primary-subtle-bg);
    color: var(--primary);
    border: 1px solid var(--primary-subtle-border);
    cursor: default;
}

.btn--done:disabled {
    opacity: 1;
}

.setup-section {
    margin-bottom: 2.5rem;
}

.setup-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 1rem;
}

.setup-card {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1.25rem;
    text-align: left;
    text-decoration: none;
    font-family: inherit;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    cursor: pointer;
    transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.setup-card:hover:not(:disabled) {
    border-color: var(--primary);
    box-shadow: var(--shadow-md);
}

.setup-card:disabled {
    cursor: not-allowed;
    opacity: 0.7;
}

.setup-card__top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
}

.setup-card__icon {
    flex-shrink: 0;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 0.375rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--primary-subtle-bg);
    color: var(--primary);
    transition: background-color var(--transition-base), color var(--transition-base);
}

.setup-card:hover:not(:disabled) .setup-card__icon {
    background: var(--primary-hover);
    color: var(--primary-subtle-border);
}

.setup-card__body {
    flex: 1;
}

.setup-card__title {
    margin: 0 0 0.375rem;
    font-size: var(--font-size-lg);
    font-weight: 600;
    color: var(--foreground);
}

.setup-card__description {
    margin: 0;
    font-size: var(--font-size-md);
    line-height: 1.5;
    color: var(--muted-foreground);
}

.setup-card__footer {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    font-size: var(--font-size-md);
    font-weight: 600;
    color: var(--primary);
}

.setup-card__footer svg {
    flex-shrink: 0;
    transition: transform var(--transition-base);
}

.setup-card:hover .setup-card__footer svg {
    transform: translateX(3px);
}

.swv-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.swv-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin: 0;
    padding: 1rem 1.25rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    box-shadow: var(--shadow-sm);
}

.swv-row__icon {
    flex-shrink: 0;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 0.375rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--primary-subtle-bg);
    color: var(--primary);
}

.swv-row__info {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    flex: 1;
    min-width: 0;
}

.swv-row__name {
    font-weight: 600;
    font-size: var(--font-size-xl);
    color: var(--foreground);
}

.swv-row__meta {
    font-size: var(--font-size-base);
    color: var(--muted-foreground);
}

.swv-row__deadline {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    font-size: var(--font-size-base);
    color: var(--muted-foreground);
}

.swv-row__deadline-dot {
    flex-shrink: 0;
    width: 0.375rem;
    height: 0.375rem;
    border-radius: var(--radius-full);
    background: var(--warning-solid);
}

.landing-empty {
    margin: 0;
    padding: 1.5rem;
    text-align: center;
    font-size: var(--font-size-lg);
    color: var(--muted-foreground);
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
}

.landing-content--wide {
    max-width: 64rem;
}

.contact-card-list {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.contact-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    overflow: hidden;
}

.contact-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.75rem 1.25rem;
    background: var(--muted);
    border-bottom: 1px solid var(--border);
}

.contact-card__name {
    font-size: var(--font-size-lg);
    font-weight: 600;
    color: var(--foreground);
}

.contact-card__number {
    margin-left: 0.75rem;
    font-family: var(--font-family-mono);
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

.contact-card__add-button {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0;
    border: none;
    background: none;
    font-family: inherit;
    font-size: var(--font-size-md);
    font-weight: 600;
    color: var(--primary);
    cursor: pointer;
}

.contact-card__add-button:hover {
    color: var(--primary-hover);
}

.contact-card__rows > * + * {
    border-top: 1px solid var(--border);
}

.contact-card__row {
    padding: 0.75rem 1.25rem;
}

.contact-card__fields {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.75rem;
}

.contact-card__email-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.contact-card__email-row .contact-card__input {
    flex: 1;
    min-width: 0;
}

.contact-card__delete-button {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: none;
    border: none;
    color: var(--muted-foreground);
    cursor: pointer;
    transition: color var(--transition-base);
}

.contact-card__delete-button:hover {
    color: var(--danger);
}

.contact-card__field-label {
    display: block;
    margin-bottom: 0.25rem;
    font-size: var(--font-size-sm);
    color: var(--muted-foreground);
}

.contact-card__input {
    width: 100%;
    padding: 0.375rem 0.625rem;
    font-family: inherit;
    font-size: var(--font-size-lg);
    color: var(--foreground);
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.25rem;
}

.contact-card__input:focus {
    outline: none;
    border-color: var(--primary);
}

.contact-card__empty {
    margin: 0;
    padding: 0.75rem 1.25rem;
    font-size: var(--font-size-base);
    color: var(--muted-foreground);
}

.field-status {
    display: block;
    min-height: 1em;
    margin-top: 0.25rem;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

.field-status[data-tone="success"] {
    color: var(--primary);
}

.field-status[data-tone="error"] {
    color: var(--danger);
}

.markdown-editor {
    /* No border/background of its own — it sits inside the already-boxed
       .teksten-field__editor card, so a second nested box doesn't appear. */
}

.markdown-editor--compact .markdown-editor__source {
    padding: 0;
}

.markdown-editor--compact .markdown-editor__source textarea {
    min-height: 2.75rem;
}

.markdown-editor__toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.25rem;
    padding: 0.5rem 0.75rem;
    background: var(--muted);
    border-bottom: 1px solid var(--border);
}

.markdown-editor__tool {
    padding: 0.25rem 0.5rem;
    font-size: var(--font-size-md);
    font-weight: 600;
    color: var(--foreground);
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.25rem;
    cursor: pointer;
    transition: border-color var(--transition-base), color var(--transition-base);
}

.markdown-editor__tool:hover {
    border-color: var(--primary);
    color: var(--primary);
}

.markdown-editor__hint {
    margin-left: auto;
    font-size: var(--font-size-sm);
    color: var(--muted-foreground);
}

.markdown-editor__panes {
    display: grid;
    grid-template-columns: 1fr 1fr;
}

.markdown-editor__panes--single {
    grid-template-columns: 1fr;
}

.markdown-editor__panes--single .markdown-editor__source {
    border-right: none;
}

.markdown-editor__source {
    margin: 0;
    padding: 0.75rem;
    border-right: 1px solid var(--border);
}

.markdown-editor__source textarea {
    display: block;
    width: 100%;
    min-height: 5rem;
    padding: 0;
    border: none;
    resize: vertical;
    font-family: inherit;
    font-size: var(--font-size-lg);
    color: var(--foreground);
    background: transparent;
}

.markdown-editor__source textarea:focus {
    outline: none;
}

.markdown-editor__preview {
    padding: 0.75rem;
    font-size: var(--font-size-lg);
    line-height: 1.5;
    color: var(--foreground);
    background: var(--muted);
    overflow-wrap: break-word;
}

.markdown-editor__preview :first-child {
    margin-top: 0;
}

.markdown-editor__preview :last-child {
    margin-bottom: 0;
}

.teksten-field__edit-button {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    margin-left: auto;
    padding: 0;
    background: transparent;
    color: var(--muted-foreground);
    border: 1px solid transparent;
    border-radius: 0.25rem;
    cursor: pointer;
    transition: color var(--transition-base), border-color var(--transition-base);
}

.teksten-field__edit-button[hidden] {
    display: none;
}

.teksten-field__edit-button:hover {
    color: var(--primary);
    border-color: var(--primary-subtle-border);
}

/* 018-vragenlijst-vrijgave: a frozen Uitvraag aanpassen pencil (chapter intro,
   category names) — greyed out, no hover affordance, but still visible with
   its title tooltip explaining why. */
.teksten-field__edit-button:disabled {
    color: var(--muted-foreground);
    opacity: 0.5;
    cursor: not-allowed;
}

.teksten-field__edit-button:disabled:hover {
    color: var(--muted-foreground);
    border-color: transparent;
}

.teksten-field__empty {
    color: var(--muted-foreground);
    font-style: italic;
}

.teksten-field__editor {
    margin-top: 0.5rem;
    margin-bottom: 1.5rem;
    padding: 0.875rem 1rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    box-shadow: var(--shadow-sm);
}

.teksten-field__editor-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 0.5rem;
}

/* 009-deadline-mails-config's data-inline-edit cards put `hidden` directly on
   this element (unlike Uitvraag aanpassen's own use of this class, where the
   ancestor .teksten-field__editor carries `hidden` instead) — the class's own
   `display: flex` above has higher specificity than the browser's default
   `[hidden] { display: none }` UA rule, so it must be restated explicitly
   here or the actions row stays visible despite the attribute. */
.teksten-field__editor-actions[hidden] {
    display: none;
}

.teksten-field__done-button {
    padding: 0.375rem 0.875rem;
    font-family: inherit;
    font-size: var(--font-size-base);
    font-weight: 600;
    color: var(--primary-foreground);
    background: var(--primary);
    border: none;
    border-radius: 0.25rem;
    cursor: pointer;
    transition: background-color var(--transition-base);
}

.teksten-field__done-button:hover {
    background: var(--primary-hover);
}

.teksten-field__cancel-button {
    padding: 0.375rem 0.875rem;
    font-family: inherit;
    font-size: var(--font-size-base);
    font-weight: 600;
    color: var(--muted-foreground);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 0.25rem;
    cursor: pointer;
    transition: background-color var(--transition-base);
}

.teksten-field__cancel-button:hover {
    background: var(--muted);
}

/* 017-fase-tracker: replaces the retired .kpi-grid/.kpi-card (plain big-
   number, no click-to-filter) everywhere it was still used — one KPI-card
   style/interaction across the whole app now, built on this shape
   (audience_progress_card / status_progress_card below). One card each for
   Besturen/Scholen (portaal_both) or Niet begonnen/Bezig met invullen/Wacht
   op accordering/Geaccordeerd (elsewhere), clickable to filter the table
   below to just that group. Real <button>s, so reset the native chrome
   first. */
.audience-progress-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
    margin-bottom: 1rem;
}

.audience-progress-card {
    display: block;
    width: 100%;
    padding: 1rem 1.25rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    box-shadow: var(--shadow-sm);
    font: inherit;
    text-align: left;
    color: inherit;
    cursor: pointer;
    transition: border-color var(--transition-base), background-color var(--transition-base);
}

/* Same restrained hover as .setup-card:hover (border only, no background
   tint) — matched to the card's own icon color (below) instead of always
   the same green, so hovering a "Bezig met invullen" card outlines amber,
   not green. */
.audience-progress-card--done:hover {
    border-color: var(--primary);
}

.audience-progress-card--pending:hover {
    border-color: var(--warning-solid);
}

.audience-progress-card--info:hover {
    border-color: var(--info-solid);
}

.audience-progress-card--none:hover {
    border-color: var(--muted-foreground);
}

/* Active/selected state — border only, same color as its own hover above,
   no full-card background tint (kept in line with .setup-card, which has
   no tinted-background state at all). */
.audience-progress-card--active.audience-progress-card--done {
    border-color: var(--primary);
}

.audience-progress-card--active.audience-progress-card--pending {
    border-color: var(--warning-solid);
}

.audience-progress-card--active.audience-progress-card--info {
    border-color: var(--info-solid);
}

.audience-progress-card--active.audience-progress-card--none {
    border-color: var(--muted-foreground);
}

.audience-progress-card__header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.audience-progress-card__text {
    display: flex;
    flex-direction: column;
}

.audience-progress-card__icon {
    /* Same boxed treatment as .setup-card__icon (the four cards above), for
       visual coherency between the two icon rows on this page. */
    flex-shrink: 0;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 0.375rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--primary-subtle-bg);
    color: var(--primary);
    transition: background-color var(--transition-base), color var(--transition-base);
}

/* Restores the original .kpi-card hierarchy this replaced — a big bold
   number first, the label demoted underneath it — now on the same
   click-to-filter card shape everything else here uses. */
.audience-progress-card__value {
    font-size: var(--font-size-4xl);
    font-weight: 700;
    line-height: 1.1;
    color: var(--foreground);
}

.audience-progress-card__label {
    margin-top: 0.125rem;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

/* Same four-color language on the icon box itself, so a card reads as "its
   own status color" at a glance instead of every card sharing the same
   green icon square audience_progress_card always used. */
.audience-progress-card__icon--done {
    background: var(--primary-subtle-bg);
    color: var(--primary);
}

.audience-progress-card__icon--pending {
    background: var(--warning-bg);
    color: var(--warning-foreground);
}

.audience-progress-card__icon--info {
    background: var(--info-bg);
    color: var(--info-foreground);
}

.audience-progress-card__icon--none {
    background: var(--muted);
    color: var(--muted-foreground);
}

/* Same hover-inverts-the-icon-square interaction as .setup-card__icon
   (bg goes solid, icon stroke goes pale) — one pairing per status color so
   a hovered "Bezig met invullen" card's icon still reads amber, not green.
   Also applied while --active (selected as the table's filter), so the
   flip persists as a "currently selected" indicator, not just a momentary
   hover effect. */
.audience-progress-card:hover .audience-progress-card__icon--done,
.audience-progress-card--active .audience-progress-card__icon--done {
    background: var(--primary-hover);
    color: var(--primary-subtle-border);
}

.audience-progress-card:hover .audience-progress-card__icon--pending,
.audience-progress-card--active .audience-progress-card__icon--pending {
    background: var(--warning-solid);
    color: var(--warning-bg);
}

.audience-progress-card:hover .audience-progress-card__icon--info,
.audience-progress-card--active .audience-progress-card__icon--info {
    background: var(--info-solid);
    color: var(--info-bg);
}

.audience-progress-card:hover .audience-progress-card__icon--none,
.audience-progress-card--active .audience-progress-card__icon--none {
    background: var(--muted-foreground);
    color: var(--muted);
}

/* Four cards instead of audience_progress_grid's two — same card component,
   narrower columns. Wraps to 2x2 on narrow screens rather than overflowing
   or shrinking illegibly, same breakpoint as .setup-grid's own collapse.
   --3 (no accordering step to show — status_progress_cards'
   with_accordering=False) drops to three even columns instead of a
   lopsided 4-minus-one gap. */
.status-progress-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1rem;
    margin-bottom: 1rem;
}

.status-progress-grid--3 {
    grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 640px) {
    .status-progress-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

.portaal-table {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    box-shadow: var(--shadow-sm);
}

/* Round the table's own four corner cells instead of `overflow: hidden` on
   the card above -- that clipped anything a descendant positioned outside
   its own box, including a locked amount input's [data-tooltip] bubble
   (the actual bug this replaced: the tooltip was there, just invisibly
   clipped). :first-child/:last-child track whichever row/cell is visually
   at each corner regardless of how many rows a given page renders (a
   group-row, a total-row, ...), no template changes needed. */
.portaal-table thead tr:first-child th:first-child {
    border-top-left-radius: 0.5rem;
}

.portaal-table thead tr:first-child th:last-child {
    border-top-right-radius: 0.5rem;
}

.portaal-table tbody tr:last-child td:first-child {
    border-bottom-left-radius: 0.5rem;
}

.portaal-table tbody tr:last-child td:last-child {
    border-bottom-right-radius: 0.5rem;
}

.portaal-table table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--font-size-lg);
}

.portaal-table thead tr {
    background: var(--muted);
    border-bottom: 1px solid var(--border);
}

.portaal-table th {
    text-align: left;
    padding: 0.75rem 1.25rem;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--muted-foreground);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wide);
}

.portaal-table tbody tr {
    border-bottom: 1px solid var(--border);
    transition: background-color var(--transition-base);
}

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

/* var(--subtle-hover-bg), not var(--muted) -- .portaal-table itself is
   white (var(--card)), and var(--muted) is the page's own background, so
   that used to make a hovered row blend into/disappear against the page
   instead of highlighting it. Same fix already applied to .landing-card's
   own row hover above. */
.portaal-table tbody tr:hover {
    background: var(--subtle-hover-bg);
}

.portaal-table td {
    padding: 0.875rem 1.25rem;
    vertical-align: middle;
}

.portaal-table__name {
    font-weight: 600;
    color: var(--foreground);
}

.portaal-table__code {
    font-family: var(--font-family-mono);
    font-size: var(--font-size-base);
    color: var(--muted-foreground);
}

.portaal-table__contact,
.portaal-table__date {
    color: var(--muted-foreground);
}

.portaal-table__actions {
    text-align: right;
}

/* The plain selector alone loses to .portaal-table th's own text-align:
   left (a class + element compound beats a single class on specificity) —
   this repeats it as a th-specific compound so a <th class="portaal-table__
   amount-head"> (used both by the main header row and the bestuur's own
   repeated sub-header row) actually right-aligns, matching every <td> that
   already carries this class with no competing base rule to lose to. */
.portaal-table__amount-head,
.portaal-table th.portaal-table__amount-head {
    text-align: right;
}

.portaal-table__amount {
    text-align: right;
}

.portaal-table__amount-input {
    width: 9rem;
    padding: 0.375rem 0.625rem;
    font-family: var(--font-family-mono);
    font-size: var(--font-size-lg);
    text-align: right;
    color: var(--foreground);
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.25rem;
}

.portaal-table__amount-input:focus {
    outline: none;
    border-color: var(--primary);
}

/* 016-bestuur-zelfbeheer-scholen: the read-only SWV-granted total on the
   granted-box, styled like a real amount cell but visibly locked — same
   greyed-text-plus-not-allowed-cursor language as every other disabled/
   locked input in this app (.category-table__input--locked,
   .config-card__text-input:disabled). */
.portaal-table__amount-input:disabled {
    color: var(--muted-foreground);
    background: var(--muted);
    cursor: not-allowed;
}

/* 008-both-respondent-level: Bestuur-with-nested-Scholen hierarchical table.
   Chevron reuses the exact same rotation transition as .data-share-table__chevron. */
.portaal-table__expand {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    cursor: pointer;
}

.portaal-table__chevron {
    flex-shrink: 0;
    transition: transform var(--transition-base);
}

.portaal-table__chevron--open {
    transform: rotate(90deg);
}

.portaal-table__name--indent {
    padding-left: 1.5rem;
    font-weight: 500;
}

.portaal-table__row--child td {
    background: var(--subtle-hover-bg);
}

/* Uitgekeerde bedragen: Scholen grouped under their own Bestuur — a plain
   (non-collapsible) section header row, unlike the Portaal's expandable
   Bestuur-met-Scholen rows above, since every School's amount input here
   needs to stay visible at once. */
.portaal-table__group-row td {
    padding: 0.5rem 1.25rem;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--muted-foreground);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wide);
    background: var(--muted);
}

/* 016-bestuur-zelfbeheer-scholen: the bestuur's own "Totaal besteed" row on
   the same .portaal-table used elsewhere on this page — a bold total, not
   the section-label treatment above. */
.portaal-table__total-row td {
    padding: 0.875rem 1.25rem;
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--foreground);
    background: var(--muted);
    border-top: 2px solid var(--border);
}

/* 016-bestuur-zelfbeheer-scholen: "not yet granted" text, shown in the
   Ontvangen-middelen table's amount cell in place of the disabled amount
   input — the warning color, same pairing as .status-badge--pending
   elsewhere. */
.granted-box__value--empty {
    font-family: var(--font-family-base);
    font-size: var(--font-size-base);
    font-weight: 600;
    color: var(--warning-foreground);
}

/* 016-bestuur-zelfbeheer-scholen: the live "Resterend" text inline in the
   Totaal-besteed cell of the bestuur's own .portaal-table — see app.js's
   recomputeCategoryTotals(), reused as the live total/remaining engine. */
.category-table__cell--remaining-inline {
    margin-left: 1rem;
    font-size: var(--font-size-md);
    font-weight: 400;
    color: var(--muted-foreground);
}

/* 008-both-respondent-level: Scholen/Besturen toggle shown only for
   RespondentLevel == "both" on Contactgegevens/Uitvraag aanpassen/
   Ondersteunende mails en deadline. */
/* Full-width white bar directly under the header — houses the
   Scholen/Besturen toggle for the three admin settings pages that need it,
   instead of the toggle sitting indented inside the grey page content below. */
.niveau-bar {
    display: flex;
    justify-content: center;
    background: var(--card);
    border-bottom: 1px solid var(--border);
}

/* Same max-width/horizontal padding as .landing-content--wide (the page
   content below) so "Instellen voor:" lines up with the page title's own
   left edge, not just this bar's own edge padding. */
.niveau-bar__inner {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    max-width: 64rem;
    padding: 0.75rem 1.5rem;
}

.niveau-bar__label {
    font-size: var(--font-size-lg);
    font-weight: 400;
    color: var(--muted-foreground);
}

/* Segmented-control style (replaces the old "two separate colored buttons"
   look) — a green track (the same pale green used throughout for a
   subtle/info surface) with the active option as a solid darker-green pill
   inside it; the inactive option sits directly on the track in a muted
   green tone, not grey. */
.niveau-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.125rem;
    padding: 0.125rem;
    background: var(--primary-subtle-bg);
    border-radius: 0.375rem;
}

.niveau-toggle__option {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
    font-size: var(--font-size-md);
    font-weight: 600;
    /* A genuine dark green (same token used for links elsewhere), not the
       greyer --primary-subtle-muted-foreground this used before. */
    color: var(--primary-link);
    text-decoration: none;
    background: transparent;
    border-radius: 0.25rem;
    transition: background-color var(--transition-base), color var(--transition-base);
}

.niveau-toggle__option svg {
    flex-shrink: 0;
}

.niveau-toggle__option:hover {
    color: var(--primary-subtle-strong-foreground);
}

.niveau-toggle__option--active,
.niveau-toggle__option--active:hover {
    background: var(--primary);
    color: var(--primary-foreground);
    box-shadow: var(--shadow-sm);
}

.status-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.25rem 0.625rem;
    border-radius: 0.25rem;
    font-size: var(--font-size-md);
    font-weight: 600;
    white-space: nowrap;
}

.status-badge--done {
    background: var(--primary-subtle-bg);
    color: var(--primary);
    border: 1px solid var(--primary-subtle-border);
}

.status-badge--pending {
    background: var(--warning-bg);
    color: var(--warning-foreground);
    border: 1px solid var(--warning-border);
}

.status-badge--none {
    background: var(--muted);
    color: var(--muted-foreground);
    border: 1px solid var(--border);
}

/* 017-fase-tracker: "Wacht op accordering" — a School that has submitted but
   its Bestuur hasn't reviewed it yet, distinct from --pending's "still being
   filled in" and --done's "fully resolved". */
.status-badge--info {
    background: var(--info-bg);
    color: var(--info-foreground);
    border: 1px solid var(--info-border);
}

/* 012-bestuur-goedkeuring-scholen: reuses the existing --danger token trio
   already used by .error-box, rather than introducing a new color. */
.status-badge--rejected {
    background: var(--danger-bg);
    color: var(--danger-foreground);
    border: 1px solid var(--danger-border);
}

/* 017-fase-tracker: bestuur-facing landing-page step tracker. No new palette
   (FR-016) — "afgerond" reuses the same primary/primary-foreground pairing
   .btn--primary already uses (solid fill reads better on a stepper marker
   than a pale badge would); "huidig" reuses .status-badge--done's own pale
   primary-subtle-bg/primary pairing, repurposed here for "current" instead
   of "done" since this component needs the pale treatment for its middle
   state, not its final one; "nog niet bereikt" reuses .status-badge--none's
   muted pairing. */
.phase-tracker {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    box-shadow: var(--shadow-sm);
    padding: 1.5rem 1.75rem;
    margin-bottom: 1rem;
}

.phase-track {
    display: flex;
    align-items: flex-start;
}

.phase-step {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    position: relative;
    min-width: 0;
    padding: 0.25rem 0.375rem 0.5rem;
    border-radius: 0.5rem;
    border: none;
    background: none;
    font: inherit;
    color: inherit;
    text-decoration: none;
}

a.phase-step {
    cursor: pointer;
}

a.phase-step:hover .phase-step__label {
    color: var(--primary);
}

.phase-step__marker {
    width: 2.125rem;
    height: 2.125rem;
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--font-size-base);
    font-weight: 600;
    flex-shrink: 0;
    z-index: 1;
    background: var(--muted);
    color: var(--muted-foreground);
    border: 2px solid transparent;
    transition: box-shadow var(--transition-base);
}

.phase-step--done .phase-step__marker {
    background: var(--primary);
    color: var(--primary-foreground);
}

.phase-step--current .phase-step__marker {
    background: var(--primary-subtle-bg);
    color: var(--primary);
    border-color: var(--primary);
}

.phase-step--viewing .phase-step__marker {
    box-shadow: 0 0 0 3px var(--primary-subtle-bg), 0 0 0 4.5px var(--primary);
}

.phase-step__connector {
    position: absolute;
    top: 1.3125rem;
    left: calc(-50% + 1.0625rem);
    width: calc(100% - 2.125rem);
    height: 2px;
    background: var(--muted);
    z-index: 0;
}

.phase-step--done .phase-step__connector,
.phase-step--current .phase-step__connector {
    background: var(--primary);
}

.phase-step__label {
    margin-top: 0.625rem;
    font-size: var(--font-size-lg);
    font-weight: 600;
    color: var(--muted-foreground);
    line-height: 1.35;
    max-width: 10rem;
}

.phase-step--current .phase-step__label {
    color: var(--primary);
}

.phase-step--done .phase-step__label {
    color: var(--foreground);
}

.phase-step__sub {
    margin-top: 0.1875rem;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
    max-width: 10.5rem;
    line-height: 1.4;
}

.viewing-banner {
    background: var(--primary-subtle-bg);
    border: 1px solid var(--primary-subtle-border);
    border-radius: 0.5rem;
    padding: 0.625rem 1rem;
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.viewing-banner__text {
    font-size: var(--font-size-base);
    color: var(--primary-link);
}

.viewing-banner--preview .btn--outline {
    color: var(--foreground);
    border-color: var(--border);
}

/* "Terug naar huidige fase" — .btn--outline's own grey border/text read as
   inactive against this banner's green-tinted background; scoped here
   (rather than changing .btn--outline itself, which every other outline
   button in the app also uses) to tie it to the banner's own accent color
   instead. */
.viewing-banner .btn--outline {
    color: var(--primary);
    border-color: var(--primary-subtle-border);
}

.viewing-banner .btn--outline:hover:not(:disabled) {
    border-color: var(--primary);
    background: var(--card);
}

@media (max-width: 640px) {
    .phase-track {
        flex-wrap: wrap;
        row-gap: 1.25rem;
    }

    .phase-step {
        flex-basis: 50%;
    }

    .phase-step__connector {
        display: none;
    }
}

/* 009-deadline-mails-config: deadline + email-template cards on Ondersteunende
   mails en deadline. Reuses status-badge--done's own green trio (var(--primary-subtle-bg)/
   var(--primary-subtle-border)/var(--primary)) for the card accent instead of inventing new colors, and
   the teksten-field__* pencil-icon edit pattern from Uitvraag aanpassen for
   the edit/cancel/done interaction instead of one page-wide save button. */
.config-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    padding: 1.25rem;
    margin-bottom: 1.5rem;
}

.config-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.25rem;
}


.config-card__title {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: 600;
    color: var(--foreground);
}

.config-card__hint {
    margin: 0 0 0.75rem;
    font-size: var(--font-size-base);
    color: var(--muted-foreground);
}

/* Confirmation popup for "Definitieve uitvraag versturen" (portaal.html) — a
   one-time, irreversible action, so a plain confirm() wasn't judged
   informative enough. Alpine x-show/x-cloak toggle, same idiom used
   elsewhere in this app instead of a bespoke modal library. */
.modal-overlay {
    position: fixed;
    inset: 0;
    background: var(--overlay-backdrop);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    z-index: 50;
}

/* Every other .modal-overlay is Alpine-driven (x-show sets this inline,
   already beating the rule above) -- _help_modal.html is the one plain-JS
   exception (toggles the native `hidden` attribute instead, see its own
   comment), so it needs an explicit override: the rule above and the
   browser's own default `[hidden]` style are equal specificity, and an
   author stylesheet always wins that tie over the user-agent default. */
.modal-overlay[hidden] {
    display: none;
}

.modal-card {
    width: 100%;
    max-width: 28rem;
    background: var(--card);
    border-radius: 0.75rem;
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}

/* _help_modal.html's own variant -- wider, and its body scrolls
   independently once the topic list is taller than the viewport, rather
   than the whole card overflowing the page. */
.modal-card--help {
    max-width: 32rem;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
}

.modal-card--help .modal-card__body {
    overflow-y: auto;
}

.modal-card__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1rem 1.5rem;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}

.modal-card__header-info {
    display: flex;
    align-items: center;
    gap: 0.625rem;
}

.modal-card__header-icon {
    flex-shrink: 0;
    width: 2rem;
    height: 2rem;
    border-radius: 0.375rem;
    background: var(--muted);
    color: var(--primary);
    display: flex;
    align-items: center;
    justify-content: center;
}

.modal-card__title {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: 600;
    color: var(--foreground);
}

.modal-card__subtitle {
    margin: 0.125rem 0 0;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

.modal-card__close {
    display: flex;
    padding: 0.25rem;
    background: none;
    border: none;
    color: var(--muted-foreground);
    cursor: pointer;
}

.modal-card__close:hover {
    color: var(--foreground);
}

.modal-card__body {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1.25rem 1.5rem;
}

.modal-card__note {
    margin: 0;
    font-size: var(--font-size-base);
    color: var(--muted-foreground);
}

/* A plain confirmation question (e.g. "contactpersoon verwijderen?") that
   needs no checklist/warning box of its own — full-strength foreground,
   unlike the muted .modal-card__note above. */
.modal-card__question {
    margin: 0;
    font-size: var(--font-size-lg);
    color: var(--foreground);
}

.modal-card__footer {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    padding: 1rem 1.5rem;
    background: var(--muted);
    border-top: 1px solid var(--border);
}

/* _help_modal.html's own thin identity strip at the bottom (this SWV's own
   name) -- centered text instead of the confirm/cancel button row above. */
.modal-card__footer--info {
    justify-content: center;
    flex-shrink: 0;
}

.modal-card__footer--info .modal-card__note {
    text-align: center;
}

/* _help_modal.html's own topic cards -- each one a real, app-defined
   question (never per-SWV content), with its own real contact(s) fetched
   from GET /hulp/contacten. */
.help-topic-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.help-topic {
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    overflow: hidden;
}

.help-topic__header {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.75rem 1rem;
    background: var(--muted);
}

.help-topic__icon {
    flex-shrink: 0;
    color: var(--primary);
    display: flex;
}

.help-topic__title {
    font-size: var(--font-size-base);
    font-weight: 600;
    color: var(--foreground);
}

.help-topic__body {
    padding: 0.875rem 1rem;
}

.help-topic__description {
    margin: 0 0 0.75rem;
    font-size: var(--font-size-sm);
    line-height: 1.5;
    color: var(--muted-foreground);
}

.help-topic__placeholder {
    margin: 0;
    font-size: var(--font-size-sm);
    font-style: italic;
    color: var(--muted-foreground);
}

.help-contact {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    padding: 0.625rem 0.75rem;
    /* var(--subtle-hover-bg) -- deliberately lighter than var(--muted), same
       "large-area surface, not table-header contrast" role it already plays
       for .portaal-table__row--child. Contrast against the avatar circle
       comes from that circle's own solid fill below, not from darkening
       this box. */
    background: var(--subtle-hover-bg);
    border-radius: 0.375rem;
}

.help-contact + .help-contact {
    margin-top: 0.5rem;
}

.help-contact__avatar {
    flex-shrink: 0;
    width: 1.75rem;
    height: 1.75rem;
    margin-top: 0.125rem;
    border-radius: var(--radius-full);
    /* A lighter tint of --primary (not the token itself) -- still solid
       enough to keep white initials legible, no border. */
    background: color-mix(in srgb, var(--primary) 70%, white);
    color: var(--primary-foreground);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--font-size-xs);
    font-weight: 700;
}

.help-contact__body {
    min-width: 0;
}

.help-contact__name {
    margin: 0;
    font-size: var(--font-size-md);
    font-weight: 600;
    color: var(--foreground);
}

.help-contact__role {
    margin: 0;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

.help-contact__links {
    display: flex;
    flex-wrap: wrap;
    column-gap: 1rem;
    row-gap: 0.125rem;
    margin-top: 0.375rem;
}

.help-contact__mail {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: var(--font-size-md);
    color: var(--primary-link);
    text-decoration: none;
}

.help-contact__mail svg {
    flex-shrink: 0;
}

.help-contact__mail:hover {
    text-decoration: underline;
}

.modal-checklist,
.modal-warning {
    display: flex;
    gap: 0.75rem;
    border-radius: 0.375rem;
    padding: 0.75rem 1rem;
}

.modal-checklist {
    background: var(--primary-subtle-bg);
    border: 1px solid var(--primary-subtle-border);
}

.modal-checklist__icon {
    flex-shrink: 0;
    margin-top: 0.125rem;
    color: var(--primary);
}

.modal-checklist__title {
    margin: 0 0 0.375rem;
    font-size: var(--font-size-base);
    font-weight: 600;
    color: var(--primary-subtle-strong-foreground);
}

.modal-checklist__list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}

.modal-checklist__item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: var(--font-size-base);
    color: var(--primary-subtle-strong-foreground);
}

.modal-checklist__item svg {
    flex-shrink: 0;
    color: var(--primary);
}

.modal-warning {
    background: var(--danger-bg);
    border: 1px solid var(--danger-border);
}

.modal-warning__icon {
    flex-shrink: 0;
    margin-top: 0.125rem;
    color: var(--danger);
}

.modal-warning__text {
    margin: 0;
    font-size: var(--font-size-base);
    color: var(--danger-foreground);
}

.config-card__date-input,
.config-card__text-input,
.config-card__textarea {
    /* Same grey input-cell treatment as the questionnaire's own
       .open-question__value (the box wrapping its textarea) — the actual
       "shade of grey" input styling used throughout the questionnaire,
       not the plain white .config-card surface itself. */
    appearance: none;
    background: var(--muted);
    border: 1px solid var(--border);
    border-radius: 0.25rem;
    padding: 0.5rem 0.75rem;
    font-size: var(--font-size-lg);
    font-family: inherit;
    color: var(--foreground);
}

.config-card__text-input:disabled,
.config-card__textarea:disabled {
    /* Same locked look as a locked questionnaire question
       (.open-question__input--locked) — greyed-out text and a not-allowed
       cursor, until the pencil icon lifts the disabled attribute. */
    color: var(--muted-foreground);
    cursor: not-allowed;
}

.config-card__date-input {
    /* Swaps the native calendar picker's default blue (today/selected date,
       focus ring) for the app's own green, matching this card's accent. */
    accent-color: var(--primary);
}

.config-card__text-input,
.config-card__textarea {
    display: block;
    width: 100%;
}

.config-card__textarea {
    /* Grows with its content instead of scrolling — app.js's
       autosizeTextarea() sets an explicit height, so a manual resize handle
       and internal scrollbar would both be redundant/conflicting. */
    resize: none;
    overflow: hidden;
}

.config-card__field {
    margin-bottom: 0.75rem;
}

.config-card__label {
    display: block;
    margin-bottom: 0.25rem;
    font-size: var(--font-size-md);
    font-weight: 600;
    color: var(--muted-foreground);
}

.config-card__token-hint {
    margin: 0.5rem 0 0;
    font-size: var(--font-size-sm);
    color: var(--muted-foreground);
}

.config-card__token-hint code {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.25rem;
    padding: 0.0625rem 0.25rem;
}

/* 016-magic-link-login */
.login-content {
    max-width: 28rem;
}

.login-form {
    /* No align-items override -- the default `stretch` is what makes the
       email input and the submit button fill the card body's full width,
       matching the mock-up (021-magic-link-login redesign). */
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* 021-magic-link-login redesign: the login/check-email pages' own card,
   replacing the plain .config-card + separate .landing-section heading —
   the icon/title/subtitle now live inside the card's own header instead of
   sitting above it as a page title, matching the supplied mock-up. */
.login-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.75rem;
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}

.login-card__header {
    padding: 1.5rem 1.75rem;
    background: var(--card);
    border-bottom: 1px solid var(--border);
}

.login-card__body {
    padding: 1.5rem 1.75rem;
}

/* Centered variant -- login_check_email.html's own "link verstuurd" intro,
   as opposed to the plain left-aligned header above. */
.login-card__intro {
    padding: 2rem 1.75rem 1.5rem;
    text-align: center;
}

.login-card__icon {
    width: 2.75rem;
    height: 2.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 1rem;
    /* Same radius/no-border treatment as every other shaded icon box in the
       app (.setup-card__icon, .swv-row__icon, .audience-progress-card__icon,
       .landing-card__icon) — a fixed 0.375rem regardless of the box's own
       size, and no border, just the tinted fill. */
    border-radius: 0.375rem;
    background: var(--primary-subtle-bg);
    color: var(--primary);
}

/* Larger and centered -- login_check_email.html's confirmation icon. */
.login-card__icon--lg {
    width: 3.5rem;
    height: 3.5rem;
    margin: 0 auto 1.25rem;
}

.login-card__title {
    margin: 0;
    font-size: var(--font-size-2xl);
    font-weight: 600;
    color: var(--foreground);
}

.login-card__title--intro {
    margin-bottom: 0.5rem;
}

.login-card__subtitle {
    margin: 0.25rem 0 0;
    font-size: var(--font-size-base);
    line-height: 1.5;
    color: var(--muted-foreground);
}

.login-email {
    margin: 0.125rem 0 1.25rem;
    font-size: var(--font-size-lg);
    font-weight: 600;
    color: var(--foreground);
}

.login-info-box {
    margin-bottom: 1.25rem;
    padding: 0.875rem 1rem;
    text-align: left;
    background: var(--muted);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
}

.login-info-box__title {
    margin: 0;
    font-size: var(--font-size-base);
    font-weight: 600;
    line-height: 1.4;
    color: var(--foreground);
}

.login-info-box__hint {
    margin: 0.25rem 0 0;
    font-size: var(--font-size-sm);
    line-height: 1.4;
    color: var(--muted-foreground);
}

.login-resend-form {
    margin: 0;
    text-align: center;
}

.login-resend-button {
    padding: 0;
    font-family: inherit;
    font-size: var(--font-size-sm);
    color: var(--muted-foreground);
    background: none;
    border: none;
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
    transition: color var(--transition-base);
}

.login-resend-button:hover {
    color: var(--foreground);
}

/* Wraps an accordion trigger that sits below other content already inside
   the same .login-card (login_check_email.html's "voer uw code in" toggle,
   under the border-t the mock-up shows there). login.html's own standalone
   code-entry card skips this wrapper and puts the trigger directly on the
   card, since there it's the first/only thing in the card and already has
   the card's own top edge. */
.login-accordion {
    border-top: 1px solid var(--border);
}

.login-accordion__trigger {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 1rem 1.75rem;
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: 600;
    text-align: left;
    color: var(--muted-foreground);
    background: none;
    border: none;
    cursor: pointer;
    transition: background-color var(--transition-base), color var(--transition-base);
}

.login-accordion__trigger:hover {
    color: var(--foreground);
    background: var(--subtle-hover-bg);
}

.login-accordion__chevron {
    flex-shrink: 0;
    transition: transform var(--transition-base);
}

.login-accordion__chevron--open {
    transform: rotate(180deg);
}

.login-accordion__content {
    padding: 0 1.75rem 1.5rem;
}

.login-code-otp__hint {
    margin: 0 0 1rem;
    font-size: var(--font-size-sm);
    line-height: 1.5;
    color: var(--muted-foreground);
}

.login-code-otp__boxes {
    display: flex;
    gap: 0.5rem;
    justify-content: center;
    margin-bottom: 1rem;
}

.login-code-otp__box {
    width: 2.5rem;
    height: 3rem;
    padding: 0;
    text-align: center;
    font-family: var(--font-family-mono);
    font-size: var(--font-size-xl);
    font-weight: 700;
    color: var(--foreground);
    background: var(--muted);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
}

.login-code-otp__box:focus {
    outline: none;
    border-color: var(--primary);
}

.login-footer-text {
    margin: 0;
    text-align: center;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

.login-role-choice {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.login-role-choice__option {
    margin: 0;
}

.login-role-choice__button {
    width: 100%;
}

.config-mail-block__title {
    margin: 0 0 0.25rem;
    font-size: var(--font-size-lg);
    font-weight: 600;
    color: var(--foreground);
}

.config-mail-block__hint {
    margin: 0 0 0.75rem;
    font-size: var(--font-size-base);
    color: var(--muted-foreground);
}

/* Read-only preview of the composed invitation email (editable intro +
   invitation_email_body()'s fixed steps/deadline/sign-off) below its
   config-card, in portaal_deadline_mails.html. var(--card) (white, same as
   the editable card above it and as a real email client's own background)
   so the preview reads as what an actual inbox would show, not as a muted
   "disabled" panel -- the read-only-ness is already conveyed by its own
   label and the lack of form fields, not by a greyed-out background. */
.email-preview {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    padding: 1.25rem;
}

.email-preview__label {
    margin: 0 0 0.75rem;
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--muted-foreground);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.email-preview__subject {
    margin: 0 0 0.75rem;
    font-weight: 600;
    color: var(--foreground);
}

.email-preview__body {
    font-size: var(--font-size-base);
    color: var(--foreground);
}

/* Collapsed-by-default preview box for a fixed (non-editable) email --
   _email_preview_accordion.html. Same rotate-on-open chevron idiom as
   .login-accordion__chevron/.data-share-table__chevron/
   .portaal-table__chevron -- each component keeps its own scoped copy of
   this small rule rather than sharing one (this app's existing
   convention, not a new one introduced here). */
.email-preview-accordion {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    margin-bottom: 0.75rem;
    overflow: hidden;
}

.email-preview-accordion__trigger {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.875rem 1.25rem;
    font-family: inherit;
    font-size: var(--font-size-md);
    font-weight: 600;
    color: var(--foreground);
    background: none;
    border: none;
    cursor: pointer;
    text-align: left;
}

.email-preview-accordion__trigger:hover {
    background: var(--subtle-hover-bg);
}

.email-preview-accordion__chevron {
    flex-shrink: 0;
    transition: transform var(--transition-base);
}

.email-preview-accordion__chevron--open {
    transform: rotate(180deg);
}

.email-preview-accordion__content {
    padding: 0 1.25rem 1.25rem;
}

.error-box {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 1.25rem;
    background: var(--danger-bg);
    border: 1px solid var(--danger-border);
    border-radius: 0.5rem;
}

.error-box__icon {
    flex-shrink: 0;
    margin-top: 0.125rem;
    color: var(--danger);
}

.error-box__title {
    margin: 0 0 0.375rem;
    font-size: var(--font-size-xl);
    font-weight: 700;
    color: var(--danger-foreground);
}

.error-box__text {
    margin: 0;
    font-size: var(--font-size-lg);
    color: var(--danger-muted-foreground);
}

.page-body {
    display: flex;
    align-items: flex-start;
}

/* Wraps a full-bleed top bar (the niveau-bar toggle on Uitvraag aanpassen;
   the review-actiebalk on questions.html) + .page-content in a column
   beside .sidebar, so the bar sits to the right of the sidebar (not
   spanning over it) and .sidebar itself starts flush under the header —
   same sticky/height math as a plain .page-body without this wrapper. */
.page-content-wrap {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* Here the niveau-bar sits beside .sidebar rather than over the plain
   .landing-content--wide shell, and .page-content centers each content
   block (.chapter, .landing-section, ...) individually at 48rem instead of
   padding one big 64rem box — so this bar's own inner column has to match
   that 48rem width, with no left padding of its own, for "Instellen voor:"
   to land on the same left edge as the title/chapter text below it (the
   symmetric-padding centering math cancels out either way; the padding
   difference doesn't, so it's zeroed here). */
.page-content-wrap > .niveau-bar .niveau-bar__inner {
    max-width: 48rem;
    padding-left: 0;
}

.sidebar {
    position: sticky;
    top: 3.25rem;
    flex-shrink: 0;
    width: 15rem;
    height: calc(100vh - 3.25rem);
    display: flex;
    flex-direction: column;
    background: var(--card);
    border-right: 1px solid var(--border);
    overflow: hidden;
    z-index: 5;
}

.sidebar__progress {
    padding: 1rem;
    border-bottom: 1px solid var(--border);
}

.sidebar__progress-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 0.5rem;
}

.sidebar__progress-label {
    font-size: var(--font-size-sm);
    font-weight: 700;
    letter-spacing: var(--letter-spacing-wider);
    text-transform: uppercase;
    color: var(--muted-foreground);
}

.sidebar__progress-percent {
    font-size: var(--font-size-sm);
    font-weight: 700;
    color: var(--primary);
}

.sidebar__progress-bar {
    height: 0.375rem;
    background: var(--muted);
    border-radius: var(--radius-full);
    overflow: hidden;
}

.sidebar__progress-bar-fill {
    height: 100%;
    background: var(--primary);
    border-radius: var(--radius-full);
    transition: width 0.4s ease;
}

.sidebar__progress-summary {
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
    margin: 0.375rem 0 0;
}

.sidebar__nav {
    flex: 1;
    overflow-y: auto;
    padding: 0.375rem 0;
}

.sidebar__chapter {
    position: relative;
    width: 100%;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 1rem;
    background: none;
    border: none;
    text-align: left;
    color: var(--muted-foreground);
    cursor: pointer;
}

.sidebar__chapter:hover {
    background: var(--muted);
    color: var(--foreground);
}

.sidebar__chapter--active {
    background: var(--muted);
    color: var(--foreground);
}

.sidebar__chapter--active::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 0.1875rem;
    background: var(--primary);
    border-radius: 0 0.125rem 0.125rem 0;
}

.sidebar__chapter-number {
    flex-shrink: 0;
    width: 1.25rem;
    height: 1.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-full);
    background: var(--muted);
    color: var(--muted-foreground);
    font-size: var(--font-size-sm);
    font-weight: 700;
}

.sidebar__chapter--active .sidebar__chapter-number {
    background: var(--primary-subtle-bg);
    color: var(--primary);
}

.sidebar__chapter-number--complete,
.sidebar__chapter--active .sidebar__chapter-number--complete {
    background: var(--primary);
    color: var(--primary-foreground);
}

.sidebar__chapter-number-check {
    display: none;
}

.sidebar__chapter-number--complete .sidebar__chapter-number-text {
    display: none;
}

.sidebar__chapter-number--complete .sidebar__chapter-number-check {
    display: block;
}

.sidebar__chapter-text {
    flex: 1;
    min-width: 0;
}

.sidebar__chapter-title {
    margin: 0;
    font-size: var(--font-size-base);
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar__chapter-progress-wrap {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.25s ease;
}

.sidebar__chapter--active .sidebar__chapter-progress-wrap:has(.sidebar__chapter-progress:not(:empty)) {
    max-height: 1.25rem;
}

.sidebar__chapter-progress {
    margin: 0.125rem 0 0;
    font-size: var(--font-size-sm);
    color: var(--muted-foreground);
}

.page-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 2rem;
    min-width: 0;
}

.autosave-banner {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    max-width: 48rem;
    margin-bottom: 1.5rem;
    padding: 0.5rem 0.75rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.25rem;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

/* Shared "subtle green notice" surface — reused by the autosave-banner/
   submit-box submitted/rejected variants below and by questions.html's
   chapter-intro. Centralizing this fixed a real inconsistency: this surface
   previously had its own separate gap/border-radius here (0.5rem/0.25rem,
   inherited from .autosave-banner's compact tip-banner base) that didn't
   match chapter-intro's (0.75rem/0.5rem), so the "Ingediend" banner's text
   sat visibly closer to its icon than an intro-text box's did. */
.subtle-notice {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 1rem;
    background: var(--primary-subtle-bg);
    border: 1px solid var(--primary-subtle-border);
    border-radius: 0.5rem;
}

.subtle-notice__icon {
    flex-shrink: 0;
    margin-top: 0.125rem;
    color: var(--primary);
}

/* 012-bestuur-goedkeuring-scholen: same --danger token trio already used by
   .error-box/.status-badge--rejected — overrides .subtle-notice's green. */
.autosave-banner--rejected {
    background: var(--danger-bg);
    border-color: var(--danger-border);
}

.autosave-banner--rejected .autosave-banner__icon {
    color: var(--danger);
}

.autosave-banner--rejected .autosave-banner__title {
    color: var(--danger-foreground);
}

.autosave-banner--rejected .autosave-banner__text {
    color: var(--danger-muted-foreground);
}

.autosave-banner__title {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--primary-subtle-strong-foreground);
}

.autosave-banner__text {
    /* Was 0.8125rem — the one place this text was smaller than the matching
       chapter-intro__text/submit-box__text (both 0.875rem). */
    margin: 0.125rem 0 0;
    font-size: var(--font-size-lg);
    color: var(--primary-subtle-muted-foreground);
}

.autosave-banner__icon {
    flex-shrink: 0;
    color: var(--primary);
}

/* 012-bestuur-goedkeuring-scholen: the top bar shown on a lower level's
   read-only answer overview — same full-bleed white-bar-under-the-header
   recipe as .niveau-bar ("Instellen voor: Scholen/Besturen" on the Uitvraag
   aanpassen page): an outer strip spanning the whole .page-content-wrap
   column, with an inner column capped at this page's own 48rem content
   width so it lines up with .chapter below it. */
.review-actiebalk {
    display: flex;
    justify-content: center;
    background: var(--card);
    border-bottom: 1px solid var(--border);
    /* Stays visible while scrolling through a long uitvraag (all audiences:
       oversight view_only AND a respondent's own submitted/approved/rejected
       view) -- pinned directly under .page-header's own sticky 3.25rem bar,
       one z-index below it so the header still paints over this on the way
       past. box-shadow only bites once actually stuck (nothing behind it to
       shadow at the top of the page), same as .page-header's own shadow. */
    position: sticky;
    top: 3.25rem;
    z-index: 9;
    box-shadow: var(--shadow-sm);
}

.review-actiebalk__inner {
    width: 100%;
    max-width: 48rem;
    padding: 0.75rem 1.5rem;
}

.review-actiebalk__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

.review-actiebalk__info {
    font-size: var(--font-size-base);
    color: var(--muted-foreground);
}

.review-actiebalk__info strong {
    color: var(--foreground);
}

.review-actiebalk__buttons {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    flex-shrink: 0;
}

.review-actiebalk__reject-form {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.review-actiebalk__label {
    font-size: var(--font-size-base);
    font-weight: 600;
    color: var(--foreground);
}

.review-actiebalk__textarea {
    width: 100%;
    min-height: 5rem;
    padding: 0.5rem 0.75rem;
    background: var(--input-background);
    border: 1px solid var(--border);
    border-radius: 0.25rem;
    font-size: var(--font-size-lg);
    color: var(--foreground);
    resize: vertical;
}

.review-actiebalk__reject-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.75rem;
}

.uitvraag-legend {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    flex-wrap: wrap;
    width: 100%;
    max-width: 48rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.375rem;
    padding: 0.75rem 1.25rem;
    font-size: var(--font-size-md);
    margin-bottom: 1.5rem;
}

.uitvraag-legend__label {
    font-weight: 600;
    color: var(--muted-foreground);
}

.uitvraag-legend__item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.uitvraag-legend__swatch {
    display: inline-block;
    flex-shrink: 0;
    width: 0.75rem;
    height: 0.75rem;
    border-radius: 0.15rem;
}

.uitvraag-legend__swatch--swv {
    background: var(--primary-subtle-bg);
    border: 1px solid var(--primary-subtle-border);
}

.uitvraag-legend__swatch--bestuur {
    background: var(--card);
    border: 1px solid var(--border);
}

.uitvraag-legend__text--swv {
    color: var(--foreground);
    font-weight: 500;
}

.uitvraag-legend__text--bestuur {
    color: var(--muted-foreground);
}

.uitvraag-info {
    width: 100%;
    max-width: 48rem;
    font-size: var(--font-size-lg);
    color: var(--primary-subtle-muted-foreground);
    background: var(--primary-subtle-bg);
    border: 1px solid var(--primary-subtle-border);
    border-radius: 0.5rem;
    padding: 0.75rem 1rem;
    margin: 0 0 1.5rem;
}

.uitvraag-info strong {
    color: var(--primary-subtle-strong-foreground);
}

/* Uitvraag aanpassen's own title section sits directly in .page-content
   (align-items: center) alongside .chapter/.uitvraag-legend/.uitvraag-info,
   which all set their own width: 100% to fill that 48rem column instead of
   shrink-wrapping their text — .landing-section needs the same treatment
   here so the title lines up with them, without widening .landing-section
   on every other page that still uses the plain .landing-content--wide
   shell (page-title-block__title style there works differently). */
.page-content > .landing-section {
    width: 100%;
    max-width: 48rem;
}

.chapter {
    width: 100%;
    max-width: 48rem;
    margin-bottom: 2rem;
    /* .page-header is a sticky 3.25rem bar (position: sticky; top: 0) that
       stays painted over whatever scrolls to the very top of the viewport --
       without this, the sidebar's chapter-nav scrollIntoView({block:"start"})
       (app.js) lands the chapter's top edge at y=0 and the header covers the
       title. scroll-margin-top reserves that same height so the browser
       stops scrolling with the title just below the header instead. 6rem
       (not 3.25rem) accounts for .review-actiebalk too -- also sticky,
       pinned directly under the header, on questions.html whenever it's
       shown (view_only oversight or a respondent's own submitted/approved/
       rejected view). A touch more than its own ~2.7rem measured height so
       there's still a sliver of breathing room, not a hairline overlap; on
       pages without that banner this just reserves a little extra empty
       scroll space, which is harmless. */
    scroll-margin-top: 6rem;
}

.chapter-header {
    position: relative;
    padding-bottom: 0.75rem;
    margin-bottom: 1rem;
    border-bottom: 1px solid var(--border);
}

.chapter-header__eyebrow {
    font-size: var(--font-size-sm);
    font-weight: 700;
    letter-spacing: var(--letter-spacing-wider);
    text-transform: uppercase;
    color: var(--muted-foreground);
    margin-bottom: 0.25rem;
}

.chapter-header__title {
    font-size: var(--font-size-3xl);
    font-weight: 700;
    color: var(--foreground);
    margin: 0 0 0.25rem;
}

.chapter-header__description {
    font-size: var(--font-size-lg);
    color: var(--muted-foreground);
    margin: 0;
}

/* Layout/color now come from .subtle-notice (applied alongside this class
   in questions.html) — only what's genuinely unique to chapter-intro
   (its margin) stays here. */
.chapter-intro {
    margin-bottom: 1.5rem;
}

.chapter-intro__text {
    font-size: var(--font-size-lg);
    color: var(--primary-subtle-muted-foreground);
}

.chapter-intro__text strong,
.chapter-intro__text b {
    color: var(--primary-subtle-strong-foreground);
}

.chapter-intro__text > *:first-child {
    margin-top: 0;
}

.chapter-intro__text > *:last-child {
    margin-bottom: 0;
}

.chapter-intro__text ul,
.chapter-intro__text ol {
    padding-left: 1.25rem;
}

.chapter-intro__text li::marker {
    color: var(--primary);
}

.chapter-intro__text a {
    color: var(--primary-link);
}

/* portaal_uitvraag_aanpassen.html's admin preview — a genuinely different
   (column, header+body) structure from the plain chapter-intro, so it keeps
   its own background/border/border-radius rather than sharing .subtle-notice
   (whose row layout wouldn't fit this one's column direction). */
.chapter-intro--editable {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    margin-bottom: 1.25rem;
    background: var(--primary-subtle-bg);
    border: 1px solid var(--primary-subtle-border);
    border-radius: 0.5rem;
}

.chapter-intro__header {
    display: flex;
    align-items: center;
}

.chapter-intro__eyebrow-group {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.chapter-intro__eyebrow {
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: var(--primary);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wider);
}

.chapter-intro__eyebrow-note {
    font-size: var(--font-size-xs);
    color: var(--muted-foreground);
}

.chapter-intro__body {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
}

/* background/border/border-radius are also declared on .subtle-notice
   (applied alongside this class for the submitted/rejected states below) —
   kept here too because the plain "Klaar om in te dienen?" state never gets
   .subtle-notice (it isn't an icon+title notice, just two stacked
   paragraphs) yet still wants the same green surface. */
.submit-box {
    width: 100%;
    max-width: 48rem;
    margin-top: 0.5rem;
    padding: 1.25rem;
    background: var(--primary-subtle-bg);
    border: 1px solid var(--primary-subtle-border);
    border-radius: 0.5rem;
}

/* 012-bestuur-goedkeuring-scholen: same --danger token trio already used by
   .error-box/.status-badge--rejected/.autosave-banner--rejected. */
.submit-box--rejected {
    background: var(--danger-bg);
    border-color: var(--danger-border);
}

.submit-box--rejected .submit-box__icon {
    color: var(--danger);
}

.submit-box--rejected .submit-box__title {
    color: var(--danger-foreground);
}

.submit-box--rejected .submit-box__text {
    color: var(--danger-muted-foreground);
}

.submit-box__title {
    margin: 0 0 0.375rem;
    /* Was 0.9375rem — the one place this title was a different size than
       the matching .autosave-banner__title (both 0.875rem). */
    font-size: var(--font-size-lg);
    font-weight: 700;
    color: var(--primary-subtle-strong-foreground);
}

.submit-box__text {
    margin: 0;
    font-size: var(--font-size-lg);
    color: var(--primary-subtle-muted-foreground);
}

.submit-box__actions {
    width: 100%;
    max-width: 48rem;
    margin-top: 0.75rem;
    display: flex;
    justify-content: flex-end;
}

.question-list {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    width: 100%;
}

.open-question {
    width: 100%;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    padding: 1rem 1.25rem;
    box-shadow: var(--shadow-sm);
}

.open-question__body {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}

.open-question__label {
    font-size: var(--font-size-lg);
    font-weight: 500;
    color: var(--foreground);
}

.open-question__description {
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
    margin: 0;
}

.open-question__value {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    background: var(--muted);
    border: 1px solid var(--border);
    border-radius: 0.25rem;
    font-size: var(--font-size-lg);
    color: var(--foreground);
}

.open-question__prefix {
    color: var(--muted-foreground);
    font-weight: 500;
}

.open-question__input {
    flex: 1;
    width: 100%;
    display: block;
    border: none;
    background: transparent;
    font: inherit;
    color: var(--foreground);
    outline: none;
    resize: none;
    overflow: hidden;
}

.open-question__input::placeholder {
    color: var(--placeholder-foreground);
}

.open-question__input--locked {
    color: var(--muted-foreground);
    cursor: not-allowed;
}

.open-question__status {
    display: block;
    min-height: 1em;
    margin-top: 0.25rem;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

.open-question__status[data-tone="success"] {
    color: var(--primary);
}

.open-question__status[data-tone="error"] {
    color: var(--danger);
}

.mc-question {
    width: 100%;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    padding: 1rem 1.25rem;
    box-shadow: var(--shadow-sm);
}

.mc-question__body {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}

.mc-question__label {
    font-size: var(--font-size-lg);
    font-weight: 500;
    color: var(--foreground);
}

.mc-question__description {
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
    margin: 0;
}

.mc-question__options {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.25rem;
}

.mc-question__option {
    position: relative;
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.125rem;
    padding: 0.5rem 0.25rem;
    border: 1px solid var(--border);
    border-radius: 0.25rem;
    background: var(--card);
    color: var(--muted-foreground);
    font-size: var(--font-size-base);
    text-align: center;
    cursor: pointer;
}

.mc-question__option input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.mc-question__option-description {
    font-size: var(--font-size-sm);
    font-style: italic;
    color: var(--muted-foreground);
}

.mc-question__option:hover {
    border-color: var(--primary);
    color: var(--foreground);
}

.mc-question__option:has(input:checked) {
    border-color: var(--primary);
    color: var(--primary);
    background: var(--primary-subtle-bg);
}

.mc-question__option--locked {
    cursor: not-allowed;
}

.mc-question__option--locked:hover {
    border-color: var(--border);
    color: var(--muted-foreground);
}

.mc-question__option--locked:has(input:checked) {
    border-color: var(--muted-foreground);
    color: var(--muted-foreground);
    background: var(--muted);
}

.mc-question__status {
    display: block;
    min-height: 1em;
    margin-top: 0.25rem;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

.mc-question__status[data-tone="success"] {
    color: var(--primary);
}

.mc-question__status[data-tone="error"] {
    color: var(--danger);
}

.category-table-question {
    width: 100%;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    padding: 1rem 1.25rem;
    box-shadow: var(--shadow-sm);
}

.category-table-question--editable {
    background: var(--primary-subtle-bg);
    border-color: var(--primary-subtle-border);
}

.category-table-question--editable .category-table {
    background: var(--card);
}

.category-table-question__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
}

.category-table-question__label {
    display: block;
    font-size: var(--font-size-lg);
    font-weight: 500;
    color: var(--foreground);
}

.category-table-question__description {
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
    margin: 0.375rem 0 0;
}

.category-table {
    display: grid;
    grid-template-columns: 2fr 1fr 3fr;
    margin-top: 0.75rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.25rem;
    box-shadow: var(--shadow-sm);
    /* No overflow: hidden here (unlike most rounded cards) -- a locked
       row's own [data-tooltip] bubble (see category_table's locked_title)
       is positioned above its cell and would otherwise get invisibly
       clipped by the grid's own box, the same bug .portaal-table's own
       comment already documents and fixes the same way: round only the
       four actual corner cells below instead of the whole container. */
}

.category-table__row-form {
    display: contents;
}

/* Hiding just the Categorie cell (.category-table__category-form) removes
   one item from the grid's auto-flow without removing this row's own two
   items (amount/toelichting) — every subsequent row then shifts left by
   one column. Marking a category pending-delete must hide this whole
   sibling form too (see the JS toggling both together), not just the name. */
.category-table__row-form[hidden] {
    display: none;
}

.category-table__cell {
    display: flex;
    align-items: center;
    padding: 0.5rem 0.75rem;
    font-size: var(--font-size-base);
    color: var(--foreground);
    border-bottom: 1px solid var(--border);
    border-left: 1px solid var(--border);
}

.category-table__cell--first {
    border-left: none;
}

.category-table__cell--head {
    background: var(--muted);
    font-size: var(--font-size-sm);
    font-weight: 700;
    letter-spacing: var(--letter-spacing-wide);
    text-transform: uppercase;
    color: var(--muted-foreground);
}

/* The grid's own four visual corners -- .category-table--first is already
   the header row's own first cell and the total row's own first cell (see
   category_table's own comment above), so only the two *last*-cell corners
   need this dedicated modifier. Replaces the border-radius/overflow:hidden
   combination removed from .category-table above. */
.category-table__cell--head.category-table__cell--first {
    border-top-left-radius: 0.25rem;
}

.category-table__cell--head.category-table__cell--last {
    border-top-right-radius: 0.25rem;
}

.category-table__cell--total-label.category-table__cell--first {
    border-bottom-left-radius: 0.25rem;
}

.category-table__cell--total-remaining.category-table__cell--last {
    border-bottom-right-radius: 0.25rem;
}

.category-table__cell--label {
    font-weight: 500;
}

.category-table__category-form {
    gap: 0.375rem;
    background: var(--card);
    /* An inset box-shadow reads as a border without adding to the box's own
       height/width like a real `border` would (see git history for why this
       matters — a real border made this row visibly taller than its sibling
       .category-table__category-display span whenever the pencil toggled). */
    box-shadow: inset 0 0 0 1px var(--border);
    border-radius: 0.375rem;
}

.category-table__category-form:focus-within {
    box-shadow: inset 0 0 0 1px var(--primary);
}

.category-table__category-form--invalid {
    box-shadow: inset 0 0 0 1px var(--danger);
}

.category-table__category-form--invalid .category-table__category-input {
    color: var(--danger);
}

/* !important because this must win over the plain hidden attribute's own
   display rule either way — a row marked for deletion has to stay gone even
   after the edit-mode toggle re-shows every other [data-category-form]. */
.category-table__category-form--pending-delete {
    display: none !important;
}

.category-table__category-form[hidden],
.category-table__category-display[hidden] {
    display: none;
}

.category-table__add-row {
    grid-column: 1 / -1;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--border);
}

.category-table__actions-row {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.75rem;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--border);
}

.category-table__actions-row .field-status {
    margin: 0;
}

.category-table__actions-row[hidden] {
    display: none;
}

.category-table__cell input {
    width: 100%;
    border: none;
    background: transparent;
    font: inherit;
    color: var(--foreground);
    outline: none;
}

.category-table__cell:has(input[data-format="currency"]) input {
    text-align: right;
}

.category-table__input--locked {
    color: var(--muted-foreground);
    cursor: not-allowed;
}

.category-table__cell--total-label,
.category-table__cell--total-amount,
.category-table__cell--total-remaining {
    background: var(--muted);
    font-weight: 600;
    border-bottom: none;
}

.category-table__cell--total-amount {
    justify-content: flex-end;
}

.category-table__cell--total-remaining {
    font-weight: 400;
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
}

.category-table__cell--danger {
    color: var(--danger);
}

/* Alpine.js hides [x-cloak] itself once it initializes; this rule only
   covers the brief window before that (first Alpine adopter in this app —
   006-data-share-tabel-in-vragenlijst). */
[x-cloak] {
    display: none !important;
}

.data-share-table-question {
    width: 100%;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    padding: 1rem 1.25rem;
    margin-bottom: 1rem;
    box-shadow: var(--shadow-sm);
}

.data-share-table-question__intro {
    font-size: var(--font-size-md);
    color: var(--muted-foreground);
    margin: 0 0 0.75rem;
}

.data-share-table-question__peildatum {
    font-size: var(--font-size-sm);
    color: var(--muted-foreground);
    text-align: right;
    margin: 0.375rem 0 0;
}

.data-share-table-empty {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 1rem;
    background: var(--muted);
    border: 1px solid var(--border);
    border-radius: 0.5rem;
    font-size: var(--font-size-base);
    color: var(--muted-foreground);
}

.data-share-table-empty__icon {
    flex-shrink: 0;
    margin-top: 0.125rem;
}

.data-share-table {
    display: grid;
    grid-template-columns: 2fr repeat(3, 1fr);
    border: 1px solid var(--border);
    border-radius: 0.25rem;
    overflow: hidden;
}

.data-share-table__group,
.data-share-table__row {
    display: contents;
}

/* Same cell metrics as .category-table__cell (padding, font-size, border-bottom
   + border-left column dividers, first-column exception) -- this table only
   adds what category-table has no equivalent for: the chevron/expand-collapse,
   subcategory indentation/shading, and the always-last total row below. */
.data-share-table__cell {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.5rem 0.75rem;
    font-size: var(--font-size-base);
    color: var(--foreground);
    border-bottom: 1px solid var(--border);
    border-left: 1px solid var(--border);
}

.data-share-table__cell--first {
    border-left: none;
}

.data-share-table__cell--head {
    background: var(--muted);
    font-size: var(--font-size-sm);
    font-weight: 700;
    letter-spacing: var(--letter-spacing-wide);
    text-transform: uppercase;
    color: var(--muted-foreground);
}

.data-share-table__cell--label {
    font-weight: 500;
}

.data-share-table__cell--indent {
    padding-left: 1.75rem;
    font-weight: 400;
    color: var(--muted-foreground);
}

.data-share-table__cell--number {
    justify-content: flex-end;
    font-variant-numeric: tabular-nums;
}

.data-share-table__cell--clickable {
    cursor: pointer;
}

/* Hovering (or, for keyboard users, focusing the clickable label of) any
   cell in a row shades every cell in that same row, not just the one
   under the pointer -- :has() lets a plain sibling cell's state reach back
   up through the row (itself display:contents, so it has no box of its
   own to style directly) to its other cells. */
.data-share-table__row--indicator:has(.data-share-table__cell:hover) .data-share-table__cell,
.data-share-table__row--expandable:has(.data-share-table__cell--clickable:focus-visible) .data-share-table__cell {
    background: var(--subtle-hover-bg);
}

/* Subcategory rows stay visibly, permanently shaded (not just on hover) so
   the expanded detail reads as nested under its indicator -- deliberately
   lighter than --muted (used elsewhere for stronger contrast, e.g. table
   headers), since this shade covers much more area at once. */
.data-share-table__row--subcategory .data-share-table__cell {
    background: var(--subtle-hover-bg);
}

.data-share-table__chevron {
    flex-shrink: 0;
    transition: transform var(--transition-base);
}

.data-share-table__chevron--open {
    transform: rotate(90deg);
}

/* --- TEMPORARY DEMO ROLE SWITCHER (part 3/3) --- */
/* Centered title in the top bar. Standalone .page-header__title (the inline
   kies_* page headers) keeps its own absolute centering -- only this wrapped
   one goes static. */
.page-header__center {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 0.75rem;
    max-width: 56%;
}

.page-header__center .page-header__title {
    position: static;
    left: auto;
    transform: none;
}

.role-switcher {
    position: absolute;
    inset: 0;
}

/* `position: absolute` above would otherwise defeat the [hidden] attribute the
   JS toggles -- keep it hidden until the user list has actually loaded (and
   stay hidden entirely when the switcher is disabled server-side). */
.role-switcher[hidden] {
    display: none;
}

/* Invisible, stretched over the whole .page-header__user block (name/org/
   avatar) -- clicking anywhere there opens this native <select>'s option list,
   without a separate visible control calling attention to a temporary demo
   feature. */
.role-switcher__select {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    margin: 0;
    border: none;
    background: transparent;
    opacity: 0;
    cursor: pointer;
}

/* The expanded option list renders on a white background in most browsers, so
   force dark text there for legibility. */
.role-switcher__select option {
    color: var(--select-option-foreground);
}

/* Same hover affordance as .page-header__brand--switchable's own clickable
   state (the SWV name, top-left) -- only while the switcher has actually
   loaded (:has(...:not([hidden]))), so hovering the name never suggests
   clickability if the demo switcher is disabled server-side. */
.page-header__user:has(.role-switcher:not([hidden])) {
    cursor: pointer;
    padding: 0.25rem 0.375rem;
    margin: -0.25rem -0.375rem;
    border-radius: 0.375rem;
    transition: background-color var(--transition-base);
}

.page-header__user:has(.role-switcher:not([hidden])):hover {
    background: var(--overlay-on-primary-hover);
}
/* --- end temporary demo role switcher --- */
