/*
 * ProfiZentrale theme layer, on top of Tabler 1.4.0.
 *
 * The identity is unchanged: terracotta (#E66F51) on warm greige (#eeebea).
 *
 * Tabler ships cold slate neutrals, which clashed with the warm background and
 * made the whole surface look muddy. Rather than hand-rolling a ramp, the app
 * now sets data-bs-theme-base="stone" on <html> (see base.html.twig), which
 * swaps Tabler's --tblr-gray-* scale for a warm one. Dark mode derives its
 * surfaces from that same scale, so both themes come from one palette.
 *
 * Contrast: every pairing below was checked against WCAG AA (4.5:1 for text,
 * 3:1 for borders and focus rings). Where a value looks oddly specific, it is
 * the lightest shade that still passes.
 *
 * Structure:
 *   1. Brand ramp
 *   2. Light theme tokens
 *   3. Dark theme tokens
 *   4. Base and typography
 *   5. Focus and accessibility
 *   6. Component polish
 *   7. Third-party widgets
 *   8. Application classes
 *   9. Symfony dump
 */

/* ------------------------------------------------------------------ *
 * 1. Brand ramp
 *
 * Derived from the existing #E66F51 at hue 12deg. Every interactive state
 * comes from this scale instead of the one-off hex values that used to be
 * scattered through the file.
 * ------------------------------------------------------------------ */

:root {
    --pz-terracotta-50:  #fdf5f2;
    --pz-terracotta-100: #fae7e0;
    --pz-terracotta-200: #f5cec1;
    --pz-terracotta-300: #efad97;
    --pz-terracotta-400: #ea8c70;
    --pz-terracotta-500: #e66f51; /* brand anchor, unchanged */
    --pz-terracotta-600: #d75a34;
    --pz-terracotta-700: #b4472a;
    --pz-terracotta-800: #8f381f;
    --pz-terracotta-900: #6b2a18;

    /* Dimmed variants. The brand red as text was reading heavy across dense
     * tables, and the fix is to take saturation out rather than to add black:
     * same hue, roughly 55% of the chroma, which looks dustier and lighter
     * while the contrast ratio barely moves. */
    --pz-terracotta-text: #c35439;      /* 4.52:1 on white */
    --pz-terracotta-text-dark: #d56f56; /* 4.51:1 on the dark surface */

    /* White on the brand terracotta is only 3.1:1, so a button label sitting
     * on it fails AA. This is the lightest shade of the same hue that carries
     * a white label at 4.6:1. The brand 500 stays on borders, accents and
     * anything that does not have text on top of it. */
    --pz-primary-solid: #bf563a;
    --pz-primary-solid-hover: var(--pz-terracotta-700);
    --pz-primary-solid-active: var(--pz-terracotta-800);

    /* Admin screens used to cap at 1600px in nine separate inline styles,
     * which made wide tables scroll sideways while leaving the page margins
     * empty. One token now drives all of them. */
    --pz-admin-max-width: 2200px;

    /* Motion, shared so timings stay consistent across components. */
    --pz-ease: cubic-bezier(0.32, 0.72, 0, 1);
    --pz-duration: 160ms;
}

/* ------------------------------------------------------------------ *
 * 2. Light theme tokens
 * ------------------------------------------------------------------ */

:root,
[data-bs-theme=light] {
    --tblr-primary: var(--pz-terracotta-500);
    --tblr-primary-rgb: 230, 111, 81;
    --tblr-primary-fg: #ffffff;
    --tblr-primary-darken: var(--pz-terracotta-700);
    --tblr-primary-lt: var(--pz-terracotta-50);
    --tblr-primary-lt-rgb: 253, 245, 242;
    --tblr-primary-text-emphasis: var(--pz-terracotta-text);
    --tblr-primary-bg-subtle: var(--pz-terracotta-50);
    --tblr-primary-border-subtle: var(--pz-terracotta-200);

    /* The outline of an input is what tells you it is an input, so form
     * controls get their own border rather than the divider colour. Lightened
     * deliberately, twice: at 2.20:1 on white it sits well under the 3:1 that
     * WCAG asks for on control boundaries. See the note in section 5. */
    --pz-border-strong: #b8ada6;

    /* The dashboard charts plot one series, so this is the only data colour
     * they need. Validated against a white card: inside the light-mode OKLCH
     * lightness band, above the chroma floor, over 3:1 on the surface. */
    --pz-chart-series: var(--pz-terracotta-500);
    --pz-chart-series-hover: var(--pz-terracotta-700);

    /* Focus rings must clear 3:1 against whatever sits behind them. The brand
     * 500 only manages 2.6:1 on the greige page background, so rings use 600. */
    --pz-focus-ring: var(--pz-terracotta-600);
    --pz-focus-shadow: 0 0 0 3px rgba(230, 111, 81, 0.24);

    /* Surface used by hover rows, quiet fills and inset panels. */
    --pz-subtle-bg: var(--tblr-gray-100);

    --tblr-body-bg: #eeebea; /* identity, unchanged */
    --tblr-body-bg-rgb: 238, 235, 234;
    --tblr-body-color: var(--tblr-gray-800);
    --tblr-body-color-rgb: 41, 37, 36;
    --tblr-emphasis-color: var(--tblr-gray-900);

    /* gray-500 is 4.05:1 on the greige page, which fails for text. This is the
     * lightest warm grey that clears 4.5:1 on both the page and on white. */
    --tblr-muted: #706964;
    --tblr-muted-rgb: 112, 105, 100;
    --tblr-secondary: #706964;
    --tblr-secondary-rgb: 112, 105, 100;

    --tblr-border-color: var(--tblr-gray-300);
    --tblr-border-color-translucent: rgba(41, 37, 36, 0.12);

    --tblr-link-color: var(--pz-terracotta-text);
    --tblr-link-color-rgb: 195, 84, 57;
    --tblr-link-hover-color: var(--pz-terracotta-700);
    --tblr-link-hover-color-rgb: 180, 71, 42;
    --tblr-code-color: var(--pz-terracotta-text);

    /* Layered and warm tinted. A single large blur reads as a grey smudge; a
     * tight contact shadow plus a soft ambient one reads as depth. */
    --tblr-box-shadow-sm: 0 1px 2px rgba(41, 37, 36, 0.06);
    --tblr-box-shadow: 0 1px 2px rgba(41, 37, 36, 0.05), 0 4px 12px rgba(41, 37, 36, 0.07);
    --tblr-box-shadow-lg: 0 2px 4px rgba(41, 37, 36, 0.05), 0 12px 32px rgba(41, 37, 36, 0.1);
    --tblr-box-shadow-inset: inset 0 1px 2px rgba(41, 37, 36, 0.06);
}

/* Shared across both themes. */
:root {
    /* The whole interface sits at 90% of the browser default, which is the
     * same result as zooming to 90% for everything sized in rem. A percentage
     * rather than a pixel value, so a user who has raised their own default
     * font size still gets a proportionally larger interface. */
    font-size: 90%;

    --tblr-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
    --tblr-font-monospace: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace;
    --tblr-body-font-family: var(--tblr-font-sans-serif);

    /* 14px was tight for long candidate records. 15px reads better and still
     * keeps tables dense. Revert this single value if any layout suffers. */
    --tblr-body-font-size: 0.9375rem;
    --tblr-body-line-height: 1.5;

    /* Tabler 1.4 already moved to 6px. Softer still, scaled so nested elements
     * stay visually concentric. */
    --tblr-border-radius: 8px;
    --tblr-border-radius-sm: 5px;
    --tblr-border-radius-lg: 12px;
    --tblr-border-radius-xl: 16px;
    --tblr-border-radius-2xl: 24px;
}

/* ------------------------------------------------------------------ *
 * 3. Dark theme tokens
 *
 * Tabler's own dark mode is built on its cold gray ramp and hardcodes a blue
 * body background, so the parts that do not derive from --tblr-gray-* are
 * re-pointed here. Surfaces (cards, dropdowns, modals) already resolve to
 * gray-800 through --tblr-bg-surface, which the stone ramp makes warm.
 * ------------------------------------------------------------------ */

[data-bs-theme=dark] {
    --tblr-primary: var(--pz-terracotta-500);
    --tblr-primary-rgb: 230, 111, 81;
    --tblr-primary-fg: var(--tblr-gray-950);
    --tblr-primary-darken: var(--pz-terracotta-600);
    --tblr-primary-lt: rgba(230, 111, 81, 0.16);
    --tblr-primary-text-emphasis: var(--pz-terracotta-text-dark);
    --tblr-primary-bg-subtle: rgba(230, 111, 81, 0.14);
    --tblr-primary-border-subtle: rgba(230, 111, 81, 0.38);

    /* On a dark surface a deep terracotta reads as mud. The vivid brand shade
     * carries a near-black label at 5.4:1 instead, which is both accessible
     * and closer to the identity than darkening the fill would be. */
    --pz-primary-solid: var(--pz-terracotta-500);
    --pz-primary-solid-hover: var(--pz-terracotta-400);
    --pz-primary-solid-active: var(--pz-terracotta-300);

    /* Lightening this moves the opposite way to the light theme: on a dark
     * surface a lighter border means more contrast, not less. 4.52:1 against
     * a card, so the dark theme gains accessibility where the light theme
     * spends it. */
    --pz-border-strong: #968a82;

    /* Picked for the dark surface rather than inherited from the light theme.
     * The brand 500 sits just above the dark-mode lightness band on a card, so
     * the charts step down to 600, which clears the band, the chroma floor and
     * 3:1 on the surface. Hover goes the other way, to 400. */
    --pz-chart-series: var(--pz-terracotta-600);
    --pz-chart-series-hover: var(--pz-terracotta-400);

    --pz-focus-ring: var(--pz-terracotta-500);
    --pz-focus-shadow: 0 0 0 3px rgba(230, 111, 81, 0.34);
    --pz-subtle-bg: rgba(255, 255, 255, 0.04);

    /* gray-900 as the page left cards only 1.15:1 clear of their background,
     * so the whole screen read as one flat slab. Dropping the page below the
     * ramp lifts the cards off it without making anything pure black. */
    --tblr-body-bg: #15120f;
    --tblr-body-bg-rgb: 21, 18, 15;
    --tblr-body-color: var(--tblr-gray-200);
    --tblr-body-color-rgb: 231, 229, 228;
    --tblr-emphasis-color: var(--tblr-gray-50);

    --tblr-muted: var(--tblr-gray-400);
    --tblr-muted-rgb: 168, 162, 158;
    --tblr-secondary: var(--tblr-gray-400);
    --tblr-secondary-rgb: 168, 162, 158;
    --tblr-secondary-color: rgba(231, 229, 228, 0.75);
    --tblr-secondary-bg: var(--tblr-gray-800);
    --tblr-tertiary-color: rgba(231, 229, 228, 0.5);
    --tblr-tertiary-bg: var(--tblr-gray-800);

    --tblr-border-color: var(--tblr-gray-700);
    --tblr-border-color-translucent: rgba(255, 255, 255, 0.11);

    --tblr-link-color: var(--pz-terracotta-400);
    --tblr-link-color-rgb: 234, 140, 112;
    --tblr-link-hover-color: var(--pz-terracotta-300);
    --tblr-link-hover-color-rgb: 239, 173, 151;
    --tblr-code-color: var(--pz-terracotta-300);
    --tblr-highlight-bg: rgba(230, 111, 81, 0.28);
    --tblr-highlight-color: var(--tblr-gray-100);

    /* Shadows do almost nothing on a dark background. Depth comes from a
     * lighter surface plus a hairline, so the shadows only stop things from
     * looking pasted on. */
    --tblr-box-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --tblr-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(0, 0, 0, 0.45);
    --tblr-box-shadow-lg: 0 2px 4px rgba(0, 0, 0, 0.4), 0 12px 32px rgba(0, 0, 0, 0.55);
    --tblr-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.35);
}

/* The login and password-reset templates hardcode .bg-white on their panel,
 * which would stay a white slab in dark mode. */
[data-bs-theme=dark] .bg-white {
    background-color: var(--tblr-bg-surface) !important;
}

/* The wordmark ships with its own light plate baked into the PNG. Rounding it
 * makes that read as deliberate against a dark navbar rather than as a stray
 * white rectangle. */
[data-bs-theme=dark] .navbar-brand-image {
    border-radius: var(--tblr-border-radius-sm);
}

/* Swapping themes without this reads as a flash. The class is added by the
 * switcher for the length of the fade only, so it never affects first paint
 * or ordinary interaction. */
.theme-transition,
.theme-transition *,
.theme-transition *::before,
.theme-transition *::after {
    transition: background-color 220ms var(--pz-ease),
                border-color 220ms var(--pz-ease),
                color 220ms var(--pz-ease),
                fill 220ms var(--pz-ease) !important;
}

/* ------------------------------------------------------------------ *
 * 4. Base and typography
 * ------------------------------------------------------------------ */

#root {
    letter-spacing: 0;
    touch-action: manipulation;
    text-rendering: optimizeLegibility;
    position: relative;
    min-height: 100%;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Headings tighten slightly as they grow, which is what keeps large type from
 * looking loose. Tabler leaves them at the body tracking. */
h1, .h1, h2, .h2, h3, .h3 {
    letter-spacing: -0.018em;
    line-height: 1.25;
}

h4, .h4, h5, .h5 {
    letter-spacing: -0.008em;
}

/* Figures line up in columns instead of drifting, which matters on every
 * candidate table and the admin overview counters. */
.table td, .table th,
.admin-overview .number,
.badge,
time {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

/* ------------------------------------------------------------------ *
 * 5. Focus and accessibility
 *
 * The previous rules set box-shadow: none on every focus state, which left
 * keyboard users with almost no indication of where they were. These bring the
 * ring back, but only for keyboard focus, so clicking a field does not light
 * it up.
 * ------------------------------------------------------------------ */

:focus-visible {
    outline: 2px solid var(--pz-focus-ring);
    outline-offset: 2px;
}

/* Note on --pz-border-strong: WCAG 1.4.11 wants 3:1 on the boundary of a
 * control. The light theme's border is deliberately set below that, at
 * 2.20:1, because the stronger grey read as heavy across dense forms. The
 * focus ring and the hover state both clear 3:1, so the control is still
 * clearly identifiable once it is being used, but at rest a light input on a
 * white card is now a soft edge rather than a compliant one. Raise this value
 * if strict AA on the resting state matters more than the lighter look. */
.form-control,
.form-select {
    border-color: var(--pz-border-strong);
}

/* Hover restores a clearly perceptible boundary before you commit to a field. */
.form-control:hover:not(:disabled):not(:focus),
.form-select:hover:not(:disabled):not(:focus) {
    border-color: var(--tblr-gray-500);
}

.form-control:focus,
.form-select:focus {
    border-color: var(--pz-focus-ring);
    box-shadow: var(--pz-focus-shadow);
}

.form-control:focus-visible,
.form-select:focus-visible {
    outline: none;
}

.form-check-input {
    border-color: var(--pz-border-strong);
}

.form-check-input:focus {
    border-color: var(--pz-focus-ring);
    box-shadow: var(--pz-focus-shadow);
}

.form-check-input:checked {
    background-color: var(--tblr-primary);
    border-color: var(--tblr-primary);
}

.form-selectgroup-input:focus + .form-selectgroup-label {
    border-color: var(--tblr-primary);
    box-shadow: var(--pz-focus-shadow);
}

.btn:focus-visible,
.nav-link:focus-visible,
a:focus-visible {
    outline: 2px solid var(--pz-focus-ring);
    outline-offset: 2px;
}

/* Anything animated below stops animating for users who ask for that. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ------------------------------------------------------------------ *
 * 6. Component polish
 * ------------------------------------------------------------------ */

.btn {
    --tblr-btn-border-radius: var(--tblr-border-radius);
    font-weight: 500;
    transition: background-color var(--pz-duration) var(--pz-ease),
                border-color var(--pz-duration) var(--pz-ease),
                color var(--pz-duration) var(--pz-ease),
                box-shadow var(--pz-duration) var(--pz-ease),
                transform var(--pz-duration) var(--pz-ease);
}

/* The old blanket `.btn:hover { background: body-bg }` fought every variant
 * rule that followed it. Ghost and default buttons are targeted directly now,
 * so the coloured variants are left alone. */
.btn:not([class*="btn-"]):hover,
.btn.btn-default:hover,
.btn.btn-white:hover {
    background-color: var(--pz-subtle-bg);
}

.btn.btn-primary {
    --tblr-btn-color: var(--tblr-primary-fg);
    --tblr-btn-bg: var(--pz-primary-solid);
    --tblr-btn-border-color: var(--pz-primary-solid);
    --tblr-btn-hover-color: var(--tblr-primary-fg);
    --tblr-btn-hover-bg: var(--pz-primary-solid-hover);
    --tblr-btn-hover-border-color: var(--pz-primary-solid-hover);
    --tblr-btn-active-color: var(--tblr-primary-fg);
    --tblr-btn-active-bg: var(--pz-primary-solid-active);
    --tblr-btn-active-border-color: var(--pz-primary-solid-active);
    --tblr-btn-disabled-bg: var(--pz-primary-solid);
    --tblr-btn-disabled-border-color: var(--pz-primary-solid);
}

.btn.btn-outline-primary {
    --tblr-btn-color: var(--tblr-primary-text-emphasis);
    --tblr-btn-border-color: var(--tblr-primary);
    --tblr-btn-hover-color: var(--tblr-primary-fg);
    --tblr-btn-hover-bg: var(--pz-primary-solid);
    --tblr-btn-hover-border-color: var(--pz-primary-solid);
    --tblr-btn-active-color: var(--tblr-primary-fg);
    --tblr-btn-active-bg: var(--pz-primary-solid-active);
    --tblr-btn-active-border-color: var(--pz-primary-solid-active);
}

/* A press needs to feel like a press. One pixel is enough. */
.btn:active:not(:disabled) {
    transform: translateY(1px);
}

.btn:disabled {
    opacity: 0.55 !important;
    box-shadow: none;
}

.card {
    border-color: var(--tblr-border-color-translucent);
    box-shadow: var(--tblr-box-shadow-sm);
    transition: box-shadow var(--pz-duration) var(--pz-ease),
                border-color var(--pz-duration) var(--pz-ease);
}

/* Card headers were uppercase terracotta at 3.1:1 contrast. Small caps with
 * tracking keeps the same voice, the emphasis shade makes it legible. */
.card-header {
    text-transform: uppercase;
    letter-spacing: 0.045em;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--tblr-primary-text-emphasis);
    background-color: transparent;
    border-bottom-color: var(--tblr-border-color-translucent);
}

.card-body {
    overflow: auto;
}

/* A card is rounded but never clips its children, and Tabler only rounds
 * .list-group. Every admin table is a .table-responsive sitting as the card's
 * last child, so its square scroll box overhangs both bottom corners and the
 * last row's rule runs straight past the curve. Giving the child the card's
 * inner radius makes it clip itself, which a scroll container does for free
 * because overflow is already set. */
.card > .table-responsive:last-child,
.card > .card-body:last-child,
.card > .card-footer:last-child,
.card > .card-table:last-child {
    border-bottom-left-radius: var(--tblr-card-inner-border-radius);
    border-bottom-right-radius: var(--tblr-card-inner-border-radius);
}

.card > .table-responsive:first-child,
.card > .card-body:first-child,
.card > .card-table:first-child {
    border-top-left-radius: var(--tblr-card-inner-border-radius);
    border-top-right-radius: var(--tblr-card-inner-border-radius);
}

.footer {
    color: var(--tblr-muted);
}

/* The footer container carries exactly the page padding, so the copyright ends
 * up flush with the left edge of the card above it and reads as a torn-off last
 * row of that card. A little more inset makes it page furniture again. */
.footer > .container-xl {
    padding-right: calc(var(--tblr-page-padding) + 1rem);
    padding-left: calc(var(--tblr-page-padding) + 1rem);
}

/* Rows lift on hover so the eye can track across wide candidate tables. */
.table-hover > tbody > tr {
    transition: background-color var(--pz-duration) var(--pz-ease);
}

.table-hover > tbody > tr:hover > * {
    background-color: var(--pz-subtle-bg);
}

.table thead th {
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--tblr-muted);
}

/* ------------------------------------------------------------------ *
 * 6b. Badges
 *
 * Tabler gives a "-lt" badge a pale fill but full-saturation hue text, and a
 * solid badge a fully saturated fill. Both end up in the same table column,
 * so one row could carry a washed-out pill next to a vivid one. Everything
 * below collapses the two into a single dimmed treatment: a pale low-chroma
 * fill, a hairline border, and same-hue text held at 4.5:1 against its own
 * fill. Scoped to .badge so alerts, avatars and status dots keep their
 * saturated versions.
 *
 * The values are generated, not picked by eye. Each pair was searched for the
 * lightest same-hue text that still clears AA on its own background.
 * ------------------------------------------------------------------ */

.badge {
    font-weight: 500;
    letter-spacing: 0.01em;
    border: 1px solid transparent;
}

/* Light */

.badge.bg-primary,
.badge.bg-primary-lt {
    background-color: #f5eae7 !important;
    color: #ad4f37 !important;
    border-color: #e7d3cd !important;
} /* 4.51:1 */

.badge.bg-danger,
.badge.bg-danger-lt {
    background-color: #f5e7e7 !important;
    color: #bd3c3c !important;
    border-color: #e7cdcd !important;
} /* 4.51:1 */

.badge.bg-red,
.badge.bg-red-lt {
    background-color: #f5e7e7 !important;
    color: #bd3c3c !important;
    border-color: #e7cdcd !important;
} /* 4.51:1 */

.badge.bg-success,
.badge.bg-success-lt {
    background-color: #e7f5ea !important;
    color: #287d35 !important;
    border-color: #cde7d1 !important;
} /* 4.58:1 */

.badge.bg-green,
.badge.bg-green-lt {
    background-color: #e7f5ea !important;
    color: #287d35 !important;
    border-color: #cde7d1 !important;
} /* 4.58:1 */

.badge.bg-warning,
.badge.bg-warning-lt {
    background-color: #f5ede7 !important;
    color: #9c5c31 !important;
    border-color: #e7d8cd !important;
} /* 4.55:1 */

.badge.bg-orange,
.badge.bg-orange-lt {
    background-color: #f5ede7 !important;
    color: #9c5c31 !important;
    border-color: #e7d8cd !important;
} /* 4.55:1 */

.badge.bg-info,
.badge.bg-info-lt {
    background-color: #e7eff5 !important;
    color: #3370a3 !important;
    border-color: #cddbe7 !important;
} /* 4.53:1 */

.badge.bg-azure,
.badge.bg-azure-lt {
    background-color: #e7eff5 !important;
    color: #3370a3 !important;
    border-color: #cddbe7 !important;
} /* 4.53:1 */

.badge.bg-blue,
.badge.bg-blue-lt {
    background-color: #e7eef5 !important;
    color: #376dad !important;
    border-color: #cdd9e7 !important;
} /* 4.54:1 */

.badge.bg-cyan,
.badge.bg-cyan-lt {
    background-color: #e7f3f5 !important;
    color: #2a7784 !important;
    border-color: #cde3e7 !important;
} /* 4.55:1 */

.badge.bg-teal,
.badge.bg-teal-lt {
    background-color: #e7f5f1 !important;
    color: #277c63 !important;
    border-color: #cde7df !important;
} /* 4.51:1 */

.badge.bg-indigo,
.badge.bg-indigo-lt {
    background-color: #e7eaf5 !important;
    color: #4a62c6 !important;
    border-color: #cdd2e7 !important;
} /* 4.54:1 */

.badge.bg-purple,
.badge.bg-purple-lt {
    background-color: #f3e7f5 !important;
    color: #a23bbb !important;
    border-color: #e2cde7 !important;
} /* 4.53:1 */

.badge.bg-pink,
.badge.bg-pink-lt {
    background-color: #f5e7ec !important;
    color: #b93a67 !important;
    border-color: #e7cdd6 !important;
} /* 4.54:1 */

.badge.bg-yellow,
.badge.bg-yellow-lt {
    background-color: #f5f0e7 !important;
    color: #89682b !important;
    border-color: #e7decd !important;
} /* 4.54:1 */

.badge.bg-lime,
.badge.bg-lime-lt {
    background-color: #f0f5e7 !important;
    color: #577926 !important;
    border-color: #dce7cd !important;
} /* 4.54:1 */

.badge.bg-secondary,
.badge.bg-secondary-lt {
    background-color: #f5ede7 !important;
    color: #726b66 !important;
    border-color: #e7d8cd !important;
} /* 4.53:1 */

.badge.bg-muted,
.badge.bg-muted-lt {
    background-color: #f5ede7 !important;
    color: #726b66 !important;
    border-color: #e7d8cd !important;
} /* 4.53:1 */

.badge.bg-dark,
.badge.bg-dark-lt {
    background-color: #f5efe7 !important;
    color: #716c65 !important;
    border-color: #e7dbcd !important;
} /* 4.56:1 */

/* Dark */

[data-bs-theme=dark] .badge.bg-primary,
[data-bs-theme=dark] .badge.bg-primary-lt {
    background-color: #37231d !important;
    color: #d67259 !important;
    border-color: #624037 !important;
} /* 4.51:1 */

[data-bs-theme=dark] .badge.bg-danger,
[data-bs-theme=dark] .badge.bg-danger-lt {
    background-color: #371d1d !important;
    color: #d96868 !important;
    border-color: #623737 !important;
} /* 4.52:1 */

[data-bs-theme=dark] .badge.bg-red,
[data-bs-theme=dark] .badge.bg-red-lt {
    background-color: #371d1d !important;
    color: #d96868 !important;
    border-color: #623737 !important;
} /* 4.52:1 */

[data-bs-theme=dark] .badge.bg-success,
[data-bs-theme=dark] .badge.bg-success-lt {
    background-color: #1d3721 !important;
    color: #2eaf42 !important;
    border-color: #37623e !important;
} /* 4.52:1 */

[data-bs-theme=dark] .badge.bg-green,
[data-bs-theme=dark] .badge.bg-green-lt {
    background-color: #1d3721 !important;
    color: #2eaf42 !important;
    border-color: #37623e !important;
} /* 4.52:1 */

[data-bs-theme=dark] .badge.bg-warning,
[data-bs-theme=dark] .badge.bg-warning-lt {
    background-color: #37281d !important;
    color: #d07d45 !important;
    border-color: #624837 !important;
} /* 4.52:1 */

[data-bs-theme=dark] .badge.bg-orange,
[data-bs-theme=dark] .badge.bg-orange-lt {
    background-color: #37281d !important;
    color: #d07d45 !important;
    border-color: #624837 !important;
} /* 4.52:1 */

[data-bs-theme=dark] .badge.bg-info,
[data-bs-theme=dark] .badge.bg-info-lt {
    background-color: #1d2b37 !important;
    color: #4d96d2 !important;
    border-color: #374f62 !important;
} /* 4.55:1 */

[data-bs-theme=dark] .badge.bg-azure,
[data-bs-theme=dark] .badge.bg-azure-lt {
    background-color: #1d2b37 !important;
    color: #4d96d2 !important;
    border-color: #374f62 !important;
} /* 4.55:1 */

[data-bs-theme=dark] .badge.bg-blue,
[data-bs-theme=dark] .badge.bg-blue-lt {
    background-color: #1d2937 !important;
    color: #5891d5 !important;
    border-color: #374b62 !important;
} /* 4.51:1 */

[data-bs-theme=dark] .badge.bg-cyan,
[data-bs-theme=dark] .badge.bg-cyan-lt {
    background-color: #1d3337 !important;
    color: #2ea5b8 !important;
    border-color: #375c62 !important;
} /* 4.55:1 */

[data-bs-theme=dark] .badge.bg-teal,
[data-bs-theme=dark] .badge.bg-teal-lt {
    background-color: #1d372f !important;
    color: #2bad86 !important;
    border-color: #376255 !important;
} /* 4.53:1 */

[data-bs-theme=dark] .badge.bg-indigo,
[data-bs-theme=dark] .badge.bg-indigo-lt {
    background-color: #1d2237 !important;
    color: #7085db !important;
    border-color: #373f62 !important;
} /* 4.54:1 */

[data-bs-theme=dark] .badge.bg-purple,
[data-bs-theme=dark] .badge.bg-purple-lt {
    background-color: #321d37 !important;
    color: #bf68d5 !important;
    border-color: #5a3762 !important;
} /* 4.50:1 */

[data-bs-theme=dark] .badge.bg-pink,
[data-bs-theme=dark] .badge.bg-pink-lt {
    background-color: #371d26 !important;
    color: #d9658e !important;
    border-color: #623746 !important;
} /* 4.54:1 */

[data-bs-theme=dark] .badge.bg-yellow,
[data-bs-theme=dark] .badge.bg-yellow-lt {
    background-color: #372e1d !important;
    color: #c08d30 !important;
    border-color: #625337 !important;
} /* 4.52:1 */

[data-bs-theme=dark] .badge.bg-lime,
[data-bs-theme=dark] .badge.bg-lime-lt {
    background-color: #2c371d !important;
    color: #74aa2a !important;
    border-color: #506237 !important;
} /* 4.50:1 */

[data-bs-theme=dark] .badge.bg-secondary,
[data-bs-theme=dark] .badge.bg-secondary-lt {
    background-color: #37281d !important;
    color: #97908c !important;
    border-color: #624937 !important;
} /* 4.50:1 */

[data-bs-theme=dark] .badge.bg-muted,
[data-bs-theme=dark] .badge.bg-muted-lt {
    background-color: #37281d !important;
    color: #97908c !important;
    border-color: #624937 !important;
} /* 4.50:1 */

[data-bs-theme=dark] .badge.bg-dark,
[data-bs-theme=dark] .badge.bg-dark-lt {
    background-color: #372b1d !important;
    color: #98938c !important;
    border-color: #624f37 !important;
} /* 4.51:1 */

.badge.badge-outline {
    background-color: transparent !important;
    border-color: currentColor !important;
}


.modal-content {
    border: none;
    box-shadow: var(--tblr-box-shadow-lg);
}

.modal-blur {
    margin-top: 0;
    background-color: rgba(12, 10, 9, 0.4);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    position: fixed;
}

.dropdown-menu {
    border-color: var(--tblr-border-color-translucent);
    box-shadow: var(--tblr-box-shadow);
}

a.list-group-item {
    transition: color var(--pz-duration) var(--pz-ease),
                background-color var(--pz-duration) var(--pz-ease);
}

a.list-group-item.active {
    color: var(--tblr-link-color) !important;
    background-color: transparent !important;
}

a.list-group-item:hover {
    color: var(--tblr-link-color);
}

a.nav-link {
    transition: color var(--pz-duration) var(--pz-ease);
}

a.nav-link:hover {
    color: var(--tblr-link-color) !important;
}

a.nav-link.active,
a.nav-link.active svg {
    color: var(--tblr-link-color) !important;
}

.nav-link-icon svg {
    color: var(--tblr-muted);
}

.icon-muted svg {
    color: var(--tblr-muted);
}

.icon-text svg {
    width: 1.1rem;
    height: 1.1rem;
}

/* Disable arrows and spinners on number inputs. */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

input[type=number] {
    -moz-appearance: textfield;
}

/* ------------------------------------------------------------------ *
 * 7. Third-party widgets
 *
 * None of these know about Tabler's theme, so each one is re-pointed at the
 * shared tokens. That is what makes them follow dark mode.
 * ------------------------------------------------------------------ */

/* react-select takes its palette from the `theme` prop in
 * assets/components/form/Select.js, which now feeds it these same variables.
 * Only the focus ring is left to CSS, because react-select hardcodes it. */
.react-select__control--is-focused {
    border-color: var(--pz-focus-ring) !important;
    box-shadow: var(--pz-focus-shadow) !important;
}

.dz-message svg {
    width: 8rem;
    height: 8rem;
    stroke-width: 0.015rem;
}

.dz-button {
    background: none;
    box-shadow: none;
    border: none;
}

/*** Quill ***/

.quill .ql-toolbar {
    border-radius: var(--tblr-border-radius) var(--tblr-border-radius) 0 0;
    border-color: var(--tblr-border-color);
}

.quill .ql-container {
    border-radius: 0 0 var(--tblr-border-radius) var(--tblr-border-radius);
    border-color: var(--tblr-border-color);
}

.ql-snow a {
    color: var(--tblr-link-color);
}

.ql-editor {
    min-height: 8rem;
}

.ql-snow.ql-toolbar button:hover,
.ql-snow .ql-toolbar button:hover,
.ql-snow.ql-toolbar button:focus,
.ql-snow .ql-toolbar button:focus,
.ql-snow.ql-toolbar button.ql-active,
.ql-snow .ql-toolbar button.ql-active,
.ql-snow.ql-toolbar .ql-picker-label:hover,
.ql-snow .ql-toolbar .ql-picker-label:hover,
.ql-snow.ql-toolbar .ql-picker-label.ql-active,
.ql-snow .ql-toolbar .ql-picker-label.ql-active,
.ql-snow.ql-toolbar .ql-picker-item:hover,
.ql-snow .ql-toolbar .ql-picker-item:hover,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected {
    color: var(--tblr-primary);
}

.ql-snow.ql-toolbar button:hover .ql-fill,
.ql-snow .ql-toolbar button:hover .ql-fill,
.ql-snow.ql-toolbar button:focus .ql-fill,
.ql-snow .ql-toolbar button:focus .ql-fill,
.ql-snow.ql-toolbar button.ql-active .ql-fill,
.ql-snow .ql-toolbar button.ql-active .ql-fill,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill,
.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill,
.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill {
    fill: var(--tblr-primary);
}

.ql-snow.ql-toolbar button:hover .ql-stroke,
.ql-snow .ql-toolbar button:hover .ql-stroke,
.ql-snow.ql-toolbar button:focus .ql-stroke,
.ql-snow .ql-toolbar button:focus .ql-stroke,
.ql-snow.ql-toolbar button.ql-active .ql-stroke,
.ql-snow .ql-toolbar button.ql-active .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,
.ql-snow.ql-toolbar button:hover .ql-stroke-miter,
.ql-snow .ql-toolbar button:hover .ql-stroke-miter,
.ql-snow.ql-toolbar button:focus .ql-stroke-miter,
.ql-snow .ql-toolbar button:focus .ql-stroke-miter,
.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter,
.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter {
    stroke: var(--tblr-primary);
}

/* Quill's snow theme is light only: it paints its icons with a hardcoded #444
 * and its pickers with a white background. */
[data-bs-theme=dark] .quill .ql-toolbar,
[data-bs-theme=dark] .quill .ql-container {
    background-color: var(--tblr-bg-surface);
}

[data-bs-theme=dark] .ql-snow .ql-stroke,
[data-bs-theme=dark] .ql-snow .ql-stroke-miter {
    stroke: var(--tblr-body-color);
}

[data-bs-theme=dark] .ql-snow .ql-fill,
[data-bs-theme=dark] .ql-snow .ql-stroke.ql-fill {
    fill: var(--tblr-body-color);
}

[data-bs-theme=dark] .ql-snow .ql-picker,
[data-bs-theme=dark] .ql-snow .ql-picker-label,
[data-bs-theme=dark] .ql-editor.ql-blank::before {
    color: var(--tblr-body-color);
}

[data-bs-theme=dark] .ql-snow .ql-picker-options {
    background-color: var(--tblr-bg-surface);
    border-color: var(--tblr-border-color);
}

[data-bs-theme=dark] .ql-snow .ql-tooltip {
    background-color: var(--tblr-bg-surface);
    border-color: var(--tblr-border-color);
    box-shadow: var(--tblr-box-shadow);
    color: var(--tblr-body-color);
}

[data-bs-theme=dark] .ql-snow .ql-tooltip input[type=text] {
    background-color: var(--tblr-body-bg);
    border-color: var(--pz-border-strong);
    color: var(--tblr-body-color);
}

/*** React Tabs ***/

.react-tabs__tab-list {
    border-bottom: none !important;
    margin: 0 20px !important;
    white-space: pre !important;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    position: relative;
    top: 1px;
    scrollbar-width: thin;
}

.react-tabs__tab {
    padding: 10px 20px;
    margin-right: 10px;
    border-radius: var(--tblr-border-radius) var(--tblr-border-radius) 0 0;
    color: var(--tblr-muted);
    transition: background-color var(--pz-duration) var(--pz-ease),
                border-color var(--pz-duration) var(--pz-ease),
                color var(--pz-duration) var(--pz-ease);
}

.react-tabs__tab--selected {
    background-color: var(--tblr-bg-surface);
    border-color: var(--tblr-border-color);
    color: var(--tblr-primary-text-emphasis);
    font-weight: 500;
    z-index: 1;
}

.react-tabs__tab:hover:not(.react-tabs__tab--selected) {
    background-color: var(--pz-subtle-bg);
    border-color: var(--tblr-border-color);
    border-radius: var(--tblr-border-radius) var(--tblr-border-radius) 0 0;
    color: var(--tblr-body-color);
}

/* ------------------------------------------------------------------ *
 * 8. Application classes
 * ------------------------------------------------------------------ */

.facility-card {
    transition: border-color var(--pz-duration) var(--pz-ease),
                box-shadow var(--pz-duration) var(--pz-ease),
                transform var(--pz-duration) var(--pz-ease);
    color: var(--tblr-body-color) !important;
}

.facility-card:hover {
    border: 1px solid var(--tblr-primary);
    box-shadow: var(--tblr-box-shadow);
    transform: translateY(-2px);
    cursor: pointer;
}

/* Was a 300 character descendant chain that broke the moment any wrapper in
 * between changed. The class alone is enough. */
.facility-logo svg {
    width: 200px;
    height: 200px;
    stroke-width: 0.5px;
}

.job-categories span.form-selectgroup-label {
    color: var(--tblr-body-color) !important;
    transition: color var(--pz-duration) var(--pz-ease),
                border-color var(--pz-duration) var(--pz-ease),
                background-color var(--pz-duration) var(--pz-ease);
}

.job-categories span.form-selectgroup-label:hover {
    color: var(--tblr-link-color) !important;
    border-color: var(--tblr-link-color) !important;
    background-color: var(--tblr-primary-bg-subtle);
}

.scroll-offset {
    scroll-margin-top: 120px;
}

.checkbox-list-item {
    transition: background-color var(--pz-duration) var(--pz-ease),
                border-color var(--pz-duration) var(--pz-ease);
}

.checkbox-list-item:hover {
    border: 1px solid var(--tblr-border-color) !important;
    background-color: var(--pz-subtle-bg) !important;
}

.isInvalid {
    color: var(--tblr-danger) !important;
}

.no-hover-underline:hover {
    text-decoration: none;
}

.contractDateIcon {
    display: flex;
    justify-content: center;
}

.contractDateIcon svg {
    width: 120px;
    height: 120px;
    stroke-width: 0.75;
}

.text-gray {
    color: var(--tblr-muted);
}

/* Status tints. The border carries the signal, the fill stays quiet, so the
 * same rule reads correctly on either background. */
.bg-accepted {
    background-color: var(--tblr-success-bg-subtle);
    border-color: var(--tblr-success);
}

.bg-accepted-lt {
    background-color: var(--tblr-success-bg-subtle);
    border-color: var(--tblr-success-border-subtle);
}

.bg-rejected {
    background-color: var(--tblr-danger-bg-subtle);
    border-color: var(--tblr-danger);
}

.accordion-table {
    background-color: var(--tblr-bg-surface);
    border-top: 1px solid var(--tblr-border-color-translucent);
    border-radius: var(--tblr-border-radius);
}

.font-weight-regular {
    font-weight: var(--tblr-body-font-weight) !important;
}

.cursor-pointer:hover {
    cursor: pointer;
}

.accordion-item {
    transition: background-color var(--pz-duration) var(--pz-ease),
                border-color var(--pz-duration) var(--pz-ease);
}

.no-pointer-events {
    pointer-events: none;
}

.transcription::before,
.transcription::after {
    display: block;
    font-weight: bold;
    line-height: 0;
    opacity: 0.4;
    position: absolute;
    transition: opacity 0.5s var(--pz-ease);
    z-index: -1;
}

.transcription::before {
    content: "\201C";
    color: var(--tblr-gray-300);
    font-size: 7rem;
    top: 48px;
    left: 2px;
}

.transcription:hover::before {
    opacity: 1;
}

.transcription::after {
    content: "\201D";
    color: var(--tblr-gray-300);
    font-size: 4.5rem;
    bottom: 5px;
    right: 10px;
}

.transcription {
    background-color: var(--pz-subtle-bg);
    border: 1px solid var(--tblr-border-color-translucent);
    border-radius: var(--tblr-border-radius);
    cursor: pointer;
    font-family: Georgia, "Times New Roman", serif;
    font-style: italic;
    padding: 1rem;
    white-space: normal;
    position: relative;
    z-index: 1;
}

[data-bs-theme=dark] .transcription::before,
[data-bs-theme=dark] .transcription::after {
    color: var(--tblr-gray-600);
}

.transcription.collapsed {
    height: 50px;
    overflow: hidden;
    padding-right: 50px;
    text-overflow: ellipsis;
}

.transcription.expanded {
    height: auto;
    white-space: normal !important;
}

/* The admin dashboard used to be a 400px column of right-aligned numbers
 * inside 6rem of padding, which left most of the screen empty and gave the
 * figures no visual weight. It is a responsive grid of tiles now. */

/* The dashboard is the first thing an admin sees, so it gets more air than the
 * dense table screens behind it. */
.admin-overview.card-body {
    padding: 1.75rem 2rem 2rem;
}

.admin-overview .stat-section-title {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--tblr-muted);
    margin-bottom: 1rem;
}

.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 1.25rem;
}

/* Inset rather than raised: these sit on a card, so a white tile on a white
 * surface would disappear. The quiet fill reads as a well instead. */
.stat-tile {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.125rem;
    width: 100%;
    padding: 1.375rem 1.5rem;
    text-align: left;
    background-color: var(--pz-subtle-bg);
    border: 1px solid var(--tblr-border-color-translucent);
    border-radius: var(--tblr-border-radius-lg);
    color: inherit;
    cursor: pointer;
    transition: background-color var(--pz-duration) var(--pz-ease),
                border-color var(--pz-duration) var(--pz-ease),
                transform var(--pz-duration) var(--pz-ease);
}

.stat-tile:hover {
    background-color: var(--tblr-primary-bg-subtle);
    border-color: var(--tblr-primary);
    transform: translateY(-2px);
}

.stat-tile-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    margin-bottom: 0.625rem;
    border-radius: var(--tblr-border-radius);
    background-color: var(--tblr-primary-bg-subtle);
    color: var(--tblr-primary-text-emphasis);
}

.stat-tile-icon svg {
    width: 1.25rem;
    height: 1.25rem;
}

/* Lining figures at a large size need to sit on the same baseline grid across
 * tiles, so the count is tabular and the tracking is pulled in. */
.stat-tile-value {
    font-size: 1.875rem;
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    color: var(--tblr-emphasis-color);
}

.stat-tile-label {
    font-size: 0.8125rem;
    color: var(--tblr-muted);
}

/* Skeleton, so the grid does not collapse and reflow when the counts land. */
.stat-tile-loading {
    cursor: default;
    pointer-events: none;
}

.stat-tile-loading .stat-tile-icon,
.stat-tile-loading .stat-tile-value,
.stat-tile-loading .stat-tile-label {
    background-color: var(--pz-subtle-bg);
    border-radius: var(--tblr-border-radius-sm);
    color: transparent;
}

.stat-tile-loading .stat-tile-value {
    width: 4.5rem;
    height: 1.875rem;
    margin-bottom: 0.25rem;
}

.stat-tile-loading .stat-tile-label {
    width: 7rem;
    height: 0.8125rem;
}

/* ---- Weekly activity chart ---------------------------------------- *
 * One series, so no legend: the section heading names what is plotted. The
 * bars are divs rather than SVG because they have to reflow with the card, and
 * a viewBox would scale the axis text along with the geometry.
 * ------------------------------------------------------------------- */
.activity-chart-plot {
    position: relative;
    height: 180px;
}

/* Solid hairlines one step off the surface. Dashed rules read as a threshold
 * or a projection when they are only a grid. */
.activity-chart-gridline {
    position: absolute;
    left: 3rem;
    right: 0;
    border-top: 1px solid var(--tblr-border-color-translucent);
    pointer-events: none;
}

.activity-chart-tick {
    position: absolute;
    right: calc(100% + 0.625rem);
    transform: translateY(-50%);
    font-size: 0.6875rem;
    font-variant-numeric: tabular-nums;
    color: var(--tblr-muted);
}

.activity-chart-bars,
.activity-chart-axis {
    display: flex;
    align-items: flex-end;
    gap: 2px;
    margin-left: 3rem;
    height: 100%;
}

/* The slot is the hit target, not the bar. A quiet week is a two-pixel mark,
 * and hovering it should not require landing on those two pixels. */
.activity-chart-slot {
    position: relative;
    display: flex;
    flex: 1 1 0;
    align-items: flex-end;
    justify-content: center;
    height: 100%;
    cursor: default;
}

.activity-chart-bar {
    width: 100%;
    max-width: 24px;
    min-height: 2px;
    background-color: var(--pz-chart-series);
    /* Rounded at the data end, square where it meets the baseline. */
    border-radius: 4px 4px 0 0;
    transition: background-color var(--pz-duration) var(--pz-ease);
}

.activity-chart-bar.is-empty {
    min-height: 0;
}

.activity-chart-bar.is-hovered {
    background-color: var(--pz-chart-series-hover);
}

/* Only the busiest week carries a number. A value on all twelve is noise, and
 * the axis plus the tooltip already reach the rest. */
.activity-chart-peak {
    position: absolute;
    bottom: 100%;
    margin-bottom: 0.25rem;
    font-size: 0.6875rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    color: var(--tblr-body-color);
}

/* bottom is set per hover from the bar's own height, so the tooltip rides the
 * cap of the column it describes rather than floating above the whole plot. */
.activity-chart-tooltip {
    position: absolute;
    display: flex;
    flex-direction: column;
    padding: 0.375rem 0.625rem;
    transform: translateX(-50%);
    white-space: nowrap;
    pointer-events: none;
    background-color: var(--tblr-bg-surface);
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius);
    box-shadow: var(--tblr-box-shadow-sm);
    z-index: 2;
}

.activity-chart-tooltip-label {
    font-size: 0.6875rem;
    color: var(--tblr-muted);
}

.activity-chart-tooltip-value {
    font-size: 0.875rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--tblr-emphasis-color);
}

/* Height comes from the labels, so the axis band can never be cut off by a
 * fixed plot height the way a nested-scroll card is. */
.activity-chart-axis {
    height: auto;
    padding-top: 0.5rem;
}

.activity-chart-axis-label {
    flex: 1 1 0;
    font-size: 0.6875rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
    color: var(--tblr-muted);
}

.activity-chart-summary {
    margin-top: 0.75rem;
    margin-left: 3rem;
    font-size: 0.75rem;
    color: var(--tblr-muted);
}

/* ---- Bar breakdown ------------------------------------------------ *
 * Shared by the nationality list, the invitation funnel and the file actions.
 * Nominal categories, so every bar is the same colour: shading them by size
 * would encode the length a second time and spend the only free channel on
 * something the bar already says.
 * ------------------------------------------------------------------- */
.bar-breakdown {
    --bar-breakdown-label: 7rem;

    display: flex;
    flex-direction: column;
    gap: 0.875rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.bar-breakdown-row {
    display: grid;
    grid-template-columns: var(--bar-breakdown-label) 1fr auto;
    align-items: center;
    gap: 0.75rem;
}

/* A long nationality truncates rather than wrapping, which would break the
 * row rhythm. The full name stays in the title attribute. */
.bar-breakdown-label {
    overflow: hidden;
    font-size: 0.8125rem;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--tblr-body-color);
}

.bar-breakdown-track {
    height: 8px;
    background-color: var(--pz-subtle-bg);
    border-radius: 4px;
}

.bar-breakdown-bar {
    display: block;
    height: 100%;
    background-color: var(--pz-chart-series);
    border-radius: 4px;
}

/* Aligned in a column, so these are the one place tabular figures belong. */
.bar-breakdown-value {
    min-width: 3rem;
    font-size: 0.8125rem;
    font-weight: 600;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--tblr-emphasis-color);
}

/* ---- Delivery meter ------------------------------------------------ *
 * Two classes, so the number leads and the bar only supports it. A pie of two
 * slices would be the wrong form outright.
 * ------------------------------------------------------------------- */
/* Capped, so a 93% fill does not stretch into a metre of bar on a wide screen
 * and lose the proportion it is meant to show. */
.delivery-meter {
    max-width: 28rem;
}

.delivery-meter-value {
    font-size: 2.25rem;
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--tblr-emphasis-color);
}

.delivery-meter-caption {
    margin-bottom: 1rem;
    font-size: 0.8125rem;
    color: var(--tblr-muted);
}

/* The track is a lighter step of the same idea rather than a neutral well, so
 * the shortfall reads as the rest of the bar and not as empty space. */
.delivery-meter-track {
    height: 10px;
    background-color: var(--tblr-danger);
    border-radius: 5px;
    overflow: hidden;
}

.delivery-meter-fill {
    height: 100%;
    background-color: var(--tblr-success);
    /* Square on the right, so the boundary between the two states is a clean
     * edge instead of a curve that reads as the end of the bar. */
    border-radius: 5px 0 0 5px;
}

.delivery-meter-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem 1.25rem;
    margin: 0.75rem 0 0;
    padding: 0;
    list-style: none;
    font-size: 0.8125rem;
    color: var(--tblr-muted);
}

.delivery-meter-legend li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* The swatch carries the colour; the words beside it carry the meaning, so
 * the state never rests on colour alone. */
.delivery-meter-swatch {
    width: 10px;
    height: 10px;
    border-radius: 3px;
}

.delivery-meter-swatch.is-sent {
    background-color: var(--tblr-success);
}

.delivery-meter-swatch.is-failed {
    background-color: var(--tblr-danger);
}

/* card-table is built to sit flush against the edges of a card, so its row
 * rules run the full width of their container. Inside a rounded box that means
 * every line overshoots the corner radius and leaves a visible stub. Clipping
 * the wrapper is what makes the rules stop at the curve. */
.admin-overview .stat-table {
    border: 1px solid var(--tblr-border-color-translucent);
    border-radius: var(--tblr-border-radius-lg);
    overflow: hidden;
}

.admin-overview .stat-table .table {
    margin-bottom: 0;
}

.admin-overview .table > :not(caption) > * > td {
    padding-top: 0.25rem !important;
    padding-bottom: 0.25rem !important;
}

/* Build stamp under the dashboard. This was a hardcoded #f8f9fa strip, which
 * stayed a bright white band in dark mode. */
/* Rendered as the card's .card-footer, so Tabler already supplies the padding
 * and the top rule. Adding a border and a radius of its own drew a second box
 * inside the card whose fill overhung the rounded bottom corners. */
.app-version-bar {
    text-align: center;
    background-color: var(--pz-subtle-bg);
    color: var(--tblr-muted);
    font-family: var(--tblr-font-monospace);
    font-size: 11px;
}

.debug {
    background-color: var(--pz-subtle-bg);
    border-radius: var(--tblr-border-radius-sm);
    font-family: var(--tblr-font-monospace);
    font-size: 10px;
    padding: 0 5px;
    position: relative;
    top: 1px;
    vertical-align: middle;
}

/* ---- Support page -------------------------------------------------- *
 * The page somebody opens when something is already broken, so the prose sets
 * a comfortable measure and the diagnostics are structured enough to be
 * pasted into a ticket rather than described in prose.
 * ------------------------------------------------------------------- */

/* The one page here that gets read rather than scanned, so it sits further
 * inside its card than a table or a form would. */
.support-page {
    padding: 2rem;
}

@media (min-width: 992px) {
    .support-page {
        padding: 2.5rem;
    }
}

/* Long lines are the main thing that made this page tiring to read. 76ch is at
 * the top of the comfortable range, which fills the card on a wide screen
 * without letting a paragraph run the full width of a desktop. */
.support-prose {
    max-width: 76ch;
}

.support-prose h2 {
    margin-bottom: 0.75rem;
}

.support-prose h3 {
    margin-top: 2rem;
    font-size: 1rem;
}

.support-prose p {
    color: var(--tblr-body-color);
}

.support-lead {
    font-size: 1.0625rem;
    line-height: 1.6;
}

.support-card-title {
    font-size: 1rem;
    margin-bottom: 0.5rem;
}

/* The sidebar is no longer a stack of separate cards, so the rule takes over
 * the job the gap between them used to do. Only once the columns are actually
 * side by side: stacked on a phone a left border would point at nothing. */
@media (min-width: 992px) {
    .support-aside {
        padding-left: 2rem;
        border-left: 1px solid var(--tblr-border-color-translucent);
    }
}

.support-section + .support-section {
    margin-top: 2rem;
}

.support-contacts {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* A whole row is the hit target rather than the link text, which on a phone is
 * the difference between reaching support and mistyping a phone number. */
.support-contact {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    padding: 0.75rem 0.875rem;
    text-decoration: none;
    background-color: var(--pz-subtle-bg);
    border: 1px solid var(--tblr-border-color-translucent);
    border-radius: var(--tblr-border-radius);
    color: inherit;
    transition: border-color var(--pz-duration) var(--pz-ease),
                background-color var(--pz-duration) var(--pz-ease);
}

.support-contact:hover {
    border-color: var(--tblr-primary);
    color: inherit;
    text-decoration: none;
}

.support-contact-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    background-color: var(--tblr-primary-lt);
    border-radius: var(--tblr-border-radius);
    color: var(--tblr-primary-text-emphasis);
}

.support-contact-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.support-contact-label {
    font-size: 0.75rem;
    color: var(--tblr-muted);
}

/* A long address shortens rather than pushing the card wider. */
.support-contact-value {
    overflow: hidden;
    font-weight: 500;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.support-diagnostics-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.5rem;
}

.support-diagnostics-head .btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    flex: 0 0 auto;
}

.support-diagnostics {
    display: grid;
    grid-template-columns: minmax(5.5rem, auto) 1fr;
    gap: 0.5rem 1rem;
    margin: 0;
    font-size: 0.8125rem;
}

.support-diagnostics dt {
    font-weight: 400;
    color: var(--tblr-muted);
}

/* The user agent is one long unbroken token, so it has to be allowed to break
 * anywhere or it forces the whole card wider than its column. */
.support-diagnostics dd {
    margin: 0;
    overflow-wrap: anywhere;
}

.support-diagnostics dd.is-mono {
    font-family: var(--tblr-font-monospace);
    font-size: 0.6875rem;
    line-height: 1.5;
    color: var(--tblr-muted);
}

/* ------------------------------------------------------------------ *
 * 9. Symfony dump
 * ------------------------------------------------------------------ */

.sf-dump {
    background-color: var(--tblr-bg-surface) !important;
    color: var(--tblr-body-color) !important;
    margin-bottom: 0 !important;
    outline: none !important;
    padding: 25px !important;
    z-index: 1000 !important;
}

.sf-dump-default {
    background-color: var(--pz-subtle-bg) !important;
    border-radius: var(--tblr-border-radius-sm);
}

.sf-dump-public {
    color: #268f36 !important;
}

.sf-dump-protected {
    color: #d39e00 !important;
}

.sf-dump-private {
    color: var(--tblr-muted) !important;
}

.sf-dump-note {
    color: var(--tblr-primary-text-emphasis) !important;
}

.sf-dump-key {
    color: #0d7685 !important;
}

.sf-dump-str {
    color: #2f9e6e !important;
}

.sf-dump-ellipsis {
    max-width: unset !important;
}

.sf-dump-toggle {
    position: relative;
    top: -1px;
    left: 1px;
}

[data-bs-theme=dark] .sf-dump-public {
    color: #6fcf7f !important;
}

[data-bs-theme=dark] .sf-dump-protected {
    color: #e8c15a !important;
}

[data-bs-theme=dark] .sf-dump-key {
    color: #5cc3d6 !important;
}

[data-bs-theme=dark] .sf-dump-str {
    color: #6fd6a5 !important;
}

/*
 * Shared language list editor, used inside the composer inspector and the
 * form editor. Colours come from the application theme tokens so the cards
 * follow light and dark mode in both hosts. The container query stacks the
 * two fields when the host panel (not the viewport) becomes narrow; the
 * inspector width changes independently of the window.
 */

.cvl-list {
    container-type: inline-size;
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
}

.cvl-item {
    border: 1px solid var(--tblr-border-color, #dadfe5);
    border-radius: 6px;
    padding: 10px 12px 12px;
    margin: 0;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
}

.cvl-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}

.cvl-title {
    float: none;
    width: auto;
    margin: 0;
    padding: 0;
    font-size: .875rem;
    font-weight: 600;
    line-height: 1.3;
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cvl-head-actions {
    display: flex;
    gap: 2px;
    flex-shrink: 0;
}

.cvl-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: 0;
    border-radius: 4px;
    background: none;
    color: var(--tblr-secondary, #706964);
    cursor: pointer;
    padding: 0;
    line-height: 1;
}

.cvl-icon-btn:hover:not(:disabled) {
    background: var(--pz-subtle-bg, #f6f8fa);
    color: inherit;
}

.cvl-icon-btn:focus-visible {
    outline: 2px solid var(--tblr-primary, #e66f51);
    outline-offset: 1px;
}

.cvl-icon-btn:disabled {
    opacity: .35;
    cursor: default;
}

.cvl-remove:hover:not(:disabled) {
    color: var(--tblr-danger, #d63939);
    background: rgba(214, 57, 57, .08);
}

/* Two equal columns while they fit, stacked below; the fields never size
   themselves after their content. */
.cvl-fields {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 8px 12px;
    min-width: 0;
}

@container (max-width: 340px) {
    .cvl-fields {
        grid-template-columns: 1fr;
    }
}

.cvl-field {
    min-width: 0;
    max-width: 100%;
}

.cvl-field .form-label {
    margin-bottom: 4px;
    font-size: .8125rem;
}

.cvl-field input,
.cvl-field select {
    width: 100%;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
}

/* The closed select truncates with an ellipsis as a last resort; the
   complete value stays available via title and the open list. */
.cvl-field select {
    text-overflow: ellipsis;
}

.cvl-error {
    margin-top: 6px;
    font-size: .8125rem;
    color: var(--tblr-danger, #d63939);
}

.cvl-add {
    align-self: flex-start;
    border: 1px dashed var(--tblr-border-color, #dadfe5);
    border-radius: 6px;
    background: none;
    color: var(--tblr-primary-text-emphasis, #c35439);
    font-size: .875rem;
    padding: 6px 12px;
    cursor: pointer;
}

.cvl-add:hover {
    background: var(--pz-subtle-bg, #f6f8fa);
}

.cvl-add:focus-visible {
    outline: 2px solid var(--tblr-primary, #e66f51);
    outline-offset: 1px;
}

/*
 * Shared profile image editor (composer inspector + form editor). Colours
 * come from the application theme tokens so both hosts follow light and
 * dark mode.
 */

.cvp-editor {
    min-width: 0;
}

.cvp-preview {
    display: flex;
    justify-content: center;
    margin-bottom: 12px;
}

.cvp-preview img {
    width: 140px;
    height: 140px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--tblr-border-color, #dadfe5);
    background: var(--pz-subtle-bg, #f6f8fa);
}

.cvp-placeholder {
    width: 100%;
    border: 1px dashed var(--tblr-border-color, #dadfe5);
    border-radius: 6px;
    background: var(--pz-subtle-bg, #f6f8fa);
    color: var(--tblr-secondary, #706964);
    font-size: .8125rem;
    text-align: center;
    padding: 24px 12px;
}

.cvp-error {
    background: rgba(214, 57, 57, .08);
    color: var(--tblr-danger, #d63939);
    border: 1px solid rgba(214, 57, 57, .25);
    border-radius: 6px;
    font-size: .8125rem;
    padding: 8px 12px;
    margin: 8px 0;
}

.cvp-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.cvp-hint {
    font-size: .75rem;
    color: var(--tblr-secondary, #706964);
    margin-top: 4px;
}

.cvp-group {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--tblr-border-color, #dadfe5);
}

.cvp-group-title {
    display: block;
    font-size: .6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--tblr-secondary, #706964);
    margin-bottom: 8px;
}

.cvp-segmented {
    display: flex;
    border: 1px solid var(--tblr-border-color, #dadfe5);
    border-radius: 6px;
    overflow: hidden;
}

.cvp-segmented button {
    flex: 1 1 0;
    min-width: 0;
    border: 0;
    background: none;
    font-size: .8125rem;
    padding: 8px;
    cursor: pointer;
    color: var(--tblr-secondary, #706964);
}

.cvp-segmented button + button {
    border-left: 1px solid var(--tblr-border-color, #dadfe5);
}

.cvp-segmented button[aria-checked="true"] {
    background: rgba(var(--tblr-primary-rgb, 230, 111, 81), .1);
    color: var(--tblr-primary-text-emphasis, #c35439);
    font-weight: 600;
}

.cvp-slider-row {
    margin-bottom: 8px;
}

.cvp-slider-row .form-label {
    margin-bottom: 2px;
    font-size: .8125rem;
}

.cvp-slider-controls {
    display: flex;
    align-items: center;
    gap: 8px;
}

.cvp-slider-controls input[type="range"] {
    flex: 1 1 auto;
    min-width: 0;
    accent-color: var(--tblr-primary, #e66f51);
}

.cvp-slider-value {
    font-size: .8125rem;
    color: var(--tblr-secondary, #706964);
    min-width: 46px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.cvp-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    overflow: hidden;
    white-space: nowrap;
}

/*
 * Editor chrome for the visual CV composer. Everything here styles the
 * workspace around the document; nothing in this file can reach the PDF
 * (the document itself lives in an iframe whose chrome styles come from
 * composerRuntime.js and are equally editor-only).
 *
 * Every colour derives from the application's theme tokens, so the composer
 * follows light and dark mode with the rest of the app. Only two things stay
 * fixed in both themes: the A4 sheets (they are the printed page) and the
 * canvas backdrop they sit on, which is always darker than the paper.
 */

.cvc-shell {
    --cvc-space-1: 4px;
    --cvc-space-2: 8px;
    --cvc-space-3: 12px;
    --cvc-space-4: 16px;
    --cvc-space-5: 24px;
    --cvc-space-6: 32px;
    --cvc-radius: 6px;
    --cvc-border: var(--tblr-border-color, #dadfe5);
    --cvc-accent: var(--tblr-primary, #e66f51);
    /* Tints are mixed from the brand rgb triplet so they follow the accent
       instead of pinning a second, unrelated hue. */
    --cvc-accent-rgb: var(--tblr-primary-rgb, 230, 111, 81);
    --cvc-accent-soft: rgba(var(--cvc-accent-rgb), .1);
    --cvc-accent-softer: rgba(var(--cvc-accent-rgb), .08);
    /* The brand hue only carries a label from this shade on; it is the one
       app.css validated for solid fills in both themes. */
    --cvc-accent-solid: var(--pz-primary-solid, var(--cvc-accent));
    /* Brand-coloured *text* needs the dimmed shade: the brand hue itself only
       reaches 3.1:1 on a surface, which is fine for borders but not labels. */
    --cvc-accent-text: var(--tblr-primary-text-emphasis, #c35439);
    --cvc-surface: var(--tblr-bg-surface, #fff);
    --cvc-surface-muted: var(--pz-subtle-bg, #f6f8fa);
    --cvc-text: var(--tblr-body-color, #1f2937);
    --cvc-text-muted: var(--tblr-secondary, #706964);
    /* The grip is the drag control, not decoration, so it holds 3:1 against
       the surface in both themes. */
    --cvc-grip: color-mix(in srgb, var(--cvc-text) 55%, transparent);
    /* Keep in sync with the canvas background injected by composerRuntime. */
    --cvc-canvas-bg: #ded9d5;
    --cvc-shadow: 0 1px 3px rgba(30, 40, 60, .06);
    --cvc-shadow-lg: 0 4px 16px rgba(30, 40, 60, .12);
    --cvc-shadow-drawer: 0 4px 24px rgba(30, 40, 60, .18);
    --cvc-skeleton-a: var(--tblr-gray-100, #eef1f4);
    --cvc-skeleton-b: var(--tblr-gray-50, #f6f8fa);
    --cvc-toolbar-h: 52px;
    --cvc-tab-h: 40px;
    --cvc-sidebar-w: 280px;
    --cvc-inspector-w: clamp(300px, 22vw, 360px);
    --cvc-danger: var(--tblr-danger, #d63939);

    display: flex;
    flex-direction: column;
    /* --cvc-shell-top is measured by the shell itself (offset from the page
       top); the fallback only covers the first paint. The 24px allowance is
       the page-body bottom padding. */
    height: calc(100dvh - var(--cvc-shell-top, 170px) - 24px);
    min-height: 560px;
    background: var(--cvc-surface);
    /* Buttons do not inherit colour from their ancestors, so every control
       below picks this up explicitly via `color: inherit`. */
    color: var(--cvc-text);
    border: 1px solid var(--cvc-border);
    border-radius: var(--cvc-radius);
    box-shadow: var(--cvc-shadow);
    overflow: hidden;
}

[data-bs-theme=dark] .cvc-shell {
    /* The paper is white in both themes, so its backdrop goes darker than
       the shell rather than lighter, and the sheets keep their lift. */
    --cvc-canvas-bg: #100e0d;
    --cvc-shadow: 0 1px 2px rgba(0, 0, 0, .4);
    --cvc-shadow-lg: 0 4px 16px rgba(0, 0, 0, .5);
    --cvc-shadow-drawer: 0 4px 24px rgba(0, 0, 0, .6);
    --cvc-skeleton-a: var(--tblr-gray-800, #292524);
    --cvc-skeleton-b: var(--tblr-gray-700, #44403c);
}

/* Let the composer use most of the viewport width; the variant list and all
   other pages keep the regular container width. */
.page-body .container-xl:has(.cvc-shell) {
    max-width: min(92%, 1880px);
}

/* ---------- toolbar ---------- */

.cvc-toolbar {
    display: flex;
    align-items: center;
    gap: var(--cvc-space-2);
    min-height: var(--cvc-toolbar-h);
    padding: 0 var(--cvc-space-3);
    border-bottom: 1px solid var(--cvc-border);
    background: var(--cvc-surface);
    flex-wrap: wrap;
}

.cvc-toolbar-group {
    display: flex;
    align-items: center;
    gap: var(--cvc-space-2);
    min-width: 0;
}

.cvc-toolbar-group.cvc-right {
    margin-left: auto;
}

.cvc-title {
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.2;
    padding: var(--cvc-space-1) var(--cvc-space-2);
    border: 1px solid transparent;
    border-radius: var(--cvc-radius);
    cursor: text;
    max-width: 340px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cvc-title:hover {
    border-color: var(--cvc-border);
    background: var(--cvc-surface-muted);
}

.cvc-title-input {
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.2;
    padding: var(--cvc-space-1) var(--cvc-space-2);
    border: 1px solid var(--cvc-accent);
    border-radius: var(--cvc-radius);
    background: var(--cvc-surface);
    color: inherit;
    outline: none;
    width: 340px;
    max-width: 45vw;
}

/* ---------- undo / redo ---------- */

.cvc-history-group {
    display: inline-flex;
    gap: var(--cvc-space-1);
}

.cvc-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 1px solid transparent;
    border-radius: var(--cvc-radius);
    background: none;
    color: inherit;
    cursor: pointer;
    padding: 0;
}

.cvc-icon-btn:hover:not(:disabled) {
    background: var(--cvc-surface-muted);
    border-color: var(--cvc-border);
}

.cvc-icon-btn:active:not(:disabled) {
    background: var(--cvc-accent-soft);
}

.cvc-icon-btn:focus-visible {
    outline: 2px solid var(--cvc-accent);
    outline-offset: 1px;
}

/* Unmistakably off, but the icon stays readable: muted colour instead of a
   near-invisible opacity fade. */
.cvc-icon-btn:disabled {
    color: color-mix(in srgb, var(--cvc-text-muted) 55%, transparent);
    cursor: default;
}

.cvc-save-indicator {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .8125rem;
    color: var(--cvc-text-muted);
    white-space: nowrap;
}

.cvc-save-indicator .cvc-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--cvc-text-muted);
    flex-shrink: 0;
}

.cvc-save-indicator.is-dirty .cvc-dot { background: #f59f00; }
.cvc-save-indicator.is-saving .cvc-dot { background: var(--cvc-accent); }
.cvc-save-indicator.is-saved .cvc-dot { background: #2fb344; }
.cvc-save-indicator.is-failed { color: var(--cvc-danger); }
.cvc-save-indicator.is-failed .cvc-dot { background: var(--cvc-danger); }

/* ---------- workspace columns ---------- */

.cvc-workspace {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
}

.cvc-sidebar {
    width: var(--cvc-sidebar-w);
    min-width: 240px;
    max-width: var(--cvc-sidebar-w);
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--cvc-border);
    background: var(--cvc-surface);
    min-height: 0;
}

.cvc-inspector {
    width: var(--cvc-inspector-w);
    min-width: 300px;
    max-width: 380px;
    display: flex;
    flex-direction: column;
    border-left: 1px solid var(--cvc-border);
    background: var(--cvc-surface);
    min-height: 0;
}

.cvc-canvas {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    background: var(--cvc-canvas-bg);
    overflow: auto;
    position: relative;
}

/* ---------- sidebar tabs ---------- */

.cvc-tabs {
    display: flex;
    border-bottom: 1px solid var(--cvc-border);
    background: var(--cvc-surface);
    flex-shrink: 0;
}

.cvc-tab {
    flex: 1 1 0;
    height: var(--cvc-tab-h);
    border: 0;
    background: none;
    font-size: .875rem;
    color: var(--cvc-text-muted);
    border-bottom: 2px solid transparent;
    cursor: pointer;
    padding: 0 var(--cvc-space-3);
    white-space: nowrap;
}

.cvc-tab:hover {
    color: inherit;
    background: var(--cvc-surface-muted);
}

.cvc-tab[aria-selected="true"] {
    color: var(--cvc-accent-text);
    font-weight: 600;
    border-bottom-color: var(--cvc-accent);
}

.cvc-tab:focus-visible {
    outline: 2px solid var(--cvc-accent);
    outline-offset: -2px;
}

.cvc-sidebar-body {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
}

.cvc-panel-heading {
    font-size: .6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--cvc-text-muted);
    padding: var(--cvc-space-4) var(--cvc-space-4) var(--cvc-space-2);
}

/* ---------- section navigator ---------- */

.cvc-nav-row {
    display: flex;
    align-items: center;
    gap: var(--cvc-space-2);
    width: 100%;
    padding: var(--cvc-space-2) var(--cvc-space-4);
    border: 0;
    background: none;
    color: inherit;
    text-align: left;
    font-size: .875rem;
    cursor: pointer;
    border-left: 2px solid transparent;
}

.cvc-nav-row:hover {
    background: var(--cvc-surface-muted);
}

.cvc-nav-row[aria-current="true"] {
    background: var(--cvc-accent-softer);
    border-left-color: var(--cvc-accent);
    font-weight: 600;
}

.cvc-nav-row:focus-visible {
    outline: 2px solid var(--cvc-accent);
    outline-offset: -2px;
}

.cvc-nav-row.is-drop-before,
.cvc-nav-tail.is-drop-before { box-shadow: inset 0 2px 0 0 var(--cvc-accent); }

.cvc-nav-row.is-drag-source { opacity: .5; }

.cvc-nav-row {
    user-select: none;
}

.cvc-nav-tail {
    min-height: 12px;
}

.cvc-nav-grip {
    border: 0;
    background: none;
    padding: 2px;
    color: var(--cvc-grip);
    cursor: grab;
    flex-shrink: 0;
    font-size: .8125rem;
    line-height: 1;
    border-radius: 4px;
}

.cvc-nav-grip:hover {
    color: var(--cvc-accent);
    background: var(--cvc-accent-soft);
}

.cvc-nav-grip:focus-visible {
    outline: 2px solid var(--cvc-accent);
    outline-offset: 1px;
}

.cvc-nav-grip[aria-pressed="true"] {
    color: var(--tblr-primary-fg, #fff);
    background: var(--cvc-accent-solid);
}

/* Template-fixed blocks show a marker, never a grab affordance. */
.cvc-nav-grip.is-fixed {
    cursor: default;
    color: color-mix(in srgb, var(--cvc-text) 25%, transparent);
}

.cvc-nav-grip.is-fixed:hover {
    color: color-mix(in srgb, var(--cvc-text) 25%, transparent);
    background: none;
}

.cvc-nav-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cvc-nav-count {
    font-size: .75rem;
    color: var(--cvc-text-muted);
    flex-shrink: 0;
    min-width: 16px;
    text-align: right;
}

.cvc-nav-add {
    border: 0;
    background: none;
    color: var(--cvc-accent-text);
    font-size: .75rem;
    padding: 2px 6px;
    border-radius: 4px;
    cursor: pointer;
    flex-shrink: 0;
    white-space: nowrap;
}

.cvc-nav-add:hover {
    background: var(--cvc-accent-soft);
}

.cvc-nav-empty {
    font-size: .75rem;
    color: var(--cvc-text-muted);
    flex-shrink: 0;
}

.cvc-sidebar-hint {
    font-size: .75rem;
    color: var(--cvc-text-muted);
    padding: var(--cvc-space-3) var(--cvc-space-4);
}

/* ---------- publication ---------- */

.cvc-muted-note {
    font-size: .75rem;
    color: var(--cvc-text-muted);
    border: 1px solid var(--cvc-border);
    border-radius: 999px;
    padding: 1px 8px;
    white-space: nowrap;
}

.cvc-publication-context {
    padding: var(--cvc-space-3) var(--cvc-space-4);
    border-bottom: 1px solid var(--cvc-border);
    background: var(--cvc-surface-muted);
    font-size: .8125rem;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.cvc-publish-current {
    display: flex;
    flex-direction: column;
    gap: 2px;
    border: 1px solid var(--cvc-border);
    border-radius: var(--cvc-radius);
    background: var(--cvc-surface-muted);
    padding: var(--cvc-space-2) var(--cvc-space-3);
    margin-bottom: var(--cvc-space-3);
    font-size: .875rem;
}

.cvc-publish-current-label {
    font-size: .6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--cvc-text-muted);
}

.cvc-publish-warning {
    margin-top: var(--cvc-space-3);
    padding: var(--cvc-space-2) var(--cvc-space-3);
    border-radius: var(--cvc-radius);
    background: rgba(245, 159, 0, .1);
    font-size: .8125rem;
}

/* ---------- version history ---------- */

.cvc-version {
    padding: var(--cvc-space-3) var(--cvc-space-4);
    border-bottom: 1px solid var(--cvc-border);
    font-size: .8125rem;
}

.cvc-version-head {
    display: flex;
    align-items: baseline;
    gap: var(--cvc-space-2);
    font-size: .875rem;
}

.cvc-version-meta {
    color: var(--cvc-text-muted);
    line-height: 1.5;
    margin-top: 2px;
}

.cvc-version-actions {
    display: flex;
    gap: var(--cvc-space-2);
    margin-top: var(--cvc-space-2);
}

/* ---------- recipients ---------- */

.cvc-chiplist {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cvc-space-2);
    padding: 0 var(--cvc-space-4) var(--cvc-space-3);
}

.cvc-panel-section {
    padding: 0 var(--cvc-space-4) var(--cvc-space-4);
    display: flex;
    flex-direction: column;
    gap: var(--cvc-space-2);
}

/* ---------- inspector ---------- */

.cvc-inspector-header {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--cvc-surface);
    border-bottom: 1px solid var(--cvc-border);
    padding: var(--cvc-space-3) var(--cvc-space-4);
    display: flex;
    align-items: center;
    gap: var(--cvc-space-2);
}

.cvc-inspector-header h4 {
    margin: 0;
    font-size: .9375rem;
}

.cvc-inspector-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: var(--cvc-space-4);
    min-height: 0;
}

/* Sticky footer with the grouped block operations; the body scrolls, the
   actions stay reachable. */
.cvc-inspector-footer {
    flex-shrink: 0;
    border-top: 1px solid var(--cvc-border);
    background: var(--cvc-surface);
    padding: var(--cvc-space-3) var(--cvc-space-4);
    display: flex;
    flex-direction: column;
    gap: var(--cvc-space-3);
}

.cvc-footer-group {
    display: flex;
    flex-direction: column;
    gap: var(--cvc-space-1);
}

.cvc-footer-label {
    font-size: .6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--cvc-text-muted);
}

.cvc-footer-actions {
    display: flex;
    gap: var(--cvc-space-2);
    flex-wrap: wrap;
}

.cvc-danger-zone {
    display: flex;
    flex-direction: column;
    gap: var(--cvc-space-1);
    padding-top: var(--cvc-space-3);
    border-top: 1px solid var(--cvc-border);
}

.cvc-danger-zone .cvc-footer-label {
    color: var(--cvc-danger);
}

.cvc-inspector-section {
    margin-top: var(--cvc-space-4);
    padding-top: var(--cvc-space-3);
    border-top: 1px solid var(--cvc-border);
}

.cvc-inspector-section-title {
    font-size: .6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--cvc-text-muted);
    margin-bottom: var(--cvc-space-2);
}

.cvc-field {
    margin-bottom: var(--cvc-space-3);
}

.cvc-field .form-label,
.cvc-field-row .form-label {
    margin-bottom: var(--cvc-space-1);
    font-size: .8125rem;
}

/* Inputs always take the full available width and can never overflow the
   panel; grids/rows below share it explicitly. */
.cvc-inspector-body input.form-control,
.cvc-inspector-body textarea.form-control,
.cvc-inspector-body select.form-select {
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
}

.cvc-inspector-body textarea.form-control {
    min-height: 88px;
    resize: vertical;
}

.cvc-field-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: var(--cvc-space-2) var(--cvc-space-3);
    margin-bottom: var(--cvc-space-3);
    align-items: end;
}

.cvc-field-row > * {
    min-width: 0;
}

/* Genuinely paired values (Von/Bis): two equal columns as long as they fit,
   stacked vertically in narrow panels. */
.cvc-field-row--dates {
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    align-items: start;
}

/* Rows ending in a compact action (language / list-item remove) keep the
   two value columns and give the action only the width it needs. */
.cvc-field-row:has(.cvc-row-action) {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
}

.cvc-row-action {
    align-self: center;
    justify-self: start;
}

.cvc-field-hint {
    font-size: .75rem;
    color: var(--cvc-text-muted);
    margin-top: var(--cvc-space-1);
}

.cvc-inspector-error {
    background: rgba(214, 57, 57, .08);
    color: var(--cvc-danger);
    border: 1px solid rgba(214, 57, 57, .25);
    border-radius: var(--cvc-radius);
    font-size: .8125rem;
    padding: var(--cvc-space-2) var(--cvc-space-3);
    margin: var(--cvc-space-2) 0;
}

/* ---------- inspector controls ---------- */

.cvc-entry-nav {
    display: inline-flex;
    align-items: center;
    gap: var(--cvc-space-1);
    font-size: .75rem;
    color: var(--cvc-text-muted);
    white-space: nowrap;
}

.cvc-entry-nav button {
    border: 1px solid var(--cvc-border);
    background: var(--cvc-surface);
    border-radius: 4px;
    width: 22px;
    height: 22px;
    line-height: 1;
    font-size: .875rem;
    cursor: pointer;
    color: inherit;
    padding: 0;
}

.cvc-entry-nav button:hover:not(:disabled) {
    background: var(--cvc-surface-muted);
}

.cvc-entry-nav button:disabled {
    opacity: .4;
    cursor: default;
}

.cvc-stepper {
    display: flex;
    align-items: center;
    gap: var(--cvc-space-1);
}

.cvc-stepper button {
    border: 1px solid var(--cvc-border);
    background: var(--cvc-surface);
    color: inherit;
    border-radius: 4px;
    width: 28px;
    height: 30px;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    flex-shrink: 0;
}

.cvc-stepper button:hover:not(:disabled) {
    background: var(--cvc-surface-muted);
}

.cvc-stepper button:disabled {
    opacity: .4;
    cursor: default;
}

.cvc-stepper input {
    width: 64px;
    min-width: 0;
    text-align: right;
    background: var(--cvc-surface);
    color: inherit;
    border: 1px solid var(--cvc-border);
    border-radius: 4px;
    height: 30px;
    padding: 0 var(--cvc-space-2);
    font-size: .875rem;
}

.cvc-stepper-unit {
    font-size: .8125rem;
    color: var(--cvc-text-muted);
}

.cvc-segmented {
    display: flex;
    border: 1px solid var(--cvc-border);
    border-radius: var(--cvc-radius);
    overflow: hidden;
}

.cvc-segmented button {
    flex: 1 1 0;
    min-width: 0;
    border: 0;
    background: none;
    font-size: .8125rem;
    padding: var(--cvc-space-2);
    cursor: pointer;
    color: var(--cvc-text-muted);
}

.cvc-segmented button + button {
    border-left: 1px solid var(--cvc-border);
}

.cvc-segmented button[aria-checked="true"] {
    background: var(--cvc-accent-soft);
    color: var(--cvc-accent-text);
    font-weight: 600;
}

.cvc-slider-row {
    margin-bottom: var(--cvc-space-2);
}

.cvc-slider-controls {
    display: flex;
    align-items: center;
    gap: var(--cvc-space-2);
}

.cvc-slider-controls input[type="range"] {
    flex: 1 1 auto;
    min-width: 0;
    accent-color: var(--cvc-accent);
}

.cvc-slider-value {
    font-size: .8125rem;
    color: var(--cvc-text-muted);
    min-width: 46px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.cvc-photo-preview {
    display: flex;
    justify-content: center;
    margin-bottom: var(--cvc-space-3);
}

.cvc-photo-preview img {
    width: 140px;
    height: 140px;
    object-fit: cover;
    border-radius: var(--cvc-radius);
    border: 1px solid var(--cvc-border);
    background: var(--cvc-surface-muted);
}

.cvc-photo-placeholder {
    width: 100%;
    border: 1px dashed var(--cvc-border);
    border-radius: var(--cvc-radius);
    background: var(--cvc-surface-muted);
    color: var(--cvc-text-muted);
    font-size: .8125rem;
    text-align: center;
    padding: var(--cvc-space-5) var(--cvc-space-3);
}

.cvc-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    overflow: hidden;
    white-space: nowrap;
}

.cvc-empty-state {
    padding: var(--cvc-space-6) var(--cvc-space-4);
    text-align: center;
    color: var(--cvc-text-muted);
}

.cvc-empty-state h5 {
    color: inherit;
    font-size: .9375rem;
    margin-bottom: var(--cvc-space-2);
}

.cvc-empty-state p {
    font-size: .8125rem;
    margin-bottom: var(--cvc-space-4);
}

.cvc-kbd-hints {
    display: inline-grid;
    grid-template-columns: auto auto;
    gap: var(--cvc-space-2) var(--cvc-space-3);
    font-size: .75rem;
    text-align: left;
}

.cvc-kbd-hints kbd {
    background: var(--cvc-surface-muted);
    border: 1px solid var(--cvc-border);
    border-radius: 4px;
    padding: 1px 6px;
    font-size: .6875rem;
    color: inherit;
    justify-self: end;
}

/* ---------- status bar ---------- */

.cvc-statusbar {
    display: flex;
    align-items: center;
    gap: var(--cvc-space-4);
    min-height: 36px;
    padding: 0 var(--cvc-space-3);
    border-top: 1px solid var(--cvc-border);
    background: var(--cvc-surface);
    font-size: .8125rem;
    color: var(--cvc-text-muted);
}

.cvc-zoom {
    display: flex;
    align-items: center;
    gap: 2px;
    margin-left: auto;
}

.cvc-zoom button {
    border: 1px solid transparent;
    background: none;
    border-radius: 4px;
    padding: 2px 8px;
    font-size: .8125rem;
    color: inherit;
    cursor: pointer;
    line-height: 1.4;
}

.cvc-zoom button:hover {
    background: var(--cvc-surface-muted);
    border-color: var(--cvc-border);
}

.cvc-zoom button[aria-pressed="true"] {
    background: var(--cvc-accent-soft);
    color: var(--cvc-accent-text);
    border-color: transparent;
}

/* ---------- message strip ---------- */

.cvc-message {
    display: flex;
    align-items: center;
    gap: var(--cvc-space-2);
    padding: var(--cvc-space-2) var(--cvc-space-3);
    font-size: .875rem;
    border-bottom: 1px solid var(--cvc-border);
}

.cvc-message.is-danger { background: rgba(214, 57, 57, .06); color: var(--cvc-danger); }
.cvc-message.is-success { background: rgba(47, 179, 68, .07); }
.cvc-message.is-info { background: var(--cvc-surface-muted); }
.cvc-message.is-warning { background: rgba(245, 159, 0, .08); }

.cvc-message .btn-close {
    margin-left: auto;
    font-size: .625rem;
}

/* ---------- action menu ---------- */

.cvc-menu-wrap {
    position: relative;
}

.cvc-menu {
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    z-index: 30;
    min-width: 200px;
    background: var(--cvc-surface);
    border: 1px solid var(--cvc-border);
    border-radius: var(--cvc-radius);
    box-shadow: var(--cvc-shadow-lg);
    padding: var(--cvc-space-1) 0;
}

.cvc-menu-item {
    display: block;
    width: 100%;
    text-align: left;
    border: 0;
    background: none;
    color: inherit;
    padding: var(--cvc-space-2) var(--cvc-space-4);
    font-size: .875rem;
    cursor: pointer;
}

.cvc-menu-item:hover:not(:disabled) {
    background: var(--cvc-surface-muted);
}

.cvc-menu-item:disabled {
    color: var(--cvc-text-muted);
    cursor: default;
}

.cvc-menu-item.is-danger {
    color: var(--cvc-danger);
}

.cvc-menu-divider {
    height: 1px;
    background: var(--cvc-border);
    margin: var(--cvc-space-1) 0;
}

/* ---------- skeleton ---------- */

.cvc-skeleton {
    background: linear-gradient(90deg, var(--cvc-skeleton-a) 25%, var(--cvc-skeleton-b) 50%, var(--cvc-skeleton-a) 75%);
    background-size: 200% 100%;
    animation: cvc-skeleton 1.4s infinite;
    border-radius: 4px;
}

@keyframes cvc-skeleton {
    from { background-position: 200% 0; }
    to { background-position: -200% 0; }
}

/* ---------- responsive ---------- */

@media (max-width: 1400px) {
    .cvc-shell {
        --cvc-sidebar-w: 250px;
        /* The inspector never shrinks below the width its controls need. */
        --cvc-inspector-w: 300px;
    }
}

@media (max-width: 1100px) {
    .cvc-sidebar,
    .cvc-inspector {
        position: absolute;
        top: 0;
        bottom: 0;
        z-index: 20;
        box-shadow: var(--cvc-shadow-drawer);
        display: none;
    }

    .cvc-sidebar { left: 0; }
    .cvc-inspector { right: 0; }

    .cvc-sidebar.is-open,
    .cvc-inspector.is-open {
        display: flex;
    }

    .cvc-workspace {
        position: relative;
    }
}

.cvc-toolbar .cvc-panel-toggle {
    display: none;
}

@media (max-width: 1100px) {
    .cvc-toolbar .cvc-panel-toggle {
        display: inline-flex;
    }
}

/*
 * Chrome for the section-based CV form editor (CvEditor and its panes).
 * Every colour derives from the application's theme tokens with light
 * fallbacks, so the editor follows light and dark mode with the rest of
 * the app; no surface is hardcoded white. The page scrolls normally: the
 * action bar and the section rail are sticky, the panes grow naturally
 * and never open a second scrollbar.
 */

.fe-root {
    --fe-border: var(--tblr-border-color, #dadfe5);
    --fe-surface: var(--tblr-bg-surface, #fff);
    --fe-surface-muted: var(--pz-subtle-bg, #f6f8fa);
    --fe-text-muted: var(--tblr-secondary, #706964);
    --fe-accent: var(--tblr-primary, #e66f51);
    --fe-accent-rgb: var(--tblr-primary-rgb, 230, 111, 81);
    --fe-accent-text: var(--tblr-primary-text-emphasis, #c35439);
    --fe-danger: var(--tblr-danger, #d63939);
    --fe-radius: 6px;
    --fe-shadow: 0 1px 3px rgba(30, 40, 60, .06);
}

/* ---------- sticky action bar ---------- */

.fe-topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 8px 16px;
    padding: 10px 16px 12px;
    margin-bottom: 12px;
    background: var(--tblr-bg-surface, #fff);
    border: 1px solid var(--fe-border);
    border-radius: var(--fe-radius);
    box-shadow: var(--fe-shadow);
}

.fe-topbar-name {
    flex: 1 1 240px;
    max-width: 360px;
    min-width: 0;
}

.fe-topbar-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

/* The composer's SaveIndicator is reused here, but its cvc-* styles live
   scoped under .cvc-shell in editor.css; this restyles it for the form
   editor with the same semantics. */
.fe-topbar .cvc-save-indicator {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .8125rem;
    color: var(--fe-text-muted);
    white-space: nowrap;
}

.fe-topbar .cvc-save-indicator .cvc-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--fe-text-muted);
    flex-shrink: 0;
}

.fe-topbar .cvc-save-indicator.is-dirty .cvc-dot { background: var(--tblr-warning, #f59f00); }
.fe-topbar .cvc-save-indicator.is-saving .cvc-dot { background: var(--fe-accent); }
.fe-topbar .cvc-save-indicator.is-saved .cvc-dot { background: var(--tblr-success, #2fb344); }
.fe-topbar .cvc-save-indicator.is-failed { color: var(--fe-danger); }
.fe-topbar .cvc-save-indicator.is-failed .cvc-dot { background: var(--fe-danger); }

.fe-message {
    margin-bottom: 12px;
}

/* ---------- two-pane shell ---------- */

.fe-shell {
    display: flex;
    align-items: flex-start;
    gap: 16px;
}

.fe-nav-pane {
    /* Sticks below the action bar; the offset is measured by CvEditor
       because the bar wraps to different heights. */
    position: sticky;
    top: var(--fe-nav-top, 84px);
    flex: 0 0 260px;
    padding: 8px;
    background: var(--tblr-bg-surface, #fff);
    border: 1px solid var(--fe-border);
    border-radius: var(--fe-radius);
}

.fe-nav-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.fe-nav-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: var(--fe-radius);
    background: transparent;
    /* Buttons do not inherit color by default. */
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.fe-nav-item:hover {
    background: var(--fe-surface-muted);
}

.fe-nav-item.is-active {
    background: rgba(var(--fe-accent-rgb), .1);
    color: var(--fe-accent-text);
    font-weight: 600;
}

.fe-nav-item:focus-visible {
    outline: 2px solid var(--fe-accent);
    outline-offset: 1px;
}

.fe-nav-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fe-count {
    flex-shrink: 0;
    font-size: .75rem;
    line-height: 1.4;
    padding: 1px 7px;
    border-radius: 999px;
    border: 1px solid var(--fe-border);
    background: var(--fe-surface-muted);
    color: var(--fe-text-muted);
}

.fe-issue-dot {
    flex-shrink: 0;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--tblr-warning, #f59f00);
}

.fe-detail {
    flex: 1 1 auto;
    min-width: 0;
}

/* The list becomes a select above the form on narrow viewports. */
.fe-nav-select {
    display: none;
    margin-bottom: 12px;
}

/* ---------- section cards and grouped blocks ---------- */

.fe-section-card {
    margin-bottom: 0;
}

.fe-heading-row {
    max-width: 420px;
    margin-bottom: 16px;
}

.fe-block {
    min-inline-size: 0;
    margin: 0 0 16px;
    padding: 12px 16px 16px;
    border: 1px solid var(--fe-border);
    border-radius: var(--fe-radius);
}

.fe-block:last-child {
    margin-bottom: 0;
}

.fe-block-title {
    float: none;
    width: auto;
    margin: 0 0 8px;
    padding: 0;
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--fe-text-muted);
}

.fe-field-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 12px 16px;
}

/* ---------- master-detail inside a section pane ---------- */

.fe-master-detail {
    display: grid;
    grid-template-columns: minmax(200px, 260px) minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

.fe-item-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.fe-item {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--fe-border);
    border-radius: var(--fe-radius);
    background: transparent;
    /* Buttons do not inherit color by default. */
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.fe-item:hover {
    background: var(--fe-surface-muted);
}

.fe-item.is-selected {
    border-color: var(--fe-accent);
    background: rgba(var(--fe-accent-rgb), .08);
}

.fe-item:focus-visible {
    outline: 2px solid var(--fe-accent);
    outline-offset: 1px;
}

.fe-item-title {
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fe-item-sub {
    font-size: .75rem;
    color: var(--fe-text-muted);
}

.fe-add-btn {
    padding: 8px 10px;
    border: 1px dashed var(--fe-border);
    border-radius: var(--fe-radius);
    background: transparent;
    color: var(--fe-text-muted);
    font: inherit;
    text-align: center;
    cursor: pointer;
}

.fe-add-btn:hover {
    border-color: var(--fe-accent);
    color: var(--fe-accent-text);
}

.fe-add-btn:focus-visible {
    outline: 2px solid var(--fe-accent);
    outline-offset: 1px;
}

.fe-detail-pane {
    min-width: 0;
}

.fe-item-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 8px;
    margin-bottom: 12px;
}

.fe-dates {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px 16px;
    margin-bottom: 12px;
}

.fe-field {
    margin-bottom: 12px;
}

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

.fe-item-row {
    display: grid;
    grid-template-columns: minmax(120px, 2fr) minmax(160px, 3fr) auto;
    gap: 8px;
    align-items: start;
    margin-bottom: 8px;
}

.fe-muted {
    margin: 0 0 8px;
    color: var(--fe-text-muted);
}

/* ---------- empty state ---------- */

.fe-empty {
    padding: 24px 12px;
    border: 1px dashed var(--fe-border);
    border-radius: var(--fe-radius);
    text-align: center;
    color: var(--fe-text-muted);
}

.fe-empty p {
    margin: 0 0 12px;
}

/* ---------- versions ---------- */

.fe-versions {
    margin-top: 16px;
}

/* ---------- narrow viewports: stacked layout ---------- */

@media (max-width: 900px) {
    .fe-shell {
        display: block;
    }

    .fe-nav-pane {
        display: none;
    }

    .fe-nav-select {
        display: block;
    }

    .fe-master-detail {
        grid-template-columns: 1fr;
    }

    .fe-dates {
        grid-template-columns: 1fr;
    }

    .fe-item-row {
        grid-template-columns: 1fr;
    }
}

