/* ============================================================
   Design tokens
   ============================================================ */
:root {
    /* Brand */
    --color-brand:               #2563eb;
    --color-brand-hover:         #1d4ed8;
    --color-brand-active:        #1e40af;

    /* Text */
    --color-text:                #0f172a;
    --color-text-strong:         #1e293b;
    --color-text-header:         #334155;
    --color-text-label:          #374151;
    --color-text-muted:          #475569;
    --color-text-subtle:         #64748b;
    --color-text-faint:          #94a3b8;
    --color-text-placeholder:    #9ca3af;
    --color-text-input:          #111827;
    --color-text-on-brand:       #ffffff;

    /* Surface */
    --color-surface:             #ffffff;
    --color-surface-app:         #f8fafc;
    --color-surface-subtle:      #f1f5f9;
    --color-surface-emphasis:    #e2e8f0;
    --color-surface-sidebar:     #1e293b;

    /* Border */
    --color-border:              #e5e7eb;
    --color-border-strong:       #e2e8f0;
    --color-border-input:        #d1d5db;

    /* Status */
    --color-success:             #16a34a;
    --color-success-modified:    #26b050;
    --color-danger:              #dc2626;
    --color-danger-bright:       #e50000;
    --color-warning:             #ca8a04;
    --color-warning-strong:      #b45309;
    --color-info:                #0284c7;

    /* Radii */
    --radius-sm:                 4px;
    --radius-md:                 6px;
    --radius-lg:                 8px;
    --radius-xl:                 10px;
    --radius-pill:               999px;

    /* Type sizes (6-step scale) */
    --font-xs:                   11px;   /* uppercase labels, micro meta */
    --font-sm:                   12px;   /* small text, meta */
    --font-base:                 13px;   /* table cells, UI */
    --font-md:                   14px;   /* body, inputs, buttons */
    --font-lg:                   15px;   /* section titles */
    --font-xl:                   22px;   /* page titles */

    /* Font weights */
    --weight-normal:             400;
    --weight-medium:             500;
    --weight-semibold:           600;

    /* Shadows */
    --shadow-button:             0 1px 2px rgba(15, 23, 42, 0.06);
    --shadow-card:               0 1px 3px rgba(15, 23, 42, 0.04);
    --shadow-sticky:             0 -4px 12px rgba(15, 23, 42, 0.08);
    --ring-brand:                0 0 0 3px rgba(37, 99, 235, 0.15);
    --ring-brand-soft:           0 0 0 3px rgba(37, 99, 235, 0.1);

    /* Letter spacing */
    --letter-tight:              -0.01em;
    --letter-wide:                0.05em;
    --letter-wider:               0.06em;

    /* Line heights */
    --line-tight:                1.25;   /* headings */
    --line-snug:                 1.35;   /* dense UI text */
    --line-base:                 1.5;    /* body */
    --line-relaxed:              1.65;   /* long-form copy */

    /* Transitions */
    --transition-fast:           0.12s ease;

    /* Font family */
    --font-family:               'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* ============================================================
   Dark theme — token overrides. Toggled by setting
   data-theme="dark" on <html>. Brand and status colours are
   intentionally preserved so brand identity stays consistent
   across themes.
   ============================================================ */
:root[data-theme="dark"] {
    /* Text */
    --color-text:                #f1f5f9;
    --color-text-strong:         #e2e8f0;
    --color-text-header:         #cbd5e1;
    --color-text-label:          #cbd5e1;
    --color-text-muted:          #94a3b8;
    --color-text-subtle:         #94a3b8;
    --color-text-faint:          #64748b;
    --color-text-placeholder:    #cbd5e1;
    --color-text-input:          #f1f5f9;

    /* Surface */
    --color-surface:             #1e293b;   /* card surface */
    --color-surface-app:         #0f172a;   /* page background */
    --color-surface-subtle:      #334155;   /* hover/badge bg */
    --color-surface-emphasis:    #475569;
    --color-surface-sidebar:     #0b1220;   /* slightly darker than card so sidebar still reads as a distinct rail */

    /* Border */
    --color-border:              #334155;
    --color-border-strong:       #475569;
    --color-border-input:        #475569;

    /* Shadows — softer on dark, with a slightly lighter accent */
    --shadow-button:             0 1px 2px rgba(0, 0, 0, 0.25);
    --shadow-card:               0 1px 3px rgba(0, 0, 0, 0.30);
    --shadow-sticky:             0 -4px 12px rgba(0, 0, 0, 0.35);
}

/* Sidebar overrides for dark mode — the original rule uses
   --color-text-strong (#1e293b); explicitly point it at the
   dark-mode sidebar token to keep visual separation from the
   content surface. */
:root[data-theme="dark"] .b-layout-sider,
:root[data-theme="dark"] .b-layout-sider-content {
    background-color: var(--color-surface-sidebar) !important;
}

/* Top bar in dark mode — Blazorise applies Bootstrap's bg-white via
   Background="Background.White" on the Bar; need !important to win. */
:root[data-theme="dark"] .b-layout-header,
:root[data-theme="dark"] .b-layout-header .b-bar,
:root[data-theme="dark"] .b-layout-header .bg-white {
    background-color: var(--color-surface) !important;
}

/* Card / table header backgrounds in dark mode use the card surface */
:root[data-theme="dark"] .b-table thead th {
    background-color: var(--color-surface-subtle);
}

/* DataGrid row hover in dark */
:root[data-theme="dark"] .b-table tbody tr:hover td {
    background-color: var(--color-surface-subtle);
}

/* Form-control input background in dark — Bootstrap base is white */
:root[data-theme="dark"] .form-control,
:root[data-theme="dark"] .form-select,
:root[data-theme="dark"] input.form-control {
    background-color: var(--color-surface-app);
    color: var(--color-text-input);
}

/* Disabled / readonly form-control — Bootstrap falls back to its
   light-grey --bs-secondary-bg which reads as white edges against
   the dark page. Pin to a dark surface with muted text instead. */
:root[data-theme="dark"] .form-control:disabled,
:root[data-theme="dark"] .form-control[readonly],
:root[data-theme="dark"] .form-select:disabled,
:root[data-theme="dark"] input.form-control:disabled,
:root[data-theme="dark"] input.form-control[readonly] {
    background-color: var(--color-surface-subtle);
    color: var(--color-text-faint);
    border-color: var(--color-border-input);
    opacity: 1;
}

/* Blazorise disabled Autocomplete sets the OUTER wrapper to a light
   grey via .dropdown.dropdown-disabled.b-is-autocomplete - flips the
   visible edges around the disabled input to light grey too. Match
   the inner input's dark surface so it reads as one piece. */
:root[data-theme="dark"] .dropdown.dropdown-disabled.b-is-autocomplete {
    background-color: var(--color-surface-subtle);
}

/* Topbar search box in dark */
:root[data-theme="dark"] .topbar-search .global-search-box input {
    background-color: var(--color-surface-subtle);
    border-color: var(--color-border-strong);
}

:root[data-theme="dark"] .topbar-search .global-search-box input:focus {
    background-color: var(--color-surface);
}

/* Secondary buttons in dark */
:root[data-theme="dark"] .btn-secondary {
    background-color: var(--color-surface-subtle);
    border-color: var(--color-border-strong);
    color: var(--color-text);
}

:root[data-theme="dark"] .btn-secondary:hover {
    background-color: var(--color-surface-emphasis);
    border-color: var(--color-border-strong);
    color: var(--color-text-strong);
}
/* Light buttons in dark. Bootstrap leaves .btn-light near-white under its own dark
   theme, so every quiet action sat as a bright box on a dark table, and where the label
   was muted text (the "assign" placeholder on a certificate run) the light-on-light was
   unreadable. Treated exactly like the secondary button above. */
:root[data-theme="dark"] .btn-light {
    background-color: var(--color-surface-subtle);
    border-color: var(--color-border-strong);
    color: var(--color-text);
}

:root[data-theme="dark"] .btn-light:hover,
:root[data-theme="dark"] .btn-light:focus-visible,
:root[data-theme="dark"] .btn-light:active {
    background-color: var(--color-surface-emphasis);
    border-color: var(--color-border-strong);
    color: var(--color-text-strong);
}



/* Category badge background in dark */
:root[data-theme="dark"] .category-badge {
    background: var(--color-surface-subtle);
    border-color: var(--color-border-strong);
}

/* Chip background in dark (inactive) */
:root[data-theme="dark"] .category-chip {
    background: var(--color-surface);
    border-color: var(--color-border-strong);
    color: var(--color-text-muted);
}

/* Recent-toggle background */
:root[data-theme="dark"] .recent-toggle {
    background: var(--color-surface-app);
    border-color: var(--color-border);
}

:root[data-theme="dark"] .recent-toggle-btn.active {
    background: var(--color-surface);
}

/* Skeleton shimmer for dark */
:root[data-theme="dark"] .list-skeleton-row {
    background: linear-gradient(90deg, var(--color-surface) 0%, var(--color-surface-subtle) 50%, var(--color-surface) 100%);
    background-size: 200% 100%;
}

/* List rows / dashboard rows hover on dark */
:root[data-theme="dark"] .dashboard-row:hover {
    background: var(--color-surface-subtle);
}

/* Blazorise DataGrid pagination buttons (First / Prev / page numbers / Next / Last)
   don't pick up Bootstrap's data-bs-theme — force token colours here. */
:root[data-theme="dark"] .pagination .page-link,
:root[data-theme="dark"] .b-table-pagination .page-link,
:root[data-theme="dark"] .b-table-pagination button,
:root[data-theme="dark"] .b-table-pagination .btn,
:root[data-theme="dark"] nav[aria-label*="pagination"] .page-link,
:root[data-theme="dark"] .pagination .page-item .btn {
    background-color: var(--color-surface) !important;
    color: var(--color-text) !important;
    border-color: var(--color-border) !important;
}

:root[data-theme="dark"] .pagination .page-link:hover,
:root[data-theme="dark"] .b-table-pagination .page-link:hover,
:root[data-theme="dark"] .b-table-pagination button:hover {
    background-color: var(--color-surface-subtle) !important;
}

:root[data-theme="dark"] .pagination .page-item.active .page-link,
:root[data-theme="dark"] .pagination .page-item .page-link.active {
    background-color: var(--color-brand) !important;
    border-color: var(--color-brand) !important;
    color: #fff !important;
}

:root[data-theme="dark"] .pagination .page-item.disabled .page-link {
    color: var(--color-text-faint) !important;
    background-color: var(--color-surface-app) !important;
}

/* Dropdown menus (Autocomplete suggestions, BarDropdownMenu, etc.) — Bootstrap
   doesn't always flip these. Force dark surface + hover state. */
:root[data-theme="dark"] .dropdown-menu {
    background-color: var(--color-surface) !important;
    border-color: var(--color-border) !important;
    color: var(--color-text);
}

:root[data-theme="dark"] .dropdown-menu .dropdown-item {
    color: var(--color-text);
}

:root[data-theme="dark"] .dropdown-menu .dropdown-item:hover,
:root[data-theme="dark"] .dropdown-menu .dropdown-item:focus,
:root[data-theme="dark"] .dropdown-menu .dropdown-item.active,
:root[data-theme="dark"] .dropdown-menu .dropdown-item.focused,
:root[data-theme="dark"] .dropdown-menu .dropdown-item.focus,
:root[data-theme="dark"] .dropdown-menu .dropdown-item.is-active,
:root[data-theme="dark"] .dropdown-menu .dropdown-item.b-is-active,
:root[data-theme="dark"] .dropdown-menu .dropdown-item[aria-selected="true"],
:root[data-theme="dark"] .dropdown-menu .b-is-autocomplete-suggestion.focused,
:root[data-theme="dark"] .dropdown-menu .b-is-autocomplete-suggestion-focused {
    background-color: var(--color-surface-subtle) !important;
    color: var(--color-text) !important;
}

/* Belt-and-braces: cover children so a colored child element can't
   stay light when the parent flips. */
:root[data-theme="dark"] .dropdown-menu .dropdown-item.active *,
:root[data-theme="dark"] .dropdown-menu .dropdown-item:hover *,
:root[data-theme="dark"] .dropdown-menu .dropdown-item[aria-selected="true"] * {
    color: inherit;
}

/* DataGrid selected row — Blazorise / Bootstrap apply a light blue
   highlight that makes text unreadable in dark mode. Use a subtle
   brand-tinted overlay instead. */
:root[data-theme="dark"] .b-table tbody tr.selected td,
:root[data-theme="dark"] .b-table tbody tr.b-table-row-selected td,
:root[data-theme="dark"] .b-table tbody tr.table-active td,
:root[data-theme="dark"] .b-table tbody tr.table-primary td,
:root[data-theme="dark"] .table > tbody > tr.table-active > *,
:root[data-theme="dark"] .table > tbody > tr.table-primary > * {
    background-color: rgba(37, 99, 235, 0.15) !important;
    color: var(--color-text) !important;
    --bs-table-bg-state: transparent;
}

html, body {
    font-family: var(--font-family);
    font-size: var(--font-md);
    line-height: var(--line-base);
    color: var(--color-text);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

a, .btn-link {
    color: var(--color-brand);
}

.btn-primary {
    color: #fff;
    background-color: var(--color-brand);
    border-color: var(--color-brand-hover);
}

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

/* ============================================================
   Sidebar — branded dark blue-grey (var(--color-text-strong) / slate-800)
   ============================================================ */

.b-layout-sider,
.b-layout-sider-content {
    background-color: var(--color-text-strong) !important;
    /*overflow: hidden;*/
}

.b-layout-sider {
    flex-shrink: 0;
}

/* Sidebar brand — clip overflow so logo doesn't bleed when collapsed */
.b-layout-sider .b-bar-brand,
.b-layout-sider .b-bar-brand .b-bar-item,
.b-layout-sider .b-bar-brand .b-bar-link {
    overflow: hidden;
}

.b-layout-sider .b-bar-brand img {
    max-width: 100%;
    height: auto;
}

/* Sidebar nav links — hover */
.b-layout-sider .b-bar-link:hover,
.b-layout-sider .b-bar-dropdown-toggle:hover {
    background-color: rgba(255, 255, 255, 0.06) !important;
}

/* Sidebar active nav item — full-width solid blue (parent + dropdown items) */
.b-layout-sider .nav-link.active,
.b-layout-sider .b-bar-link.active,
.b-layout-sider .b-bar-item .nav-link.active,
.b-layout-sider .b-bar-dropdown-item.active,
.b-layout-sider .dropdown-item.active {
    background-color: var(--color-brand) !important;
    color: #fff !important;
}

/* Brand link should never show active highlight */
.b-layout-sider .b-bar-brand .nav-link.active,
.b-layout-sider .b-bar-brand .b-bar-link.active,
.b-layout-sider .b-bar-brand .nav-link {
    background-color: transparent !important;
}

/* ============================================================
   Content area edge — clean seam between sidebar and content
   ============================================================ */

.b-layout-sider + .b-layout {
    border-left: 1px solid var(--color-border);
    /*min-width: 0;*/
}

/* ============================================================
   Top bar — light with bottom border
   ============================================================ */

.b-layout-header {
    border-bottom: 1px solid var(--color-border);
}

.b-layout-header .b-bar {
    box-shadow: none !important;
}

.b-layout-header .b-bar-link,
.b-layout-header .b-bar-dropdown-toggle {
    color: var(--color-text-header) !important;
    font-weight: var(--weight-medium);
}

.b-layout-header .b-bar-link:hover,
.b-layout-header .b-bar-dropdown-toggle:hover {
    color: var(--color-brand) !important;
}

/* User actions (profile, logout) in top bar */
.b-layout-header .nav-link,
.b-layout-header .nav-link .svg-inline--fa,
.b-layout-header .nav-link i {
    color: var(--color-text-muted) !important;
}

.b-layout-header .nav-link:hover,
.b-layout-header .nav-link:hover .svg-inline--fa,
.b-layout-header .nav-link:hover i {
    color: var(--color-brand) !important;
}

/* ============================================================
   Content area — off-white background
   ============================================================ */

.b-layout-content {
    background-color: var(--color-surface-app);
}

/* Mouse-click focus is silent; keyboard focus shows a branded ring. */
.btn:focus,
.btn-link:focus,
.form-control:focus,
.form-select:focus,
.form-check-input:focus,
a:focus {
    outline: none;
    box-shadow: none;
}

.btn:focus-visible,
.btn-link:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
a:focus-visible {
    outline: 2px solid var(--color-brand);
    outline-offset: 2px;
    border-radius: var(--radius-md);
}

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

.form-check-input:focus-visible {
    outline: 2px solid var(--color-brand);
    outline-offset: 1px;
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--color-success-modified);
}

.invalid {
    outline: 1px solid var(--color-danger-bright);
}

.validation-message {
    color: var(--color-danger-bright);
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

/* ============================================================
   Sidebar user pod — bottom-left identity & preferences
   ============================================================ */

.b-layout-sider .b-bar-end {
    margin-top: auto;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
    padding-top: 6px;
}

.user-pod {
    padding: 4px 8px;
}

.user-pod .dropdown {
    width: 100%;
}

.user-pod .user-pod-trigger {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border-radius: var(--radius-md);
    background: transparent;
    border: none;
    color: rgba(255, 255, 255, 0.85);
    text-align: left;
    cursor: pointer;
    transition: background-color var(--transition-fast);
}

.user-pod .user-pod-trigger:hover,
.user-pod .user-pod-trigger:focus {
    background: rgba(255, 255, 255, 0.06);
    color: #fff;
    box-shadow: none;
}

.user-pod .user-pod-trigger::after {
    /* Hide Bootstrap's default dropdown caret — we use the avatar as
       the visual affordance instead. */
    display: none;
}

.user-pod-avatar {
    font-size: 24px;
    flex: 0 0 auto;
    color: rgba(255, 255, 255, 0.75);
}

.user-pod-name {
    font-size: var(--font-base);
    font-weight: var(--weight-medium);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1 1 auto;
}

/* Collapsed sidebar — hide the name, keep just the avatar */
.b-layout-sider.b-bar-collapsed .user-pod-name {
    display: none;
}

/* Dropdown menu styling for the user pod popover */
.user-pod .dropdown-menu {
    min-width: 200px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
    padding: 6px;
}

.user-pod .dropdown-item {
    border-radius: var(--radius-md);
    padding: 8px 10px;
    font-size: var(--font-base);
    display: flex;
    align-items: center;
}

.user-pod-logout-item {
    list-style: none;
    margin: 0;
    padding: 0;
}

.user-pod-logout-item form {
    margin: 0;
}

.user-pod-logout {
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    color: var(--color-danger);
    cursor: pointer;
}

.user-pod-logout:hover,
.user-pod-logout:focus {
    background: var(--color-surface-subtle);
    color: var(--color-danger);
}

/* ============================================================
   Shared report row (used by Dashboard + RecentReportsPanel)
   ============================================================ */

.dashboard-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    border-radius: var(--radius-md);
    cursor: pointer;
    color: var(--color-text);
    text-decoration: none;
    min-height: 40px;
    transition: background-color var(--transition-fast), color var(--transition-fast);
}

.dashboard-row:hover {
    background: var(--color-surface-subtle);
    color: var(--color-text);
    text-decoration: none;
}

.dashboard-row:focus-visible {
    outline: 2px solid var(--color-brand);
    outline-offset: 2px;
}

.row-primary {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.row-project {
    font-size: var(--font-md);
    font-weight: var(--weight-medium);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.3;
}

.row-client {
    font-weight: var(--weight-normal);
    color: var(--color-text-muted);
}

.row-site {
    font-size: var(--font-base);
    color: var(--color-text-faint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.3;
}

.row-meta {
    flex: 0 0 auto;
    text-align: right;
    font-size: var(--font-sm);
    color: var(--color-text-faint);
    white-space: nowrap;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 1px;
}

.row-meta .author {
    font-weight: var(--weight-medium);
    color: var(--color-text-muted);
}

/* ============================================================
   Recent reports panel (used on report home pages)
   ============================================================ */

.recent-panel {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-card);
    padding: 14px 12px 10px 12px;
}

.recent-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin: 0 4px 8px 4px;
}

.recent-panel-title {
    font-size: var(--font-xs);
    letter-spacing: var(--letter-wider);
    text-transform: uppercase;
    color: var(--color-text-muted);
    font-weight: var(--weight-semibold);
}

.recent-toggle {
    display: inline-flex;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--color-surface-app);
}

.recent-toggle-btn {
    background: transparent;
    border: none;
    padding: 4px 10px;
    font-size: var(--font-sm);
    font-weight: var(--weight-medium);
    color: var(--color-text-muted);
    cursor: pointer;
}

.recent-toggle-btn:hover {
    color: var(--color-brand);
}

.recent-toggle-btn.active {
    background: #fff;
    color: var(--color-brand);
    box-shadow: var(--shadow-button);
}

.recent-empty {
    font-size: var(--font-base);
    color: var(--color-text-faint);
    padding: 20px 8px;
    text-align: center;
    line-height: 1.5;
}

.recent-filter-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin: 0 4px 10px 4px;
    padding: 8px 0 0 0;
    border-top: 1px dashed var(--color-border);
}

.recent-filter-select {
    flex: 0 1 220px;
    min-width: 140px;
    padding: 4px 8px;
    font-size: var(--font-sm);
    color: var(--color-text-strong);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    cursor: pointer;
}

.recent-filter-select:focus {
    outline: none;
    border-color: var(--color-brand);
    box-shadow: 0 0 0 0.15rem rgba(37, 99, 235, 0.15);
}

.recent-filter-clear {
    margin-left: auto;
    background: transparent;
    border: none;
    color: var(--color-brand);
    font-size: var(--font-sm);
    font-weight: var(--weight-medium);
    cursor: pointer;
    padding: 4px 6px;
}

.recent-filter-clear:hover {
    text-decoration: underline;
}

.recent-footer {
    margin-top: 8px;
    padding: 6px 4px 0 4px;
    font-size: var(--font-sm);
    color: var(--color-text-faint);
    text-align: center;
    border-top: 1px dashed var(--color-border);
}

/* ============================================================
   Report home pages — hero strip (search + new)
   ============================================================ */

.report-hero {
    display: flex;
    gap: 12px;
    align-items: center;
}

.report-hero-search {
    flex: 1 1 auto;
    min-width: 0;
}

.report-hero-search .autocomplete,
.report-hero-search .dropdown,
.report-hero-search input.form-control {
    width: 100%;
}

.report-hero-search input.form-control {
    height: 40px;
    border-radius: var(--radius-lg);
    border-color: var(--color-border);
    font-size: var(--font-md);
}

.report-hero-search input.form-control:focus {
    border-color: var(--color-brand);
    box-shadow: var(--ring-brand);
}

/* ============================================================
   List pages — loading skeleton
   ============================================================ */

.list-skeleton {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 4px 0 16px 0;
}

.list-skeleton-row {
    height: 42px;
    border-radius: var(--radius-md);
    background: linear-gradient(90deg, var(--color-surface-subtle) 0%, var(--color-border-strong) 50%, var(--color-surface-subtle) 100%);
    background-size: 200% 100%;
    animation: shimmer 1.4s infinite ease-in-out;
}

/* Vary widths for natural feel */
.list-skeleton-row:nth-child(1) { width: 100%; }
.list-skeleton-row:nth-child(2) { width: 96%; }
.list-skeleton-row:nth-child(3) { width: 100%; }
.list-skeleton-row:nth-child(4) { width: 92%; }
.list-skeleton-row:nth-child(5) { width: 98%; }

/* ============================================================
   DataGrid — empty state
   ============================================================ */

.b-table-empty-row td,
.table tbody tr.b-table-empty-row td {
    text-align: center;
    color: var(--color-text-faint);
    padding: 40px 16px !important;
    font-size: var(--font-base);
    border: none !important;
}

/* ============================================================
   Edit pages — flatten inner tab-panel cards
   ============================================================ */

.tab-content .tab-pane .card {
    border: none;
    box-shadow: none;
    background: transparent;
}

.tab-content .tab-pane .card .card-body {
    padding: 0 0 8px 0;
}

/* Section cards that have a CardHeader — show a subtle label rule */
.tab-content .tab-pane .card .card-header {
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--color-border);
    padding: 4px 0 8px 0;
}

.tab-content .tab-pane .card .card-header .card-title {
    font-size: var(--font-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--letter-wider);
    color: var(--color-text-muted);
}

/* ============================================================
   Edit pages — sticky action bar
   ============================================================ */

.edit-actions-sticky {
    position: sticky;
    bottom: 0;
    z-index: 20;
    background: var(--color-surface);
    border-top: 1px solid var(--color-border-strong);
    box-shadow: var(--shadow-sticky);
    padding: 14px 24px;
    display: flex;
    gap: 8px;
    align-items: center;
    margin-top: 16px;
}

/* ============================================================
   Generation tray (top bar)
   ============================================================ */

/* Search + tray live in one flex row we control (the Blazorise bar's own
   start/end groups stack on this layout), so placement is independent of it. */
.b-layout-header .topbar-row,
.b-layout-header .topbar-row .b-bar-item {
    width: 100%;
    flex: 1 1 auto;
}

.topbar-row-inner {
    display: flex;
    align-items: center;
    width: 100%;
}

.topbar-tray {
    margin-left: auto;
    margin-right: 24px;
    position: relative;
}

/* The tray dropdown must float as an overlay, not sit in flow (which would
   stretch the flex row and grow the whole header when opened). */
.topbar-tray .dropdown-menu {
    position: absolute !important;
    top: calc(100% + 6px);
    right: 0;
    left: auto !important;
    z-index: 1100;
}

/* Subtle borderless icon button instead of the default white btn-light box. */
.gen-tray-toggle.btn,
.gen-tray-toggle.btn:active,
.gen-tray-toggle.btn:focus {
    position: relative;
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    color: var(--color-text-header) !important;
    padding: 4px 8px;
    font-size: 1.15rem;
    line-height: 1;
}

.gen-tray-toggle.btn:hover {
    color: var(--color-brand) !important;
}

/* Hide Bootstrap's dropdown caret - the cloud icon is the affordance. */
.gen-tray-toggle.dropdown-toggle::after {
    display: none;
}

.gen-tray-badge {
    position: absolute;
    top: -2px;
    right: -2px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 8px;
    background: #16a34a;
    color: #fff;
    font-size: 10px;
    line-height: 16px;
    text-align: center;
    font-weight: 700;
}

/* ============================================================
   Edit pages — generating indicator
   ============================================================ */

.generating-indicator {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--font-base);
    font-weight: var(--weight-medium);
    color: var(--color-brand);
    margin-left: auto;
}

.generating-indicator .spinner-border {
    width: 1rem;
    height: 1rem;
    border-width: 2px;
    color: var(--color-brand);
}

/* ============================================================
   Edit pages — breadcrumb
   ============================================================ */

.edit-breadcrumb {
    font-size: var(--font-base);
    margin-top: 14px;
    margin-bottom: 10px;
}

.edit-breadcrumb a {
    color: var(--color-text-muted);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.edit-breadcrumb a:hover {
    color: var(--color-brand);
}

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

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

/* Page-level headings — all non-dashboard pages use <Heading Size="HeadingSize.Is4">,
   which renders as h4. Match the Dashboard heading style. */
.b-layout-content h4 {
    font-size: var(--font-xl);
}

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

.card {
    background-color: var(--color-surface);
    border-color: var(--color-border);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-card);
}

.card-header {
    background-color: transparent;
    border-bottom-color: var(--color-border);
    padding: 10px 16px;
}

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

/* ============================================================
   Tabs
   ============================================================ */

.nav-tabs {
    border-bottom-color: var(--color-border);
    gap: 2px;
    flex-wrap: wrap;
}

.nav-tabs .nav-link {
    font-size: var(--font-base);
    font-weight: var(--weight-medium);
    color: var(--color-text-muted);
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    padding: 7px 14px;
    border-color: transparent;
    white-space: nowrap;
    transition: color var(--transition-fast), background-color var(--transition-fast), border-color var(--transition-fast);
}

.nav-tabs .nav-link:hover {
    color: var(--color-brand);
    background-color: var(--color-surface-subtle);
    border-color: transparent;
}

.nav-tabs .nav-link.active {
    color: var(--color-brand);
    font-weight: var(--weight-semibold);
    background-color: var(--color-surface);
    border-color: var(--color-border) var(--color-border) var(--color-surface);
}

/* ============================================================
   Form fields
   ============================================================ */

.b-field-label,
.form-label,
label.form-label,
label.b-field-label {
    font-size: var(--font-base);
    font-weight: var(--weight-medium);
    color: var(--color-text-label) !important;
    margin-bottom: 4px;
}

.form-control,
.form-select {
    border-radius: var(--radius-md);
    border-color: var(--color-border-input);
    font-size: var(--font-md);
    color: var(--color-text-input);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

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

.form-control::placeholder,
input.form-control::placeholder,
.form-select::placeholder {
    color: var(--color-text-placeholder) !important;
    opacity: 1;
}

/* Bootstrap floating labels keep the placeholder transparent (the label sits in its
   place). The !important rule above otherwise re-shows the placeholder, so it collides
   with the floating label - re-assert transparency for form-floating inputs (more
   specific + !important, so it wins). Fixes the /Account/* management fields. */
.form-floating > .form-control::placeholder,
.form-floating > input.form-control::placeholder {
    color: transparent !important;
}

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

.btn {
    border-radius: var(--radius-md);
    font-size: var(--font-md);
    font-weight: var(--weight-medium);
    transition:
        background-color var(--transition-fast),
        border-color var(--transition-fast),
        color var(--transition-fast),
        box-shadow var(--transition-fast),
        transform var(--transition-fast);
}

/* Tactile press feedback on real button clicks (only when not disabled).
   Cancel the transition during press so it feels snappy. */
.btn:not(:disabled):active {
    transform: translateY(1px);
    transition-duration: 0s;
}

.btn-secondary {
    background-color: var(--color-surface-subtle);
    border-color: var(--color-border-strong);
    color: var(--color-text-header);
}

.btn-secondary:hover {
    background-color: var(--color-border-strong);
    border-color: #cbd5e1;
    color: var(--color-text-strong);
}

/* ============================================================
   DataGrid / Tables
   ============================================================ */

.b-table {
    font-size: var(--font-base);
}

.b-table thead th {
    font-size: var(--font-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--letter-wide);
    color: var(--color-text-muted);
    background-color: var(--color-surface-app);
    border-bottom: 1px solid var(--color-border) !important;
    padding: 8px 12px;
}

.b-table tbody td {
    padding: 8px 12px;
    color: var(--color-text-strong);
    border-bottom-color: var(--color-surface-subtle) !important;
    vertical-align: middle;
}

.b-table tbody tr:hover td {
    background-color: var(--color-surface-app);
}

.cell-clamp {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Muted product list shown under a tested-system description in the grids.
   Wraps freely to as many lines as needed so full product names are visible
   (no ellipsis). Normal wrapping (not white-space:nowrap) means it never widens
   the table / forces a horizontal scrollbar. Colour is theme-aware for contrast. */
.ts-products-line {
    color: var(--color-text-subtle);
    font-size: 12px;
    margin-top: 3px;
    white-space: normal;
    overflow-wrap: anywhere;
}

.page-title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin: 16px 0 12px 0;
}

.page-title-row h4 {
    margin: 0;
}

.topbar-search {
    flex: 1 1 auto;
    max-width: 480px;
    min-width: 240px;
    margin-left: 24px;
}


.topbar-search .global-search-box .autocomplete,
.topbar-search .global-search-box {
    width: 100%;
    position: relative;
}

.topbar-search .global-search-box input {
    background-color: var(--color-surface);
    border-color: #cbd5e1;
}

.topbar-search .global-search-box input:focus {
    background-color: var(--color-surface);
    border-color: var(--color-brand);
    box-shadow: 0 0 0 0.15rem rgba(37, 99, 235, 0.15);
}

/* Suggestions dropdown: at least the input width, but allowed to grow wider for legibility */
.topbar-search .global-search-box .dropdown-menu {
    min-width: 100%;
    width: max-content;
    max-width: min(640px, calc(100vw - 32px));
    overflow-x: hidden;
}

.topbar-search .global-search-box .dropdown-menu .dropdown-item {
    overflow: hidden;
}

/* Allow flex children to shrink so the inner ellipsis works */
.topbar-search .global-search-box .dropdown-menu .dropdown-item > div,
.topbar-search .global-search-box .dropdown-menu .dropdown-item > div > div {
    min-width: 0;
}

/* Truncate any long line inside each suggestion row */
.topbar-search .global-search-box .dropdown-menu .dropdown-item small {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* Product category chip filter bar (Tested Product Library) */
.category-chip-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 14px;
}

.category-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    background: var(--color-surface);
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-pill);
    font-size: var(--font-base);
    font-weight: var(--weight-medium);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: background-color var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
}

.category-chip:hover {
    border-color: var(--chip-color, var(--color-text-faint));
    color: var(--chip-color, var(--color-text-muted));
}

.category-chip.active {
    background: var(--chip-color, var(--color-text-muted));
    border-color: var(--chip-color, var(--color-text-muted));
    color: #fff;
}

.category-chip.active .chip-dot {
    background: #fff;
}

.chip-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--chip-color, var(--color-text-faint));
    flex: 0 0 auto;
}

.category-count {
    font-size: var(--font-xs);
    color: inherit;
    opacity: 0.75;
    margin-left: 2px;
}

/* Per-row category badge inside the grid */
.category-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 9px;
    border-radius: var(--radius-pill);
    background: var(--color-surface-subtle);
    color: var(--chip-color, var(--color-text-muted));
    font-size: var(--font-sm);
    font-weight: var(--weight-semibold);
    border: 1px solid var(--color-border-strong);
    white-space: nowrap;
}

/* ============================================================
   Status text — inline status indicator with icon + label
   (CardHeader: Ready / N incomplete / Saved h:mm tt)
   ============================================================ */

.status-text {
    display: inline-flex;
    align-items: center;
    font-size: var(--font-sm);
    font-weight: var(--weight-medium);
    color: var(--color-text-subtle);
}

.status-text--success { color: var(--color-success); }
.status-text--warning { color: var(--color-warning-strong); }
.status-text--muted {
    color: var(--color-text-subtle);
    font-weight: var(--weight-normal);
}

/* Inline parent-project link inside a report edit card header */
.parent-project-link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-left: 12px;
    padding: 2px 8px;
    font-size: var(--font-sm);
    font-weight: var(--weight-medium);
    color: var(--color-brand);
    text-decoration: none;
    border-radius: var(--radius-md);
    transition: background-color var(--transition-fast);
}

.parent-project-link:hover {
    background-color: var(--color-surface-subtle);
    color: var(--color-brand-hover);
    text-decoration: none;
}

.parent-project-link i {
    font-size: 12px;
}

/* ============================================================
   Type pill — coloured badge identifying the report/project type
   in edit page headers, paired with a coloured left bar on the card
   ============================================================ */

.type-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 11px;
    border-radius: 999px;
    font-size: var(--font-sm);
    font-weight: var(--weight-semibold);
    color: #fff;
    white-space: nowrap;
    line-height: 1.2;
    margin-right: 10px;
    vertical-align: middle;
}

.type-pill i {
    font-size: 0.9em;
}

/* Per-attribute mismatch indicator (TestedSystemEditForm). Sits beside the
   FieldLabel text and shows a tooltip explaining the baseline requirement. */
.field-mismatch-icon {
    color: #dc3545;
    margin-left: 6px;
    font-size: 0.9em;
    cursor: help;
}

/* Summary strip at the top of a section listing all attributes that don't
   match the baseline. Each pill is one mismatched attribute. */
.section-mismatch-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 0 0 14px 0;
    padding: 10px 14px;
    background-color: rgba(220, 53, 69, 0.08);
    border: 1px solid rgba(220, 53, 69, 0.3);
    border-radius: 6px;
    font-size: 0.85rem;
}

.section-mismatch-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
    color: #dc3545;
    margin-right: 4px;
}

.section-mismatch-pill {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    padding: 3px 10px;
    background-color: var(--color-surface);
    border: 1px solid rgba(220, 53, 69, 0.35);
    border-radius: 999px;
    color: #dc3545;
    font-weight: 500;
    line-height: 1.3;
}

.section-mismatch-pill .pill-req {
    color: var(--color-text-muted);
    font-weight: 400;
}

/* Baseline match-count badge on each system row (FacadeEdit systems list).
   Shows "X/Y" where X = matched attributes, Y = baseline-specified attributes. */
.baseline-score {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.85rem;
    font-weight: 600;
    white-space: nowrap;
}

.baseline-score--full {
    color: var(--color-success);
}

.baseline-score--partial {
    color: #dc3545;
}

/* ============================================================
   Facade comparison grid - attribute rows x system columns
   ============================================================ */

.compare-toolbar {
    margin-bottom: 12px;
}

.compare-grid-wrap {
    overflow-x: auto;
    border: 1px solid var(--color-border);
    border-radius: 8px;
}

.compare-grid {
    border-collapse: separate;
    border-spacing: 0;
    width: 100%;
    font-size: 0.875rem;
}

.compare-grid th,
.compare-grid td {
    padding: 8px 14px;
    text-align: left;
    white-space: nowrap;
    border-bottom: 1px solid var(--color-border);
}

.compare-grid thead th {
    background: var(--color-surface-subtle);
    font-weight: 600;
    position: sticky;
    top: 0;
    z-index: 2;
}

/* Sticky first two columns so Attribute + Baseline stay visible while scrolling systems */
.compare-attr-col {
    position: sticky;
    left: 0;
    width: 190px;
    min-width: 190px;
    background: var(--color-surface);
    font-weight: 600;
    z-index: 1;
}

.compare-baseline-col {
    position: sticky;
    left: 190px;
    width: 150px;
    min-width: 150px;
    background: var(--color-surface-subtle);
    font-weight: 500;
    box-shadow: 1px 0 0 var(--color-border);
}

.compare-grid thead .compare-attr-col,
.compare-grid thead .compare-baseline-col {
    z-index: 3;
}

.compare-sys-col {
    min-width: 110px;
}

.compare-score-row td {
    background: var(--color-surface-emphasis);
    font-weight: 700;
}

.compare-cell--ok {
    color: var(--color-success);
}

.compare-cell--fail {
    color: #dc3545;
    font-weight: 600;
}

/* Identity rows (Reference ID, Description) at the top of the compare grid -
   not baseline comparisons, so neutral weight and allowed to wrap (Description
   can be long) within a capped width instead of the default nowrap. */
.compare-grid td.compare-meta-cell {
    white-space: normal;
    overflow-wrap: anywhere;
    max-width: 240px;
    vertical-align: top;
    font-weight: 400;
}

.page-title-with-pill {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

/* ============================================================
   Empty state — unified "no results" pattern
   ============================================================ */

.empty-state {
    text-align: center;
    color: var(--color-text-faint);
    font-size: var(--font-base);
    padding: 24px 16px;
    line-height: var(--line-relaxed);
}

/* ============================================================
   Form-field primitives
   ------------------------------------------------------------
   .field-required  — add to a FieldLabel to append a red *
   .field-error     — apply to a FieldLabel when validation fails
                      (turns label and the * red)
   .field-help      — small helper text shown below an input
   .field-error-message — validation feedback shown below an input
   ============================================================ */

.field-required::after {
    content: " *";
    color: var(--color-danger);
    font-weight: var(--weight-semibold);
}

.field-error,
.field-error.field-required::after {
    color: var(--color-danger);
}

.field-help {
    display: block;
    margin-top: 2px;
    font-size: var(--font-sm);
    color: var(--color-text-faint);
    line-height: var(--line-snug);
}

.field-error-message {
    display: block;
    margin-top: 2px;
    font-size: var(--font-sm);
    color: var(--color-danger);
    line-height: var(--line-snug);
}

/* ============================================================
   System Editor side-nav layout
   - Used on the Facade Report Tested Systems tab to navigate
     between sections of the selected system without nested
     accordions or tabs.
   - Desktop (>= 992px): vertical rail on the left, content on
     the right.
   - Below 992px: horizontal scrollable strip stacked above the
     content so the form stays usable on narrow screens.
   ============================================================ */

.system-editor {
    display: grid;
    grid-template-columns: 200px minmax(0, 1fr);
    gap: 1.5rem;
    align-items: start;
}

.system-editor-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0.25rem;
    background: var(--color-surface-subtle);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    position: sticky;
    top: 1rem;
}

.system-editor-nav-item {
    appearance: none;
    background: transparent;
    border: 0;
    border-radius: var(--radius-sm);
    padding: 0.45rem 0.75rem;
    text-align: left;
    font-size: var(--font-sm);
    color: var(--color-text-label);
    cursor: pointer;
    line-height: var(--line-snug);
    white-space: nowrap;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.system-editor-nav-item-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.system-editor-nav-item-dot {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--color-danger);
    box-shadow: 0 0 0 2px var(--color-surface-subtle);
}

.system-editor-nav-item.active .system-editor-nav-item-dot {
    /* Keep the dot legible on the brand-blue active background. */
    box-shadow: 0 0 0 2px var(--color-brand);
}

.system-editor-nav-item:hover {
    background: var(--color-surface);
    color: var(--color-text-strong);
}

.system-editor-nav-item:focus-visible {
    outline: 2px solid var(--color-brand);
    outline-offset: 1px;
}

.system-editor-nav-item.active {
    background: var(--color-brand);
    color: var(--color-text-on-brand);
    font-weight: var(--weight-semibold);
}

.system-editor-nav-item.active:hover {
    background: var(--color-brand-hover);
    color: var(--color-text-on-brand);
}

.system-editor-nav-divider {
    height: 1px;
    margin: 0.4rem 0.25rem;
    background: var(--color-border-strong);
}

.system-editor-content {
    min-width: 0;
}

@media (max-width: 991.98px) {
    .system-editor {
        grid-template-columns: minmax(0, 1fr);
        gap: 1rem;
    }

    .system-editor-nav {
        flex-direction: row;
        overflow-x: auto;
        position: static;
        padding: 0.25rem;
        gap: 0.25rem;
        -webkit-overflow-scrolling: touch;
    }

    .system-editor-nav-item {
        flex: 0 0 auto;
    }

    .system-editor-nav-divider {
        width: 1px;
        height: auto;
        margin: 0.25rem 0.25rem;
        align-self: stretch;
    }
}

/* ---- Project command center ---- */
.cc-identity {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: var(--font-md);
    min-width: 0;
}

.cc-identity__sep {
    color: var(--color-text-muted);
}

/* Shared column template so the header row and every data row line up. */
.cc-table {
    --cc-cols: 150px 110px 185px 110px 76px 1fr;
}

.cc-head {
    display: grid;
    grid-template-columns: var(--cc-cols);
    align-items: center;
    column-gap: 12px;
    padding: 0 8px 8px;
    border-bottom: 1px solid var(--color-border);
}

.cc-head > span {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
    color: var(--color-text-faint);
    white-space: nowrap;
}

.cc-rows {
    display: flex;
    flex-direction: column;
}

/* Fixed-column grid so type / issue / status / owner / modified line up
   vertically across every row (a per-row auto grid would size independently). */
.cc-row {
    display: grid;
    grid-template-columns: var(--cc-cols);
    align-items: center;
    column-gap: 12px;
    padding: 10px 8px;
    border-bottom: 1px solid var(--color-border);
    min-height: 48px;
}

.cc-row:last-child {
    border-bottom: none;
}

/* Report type doubles as a link to that report's editor (the Open button stays too). */
.cc-row__type {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    font-weight: 600;
    color: var(--color-text);
    text-decoration: none;
}

.cc-row__type:hover {
    color: var(--color-brand);
}

/* Underline only the label text on hover - not the type icon (an underline on the
   anchor would run under the icon too). */
.cc-row__type:hover .cc-row__type-label {
    text-decoration: underline;
}

.cc-row__issue,
.cc-row__owner {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--font-sm);
}

.cc-row__issue {
    color: var(--color-text-muted);
}

.cc-row__owner {
    color: var(--color-text);
}

.cc-row__when {
    font-size: var(--font-sm);
    color: var(--color-text-muted);
    white-space: nowrap;
}

/* Actions split into a left-anchored main group (Open + Generate) and a
   right-pinned destructive group, so "Open" lands in the same place on every
   row and Delete is visually separated from the safe actions. */
.cc-row__actions {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
}

.cc-row__actions-main {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.cc-row__actions-danger {
    margin-left: auto;
    padding-left: 12px;
    border-left: 1px solid var(--color-border);
}

.cc-row__placeholder {
    color: var(--color-text-faint);
}

/* MissingFieldsBadge carries a start margin for inline use on edit-page headers;
   inside the grid cell it should sit flush so it lines up under the Status header. */
.cc-row__badge .status-text {
    margin-left: 0 !important;
}

/* ============================================================
   Certificate run - stage indicator (Examen)
   ============================================================ */
.run-stages {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 4px 0 2px;
}

.run-stage {
    display: flex;
    align-items: center;
    gap: 8px;
}

.run-stage-marker {
    width: 28px;
    height: 28px;
    border-radius: var(--radius-pill);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--font-sm);
    font-weight: var(--weight-semibold, 600);
    background: var(--color-surface-emphasis);
    color: var(--color-text-subtle);
    border: 1px solid var(--color-border-strong);
    flex: 0 0 auto;
}

.run-stage.done .run-stage-marker {
    background: var(--color-success);
    border-color: var(--color-success);
    color: var(--color-text-on-brand);
}

.run-stage.current .run-stage-marker {
    background: var(--color-brand);
    border-color: var(--color-brand);
    color: var(--color-text-on-brand);
}

.run-stage-label {
    font-size: var(--font-base);
    color: var(--color-text-subtle);
    white-space: nowrap;
}

.run-stage.done .run-stage-label {
    color: var(--color-text-muted);
}

.run-stage.current .run-stage-label {
    color: var(--color-text-strong);
    font-weight: var(--weight-semibold, 600);
}

.run-stage-connector {
    flex: 0 0 22px;
    height: 2px;
    background: var(--color-border-strong);
    border-radius: 1px;
}

.run-stage-connector.done {
    background: var(--color-success);
}

/* ---- PDF.js consent viewer ---- */

.pdf-viewer-host {
    height: 85vh;
    overflow: auto;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    background: var(--color-surface-subtle);
    padding: 8px 0;
}

.pdf-viewer-page {
    margin: 12px auto;
    background: #fff;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}

.pdf-viewer-page canvas {
    display: block;
}

/* Two-line truncation for long grid text; full text via title tooltip. */
.clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Disabled controls must read as disabled - the ported button styles set their
   own backgrounds, which overrode Bootstrap's dimming. */
.btn:disabled,
.btn.disabled,
fieldset:disabled .btn {
    opacity: .5;
    cursor: not-allowed;
    box-shadow: none;
}

/* ---- Bulk evidence modal ---- */

.bulk-pane {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.bulk-pane-divided {
    border-left: 1px solid var(--color-border);
    padding-left: 1.5rem;
}

@media (max-width: 991.98px) {
    .bulk-pane-divided { border-left: none; padding-left: 0; }
}

.bulk-pane-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem;
    padding-bottom: .5rem;
    border-bottom: 1px solid var(--color-border);
}

.bulk-pane-title {
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--color-text-faint);
    margin-right: auto;
}

.bulk-list {
    overflow-y: auto;
    max-height: 52vh;
    margin-top: .15rem;
}

.bulk-row {
    display: flex;
    align-items: flex-start;
    gap: .7rem;
    padding: .6rem .35rem;
    border-bottom: 1px solid var(--color-border);
    border-radius: 3px;
}

.bulk-row:last-child { border-bottom: none; }
.bulk-row:hover { background: var(--color-surface-subtle); }

.bulk-row.is-selected {
    background: color-mix(in srgb, var(--color-brand) 8%, transparent);
}

.bulk-row .form-check { margin: .1rem 0 0; }

.bulk-row-body { flex: 1 1 auto; min-width: 0; }

.bulk-row-title {
    display: block;
    line-height: 1.35;
}

.bulk-meta {
    display: block;
    font-size: .8rem;
    color: var(--color-text-faint);
    margin-top: .12rem;
}

.bulk-count {
    flex: none;
    font-size: .82rem;
    white-space: nowrap;
    padding-top: .1rem;
}

/* Wider than Blazorise's ExtraLarge: this screen is a working surface. */
.modal .modal-dialog.bulk-dialog {
    max-width: min(1240px, 94vw);
}

/* Snackbar messages carry document names and counts - they must wrap rather
   than run off the edge. */
.snackbar {
    max-width: min(560px, 92vw);
}

/* A message is only ever read, never clicked - so it must never take a click meant for what is
   under it. Sat bottom-centre, it covered a popup's Save button exactly when it mattered: after a
   save was refused, the next click only dismissed the warning. And while a popup is open the
   messages move to the top, so the Save button stays in sight as well as in reach. */
.snackbar-stack-bottom,
.snackbar-stack-bottom .snackbar {
    pointer-events: none;
}

body.modal-open .snackbar-stack-bottom {
    bottom: auto;
    top: 2.5rem;
}

/* Blazorise's own snackbar stylesheet loads after this one and sets nowrap +
   ellipsis on .snackbar-body, so these need the extra specificity to win. */
.snackbar .snackbar-body,
.snackbar-stack .snackbar-body {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: anywhere;
    line-height: 1.4;
}

/* The browser owns a file input's "No file chosen" text and it cannot be
   rewritten - it goes stale the moment the input is read and reset, sitting
   beside the app's own line saying which file it has. Every FileEdit here
   reports its selection itself, so the native text is hidden rather than
   left to contradict it. The Choose file button keeps its own colour. */
input[type="file"] {
    color: transparent;
}

/* The overview strip: the numbers are the links, so they wear the link colour and
   answer on hover - a link dressed as body text is a link nobody finds. */
.stat-link { text-decoration: none; }
.stat-link .stat-number { font-size: 1.9rem; font-weight: 600; color: var(--bs-primary); }
.stat-link:hover .stat-number { text-decoration: underline; }

/* ============================================================
   Ported from Keystone's 2026-08 UI modernization: spin util,
   top bar row + utility cluster, and the sectioned nav rail.
   Token-driven throughout - both apps share the token layer.
   ============================================================ */
/* Base properties for any ti-* class, so a glyph works no matter how Blazorise
   assembles the class list: its Icon component emits e.g. "fas ti-plus" without
   the .ti base class, which resolves the codepoint but leaves the element in the
   body font - a tofu box. The stray "fas" is inert with FontAwesome css gone. */
[class^="ti-"], [class*=" ti-"] {
    font-family: 'tabler-icons' !important;
    speak: none;
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

@keyframes ti-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .ti-spin { animation-duration: 2.5s; }
}
.b-layout-header .topbar-row,
.b-layout-header .topbar-row .b-bar-item {
    width: 100%;
    flex: 1 1 auto;
}

.topbar-row-inner {
    display: flex;
    align-items: center;
    width: 100%;
    /* Both edges align with the content inset below (LayoutContent runs
       Padding.Is4.OnX): right so the avatar meets the cards' edge, left so
       the search trigger doesn't hug the sidebar separator. */
    padding-left: 16px;
    padding-right: 16px;
}
/* ============================================================
   Nav rail (2026-08 redesign) — sectioned sidebar, light in light
   mode (Auth0-style single surface) and darker-than-content in
   dark mode. The :has(.nav-rail) guards keep every rule inert
   while Ui:UseClassicNav renders the old Bar instead.
   ============================================================ */

.b-layout-sider:has(.nav-rail),
.b-layout-sider:has(.nav-rail) .b-layout-sider-content {
    background: var(--color-surface-app) !important;
}

.b-layout-sider:has(.nav-rail) {
    border-right: 1px solid var(--color-border);
}

:root[data-theme="dark"] .b-layout-sider:has(.nav-rail),
:root[data-theme="dark"] .b-layout-sider:has(.nav-rail) .b-layout-sider-content {
    background: var(--color-surface-sidebar) !important;
}

.nav-rail {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 10px 8px 16px 8px;
    overflow-y: auto;
    min-width: 230px;
}

.nav-rail-brand {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 4px 10px 12px 10px;
    font-size: 15px;
    font-weight: var(--weight-semibold);
    color: var(--color-text);
    text-decoration: none;
    letter-spacing: var(--letter-tight);
}

.nav-rail-brand:hover { color: var(--color-text); }

.nav-rail-logo { width: 28px; height: 28px; }

.nav-rail-section {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    font-size: var(--font-xs);
    letter-spacing: var(--letter-wider);
    text-transform: uppercase;
    font-weight: var(--weight-semibold);
    color: var(--color-text-subtle);
    padding: 14px 10px 4px 10px;
    background: transparent;
    border: none;
    text-align: left;
}

.nav-rail-section i { font-size: 13px; }

.nav-rail-section-toggle { cursor: pointer; border-radius: var(--radius-md); }

.nav-rail-section-toggle:hover { color: var(--color-text-header); }

.nav-rail-item {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: var(--font-base);
    font-weight: var(--weight-medium);
    color: var(--color-text-header);
    text-decoration: none;
    padding: 6px 10px;
    border-radius: var(--radius-md);
    white-space: nowrap;
    transition: background-color var(--transition-fast), color var(--transition-fast);
}

.nav-rail-item i {
    font-size: 16px;
    width: 18px;
    text-align: center;
    flex: 0 0 auto;
}

.nav-rail-item:hover {
    background: var(--color-surface-subtle);
    color: var(--color-text);
    text-decoration: none;
}

.nav-rail-item.active {
    background: rgba(37, 99, 235, 0.10);
    color: var(--color-brand-hover);
}

.nav-rail-item-solo { margin-top: 14px; }

:root[data-theme="dark"] .nav-rail-item { color: #cbd5e1; }
:root[data-theme="dark"] .nav-rail-item:hover { background: rgba(255, 255, 255, 0.06); color: #f1f5f9; }
:root[data-theme="dark"] .nav-rail-item.active { background: rgba(37, 99, 235, 0.30); color: #fff; }

/* Off-canvas below tablet width: the rail slides in over the content,
   toggled by the hamburger in the top bar (html.nav-open). */
.nav-rail-mobile-toggle {
    display: none;
    width: 34px;
    height: 34px;
    border: none;
    background: transparent;
    border-radius: var(--radius-md);
    color: var(--color-text-muted);
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    margin-right: 8px;
}

.nav-rail-mobile-toggle i { font-size: 19px; }

@media (max-width: 767.98px) {
    .nav-rail-mobile-toggle { display: inline-flex; }

    .b-layout-sider:has(.nav-rail) {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        width: 248px;
        z-index: 1300;
        transform: translateX(-100%);
        transition: transform 0.2s ease;
        box-shadow: none;
    }

    :root.nav-open .b-layout-sider:has(.nav-rail) {
        transform: translateX(0);
        box-shadow: 0 10px 40px rgba(15, 23, 42, 0.35);
    }

    @media (prefers-reduced-motion: reduce) {
        .b-layout-sider:has(.nav-rail) { transition: none; }
    }
}

/* ---- Desktop collapse (:root.nav-collapsed) ----
   The rail folds to a 16px strip and the content takes the width; hovering
   the strip (or tabbing into it) peeks the full rail OVER the content, and
   clicking anything that says so pins it back open. Same class-on-<html>
   mechanic as the phone off-canvas above, but persisted per browser
   (examen-nav-collapsed, applied pre-paint in App.razor so a remembered
   collapse never shifts the page after load). Scoped to >=768px: phones keep
   the hamburger behaviour untouched. Default is expanded - nobody meets the
   collapsed rail by surprise. */

.nav-rail-head { display: flex; align-items: flex-start; }
.nav-rail-head .nav-rail-brand { flex: 1 1 auto; min-width: 0; }

.nav-rail-collapse,
.nav-rail-pin {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    margin: 4px 2px 0 0;
    padding: 0;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    color: var(--color-text-subtle);
    font-size: 12px;
    cursor: pointer;
    transition: color var(--transition-fast), border-color var(--transition-fast);
}

.nav-rail-collapse:hover,
.nav-rail-pin:hover { color: var(--color-text); border-color: var(--color-border-strong); }

/* Pin only exists while peeking a collapsed rail; the strip only while collapsed.
   Both are display-driven off :root.nav-collapsed rather than Blazor state, so a
   remembered collapse renders correctly on first paint. */
.nav-rail-pin { display: none; }
.nav-rail-strip { display: none; }

/* The collapse affordance is desktop-only; on phones the off-canvas hamburger
   already owns show/hide and this button would be a dead control. */
@media (max-width: 767.98px) {
    .nav-rail-collapse { display: none; }
}

@media (min-width: 768px) {
    :root.nav-collapsed .b-layout-sider:has(.nav-rail) {
        width: 16px;
        min-width: 16px;
        flex: 0 0 16px;
    }

    /* The rail becomes a viewport-fixed drawer. Transition delays are the whole
       peek feel: 120ms of hover intent on the way in, 250ms of forgiveness on
       the way out. */
    :root.nav-collapsed .b-layout-sider:has(.nav-rail) .nav-rail {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        z-index: 1300;
        width: 230px;
        background: var(--color-surface-app);
        border-right: 1px solid var(--color-border);
        box-shadow: 0 10px 40px rgba(15, 23, 42, 0.35);
        transform: translateX(-103%);
        transition: transform 0.18s ease 0.25s;
    }

    :root[data-theme="dark"].nav-collapsed .b-layout-sider:has(.nav-rail) .nav-rail {
        background: var(--color-surface-sidebar);
    }

    :root.nav-collapsed .b-layout-sider:has(.nav-rail):hover .nav-rail,
    :root.nav-collapsed .b-layout-sider:has(.nav-rail):focus-within .nav-rail {
        transform: translateX(0);
        transition-delay: 0.12s;
    }

    /* The 16px remnant. Viewport-fixed so Blazorise's sticky sider content can't
       clip it; sits under the drawer (1290 < 1300) so the peek covers it. */
    :root.nav-collapsed .nav-rail-strip {
        display: flex;
        align-items: center;
        justify-content: center;
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        width: 16px;
        z-index: 1290;
        padding: 0;
        border: none;
        border-right: 1px solid var(--color-border);
        background: var(--color-surface-app);
        color: var(--color-text-subtle);
        font-size: 11px;
        cursor: pointer;
    }

    :root.nav-collapsed .b-layout-sider:has(.nav-rail):hover .nav-rail-strip {
        background: var(--color-surface-subtle);
        color: var(--color-text-muted);
    }

    :root[data-theme="dark"].nav-collapsed .nav-rail-strip {
        background: var(--color-surface-sidebar);
    }

    :root.nav-collapsed .nav-rail-collapse { display: none; }
    :root.nav-collapsed .nav-rail-pin { display: flex; }

    @media (prefers-reduced-motion: reduce) {
        /* Keep the intent/forgiveness delays, drop the motion. */
        :root.nav-collapsed .b-layout-sider:has(.nav-rail) .nav-rail { transition-duration: 0s; }
    }
}

.topbar-utils {
    display: flex;
    align-items: center;
    gap: 2px;
    margin-left: 2px; /* matches the intra-cluster gap so the tray reads as one of us */
    flex: 0 0 auto;
}

.topbar-icon-btn {
    width: 34px;
    height: 34px;
    border: none;
    background: transparent;
    border-radius: var(--radius-md);
    color: var(--color-text-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background-color var(--transition-fast), color var(--transition-fast);
}

.topbar-icon-btn:hover {
    background: var(--color-surface-subtle);
    color: var(--color-text-strong);
}

/* No lingering box after a mouse click (Blazor keeps the button focused);
   keyboard focus still gets a visible ring. */
.topbar-icon-btn:focus { outline: none; }
.topbar-icon-btn:focus-visible {
    outline: none;
    box-shadow: var(--ring-brand-soft);
}

.topbar-icon-btn i {
    font-size: 18px;
}

/* Theme toggle renders both glyphs; the active theme picks which shows */
.theme-icon-when-dark { display: none; }
:root[data-theme="dark"] .theme-icon-when-light { display: none; }
:root[data-theme="dark"] .theme-icon-when-dark { display: inline-block; }

.topbar-divider {
    width: 1px;
    height: 22px;
    background: var(--color-border);
    margin: 0 6px;
    flex: 0 0 auto;
}

/* Same overlay requirement as .topbar-tray above: inside the header Bar,
   an open dropdown otherwise sits in flow and stretches the whole header. */
.topbar-utils .dropdown {
    position: relative;
}

.topbar-utils .dropdown-menu {
    position: absolute !important;
    top: calc(100% + 6px);
    right: 0;
    left: auto !important;
    z-index: 1100;
    min-width: 210px;
}

.topbar-avatar-toggle,
.topbar-avatar-toggle.btn,
.topbar-avatar-toggle:focus,
.topbar-avatar-toggle:focus-visible,
.topbar-avatar-toggle:hover {
    background: transparent !important;
    border: none !important;
    padding: 2px;
    box-shadow: none !important;
    outline: none;
}

/* Keyboard/programmatic focus shows as a halo on the avatar circle itself,
   not Bootstrap's rectangle around the button (Blazorise focuses the toggle
   when the menu opens, which lights :focus-visible even on mouse clicks). */
.topbar-avatar-toggle:focus-visible .topbar-avatar {
    box-shadow: var(--ring-brand-soft);
}

.topbar-avatar {
    width: 30px;
    height: 30px;
    border-radius: var(--radius-pill);
    background: var(--color-surface-emphasis);
    color: var(--color-text-strong);
    font-size: 12.5px;
    font-weight: var(--weight-semibold);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    letter-spacing: 0.02em;
    transition: box-shadow var(--transition-fast);
}

.topbar-avatar-toggle:hover .topbar-avatar {
    box-shadow: 0 0 0 3px var(--color-surface-subtle);
}

.topbar-avatar-name {
    padding: 8px 16px 4px 16px;
    font-size: var(--font-sm);
    font-weight: var(--weight-medium);
    color: var(--color-text-muted);
    white-space: nowrap;
}

/* The top bar has no search yet (the command palette is next); the spacer
   pushes the utility cluster to the right edge on its own. */
.topbar-spacer { margin-left: auto; }

/* Blazorise's Icon Spin emits fa-spin; with FontAwesome css unloaded the
   class is bare, so it drives the same keyframes as ti-spin. */
.fa-spin, .ti-spin { display: inline-block; animation: ti-spin 1s linear infinite; }

/* ============================================================
   Command palette (B2) - portable shell styles. Token-driven,
   so dark mode needs no extra rules beyond the backdrop.
   ============================================================ */

.palette-trigger {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 240px;
    border: 1px solid var(--color-border-input);
    background: var(--color-surface);
    color: var(--color-text-subtle);
    border-radius: var(--radius-md);
    font-size: var(--font-base);
    padding: 6px 10px;
    cursor: pointer;
    transition: border-color var(--transition-fast), color var(--transition-fast);
}

.palette-trigger:hover { border-color: var(--color-border-strong); color: var(--color-text-muted); }
.palette-trigger i { font-size: 15px; }
.palette-trigger span { flex: 1 1 auto; text-align: left; }

.search-kbd-inline {
    border: 1px solid var(--color-border-strong);
    background: var(--color-surface-app);
    color: var(--color-text-subtle);
    border-radius: 5px;
    font-size: 10.5px;
    font-weight: var(--weight-medium);
    padding: 1px 6px;
    white-space: nowrap;
}

@media (max-width: 767.98px), (hover: none) {
    .search-kbd-inline { display: none; }
    .palette-trigger { min-width: 0; }
    .palette-trigger span { display: none; }
    /* Nothing to press on a touch screen: no esc badge, no key legend. The footer's own
       rule (display: flex) sits later in this file, so this one outranks it by specificity. */
    .palette-input-row kbd { display: none; }
    .palette-panel .palette-foot { display: none; }
}

.palette-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1400;
    background: rgba(15, 23, 42, 0.45);
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 12vh 16px 16px;
}

.palette-panel {
    width: 100%;
    max-width: 560px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 12px;
    box-shadow: var(--shadow-card);
    overflow: hidden;
    animation: palette-in 0.12s ease-out;
}

@keyframes palette-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .palette-panel { animation: none; }
}

.palette-input-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--color-border);
    color: var(--color-text-subtle);
}

.palette-input-row i { font-size: 17px; }

.palette-input-row input {
    flex: 1 1 auto;
    border: none;
    outline: none;
    background: transparent;
    color: var(--color-text);
    font-size: var(--font-md);
}

.palette-input-row input::placeholder { color: var(--color-text-faint); }

.palette-input-row kbd,
.palette-foot kbd {
    border: 1px solid var(--color-border-strong);
    background: var(--color-surface-app);
    color: var(--color-text-subtle);
    border-radius: 5px;
    font-size: 10.5px;
    padding: 1px 6px;
}

.palette-results {
    max-height: 48vh;
    overflow-y: auto;
    padding: 6px;
}

.palette-empty {
    padding: 22px 14px;
    text-align: center;
    color: var(--color-text-subtle);
    font-size: var(--font-base);
}

.palette-group-label {
    font-size: var(--font-xs);
    letter-spacing: var(--letter-wider);
    text-transform: uppercase;
    font-weight: var(--weight-semibold);
    color: var(--color-text-subtle);
    padding: 10px 10px 4px 10px;
}

.palette-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    border: none;
    background: transparent;
    text-align: left;
    color: var(--color-text-header);
    font-size: var(--font-base);
    padding: 7px 10px;
    border-radius: var(--radius-md);
    cursor: pointer;
}

.palette-item i { font-size: 16px; width: 18px; text-align: center; flex: 0 0 auto; color: var(--color-text-subtle); }
.palette-item.active { background: var(--color-surface-subtle); color: var(--color-text); }
.palette-item.active i { color: var(--color-brand); }

.palette-item-title { flex: 0 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.palette-item-subtitle {
    flex: 1 1 auto;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--color-text-subtle);
    font-size: var(--font-sm);
    text-align: right;
}

.palette-foot {
    display: flex;
    gap: 14px;
    padding: 8px 14px;
    border-top: 1px solid var(--color-border);
    color: var(--color-text-subtle);
    font-size: var(--font-xs);
}

/* ============================================================
   Pill tabs - a row of choices that doubles as a summary, with an
   optional count. The worklist's kinds, and Activity's two feeds.
   ============================================================ */

.pill-tab {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px 12px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-pill);
    font-size: var(--font-base);
    font-weight: var(--weight-medium);
    color: var(--color-text-muted);
    cursor: pointer;
    transition: border-color var(--transition-fast), color var(--transition-fast);
}

.pill-tab:hover { border-color: var(--color-border-strong); color: var(--color-text); }

.pill-tab.active {
    border-color: var(--color-brand);
    color: var(--color-brand);
    background: color-mix(in srgb, var(--color-brand) 8%, transparent);
}

.pill-tab i { font-size: 15px; }

.pill-tab-count {
    font-variant-numeric: tabular-nums;
    font-weight: var(--weight-semibold);
    color: var(--color-text-subtle);
}

.pill-tab.active .pill-tab-count { color: var(--color-brand); }

/* ============================================================
   Validity markers - a checklist read one row at a time, so each
   row needs room around it and its evidence set apart from the
   words about it. Dense rows made a complete document look alarming.
   ============================================================ */

.marker-rows {
    display: flex;
    flex-direction: column;
}

.marker-row {
    display: grid;
    grid-template-columns: 5.5rem minmax(0, 1fr) 8.5rem;
    gap: 18px;
    align-items: start;
    padding: 14px 2px;
    border-top: 1px solid var(--color-border);
}

.marker-row:first-child { border-top: 0; padding-top: 4px; }

.marker-row-label {
    font-size: var(--font-md);
    font-weight: var(--weight-medium);
    color: var(--color-text);
}

/* The words the document actually carried: set apart, because it is the
   evidence and not the commentary. */
.marker-row-evidence {
    margin-top: 7px;
    padding: 7px 10px;
    border-left: 2px solid var(--color-border-strong);
    background: var(--color-surface-app);
    border-radius: var(--radius-sm);
    font-family: var(--bs-font-monospace, ui-monospace, monospace);
    font-size: var(--font-sm);
    color: var(--color-text-muted);
    line-height: 1.5;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.marker-row-detail {
    margin-top: 7px;
    font-size: var(--font-base);
    color: var(--color-text-muted);
    line-height: 1.55;
}

/* Why it matters - present on a row that is not carried, and quieter than
   the finding itself. */
.marker-row-why {
    margin-top: 5px;
    font-size: var(--font-sm);
    color: var(--color-text-subtle);
    line-height: 1.5;
}

.marker-row-how {
    font-size: var(--font-sm);
    color: var(--color-text-subtle);
    text-align: right;
    line-height: 1.5;
    padding-top: 2px;
}

.marker-row-badge { padding-top: 1px; }

/* ============================================================
   A consent condition as the instrument set it out. The extractor
   captures nested lists and tables; this is what lets them read
   like the document rather than one flattened paragraph.
   ============================================================ */

.condition-body {
    font-size: var(--font-md);
    line-height: 1.6;
    color: var(--color-text);
}

.condition-body > :first-child { margin-top: 0; }
.condition-body > :last-child { margin-bottom: 0; }

.condition-body p { margin: 0 0 10px; }

.condition-body ul,
.condition-body ol {
    margin: 0 0 10px;
    padding-left: 22px;
}

/* Nested lists sit closer than the level above them, which is how a
   consent's (a)(i) structure reads on paper. */
.condition-body li { margin-bottom: 4px; }

/* An instrument labels its own sub-paragraphs - a., (b), ii. - and those labels are how a
   sub-paragraph is cited, so they are kept as text and the marker the browser would draw
   beside them is turned off. The negative indent hangs the label in the margin, so wrapped
   lines line up under the words rather than under the label. */
.condition-body ul.labelled {
    list-style: none;
    padding-left: 1.9rem;
}

.condition-body ul.labelled > li { text-indent: -1.9rem; }
.condition-body ul.labelled ul.labelled { padding-left: 1.9rem; }
.condition-body li > ul,
.condition-body li > ol { margin: 5px 0 0; }

.condition-body code {
    font-family: var(--bs-font-monospace, ui-monospace, monospace);
    font-size: var(--font-sm);
    background: var(--color-surface-app);
    padding: 1px 4px;
    border-radius: var(--radius-sm);
}

.condition-table {
    width: 100%;
    margin: 4px 0 12px;
    border-collapse: collapse;
    font-size: var(--font-base);
}

.condition-table th,
.condition-table td {
    border: 1px solid var(--color-border);
    padding: 6px 9px;
    text-align: left;
    vertical-align: top;
}

.condition-table th {
    background: var(--color-surface-app);
    font-weight: var(--weight-semibold);
}

/* No markdown to render - an older extraction, or a condition somebody
   rewrote by hand - so the plain text, wrapped as it always was. */
.condition-body-plain {
    white-space: pre-wrap;
    font-family: inherit;
    font-size: var(--font-md);
    line-height: 1.6;
    margin: 0;
}

/* ============================================================
   Register group headings. The count is the point: a person who
   grouped by discipline came for "how many of these are still
   undetermined", not for the discipline's name.
   ============================================================ */

.register-group {
    display: inline-flex;
    align-items: baseline;
    gap: 10px;
}

.register-group-count {
    font-size: var(--font-sm);
    font-weight: var(--weight-normal);
    color: var(--color-text-subtle);
    font-variant-numeric: tabular-nums;
}

/* ============================================================
   The document review queue. A list to work through rather than a
   grid to scan: the file, what it is, and what is outstanding on it.
   ============================================================ */

.review-queue {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.review-queue-item {
    display: flex;
    flex-direction: column;
    gap: 3px;
    width: 100%;
    text-align: left;
    padding: 9px 10px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: background var(--transition-fast), border-color var(--transition-fast);
}

.review-queue-item:hover { background: var(--color-surface-app); }

.review-queue-item.active {
    background: color-mix(in srgb, var(--color-brand) 8%, transparent);
    border-color: var(--color-brand);
}

.review-queue-name {
    font-size: var(--font-base);
    color: var(--color-text);
    /* A handover file name is prose and runs long; two lines, then elide. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.review-queue-meta {
    display: flex;
    gap: 8px;
    align-items: center;
    font-size: var(--font-sm);
    color: var(--color-text-subtle);
}

.review-queue-state { font-weight: var(--weight-medium); }
.review-queue-state.ok { color: var(--color-success, #15803d); }
.review-queue-state.bad { color: var(--color-danger, #b91c1c); }
.review-queue-state.pending { color: var(--color-warning-text, #a16207); }
.review-queue-state.run { color: var(--color-brand); }

/* Set once at the top of a sitting: which kind, which job. */
.review-queue-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    padding: 8px 10px 4px;
    border-bottom: 1px solid var(--color-border);
}

.review-queue-chip {
    font-size: var(--font-sm);
    padding: 3px 9px;
    border-radius: 999px;
    border: 1px solid var(--color-border);
    background: transparent;
    color: var(--color-text-subtle);
    cursor: pointer;
    transition: background var(--transition-fast), border-color var(--transition-fast);
}

.review-queue-chip:hover { background: var(--color-surface-app); }

.review-queue-chip.active {
    border-color: var(--color-brand);
    color: var(--color-brand);
    background: color-mix(in srgb, var(--color-brand) 8%, transparent);
}

.review-queue-chip-count { opacity: .7; margin-left: 3px; }

.review-queue-project {
    margin-left: auto;
    font-size: var(--font-sm);
    padding: 3px 6px;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
    background: var(--color-surface);
    color: var(--color-text);
    max-width: 14rem;
}

/* ============================================================
   The words that produced a suggested requirement. Quiet and
   indented: it is the evidence for the row above it, not a
   second row.
   ============================================================ */

.deliverable-quote {
    margin-left: 26px;
    padding-left: 10px;
    border-left: 2px solid var(--color-border-strong);
    font-size: var(--font-sm);
    color: var(--color-text-muted);
    line-height: 1.5;
    max-width: 78ch;
}

/* ── Checklist setup: the facts, what follows from them, and the draft ────────────────
   Three states have to look different at a glance, because "no" is set from evidence and
   "not known yet" is the absence of it, and a certifier reading a screen of forty facts is
   looking for the ones nobody has answered. */
.fact-chips { display:flex; flex-wrap:wrap; gap:6px; }
.fact-chip, .tag-chip, .tri-btn {
    font: inherit; font-size: var(--font-sm); line-height:1.4; cursor:pointer;
    padding:3px 10px; border-radius:999px; border:1px solid var(--color-border-input);
    background: var(--color-surface); color: var(--color-text-subtle);
}
.fact-chip:hover, .tag-chip:hover, .tri-btn:hover { border-color: var(--color-brand); color: var(--color-brand); }
.fact-chip:disabled, .tag-chip:disabled, .tri-btn:disabled { cursor:default; opacity:.6; }
.fact-chip.on, .tag-chip.on { background: var(--color-brand); border-color: var(--color-brand); color:#fff; }
.fact-chip.clear { border-style:dashed; }
.fact-tri { display:flex; flex-wrap:wrap; gap:6px; }
.tri-btn.yes.on { background: var(--color-success); border-color: var(--color-success); color:#fff; }
/* No is a positive answer and reads as one: filled and solid, nothing like the dashed outline
   of a fact nobody has answered. Filled from the surface scale rather than from the text colour,
   so it stays legible when the theme inverts. */
.tri-btn.no.on { background: var(--color-surface-emphasis); border-color: var(--color-text-subtle); color: var(--color-text); font-weight:600; }
.tri-btn.on:not(.yes):not(.no):not(.unknown) { background: var(--color-brand); border-color: var(--color-brand); color:#fff; }
.tri-btn.unknown { border-style:dashed; }
.tri-btn.unknown.on { border-style:dashed; border-color: var(--color-warning); color: var(--color-warning); background: transparent; }
.tri-btn.clear { border-style:dashed; }
.fact-number { display:flex; gap:6px; align-items:center; max-width:22rem; }
.fact-finer { margin:-4px 0 12px 18px; padding-left:12px; border-left:2px solid var(--color-border); }
.tag-group { margin-bottom:10px; }
.tag-group-name {
    font: inherit; font-size: var(--font-sm); cursor:pointer; background:none; border:none; padding:0 0 4px;
    color: var(--color-text-subtle); display:flex; gap:8px; align-items:baseline;
}
.tag-group-name:hover { color: var(--color-brand); }
.tag-group-name.all { color: var(--color-brand); font-weight:600; }
.tag-group-name.some { color: var(--color-brand); }
.tag-count { font-size: var(--font-sm); opacity:.75; }

/* The counts and the one action that writes, kept in view while the facts scroll past. */
.checklist-summary {
    position: sticky; top: 0; z-index: 20;
    display:flex; flex-wrap:wrap; gap:6px 16px; align-items:center;
    margin-top: 12px; padding: 10px 16px;
    background: var(--color-surface); border:1px solid var(--color-border-strong); border-radius: var(--radius-md);
    box-shadow: var(--shadow-sticky);
}
.checklist-counts { color: var(--color-text); }
.checklist-move { color: var(--color-text-subtle); font-size: var(--font-sm); }

.derived-list { display:flex; flex-direction:column; }
.derived-row { display:grid; grid-template-columns: minmax(9rem, auto) auto; gap:2px 10px; padding:7px 0; border-bottom:1px solid var(--color-border); }
.derived-row:last-child { border-bottom:none; }
.derived-label { color: var(--color-text-subtle); font-size: var(--font-sm); }
.derived-value { color: var(--color-text); font-weight:600; font-size: var(--font-sm); }
.derived-value.unknown { color: var(--color-warning); font-weight:400; font-style:italic; }
.derived-reason { grid-column: 1 / -1; color: var(--color-text-subtle); font-size: var(--font-sm); }

.draft-row { display:flex; flex-direction:column; gap:2px; padding:7px 0; border-bottom:1px solid var(--color-border); }
.draft-line { display:flex; flex-wrap:wrap; gap:8px; align-items:baseline; }
.draft-state { font-size: var(--font-sm); padding:1px 8px; border-radius:999px; border:1px solid var(--color-border); color: var(--color-text-subtle); white-space:nowrap; }
.draft-state.always { border-color: var(--color-success); color: var(--color-success); }
.draft-state.ask { border-color: var(--color-warning); color: var(--color-warning); }
.draft-state.never { border-style:dashed; }
.draft-override {
    font: inherit; font-size: var(--font-sm); cursor:pointer; background:none; border:none; padding:0;
    color: var(--color-text-subtle); text-decoration:underline; text-underline-offset:2px;
}
.draft-override:hover { color: var(--color-brand); }
.draft-override:disabled { cursor:default; opacity:.5; }
.draft-flag { font-size: var(--font-sm); color: var(--color-text-subtle); font-style:italic; }
.draft-flag.warn { color: var(--color-warning-strong); font-style:normal; }
.draft-reason { color: var(--color-text-subtle); font-size: var(--font-sm); }
.draft-own-reason { color: var(--color-text); }

.register-row { display:flex; flex-direction:column; gap:3px; padding:8px 10px; border-bottom:1px solid var(--color-border); }
.register-title { color: var(--color-text); }
.register-meta { display:flex; flex-wrap:wrap; gap:8px; align-items:center; font-size: var(--font-sm); color: var(--color-text-subtle); }
.register-chip { padding:1px 8px; border-radius:999px; border:1px solid var(--color-border); text-decoration:none; color: var(--color-text-subtle); }
.register-chip.locked { border-color: var(--color-success, #15803d); color: var(--color-success, #15803d); }
.register-chip.open { border-color: var(--color-brand); color: var(--color-brand); }
.register-chip.none { font-style: italic; }
.register-chip.scope { border-style: dashed; color: var(--color-text-subtle); }

/* What happened to each file in the last upload. */
.upload-outcomes { margin: 4px 0 6px; padding-left: 1.1rem; font-size: var(--font-sm); }
.upload-outcome.skipped, .upload-outcome.refused, .upload-outcome.failed, .upload-outcome.warn { color: var(--color-warning-strong); }
