/* ==========================================================================
   Performance Management System - Main Stylesheet
   Design system: RT Brand colors in Notion Calendar structure
   ========================================================================== */

:root {
    /* Primary palette - RT Brand */
    --color-primary: #213F99;
    --color-primary-hover: #1a3380;
    --color-primary-active: #14296b;
    --color-accent: #F5821F;
    --color-accent-hover: #e0741a;
    --color-dark-surface: #27187E;
    --color-link: #213F99;
    --color-link-hover: #1a3380;

    /* Focus */
    --color-focus-ring: rgba(33, 63, 153, 0.35);

    /* Text */
    --color-text-primary: #4D555A;
    --color-text-secondary: #615d59;
    /* Lifted from #767270 (4.76:1 on white, 4.37:1 on --color-surface-secondary)
       so muted text clears WCAG AA at the 10-13px sizes it is actually used at.
       Now 5.60:1 / 5.14:1. Reported on six screens before being fixed here. */
    --color-text-muted: #6b6764;
    --color-text-inverse: #ffffff;

    /* Surfaces - Notion Calendar neutrals */
    --color-background: #F7F7FF;
    --color-surface: #ffffff;
    --color-surface-secondary: #f6f5f4;
    --color-surface-muted: #f0efed;
    --color-border: #dfdcd9;
    --color-border-strong: #c4c0bb;

    /* Semantic */
    --color-success: #0d7c3f;
    --color-success-bg: #f0fdf4;
    --color-success-border: #bbf7d0;
    --color-error: #dc2626;
    --color-error-bg: #fef2f2;
    --color-error-border: #fecaca;
    --color-error-text: #991b1b;
    --color-warning: #d97706;
    --color-warning-bg: #fffbeb;
    --color-warning-border: #fde68a;
    --color-warning-text: #C25E12;

    /* Secondary accent (indigo) — anchored to brand #27187E.
       Sanctions the purple family used by the rating form and
       increment approval screens; use these tokens, never literals. */
    --color-accent-2: #534AB7;
    --color-accent-2-strong: #27187E;
    --color-accent-2-soft: #7F77DD;
    --color-accent-2-bg: #F6F4FE;
    --color-accent-2-border: #DFDCF8;
    --color-accent-2-tint: #EEEDFE;

    --color-info: #185fa5;
    --color-info-bg: #eff6ff;
    --color-info-border: #bfdbfe;

    /* Rating band tokens — chip/tile colors for the five performance
       bands (Poor / Average / Good / Very Good / Excellent).
       Roles: -bg tile background, -border tile border, -text label,
       -text-strong emphasized value, -text-soft subtitle/pill. */
    --rating-poor-bg: #FCEBEB;
    --rating-poor-border: #F09595;
    --rating-poor-text: #A32D2D;
    --rating-poor-text-strong: #791F1F;
    --rating-poor-text-soft: #E24B4A;

    --rating-average-bg: #FAECE7;
    --rating-average-border: #F0997B;
    --rating-average-text: #993C1D;
    --rating-average-text-strong: #712B13;

    --rating-good-bg: #FAEEDA;
    --rating-good-border: #FAC775;
    --rating-good-text: #854F0B;
    --rating-good-text-strong: #633806;
    --rating-good-text-soft: #BA7517;

    --rating-very-good-bg: #E6F1FB;
    --rating-very-good-border: #85B7EB;
    --rating-very-good-text: #185FA5;
    --rating-very-good-text-strong: #0C447C;
    --rating-very-good-text-soft: #378ADD;

    --rating-excellent-bg: #EAF3DE;
    --rating-excellent-border: #97C459;
    --rating-excellent-text: #3B6D11;
    --rating-excellent-text-strong: #27500A;

    /* Criteria-section tints (rating form / appraisal panels).
       Technical = light blue (text reuses --rating-very-good-*),
       behavioural = teal. */
    --section-technical-bg: #F0F6FD;
    --section-technical-border: #C5DEFA;
    --section-technical-divider: #D6E6F9;

    --section-behavioural-bg: #EFF9F4;
    --section-behavioural-bg-strong: #E1F5EE;
    --section-behavioural-border: #C2EDDA;
    --section-behavioural-divider: #D2F0E2;
    --section-behavioural-accent: #0F6E56;
    --section-behavioural-text-strong: #085041;
    --section-behavioural-text-soft: #1D9E75;

    /* Branding panel (dark surface in both modes) */
    --color-text-branding-secondary: rgba(255, 255, 255, 0.7);
    --color-text-branding-muted: rgba(255, 255, 255, 0.65);
    --color-blur-primary: rgba(33, 63, 153, 0.25);
    --color-blur-accent: rgba(245, 130, 31, 0.15);

    /* Typography */
    --font-family: 'Inter', 'NotionInter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    /* Monospace — rt-design-system typography.fontFamily.mono. Self-hosted in
       fonts.css since 12-Sep-2026. Every monospace rule in the app reads this
       token; there were eight hand-written stacks before, six of which never
       named JetBrains Mono at all. */
    --font-family-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
    /* The app type scale. An APPROVED DEVIATION from rt-design-system: this
       app's primary surfaces are dense data tables, so the small end is one
       step tighter than the design system's. Recorded in AGENTS.md
       ("Typography conventions"). Use the token, never a literal. */
    --font-size-xs: 11px;
    --font-size-sm: 13px;
    --font-size-body: 14px;
    --font-size-md: 15px;
    /* 16px. Same value and same name as rt-design-system's `base`, on purpose:
       importing DS vocabulary used to produce var(--font-size-base), which was
       undefined here and silently did nothing. Also the touch-field size. */
    --font-size-base: 16px;
    --font-size-lg: 18px;
    --font-size-xl: 20px;
    --font-size-2xl: 24px;
    --font-size-3xl: 28px;
    /* 36px = rt-design-system text-4xl. The largest figure in the app. */
    --font-size-4xl: 36px;
    /* KPI figures. One alias so every KPI card across every screen moves
       together; they were 21px on two screens and 22px on nine. */
    --fs-kpi: var(--font-size-2xl);
    --font-weight-regular: 400;
    --font-weight-medium: 500;
    --font-weight-semibold: 600;
    /* 700 has a real Inter face as of 12-Sep-2026 (fonts.css). Before that,
       everything above 600 was synthesized. Do not add 650/550/800 back —
       there is no face for them and they collapse into this one. */
    --font-weight-bold: 700;
    /* Six steps, because three could not express the real usage: the app had
       22 distinct line-heights and forcing them into tight/normal/relaxed
       would have moved 60 declarations by up to 0.15, which crowds dense
       table rows and can clip descenders on large figures. This ladder maps
       every existing value with 0.05 drift or less, except six sites. */
    --line-height-none: 1;       /* single-line chrome, badges, big figures */
    --line-height-flat: 1.15;    /* hero numerals */
    --line-height-tight: 1.25;
    --line-height-snug: 1.35;
    --line-height-normal: 1.5;
    --line-height-relaxed: 1.6;

    /* Spacing - 4px base scale */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-8: 32px;
    --space-10: 40px;
    --space-12: 48px;
    --space-16: 64px;

    /* Border radius */
    --radius-sm: 4px;
    --radius-md: 8px;
    --radius-lg: 12px;
    --radius-full: 9999px;

    /* Shadows — cool-tinted, two-layer soft elevation (Gemini-style).
       Layer 1 = tight crisp edge; layer 2 = wider ambient lift.
       Color 16,24,40 (cool slate) reads as shade, not muddy grey, on the light wash. */
    --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 3px rgba(16, 24, 40, 0.06);
    --shadow-md: 0 2px 4px rgba(16, 24, 40, 0.04), 0 6px 16px rgba(16, 24, 40, 0.08);
    --shadow-lg: 0 4px 8px rgba(16, 24, 40, 0.05), 0 12px 32px rgba(16, 24, 40, 0.10);
    --shadow-focus: 0 0 0 3px var(--color-focus-ring);

    /* Score category verdict colors (single source of truth) */
    --cat-poor: #dc2626;
    --cat-average: #F5821F;
    --cat-good: #d97706;
    --cat-very-good: #213F99;
    --cat-excellent: #0d7c3f;

    /* Transitions */
    --transition-fast: 150ms ease;
    --transition-base: 200ms ease;
    --transition-slow: 300ms ease;

    /* Custom easing curves (Emil Kowalski) */
    --ease-out-strong: cubic-bezier(0.23, 1, 0.32, 1);
    --ease-in-out-strong: cubic-bezier(0.77, 0, 0.175, 1);
    --ease-out-ui: cubic-bezier(0.33, 1, 0.68, 1);

    /* Derived tokens */
    --color-primary-tint: rgba(33, 63, 153, 0.08);

    /* Strong heading color (indigo in light, soft indigo in dark) */
    --color-heading-strong: #27187E;

    /* Sidebar palette (light) — derived from the accent so the rail's
       temperature follows the user's choice. Low mix ratios keep it a
       tinted neutral, never a colored panel; text ratios stay dark enough
       for WCAG contrast on the tinted background. */
    --sidebar-bg: color-mix(in srgb, var(--color-primary) 5%, #f8f8fa);
    --sidebar-border: color-mix(in srgb, var(--color-primary) 13%, #e6e7ea);
    --sidebar-scrollbar: color-mix(in srgb, var(--color-primary) 18%, #d3d5da);
    --sidebar-hover: color-mix(in srgb, var(--color-primary) 9%, #f0f0f3);
    --sidebar-hover-strong: color-mix(in srgb, var(--color-primary) 15%, #e8e9ed);
    --sidebar-text: color-mix(in srgb, var(--color-primary) 30%, #22262d);
    --sidebar-text-secondary: color-mix(in srgb, var(--color-primary) 38%, #565c66);
    --sidebar-text-muted: color-mix(in srgb, var(--color-primary) 25%, #949aa5);
    /* Chart theme tokens — read by Chart.js configs so charts follow the theme. */
    --chart-grid: rgba(0, 0, 0, 0.06);
    --chart-axis: #6b7280;
    --chart-neutral: #a39e98;
}


/* ==========================================================================
   Base styles
   ========================================================================== */

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

html {
    font-size: 16px;
    /* Light only. "light dark" let an OS in dark mode repaint native
       controls: button text went white and checkboxes black on phones and
       Macs set to dark (responsive review item 4, 11-Sep-2026). */
    color-scheme: light;
    -webkit-text-size-adjust: 100%;
}

body {
    font-family: var(--font-family);
    font-size: var(--font-size-body);
    font-weight: var(--font-weight-regular);
    line-height: var(--line-height-normal);
    color: var(--color-text-primary);
    /* Full-page ambient gradient wash.
       Layer order: solid fallback color, then background image.
       - Plain PNG url() is the universal fallback (any browser understands it).
       - image-set() overrides for modern browsers to prefer the smaller WebP.
       - fixed + cover keeps the wash still while content scrolls; opaque
         sidebar and cards sit on top, so text legibility is unaffected. */
    background-color: var(--color-background);
    /* Accent-aware ambient wash (replaces the static PNG so the background
       follows the user's accent and theme). Style: soft edge glows with a
       near-white center — glow, never a full-strength gradient blob.
       Layers: accent bloom top-right, faint warm counter-glow bottom-left. */
    background-image:
        radial-gradient(120% 90% at 88% -8%,
            color-mix(in srgb, var(--accent-soft, #8ea4e8) 22%, transparent) 0%,
            color-mix(in srgb, var(--accent-soft, #8ea4e8) 8%, transparent) 38%,
            transparent 62%),
        radial-gradient(100% 75% at -8% 108%,
            color-mix(in srgb, var(--color-accent) 7%, transparent) 0%,
            transparent 50%);
    background-repeat: no-repeat;
    background-attachment: fixed;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Base link styling is wrapped in :where() so it carries ZERO specificity.
   A plain <a> still gets the link colour and the hover underline, but any
   component class (.btn, .pd-open, .au-btn--primary, .hod-page-btn.active,
   the .*-chip sets) now wins in every state, including :hover.
   Before this, a:hover (0,1,1) outranked a component's own colour (0,1,0),
   so a filled anchor was repainted in --color-link-hover on hover. Under RT
   that value is coral and the button fill is coral, so the label vanished. */
:where(a) {
    color: var(--color-link);
    text-decoration: none;
    transition: color var(--transition-fast);
}

:where(a:hover) {
    color: var(--color-link-hover);
    text-decoration: underline;
}


/* ==========================================================================
   Typography
   ========================================================================== */

h1, h2, h3, h4, h5, h6 {
    color: var(--color-text-primary);
    font-weight: var(--font-weight-semibold);
    line-height: var(--line-height-tight);
}

h1 { font-size: var(--font-size-3xl); }
h2 { font-size: var(--font-size-2xl); }
h3 { font-size: var(--font-size-xl); }
h4 { font-size: var(--font-size-lg); }

.text-muted { color: var(--color-text-muted); }
.text-secondary { color: var(--color-text-secondary); }
.text-primary-color { color: var(--color-primary); }
.text-accent { color: var(--color-accent); }


/* ==========================================================================
   Form inputs
   ========================================================================== */

.form-input,
input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="url"],
input[type="tel"],
input[type="search"],
select,
textarea {
    font-family: var(--font-family);
    font-size: var(--font-size-body);
    color: var(--color-text-primary);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: 13px 12px;
    transition: border-color 200ms ease-out, box-shadow 200ms ease-out;
    outline: none;
    width: 100%;
}

.form-input::placeholder,
input::placeholder,
textarea::placeholder {
    color: var(--color-text-muted);
}

.form-input:focus,
input:focus,
select:focus,
textarea:focus {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-focus);
}

.form-label,
label {
    display: block;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    margin-bottom: 6px;
}


/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    font-family: var(--font-family);
    font-size: var(--font-size-body);
    font-weight: var(--font-weight-semibold);
    line-height: var(--line-height-none);
    padding: 10px 20px;
    border-radius: var(--radius-sm);
    border: none;
    cursor: pointer;
    text-decoration: none;
    transition: background-color 200ms var(--ease-out-strong), transform 160ms var(--ease-out-strong);
    white-space: nowrap;
}

.btn:active {
    transform: scale(0.97);
}

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

.btn-primary {
    background-color: var(--color-primary);
    color: var(--color-text-inverse);
}

.btn-primary:hover {
    background-color: var(--color-primary-hover);
    color: var(--color-text-inverse);
    text-decoration: none;
}

.btn-primary:active {
    background-color: var(--color-primary-active);
}

.btn-accent {
    background-color: var(--color-accent);
    color: var(--color-text-inverse);
}

.btn-accent:hover {
    background-color: var(--color-accent-hover);
    color: var(--color-text-inverse);
    text-decoration: none;
}

.btn-danger {
    background-color: var(--color-error);
    color: var(--color-text-inverse);
}

.btn-danger:hover {
    background-color: var(--color-error-text);
    color: var(--color-text-inverse);
    text-decoration: none;
}

.btn-success {
    background-color: var(--color-success);
    color: var(--color-text-inverse);
}

.btn-success:hover {
    filter: brightness(1.06);
    color: var(--color-text-inverse);
    text-decoration: none;
}

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

.btn-secondary:hover {
    background-color: var(--color-surface-secondary);
    text-decoration: none;
}

.btn-ghost {
    background-color: transparent;
    color: var(--color-text-primary);
}

.btn-ghost:hover {
    background-color: var(--color-surface-muted);
    text-decoration: none;
}

.btn-xs {
    font-size: var(--fs-11, 11px);
    padding: 4px 8px;
    gap: 4px;
}

.btn-sm {
    font-size: var(--font-size-sm);
    padding: 6px 12px;
}

.btn-lg {
    font-size: var(--font-size-md);
    padding: 12px 24px;
}

.btn-full {
    width: 100%;
}


/* ==========================================================================
   Cards
   ========================================================================== */

.card {
    background-color: var(--color-surface);
    border-radius: var(--radius-lg);
    padding: var(--space-8);
    box-shadow: var(--shadow-md);
}

.card-sm {
    padding: var(--space-6);
}

.card-bordered {
    box-shadow: none;
    border: 1px solid var(--color-border);
}


/* ==========================================================================
   Alerts
   ========================================================================== */

.alert {
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-normal);
}

.alert-error {
    background-color: var(--color-error-bg);
    color: var(--color-error-text);
    border: 1px solid var(--color-error-border);
}

.alert-success {
    background-color: var(--color-success-bg);
    color: var(--color-success);
    border: 1px solid var(--color-success-border);
}

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


/* ==========================================================================
   Layout utilities
   ========================================================================== */

.container {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 var(--space-6);
}

.container-sm { max-width: 640px; }
.container-md { max-width: 840px; }
.container-lg { max-width: 1024px; }

.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }
.gap-1 { gap: var(--space-1); }
.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.gap-4 { gap: var(--space-4); }
.gap-6 { gap: var(--space-6); }
.gap-8 { gap: var(--space-8); }

.hidden { display: none; }
.block { display: block; }

.text-center { text-align: center; }
.text-right { text-align: right; }

.mt-1 { margin-top: var(--space-1); }
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-6 { margin-top: var(--space-6); }
.mt-8 { margin-top: var(--space-8); }
.mb-1 { margin-bottom: var(--space-1); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-6 { margin-bottom: var(--space-6); }
.mb-8 { margin-bottom: var(--space-8); }

.p-2 { padding: var(--space-2); }
.p-3 { padding: var(--space-3); }
.p-4 { padding: var(--space-4); }
.p-6 { padding: var(--space-6); }
.p-8 { padding: var(--space-8); }


/* ==========================================================================
   Sidebar Navigation
   ========================================================================== */

.app-layout {
    display: flex;
    min-height: 100vh;
}

.sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 240px;
    background-color: var(--sidebar-bg);
    border-right: 1px solid var(--sidebar-border);
    display: flex;
    flex-direction: column;
    z-index: 100;
    /* overflow stays visible so the edge-floating collapse toggle can sit
       half outside the rail; vertical scrolling lives on .sidebar-nav */
    transition: width 200ms var(--ease-out-strong);
}

.sidebar-nav::-webkit-scrollbar {
    width: 4px;
}

.sidebar-nav::-webkit-scrollbar-track {
    background: transparent;
}

.sidebar-nav::-webkit-scrollbar-thumb {
    background-color: var(--sidebar-scrollbar);
    border-radius: var(--radius-full);
}

/* Collapsed state */
.sidebar.collapsed {
    width: 60px;
}

.sidebar.collapsed .sidebar-brand,
.sidebar.collapsed .sidebar-user-info,
.sidebar.collapsed .nav-item span,
.sidebar.collapsed .nav-item--logout span {
    opacity: 0;
    width: 0;
    overflow: hidden;
    white-space: nowrap;
    pointer-events: none;
    transition: opacity 150ms var(--ease-out-strong);
}

.sidebar.collapsed .nav-section-label {
    opacity: 0;
    height: 0;
    padding: 0;
    margin: 0;
    overflow: hidden;
    pointer-events: none;
    transition: opacity 150ms var(--ease-out-strong),
                height 200ms var(--ease-out-strong),
                padding 200ms var(--ease-out-strong);
}

.sidebar.collapsed .sidebar-header {
    justify-content: center;
    padding: 0;
    height: 56px;              /* identical to expanded — no vertical jump */
    align-items: center;
}

.sidebar.collapsed .sidebar-nav {
    align-items: center;
}

.sidebar.collapsed .nav-item {
    justify-content: center;
    padding: 8px;
    width: 40px;
}

.sidebar.collapsed .sidebar-footer {
    align-items: center;
}

.sidebar.collapsed .sidebar-user {
    justify-content: center;
    padding: var(--space-2);
}

.sidebar.collapsed .nav-item--button {
    justify-content: center;
    padding: 8px;
    width: 40px;
}

/* Collapse toggle button */
.sidebar-collapse-btn {
    position: absolute;
    top: 15px;                 /* vertically centered in the 56px header row */
    right: -13px;              /* straddles the sidebar border — same spot in
                                  expanded and collapsed states */
    width: 26px;
    height: 26px;
    border-radius: var(--radius-full);
    background: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    box-shadow: var(--shadow-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 110;
    opacity: 1;
    transition: background-color 200ms var(--ease-out-strong),
                border-color 200ms var(--ease-out-strong),
                transform 160ms var(--ease-out-strong);
}

.sidebar-collapse-btn svg {
    width: 14px;
    height: 14px;
    color: var(--color-text-secondary);
    transition: transform 200ms var(--ease-out-strong), color 200ms var(--ease-out-strong);
}

/* Collapsed: same position — only the chevron direction flips. */

.sidebar.collapsed .sidebar-collapse-btn svg {
    transform: rotate(180deg);
}

@media (hover: hover) and (pointer: fine) {
    .sidebar:hover .sidebar-collapse-btn {
        opacity: 1;
    }

    .sidebar-collapse-btn:hover {
        background-color: var(--color-surface-secondary);
        border-color: var(--color-primary);
    }
    .sidebar-collapse-btn:hover svg {
        color: var(--color-primary);
    }
}

.sidebar-collapse-btn:active {
    transform: scale(0.92);
}

/* JS-powered tooltip — rendered outside sidebar overflow */
/* Tooltip uses inverted surface: always dark bg + white text in light mode,
   always light bg + dark text in dark mode */
.sidebar-tooltip {
    position: fixed;
    background: #2b2b2b;
    color: #ffffff;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    padding: 4px 8px;
    border-radius: var(--radius-sm);
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 125ms var(--ease-out-strong);
    z-index: 300;
}

.sidebar-tooltip.visible {
    opacity: 1;
}

.sidebar-header {
    padding: 0 var(--space-2);
    padding-left: 10px;
    border-bottom: 1px solid var(--sidebar-border);
    display: flex;
    align-items: center;
    gap: var(--space-3);
    height: 56px;
    box-sizing: border-box;
}

.sidebar-logo {
    width: 28px;
    height: 28px;
    background: var(--color-primary);
    border-radius: var(--radius-md);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.sidebar-logo svg {
    width: 16px;
    height: 16px;
    color: var(--color-text-inverse);
}

.sidebar-brand {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--sidebar-text);
    line-height: var(--line-height-tight);
}

.sidebar-nav {
    flex: 1;
    padding: var(--space-3) var(--space-2);
    display: flex;
    flex-direction: column;
    gap: 2px;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: thin;
    scrollbar-color: var(--sidebar-scrollbar) transparent;
}

.nav-section-label {
    font-size: var(--font-size-sm);
    font-weight: 700;
    color: var(--sidebar-text-secondary);
    text-transform: none;
    letter-spacing: 0.03em;
    padding: var(--space-4) var(--space-3) var(--space-2);
    transition: opacity 150ms var(--ease-out-strong),
                height 200ms var(--ease-out-strong),
                padding 200ms var(--ease-out-strong);
}

.nav-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: 8px var(--space-3);
    border-radius: var(--radius-sm);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-regular);
    text-decoration: none;
    cursor: pointer;
    transition: background-color 200ms var(--ease-out-strong),
                color 200ms var(--ease-out-strong);
    position: relative;
    user-select: none;
}

.nav-item svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    color: var(--sidebar-text-muted);
    opacity: 1;
    transition: opacity 200ms var(--ease-out-strong);
}

/* Hover — gated behind pointer:fine to avoid false positives on touch */
@media (hover: hover) and (pointer: fine) {
    .nav-item:hover {
        background-color: var(--sidebar-hover);
        color: var(--sidebar-text);
    }

    .nav-item:hover svg {
        color: var(--color-primary);
        opacity: 1;
    }
}

.nav-item:active {
    transform: scale(0.97);
    transition: background-color 200ms var(--ease-out-strong),
                color 200ms var(--ease-out-strong),
                transform 120ms var(--ease-out-strong);
}

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

.nav-item.active {
    background-color: var(--color-primary);
    color: #ffffff;
    font-weight: var(--font-weight-medium);
}

.nav-item.active svg {
    opacity: 1;
    color: #ffffff;
}

/* Active indicator bar — left edge (hidden; using solid fill active state instead) */
.nav-item::before {
    content: '';
    position: absolute;
    left: 0;
    top: 6px;
    bottom: 6px;
    width: 3px;
    border-radius: 0 var(--radius-full) var(--radius-full) 0;
    background-color: var(--color-primary);
    opacity: 0;
    transition: opacity 200ms var(--ease-out-strong);
}

.nav-item.active::before {
    opacity: 0;
}

.sidebar-footer {
    padding: var(--space-3) var(--space-2);
    border-top: 1px solid var(--sidebar-border);
    margin-top: auto;
}

.sidebar-user {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    margin-bottom: 2px;
}

.sidebar-avatar {
    width: 28px;
    height: 28px;
    border-radius: var(--radius-full);
    background-color: var(--color-primary);
    color: var(--color-text-inverse);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    flex-shrink: 0;
}

.sidebar-user-info {
    overflow: hidden;
}

.sidebar-user-name {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--sidebar-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-user-email {
    font-size: var(--font-size-xs);
    color: var(--sidebar-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nav-item--logout {
    color: var(--sidebar-text-muted);
}

@media (hover: hover) and (pointer: fine) {
    .nav-item--logout:hover {
        background-color: var(--color-error-bg);
        color: var(--color-error);
    }

    .nav-item--logout:hover svg {
        opacity: 1;
        color: var(--color-error);
    }
}

/* Main content area pushed right by sidebar width */
.main-content {
    flex: 1;
    margin-left: 240px;
    /* Own the vertical scroll here (not the document) so the sticky
       .content-header pins against a container that actually scrolls.
       overflow-x:hidden alone silently makes overflow-y computed:auto,
       creating a phantom, non-scrolling box that broke the sticky
       header — a real height + overflow-y:auto makes that box scroll. */
    height: 100vh;
    min-width: 0;
    overflow-x: hidden;
    overflow-y: auto;
    transition: margin-left 200ms var(--ease-out-strong);
}

.sidebar.collapsed ~ .main-content {
    margin-left: 60px;
}

/* ═══════════════════════════════════════════════════════════════════
   STANDARD APP HEADER (2026-07-13, flattened 2026-08-17)
   One canonical header for every screen: a flat surface with a hairline
   bottom border, a foreground-coloured title, plain bordered controls and a
   shared action slot. Screens fill the action slot via the header_actions
   block using the .ch-* classes below.

   This was a deep-purple to RT-blue gradient bar with a white title and
   glass buttons, its second stop driven by the user's saved secondary
   colour. RT is flat-surface and single-accent, so with the colour picker
   removed there was nothing left to drive the ramp and nothing the gradient
   was still expressing. rt-dashboard.css declares the same three properties
   under body[data-ds="rt"]; that override is kept because the RT probes
   assert it, and this base now agrees with it rather than fighting it.
   ═══════════════════════════════════════════════════════════════════ */
.content-header {
    padding: 0 var(--space-8);
    /* min-height, not height: a long title or a second row of controls
       must grow the bar, never spill over the content under it. */
    min-height: 56px;
    box-sizing: border-box;
    background: var(--color-background);
    border-bottom: 1px solid var(--color-border);
    box-shadow: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    position: sticky;
    top: 0;
    z-index: 50;
}

/* Title block: title on top, optional subtitle beneath. Both were inverse
   (white) for the gradient bar; on a flat surface they take foreground text. */
.content-header-title {
    /* ONE page-title ladder, 12-Sep-2026 (typography audit P1-4). Desktop 24 /
       tablet 20 / phone 18, all three on the design-system scale (2xl / xl /
       lg). Was 22px -- a size on neither scale -- with five page-level
       overrides at five different breakpoints (560/600/767/900), which made
       the same title read 17, 18, 19, 20 or 22px depending on the page. The
       tablet and phone steps live in the two media queries near the end of
       this file; do NOT re-add a per-page override. */
    font-size: var(--font-size-2xl);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
    line-height: var(--line-height-tight);
    min-width: 0;
}
.content-header-title .ch-sub {
    display: block;
    font-size: var(--fs-11, 11px);
    font-weight: var(--font-weight-regular);
    color: var(--color-text-muted);
    margin-top: 1px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Right cluster wraps the screen action slot + the global theme controls. */
.content-header > .content-header-right {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-shrink: 0;
}

/* Header controls: ordinary bordered buttons, not glass on a gradient. */
.content-header .theme-btn {
    color: var(--color-text-secondary);
    border-color: var(--color-border);
    background: transparent;
}
.content-header .theme-btn:hover {
    color: var(--color-text-primary);
    border-color: var(--color-border-strong);
    background: var(--color-surface-muted);
}

/* ── Shared header-action components (.ch-*) ─────────────────────────
   Used by every screen's [% block header_actions %]. Styled for the
   gradient background so cycle selectors and buttons look identical
   across screens. */
.ch-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
}

/* ── Header control base, flattened 2026-08-17 ──────────────────────────────
   .ch-cycle, .ch-btn and .ch-chip were all glass-on-gradient: translucent
   white fills, white text, white focus rings. On the flat header they were
   invisible, which is why every RT screen carried its own override and why
   .ch-chip in particular was missed on the executive screens for six days.
   The base below is now the flat treatment, so a new screen gets it for free
   and cannot forget. The per-screen body[data-ds="rt"] overrides in the
   rt-*.css files are left in place: they set the same values and their probes
   assert them. ─────────────────────────────────────────────────────────── */

/* Cycle selector (review-cycle dropdown) — replaces per-screen .hrv-cycle. */
.ch-cycle {
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: 500;
    padding: 7px 12px;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
    background: var(--color-background);
    color: var(--color-text-primary);
    cursor: pointer;
    transition: background var(--transition-fast), border-color var(--transition-fast);
}
.ch-cycle:hover { background: var(--color-surface-muted); border-color: var(--color-border-strong); }
.ch-cycle:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
/* Native option lists render on the OS surface, so keep them readable. */
.ch-cycle option { color: var(--color-text-primary); background: var(--color-surface); }

/* Header buttons (export / submit / back / edit). */
.ch-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 12px;
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
    background: var(--color-background);
    color: var(--color-text-primary);
    cursor: pointer;
    transition: background var(--transition-fast), border-color var(--transition-fast), opacity var(--transition-fast);
}
.ch-btn:hover { background: var(--color-surface-muted); border-color: var(--color-border-strong); color: var(--color-text-primary); }
.ch-btn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.ch-btn svg { width: 15px; height: 15px; }
/* Solid (primary action) variant — accent fill, inverse text. */
.ch-btn--solid {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-text-inverse);
}
.ch-btn--solid:hover { background: var(--color-primary-hover); border-color: var(--color-primary-hover); color: var(--color-text-inverse); }
/* Disabled / done state (e.g. "Submitted for HOD Approval"). */
.ch-btn:disabled, .ch-btn[disabled] { opacity: 0.65; cursor: default; }

/* Read-only context chip in the header (e.g. FY / cycle name) — a quiet
   bordered pill that does not compete with the action buttons. */
.ch-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 26px;
    padding: 0 10px;
    font-size: var(--fs-12, 12px);
    font-weight: 600;
    white-space: nowrap;
    border-radius: var(--radius-full);
    background: var(--color-surface-secondary);
    border: 1px solid var(--color-border);
    color: var(--color-text-secondary);
}
.ch-chip svg { width: 12px; height: 12px; opacity: 1; color: var(--color-text-muted); }

/* Content body — wraps [% block content %], provides consistent padding */
.content-body {
    /* Top 24px, 01-Oct-2026 spacing contract: the ONE place a screen's top
       margin is set. Was 20px, and page wrappers then added 0 / 16 / 32px on
       top, so content started 20, 36 or 52px below the header depending on
       the screen. Wrappers now add nothing at the top. */
    padding: var(--space-6) var(--space-8);
}

/* Logout button — replaces inline styles (item 7) */
.nav-item--button {
    width: 100%;
    border: none;
    background: none;
    font-family: inherit;
    font-size: inherit;
    text-align: left;
}

/* ═══════════════════════════════════════════════════════════════════
   DRAWER SHELL — phones and tablets (11-Sep-2026)
   One rule for every phone and every tablet in BOTH orientations:
     • any window 1024px wide or less, and
     • any touch screen up to 1366px (iPad Air/Pro landscape: 1180/1194/1366).
   A desktop with a mouse above 1024px keeps the fixed sidebar and its
   collapse toggle. The same query is used by base.html (drawerMq) — change
   them together. Breakpoints: docs/responsive_build_plan_v1.md.
   ═══════════════════════════════════════════════════════════════════ */
.mobile-header,
.sidebar-overlay {
    display: none;
}

@media (max-width: 1024px), (pointer: coarse) and (max-width: 1366px) {
    .sidebar-collapse-btn {
        display: none;         /* mobile uses the hamburger drawer instead */
    }

    .sidebar {
        transform: translateX(-100%);
        transition: transform 250ms var(--ease-out-strong);
        box-shadow: none;
    }

    .sidebar.open {
        transform: translateX(0);
        box-shadow: var(--shadow-lg);
    }

    .main-content {
        margin-left: 0;
    }

    .sidebar-overlay {
        display: block;
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.3);
        z-index: 99;
        opacity: 0;
        pointer-events: none;
        transition: opacity 250ms var(--ease-out-strong);
    }

    .sidebar-overlay.visible {
        opacity: 1;
        pointer-events: auto;
    }

    .mobile-header {
        display: flex;
        align-items: center;
        gap: var(--space-3);
        padding: var(--space-3) var(--space-4);
        background: var(--color-surface);
        border-bottom: 1px solid var(--color-border);
        position: sticky;
        top: 0;
        z-index: 51;   /* sits above the pinned content-header */
    }

    /* Only the hamburger bar stays pinned; it carries the page title.
       The page header scrolls away with the content. Pinning both took up
       to 306px (38%) of an 812px phone screen on Bell Curve. */
    body .content-header {
        position: relative;
        top: auto;
        z-index: 1;
        height: auto;
        flex-wrap: wrap;
        row-gap: var(--space-2);
        padding-top: var(--space-3);
        padding-bottom: var(--space-3);
    }
    body .content-header > .content-header-left {
        flex: 1 1 auto;
        min-width: 0;
    }
    .mobile-header-title {
        flex: 1 1 auto;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: var(--font-size-md);
        font-weight: var(--font-weight-semibold);
        color: var(--color-text-primary);
    }

    .hamburger-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 36px;
        height: 36px;
        border: none;
        background: none;
        cursor: pointer;
        color: var(--color-text-primary);
        border-radius: var(--radius-sm);
        transition: background-color 200ms var(--ease-out-strong);
    }

    .hamburger-btn:hover {
        background-color: var(--color-surface-secondary);
    }

    .hamburger-btn svg {
        width: 20px;
        height: 20px;
    }
}



/* ==========================================================================
   Responsive utilities
   ========================================================================== */

@media (max-width: 840px) {
    .hide-mobile { display: none; }
}

@media (min-width: 841px) {
    .hide-desktop { display: none; }
}


/* Dark mode was removed 2026-08-17. Two @media (prefers-color-scheme: dark)
   blocks and every [data-theme="dark"] rule lived here and throughout this
   file; the RT design system is light-only, so there is no second legend for
   these tokens any more. */


/* ==========================================================================
   Reduced motion: keep opacity/color, remove movement
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        /* Kill movement animations (transform, position) */
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        scroll-behavior: auto !important;
    }

    /* Remove transform-based motion but preserve state-indication transitions */
    *,
    *::before,
    *::after {
        transition-property: opacity, color, background-color, border-color, box-shadow !important;
        transition-duration: 200ms !important;
        transition-timing-function: ease !important;
    }

    /* Ensure modals, dropdowns appear/disappear without sliding */
    .modal-box,
    .import-modal-box,
    .master-dropdown-menu {
        transform: none !important;
    }
}


/* ==========================================================================
   Settings page - Tile grid
   ========================================================================== */

.settings-page {
    /* No top padding: .content-body owns the top margin (spacing contract,
       01-Oct-2026). This 32px used to put the hubs 52px below the header. */
    padding: 0 0 var(--space-8);
    /* Raised from 1280px 2026-08-17, same reason as .master-page: at 1280 this
       centred inside a 1640px content body and left dead bands down each side.
       Used by BOTH hub screens (Settings and Reports) — there is no
       .reports-page class, which is easy to assume and wrong. */
    max-width: 1920px;
    margin: 0 auto;
}

.settings-subtitle {
    font-size: var(--font-size-body);
    color: var(--color-text-secondary);
    margin-bottom: var(--space-6);
}

.settings-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-5);
}

.settings-tile {
    display: flex;
    align-items: flex-start;
    gap: var(--space-4);
    padding: var(--space-5);
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    text-decoration: none;
    color: inherit;
    transition: border-color 200ms var(--ease-out-strong),
                box-shadow 200ms var(--ease-out-strong),
                transform 160ms var(--ease-out-strong);
    cursor: pointer;
}

.settings-tile:hover {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
    text-decoration: none;
    color: inherit;
}

.settings-tile:active {
    transform: translateY(0) scale(0.99);
}

.settings-tile:focus-visible {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: var(--shadow-focus);
}

.settings-tile-icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--color-primary-tint);
    border-radius: var(--radius-md);
    color: var(--color-primary);
}

.settings-tile-icon svg {
    width: 20px;
    height: 20px;
}

.settings-tile-content {
    flex: 1;
    min-width: 0;
}

.settings-tile-title {
    font-size: var(--font-size-body);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
    margin-bottom: var(--space-1);
    line-height: var(--line-height-tight);
}

.settings-tile-desc {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    line-height: var(--line-height-normal);
    margin: 0;
    min-height: 2.9em;
}

/* Responsive: 2 columns on medium screens */
@media (max-width: 960px) {
    .settings-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Responsive: 1 column on small screens */
@media (max-width: 600px) {
    .settings-page {
        padding: 0 0 var(--space-5);
    }

    .settings-grid {
        grid-template-columns: 1fr;
        gap: var(--space-3);
    }

    .settings-tile {
        padding: var(--space-4);
    }
}


/* ==========================================================================
   Master Screen - Shared styles for list/table master screens
   ========================================================================== */

.master-page {
    /* No top padding: .content-body owns the top margin (spacing contract,
       01-Oct-2026). Bottom 16px kept for the pagination footer. */
    padding: 0 0 var(--space-4);
    /* Raised from 1280px 2026-08-17. At 1280 the page centred inside a 1640px
       content body on a 1880px window and left a measured 180px dead band down
       each side while the table inside it scrolled horizontally. Matches the RT
       screen wrappers (.pd-wrap), fixed the same way on 2026-08-01.
       Horizontal padding stays 0: .content-body already supplies 24px 32px. */
    max-width: 1920px;
    margin: 0 auto;
}

/* Toolbar - filters left, actions right, on one row when they fit.
   01-Oct-2026: the row may wrap. Actions used to be flex-shrink:0, so with five
   or six buttons the FILTERS were squeezed into whatever width was left and
   stacked into a ragged column (TNA Report Master 144px tall at 1440). Now the
   whole actions group drops to its own line, right-aligned, and the filters
   keep one clean row. margin-bottom 24px = section gap (spacing contract). */
.master-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3) var(--space-4);
    margin-bottom: var(--space-6);
    padding: var(--space-3) var(--space-4);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
}

.master-toolbar-filters {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    /* auto basis = the filters' own one-row width, so the actions wrap
       before the filters do. */
    flex: 1 1 auto;
    min-width: 0;
}

.master-toolbar-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-shrink: 0;
    margin-left: auto;
}

/* A plain <select class="form-input"> on a toolbar takes its text width, not
   the 100% that .form-input gives a form field. The report cycle dropdown
   stretched across the row and pushed Division and Category onto a second
   line (filter row 98px -> 58px). Phase 2 D2, 01-Oct-2026. Phones keep the
   full-width stacked toolbar. */
@media (min-width: 841px) {
    .master-toolbar-filters > select.form-input {
        width: auto;
        flex: 0 0 auto;
    }
}

/* Search */
.master-search {
    position: relative;
    width: 240px;
    flex-shrink: 0;
}

.master-search-icon {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    width: 15px;
    height: 15px;
    color: var(--color-text-muted);
    pointer-events: none;
}

.master-search-input {
    padding-left: 32px !important;
    height: 34px;
    font-size: var(--font-size-sm);
    border-radius: var(--radius-md);
}

/* Filter selects (legacy single-select, keep for fallback) */
.master-filter-select {
    height: 34px;
    font-size: var(--font-size-sm);
    padding: 0 var(--space-3);
    min-width: 130px;
    max-width: 160px;
    cursor: pointer;
    border-radius: var(--radius-md);
}

/* Multi-select filter dropdown */
.ms-filter {
    position: relative;
    display: inline-block;
}

.ms-filter-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 34px;
    padding: 0 var(--space-3);
    font-family: var(--font-family);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-regular);
    color: var(--color-text-primary);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    cursor: pointer;
    white-space: nowrap;
    transition: border-color 150ms var(--ease-out-strong),
                background-color 150ms var(--ease-out-strong);
}

.ms-filter-btn:hover {
    border-color: var(--color-border-strong);
}

.ms-filter.open .ms-filter-btn {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 2px var(--color-focus-ring);
}

.ms-filter-btn .ms-chevron {
    width: 12px;
    height: 12px;
    color: var(--color-text-muted);
    transition: transform 150ms var(--ease-out-strong);
    flex-shrink: 0;
}

.ms-filter.open .ms-chevron {
    transform: rotate(180deg);
}

.ms-filter-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    font-size: var(--fs-10, 10px);
    font-weight: var(--font-weight-semibold);
    background: var(--color-primary);
    color: var(--color-text-inverse);
    border-radius: var(--radius-full);
    line-height: var(--line-height-none);
}

.ms-filter-menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    min-width: 180px;
    z-index: 200;
    padding: var(--space-1) 0;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px) scale(0.97);
    transform-origin: top left;
    transition: opacity 150ms var(--ease-out-strong),
                transform 150ms var(--ease-out-strong),
                visibility 150ms;
}

.ms-filter.open .ms-filter-menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0) scale(1);
}

.ms-filter-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 7px var(--space-3);
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
    cursor: pointer;
    transition: background-color 100ms var(--ease-out-strong);
    user-select: none;
}

.ms-filter-item:hover {
    background-color: var(--color-surface-secondary);
}

.ms-filter-item:active {
    background-color: var(--color-surface-muted);
}

/* Dynamic option list with nothing left under the other filters
   (core/facets.py). Not clickable, so it is not a .ms-filter-item. */
.ms-filter-empty {
    padding: 7px var(--space-3);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

.ms-filter-item input[type="checkbox"] {
    width: 14px;
    height: 14px;
    accent-color: var(--color-primary);
    cursor: pointer;
    flex-shrink: 0;
    margin: 0;
}

.ms-filter-divider {
    height: 1px;
    background: var(--color-border);
    margin: var(--space-1) 0;
}

.ms-filter-clear {
    display: block;
    width: 100%;
    padding: 6px var(--space-3);
    font-family: var(--font-family);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    background: none;
    border: none;
    cursor: pointer;
    text-align: left;
    transition: color 120ms var(--ease-out-strong);
}

.ms-filter-clear:hover {
    color: var(--color-primary);
}

/* Dropdown menu */
.master-dropdown {
    position: relative;
    display: inline-block;
}

.master-dropdown-menu {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    min-width: 180px;
    z-index: 200;
    padding: var(--space-1) 0;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px) scale(0.97);
    transform-origin: top right;
    transition: opacity 120ms var(--ease-out-strong),
                transform 120ms var(--ease-out-strong);
}

.master-dropdown.open .master-dropdown-menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0) scale(1);
    transition: opacity 150ms var(--ease-out-strong),
                transform 150ms var(--ease-out-strong);
}

.master-dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 8px var(--space-3);
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
    text-decoration: none;
    cursor: pointer;
    border: none;
    background: none;
    width: 100%;
    font-family: var(--font-family);
    transition: background-color 120ms var(--ease-out-strong);
}

.master-dropdown-item:hover {
    background-color: var(--color-surface-secondary);
    text-decoration: none;
    color: var(--color-text-primary);
}

.master-dropdown-item:focus-visible {
    outline: none;
    box-shadow: var(--shadow-focus) inset;
    background-color: var(--color-surface-secondary);
}

.master-dropdown-item:active {
    background-color: var(--color-surface-muted);
}

.master-dropdown-item svg {
    flex-shrink: 0;
    color: var(--color-text-muted);
}

/* Table info bar */
.master-table-info {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    margin-bottom: var(--space-3);
}

.master-table-count {
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
}

.master-table-filter-hint {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
}

/* Table wrapper */
.master-table-wrap {
    overflow-x: auto;
    /* RT 2026-08-17: the border defines the edge and elevation nearly vanishes.
       This previously read "Border removed — the soft shadow now defines the
       edge (floats on the wash)", which is the Notion Calendar reading. It left
       a flat bordered .master-toolbar directly above a table card floating on a
       two-layer shadow. --radius-lg resolves to 6px through the RT tokens. */
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    background: var(--color-background);
    box-shadow: none;
}

.master-table {
    width: 100%;
    min-width: max-content;
    border-collapse: collapse;
    font-size: var(--font-size-sm);
    table-layout: auto;
}

.master-table thead {
    position: sticky;
    top: 0;
    z-index: 2;
}

.master-table th {
    background: var(--color-surface-secondary);
    color: var(--color-text-secondary);
    font-weight: var(--font-weight-semibold);
    font-size: var(--fs-11, 11px);
    text-transform: none;
    letter-spacing: 0.05em;
    padding: 10px var(--space-4);
    text-align: left;
    border-bottom: 1px solid var(--color-border);
    white-space: nowrap;
}

/* Compact row (Phase 2 D1, 01-Oct-2026): 6px + a 40px floor. Was 10px, and the
   30px row icons then set every row at 51px. Rows are now 40-41px whatever the
   content, so a 1440x900 screen shows 15 TNA records instead of 12. Phones lay
   these cells out as cards and reset the height there. */
.master-table td {
    padding: 6px var(--space-4);
    height: 40px;
    border-bottom: 1px solid var(--color-border);
    vertical-align: middle;
    color: var(--color-text-primary);
}

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

.master-table tbody tr {
    transition: background-color 120ms var(--ease-out-strong);
}

@media (hover: hover) and (pointer: fine) {
    .master-table tbody tr:hover {
        background-color: color-mix(in srgb, var(--color-primary) 4%, transparent);
    }
}

.master-table-name {
    font-weight: var(--font-weight-medium);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.master-table-desc {
    color: var(--color-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.master-table-visible {
    overflow: hidden;
}

.master-table-actions-th {
    text-align: center;
}

.master-table-actions {
    text-align: center;
    white-space: nowrap;
}

/* Action buttons in table */
.master-action-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;    /* 30 -> 28 with the compact row (D1); touch floor stays 40 */
    height: 28px;
    border: none;
    background: none;
    border-radius: var(--radius-sm);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: background-color 120ms var(--ease-out-strong),
                color 120ms var(--ease-out-strong),
                transform 160ms var(--ease-out-strong);
}

@media (hover: hover) and (pointer: fine) {
    .master-action-btn:hover {
        background-color: var(--color-primary-tint);
        color: var(--color-primary);
    }

    .master-action-btn--danger:hover {
        background-color: var(--color-error-bg);
        color: var(--color-error);
    }
}

.master-action-btn:active {
    transform: scale(0.94);
}

/* Table row stagger fade-in (capped at 8 rows) */
@keyframes rowFadeIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

.master-table tbody tr.row-stagger {
    animation: rowFadeIn 250ms var(--ease-out-strong) both;
}
.master-table tbody tr.row-stagger:nth-child(1)  { animation-delay: 0ms; }
.master-table tbody tr.row-stagger:nth-child(2)  { animation-delay: 40ms; }
.master-table tbody tr.row-stagger:nth-child(3)  { animation-delay: 80ms; }
.master-table tbody tr.row-stagger:nth-child(4)  { animation-delay: 120ms; }
.master-table tbody tr.row-stagger:nth-child(5)  { animation-delay: 160ms; }
.master-table tbody tr.row-stagger:nth-child(6)  { animation-delay: 200ms; }
.master-table tbody tr.row-stagger:nth-child(7)  { animation-delay: 240ms; }
.master-table tbody tr.row-stagger:nth-child(8)  { animation-delay: 280ms; }
.master-table tbody tr.row-stagger:nth-child(n+9) { animation-delay: 280ms; }

/* Toggle status optimistic feedback */
.status-badge.is-toggling {
    opacity: 0.5;
    transition: opacity 100ms var(--ease-out-strong);
}

/* Rating color dot (bell curve table) */
.rating-color-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: var(--radius-full);
    margin-right: 6px;
    vertical-align: middle;
    flex-shrink: 0;
    transition: background-color 200ms var(--ease-out-strong);
}

/* Field code badge */
.field-code-badge {
    font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: var(--fs-11, 11px);
    background: var(--color-surface-muted);
    color: var(--color-text-secondary);
    padding: 3px 8px;
    border-radius: var(--radius-sm);
    white-space: nowrap;
    letter-spacing: -0.01em;
}

/* Field type badges - base */
.field-type-badge {
    display: inline-block;
    font-size: var(--fs-11, 11px);
    font-weight: var(--font-weight-medium);
    padding: 3px 10px;
    border-radius: var(--radius-full);
    white-space: nowrap;
    background: var(--color-primary-tint);
    color: var(--color-primary);
}

/* Per-type colors (light mode defaults, dark mode overrides below) */
.field-type--text        { background: rgba(33, 63, 153, 0.09);  color: #1a3380; }
.field-type--number      { background: rgba(13, 124, 63, 0.09);  color: #0d7c3f; }
.field-type--email       { background: color-mix(in srgb, var(--color-accent-2-strong) 9%, transparent); color: var(--color-accent-2-strong); }
.field-type--date        { background: rgba(219, 39, 119, 0.09); color: #9d174d; }
.field-type--textarea    { background: rgba(245, 130, 31, 0.09); color: #c2680c; }
.field-type--dropdown    { background: rgba(14, 116, 144, 0.09); color: #0e7490; }
.field-type--radio       { background: rgba(124, 58, 237, 0.09); color: #6d28d9; }
.field-type--checkbox    { background: var(--color-primary-tint); color: var(--color-primary); }
.field-type--file_upload { background: rgba(107, 114, 128, 0.09);color: #4b5563; }
.field-type--rating_scale{ background: rgba(217, 119, 6, 0.09);  color: #b45309; }
.field-type--percentage  { background: rgba(13, 148, 136, 0.09); color: #0d9488; }
.field-type--currency    { background: rgba(16, 185, 129, 0.09); color: #047857; }

/* Status badges */
.status-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: var(--fs-11, 11px);
    font-weight: var(--font-weight-semibold);
    padding: 3px 10px;
    border-radius: var(--radius-full);
    white-space: nowrap;
}

.status-badge--active {
    background: var(--color-success-bg);
    color: var(--color-success);
}

.status-badge--inactive {
    background: var(--color-error-bg);
    color: var(--color-error);
}

.status-badge--withdrawn {
    background: var(--color-accent-2-bg);
    color: var(--color-accent-2);
}

/* Generic semantic modifiers — use these for any new status pill
   instead of inventing a bespoke badge class. */
.status-badge--success {
    background: var(--color-success-bg);
    color: var(--color-success);
}

.status-badge--error {
    background: var(--color-error-bg);
    color: var(--color-error);
}

.status-badge--warning {
    background: var(--color-warning-bg);
    color: var(--color-warning);
}

.status-badge--info {
    background: var(--color-primary-tint);
    color: var(--color-primary);
}

.status-badge--accent2 {
    background: var(--color-accent-2-bg);
    color: var(--color-accent-2);
}

.status-badge--neutral {
    background: var(--color-surface-muted);
    color: var(--color-text-secondary);
}

/* Role pills */
.role-pill {
    display: inline-block;
    font-size: var(--fs-10, 10px);
    font-weight: var(--font-weight-medium);
    padding: 2px 7px;
    border-radius: var(--radius-full);
    background: var(--color-surface-muted);
    color: var(--color-text-secondary);
    white-space: nowrap;
    margin: 1px 2px 1px 0;
    line-height: var(--line-height-snug);
}

/* Pagination */
.master-pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    padding: var(--space-4) 0;
    flex-wrap: wrap;
}

.master-pagination-info {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}

/* Page-size selector */
.master-page-size {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-left: auto;
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
}
.master-page-size-label {
    white-space: nowrap;
}
.master-page-size select {
    appearance: none;
    -webkit-appearance: none;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: 4px 28px 4px 10px;
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
    cursor: pointer;
    min-width: 72px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%234D555A' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 8px center;
    transition: border-color 150ms var(--ease-out-strong);
}
.master-page-size select:hover {
    border-color: var(--color-primary);
}
.master-page-size select:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-focus-ring);
}

/* Pagination footer layout: prev/next centered, page-size right */
.master-pagination-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
}
.master-pagination-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-4) 0;
    flex-wrap: wrap;
    gap: var(--space-3);
}
.master-pagination-footer .master-pagination-nav {
    flex: 1;
    min-width: 0;
}
.master-pagination-footer .master-page-size {
    margin-left: 0;
    flex-shrink: 0;
}

/* Empty state - inside table */
.master-empty-cell {
    padding: 0 !important;
    border-bottom: none !important;
    /* .master-table--wide sets max-width:180px + overflow:hidden + nowrap on
       EVERY td, and this is a td. Without these three the empty message is
       clipped to 180px. See rt-masters.css section 3. */
    max-width: none;
    overflow: visible;
    white-space: normal;
}

.master-empty-state {
    text-align: center;
    padding: var(--space-12) var(--space-6);
}

.master-empty-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: var(--radius-lg);
    background: var(--color-surface-secondary);
    color: var(--color-text-muted);
    margin-bottom: var(--space-4);
}

.master-empty-title {
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
    margin: 0 0 var(--space-1);
}

.master-empty-desc {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    margin: 0;
}


/* ==========================================================================
   Modal
   ========================================================================== */

/* ---------------------------------------------------------------------------
   Modal - overlay, container, box
   --------------------------------------------------------------------------- */
.modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    z-index: 900;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-8) var(--space-4);
    opacity: 0;
    visibility: hidden;
    transition: opacity 120ms var(--ease-out-strong),
                visibility 120ms;
}

.modal-overlay.active {
    opacity: 1;
    visibility: visible;
    transition: opacity 200ms var(--ease-out-strong),
                visibility 200ms;
}

.modal-container {
    width: 100%;
    max-width: 640px;
    max-height: calc(100vh - 64px);
    display: flex;
    flex-direction: column;
}

.modal-box {
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - 64px);
    overflow: hidden;
    opacity: 0;
    transform: translateY(-8px) scale(0.98);
    transform-origin: center;
    will-change: transform, opacity;
    transition: opacity 120ms var(--ease-out-strong),
                transform 120ms var(--ease-out-strong);
}

.modal-box form {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
    overflow: hidden;
}

.modal-overlay.active .modal-box {
    opacity: 1;
    transform: translateY(0) scale(1);
    transition: opacity 200ms var(--ease-out-strong),
                transform 200ms var(--ease-out-strong);
}

/* ---------------------------------------------------------------------------
   Modal - header
   --------------------------------------------------------------------------- */
.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-5) var(--space-6);
    border-bottom: 1px solid var(--color-border);
    flex-shrink: 0;
}

.modal-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
    margin: 0;
}

.modal-close-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: none;
    background: none;
    border-radius: var(--radius-sm);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: background-color 150ms var(--ease-out-strong),
                color 150ms var(--ease-out-strong),
                transform 160ms var(--ease-out-strong);
}

.modal-close-btn:hover {
    background: var(--color-surface-secondary);
    color: var(--color-text-primary);
}

.modal-close-btn:active {
    transform: scale(0.92);
}

/* ---------------------------------------------------------------------------
   Modal - scrollable body
   --------------------------------------------------------------------------- */
.modal-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: var(--space-5) var(--space-6);
    overscroll-behavior: contain;
}

/* Subtle fade at scroll edges */
.modal-body {
    mask-image: linear-gradient(
        to bottom,
        transparent 0px,
        black 8px,
        black calc(100% - 8px),
        transparent 100%
    );
    -webkit-mask-image: linear-gradient(
        to bottom,
        transparent 0px,
        black 8px,
        black calc(100% - 8px),
        transparent 100%
    );
}

/* ---------------------------------------------------------------------------
   Modal - sections (fieldsets)
   --------------------------------------------------------------------------- */
.modal-section {
    border: none;
    margin: 0 0 var(--space-5) 0;
    padding: 0;
}

.modal-section:last-child {
    margin-bottom: 0;
}

.modal-section-label {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-muted);
    text-transform: none;
    letter-spacing: 0.06em;
    margin-bottom: var(--space-3);
    padding-bottom: var(--space-2);
    border-bottom: 1px solid var(--color-border);
}

/* ---------------------------------------------------------------------------
   Modal - form fields
   --------------------------------------------------------------------------- */
.modal-field {
    margin-bottom: var(--space-3);
}

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

.modal-field label {
    display: block;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-primary);
    margin-bottom: 5px;
}

/* Tighter inputs inside modal */
.modal-box input[type="text"],
.modal-box input[type="number"],
.modal-box textarea,
.modal-box select {
    padding: 9px 12px;
    font-size: var(--font-size-sm);
    border-radius: var(--radius-md);
}

.modal-box textarea {
    resize: vertical;
    min-height: 60px;
}

.required-mark {
    color: var(--color-error);
}

.field-error {
    font-size: var(--font-size-xs);
    color: var(--color-error);
    margin-top: 4px;
}

.field-code-preview {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    margin-top: 5px;
}

.field-code-preview code {
    font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    background: var(--color-surface-muted);
    padding: 1px 5px;
    border-radius: var(--radius-sm);
    color: var(--color-primary);
    font-size: var(--fs-11, 11px);
}

/* ---------------------------------------------------------------------------
   Modal - toggle switches (replace bare checkboxes)
   --------------------------------------------------------------------------- */
.modal-toggle-row {
    display: flex;
    align-items: center;
    gap: var(--space-6);
    padding: var(--space-3) 0;
}

.modal-toggle {
    display: inline-flex !important;
    align-items: center;
    gap: var(--space-2);
    cursor: pointer;
    font-weight: var(--font-weight-regular) !important;
    margin-bottom: 0 !important;
    user-select: none;
}

.modal-toggle input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.modal-toggle-track {
    position: relative;
    display: inline-block;
    width: 36px;
    height: 20px;
    background: var(--color-border-strong);
    border-radius: var(--radius-full);
    transition: background-color 200ms var(--ease-out-strong);
    flex-shrink: 0;
}

.modal-toggle input:checked + .modal-toggle-track {
    background: var(--color-primary);
}

.modal-toggle-thumb {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    background: white;
    border-radius: var(--radius-full);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
    transition: transform 200ms var(--ease-out-strong);
}

.modal-toggle input:checked + .modal-toggle-track .modal-toggle-thumb {
    transform: translateX(16px);
}

.modal-toggle input:focus-visible + .modal-toggle-track {
    box-shadow: 0 0 0 3px var(--color-focus-ring);
}

.modal-toggle-text {
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
}

/* ---------------------------------------------------------------------------
   Modal - Visible To grid
   --------------------------------------------------------------------------- */
.visible-to-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 2px var(--space-3);
    padding: var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface-secondary);
    max-height: 200px;
    overflow-y: auto;
}

.visible-to-option {
    display: flex !important;
    align-items: center;
    gap: 6px;
    font-size: var(--font-size-xs) !important;
    font-weight: var(--font-weight-regular) !important;
    cursor: pointer;
    padding: 5px 0;
    margin-bottom: 0 !important;
}

.visible-to-option input[type="checkbox"] {
    width: 14px;
    height: 14px;
    accent-color: var(--color-primary);
    cursor: pointer;
    flex-shrink: 0;
}

/* ---------------------------------------------------------------------------
   Modal - two-column grid
   --------------------------------------------------------------------------- */
.modal-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 var(--space-4);
}

.modal-field--full {
    grid-column: 1 / -1;
}

@media (max-width: 600px) {
    .modal-grid {
        grid-template-columns: 1fr;
    }
}

/* Field hint text */
.field-hint {
    font-size: var(--font-size-xs);
    color: var(--color-text-muted);
    margin-bottom: var(--space-2);
    line-height: var(--line-height-normal);
}

/* Mandatory badges in table */
.mandatory-badge {
    display: inline-block;
    font-size: var(--fs-11, 11px);
    font-weight: var(--font-weight-medium);
    padding: 3px 10px;
    border-radius: var(--radius-full);
    white-space: nowrap;
}

.mandatory-badge--yes {
    background: var(--color-primary-tint);
    color: var(--color-primary);
}

.mandatory-badge--no {
    background: var(--color-surface-muted);
    color: var(--color-text-muted);
}

/* Conditional logic badge in table */
.cond-logic-badge {
    display: inline-block;
    font-size: var(--fs-11, 11px);
    font-weight: var(--font-weight-medium);
    padding: 3px 10px;
    border-radius: var(--radius-full);
    white-space: nowrap;
    background: var(--color-surface-muted);
    color: var(--color-text-muted);
}

.cond-logic-badge--active {
    background: rgba(245, 130, 31, 0.1);
    color: var(--color-accent);
}

/* Conditional logic rule builder in modal */
.cond-logic-container {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.cond-rule-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    background: var(--color-surface-secondary);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

.cond-rule-label {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-muted);
    min-width: 36px;
    text-transform: none;
    letter-spacing: 0.03em;
}

.cond-rule-field,
.cond-rule-value {
    flex: 1;
    min-width: 0;
    padding: 6px 10px;
    font-size: var(--font-size-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text-primary);
}

.cond-rule-op {
    width: 120px;
    padding: 6px 10px;
    font-size: var(--font-size-sm);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text-primary);
}

.cond-rule-remove {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: none;
    background: none;
    border-radius: var(--radius-sm);
    color: var(--color-text-muted);
    cursor: pointer;
    flex-shrink: 0;
}

.cond-rule-remove:hover {
    background: var(--color-error-bg);
    color: var(--color-error);
}

/* Metadata cells in table */
.master-table-meta {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    white-space: nowrap;
}

.master-table-placeholder {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 120px;
}

/* Wide table horizontal scroll (Employee Master etc.) */
.master-table--wide {
    table-layout: auto;
    min-width: 1800px;
}

/* A table with no rows has nothing to lay out, so the 1800px floor above only
   pushes the empty state off the side of the scroll viewport — measured 1886px
   of content inside a 1280px window, which put "No employees yet" and the line
   telling a new user how to add their first record completely off-screen.
   Where :has() is unsupported this rule does not apply and the behaviour is
   unchanged, so it degrades rather than breaks. */
.master-table:has(.master-empty-cell) {
    min-width: 0;
    width: 100%;
    /* fixed is required, not cosmetic: with `auto` the table still cannot go
       below the min-content width of its header cells, so on a phone the empty
       message centred itself off-screen even with min-width dropped. */
    table-layout: fixed;
}

.master-table:has(.master-empty-cell) thead {
    display: none;
}

.master-table--wide th {
    padding: 10px 12px;
}
.master-table--wide td {
    padding: 6px 12px;   /* compact row, same as .master-table td (Phase 2 D1) */
}

.master-table--wide td {
    max-width: 180px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Scroll hint: subtle shadow on right edge when table overflows */
.master-table-wrap--scrollable {
    position: relative;
}
.master-table-wrap--scrollable::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 32px;
    background: linear-gradient(to right, transparent, rgba(0, 0, 0, 0.04));
    pointer-events: none;
    border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
    opacity: 1;
    transition: opacity 200ms ease-out;
}
.master-table-wrap--scrollable.scrolled-end::after {
    opacity: 0;
}

/* Modal footer bar.

   .modal-actions is the original name. .modal-footer was introduced later by
   four panel modals (Management Summary, Payroll Handover, Increments
   Dashboard) and was never defined anywhere, so those footers had NO padding
   and NO top border — the buttons sat flush against the modal edges. Both
   names now resolve to the same bar so neither can drift again.

   A screen may override display/justify-content/padding from its own
   stylesheet (loaded after this file); .dsh-panel-foot does exactly that. */
.modal-actions,
.modal-footer {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-6);
    border-top: 1px solid var(--color-border);
    background: var(--color-surface);
    flex-shrink: 0;
}


/* ==========================================================================
   Master screen responsive
   ========================================================================== */

@media (max-width: 1024px) {
    .master-toolbar {
        flex-wrap: wrap;
    }

    .master-toolbar-filters {
        flex-wrap: wrap;
        width: 100%;
    }

    .master-search {
        width: 200px;
    }
}

@media (max-width: 840px) {
    .master-page {
        padding: 0 0 var(--space-3);
    }

    .content-body {
        padding: var(--space-4) var(--space-4);
    }

    .content-header {
        padding: 0 var(--space-4);
    }

    .master-toolbar {
        flex-direction: column;
        align-items: stretch;
        gap: var(--space-3);
        padding: var(--space-3);
    }

    .master-toolbar-filters {
        flex-direction: column;
        gap: var(--space-2);
    }

    .master-search {
        width: 100%;
    }

    .master-filter-select {
        width: 100%;
        max-width: none;
    }

    .master-toolbar-actions {
        justify-content: flex-end;
    }

    .visible-to-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .master-table {
        table-layout: auto;
    }
}

@media (max-width: 600px) {
    .modal-overlay {
        padding: var(--space-3);
    }

    .modal-container {
        max-width: 100%;
        max-height: calc(100vh - 24px);
    }

    .visible-to-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* ============================================
   Score category badge (used in scorecard tables)
   ============================================ */
.score-cat-badge {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 4px;
    font-size: var(--font-size-xs);
    font-weight: 600;
    color: #fff;
    background: var(--color-text-muted);
}
.score-cat--poor { background: var(--cat-poor); }
.score-cat--average { background: var(--cat-average); }
.score-cat--good { background: var(--cat-good); }
.score-cat--very-good { background: var(--cat-very-good); }
.score-cat--excellent { background: var(--cat-excellent); }


/* The dark token legend that lived here was removed 2026-08-17 along with the
   toggle that activated it. The accent tokens it referred to are no longer set
   inline on <html> either: rt-dashboard.css fixes Hot Coral on body. */

/* ==========================================================================
   Header controls (top-right of content header)
   --------------------------------------------------------------------------
   .theme-controls / .theme-btn keep their names: the cluster used to hold the
   colour-mode toggle and the accent picker, both removed 2026-08-17, and the
   class is referenced by ~20 templates, rt-dashboard.css and the 40px
   tap-target probes. Only the notifications bell remains in it.
   ========================================================================== */
.theme-controls {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-left: auto;
    position: relative;
}

.theme-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    color: var(--color-text-secondary);
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast),
                border-color var(--transition-fast);
}

.theme-btn:hover {
    color: var(--color-text-primary);
    border-color: var(--color-border-strong);
    background: var(--color-surface-secondary);
}

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

.theme-btn svg { width: 16px; height: 16px; }

/* Sun/moon: show the icon for the theme you would switch TO */

.notif-popover {
    position: absolute;
    top: calc(100% + var(--space-2));
    right: 0;
    z-index: 60;
    display: none;
    padding: var(--space-3);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
}

.notif-popover.open { display: block; }


/* ==========================================================================
   Reports suite — RAG verdict chips (Excel-convention colors per RT spec)
   and print rules so browser print = clean PDF.
   ========================================================================== */
.rag-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 10px;
    border-radius: var(--radius-full);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
}
.rag-chip::before {
    content: '';
    width: 7px; height: 7px; border-radius: var(--radius-full);
    background: currentColor;
}
/* RAG chips, tokenised 2026-08-17. These were #E2EFDA / #FFF2CC / #FCE4D6 —
   the SPREADSHEET verdict palette, correct in an xlsx cell and wrong on screen.
   Third place the same leak turned up, after the two help screens. The green
   chip also measured 4.43:1, just under AA, which the -text tokens fix. */
.rag-green { background: var(--color-success-bg); color: var(--color-success-text); }
.rag-amber { background: var(--color-warning-bg); color: var(--color-warning-text); }
.rag-red   { background: var(--color-error-bg);   color: var(--color-error-text); }

/* Report meta header printed above tables */
.report-meta {
    display: flex; flex-wrap: wrap; gap: var(--space-4);
    padding: var(--space-3) var(--space-4);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    margin-bottom: var(--space-4);
    font-size: var(--font-size-sm);
}
.report-meta strong { color: var(--color-text-primary); }
.report-meta span { color: var(--color-text-secondary); }

@media print {
    .sidebar, .content-header, .master-toolbar, .mobile-header,
    .master-pagination-footer, .no-print { display: none !important; }
    .main-content { margin-left: 0 !important; }
    body { background: #fff !important; }
    .master-table-wrap { border: none; box-shadow: none; }
}

/* ============================================================
   Toast / feedback system (shared, injected by static/js/app.js)
   ============================================================ */
.toast-root {
    position: fixed;
    bottom: var(--space-6);
    right: var(--space-6);
    z-index: 1200; /* above modal overlays */
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    max-width: 380px;
    pointer-events: none;
}
.toast {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    background: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-left: 3px solid var(--color-primary);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: var(--space-3) var(--space-4);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-normal);
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 200ms var(--ease-out-strong), transform 200ms var(--ease-out-strong);
    pointer-events: auto;
}
.toast--visible { opacity: 1; transform: translateY(0); }
.toast--leaving { opacity: 0; transform: translateY(4px); }
.toast--success { border-left-color: var(--color-success); }
.toast--success .toast-icon { color: var(--color-success); }
.toast--error { border-left-color: var(--color-error); }
.toast--error .toast-icon { color: var(--color-error); }
.toast--warning { border-left-color: var(--color-warning); }
.toast--warning .toast-icon { color: var(--color-warning); }
.toast--info .toast-icon { color: var(--color-primary); }
.toast-icon { flex-shrink: 0; margin-top: 1px; display: inline-flex; }
.toast-message { flex: 1; }
.toast-close {
    flex-shrink: 0;
    background: none;
    border: none;
    padding: 8px;
    margin: -8px -10px -8px 0;
    cursor: pointer;
    color: var(--color-text-muted);
    border-radius: var(--radius-sm);
    display: inline-flex;
}
.toast-close:hover { color: var(--color-text); background: var(--color-surface-muted); }
.toast-close:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; }
@media (max-width: 640px) {
    .toast-root { left: var(--space-4); right: var(--space-4); bottom: var(--space-4); max-width: none; }
}

/* ============================================================
   Import modal (shared across master list pages) — moved from
   per-page extra_css blocks in Phase 2. Do not redefine per page.
   ============================================================ */
.import-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    z-index: 999;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    visibility: hidden;
    transition: opacity 150ms var(--ease-out-strong), visibility 150ms;
}
.import-modal-overlay.active {
    opacity: 1;
    visibility: visible;
    transition: opacity 200ms var(--ease-out-strong), visibility 200ms;
}
.import-modal-box {
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    width: 100%;
    max-width: 440px;
    box-shadow: var(--shadow-lg);
    opacity: 0;
    transform: translateY(-8px) scale(0.98);
    transition: opacity 150ms var(--ease-out-strong), transform 150ms var(--ease-out-strong);
}
.import-modal-overlay.active .import-modal-box {
    opacity: 1;
    transform: translateY(0) scale(1);
    transition: opacity 200ms var(--ease-out-strong), transform 200ms var(--ease-out-strong);
}
.import-modal-box h3 {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    margin: 0;
}
.import-file-input-wrap {
    border: 2px dashed var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-6) var(--space-4);
    text-align: center;
    transition: border-color 200ms var(--ease-out-strong), background 200ms var(--ease-out-strong);
    cursor: pointer;
}
.import-file-input-wrap:hover {
    border-color: var(--color-primary);
    background: var(--color-primary-tint);
}
.import-file-input-wrap input[type="file"] {
    display: block;
    margin: var(--space-2) auto 0;
    font-size: var(--font-size-sm);
    border: none;
    padding: 0;
    width: auto;
}
.import-file-input-wrap p {
    font-size: var(--font-size-sm);
    color: var(--color-text-muted);
    margin: 0 0 var(--space-2);
}
.import-spinner { display: none; align-items: center; gap: 6px; }
.htmx-request .import-spinner { display: inline-flex; }
.htmx-request #importBtnText { display: none; }
@keyframes pms-spin { to { transform: rotate(360deg); } }
.spinner-icon { animation: pms-spin 0.8s linear infinite; }
.import-error {
    background: var(--color-error-bg);
    color: var(--color-error-text);
    border: 1px solid var(--color-error-border);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
    font-size: var(--font-size-sm);
    margin-top: var(--space-3);
}
.import-file-input-wrap.uploading {
    border-color: var(--color-primary);
    background: var(--color-primary-tint);
    pointer-events: none;
    opacity: 0.7;
}

/* ============================================================
   Phase 3: loading states, screen-reader helper, info tokens
   ============================================================ */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Any htmx swap target dims while its request is in flight
   (class applied centrally by app.js — no per-template wiring). */
.pms-loading {
    opacity: 0.55;
    pointer-events: none;
    transition: opacity 150ms var(--ease-out-strong);
}

/* Sortable table headers */
th.sortable {
    cursor: pointer;
    user-select: none;
}
th.sortable:hover { color: var(--color-text-primary); }
th.sortable:focus-visible { outline: 2px solid var(--color-primary); outline-offset: -2px; }
th.sortable .sort-arrow {
    display: inline-block;
    width: 12px;
    margin-left: 2px;
    color: var(--color-primary);
    font-size: var(--fs-10, 10px);
}

/* ============================================================
   Tabs (shared component) — consolidates iap-div-tab, bcr-tab,
   rp-tab. Local class names may remain on elements as JS hooks,
   but visual styling lives here only.
   ============================================================ */
.pms-tabs {
    display: flex;
    gap: 0;
    border-bottom: 1px solid var(--color-border);
    overflow-x: auto;
    scrollbar-width: none;
}
.pms-tabs::-webkit-scrollbar { display: none; }
.pms-tab {
    padding: 10px 18px;
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    cursor: pointer;
    white-space: nowrap;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    text-decoration: none;
    transition: color 150ms var(--ease-out-strong),
                border-color 150ms var(--ease-out-strong),
                transform 100ms ease-out;
}
@media (hover: hover) {
    .pms-tab:hover { color: var(--color-text-primary); }
}
.pms-tab:active { transform: scale(0.97); }
.pms-tab:focus-visible { outline: 2px solid var(--color-primary); outline-offset: -2px; }
.pms-tab.active {
    color: var(--color-primary);
    border-bottom-color: var(--color-primary);
}
.pms-tab-count {
    font-variant-numeric: tabular-nums;
    font-weight: var(--font-weight-bold, 700);
    font-size: var(--font-size-xs);
    background: var(--color-surface-muted);
    color: var(--color-text-muted);
    padding: 1px 8px;
    border-radius: var(--radius-full);
}
.pms-tab.active .pms-tab-count {
    background: var(--color-primary-tint);
    color: var(--color-primary);
}

/* Skip link (WCAG 2.4.1) — visually hidden until focused */
/* Visually hidden, still announced.

   .sr-only was USED in four templates and DEFINED in none of them, so every
   caption and every screen-reader-only span rendered as visible body text —
   including the two table captions on the Management Summary, where it printed
   a stray centred line above each table. Found by screenshot; no structural
   check could see it.

   clip-path rather than the legacy clip rect: `clip` does nothing unless the
   element is absolutely positioned, and <caption> resists that. This technique
   works on a caption, a span and a legend alike, and leaves the text readable
   to assistive technology. */
.sr-only,
.visually-hidden {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
    border: 0 !important;
}
/* The one exception: a control that must reappear on keyboard focus. */
.sr-only-focusable:focus,
.sr-only-focusable:focus-visible {
    position: static !important;
    width: auto !important;
    height: auto !important;
    margin: 0 !important;
    overflow: visible !important;
    clip: auto !important;
    clip-path: none !important;
    white-space: normal !important;
}

.skip-link {
    position: absolute;
    left: -9999px;
    top: var(--space-2);
    z-index: 2000;
    background: var(--color-primary);
    color: var(--color-text-inverse);
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-md);
    font-size: var(--font-size-sm);
    text-decoration: none;
}
.skip-link:focus {
    left: var(--space-2);
    outline: 2px solid var(--color-text-inverse);
    outline-offset: 2px;
}

/* ============================================================
   Shared badge/pill families — deduplicated from per-template
   <style> blocks (Phase: round-2 consolidation). Interactive
   states are gated to label.rf-pill (the rating form); read-only
   span.rf-pill pills (detail panels) get no hover behavior.
   ============================================================ */
.rf-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 2px 7px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-full);
    font-size: var(--fs-10, 10px);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
    cursor: pointer;
    background: var(--color-surface);
    transition: border-color 150ms ease, color 150ms ease, background-color 150ms ease, transform 150ms ease;
    white-space: nowrap;
    user-select: none;
}

label.rf-pill:hover {
    border-color: var(--color-text-muted);
    color: var(--color-text-primary);
}

label.rf-pill:active {
    transform: scale(0.97);
}

label.rf-pill input[type="radio"] {
    display: none;
}

.rf-pill.selected-poor { background: var(--color-error); color: var(--color-text-inverse); border-color: var(--color-error); }

.rf-pill.selected-average { background: var(--color-accent); color: var(--color-text-inverse); border-color: var(--color-accent); }

.rf-pill.selected-good { background: var(--color-warning); color: var(--color-text-inverse); border-color: var(--color-warning); }

.rf-pill.selected-verygood { background: var(--color-primary); color: var(--color-text-inverse); border-color: var(--color-primary); }

.rf-pill.selected-excellent { background: var(--color-success); color: var(--color-text-inverse); border-color: var(--color-success); }

.rf-score-badge {
    display: inline-flex;
    padding: 2px 10px;
    border-radius: var(--radius-full);
    font-size: var(--fs-11, 11px);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-inverse);
}

.hr-lock-badge {
    font-size: var(--fs-9, 9px);
    padding: 2px 6px;
    border-radius: var(--radius-sm);
    background: var(--color-accent-2-bg);
    color: var(--color-accent-2-soft);
    font-weight: var(--font-weight-medium);
    display: inline-flex;
    align-items: center;
    gap: 3px;
    white-space: nowrap;
}

.hr-lock-badge svg { flex-shrink: 0; }

.sc-badge {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 12px;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    line-height: var(--line-height-normal);
}

.sc-badge--active {
    background: var(--color-success-bg);
    color: var(--color-success);
}

.sc-badge--inactive {
    background: var(--color-error-bg);
    color: var(--color-error);
}

.sc-badge--withdrawn {
    background: var(--color-warning-bg);
    color: var(--color-warning);
}

.rating-badge {
    display: inline-flex;
    padding: 2px 10px;
    border-radius: var(--radius-full);
    font-size: var(--fs-12, 12px);
    font-weight: var(--font-weight-medium);
}

.rating-badge.unrated {
    background: var(--color-surface-muted);
    color: var(--color-text-muted);
    border: 1px solid var(--color-border);
}

.cycle-status-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    font-size: var(--fs-11, 11px);
    font-weight: var(--font-weight-medium);
    text-transform: none;
    letter-spacing: 0.04em;
}

.cycle-status-badge.open {
    background: var(--color-success-bg);
    color: var(--color-success);
    border: 1px solid var(--color-success-border);
}

.cycle-status-badge.submitted {
    background: var(--color-info-bg);
    color: var(--color-info);
    border: 1px solid var(--color-info-border);
}

/* Rating-band variants of .rating-badge (used via RATING_CSS_CLASS in
   hod_approval_tab_content rows) — rebuilt on the rating-band tokens. */
.rating-badge.poor { background: var(--rating-poor-bg); color: var(--rating-poor-text); border: 1px solid var(--rating-poor-border); }
.rating-badge.average { background: var(--rating-average-bg); color: var(--rating-average-text); border: 1px solid var(--rating-average-border); }
.rating-badge.good { background: var(--rating-good-bg); color: var(--rating-good-text); border: 1px solid var(--rating-good-border); }
.rating-badge.very-good { background: var(--rating-very-good-bg); color: var(--rating-very-good-text); border: 1px solid var(--rating-very-good-border); }
.rating-badge.excellent { background: var(--rating-excellent-bg); color: var(--rating-excellent-text); border: 1px solid var(--rating-excellent-border); }


/* ============================================================
   PMS error banner (Option B)
   Centered top banner for ALL error messages. Soft pink box,
   bold deep-red text. Manual close only (no auto-dismiss timer).
   Palette: #FCE4D6 box / #B00020 text — matches the reject/flag
   convention and passes contrast.
   ============================================================ */
.err-banner-root {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1300; /* above toasts (1200) and modal overlays */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-4);
    pointer-events: none;
}
.err-banner {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    width: 100%;
    max-width: 620px;
    background: #FCE4D6;
    border: 1.5px solid #F3B7A0;
    border-left: 5px solid #B00020;
    border-radius: var(--radius-md);
    box-shadow: 0 10px 30px rgba(176, 0, 32, 0.18);
    padding: var(--space-3) var(--space-4);
    color: #B00020;
    font-size: var(--font-size-sm);
    font-weight: 700;
    line-height: var(--line-height-normal);
    opacity: 0;
    transform: translateY(-12px);
    transition: opacity 180ms var(--ease-out-strong), transform 180ms var(--ease-out-strong);
    pointer-events: auto;
}
.err-banner--visible { opacity: 1; transform: translateY(0); }
.err-banner--leaving { opacity: 0; transform: translateY(-8px); }
.err-banner-icon {
    flex-shrink: 0;
    margin-top: 1px;
    display: inline-flex;
    color: #C62828;
}
.err-banner-msg {
    flex: 1;
    color: #B00020;
    font-weight: 700;
}
.err-banner-close {
    flex-shrink: 0;
    background: none;
    border: none;
    padding: 8px;
    margin: -8px -10px -8px 0;
    cursor: pointer;
    color: #B00020;
    opacity: 0.75;
    border-radius: var(--radius-sm);
    display: inline-flex;
}
.err-banner-close:hover { opacity: 1; background: rgba(176, 0, 32, 0.08); }
.err-banner-close:focus-visible { outline: 2px solid #B00020; outline-offset: 1px; }
@media (max-width: 640px) {
    .err-banner-root { padding: var(--space-3); }
    .err-banner { max-width: none; }
}

/* ============================================================
   CONFIRM DIALOG  (window.confirmDialog in app.js)
   ------------------------------------------------------------
   Replaces native window.confirm. Built from semantic tokens only,
   so it inherits whichever design system the screen opted into —
   no RT-specific rules are needed for it.

   z-index sits above .modal-overlay (1000) because a confirm can be
   raised from inside an already-open screen modal.
   ============================================================ */
.pms-confirm-overlay {
    position: fixed;
    inset: 0;
    z-index: 2000;
    background: rgba(0, 0, 0, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-4);
    opacity: 0;
    transition: opacity 160ms cubic-bezier(0.23, 1, 0.32, 1);
}
.pms-confirm-overlay.active { opacity: 1; }

/* A confirm carrying a structured body (buildBody) needs more room than the
   460px default, which was sized for a title, a line of prose and four facts. */
.pms-confirm-box:has(.pms-confirm-custom) { width: 560px; }

.pms-confirm-box {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    width: 460px;
    max-width: 100%;
    max-height: calc(100vh - 2 * var(--space-4));
    overflow-y: auto;
    padding: var(--space-5);
    transform: scale(0.96);
    transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1);
}
.pms-confirm-overlay.active .pms-confirm-box { transform: scale(1); }

.pms-confirm-icon {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: var(--space-3);
}
.pms-confirm-icon--danger  { background: var(--color-error-bg); color: var(--color-error); }
.pms-confirm-icon--primary { background: var(--color-info-bg);  color: var(--color-primary); }

.pms-confirm-title {
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
    margin-bottom: var(--space-2);
    line-height: var(--line-height-tight);
}
.pms-confirm-body {
    font-size: var(--font-size-sm);
    color: var(--color-text-secondary);
    line-height: var(--line-height-relaxed);
}

/* A disabled .btn had no disabled appearance anywhere in the app — it read as
   fully live. That only became visible once the typed-confirmation guard made a
   button start out disabled, but it applies to every disabled .btn. */
.btn:disabled, .btn[disabled] {
    opacity: 0.45;
    cursor: not-allowed;
    box-shadow: none;
}
.btn:disabled:active, .btn[disabled]:active { transform: none; }

/* Typed-confirmation guard. Used by an action with no undo: the confirm
   button stays disabled until the string matches. */
.pms-confirm-guard { margin-top: var(--space-3); text-align: left; }
.pms-confirm-guard-label {
    display: block; font-size: var(--fs-12, 12px); font-weight: 600;
    color: var(--color-text-secondary); margin-bottom: 6px;
}
.pms-confirm-guard-input {
    width: 100%; min-height: 40px; padding: 9px 11px; font: inherit; font-size: var(--font-size-sm);
    color: var(--color-text-primary); background: var(--color-surface);
    border: 1px solid var(--color-border); border-radius: var(--radius-md);
}
.pms-confirm-guard-input:focus {
    outline: none; border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-primary-tint);
}

.pms-confirm-details {
    margin-top: var(--space-3);
    padding: var(--space-3);
    background: var(--color-surface-muted);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: var(--fs-12, 12px);
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 4px var(--space-3);
}
.pms-confirm-details dt {
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-primary);
    white-space: nowrap;
}
.pms-confirm-details dd {
    color: var(--color-text-secondary);
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------
   confirmDialog(): structured body (opts.buildBody)

   For a confirm whose numbers need ranking. .pms-confirm-details renders every
   row at one weight, which is right for four facts and wrong for a batch whose
   annualised cost is the decision. These primitives are generic on purpose —
   any caller handing over money, a consequence list or a named set of records
   can reuse them rather than growing its own.
   --------------------------------------------------------------------------- */
.pms-confirm-custom { margin-top: var(--space-4); text-align: left; }

/* Scope chips: division / category / cycle, each labelled. */
.pms-cf-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-4); }
.pms-cf-chip {
    font-size: var(--fs-10-5, 10.5px); font-weight: var(--font-weight-semibold);
    padding: 3px 9px; border-radius: var(--radius-sm);
    background: var(--color-surface-secondary); border: 1px solid var(--color-border);
    color: var(--color-text-primary);
}
.pms-cf-chip .k { color: var(--color-text-muted); font-weight: var(--font-weight-regular); margin-right: 4px; }

/* Money block: one hero figure, then the arithmetic that produces it. */
.pms-cf-money {
    border: 1px solid var(--color-border-strong); border-radius: var(--radius-md);
    overflow: hidden; margin-bottom: var(--space-4);
}
.pms-cf-hero { padding: 14px 16px; background: var(--color-surface-secondary); border-bottom: 1px solid var(--color-border); }
.pms-cf-hero .k { font-size: var(--fs-10, 10px); font-weight: var(--font-weight-semibold); color: var(--color-text-muted); margin-bottom: 3px; }
.pms-cf-hero .v {
    font-size: var(--font-size-3xl); font-weight: var(--font-weight-bold); letter-spacing: -.5px;
    color: var(--color-text-primary); font-variant-numeric: tabular-nums; line-height: var(--line-height-flat);
}
.pms-cf-hero .v .cur { font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--color-text-muted); margin-right: 5px; }
.pms-cf-hero .sub { font-size: var(--fs-11, 11px); color: var(--color-text-muted); margin-top: 3px; }
.pms-cf-rows { display: grid; grid-template-columns: 1fr auto; gap: 1px 0; background: var(--color-border); }
.pms-cf-rows > div { background: var(--color-surface); padding: 8px 16px; font-size: var(--font-size-sm); }
.pms-cf-rows .k { color: var(--color-text-secondary); }
.pms-cf-rows .v { text-align: right; font-variant-numeric: tabular-nums; font-weight: var(--font-weight-semibold); }
.pms-cf-rows .v .cur { font-size: var(--fs-10, 10px); color: var(--color-text-muted); font-weight: var(--font-weight-regular); margin-right: 3px; }
.pms-cf-rows .zero { color: var(--color-text-muted); font-weight: var(--font-weight-regular); }
.pms-cf-rows .k.tot, .pms-cf-rows .v.tot {
    font-weight: var(--font-weight-bold); color: var(--color-text-primary);
    border-top: 1px solid var(--color-border-strong);
}

/* Consequences: facts, one per line, not a paragraph. */
.pms-cf-conseq {
    border: 1px solid var(--color-border); border-radius: var(--radius-md);
    background: var(--color-surface); margin-bottom: var(--space-4);
}
.pms-cf-conseq .row {
    display: flex; gap: 10px; align-items: flex-start;
    padding: 9px 14px; font-size: var(--font-size-sm); border-bottom: 1px solid var(--color-border);
    color: var(--color-text-secondary);
}
.pms-cf-conseq .row:last-child { border-bottom: none; }
.pms-cf-conseq .row b { font-weight: var(--font-weight-semibold); color: var(--color-text-primary); }
.pms-cf-conseq .ic { width: 16px; flex-shrink: 0; text-align: center; color: var(--color-text-muted); }
.pms-cf-conseq .row.warn { background: var(--color-warning-bg); color: var(--color-warning); }
.pms-cf-conseq .row.warn b, .pms-cf-conseq .row.warn .ic { color: inherit; }

/* Who is in the batch: named, collapsed, scrolling past a handful. */
.pms-cf-who { border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; }
.pms-cf-who > summary {
    cursor: pointer; list-style: none; padding: 9px 14px; min-height: 40px;
    display: flex; align-items: center; gap: 8px; font-size: var(--fs-12, 12px);
    font-weight: var(--font-weight-semibold); background: var(--color-surface-secondary);
}
.pms-cf-who > summary::-webkit-details-marker { display: none; }
.pms-cf-who > summary::after { content: '\25BE'; margin-left: auto; color: var(--color-text-muted); font-size: var(--fs-11, 11px); }
.pms-cf-who[open] > summary::after { content: '\25B4'; }
.pms-cf-who .count { color: var(--color-text-muted); font-weight: var(--font-weight-regular); }
.pms-cf-who .list { max-height: 156px; overflow-y: auto; }
.pms-cf-who .r {
    display: grid; grid-template-columns: 68px 1fr auto; gap: 10px; align-items: center;
    padding: 7px 14px; font-size: var(--fs-12, 12px); border-top: 1px solid var(--color-border);
}
.pms-cf-who .r .id { font-variant-numeric: tabular-nums; color: var(--color-text-muted); }
.pms-cf-who .r .amt { font-variant-numeric: tabular-nums; font-weight: var(--font-weight-semibold); }
.pms-cf-who .r .adj {
    font-size: var(--fs-10, 10px); font-weight: var(--font-weight-semibold); padding: 1px 7px; border-radius: var(--radius-full);
    background: var(--color-warning-bg); border: 1px solid var(--color-warning-border);
    color: var(--color-warning); margin-left: 6px; white-space: nowrap;
}
.pms-cf-hint { font-size: var(--fs-11, 11px); color: var(--color-text-muted); margin-right: auto; text-align: left; }

.pms-confirm-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-2);
    margin-top: var(--space-5);
    flex-wrap: wrap;
}

@media (max-width: 560px) {
    .pms-confirm-box { padding: var(--space-4); }
    .pms-confirm-details { grid-template-columns: 1fr; gap: 0; }
    .pms-confirm-details dd { margin-bottom: var(--space-2); }
    .pms-confirm-details dd:last-child { margin-bottom: 0; }
    /* Confirm on top, and both actions at a comfortable tap size. */
    .pms-confirm-actions { flex-direction: column-reverse; }
    .pms-confirm-actions .btn { width: 100%; min-height: 40px; }
}
@media (prefers-reduced-motion: reduce) {
    .pms-confirm-overlay, .pms-confirm-box { transition: none; }
}


/* ═══════════════════════════════════════════════════════════════════
   RESPONSIVE FOUNDATIONS — Phase 0 (11-Sep-2026)
   Breakpoints (docs/responsive_build_plan_v1.md), only these three:
     phone    max-width: 767px          (rt-design-system MOBILE_BREAKPOINT)
     tablet   768–1024px, or pointer: coarse up to 1366px (drawer shell)
     desktop  1025px+ with a mouse
   Touch sizing keys off (pointer: coarse), not width.
   ═══════════════════════════════════════════════════════════════════ */

/* Drawer open: the page underneath must not scroll behind the overlay. */
html.drawer-open,
html.drawer-open body {
    overflow: hidden;
}

/* Tablet (768-1024px): the title steps down one notch. This band had almost
   no typography of its own before the audit -- text was either the desktop
   size or the 12px mobile floor, with nothing between. */
@media (min-width: 768px) and (max-width: 1024px) {
    body .content-header .content-header-title {
        font-size: var(--font-size-xl);
    }
}

/* Phone: the page title takes its own row; controls wrap beneath it. */
@media (max-width: 767px) {
    body .content-header > .content-header-left {
        flex-basis: 100%;
    }
    body .content-header .content-header-title {
        font-size: var(--font-size-lg);
    }
    body .content-header > .content-header-right {
        width: 100%;
        flex-wrap: wrap;
        justify-content: flex-start;
        gap: var(--space-2);
    }
}

/* Dialogs: size against the VISIBLE viewport. 100vh on a phone includes the
   area under the browser's toolbar, which hid the footer buttons. */
@supports (height: 100dvh) {
    .modal-container,
    .modal-box {
        max-height: calc(100dvh - 64px);
    }
}

/* Phone: the shared dialog becomes a bottom sheet with its actions in reach. */
@media (max-width: 767px) {
    .modal-overlay {
        padding: 0;
        align-items: flex-end;
    }
    .modal-container {
        max-width: 100%;
        max-height: 94vh;
    }
    .modal-box {
        max-height: 94vh;
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    }
    @supports (height: 100dvh) {
        .modal-container,
        .modal-box {
            max-height: 94dvh;
        }
    }
    .modal-header,
    .modal-body {
        padding-left: var(--space-4);
        padding-right: var(--space-4);
    }
    .modal-footer {
        flex-wrap: wrap;
        padding: var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
    }
}

/* Touch screens: 16px text in fields, or iOS Safari zooms the page on focus. */
@media (pointer: coarse) {
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="hidden"]),
    select,
    textarea {
        font-size: 16px !important;
    }
}

/* --------------------------------------------------------------------------
   TEXT FLOOR — responsive Phase 2 (11-Sep-2026)
   Every sub-12px font-size in the screen stylesheets and templates reads a
   token: var(--fs-11, 11px). On a desktop with a mouse the token IS the old
   size, so nothing moves. On phones and tablets (the drawer shell) every one
   of them becomes 12px, the legibility floor. Chart axis ticks are drawn by
   Chart.js options, not CSS, and keep their own size. PDF, print and email
   templates were not rewritten and keep literal sizes.
   Defined in main.css (sign-in pages) and again in rt-masters.css (app pages,
   not long-cached) — keep the two identical.
   -------------------------------------------------------------------------- */
:root {
    --fs-8: 8px; --fs-9: 9px; --fs-9-5: 9.5px; --fs-10: 10px;
    --fs-10-5: 10.5px; --fs-11: 11px; --fs-11-5: 11.5px;
    /* 12px is the floor TARGET, so it never changes at any width. It joins the
       family so that every small size in the app reads a token. */
    --fs-12: 12px;
}
@media (max-width: 1024px), (pointer: coarse) {
    :root {
        --fs-8: 12px; --fs-9: 12px; --fs-9-5: 12px; --fs-10: 12px;
        --fs-10-5: 12px; --fs-11: 12px; --fs-11-5: 12px;
        --font-size-xs: 12px;   /* the 11px design token */
    }
}
