/* SPEC-022 Design System -- Typeface System Adoption. Four --font-* custom properties
   are the single typographic source (AC-1) -- no surface hardcodes a font-family name.
   All fallback stacks are sans-serif-only, never a serif fallback (AC-7). */
:root {
    --font-display: 'Plus Jakarta Sans', -apple-system, 'Segoe UI', Roboto, sans-serif;
    --font-body: 'Plus Jakarta Sans', -apple-system, 'Segoe UI', Roboto, sans-serif;
    --font-product: 'Public Sans', -apple-system, 'Segoe UI', Roboto, sans-serif;
    --font-accent: 'Barlow Semi Condensed', -apple-system, 'Segoe UI', Roboto, sans-serif;
}

/* Plus Jakarta Sans -- self-hosted WOFF2, v12 pinned (Google Fonts), no CDN (AC-8).
   Weights bundled: 400/600/700 -- confirmed exhaustively against every brand-surface
   selector (SPEC-022 tasks.md Task 1/Task 5); no italics in use. */
@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('/fonts/plus-jakarta-sans/plus-jakarta-sans-400.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('/fonts/plus-jakarta-sans/plus-jakarta-sans-600.woff2') format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('/fonts/plus-jakarta-sans/plus-jakarta-sans-700.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* Public Sans -- self-hosted WOFF2, v21 pinned (Google Fonts), no CDN (AC-8).
   Weights bundled: 300/400/500/600/700 (full spec.md AC-1 range -- broadest surface of
   the three families, applied to every authenticated-app selector; not narrowed by
   usage sampling). */
@font-face {
    font-family: 'Public Sans';
    src: url('/fonts/public-sans/public-sans-300.woff2') format('woff2');
    font-weight: 300;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Public Sans';
    src: url('/fonts/public-sans/public-sans-400.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Public Sans';
    src: url('/fonts/public-sans/public-sans-500.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Public Sans';
    src: url('/fonts/public-sans/public-sans-600.woff2') format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Public Sans';
    src: url('/fonts/public-sans/public-sans-700.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* Barlow Semi Condensed -- self-hosted WOFF2, v16 pinned (Google Fonts), no CDN (AC-8).
   Weights bundled: 400/500/600/700 (full spec.md AC-1 range, per PO decision -- 500 has
   zero confirmed usage across the exhaustive Task 1 sweep, but the full range is
   bundled per AC-1 rather than narrowed to only-observed weights). */
@font-face {
    font-family: 'Barlow Semi Condensed';
    src: url('/fonts/barlow-semi-condensed/barlow-semi-condensed-400.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Barlow Semi Condensed';
    src: url('/fonts/barlow-semi-condensed/barlow-semi-condensed-500.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Barlow Semi Condensed';
    src: url('/fonts/barlow-semi-condensed/barlow-semi-condensed-600.woff2') format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Barlow Semi Condensed';
    src: url('/fonts/barlow-semi-condensed/barlow-semi-condensed-700.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* SPEC-021 Design System -- Phosphor Icon Library Adoption. The <Icon> component (in
   Dredd.Components) emits every icon's <svg> with this class. Set once here so a
   replaced element (sized by width/height, vertical-align-sensitive) never shifts
   alignment inside an existing flex row, chip, sortable table header, or composer
   header the way a naive inline <svg> would (AC-4/AC-5, FR-12's regression note).
   Size itself comes from the svg width/height attributes the component emits, not
   from this class, so a call site cannot override it accidentally. */
.dredd-icon {
    display: inline-flex;
    vertical-align: middle;
    flex: 0 0 auto;
}

html, body {
    margin: 0;
    font-family: var(--font-product);
}

h1:focus {
    outline: none;
}

.content {
    padding-top: 1.1rem;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid red;
}

.validation-message {
    color: red;
}

#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

.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."
    }

.loading-progress {
    position: relative;
    display: block;
    width: 8rem;
    height: 8rem;
    margin: 20vh auto 1rem auto;
}

    .loading-progress circle {
        fill: none;
        stroke: #e0e0e0;
        stroke-width: 0.6rem;
        transform-origin: 50% 50%;
        transform: rotate(-90deg);
    }

        .loading-progress circle:last-child {
            stroke: #1b6ec2;
            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
            transition: stroke-dasharray 0.05s ease-in-out;
        }

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

    .loading-progress-text:after {
        content: var(--blazor-load-percentage-text, "Loading");
    }

code {
    color: #c02d76;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* =============================================================================
   SPEC-002 — Login page branding
   Tokens sourced from docs/planning/Justice_Portal_Style_Guide_v5.pdf §1.2-1.4.
   Layout: two-column shell with navy left pane (branding) and white right pane
   (sign-in form from SPEC-001). AC contracts enforced here are non-overrideable
   by jurisdiction data (AC-13).
   ============================================================================= */

.login-shell {
    display: flex;
    min-height: 100vh;
    background: #FFFFFF;
    font-family: var(--font-product);
}

.login-left-pane {
    flex: 0 0 55%;
    background: #1E3A5F;
    color: #FFFFFF;
    padding: 48px;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    box-sizing: border-box;
}

.login-right-pane {
    flex: 1;
    background: #FFFFFF;
    padding: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    box-sizing: border-box;
}

.branding-pane {
    display: flex;
    flex-direction: column;
    gap: 24px;
    height: 100%;
}

.branding-seal {
    width: 96px;
    height: 96px;
    object-fit: contain;
}

.court-name {
    font-family: var(--font-display);
    font-size: 20pt;
    line-height: 30px;
    font-weight: 700;
    text-transform: uppercase;
    color: #FFFFFF;
    margin: 0;
}

.sub-jurisdiction {
    font-family: var(--font-display);
    font-size: 18px;
    line-height: 26px;
    font-weight: 700;
    letter-spacing: 0.5px;
    color: #FFFFFF;
    margin: 0;
}

.hero-block {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 32px;
}

.hero-eyebrow {
    font-family: var(--font-accent);
    font-size: 11px;
    line-height: 16px;
    font-weight: 600;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #FFFFFF;
}

.hero-headline {
    font-family: var(--font-display);
    font-size: 28px;
    line-height: 36px;
    font-weight: 700;
    color: #FFFFFF;
    margin: 0;
}

.hero-description {
    font-family: var(--font-body);
    font-size: 15px;
    line-height: 22px;
    font-weight: 400;
    color: #FFFFFF;
    margin: 0;
}

.callout-list {
    list-style: none;
    padding: 0;
    margin: 16px 0 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.callout-item {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 12px;
    color: #FFFFFF;
}

.callout-item p {
    font-family: var(--font-body);
    margin: 0;
    font-size: 14px;
    line-height: 22px;
}

.branding-attribution {
    font-family: var(--font-body);
    margin-top: auto;
    font-size: 13px;
    line-height: 20px;
    color: rgba(255, 255, 255, 0.85);
}

.branding-attribution p {
    margin: 0;
}

/* =============================================================================
   SPEC-001 — Login sign-in card
   Tokens sourced from docs/planning/Justice_Portal_Style_Guide_v5.pdf §2.2
   (form inputs anatomy, button tokens, focus ring token, card surface tokens).
   ============================================================================= */

.signin-card {
    width: 100%;
    max-width: 420px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 12px;
    padding: 32px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    box-sizing: border-box;
}

.signin-card h1 {
    font-size: 22px;
    line-height: 30px;
    font-weight: 700;
    color: #1E3A5F;
    margin: 0;
}

.signin-card .form-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.signin-card .form-field label {
    font-family: var(--font-accent);
    font-size: 11px;
    line-height: 16px;
    font-weight: 600;
    letter-spacing: 0.3px;
    text-transform: uppercase;
    color: #5A6779;
}

.signin-card .form-field input {
    height: 44px;
    padding: 0 12px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 15px;
    line-height: 22px;
    color: #1E3A5F;
    background: #FFFFFF;
    box-sizing: border-box;
    font-family: inherit;
}

.signin-card .form-field input:hover {
    border-color: #8A94A6;
}

.signin-card .form-field input:focus-visible,
.signin-card .form-field input:focus {
    outline: none;
    border-color: #1E3A5F;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
}

.signin-card .form-field input:disabled {
    background: #EEF0F3;
    cursor: not-allowed;
}

.signin-card .password-input {
    position: relative;
    display: block;
}

.signin-card .password-input input {
    width: 100%;
    padding-right: 64px;
}

.signin-card .password-input button {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    background: transparent;
    border: none;
    color: #1E3A5F;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    padding: 6px 10px;
    border-radius: 4px;
    font-family: inherit;
}

.signin-card .password-input button:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
}

.signin-card .password-policy {
    font-size: 11px;
    line-height: 20px;
    font-weight: 400;
    color: #5A6779;
    margin: 4px 0 0;
}

.signin-card .signin-submit {
    width: 100%;
    height: 48px;
    background: #1E3A5F;
    color: #FFFFFF;
    border: none;
    border-radius: 6px;
    font-size: 14px;
    line-height: 18px;
    font-weight: 600;
    cursor: pointer;
    padding: 0 16px;
    margin-top: 8px;
    transition: background-color 0.15s ease;
    font-family: inherit;
}

.signin-card .signin-submit:hover {
    background: #142640;
}

.signin-card .signin-submit:focus-visible,
.signin-card .signin-submit:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
}

.signin-card .signin-submit:disabled {
    background: #C9CED8;
    cursor: not-allowed;
}

.signin-card .error-message {
    padding: 12px 16px;
    background: #FDECEC;
    border: 1px solid #B84D4D;
    border-radius: 6px;
    color: #B84D4D;
    font-size: 14px;
    line-height: 20px;
}

.signin-card .inactivity-banner {
    padding: 12px 16px;
    background: #FDF5E6;
    border: 1px solid #8A6B25;
    border-radius: 6px;
    color: #8A6B25;
    font-size: 14px;
    line-height: 20px;
}

.signin-card .validation-message {
    color: #B84D4D;
    font-size: 13px;
    line-height: 18px;
    margin: 4px 0 0;
}

/* =============================================================================
   SPEC-010 — Pending Decisions workspace shell + queue
   Tokens from docs/planning/Justice_Portal_Style_Guide_v5.pdf
   §1.1 color taxonomy (Status semantic colors), §1.3 typography (Inter, H3,
   Body), §1.5 radius (9999px status pill, 8px card), §2.3 status pills,
   §2.4 cards, §2.5 left nav.
   Per AC-5: status color is ALWAYS paired with explicit text label.
   ============================================================================= */

/* Issue #1339: column, not row. The top app bar is the first child and spans the full page
   width (Master §6.2 — "Top app bar (global, fixed)"); .workspace-shell-body below it is the
   horizontal [nav][main] row. Previously this was a row with the bar nested inside <main>,
   so the bar could only span (viewport − 220px). */
.workspace-shell {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    font-family: var(--font-product);
    color: #1F2937;
    background: #F7F8FA;
}

/* Issue #1339: no min-height here. The bar (56px) + this row must total 100vh, not 100vh+56px;
   .workspace-shell-body carries flex: 1 and stretches this nav to fill it. */
.workspace-shell-body {
    display: flex;
    flex: 1;
    min-height: 0;
}

/* Issue #2223: .workspace-shell only sets min-height: 100vh, so on a page taller than the
   viewport the whole document scrolls and carries this nav along with it. position: sticky
   with a top offset matching .top-app-bar's height (56px) keeps the nav docked under the bar
   instead of scrolling away; the height + overflow-y cap is defensive so the nav scrolls
   internally on the (currently theoretical) case where its own item list outgrows one screen. */
.workspace-nav {
    flex: 0 0 220px;
    background: #FFFFFF;
    color: #1A202C;
    border-right: 1px solid #E1E5EB; /* Style Guide v5 §2.5 — "220px wide, white fill, 1px right border" */
    padding: 24px 0;
    box-sizing: border-box;
    position: sticky;
    top: 56px;
    max-height: calc(100vh - 56px);
    overflow-y: auto;
}

.workspace-nav ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.workspace-nav-group + .workspace-nav-group {
    margin-top: 16px;
}

/* Issue #1143 (delta log Entry 211): reverted to Style Guide v5 §2.5's literal white-fill
   sidebar spec, superseding the 2026-07-22 navy-shell decision (Issue #718 follow-up).
   WORKSPACE + ADMIN section labels match the size/weight/letter-spacing of .admin-nav h2
   (§2.5 Overline text). .active marks the shell's own section (WORKSPACE here, ADMIN in
   AdminNav) per Master Design Summary §6.2 line 1068. */
.workspace-nav-label {
    font-family: var(--font-accent);
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779; /* Text/Secondary on White — Style Guide v5 contrast table: 4.9:1, Pass AA */
    padding: 12px 24px 6px;
    margin: 0;
}

.workspace-nav-label.active {
    color: #1E3A5F; /* Navy on White — 10.7:1, Pass AAA */
}

.workspace-nav-item {
    display: block;
    padding: 12px 24px;
    color: #1A202C; /* Text/Primary on White — Style Guide v5 contrast table: 15.4:1, Pass AAA */
    text-decoration: none;
    font-size: 15px;
    line-height: 22px;
    font-weight: 600;
    border-left: 3px solid transparent;
}

/* :not([aria-disabled="true"]) keeps the hover repaint off a write-gate-locked item (see the
   [aria-disabled] block below) — :hover still fires on an aria-disabled element, and excluding
   it here is cheaper than overriding it there, which would have to restate the active-state
   background too. */
.workspace-nav-item:hover:not([aria-disabled="true"]) {
    background: rgba(30, 58, 95, 0.06);
}

.workspace-nav-item.active {
    /* §6.5's literal Surface/Alt fill + 3px Navy left accent — dormant since 2026-07-22, live again per Entry 211 */
    background: #EEF0F3;
    border-left-color: #1E3A5F;
}

/* The paired [aria-disabled] CSS the accessible-disabled house rule requires (issue #2177). A
   workspace-nav-item is aria-disabled rather than natively inert while a write holds the
   circuit write gate (issue #1193), so without this it is computed-style identical to a live
   sibling — cursor: pointer, opacity: 1 — and reads as operable. axe has no rule that catches
   an aria-disabled control that still LOOKS operable. Mirrors .user-detail-breadcrumb a,
   .role-detail-breadcrumb a, .roles-table td a and .row-link — the same block shape, scoped to
   this selector. Deliberately does NOT touch background: an .active item locked mid-write
   should still read as "this is where you are", just not as "this is clickable" — unlike the
   hover repaint above, that is real state, not an illusion of operability. */
.workspace-nav-item[aria-disabled="true"] {
    cursor: not-allowed;
    opacity: 0.4;
    text-decoration: none;
}

/* KEEP flex-direction: column. It looks vestigial after Issue #1339 moved TopAppBar out of
   <main> (this container now wraps a single child), but it is load-bearing: in a column the
   cross axis is horizontal, so the child stretches to full width under the default
   align-items: stretch. As a row the child would take flex-basis: auto with flex-grow: 0 and
   size to its content instead, shrinking the content wrapper — neither *-main-content sets an
   explicit width. No test guards that; the sibling scrollWidth == clientWidth assertion stays
   true on a shrunken wrapper. (PR #1340 review — Rayce Newman, correcting a suggestion to
   delete it.) */
.workspace-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    box-sizing: border-box;
}

.workspace-main-content {
    padding: 32px 40px;
    box-sizing: border-box;
    overflow-x: auto;
}

/* ---- Page header (title + toolbar) ------------------------------------ */

.queue-page-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 24px;
}

.queue-page-header h1 {
    font-size: 24px;
    line-height: 32px;
    font-weight: 700;
    color: #1E3A5F;
    margin: 0;
}

.queue-toolbar {
    display: flex;
    gap: 12px;
}

/* Placeholder button — Telerik swap deferred until SPEC-003 lands. */
.btn {
    font-family: inherit;
    font-size: 14px;
    line-height: 20px;
    font-weight: 600;
    padding: 8px 16px;
    border-radius: 6px;
    border: 1px solid transparent;
    cursor: pointer;
}

.btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.btn-primary {
    background: #1E3A5F;
    color: #FFFFFF;
}

.btn-primary:hover:not(:disabled) {
    background: #244668;
}

/* ---- Telerik primary button — brand override --------------------------- */
/* Telerik's default `Primary` theme color is #ff6358 (red-orange), which fails
   WCAG 2 AA contrast (2.92:1) against white text. Swap in the project's navy
   (#1E3A5F → 8.6:1) so every `<TelerikButton ThemeColor="Primary">` across the
   app inherits the brand color + a compliant contrast ratio. Loaded after the
   Telerik stylesheet (see App.razor's link order) to win the cascade.
   Targets both class spellings the Kendo theme can emit (k-button-primary on
   older themes, k-button-solid-primary on newer fill-mode-aware themes). */
.k-button.k-button-primary,
.k-button.k-button-primary:hover,
.k-button.k-button-primary:focus,
.k-button.k-button-primary:active,
.k-button.k-button-solid-primary,
.k-button.k-button-solid-primary:hover,
.k-button.k-button-solid-primary:focus,
.k-button.k-button-solid-primary:active {
    background-color: #1E3A5F;
    border-color: #1E3A5F;
    color: #FFFFFF;
}

.k-button.k-button-primary:hover:not(:disabled),
.k-button.k-button-solid-primary:hover:not(:disabled) {
    background-color: #244668;
    border-color: #244668;
}

.k-button.k-button-primary:disabled,
.k-button.k-button-primary.k-disabled,
.k-button.k-button-solid-primary:disabled,
.k-button.k-button-solid-primary.k-disabled {
    background-color: #1E3A5F;
    border-color: #1E3A5F;
    opacity: 0.5;
}

/* WCAG 2.4.7 (Focus Visible) — explicit keyboard-focus indicator. The brand
   override above replaces Telerik's background/border on `:focus`; declaring our
   own `:focus-visible` here removes the dependency on whatever focus ring the
   underlying Telerik theme may or may not still apply after the cascade resolves.
   The 3px navy outline matches the button's fill color so the ring reads as a
   deliberate halo; the 2px offset keeps it clear of the button edge. `.force-focus-visible`
   forces the same ring for a PROGRAMMATIC focus a preceding POINTER interaction stops
   Chromium/Firefox matching to `:focus-visible` (issue #2200) — see focus-visible-force.js. */
.k-button.k-button-primary:focus-visible, .k-button.k-button-solid-primary:focus-visible,
.k-button.k-button-primary.force-focus-visible, .k-button.k-button-solid-primary.force-focus-visible {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}

/* Narrow Telerik font override (SPEC-022 AC-12, OQ-4) — no custom ThemeBuilder
   theme exists yet, so this rides the cascade the same way the color override
   above does, targeting only the four Kendo component base classes actually in
   use (TelerikRootComponent is the app-wide wrapper and needs no font rule of
   its own). Loaded after the Telerik stylesheet (see src/Dredd.Client/App.razor's
   link order) to win the cascade, same as the color override above. */
.k-button,
.k-dialog,
.k-editor,
.k-grid {
    font-family: var(--font-product);
}

/* ---- KPI tile row ----------------------------------------------------- */

.kpi-tile-row {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 16px;
    margin-bottom: 24px;
}

.kpi-tile {
    background: #FFFFFF;
    border: 1px solid #E5E7EB;
    border-radius: 8px;
    padding: 16px 20px;
    cursor: pointer;
    /* Button-element resets so a <button class="kpi-tile"> renders identical to <article class="kpi-tile">.
       Plain text alignment, inherited font, no UA-default border or background. box-sizing is explicit
       because <button> gets border-box for free from the UA form-control default but <article> does not —
       without it, the non-interactive tile's width:100% adds its border+padding on top of the grid track,
       overflowing it and forcing a phantom horizontal scrollbar on the page. */
    text-align: left;
    font: inherit;
    color: inherit;
    width: 100%;
    box-sizing: border-box;
    appearance: none;
}

button.kpi-tile:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 2px;
}

.kpi-tile.kpi-tile-active {
    border: 2px solid #1E3A5F;
    padding: 15px 19px; /* compensate for the +1px border so the layout doesn't shift */
}

.kpi-filter-hint {
    font-size: 11px;
    line-height: 14px;
    color: #1E3A5F;
    font-weight: 600;
    margin: 4px 0 0;
}

.kpi-tile.non-interactive {
    cursor: default;
}

.kpi-tile header {
    font-family: var(--font-accent);
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #595F6B;
    margin: 0 0 8px;
}

.kpi-count {
    font-family: var(--font-accent);
    font-variant-numeric: tabular-nums;
    font-size: 28px;
    line-height: 36px;
    font-weight: 700;
    color: #1E3A5F;
    margin: 0;
}

.kpi-delta {
    font-size: 12px;
    line-height: 16px;
    color: #595F6B;
    margin: 4px 0 0;
}

/* KPI tiles wrap to a 2x2 grid below the table-readable width per §2.5. */
@media (max-width: 880px) {
    .kpi-tile-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ---- Queue tab strip + per-queue banner (SPEC-012 AC-1/AC-3/AC-6) ------ */
/*
   Distinct from `.queue-tab` further down, which styles the admin time-frame /
   notification-destination radio labels — a different surface with a pill treatment.
   This is the workspace tab strip, matching `.defendant-tab*`'s underline treatment so
   the two tab strips in the app read as the same control.
*/

.queue-tab-strip {
    display: flex;
    gap: 4px;
    margin: 0 0 12px;
    border-bottom: 1px solid #E5E7EB;
}

.queue-strip-tab {
    appearance: none;
    background: transparent;
    border: none;
    border-bottom: 3px solid transparent;
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 600;
    /* WCAG 1.4.3 AA: #595F6B on #F5F6F8 ~= 5.9:1 — the same inactive-tab color the
       page's other muted text uses, rather than .defendant-tab's #666666 (which sits on
       that strip's lighter #F5F5F5 background). */
    color: #595F6B;
    cursor: pointer;
}

.queue-strip-tab:hover {
    color: #1E3A5F;
}

.queue-strip-tab:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: -2px;
}

.queue-strip-tab-active {
    color: #1E3A5F;
    border-bottom-color: #1E3A5F;
}

.queue-tab-strip-empty {
    margin: 0 0 12px;
    color: #595F6B;
    font-size: 14px;
    line-height: 20px;
}

/* AC-6: plain italic muted advisory text, no background — lowest rung of the
   4-severity banner model. */
.queue-banner {
    margin: 0 0 16px;
    color: #595F6B;
    font-size: 14px;
    line-height: 20px;
    font-style: italic;
}

/* ---- Queue table ------------------------------------------------------ */

.queue-table-region {
    background: #FFFFFF;
    border: 1px solid #E5E7EB;
    border-radius: 8px;
    overflow: hidden;
}

.queue-loading,
.queue-empty {
    padding: 32px;
    text-align: center;
    color: #595F6B;
    font-size: 15px;
}

.queue-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
    line-height: 20px;
}

.queue-table thead th {
    font-family: var(--font-accent);
    text-align: left;
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: #595F6B;
    padding: 12px 16px;
    background: #F7F8FA;
    border-bottom: 1px solid #E5E7EB;
}

.queue-table tbody td {
    padding: 12px 16px;
    border-bottom: 1px solid #F0F1F4;
    vertical-align: middle;
    color: #1F2937;
}

.queue-table tbody tr:last-child td {
    border-bottom: 0;
}

.court-case-cell {
    font-family: var(--font-accent);
    font-variant-numeric: tabular-nums;
}

.case-number-cell {
    font-family: var(--font-accent);
    font-variant-numeric: tabular-nums;
}

/* ---- Bulk-push selection column (SPEC-012 AC-7 / FR-7) ---------------- */
/*
   The checkbox column sits left of the status bar. Fixed width so adding it does not
   reflow the text columns' proportions for a push_records holder versus a caller who
   never sees it.
*/
.select-cell {
    width: 40px;
    text-align: center;
}

.queue-row-select {
    width: 16px;
    height: 16px;
    cursor: pointer;
    accent-color: #1E3A5F;
}

/*
   FR-7 ineligible row: the checkbox is aria-disabled rather than natively `disabled` so it
   stays focusable and its aria-label explanation is reachable by assistive tech. That means
   the browser paints it as a LIVE control, so this rule is what stops it reading as one —
   the paired [aria-disabled] CSS the accessible-disabled house rule requires.
*/
.queue-row-select[aria-disabled="true"] {
    cursor: not-allowed;
    opacity: 0.4;
}

/* ---- Bulk-action bar (SPEC-012 AC-7 / FR-8; Figure 13.4) -------------- */
/*
   Navy bar above the table, appearing on any selection. #1E3A5F is the portal's primary
   navy (same token as the active tab and the KPI counts); white body text on it is
   White on Navy — Style Guide v5 contrast table: 10.7:1, Pass AAA.
*/
/*
   The always-present role="status" wrapper (WCAG 4.1.3) — a live region must already be in the
   accessibility tree for a later mutation to be announced — is deliberately left UNSTYLED.

   It carried `display: contents` in review; that is the value most associated with an element being
   dropped from the accessibility tree, and here the element's own `role="status"` semantics are the
   entire point, so the risk was of silently nullifying the very fix it was supporting (invisibly to
   axe-core, which cannot see live-region registration either way). The layout justification did not
   hold on inspection: `.workspace-main-content` is plain block flow (no flex/grid/gap), so an empty
   wrapper reserves zero vertical space on its own, and `.bulk-action-bar`'s `margin: 0 0 12px`
   collapses through a wrapper with no padding, border, or height. Removing the rule is visually
   byte-identical and keeps the region in the a11y tree. Do not add a `display` value here without a
   screen-reader pass on the 0 -> 1 selection announcement.
*/

.bulk-action-bar {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 10px 16px;
    margin: 0 0 12px;
    border-radius: 8px;
    background: #1E3A5F;
    color: #FFFFFF;
    font-size: 14px;
    line-height: 20px;
}

.bulk-action-count {
    font-weight: 600;
}

/*
   Reverse-contrast button on the navy bar: white text on transparent with a white border,
   filling on hover. #1E3A5F text on #FFFFFF (the hover state) is the same Style Guide v5
   White-on-Navy pair inverted (10.7:1), so both states pass AAA.
*/
.bulk-action-push {
    appearance: none;
    padding: 6px 14px;
    border: 1px solid #FFFFFF;
    border-radius: 4px;
    background: transparent;
    color: #FFFFFF;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
}

.bulk-action-push:hover {
    background: #FFFFFF;
    color: #1E3A5F;
}

/* White focus ring — the page's #1E3A5F ring would vanish against the navy bar. */
.bulk-action-push:focus-visible {
    outline: 2px solid #FFFFFF;
    outline-offset: 2px;
}

/* ---- Bulk-push dialog + summary banner (SPEC-012 AC-8 / AC-10a) ------- */

/*
   Native <dialog> (.modal-dialog supplies the frame + backdrop), NOT a TelerikDialog — Telerik does not
   re-render its hosted fragments when only the child component's state changes, so the AC-8 interpolated
   title, the confirmation body, and the Push button's disabled state all sat stale. See the component's
   markup comment. Layout here mirrors QueueConfigurationDialog's header / body / actions structure.

   Width comes from the shared frame (480px, `calc(100% - 48px)` below it). A bare
   `.bulk-push-dialog { width; max-width }` used to sit here and never applied — (0,1,0) against the
   frame's (0,1,1) — so it was removed (Issue #1295). Any real override here needs `dialog.` in front.
*/

/* .dialog-close positions itself absolutely against the dialog, so the header needs no flex slot for
   it — only room on the right so a long interpolated title does not run under it. */
.bulk-push-dialog-header {
    margin: 0 32px 12px 0;
}

.bulk-push-dialog-header h3 {
    margin: 0;
    font-size: 16px;
    line-height: 22px;
    font-weight: 600;
    color: #1E3A5F;
}

.bulk-push-dialog-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 16px;
}

.bulk-push-targets {
    border: 0;
    padding: 0;
    margin: 0 0 12px;
}

.bulk-push-confirm-body {
    margin: 0;
    color: #1F2937;
    font-size: 14px;
    line-height: 20px;
}

/* FR-13 completed-operation summary — informational green, matching .success-message. */
.bulk-push-summary {
    padding: 12px 16px;
    margin: 0 0 12px;
    border: 1px solid #0F7B5C;
    border-radius: 8px;
    background: #E6F4EF;
    color: #0F5C45;
    font-size: 14px;
    line-height: 20px;
}

.bulk-push-summary-headline {
    margin: 0;
    font-weight: 600;
}

/* One line per skipped record, reason only (AC-10a) — no ids, no names. */
.bulk-push-skip-list {
    margin: 8px 0 0;
    padding-left: 20px;
}

.bulk-push-error {
    margin: 0 0 12px;
}

/* 4-pixel left bar (AC-5) — color matches the row's status. Lives in a tight
   left-edge cell whose only content is the bar div. Width is fixed so the cell
   contributes the bar visually without consuming text width. */
.status-bar-cell {
    width: 4px;
    padding: 0 !important;
}

.status-bar {
    display: block;
    width: 4px;
    height: 100%;
    min-height: 44px;
}

.status-bar-awaiting_input  { background: #2B6CB0; }
.status-bar-ready_for_review { background: #0F7B5C; }
.status-bar-in_review       { background: #8A6B25; }

/* ---- Status pill ------------------------------------------------------ */

.status-pill {
    font-family: var(--font-accent);
    display: inline-block;
    padding: 4px 10px;
    border-radius: 9999px;
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    white-space: nowrap;
}

.status-pill-awaiting_input  { background: #E6F0FA; color: #2B6CB0; }
.status-pill-ready_for_review { background: #E6F4EF; color: #0F7B5C; }
.status-pill-in_review       { background: #FDF5E6; color: #8A6B25; }
.status-pill-decided         { background: #EEF0F3; color: #5A6779; }

/* ---- Overdue affordance (AC-6) ---------------------------------------- */

.hours-cell.overdue {
    color: #B84D4D;
    font-weight: 700;
}

/* Solid Danger/Primary fill + white text (not the tinted Danger pill), so the
   chip clears WCAG 1.4.3 AA at 11px: #FFFFFF on #B84D4D is 4.99:1, where the old
   Danger/Primary-on-Danger/Tint pairing was 4.37:1 (Issue #323). Both colors are
   existing Style Guide v5 §1.2 tokens — no token change — and the solid-danger
   affordance mirrors .reconnect-indicator. */
.overdue-chip {
    font-family: var(--font-accent);
    display: inline-block;
    margin-left: 8px;
    padding: 2px 8px;
    background: #B84D4D;
    color: #FFFFFF;
    border-radius: 9999px;
    font-size: 11px;
    line-height: 14px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
}

/* ---- Defendant cell + row activation --------------------------------- */

.queue-row-link {
    color: #1F2937;
    text-decoration: none;
    font-weight: 600;
}

.queue-row-link:hover {
    color: #1E3A5F;
    text-decoration: underline;
}

.queue-row:hover {
    background: #F9FAFB;
    cursor: pointer;
}

/* =============================================================================
   SPEC-003 / SPEC-004 — Admin shell + Roles pages
   Tokens sourced from docs/planning/Justice_Portal_Style_Guide_v5.pdf §1.2-1.4.
   Covers: AdminLayout shell, CapabilityChangeBanner, RolesListPage,
   RoleDetailPage, CapabilityComposer, RoleChangeHistory, shared utilities
   (btn-primary, btn-danger, form-field, error-message, modal-dialog).
   ============================================================================= */

/* ---------------------------------------------------------------------------
   Shared utilities
   --------------------------------------------------------------------------- */

.btn-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 36px;
    padding: 0 16px;
    background: #1E3A5F;
    color: #FFFFFF;
    border: none;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    font-family: var(--font-product);
    transition: background-color 0.15s ease;
    white-space: nowrap;
}

.btn-primary:hover {
    background: #142640;
}

.btn-primary:focus-visible,
.btn-primary:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
}

.btn-primary:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.btn-danger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 36px;
    padding: 0 16px;
    background: #FFFFFF;
    color: #B84D4D;
    border: 1px solid #B84D4D;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    font-family: var(--font-product);
    transition: background-color 0.15s ease, border-color 0.15s ease;
    white-space: nowrap;
}

.btn-danger:hover {
    background: #FDECEC;
}

.btn-danger:focus-visible,
.btn-danger:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(184, 77, 77, 0.18);
}

.btn-danger:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.form-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.form-field label {
    font-family: var(--font-accent);
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779;
}

/* .user-detail-phone-input rides these selector groups rather than copying their
   declarations, so the Phone field on /admin/users/{id} keeps following the house input
   style if that style later moves. The field cannot use the .form-field WRAPPER: that
   wrapper is `flex-direction: column` with its own <label>, and this field's label is the
   row's <dt>, laid out by .user-detail-section dl's grid. Only the input treatment is
   shared. Before this, .user-detail-phone-input matched no rule at all and the field
   rendered as a bare user-agent input. */
.form-field input,
.user-detail-phone-input {
    height: 44px;
    padding: 0 12px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 15px;
    line-height: 22px;
    color: #1A202C;
    background: #FFFFFF;
    box-sizing: border-box;
    font-family: var(--font-product);
    transition: border-color 0.15s ease;
}

/* Style Guide v5 §2.2 pins inputs at a 44px minimum, which the shared group above applies.
   This field is the one documented exception: it is an inline editor inside the Account
   Details <dl>, not a field on a form card, and it has to stand in the same box as the Edit
   button it replaces — 36px, Style Guide §2.1's Default button size, and the height the
   Revoke button in this page's Sessions table already renders at. Recorded as a deliberate
   §2.2 deviation in specs/spec-delta-log.md.

   BARE single class on purpose, and NOT `input.user-detail-phone-input`: the compound form
   out-ranks the group's own `.user-detail-phone-input` selector (0,1,1 against 0,1,0), which
   makes check-css-dialog-override-specificity.py report the group's `height: 44px` as a dead
   declaration. At equal specificity that lint stays silent and source order decides, which is
   what this rule relies on. Nothing later in this file declares height on this class. */
.user-detail-phone-input {
    height: 36px;
}

.form-field input:hover,
.user-detail-phone-input:hover {
    border-color: #8A94A6;
}

.form-field input:focus-visible,
.form-field input:focus,
.user-detail-phone-input:focus-visible,
.user-detail-phone-input:focus {
    outline: none;
    border-color: #1E3A5F;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
}

.form-field input[readonly],
.form-field input:read-only,
.user-detail-phone-input[readonly],
.user-detail-phone-input:read-only {
    background: #EEF0F3;
    cursor: default;
}

/* Issue #2179: .form-field input carried the app typeface + box treatment but had no textarea
   equivalent, so #role-description (RoleDetailPage) and #queue-banner (QueueConfigurationDialog)
   -- both plain <textarea> elements inside a .form-field wrapper -- fell through to the browser's
   UA default stylesheet, which renders <textarea> in monospace (SPEC-022 AC-1/AC-3/AC-6
   regression: "no surface hardcodes a font-family name" / "no surface renders a monospace
   typeface"). A separate rule rather than folding textarea into the selector above: `height: 44px`
   is a fixed single-line input height and would collapse these multi-row fields (rows="2"/"3") to
   44px tall. resize: vertical matches the codebase's other manually-styled textareas
   (.decision-comment-field, .condition-editor-body). */
.form-field textarea {
    padding: 8px 12px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 15px;
    line-height: 22px;
    color: #1A202C;
    background: #FFFFFF;
    box-sizing: border-box;
    font-family: var(--font-product);
    transition: border-color 0.15s ease;
    resize: vertical;
}

.form-field textarea:hover {
    border-color: #8A94A6;
}

.form-field textarea:focus-visible,
.form-field textarea:focus {
    outline: none;
    border-color: #1E3A5F;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
}

.form-field textarea[readonly],
.form-field textarea:read-only {
    background: #EEF0F3;
    cursor: default;
}

.error-message {
    background: #FEF2F2;
    border: 1px solid #FCA5A5;
    border-radius: 6px;
    color: #B91C1C;
    font-size: 14px;
    line-height: 20px;
    padding: 12px 16px;
}

/* SPEC-017 AC-19 (Issue #2583) — layout for a message that carries a trailing dismiss control.
   .error-message is not a flex container, so the control needs one. Written as the COMPOUND
   selector (specificity 0-2-0 against .error-message's 0-1-0) so it wins regardless of source
   order — unlike the per-page margin overrides below, which are 0-1-0 against 0-1-0 and must sit
   after .error-message to take effect. The dismiss control itself reuses .banner-dismiss. */
.error-message.dismissible-alert {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

/* ---- Workspace queue banners (issue #1376) ---------------------------- */
/*
   Both queue banners render immediately above `.kpi-tile-row`, which carries a
   margin-bottom but nothing on top, and `.error-message` above is marginless because
   its other hosts (the sign-in card, dialog forms) own their own spacing. Without this
   the banner sits flush against the tiles. Applied to both banners rather than only the
   export one: they occupy the same slot in the render order and stack together when a
   load failure and an export failure are on screen at once.

   Placed BELOW `.error-message` deliberately. Both selectors resolve to specificity
   (0,1,0), so source order is the only tiebreak -- above it, the day `.error-message`
   gains a `margin` shorthand or its own `margin-bottom`, the shared rule would win and
   silently zero this spacing.
*/
.queue-load-error,
.queue-export-error {
    margin-bottom: 10px;
}

/* Issue #1131 — the generic unhandled-exception error page's own layout (ErrorLayout.razor).
   Deliberately minimal: centered static copy, no chrome tied to nav/branding data. */
.error-page-shell {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 48px;
    box-sizing: border-box;
}

.error-page {
    max-width: 480px;
    text-align: center;
}

.error-page-trace-id {
    margin-top: 16px;
    color: #6B7280;
    font-size: 13px;
}

.field-error {
    display: block;
    font-size: 12px;
    line-height: 18px;
    color: #B84D4D;
    margin-top: 4px;
}

/* Residue of the original overlay treatment, kept only for what the frame does not set.
   Every element carrying this class is a <dialog>, so `dialog.modal-dialog` below is (0,1,1)
   against this selector's (0,1,0) and wins every shared property regardless of source order —
   it owns the card box, background, padding, margin and centring outright. The ten declarations
   that duplicated or contradicted it were dead and have been removed (Issue #1295); `z-index`
   below is live because the frame declares none of it. Put any new dialog-surface
   declaration in the `dialog.`-prefixed rule below, not here — a bare class loses.

   The invariant this rests on: every carrier of `modal-dialog` is a <dialog> element.
   Put the class on anything else and the frame stops applying, leaving that element with
   only the declaration below — and the specificity lint stays silent by design,
   because it only calls a declaration dead when the frame covers every carrier.

   `align-items: center` and `justify-content: center` USED to sit here and were removed
   (2026-09-18). They were not merely dead — `align-items` was actively wrong, and it is the
   one declaration in this rule the Issue #1295 sweep could not have caught, because the frame
   declares neither property and so a "does the frame override it?" test says keep. They are
   vestigial from the layout model this comment's own first line names: when `.modal-dialog`
   was the full-screen SCRIM, the two centred the dialog CARD inside it. Once the class moved
   onto the `<dialog>` element itself, the same two declarations started centring the dialog's
   CONTENTS instead — and because the frame sets `flex-direction: column`, `align-items: center`
   shrink-wrapped every header, body and footer to its own content width. That is why a sectioned
   dialog's header band rendered as a floating centred tab rather than spanning the dialog:
   measured at 166px inside the 720px condition editor, and 168px inside the 600px note-type
   editor. Removing it restores the flex default (`stretch`), which is what every dialog in the
   tree wants. `justify-content: center` was inert on a `height: fit-content` column and is
   removed with it rather than left to mislead the next reader.

   The sentence above about the frame owning "centring outright" is true of the dialog's own
   VIEWPORT centring (`inset: 0` + `margin: auto`) and was never true of these two — that
   conflation is what let them survive the sweep. */
.modal-dialog {
    z-index: 1000;
}

/* Both rules below are INERT, and kept only because removing them is outside this change's scope.
   They describe the original design where the dialog was its own scrim (translucent background on
   the element, ::backdrop suppressed to transparent). Neither applies: `.modal-dialog[open]` (0,2,0)
   loses to `dialog.modal-dialog[open]` (0,2,1), which paints the card white, and
   `.modal-dialog::backdrop` (0,1,1) loses to `dialog.modal-dialog::backdrop` (0,1,2), which paints
   the real scrim. The shipped mechanism is the browser's own top-layer ::backdrop, not suppression.
   The specificity lint does not reach either one — its override side is bare-single-class only, so
   an attribute-qualified or pseudo-element override is a declared limit in its contract rather than
   an oversight. */
.modal-dialog[open] {
    background: rgba(15, 23, 42, 0.45);
}

.modal-dialog::backdrop {
    background: transparent;
}

/* Card surface — child content flows here; the dialog itself acts as the scrim */
.modal-dialog > * {
    pointer-events: auto;
}

/* The dialog element itself IS the card in the Blazor markup pattern used here
   (no wrapper div). Apply card styles directly. */
/* Overrides the .modal-dialog[open] scrim rule (0,2,0) which would otherwise win over
   dialog.modal-dialog (0,1,1). Adding the element selector restores specificity to 0,2,1. */
dialog.modal-dialog[open] {
    background: #FFFFFF;
}

/* Restores the UA stylesheet's `dialog:not([open]) { display: none }`, which the
   `dialog.modal-dialog` frame rule below overrides with `display: flex`. The bare
   `.modal-dialog` above declared it too until Issue #1295 removed that copy as dead;
   the frame is now the only source, so this rule is what keeps a closed dialog hidden.
   Latent until SPEC-018: every other dialog here is mounted only while open, so none
   is ever in the DOM closed. The pop-up notification dialog is always
   mounted (its open state is derived from whether a pop-up is pending), and without this it renders
   as an empty white card — no backdrop, no content — in the middle of every authenticated page. */
dialog.modal-dialog:not([open]) {
    display: none;
}

/* THE dialog frame. Type-qualified on purpose: `dialog.modal-dialog` is (0,1,1), so it
   beats any bare single-class override such as `.invite-modal` (0,1,0) regardless of
   source order. That is the trap Issue #1295 catalogued: five bare-class rules — four
   per-dialog overrides plus this frame's own unqualified residue — carried declarations
   that never applied. Style a specific dialog as `dialog.<class>` (or
   `dialog.modal-dialog.<class>`), never as a bare class;
   check-css-dialog-override-specificity.py fails the build on a bare one. */
dialog.modal-dialog {
    background: #FFFFFF;
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18), 0 2px 8px rgba(15, 23, 42, 0.10);
    max-width: 480px;
    width: calc(100% - 48px);
    padding: 32px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    border: none;
    position: fixed;
    inset: 0;
    margin: auto;
    height: fit-content;
    max-height: calc(100vh - 48px);
    overflow-y: auto;
}

dialog.modal-dialog::backdrop {
    background: rgba(15, 23, 42, 0.45);
}

dialog.modal-dialog h3 {
    font-size: 18px;
    font-weight: 700;
    color: #1A202C;
    margin: 0;
    line-height: 26px;
}

dialog.modal-dialog p {
    font-size: 14px;
    color: #5A6779;
    margin: 0;
    line-height: 22px;
}

.dialog-buttons {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    margin-top: 8px;
}

/* Plain cancel button inside dialogs (unstyled button element) */
.dialog-buttons > button:not(.btn-primary):not(.btn-danger) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 36px;
    padding: 0 16px;
    background: #FFFFFF;
    color: #1A202C;
    border: 1px solid #E1E5EB;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    font-family: var(--font-product);
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.dialog-buttons > button:not(.btn-primary):not(.btn-danger):hover {
    background: #EEF0F3;
    border-color: #8A94A6;
}

.dialog-buttons > button:not(.btn-primary):not(.btn-danger):focus-visible,
.dialog-buttons > button:not(.btn-primary):not(.btn-danger):focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
}

.dialog-close {
    position: absolute;
    top: 12px;
    right: 12px;
    background: none;
    border: none;
    cursor: pointer;
    color: #5A6779;
    font-size: 16px;
    line-height: 1;
    padding: 4px 6px;
    border-radius: 4px;
    font-family: inherit;
    /* SPEC-021 Task 5: raised to the Style Guide's own 40px pointer minimum (AC-7).
       min-width/min-height win over the implicit content-sized box; the glyph inside
       stays 20px via the Icon component's own width/height. See open issue #1393 for
       the separate 40-vs-44 question this does not settle. */
    min-width: 40px;
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.dialog-close:hover {
    color: #1A202C;
    background: #EEF0F3;
}

.dialog-close:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   Admin shell — AdminLayout
   --------------------------------------------------------------------------- */

/* Issue #1339: column, mirroring .workspace-shell — see the note there. */
.admin-shell {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background: #F5F6F8;
    font-family: var(--font-product);
}

.admin-shell-body {
    display: flex;
    flex: 1;
    min-height: 0;
}

/* Issue #2223: same fix as .workspace-nav above — .admin-shell only sets min-height: 100vh,
   so a tall admin page (e.g. Role Detail with many capability checkboxes) scrolls the nav
   away with it. Sticky + top offset docks it under .top-app-bar instead. */
.admin-nav {
    flex: 0 0 220px;
    width: 220px;
    background: #FFFFFF;
    border-right: 1px solid #E1E5EB; /* Style Guide v5 §2.5 — "220px wide, white fill, 1px right border" */
    box-sizing: border-box;
    padding: 24px 0;
    position: sticky;
    top: 56px;
    max-height: calc(100vh - 56px);
    overflow-y: auto;
}

.admin-nav-group + .admin-nav-group {
    margin-top: 16px;
}

.admin-nav h2 {
    font-family: var(--font-accent);
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779; /* mirrors .workspace-nav-label — Text/Secondary on White, 4.9:1 Pass AA */
    padding: 12px 20px 6px;
    margin: 0;
    box-sizing: border-box;
}

/* Issue #1143 (delta log Entry 211): reverted to Style Guide v5 §2.5's literal white-fill
   sidebar spec, superseding the 2026-07-22 navy-shell decision (Issue #718 follow-up).
   Marks this shell's own section (ADMIN here, WORKSPACE in WorkspaceLayout) per Master
   Design Summary §6.2 line 1068. Matches .workspace-nav-label.active's treatment. */
.admin-nav h2.active {
    color: #1E3A5F; /* Navy on White — 10.7:1, Pass AAA */
}

.admin-nav ul {
    list-style: none;
    margin: 0;
    padding: 0;
}

.admin-nav ul li {
    margin: 0;
}

.admin-nav ul li a,
.admin-nav ul li .nav-link {
    display: block;
    padding: 8px 20px;
    min-height: 36px;
    line-height: 20px;
    font-size: 15px; /* matches .workspace-nav-item — Issue #1819 */
    font-weight: 600; /* matches .workspace-nav-item — Issue #1819 */
    color: #1A202C; /* Text/Primary on White — Style Guide v5 contrast table: 15.4:1, Pass AAA */
    text-decoration: none;
    border-left: 3px solid transparent;
    box-sizing: border-box;
    transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}

/* Roles nav item is a <button> (programmatic NavigateTo so the unsaved-changes guard
   can intercept it); reset native button chrome so it matches the anchor nav items. */
.admin-nav ul li button.nav-link {
    width: 100%;
    text-align: left;
    background: transparent;
    border-top: none;
    border-right: none;
    border-bottom: none;
    font-family: inherit;
    cursor: pointer;
}

.admin-nav ul li a:hover,
.admin-nav ul li .nav-link:hover {
    background: rgba(30, 58, 95, 0.06); /* mirrors .workspace-nav-item:hover */
}

.admin-nav ul li a.active,
.admin-nav ul li .nav-link.active {
    /* §6.5's literal Surface/Alt fill + 3px Navy left accent — dormant since 2026-07-22, live again per Entry 211 */
    background: #EEF0F3;
    border-left-color: #1E3A5F;
    color: #1A202C;
    font-weight: 600;
}

.admin-nav ul li a:focus-visible,
.admin-nav ul li .nav-link:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 2px #1E3A5F; /* Navy ring, visible again on the white sidebar */
}

/* KEEP flex-direction: column. It looks vestigial after Issue #1339 moved TopAppBar out of
   <main> (this container now wraps a single child), but it is load-bearing: in a column the
   cross axis is horizontal, so the child stretches to full width under the default
   align-items: stretch. As a row the child would take flex-basis: auto with flex-grow: 0 and
   size to its content instead, shrinking the content wrapper — neither *-main-content sets an
   explicit width. No test guards that; the sibling scrollWidth == clientWidth assertion stays
   true on a shrunken wrapper. (PR #1340 review — Rayce Newman, correcting a suggestion to
   delete it.) */
.admin-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.admin-main-content {
    padding: 32px;
    overflow: auto;
}

/* ---------------------------------------------------------------------------
   Capability change banner — CapabilityChangeBanner
   --------------------------------------------------------------------------- */

.capability-change-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: #E6F0FA;
    border: none;
    border-left: 3px solid #2B6CB0;
    border-radius: 6px;
    padding: 12px 16px;
    margin-bottom: 16px;
    font-size: 14px;
    line-height: 20px;
    color: #2B6CB0;
    box-sizing: border-box;
}

.banner-dismiss {
    background: transparent;
    border: none;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    color: inherit;
    padding: 0 4px;
    flex-shrink: 0;
    border-radius: 4px;
    transition: opacity 0.12s ease;
    /* SPEC-021 Task 5: raised to the Style Guide's own 40px pointer minimum (AC-7). */
    min-width: 40px;
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.banner-dismiss:hover {
    opacity: 0.7;
}

.banner-dismiss:focus-visible,
.banner-dismiss:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(43, 108, 176, 0.25);
}

/* ---------------------------------------------------------------------------
   Roles list page — RolesListPage
   --------------------------------------------------------------------------- */

/* AC-16: no page-level max-width cap — the Roles list renders at the full width of the admin
   content area, matching the Conditions Library and Queue Views admin pages. The 900px cap this
   rule carried before AC-16 is gone; column widths and internal max-widths (e.g. the empty state's
   own 40px padding) are what still bound how wide any one element reads. */
.roles-page {
}

/* AC-13 breadcrumb. Structure and rule shapes mirror .notes-admin-breadcrumb (SPEC-015 AC-28) and
   .queue-views-breadcrumb (SPEC-011 AC-32) — the "/" separator is Style Guide v5 §2.5's, generated
   as decorative ::after content so it never enters the crumb's accessible name. */
.roles-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    font-size: 13px;
    line-height: 18px;
    color: #5A6779;
}

.roles-breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-left: 6px;
    color: #A0AAB8;
}

.roles-breadcrumb li[aria-current="page"] {
    color: #1A202C;
    font-weight: 600;
}

/* AC-14 static page description, directly beneath the <h1>. */
.roles-page-description {
    margin: 0 0 16px;
    color: #5A6779;
    font-size: 14px;
    line-height: 20px;
}

/* AC-15 summary line (total roles · users assigned · built-in). Sits between the description and
   the table/empty-state, so it reads as a scan-first count before the row-level detail. */
.roles-summary-line {
    margin: 0 0 16px;
    color: #5A6779;
    font-size: 13px;
    line-height: 18px;
}

.roles-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 24px;
}

.roles-header h1 {
    font-size: 22px;
    font-weight: 700;
    line-height: 30px;
    color: #1A202C;
    margin: 0;
}

.roles-empty-state {
    margin-top: 32px;
    padding: 40px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    text-align: center;
    color: #5A6779;
    font-size: 14px;
    line-height: 22px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
}

.roles-empty-state p {
    margin: 0;
}

.roles-table {
    width: 100%;
    border-collapse: collapse;
    background: #FFFFFF;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid #E1E5EB;
}

.roles-table thead tr {
    background: #F5F6F8;
}

.roles-table th {
    font-family: var(--font-accent);
    padding: 10px 16px;
    text-align: left;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #595F6B; /* WCAG 1.4.3 AA: #595F6B on #F5F6F8 ≈ 5.0:1 (was #8A94A6 ≈ 3.1:1); 5 nodes share this token */
    border-bottom: 1px solid #E1E5EB;
    white-space: nowrap;
}

.roles-table td {
    padding: 14px 16px;
    font-size: 14px;
    line-height: 20px;
    color: #1A202C;
    border-bottom: 1px solid #E1E5EB;
    vertical-align: middle;
}

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

.roles-table tbody tr:hover {
    background: #F5F6F8;
}

.roles-table td a {
    color: #1E3A5F;
    text-decoration: none;
    font-weight: 500;
}

.roles-table td a:hover {
    text-decoration: underline;
}

/* AC-18: role name pill/chip (Style Guide v5 §1.5 radius/full pill token). Neutral, not a status
   pill — it does not indicate state, so it borrows only the shape token, not any status tint.
   Qualified as .roles-table td a.role-name-pill so it wins over the .roles-table td a / :hover
   color-and-underline rules above (a link with a pill background reading underline-on-hover looks
   like a paper-cut, not a link affordance, so both are overridden to none here). */
.role-name-cell {
    vertical-align: top;
}

.role-name-pill,
.roles-table td a.role-name-pill {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 9999px;
    background: #EEF0F3;
    color: #1A202C;
    font-weight: 500;
    font-size: 13px;
    line-height: 18px;
    text-decoration: none;
}

/* :not([aria-disabled="true"]) keeps the hover repaint off a write-gate-locked pill (see the
   [aria-disabled] block below). Excluded here rather than overridden there because an override
   would have to restate the base pill background from the rule above. */
.roles-table td a.role-name-pill:hover:not([aria-disabled="true"]) {
    background: #E1E5EB;
    text-decoration: none;
}

/* The paired [aria-disabled] CSS the accessible-disabled house rule requires. The roles-table
   role-name link is aria-disabled rather than natively inert while a write holds the circuit
   write gate (issue #1193), so without this it is computed-style identical to a live sibling —
   cursor: pointer, opacity: 1 — and reads as operable, the same gap PR #1865 closed for .page-
   btn. axe has no rule that catches an aria-disabled control that still LOOKS operable. The
   :hover arm is neutralized for the same reason .btn-primary's is: :hover still fires on an aria-
   disabled element, so the underline would keep painting the link live.
   Since AC-18 (#1992) made the name a pill, a SECOND hover treatment reaches this link: the
   pill's own background swap. This block cannot answer that one — it declares no background, so
   there is nothing for ordering or specificity to win — which is why the pill's :hover selector
   carries :not([aria-disabled="true"]) instead. Excluding it there rather than re-declaring
   #EEF0F3 here keeps the base pill background stated once. */
.roles-table td a[aria-disabled="true"],
.roles-table td a[aria-disabled="true"]:hover {
    cursor: not-allowed;
    opacity: 0.4;
    text-decoration: none;
}

/* AC-18 BUILT-IN tag, beside the name pill. Reuses .status-pill's shape (uppercase, pill radius)
   plus the EXISTING info-blue tint pair .status-pill--pending already carries, the same reuse
   NotesAdminPage's Source-column BUILT-IN/CUSTOM pill makes rather than defining a third tint pair
   (see that rule's own comment, above the Notes admin section of this file). Carries visible text,
   not color alone (WCAG 2.1 SC 1.4.1). */
.role-built-in-tag {
    margin-left: 8px;
    vertical-align: middle;
}

/* AC-17 per-role description, the second line beneath the name pill / BUILT-IN tag. A role with no
   description renders no element here at all (the markup omits the <p> outright) rather than an
   empty one, so there is no reserved blank line. */
.role-description-line {
    margin: 6px 0 0;
    color: #5A6779;
    font-size: 13px;
    line-height: 18px;
}

/* AC-19 capability domain-rollup chips, beneath the capability count. Quieter than .status-pill —
   deliberately, the same reasoning .notifications-rule-channel-chip's own comment states: this
   column's count is the scannable signal, and a chip at equal pill-weight would compete with it. */
.role-domain-chips {
    margin-top: 6px;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

.role-domain-chip {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 4px;
    background: #EEF2F7;
    color: #2D3B4E;
    font-size: 11px;
    line-height: 16px;
    white-space: nowrap;
}

/* The "+N" overflow chip names a count, not a domain — a quieter neutral than the domain chips
   themselves so it reads as "and more," not as a fourth domain. */
.role-domain-chip--overflow {
    background: #E1E5EB;
    color: #5A6779;
}

/* AC-20: the overflow menu's absolutely-positioned panel is clipped by .roles-table's own
   `overflow: hidden` (set above to clip its 8px corner radius) the same way .conditions-table
   clips RowActionsMenu — see that rule's own comment for the full trade-off (measured there, not
   re-derived here). Scoped with :has() so the clip lifts only while a panel is mounted. */
.roles-table:has(.row-actions-menu) {
    overflow: visible;
}

.pagination {
    display: flex;
    flex-direction: row;
    gap: 8px;
    margin-top: 24px;
}

.page-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border: 1px solid #E1E5EB;
    background: #FFFFFF;
    border-radius: 6px;
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    color: #5A6779;
    font-family: var(--font-product);
    transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

.page-btn:hover {
    background: #EEF0F3;
    border-color: #C9CED8;
    color: #1E3A5F;
}

.page-btn:focus-visible,
.page-btn:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
}

.page-btn.active {
    background: #1E3A5F;
    color: #FFFFFF;
    border-color: #1E3A5F;
    font-weight: 600;
}

/* ---------------------------------------------------------------------------
   Users list page — UsersListPage
   --------------------------------------------------------------------------- */

/* AC-22: no page-level max-width cap (Issue #1258 follow-up) -- the Users list renders at the
   full width of the admin content area, matching the Roles list's identical criterion (SPEC-003
   AC-16). The 1040px cap this rule carried before AC-22 is gone; column widths and internal
   max-widths are what still bound how wide any one element reads. */
.users-page {
}

.users-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    font-size: 13px;
    line-height: 18px;
    color: #5A6779;
}

.users-breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-left: 6px;
    color: #A0AAB8;
}

.users-breadcrumb li[aria-current="page"] {
    color: #1A202C;
    font-weight: 600;
}

/* AC-20 static page description, directly beneath the <h1>. */
.users-page-description {
    margin: 0 0 16px;
    color: #5A6779;
    font-size: 14px;
    line-height: 20px;
}

/* AC-21 summary line (account total · status breakdown). Sits between the description/filter bar
   and the table/empty-state, so it reads as a scan-first count before the row-level detail. */
.users-summary-line {
    margin: 0 0 16px;
    color: #5A6779;
    font-size: 13px;
    line-height: 18px;
}

.users-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 24px;
}

.users-header h1 {
    font-size: 22px;
    font-weight: 700;
    line-height: 30px;
    color: #1A202C;
    margin: 0;
}

.users-filter-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 20px;
}

.users-search {
    flex: 1 1 280px;
    min-width: 200px;
    padding: 8px 12px;
    font-size: 14px;
    line-height: 20px;
    color: #1A202C;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 6px;
    font-family: inherit;
    box-sizing: border-box;
}

.users-filter-select {
    padding: 8px 12px;
    font-size: 14px;
    line-height: 20px;
    color: #1A202C;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 6px;
    font-family: inherit;
    cursor: pointer;
}

.users-search:focus-visible,
.users-filter-select:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
    border-color: #1E3A5F;
}

.users-table {
    width: 100%;
    border-collapse: collapse;
    background: #FFFFFF;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid #E1E5EB;
}

.users-table thead tr {
    background: #F5F6F8;
}

.users-table th {
    padding: 0;
    text-align: left;
    border-bottom: 1px solid #E1E5EB;
    white-space: nowrap;
}

.th-label {
    font-family: var(--font-accent);
    display: block;
    padding: 10px 16px;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #595F6B;
}

.users-table td {
    padding: 0;
    color: #1A202C;
    border-bottom: 1px solid #E1E5EB;
    vertical-align: middle;
}

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

.users-table-row:hover {
    background: #F5F6F8;
}

/* Sortable column header — a <button> styled to match the static .th-label.
   Native button chrome reset; fills the cell so the whole header is the hit area. */
.sort-header {
    font-family: var(--font-accent);
    display: inline-flex;
    align-items: center;
    gap: 4px;
    width: 100%;
    padding: 10px 16px;
    background: transparent;
    border: none;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #595F6B;
    text-align: left;
    cursor: pointer;
}

.sort-header:hover,
.sort-header.active {
    color: #1E3A5F;
}

.sort-header:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 2px rgba(30, 58, 95, 0.35);
}

.sort-chevron {
    font-size: 9px;
    line-height: 1;
}

/* Row link — covers the cell so the whole row reads as one click target while keeping
   native <a> semantics. Only the name cell's link is focusable (others tabindex=-1);
   none are aria-hidden, so screen readers still read each cell's content. */
.row-link {
    display: block;
    padding: 14px 16px;
    font-size: 14px;
    line-height: 20px;
    color: #1A202C;
    text-decoration: none;
}

.row-link--name {
    display: flex;
    align-items: center;
    gap: 10px;
    color: #1E3A5F;
    font-weight: 500;
}

.row-link--name:hover {
    text-decoration: underline;
}

/* The paired [aria-disabled] CSS the accessible-disabled house rule requires. Every users-table
   row link (one selector reaches all five — .row-link--name also carries .row-link) is aria-
   disabled rather than natively inert while a write holds the circuit write gate (issue #1193),
   so without this it is computed-style identical to a live sibling — cursor: pointer, opacity: 1
   — and reads as operable, the same gap PR #1865 closed for .page-btn. axe has no rule that
   catches an aria-disabled control that still LOOKS operable. The :hover arm is neutralized for
   the same reason .btn-primary's is: :hover still fires on an aria-disabled element, so the
   underline would keep painting the link live. */
.row-link[aria-disabled="true"],
.row-link[aria-disabled="true"]:hover {
    cursor: not-allowed;
    opacity: 0.4;
    text-decoration: none;
}

.avatar {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 9999px;
    color: #FFFFFF;
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.3px;
}

.status-pill--active   { background: #E6F4EF; color: #0F7B5C; }
.status-pill--inactive { background: #EEF0F3; color: #5A6779; }
.status-pill--locked   { background: #FDF5E6; color: #8A6B25; }
.status-pill--pending  { background: #E6F0FA; color: #2B6CB0; }
.status-pill--archived { background: #EEF0F3; color: #5A6779; }
/* Added by SPEC-018 PR 6f for the delivery log's Failed and Bounced rows. Joins the shared
   family rather than opening a notifications-only palette, so the one red reads the same
   wherever a status pill means "needs attention". */
.status-pill--failed   { background: #FDECEC; color: #B03030; }

.users-empty-state {
    margin-top: 32px;
    padding: 40px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    text-align: center;
    color: #5A6779;
    font-size: 14px;
    line-height: 22px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
}

.users-empty-state p {
    margin: 0;
}

/* Screen-reader-only utility — visually hidden, present in the accessibility tree. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ---------------------------------------------------------------------------
   Role detail page — RoleDetailPage
   --------------------------------------------------------------------------- */

.role-detail-page {
    max-width: 1100px;
}

/* AC-19 breadcrumb (Issue #1258 follow-up). "/" separator per Style Guide v5 §2.5, matching the
   convention every admin list page uses (SPEC-003 AC-13) -- mirrors .user-detail-breadcrumb's
   identical shape (SPEC-007 AC-19), including the paired [aria-disabled] hover-safety block the
   accessible-disabled house rule requires for the gated "Roles" link. */
.role-detail-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    list-style: none;
    margin: 0 0 20px;
    padding: 0;
    font-size: 13px;
    line-height: 18px;
    color: #5A6779;
}

.role-detail-breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-left: 6px;
    color: #A0AAB8;
}

.role-detail-breadcrumb li[aria-current="page"] {
    color: #1A202C;
    font-weight: 600;
}

.role-detail-breadcrumb a[aria-disabled="true"],
.role-detail-breadcrumb a[aria-disabled="true"]:hover {
    cursor: not-allowed;
    opacity: 0.4;
    text-decoration: none;
}

.role-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 24px;
}

.role-header h1 {
    font-size: 22px;
    font-weight: 700;
    line-height: 30px;
    color: #1A202C;
    margin: 0;
}

.role-detail-layout {
    display: flex;
    flex-direction: row;
    gap: 32px;
    align-items: flex-start;
}

.role-detail-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.role-detail-aside {
    flex: 0 0 280px;
    width: 280px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    padding: 20px;
    box-sizing: border-box;
}

.role-detail-aside h3 {
    font-size: 14px;
    font-weight: 600;
    line-height: 20px;
    color: #1A202C;
    margin: 0 0 12px;
}

.role-detail-aside p {
    font-size: 13px;
    color: #5A6779;
    margin: 0;
}

.role-detail-aside ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

.role-detail-aside ul li {
    padding: 8px 0;
    border-bottom: 1px solid #E1E5EB;
    font-size: 13px;
    line-height: 20px;
    color: #5A6779;
}

.role-detail-aside ul li:last-child {
    border-bottom: none;
}

/* Role detail Danger Zone — high-severity treatment (red border) per Style Guide v5 4-severity
   model. Tokens reused verbatim from .user-detail-danger-zone so both Danger Zones read alike. */
.role-detail-danger-zone {
    margin-top: 24px;
    padding: 20px 24px;
    background: #FEF5F5;
    border: 1px solid #C53030;
    border-radius: 8px;
}

.role-detail-danger-zone h2 {
    font-size: 16px;
    font-weight: 700;
    color: #9B2C2C;
    margin: 0 0 12px;
}

/* Issue #1261 moved the change history out of .role-detail-main to below the Danger Zone at page
   level (SPEC-004 AC-16), so it no longer inherits that column's 24px flex gap. Two classes, so
   this outranks the `.role-change-history { margin-top: 0 }` rule further down regardless of
   source order. */
.role-detail-page > .role-change-history {
    margin-top: 24px;
}

/* ---------------------------------------------------------------------------
   Capability composer — CapabilityComposer
   --------------------------------------------------------------------------- */

.capability-composer {
    display: flex;
    flex-direction: column;
    gap: 0;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    padding: 20px;
}

.capability-domain-group {
    border-bottom: 1px solid #E1E5EB;
}

.capability-domain-group:last-child {
    border-bottom: none;
}

/* SPEC-004 AC-3 (issue #2665): the per-domain select-all sits BESIDE the collapse button, not inside it --
   a checkbox nested in a <button> is invalid HTML and its click would toggle the collapse too. The row is
   also outside the collapsed body, so a domain can be selected whole without being expanded. */
.capability-domain-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.capability-domain-row .capability-domain-header {
    flex: 1 1 auto;
    width: auto;
}

.capability-composer-header {
    display: flex;
    align-items: center;
    padding-bottom: 12px;
    border-bottom: 1px solid #E1E5EB;
}

.capability-select-all {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    font-weight: 600;
    line-height: 20px;
    color: #1A202C;
    cursor: pointer;
    user-select: none;
}

.capability-select-all input[type="checkbox"] {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    accent-color: #1E3A5F;
    cursor: pointer;
}

.capability-select-all.disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.capability-select-all.disabled input[type="checkbox"] {
    cursor: not-allowed;
}

.capability-domain-header {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 12px 0;
    background: transparent;
    border: none;
    font-size: 14px;
    font-weight: 600;
    line-height: 20px;
    color: #1A202C;
    cursor: pointer;
    text-align: left;
    gap: 8px;
    font-family: var(--font-product);
    transition: color 0.12s ease;
}

.capability-domain-header:hover {
    color: #1E3A5F;
}

.capability-domain-header:focus-visible,
.capability-domain-header:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
    border-radius: 4px;
}

/* SPEC-021 Task 14 (FR-9 row 7): the chevron is now a real <Icon> in the button's own markup
   (Icon.razor), not a CSS ::before pseudo-element -- AC-2 requires per-page iconography to
   route through the shared abstraction, which a pseudo-element structurally cannot. The
   rotation transition moves onto the rendered .dredd-icon inside this header. Converting this
   also fixes a pre-existing accessible-name defect: the old ::before content folded into the
   button's accessible name ("▼ Users"), which is why RoleDetailPage.cs's PinnedCapabilityDomainLabel
   locator used to need a substring match. */
.capability-domain-header .dredd-icon {
    color: #8A94A6;
    flex-shrink: 0;
    transition: transform 0.15s ease;
}

.capability-domain-header[aria-expanded="false"] .dredd-icon {
    transform: rotate(-90deg);
}

.capability-list {
    list-style: none;
    padding: 0 0 12px 0;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 8px;
}

.capability-list li {
    margin: 0;
    padding: 0;
}

.capability-label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    line-height: 20px;
    color: #1A202C;
    cursor: pointer;
    padding: 4px 0;
    user-select: none;
}

.capability-label input[type="checkbox"] {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    accent-color: #1E3A5F;
    cursor: pointer;
}

.capability-label.disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.capability-label.disabled input[type="checkbox"] {
    cursor: not-allowed;
}

/* ---------------------------------------------------------------------------
   Role change history — RoleChangeHistory
   --------------------------------------------------------------------------- */

.role-change-history {
    margin-top: 0;
}

.role-change-history h3 {
    font-size: 14px;
    font-weight: 600;
    line-height: 20px;
    color: #1A202C;
    margin: 0 0 12px;
}

.role-change-history > a {
    color: #1E3A5F;
    font-size: 13px;
    text-decoration: none;
    display: inline-block;
    margin-top: 4px;
}

.role-change-history > a:hover {
    text-decoration: underline;
}

.role-change-history > p {
    font-size: 13px;
    color: #5A6779;
    margin: 0 0 8px;
}

.change-history-list {
    list-style: none;
    padding: 0;
    margin: 0 0 12px;
    display: flex;
    flex-direction: column;
    gap: 0;
}

.change-history-list li {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 8px 0;
    border-bottom: 1px solid #E1E5EB;
    font-size: 13px;
    line-height: 18px;
}

.change-history-list li:last-child {
    border-bottom: none;
}

.change-description {
    color: #1A202C;
    font-weight: 500;
}

.change-actor {
    color: #5A6779;
    font-size: 12px;
    line-height: 18px;
}

.change-date {
    color: #595F6B; /* WCAG 1.4.3 AA: #595F6B on #F5F6F8 ≈ 5.9:1 (was #8A94A6 ≈ 2.8:1) */
    font-size: 12px;
    line-height: 18px;
}

/* ---- Queue filter chip (AC-12) -------------------------------------- */

.queue-filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px 6px 14px;
    margin: 0 0 16px;
    background: #E6F0FA;
    color: #1E3A5F;
    border-radius: 9999px;
    font-size: 13px;
    line-height: 18px;
    font-weight: 600;
}

.queue-filter-chip-label {
    white-space: nowrap;
}

.queue-filter-chip-clear {
    appearance: none;
    background: transparent;
    border: none;
    padding: 2px 6px;
    margin: 0;
    color: #1E3A5F;
    font-size: 14px;
    line-height: 16px;
    font-weight: 700;
    cursor: pointer;
    border-radius: 9999px;
    /* SPEC-021 Task 5: raised to the Style Guide's own 40px pointer minimum (AC-7). */
    min-width: 40px;
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.queue-filter-chip-clear:hover {
    background: rgba(30, 58, 95, 0.12);
}

.queue-filter-chip-clear:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: 1px;
}

/* ---- Reconnect indicator (AC-10a) ----------------------------------- */
/*
   Blazor's framework JS toggles `components-reconnect-show / -hide / -failed /
   -rejected` on the `#components-reconnect-modal` element. The default-hidden
   shape becomes visible only when Blazor adds the show / failed / rejected
   class. Living at the top of the workspace shell so it reads as a header
   banner per AC-10a.
*/
.reconnect-indicator {
    display: none;
    position: sticky;
    top: 0;
    z-index: 1000;
    width: 100%;
    padding: 8px 24px;
    background: #B84D4D;
    color: #FFFFFF;
    font-size: 13px;
    font-weight: 600;
    text-align: center;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
    box-sizing: border-box;
}

.reconnect-indicator.components-reconnect-show,
.reconnect-indicator.components-reconnect-failed,
.reconnect-indicator.components-reconnect-rejected {
    display: block;
}

.reconnect-indicator-default,
.reconnect-indicator-failed,
.reconnect-indicator-rejected {
    display: none;
}

.reconnect-indicator.components-reconnect-show .reconnect-indicator-default,
.reconnect-indicator.components-reconnect-failed .reconnect-indicator-failed,
.reconnect-indicator.components-reconnect-rejected .reconnect-indicator-rejected {
    display: inline;
}

.reconnect-indicator-retry {
    appearance: none;
    background: rgba(255, 255, 255, 0.2);
    color: #FFFFFF;
    border: 1px solid rgba(255, 255, 255, 0.6);
    border-radius: 4px;
    padding: 2px 12px;
    margin-left: 12px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}

.reconnect-indicator-retry:hover {
    background: rgba(255, 255, 255, 0.3);
}

/* ---- Queue row fade-out (AC-14) ------------------------------------- */
/*
   Rows leaving the active filter (or removed from the queue entirely) get
   the `exiting` class for ExitFadeDuration (300ms) before the page state
   removes them from the rendered row list. The CSS transition makes the
   removal a smooth fade rather than an abrupt disappearance.
*/
.queue-row.exiting {
    opacity: 0;
    transition: opacity 300ms ease-out;
    pointer-events: none;
}

/* ============================================================
   Defendant Details surface (SPEC-013)
   ============================================================ */

/* ---- Page-level error + loading states ------------------------------ */
.defendant-page-loading {
    padding: 32px 24px;
    color: #555555;
    font-style: italic;
}
.defendant-page-error {
    margin: 24px;
    padding: 16px 20px;
    background: #FDECEA;
    border: 1px solid #C62828;
    border-radius: 4px;
    color: #C62828;
}
.defendant-page-error a {
    color: #1E3A5F;
    font-weight: 600;
}

/* ---- Sticky header region (AC-2; SPEC-017 AC-13 / issue #519) -------
   The wrapper (not .defendant-header itself) owns the sticky positioning so the
   optional read-only banner sticks together with the header as one unit, without
   hardcoding the header's height (which varies with DOB visibility / name wrap). */
.defendant-sticky-region {
    position: sticky;
    top: 0;
    z-index: 10;
}
.defendant-header {
    background: #FFFFFF;
    border-bottom: 2px solid #1E3A5F;
    padding: 16px 24px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}
.defendant-header-top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
}
/* Charges row (SPEC-020 AC-44 / SPEC-013 AC-2 amendment) — a separate row at the bottom
   of the header, below .defendant-header-top, matching .defendant-meta's dt/dd styling. */
.defendant-charges {
    display: flex;
    margin: 0;
    font-size: 13px;
}
.defendant-charges > div {
    display: flex;
    gap: 4px;
    align-items: baseline;
}
.defendant-charges dt {
    color: #666666;
    font-weight: 500;
    margin: 0;
}
.defendant-charges dd {
    color: #1E3A5F;
    font-weight: 600;
    margin: 0;
}

/* ---- Read-only viewing banner (SPEC-017 AC-13, issue #519) ----------
   Generic Case-Lookup read-only session banner — distinct from .amber-banner
   (lock-holder/reservation notice). Sticks with the header via .defendant-sticky-region. */
.readonly-viewing-banner {
    background: #1E3A5F;
    color: #FFFFFF;
    text-align: center;
    padding: 6px 16px;
    font-weight: 700;
    font-size: 13px;
    letter-spacing: 0.5px;
}
.defendant-identity {
    display: flex;
    align-items: center;
    gap: 16px;
    flex: 1;
}
.defendant-initials {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: #1E3A5F;
    color: #FFFFFF;
    font-weight: 700;
    font-size: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.defendant-id-block {
    flex: 1;
    min-width: 0;
}
.defendant-name {
    font-size: 22px;
    font-weight: 700;
    color: #1E3A5F;
    margin: 0 0 4px 0;
    line-height: 1.2;
}
.defendant-meta {
    display: flex;
    gap: 24px;
    flex-wrap: wrap;
    margin: 0;
    font-size: 13px;
}
.defendant-meta > div {
    display: flex;
    gap: 4px;
    align-items: baseline;
}
.defendant-meta dt {
    color: #666666;
    font-weight: 500;
    margin: 0;
}
.defendant-meta dd {
    color: #1E3A5F;
    font-weight: 600;
    margin: 0;
}
.custody-counter {
    font-family: var(--font-accent);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.5px;
}
.defendant-header-actions {
    display: flex;
    gap: 8px;
}
.defendant-print-btn {
    background: #FFFFFF;
    color: #1E3A5F;
    border: 2px solid #1E3A5F;
    border-radius: 4px;
    padding: 6px 16px;
    font-weight: 600;
    cursor: pointer;
}
.defendant-print-btn:hover {
    background: #1E3A5F;
    color: #FFFFFF;
}
.defendant-print-btn:focus-visible {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}
/* SPEC-013 AC-23 (Issue #2054) — same visual treatment as Print, plus a disabled
   state Print does not need (Print has no in-flight round trip to disable across). */
.defendant-export-btn {
    background: #FFFFFF;
    color: #1E3A5F;
    border: 2px solid #1E3A5F;
    border-radius: 4px;
    padding: 6px 16px;
    font-weight: 600;
    cursor: pointer;
}
.defendant-export-btn:hover:not(:disabled) {
    background: #1E3A5F;
    color: #FFFFFF;
}
.defendant-export-btn:focus-visible {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}
.defendant-export-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* ---- Tab strip (AC-3) ----------------------------------------------- */
.defendant-tab-strip {
    display: flex;
    gap: 4px;
    padding: 0 24px;
    background: #F5F5F5;
    border-bottom: 1px solid #DDDDDD;
}
.defendant-tab {
    appearance: none;
    background: transparent;
    border: none;
    border-bottom: 3px solid transparent;
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 600;
    color: #666666;
    cursor: pointer;
}
.defendant-tab:hover { color: #1E3A5F; }
.defendant-tab:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: -2px;
}
.defendant-tab-active {
    color: #1E3A5F;
    border-bottom-color: #1E3A5F;
}

/* ---- Amber banner (AC-9, AC-17) ------------------------------------- */
.amber-banner {
    margin: 16px 24px;
    padding: 12px 16px;
    background: #FFF3CD;
    border-left: 4px solid #B26A00;
    border-radius: 4px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}
.amber-banner-body {
    flex: 1;
    color: #855600;
}
.amber-banner-label {
    margin-right: 6px;
    font-weight: 700;
}
.amber-banner-actions {
    display: flex;
    gap: 8px;
}
.amber-banner-btn {
    appearance: none;
    background: #FFFFFF;
    color: #1E3A5F;
    border: 2px solid #1E3A5F;
    border-radius: 4px;
    padding: 6px 14px;
    font-weight: 600;
    font-size: 13px;
    cursor: pointer;
}
.amber-banner-btn:hover {
    background: #1E3A5F;
    color: #FFFFFF;
}
.amber-banner-btn:focus-visible {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}

/* ---- Lock-override live region (AC-17) ------------------------------ */
.lock-override-notice {
    margin: 16px 24px;
    padding: 12px 16px;
    background: #FDECEA;
    border-left: 4px solid #C62828;
    color: #C62828;
    border-radius: 4px;
    font-weight: 600;
}

/* Issue #1810 — the Overview conditions card could not be refreshed after a committed conditions
   mutation. Warning-toned rather than the error red above (.lock-override-notice): the write itself
   succeeded, so the amber palette shared with .amber-banner is the honest signal. */
.conditions-stale-notice {
    margin: 16px 24px;
    padding: 12px 16px;
    background: #FFF3CD;
    border-left: 4px solid #B26A00;
    color: #855600;
    border-radius: 4px;
    font-weight: 600;
}

/* ---- Tab content layout (AC-4) -------------------------------------- */
.defendant-tab-content {
    padding: 24px;
}
/* AC-24 (Issue #2457) — Overview/Conditions/Documents/Notes are always mounted now
   (DefendantDetailsPage.razor), so on-screen single-panel-at-a-time display is CSS,
   not conditional rendering. The @media print block below overrides both rules so
   every non-audit-history panel is visible together regardless of which is active. */
.defendant-tab-content .tab-panel {
    display: none;
}
.defendant-tab-content .tab-panel--active {
    display: block;
}
.overview-tab-content {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr);
    gap: 24px;
    align-items: start;
}
.overview-main-column,
.overview-right-rail {
    display: flex;
    flex-direction: column;
    gap: 16px;
}
@media (max-width: 960px) {
    .overview-tab-content {
        grid-template-columns: 1fr;
    }
}

.tab-stub {
    padding: 32px;
    background: #F5F5F5;
    border-radius: 4px;
    color: #555555;
}
.tab-stub h2 {
    color: #1E3A5F;
    margin: 0 0 8px 0;
}

/* ---- Assessment card (AC-5) ----------------------------------------- */
.assessment-card,
.compact-card,
.decision-box,
.published-decision-panel,
.notes-summary-panel {
    background: #FFFFFF;
    border: 1px solid #DDDDDD;
    border-radius: 6px;
    padding: 16px 20px;
}
.assessment-card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
}
.assessment-card-header h2 {
    font-size: 16px;
    color: #1E3A5F;
    margin: 0;
}
.recommendation-pill {
    font-family: var(--font-accent);
    display: inline-block;
    padding: 4px 12px;
    border-radius: 999px;
    background: #1E3A5F;
    color: #FFFFFF;
    font-size: 13px;
    font-weight: 600;
}
/* No correctly-shaped recommendation exists (Issue #2257) — muted, so it does not read as a real one. */
.recommendation-unknown {
    background: #EEEEEE;
    color: #666666;
}

/* NPS has not supplied scores yet (spec.md v2.20, Issue #2308). Same box metrics as
   .recommendation-pill so the header does not reflow when a poll clears the pending state, and
   deliberately neutral — no risk-band hue — so it cannot read as a band. The literal word
   "Pending" carries the meaning; the color never does (style guide accessibility contract). */
.assessment-pending-indicator {
    font-family: var(--font-accent);
    display: inline-block;
    padding: 4px 12px;
    border-radius: 999px;
    background: #EEEEEE;
    color: #444444;
    font-size: 13px;
    font-weight: 600;
}

.assessment-risk-metric-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
    margin-bottom: 16px;
}
.risk-metric {
    padding: 12px;
    border: 1px solid #EEEEEE;
    border-radius: 4px;
    text-align: center;
}
.risk-metric-label {
    font-size: 12px;
    font-weight: 600;
    color: #666666;
    margin-bottom: 4px;
}
.risk-metric-score {
    font-size: 28px;
    font-weight: 700;
    color: #1E3A5F;
}

/* Risk pill colors — paired with the visible level text label, never color-alone. */
.risk-pill {
    font-family: var(--font-accent);
    display: inline-block;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    color: #FFFFFF;
    margin-top: 4px;
}
.risk-pill-low { background: #2E7D32; }
/* Medium darkened from #B26A00 (4.23:1 white-on-bg, failed WCAG AA at 11px bold) to
   #9C5C00 (~5.0:1). The 11px-bold pill is "small text" per WCAG, so 4.5:1 is the floor. */
.risk-pill-medium { background: #9C5C00; }
.risk-pill-high { background: #C84A00; }
.risk-pill-very-high { background: #C62828; }
/* Unknown darkened from #777777 (4.47:1 white-on-bg, just below 4.5:1) to #6E6E6E
   (~5.0:1) for the same WCAG AA reason as Medium above. */
.risk-pill-unknown { background: #6E6E6E; }

.assessment-key-factors h3 {
    font-size: 13px;
    color: #1E3A5F;
    margin: 0 0 8px 0;
}
.assessment-key-factors ul {
    padding-left: 20px;
    margin: 0;
}
.assessment-key-factors li {
    margin-bottom: 4px;
    font-size: 13px;
}

/* ---- Compact summary cards (AC-6, AC-7) ----------------------------- */
.compact-card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
}
.compact-card-header h2 {
    font-size: 15px;
    color: #1E3A5F;
    margin: 0;
}
.count-badge {
    display: inline-block;
    background: #1E3A5F;
    color: #FFFFFF;
    border-radius: 999px;
    padding: 1px 8px;
    font-size: 12px;
    margin-left: 6px;
}
.compact-card-view-all {
    appearance: none;
    background: transparent;
    border: none;
    color: #1E3A5F;
    font-weight: 600;
    font-size: 13px;
    cursor: pointer;
    text-decoration: underline;
}
.compact-card-view-all:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: 2px;
}
.compact-card-empty {
    /* #777 = 4.47:1 on white, just below WCAG AA 4.5:1 floor for small text. */
    color: #6E6E6E;
    font-style: italic;
    margin: 0;
}
.compact-card-list {
    padding-left: 18px;
    margin: 0;
}
.compact-card-list li {
    margin-bottom: 4px;
    font-size: 13px;
    display: flex;
    justify-content: space-between;
    gap: 12px;
}
.compact-card-list .filename {
    font-weight: 500;
    color: #1E3A5F;
}

/* ---- Decision box (AC-11, AC-12, AC-13) ----------------------------- */
.decision-box h2 {
    font-size: 16px;
    color: #1E3A5F;
    margin: 0 0 12px 0;
}
.decision-box-hint {
    color: #666666;
    font-size: 13px;
    font-style: italic;
}
.decision-options {
    border: none;
    padding: 0;
    margin: 0 0 16px 0;
}
.decision-options legend {
    font-weight: 600;
    color: #1E3A5F;
    margin-bottom: 8px;
}
.decision-option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    border: 1px solid #DDDDDD;
    border-radius: 4px;
    margin-bottom: 6px;
    cursor: pointer;
}
.decision-option:hover {
    border-color: #1E3A5F;
}
.decision-option input:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: 2px;
}
.decision-attestation {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 16px;
    font-size: 13px;
    color: #444444;
}
.decision-comment-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 16px;
}
.decision-comment-field label {
    font-size: 13px;
    font-weight: 600;
    color: #1E3A5F;
}
.decision-comment-field textarea {
    min-height: 72px;
    padding: 8px 12px;
    border: 1px solid #DDDDDD;
    border-radius: 4px;
    font: inherit;
    resize: vertical;
}
.decision-comment-field textarea:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: 2px;
}
.decision-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.decision-submit-btn {
    appearance: none;
    background: #1E3A5F;
    color: #FFFFFF;
    border: none;
    border-radius: 4px;
    padding: 10px 20px;
    font-weight: 700;
    cursor: pointer;
}
.decision-submit-btn[disabled] {
    background: #BBBBBB;
    cursor: not-allowed;
}
.decision-submit-btn:focus-visible {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}
.decision-release-btn,
.decision-push-btn {
    appearance: none;
    background: transparent;
    color: #1E3A5F;
    border: 2px solid #1E3A5F;
    border-radius: 4px;
    padding: 8px 16px;
    font-weight: 600;
    cursor: pointer;
}
.decision-release-btn:hover,
.decision-push-btn:hover {
    background: #1E3A5F;
    color: #FFFFFF;
}

/* ---- Published decision panel (AC-18) + read-only Decision-box guidance
   (SPEC-017 AC-15, issue #518) — the latter reuses the same dt/dd field-list
   presentation via the shared .readonly-decision-fields selector below. ------- */
.published-decision-panel h2 {
    font-size: 16px;
    color: #1E3A5F;
    margin: 0 0 12px 0;
}
.published-decision-fields,
.readonly-decision-fields {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 0;
}
.published-decision-fields > div,
.readonly-decision-fields > div {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.published-decision-fields dt,
.readonly-decision-fields dt {
    font-size: 12px;
    color: #666666;
    font-weight: 600;
}
.published-decision-fields dd,
.readonly-decision-fields dd {
    margin: 0;
    color: #1E3A5F;
    font-weight: 600;
}
.decision-outcome-pill {
    display: inline-block;
    padding: 4px 12px;
    border-radius: 999px;
    color: #FFFFFF;
    font-weight: 700;
}
.decision-outcome-released { background: #2E7D32; }
.decision-outcome-detained { background: #C62828; }
.author-role {
    /* WCAG AA — see .compact-card-empty above. */
    color: #6E6E6E;
    font-weight: 500;
    font-size: 12px;
}
.signature-signed-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.signature-thumbnail {
    max-width: 160px;
    max-height: 60px;
    border: 1px solid #DDDDDD;
    background: #FFFFFF;
}
.signature-placeholder {
    color: #555555;
    font-style: italic;
}
/* Issue #2455 — proxied signature fetch fails (404/503): swap in place of the browser's
   broken-image glyph, matching the Admin -> Users signature-seal-preview-placeholder pattern.
   Native [hidden] is sufficient here (no explicit display override to fight, unlike the flex
   .signature-seal-preview-placeholder). */
.signature-thumbnail-placeholder {
    color: #555555;
    font-style: italic;
}

/* ---- Notes summary panel (AC-19) ------------------------------------ */
.notes-summary-panel h2 {
    font-size: 16px;
    color: #1E3A5F;
    margin: 0;
}
.notes-summary-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
}
.notes-view-all {
    appearance: none;
    background: transparent;
    border: none;
    color: #1E3A5F;
    font-weight: 600;
    cursor: pointer;
    text-decoration: underline;
}
.notes-empty {
    /* WCAG AA — see .compact-card-empty above. */
    color: #6E6E6E;
    font-style: italic;
    margin: 0 0 12px 0;
}
.notes-list {
    list-style: none;
    padding: 0;
    margin: 0 0 12px 0;
}
.notes-list li {
    padding: 8px 0;
    border-bottom: 1px solid #EEEEEE;
}
.notes-list li:last-child {
    border-bottom: none;
}
.note-preview {
    margin: 0 0 4px 0;
    color: #1E3A5F;
}
.notes-list time {
    font-size: 12px;
    /* WCAG AA — see .compact-card-empty above. */
    color: #6E6E6E;
}
.note-private-judicial {
    border-left: 3px solid #B26A00;
    padding-left: 10px;
}
.note-summary-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 4px;
}
/* Compact-panel content preview: render the stored rich text, clamped to a few lines. */
.notes-list .note-preview {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.notes-summary-error {
    /* WCAG AA — matches the .notes-empty muted tone; announced via role="alert". */
    color: #B00020;
    font-style: italic;
    margin: 0 0 12px 0;
}
.notes-summary-loading {
    color: #6E6E6E;
    font-style: italic;
    margin: 0 0 12px 0;
}

/* ---- Notes tab (SPEC-015 AC-7/AC-8/AC-9) ---------------------------- */
.notes-tab {
    display: flex;
    flex-direction: column;
    gap: 16px;
}
.notes-tab h2 {
    font-size: 18px;
    color: #1E3A5F;
    margin: 0;
}
.notes-banner {
    /* FR-12/AC-8 — plain italic advisory line at the top of the Notes tab. */
    font-style: italic;
    color: #5A6779;
    margin: 0;
}
.notes-tab-error {
    color: #B00020;
    font-style: italic;
    margin: 0;
}
.notes-tab-loading {
    color: #6E6E6E;
    font-style: italic;
    margin: 0;
}
.notes-card-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.note-card {
    border: 1px solid #EEEEEE;
    border-radius: 6px;
    padding: 12px 14px;
    background: #FFFFFF;
}
.note-card--private-judicial {
    border-left: 3px solid #B26A00;
}
.note-card-header,
.linked-note-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
    flex-wrap: wrap;
}
.note-author,
.linked-note-author {
    font-weight: 600;
    color: #1E3A5F;
}
.note-timestamp,
.linked-note-timestamp {
    font-size: 12px;
    /* WCAG AA muted tone. */
    color: #6E6E6E;
    margin-left: auto;
}
.note-content,
.linked-note-content {
    color: #1E3A5F;
}
.note-type-pill,
.linked-note-type-pill {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    background: #E6F0FA;
    color: #2B6CB0;
}

/* ---- Documents tab (SPEC-016 AC-1/AC-2/AC-3/AC-4/AC-5/AC-10) --------- */
.documents-tab-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}
.documents-tab h2 {
    font-size: 18px;
    color: #1E3A5F;
    margin: 0;
}
.document-upload-label {
    display: inline-flex;
    align-items: center;
    padding: 6px 14px;
    border: 1px solid #2B6CB0;
    border-radius: 6px;
    background: #2B6CB0;
    color: #FFFFFF;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}
.document-upload-label:has(input:disabled) {
    opacity: 0.6;
    cursor: default;
}
/* WCAG 2.4.7 (Focus Visible) — the file input is visually hidden (see
   .document-upload-input below), so :focus lands on a clipped 1x1px element with
   nothing visible to a keyboard user. This renders the ring on the visible label
   instead, matching the .k-button-primary:focus-visible precedent above (same
   3px navy outline / 2px offset). */
.document-upload-label:has(input:focus-visible) {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}
.document-upload-input {
    /* Visually hidden but still keyboard/AT-accessible via the wrapping <label>. */
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
.document-upload-error {
    color: #B00020;
    font-style: italic;
    margin: 0 0 12px 0;
}
.documents-tab-error {
    color: #B00020;
    font-style: italic;
    margin: 0;
}
.documents-tab-loading {
    color: #6E6E6E;
    font-style: italic;
    margin: 0;
}
.documents-empty {
    color: #6E6E6E;
    margin: 0;
}
.document-row-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.document-row {
    display: flex;
    align-items: center;
    gap: 12px;
    border: 1px solid #EEEEEE;
    border-radius: 6px;
    padding: 10px 14px;
    background: #FFFFFF;
}
.document-icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    padding: 2px 6px;
    border-radius: 4px;
    background: #F5F5F5;
    color: #555555;
    font-size: 11px;
    font-weight: 700;
}
.document-filename {
    flex: 1 1 auto;
    font-weight: 500;
    color: #1E3A5F;
}
/* Issue #2485 — AC-11's row-click affordance. Resets <button> chrome so the filename reads
   identically to the plain-<span> case (DocumentAvailabilityPolicy.SuppressesEgress rows), with
   underline + focus ring as the only visual signal that this one is interactive. */
button.document-filename-button {
    appearance: none;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    text-align: left;
    cursor: pointer;
}
button.document-filename-button:hover {
    text-decoration: underline;
}
button.document-filename-button:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: 2px;
}
.document-size {
    color: #6E6E6E;
    font-size: 13px;
}
.document-source-pill {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    background: #E6F0FA;
    color: #2B6CB0;
}
/* SPEC-015 AC-15 source-note tag ("FROM 1 NOTE"), rendered beside the provenance pill. A quieter
   neutral on purpose: the pill answers "where did this file come from", this tag answers "which
   note references it" — a secondary relationship that must not compete with provenance.
   #5A6779 on #EEF1F5 is 5.6:1 — WCAG 1.4.3 AA. */
.document-source-note-tag {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
    background: #EEF1F5;
    color: #5A6779;
}
.document-timestamp {
    font-size: 12px;
    /* WCAG AA muted tone. */
    color: #6E6E6E;
}
/* SPEC-016 AC-2 v1.8 scan-state indicator ("Scanning", "Scan timed out", ...) — rendered only while
   a row has not reached the Clean scan state (ADR-0039 §2).

   Deliberately NOT a fourth source pill: ADR-0039 §2 rejects that shape because scan state is not a
   provenance, so this shares no visual vocabulary with .document-source-pill / .document-source-note-tag.
   Square-ish corners (radius/md, 4px) instead of their 999px chip radius, a visible 1px border they
   do not have, and the Style Guide v5 warning pair rather than either of their tints — three
   independent axes of difference, so the two never read as members of one set.

   Colour is redundant to the visible text, which carries the state on its own (WCAG 2.1 SC 1.4.1).
   #8A6B25 on #FDF5E6 is 4.6:1 — SC 1.4.3 AA for text at this size. Both tokens are StyleGuide.cs's
   WarningPrimary / WarningTint; no new colour is introduced. */
.document-scan-state {
    display: inline-block;
    padding: 2px 8px;
    border: 1px solid #8A6B25;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 600;
    background: #FDF5E6;
    color: #8A6B25;
}
/* Holds the row's single "..." kebab since Issue #1277, which is why the gap has nothing left to
   space -- kept because a later second control in this slot would want it back, and because removing
   it changes nothing today. A <div> since #1277, not a <span>: RowActionsMenu's wrapper is a <div>
   and a <div> inside a <span> is invalid nesting. Still a flex item of .document-row either way.

   No :has() overflow lift here, unlike .conditions-table and .notifications-rules-table. Verified by
   reading every ancestor rather than assumed from those cases: neither .document-row-list,
   .document-row, .documents-tab nor .defendant-tab-content sets overflow, so nothing clips the
   absolutely-positioned panel. */
.document-row-actions {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 12px;
}
.document-download-error {
    color: #B00020;
    font-style: italic;
    margin: 0 0 12px 0;
}
.document-delete-error {
    color: #B00020;
    font-style: italic;
    margin: 0 0 12px 0;
}

/* ---- Document detail view (SPEC-016 AC-11, Task 11) — preview <iframe>
   beside the PR 7 annotation panel slot, per design.md's UI Component
   Breakdown ("<iframe> preview beside AnnotationPanel"). --------------- */
.document-detail-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}
.document-detail-header h2 {
    font-size: 18px;
    color: #1E3A5F;
    margin: 0;
}
.document-detail-close-btn {
    height: 36px;
    padding: 0 14px;
    border: 1px solid #CBD2DC;
    border-radius: 6px;
    background: #FFFFFF;
    font-size: 14px;
    color: #1A202C;
    cursor: pointer;
}
.document-detail-close-btn:hover {
    background: #F7F9FB;
}
.document-detail-close-btn:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 1px;
}
.document-detail-body {
    display: flex;
    gap: 16px;
    align-items: stretch;
}
.document-preview-frame {
    flex: 1 1 auto;
    width: 100%;
    height: 70vh;
    min-height: 480px;
    border: 1px solid #EEEEEE;
    border-radius: 6px;
    background: #FFFFFF;
}
/* #2898 slice 4: stands in for the preview frame when the document is not a PDF. Real text, so it
   reads without the frame (WCAG 1.3.1); the Download button keeps the close button's look. */
.document-preview-unavailable {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    padding: 24px;
    border: 1px solid #EEEEEE;
    border-radius: 6px;
    background: #FFFFFF;
    color: #1A202C;
}
.document-preview-unavailable p {
    margin: 0;
    font-size: 15px;
}
.document-detail-download-btn {
    height: 36px;
    padding: 0 14px;
    border: 1px solid #CBD2DC;
    border-radius: 6px;
    background: #FFFFFF;
    font-size: 14px;
    color: #1A202C;
    cursor: pointer;
}
.document-detail-download-btn:hover {
    background: #F7F9FB;
}
.document-detail-download-btn:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 1px;
}
.annotation-panel {
    /* Fixed side-column width, matching the reserved .document-annotation-panel-slot placeholder
       this replaces (SPEC-016 PR 7). Absent entirely (AC-11) when there are no linked notes and no
       load error, so .document-preview-frame's flex:1 fills the space with no empty gutter. */
    flex: 0 0 320px;
    overflow-y: auto;
    max-height: 70vh;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.annotation-panel-error {
    color: #B00020;
    font-style: italic;
    margin: 0;
}
.linked-note-card {
    display: flex;
    gap: 10px;
    border: 1px solid #EEEEEE;
    border-radius: 6px;
    padding: 12px 14px;
    background: #FFFFFF;
}
.linked-note-body-wrap {
    flex: 1 1 auto;
    min-width: 0;
}
/* .linked-note-header/-author/-timestamp/-content/-type-pill share their declarations with the
   .note-card family above (comma-joined) rather than a second hand-copied set — SPEC-016 PR 7
   review, Dean Kohler. */

/* ---- Push-to-queue dialog (AC-15) ----------------------------------- */
/*
   Native <dialog> (.modal-dialog supplies the frame + backdrop), NOT a TelerikDialog — same
   defect class as the bulk-push dialog above: Telerik does not re-render its Title parameter
   when only this component's own state changes, so the AC-15 interpolated title stayed stale
   after selecting a queue. See PushToQueueDialog.razor's own remarks. Layout mirrors the
   bulk-push dialog's header / body / actions structure immediately above.

   Width comes from the shared frame, as for the bulk-push dialog: the bare
   `.push-to-queue-dialog { width; max-width }` that used to sit here was outranked by the frame's
   `dialog.modal-dialog` and never applied, so it was removed (Issue #1295).
*/

.push-dialog-header {
    margin: 0 32px 12px 0;
}

.push-dialog-header h3 {
    margin: 0;
    font-size: 16px;
    line-height: 22px;
    font-weight: 600;
    color: #1E3A5F;
}

.push-dialog-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 16px;
}

/* Issue #1418: strip the UA fieldset chrome. <fieldset>/<legend> stay for the grouping
   semantics a screen reader needs over the radio set — only the presentation goes. `min-width: 0`
   is not cosmetic: UA stylesheets set `min-inline-size: min-content` on fieldset, which blocks
   shrinking inside the flex column `dialog.modal-dialog` establishes. */
.push-dialog-body fieldset {
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;
}

.push-dialog-body legend {
    padding: 0;
    font-size: 13px;
    line-height: 18px;
    font-weight: 600;
    color: #1E3A5F;
}

/* Issue #1418: states the dialog's purpose before a queue is picked. Rendered only when there
   are queues to choose — pairing "Select which queue..." with the empty state's "No other queue
   is available" would contradict itself. */
.push-dialog-description {
    margin: 0 0 12px;
    color: #555555;
}

.push-dialog-empty {
    color: #555555;
    font-style: italic;
}
.push-dialog-option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
}
.push-dialog-confirm-body {
    margin: 12px 0 0;
}

/* ---- Print media (AC-2) --------------------------------------------- */
@media print {
    .defendant-tab-strip,
    .defendant-header-actions,
    .amber-banner-actions,
    .decision-actions,
    .reconnect-indicator,
    .workspace-nav,
    .top-app-bar,
    .notes-view-all,
    .notes-summary-add,
    .notes-add-btn,
    /* AC-24 (Issue #2457) — interactive controls and Overview compact-card summaries
       that would otherwise duplicate the full sections print now shows alongside them.
       .decision-box is shared by DecisionBox.razor (interactive, pre-publish) AND
       ReadOnlyDecisionGuidance.razor (decision-box decision-box-readonly) — both must
       stay out of print; PublishedDecisionPanel.razor uses the distinct
       .published-decision-panel class and is deliberately NOT on this list, so the
       actual published decision (when one exists) still prints. */
    .document-upload-label,
    .document-row-actions,
    .conditions-picker-print-hide,
    .applied-condition-actions,
    .applied-condition-edit-actions,
    .note-card-actions,
    .note-card-attachment-remove,
    /* SPEC-015 AC-32 — an author's unpublished drafts are private to them and are not part of the
       record. SPEC-013 AC-24 prints the Notes tab's content, so they are suppressed here explicitly
       rather than left to inherit: a printed page leaves the author's control entirely. */
    .note-draft-list,
    .compact-documents-card,
    .compact-conditions-card,
    .notes-summary-panel,
    .decision-box {
        display: none !important;
    }
    .defendant-sticky-region {
        position: static;
    }
    .defendant-header {
        box-shadow: none;
    }
    .overview-tab-content {
        grid-template-columns: 1fr;
    }
    /* AC-24 — reveal every always-mounted panel together, regardless of which one is
       the on-screen "active" tab; tab-panel--audit-only overrides it back off for the
       one tab (Audit History) that stays out of print even when it happens to be the
       active/mounted panel. */
    .defendant-tab-content .tab-panel {
        display: block !important;
    }
    .defendant-tab-content .tab-panel--audit-only {
        display: none !important;
    }
}

/* ---------------------------------------------------------------------------
   User detail page — UserDetailPage
   --------------------------------------------------------------------------- */

.user-detail-page {
    max-width: 1040px;
}

.user-detail-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    list-style: none;
    margin: 0 0 20px;
    padding: 0;
    font-size: 13px;
    line-height: 18px;
    color: #5A6779;
}

/* AC-19 (Issue #1258 follow-up): "/" per Style Guide v5 §2.5, matching the separator every
   admin list page uses (SPEC-003 AC-13) -- was "›" before spec v1.5. */
.user-detail-breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-left: 6px;
    color: #A0AAB8;
}

.user-detail-breadcrumb li[aria-current="page"] {
    color: #1A202C;
    font-weight: 600;
}

/* The paired [aria-disabled] CSS the accessible-disabled house rule requires. The breadcrumb
   "Users" link is aria-disabled rather than natively inert while a write holds the circuit write
   gate (issue #1193), so without this it is computed-style identical to a live sibling — cursor:
   pointer, opacity: 1 — and reads as operable, the same gap PR #1865 closed for .page-btn. axe
   has no rule that catches an aria-disabled control that still LOOKS operable. The :hover arm here
   is defensive rather than corrective, and that differs from the other two blocks: app.css gives
   this link no base rule and no hover rule, so the text-decoration being suppressed is the UA
   default, which is not hover-conditional. Kept because the Kendo theme loads ahead of app.css
   (src/Dredd.Client/App.razor) and an a:hover from it was not ruled out. */
.user-detail-breadcrumb a[aria-disabled="true"],
.user-detail-breadcrumb a[aria-disabled="true"]:hover {
    cursor: not-allowed;
    opacity: 0.4;
    text-decoration: none;
}

.user-detail-header {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    margin-bottom: 28px;
}

.user-detail-avatar {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 9999px;
    color: #FFFFFF;
    font-size: 20px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.3px;
}

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

.user-detail-identity h1 {
    font-size: 22px;
    font-weight: 700;
    line-height: 30px;
    color: #1A202C;
    margin: 0 0 4px;
}

.user-detail-email {
    margin: 0 0 10px;
    font-size: 14px;
    line-height: 20px;
    color: #5A6779;
}

.user-detail-roles-inline {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.user-detail-role-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 10px;
    border-radius: 9999px;
    background: #EEF2F7;
    color: #2D3748;
    font-size: 12px;
    font-weight: 600;
    line-height: 18px;
}

/* Role assignment section (Task 8). The pill list reuses .user-detail-role-pill as its <li>. */
.user-detail-role-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
}

.user-detail-role-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    padding: 0;
    border: none;
    border-radius: 9999px;
    background: transparent;
    color: #5A6779;
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
    /* SPEC-021 Task 5: raised to the Style Guide's own 40px pointer minimum (AC-7).
       This is the worst offender in the inventory (explicit 16x16, below even the
       WCAG 2.2 AA 24px floor) -- min-width/min-height win over the explicit
       width/height above, so the rendered hit area grows to 40x40 (still circular,
       border-radius: 9999px). Visibly larger than today by design (OQ-D4). */
    min-width: 40px;
    min-height: 40px;
}

.user-detail-role-remove:hover {
    background: #D9E0E8;
    color: #1A202C;
}

.user-detail-role-remove:focus-visible,
.user-detail-role-remove:focus {
    outline: 2px solid #1E3A5F;
    outline-offset: 1px;
}

.user-detail-role-add {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    color: #2D3748;
}

.user-detail-role-add select {
    padding: 6px 10px;
    border: 1px solid #C3CAD6;
    border-radius: 6px;
    font-size: 14px;
}

.user-detail-role-add-empty {
    font-size: 13px;
    color: #5A6779;
    margin: 0;
}

.user-detail-section {
    padding: 20px 24px;
    margin-bottom: 20px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
}

.user-detail-section h2 {
    font-size: 16px;
    font-weight: 700;
    line-height: 22px;
    color: #1A202C;
    margin: 0 0 16px;
}

.user-detail-section dl {
    display: grid;
    grid-template-columns: max-content 1fr;
    /* The Phone row's <dd> holds 44px controls; Created and Last Active hold one line of
       text each. Centring keeps every <dt> level with its own <dd> instead of pinning the
       Phone label to the top of a tall row. A no-op on the two text rows. */
    align-items: center;
    gap: 8px 24px;
    margin: 0;
}

.user-detail-section dt {
    font-size: 13px;
    font-weight: 600;
    color: #5A6779;
}

.user-detail-section dd {
    margin: 0;
    font-size: 14px;
    color: #1A202C;
}

/* The Phone row is the only <dd> in this <dl> that holds controls, so it needs a row
   layout the two text rows do not. Without it the input, Save and Cancel sit in raw
   inline flow separated by nothing but source whitespace. */
.user-detail-phone {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
}

/* The validation message takes its own line below the controls instead of becoming a
   fourth item in the row. .error-message is a padded red card, not an inline hint, so
   left in the row it would stretch the row's height on every rejection. */
.user-detail-phone-error {
    flex-basis: 100%;
}

/* The Phone row's buttons carry NO height override, deliberately. `.btn-primary` (Edit,
   Save) and `.btn-secondary` (Cancel) each already declare Style Guide v5 §2.1's 36px
   Default — the height this row wants, and the height the Revoke button in the Sessions
   table below renders at. The input is scoped down to match; see .user-detail-phone-input
   beside the shared input group. Do not reintroduce a height here: the previous 44px
   override needed compound selectors purely to beat the later-declared `.btn-secondary`,
   and removing it removes that cascade hazard rather than papering over it. */

.user-detail-sessions-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}

.user-detail-sessions-table th {
    font-family: var(--font-accent);
    text-align: left;
    padding: 8px 12px;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: #5A6779;
    border-bottom: 1px solid #E1E5EB;
}

.user-detail-sessions-table td {
    padding: 10px 12px;
    color: #1A202C;
    border-bottom: 1px solid #EEF0F3;
}

.user-detail-sessions-table tbody tr:last-child td {
    border-bottom: none;
}

/* Account actions button row inside the standard section card (Task 7). */
.user-detail-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 12px;
}

/* Reset password — neutral/secondary action (Reactivate is .btn-primary, Deactivate is .btn-danger). */
.user-detail-reset-password {
    padding: 8px 16px;
    font-size: 14px;
    font-weight: 600;
    color: #1E3A5F;
    background: #FFFFFF;
    border: 1px solid #C3CAD6;
    border-radius: 6px;
    cursor: pointer;
}

.user-detail-reset-password:hover {
    background: #F4F6F9;
}

.user-detail-reset-password:focus-visible,
.user-detail-reset-password:focus {
    outline: 2px solid #1E3A5F;
    outline-offset: 2px;
}

/* Resend invite — same neutral/secondary treatment as Reset password (Task 5, issue #352). */
.user-detail-resend-invite {
    padding: 8px 16px;
    font-size: 14px;
    font-weight: 600;
    color: #1E3A5F;
    background: #FFFFFF;
    border: 1px solid #C3CAD6;
    border-radius: 6px;
    cursor: pointer;
}

.user-detail-resend-invite:hover {
    background: #F4F6F9;
}

.user-detail-resend-invite:focus-visible,
.user-detail-resend-invite:focus {
    outline: 2px solid #1E3A5F;
    outline-offset: 2px;
}

/* Danger Zone — high-severity treatment (red border) per Style Guide v5 4-severity model. */
.user-detail-danger-zone {
    padding: 20px 24px;
    margin-top: 8px;
    background: #FEF5F5;
    border: 1px solid #C53030;
    border-radius: 8px;
}

.user-detail-danger-zone h2 {
    font-size: 16px;
    font-weight: 700;
    color: #9B2C2C;
    margin: 0 0 12px;
}

.user-detail-skeleton {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 240px;
}

.user-detail-skeleton-spinner {
    width: 32px;
    height: 32px;
    border: 3px solid #E1E5EB;
    border-top-color: #1E3A5F;
    border-radius: 9999px;
    animation: user-detail-spin 0.8s linear infinite;
}

@keyframes user-detail-spin {
    to { transform: rotate(360deg); }
}

.user-detail-not-found {
    padding: 40px;
    text-align: center;
    color: #5A6779;
    font-size: 14px;
    line-height: 22px;
}

.user-detail-not-found a {
    display: inline-block;
    margin-top: 12px;
}

/* ---------------------------------------------------------------------------
   User detail — session revoke controls (Task 6)
   --------------------------------------------------------------------------- */

.success-message {
    background: #F0FDF4;
    border: 1px solid #86EFAC;
    border-radius: 6px;
    color: #15803D;
    font-size: 14px;
    line-height: 20px;
    padding: 12px 16px;
    margin-bottom: 16px;
}

.user-detail-session-revoke {
    padding: 4px 12px;
    font-size: 13px;
}

.user-detail-revoke-all {
    margin-top: 16px;
}

/* ---------------------------------------------------------------------------
   SPEC-009 — Signature & seal card (Task 9). Sizes/tokens mirror the existing
   user-detail-* rules above so the card reads as the same design system.
   --------------------------------------------------------------------------- */

.signature-seal-card .signature-seal-row + .signature-seal-row {
    margin-top: 20px;
    padding-top: 20px;
    border-top: 1px solid #EEF0F3;
}

.signature-seal-row-title {
    font-family: var(--font-accent);
    font-size: 13px;
    font-weight: 600;
    color: #5A6779;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    margin: 0 0 10px;
}

.signature-seal-row-error,
.signature-seal-load-error {
    padding: 8px 12px;
    margin: 0 0 10px;
    background: #FCEBEA;
    color: #8A1A12;
    border-radius: 6px;
    font-size: 13px;
}

.signature-seal-row-filled {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
}

/* #1349 plan PR 10 — a replacement under scan on an already-served row (AC-8's retain-until-clean).
   flex-basis: 100% forces it (and everything after it) onto its own line within the flex-wrap row
   above, rather than squeezing in as another column next to the preview image. */
.signature-seal-row-pending-note {
    flex-basis: 100%;
    margin: 0;
    font-size: 13px;
    color: #8A6B25;
    background: #FDF5E6;
    border-radius: 6px;
    padding: 6px 10px;
}

/* #1349 plan PR 10 — a first-ever upload still under scan, so there is no served image to show
   alongside it (AC-7/AC-12). A vertical stack, not the filled row's horizontal layout. */
.signature-seal-row-pending {
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: flex-start;
}

.signature-seal-preview {
    /* requirements.md: "image rendered as-is, no crop/background fill" — no background here so a
       transparent-background PNG (the common case for a signature/seal) renders as intended. */
    width: 96px;
    height: 48px;
    object-fit: contain;
    border: 1px solid #E1E5EB;
    border-radius: 6px;
}

/* spec.md Edge Cases — proxied preview unavailable at render time: no broken-image icon, no error
   surfaced. Sized to match .signature-seal-preview so the row layout doesn't shift on swap. */
.signature-seal-preview-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 96px;
    height: 48px;
    border: 1px solid #E1E5EB;
    border-radius: 6px;
    background: #F7F9FB;
    color: #5A6779;
    font-size: 11px;
    font-style: italic;
    text-align: center;
}

.signature-seal-preview-placeholder[hidden] {
    display: none;
}

.signature-seal-row-meta {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
    min-width: 0;
}

.signature-seal-filename {
    font-size: 14px;
    color: #1A202C;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.signature-seal-filesize {
    font-size: 12px;
    color: #5A6779;
}

.signature-seal-row-actions {
    display: flex;
    gap: 10px;
    flex-shrink: 0;
}

.signature-seal-replace-label {
    position: relative;
    display: inline-flex;
    align-items: center;
    height: 36px;
    padding: 0 14px;
    border: 1px solid #CBD2DC;
    border-radius: 6px;
    background: #FFFFFF;
    font-size: 14px;
    color: #1A202C;
    cursor: pointer;
}

.signature-seal-replace-label:hover {
    background: #F7F9FB;
}

/* WCAG 2.4.7 (Focus Visible) — the file input underneath is opacity:0, so :focus lands on an
   invisible element with nothing visible to a keyboard user. Renders the ring on the visible
   label instead, matching the .document-upload-label:has(input:focus-visible) precedent. */
.signature-seal-replace-label:has(input:focus-visible) {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}

.signature-seal-dropzone {
    position: relative;
    padding: 20px;
    text-align: center;
    border: 2px dashed #C3CAD6;
    border-radius: 8px;
    background: #FAFBFC;
}

.signature-seal-dropzone:has(.signature-seal-dropzone-input:hover) {
    border-color: #2B6CB0;
    background: #F4F8FC;
}

/* WCAG 2.4.7 (Focus Visible) — same rationale as .signature-seal-replace-label above. */
.signature-seal-dropzone:has(.signature-seal-dropzone-input:focus-visible) {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}

.signature-seal-dropzone-copy {
    margin: 0 0 4px;
    font-size: 14px;
    color: #1A202C;
}

.signature-seal-upload-cta {
    color: #1E3A5F;
    font-weight: 600;
    text-decoration: underline;
}

.signature-seal-hint {
    margin: 0;
    font-size: 12px;
    color: #5A6779;
}

.signature-seal-empty-copy {
    margin: 0;
    font-size: 14px;
    color: #5A6779;
}

/* The actual <input type="file"> InputFile renders is stretched invisibly over the whole
   dropzone/replace-label so both click-to-browse and native OS drag-and-drop onto the element
   fire the same InputFile OnChange handler (AC-4) — no custom drag/drop JS interop needed. */
.signature-seal-dropzone-input,
.signature-seal-hidden-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

/* ---------------------------------------------------------------------------
   SPEC-008 — Invite user flow (admin side): AC-2 disabled state + InviteUserModal.
   Sizes/tokens mirror the existing Roles/Admin/Users pages so the new surfaces
   read as the same design system. (The invitee-side account-setup styles ship
   with AccountSetupPage in PR 4b.)
   --------------------------------------------------------------------------- */

/* AC-2 — disabled "Invite user" button + tooltip wrapper. position: relative so the visually-
   hidden tooltip span (WCAG 1.3.1 / 3.3.1) can be positioned relative to the button without
   affecting layout flow; the native title attribute on the wrapper gives sighted mouse users a
   hover tooltip while the sr-only span gives assistive tech an accessible description. */
.invite-btn-wrapper {
    position: relative;
    display: inline-block;
}

/* AC-2 — visual disabled treatment for the aria-disabled "Invite user" button. The accessible-
   disabled markup uses aria-disabled (not native `disabled`) so the button stays focusable and AT
   can reach the aria-describedby explanation — but that means `.btn-primary:disabled` never matches
   and `.btn-primary:hover` still fires, painting a fully-active CTA that lifts on hover. This rule
   restores the design.md-intended disabled affordance (opacity + not-allowed) and neutralizes the
   hover so the control reads as disabled to sighted users too (WCAG 1.4.1-adjacent perceivability). */
.btn-primary[aria-disabled="true"],
.btn-primary[aria-disabled="true"]:hover {
    opacity: 0.4;
    cursor: not-allowed;
    background: #1E3A5F;
}

/* Invite user modal — dialog surface layered on the shared dialog.modal-dialog frame.

   This selector is (0,1,0) and the frame is (0,1,1), so seven of its eight declarations never
   applied. Six are now deleted on the PO ruling in Issue #1295, which chose the flat shared frame:
   `padding: 0` and `border-radius: 12px` differed from what ships, and `background`, `display`,
   `flex-direction` and `max-width` merely restated the frame's own values. Deleting a declaration
   the cascade already discards cannot change rendering, so this is render-neutral.

   Two consequences of that ruling are worth having written down, because both are visible and both
   were accepted rather than missed. `.invite-modal-header` owns a `border-bottom` and
   `.invite-modal-footer` a `border-top`, and with the frame's 32px padding winning, those dividers
   are inset 32px on each side and never reach the card edges. And the card ships the frame's 8px
   corners rather than 12px — which is the correct token: Style Guide v5 §1.5 assigns `radius / lg`
   8px to "Cards, panels, modals" and reserves `radius / xl` 12px for "Login card, hero surfaces",
   so the dead rule was asking for the wrong value. (§2.7 says `radius/xl` for modals and therefore
   contradicts §1.5; that is a Style-Guide defect the PO has taken separately, and it is the likely
   source of the 12px here.)

   `width: 100%` is the one declaration still standing, and still dead. It differs from the frame's
   `calc(100% - 48px)`, and with `box-sizing: border-box` live it is the widest-reaching of the three
   — activating it would take the card edge-to-edge below a ~528px viewport, removing the frame's
   24px gutters (400px instead of 352px at a 400px viewport, measured). It was found after the
   ruling was given, so it is held pending confirmation rather than deleted alongside the rest.
*/
/* `width: 100%` was deleted here with the other six dead declarations (Issue #1295).
   It never applied — (0,1,0) loses to the frame's `calc(100% - 48px)` — so removing it
   changes nothing rendered. It is gone rather than exempted because leaving it armed a
   trap: type-qualifying this selector is the documented next step if the sectioned
   layout is ever revisited, and that single move would have made `width: 100%` win and
   taken the card edge-to-edge below a 528px viewport, losing the frame's 24px gutters.
   The lint goes quiet exactly when the selector is prefixed, so nothing would have
   caught it. If width is ever wanted here, derive it from the frame deliberately.

   `box-sizing: border-box` stays and is load-bearing: app.css has no global box-sizing
   reset (it is set per-selector at :31, :126, :137, :255 and elsewhere) and nothing else
   sets it on this dialog. */
.invite-modal {
    box-sizing: border-box;
}

.invite-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px 24px;
    border-bottom: 1px solid #E1E5EB;
}

.invite-modal-header h3 {
    font-size: 18px;
    font-weight: 700;
    line-height: 24px;
    color: #1A202C;
    margin: 0;
}

.invite-modal-body {
    padding: 20px 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.invite-modal-footer {
    padding: 16px 24px;
    border-top: 1px solid #E1E5EB;
}

/* ---------------------------------------------------------------------------
   SPEC-008 — Invitee account-setup page (first-sign-in). Mirrors the
   .signin-card surface in the login shell. (The admin-side invite modal +
   AC-2 disabled-button styles ship with PR 4a.)
   --------------------------------------------------------------------------- */

/* Account setup page (first-sign-in) — mirrors the .signin-card surface in the login shell. */
.account-setup-page {
    display: flex;
    flex-direction: column;
}

.setup-card {
    width: 100%;
    max-width: 420px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 12px;
    padding: 32px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    box-sizing: border-box;
}

.setup-card h1 {
    font-size: 22px;
    line-height: 30px;
    font-weight: 700;
    color: #1E3A5F;
    margin: 0;
}

.setup-card-identity {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.setup-card-identity p {
    margin: 0;
    font-size: 14px;
    line-height: 20px;
    color: #1A202C;
}

.setup-card-identity p:first-child {
    font-weight: 600;
}

.password-requirements {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.password-requirements-item {
    font-size: 12px;
    line-height: 18px;
    color: #5A6779;
}

/* Invalid/expired/consumed link states — same card surface as .setup-card, centered copy. */
.setup-token-state {
    width: 100%;
    max-width: 420px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 12px;
    padding: 32px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.setup-token-state p {
    margin: 0;
    font-size: 14px;
    line-height: 22px;
    color: #1A202C;
}

/* ---- Conditions Library admin (SPEC-014 PR 1b) ---------------------------- */

/* AC-28: no page-level max-width cap (Issue #1258 follow-up) -- ratifies what was already true
   (this rule never carried one) as the standard, so a later revision cannot reintroduce a cap
   without amending AC-28. */
.conditions-page {
    padding: 24px 32px;
}

.conditions-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}

.conditions-header h1 {
    margin: 0;
    font-size: 24px;
    color: #1A202C;
}

.conditions-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    font-size: 13px;
    line-height: 18px;
    color: #5A6779;
}

.conditions-breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-left: 6px;
    color: #A0AAB8;
}

.conditions-breadcrumb li[aria-current="page"] {
    color: #1A202C;
    font-weight: 600;
}

/* AC-26 static page description, directly beneath the <h1>. */
.conditions-page-description {
    margin: 0 0 16px;
    color: #5A6779;
    font-size: 14px;
    line-height: 20px;
}

/* AC-27 summary line (active · archived counts). Sits between the filter bar and the
   table/empty-state, since the counts depend on _result being loaded (unlike the breadcrumb and
   description above, which render unconditionally). */
.conditions-summary-line {
    margin: 0 0 16px;
    color: #5A6779;
    font-size: 13px;
    line-height: 18px;
}

.conditions-policy-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    margin-bottom: 16px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
}

.conditions-policy-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    color: #1A202C;
    cursor: pointer;
}

.conditions-filter-bar {
    margin-bottom: 12px;
}

.conditions-filter-select {
    height: 36px;
    padding: 0 12px;
    border: 1px solid #CBD2DC;
    border-radius: 6px;
    background: #FFFFFF;
    font-size: 14px;
    color: #1A202C;
}

.conditions-filter-select:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 1px;
}

.conditions-table {
    width: 100%;
    border-collapse: collapse;
    background: #FFFFFF;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid #E1E5EB;
}

.conditions-table th,
.conditions-table td {
    text-align: left;
    padding: 12px 16px;
    border-bottom: 1px solid #EEF0F3;
    font-size: 14px;
    color: #1A202C;
    vertical-align: top;
}

.conditions-table th {
    font-weight: 600;
    color: #5A6779;
    background: #F7F9FB;
}

.condition-text-cell {
    max-width: 520px;
    line-height: 22px;
}

.condition-usage-cell {
    font-family: var(--font-accent);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* One kebab, not three link-buttons, since Issue #1277 -- so the old flex row has nothing left to
   space, and a flex <td> drops out of the table's column-width algorithm. Right-aligned to match
   .row-actions-cell's own justify-content: flex-end. */
.condition-actions-cell {
    text-align: right;
    white-space: nowrap;
}

/* .conditions-table sets `overflow: hidden` to clip its 8px corner radius, which also clips the
   absolutely-positioned row-actions panel -- the same defect Telerik's five grid ancestors cause on
   the Notes surface, measured here by reading the rule rather than assumed from that case. Lifting
   the clip is scoped with :has() so it applies ONLY while a panel is mounted: with every menu closed
   the table keeps `overflow: hidden` and its corner clip exactly as before.

   The lift stays even though the shared block below DOES apply `position: fixed` to the panel, which
   escapes this clip on its own. It is the fallback path, not a duplicate: CSS anchor positioning is
   Chromium-only today, and where the `@supports` condition fails the panel is still `absolute` and
   this lift is the only thing that reveals it. So on Chromium the lift no longer rescues the panel --
   it only suspends the corner clip, which is the trade-off recorded next.

   Trade-off to verify by hand: while a panel is open the table's own corner clip is suspended, so the
   last row's square background corner can peek past the radius. Cosmetic, and only for as long as a
   menu is open. */
.conditions-table:has(.row-actions-menu) {
    overflow: visible;
}

/* ---- Shared row actions overflow menu (Issues #1106, #1277) ------------
   The admin-list mockups render a row's actions as a single "..." kebab in a trailing column, and
   Style Guide v5 §4.5 makes that the row-action convention. Replaces inline link-button clusters,
   which had no spacing rules and so sat closer than §3.3's 8px adjacent-target minimum. Every value
   below snaps to a §1.4 8-point-grid token.

   Renamed from .note-type-actions-* by #1277 when the Note Types one-off became the shared
   RowActionsMenu component. Renamed rather than duplicated: a parallel class set would leave two
   trigger sizes free to drift, which is the inconsistency #1277 exists to remove. */

.row-actions-cell {
    position: relative;
    display: flex;
    justify-content: flex-end;
}

/* 40x40, not §2.1 Icon-only's 32x32 nominal: §1.7 and §3.3 both state a 40px pointer MINIMUM, and a
   minimum governs a nominal. Border and icon colour are §2.1 Icon-only's own tokens.

   ADR-0018's prose bullet says "44x44px touch targets", which contradicts the Style Guide's 40px
   minimum cited above. Kept at 40 by #1277 so every surface matches the shipped Notes trigger, and
   the contradiction is tracked separately rather than settled inside a cosmetic PR. One fact bounds
   it: WCAG 2.1 SC 2.5.5 Target Size is Level AAA, and the 44x44 minimum at AA is SC 2.5.8, which
   arrived in WCAG 2.2. ADR-0018's stated conformance target is WCAG 2.1 AA, so 40x40 does not breach
   the target it names — only the bullet, which appears to have imported a 2.2-era number. */
.row-actions-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    background: #FFFFFF;
    color: #5A6779;
    border: 1px solid #E1E5EB;
    border-radius: 6px;
    font-family: inherit;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
}

.row-actions-trigger:hover {
    background: #F7F9FB;
}

/* Outline-only, and declared on :focus-visible alone — no bare :focus visual override, so the
   framework's own focus state is never silently replaced (WCAG 2.4.7). Mirrors .link-button. */
.row-actions-trigger:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 2px;
}

.row-actions-trigger:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* elevation/2 (§1.6) — the token the guide assigns to "Dropdown menus, popovers". radius/lg for a
   panel.

   Z-INDEX BANDS — the single source of truth for this stylesheet. `.top-app-bar`'s own comment
   points here.

     10      per-page sticky regions      .defendant-sticky-region
     15      the bar's own dropdown       .topnav-menu-backdrop — INSIDE .top-app-bar's stacking
             dismissal layer              context alongside the row below; outranks nothing at
                                          the page level, only needs to sit under its own panel
     20      the bar's own dropdowns      .notification-bell-panel, .user-chip-menu — these sit
                                          INSIDE .top-app-bar's stacking context, so they ride on
                                          its 40 and never compete with the page band directly
     40      global top app bar           .top-app-bar
     50-51   transient popover layer      .row-actions-backdrop (50), this panel (51)
     900+    overlay band                 .notification-toasts, dialog.modal-dialog,
                                          .reconnect-indicator, .note-composer

   This pair sat at 30/31 until issue #2523. That put it inside the in-page band, which held only
   while the top app bar sat at 10. PR #2498 raised the bar to 40 to outrank every per-page sticky
   region — correct on its own terms, and it silently took the bar above the dismissal backdrop as
   well. The pair belongs ABOVE global chrome, not inside the page band: a row-actions menu is a
   transient popover, and a popover has to dismiss over whatever it opens on top of.

   The two values move together and their ORDER is load-bearing. The backdrop has to outrank the
   chrome it dismisses over, and the panel has to outrank the backdrop, or the backdrop covers the
   menu items. Keep 51 > 50 > 40. */
.row-actions-menu {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    z-index: 51;
    display: flex;
    flex-direction: column;
    min-width: 160px;
    padding: 4px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(16, 24, 40, 0.08);
}

/* §2.1 Default size (36px, 13px/600) — the size the guide assigns to controls inside table rows. */
.row-actions-menu-item {
    display: flex;
    align-items: center;
    width: 100%;
    height: 36px;
    padding: 0 16px;
    background: none;
    color: #1A202C;
    border: none;
    border-radius: 6px;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
}

.row-actions-menu-item:hover {
    background: #F7F9FB;
}

/* Inset offset so the ring is not clipped by the menu's own 4px padding and rounded corners. */
.row-actions-menu-item:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: -2px;
}

/* §2.1 Destructive: #B84D4D text on #FFFFFF, #FDECEC hover. */
.row-actions-menu-item--danger {
    color: #B84D4D;
}

.row-actions-menu-item--danger:hover {
    background: #FDECEC;
}

/* Catches an outside click so the menu dismisses without JS interop. Transparent and below the menu;
   the menu's own z-index lifts it clear of this layer.

   This element IS the outside-click contract — RowActionsMenu.razor binds @onclick="CloseAsync" to
   it and has no other pointer dismissal path. So it must outrank every sticky or fixed page chrome
   element it covers, or the click hit-tests to that chrome instead and nothing closes. The band
   table at .row-actions-menu carries the numbers; read it before you change this value.

   The failure is quiet, and that is what makes it worth a comment. Escape dismissal keeps working
   because a keypress never hit-tests, so the component looks healthy on a keyboard walk while the
   pointer gesture is dead. Issue #2523 is the worked example: PR #2498 raised .top-app-bar from 10
   to 40 above this 30, and a click anywhere in the bar's top 56px band stopped dismissing an open
   menu on all five call sites. */
.row-actions-backdrop {
    position: fixed;
    inset: 0;
    z-index: 50;
    background: transparent;
}

/* The panel is absolutely positioned, so it counts toward the SCROLLABLE OVERFLOW of whatever
   scroll container it sits in. On the admin surfaces that container is `.admin-main-content`
   (`overflow: auto`), so opening a menu on a row near the bottom grew it from 383px to 436px and
   raised a scrollbar the user then had to drag to reach the last item. Reported after #1277 shipped
   to the dev app; measured, not inferred.

   Two fixes were rejected before this one, both by measurement:

     * Lifting `overflow` on `.admin-main-content` with the same `:has()` trick used below. Chrome
       zeroes a scroll container's scrollTop for as long as `overflow` is `visible` and restores it
       when it returns to `auto` (verified in isolation: 250 -> 0 -> 250). So on any list long enough
       to scroll, opening a kebab would jerk the view to the top and back. That is worse than the
       scrollbar it removes.
     * `position-try-fallbacks: flip-block` alone, keeping `position: absolute`. It does not flip,
       because the panel is not anchor-positioned -- and an absolute panel still extends the scroll
       container even when it does flip.

   What works is taking the panel out of the scroll container's overflow entirely with
   `position: fixed`, and letting CSS ANCHOR POSITIONING keep it glued to its own row's trigger.
   That answers the objection recorded against `position: fixed` in the Telerik note below -- "it
   detaches from the trigger on any scroll, and re-anchoring it needs JS interop plus a scroll
   listener plus a DotNetObjectReference callback" -- because the anchor engine re-positions natively
   on scroll, with no JS at all. The whole feature stays JS-free.

   `anchor-scope` is what makes this per-row: every `.row-actions-cell` publishes the same
   `--row-actions-trigger` name, and without scoping every panel would resolve to whichever cell came
   last in the document. `position-area: block-end span-inline-start` reproduces the old
   `top: calc(100% + 4px); right: 0` placement (below the trigger, right edges flush), and
   `position-try-fallbacks: flip-block` puts the panel ABOVE the trigger when there is not room
   below -- measured at a 380px viewport: trigger at y330-370, panel flipped to y208-326, fully on
   screen. `top`/`right` are cleared because `position-area` computes the insets itself.

   Wrapped in `@supports` deliberately. CSS anchor positioning is Chromium-only today, and this file
   declares no browser baseline. Where it is unavailable the rules above stand unchanged and the
   `:has()` overflow lifts below remain the mechanism -- i.e. the surface behaves exactly as it did
   before this block existed, scrollbar included. This is an enhancement on top of a working
   fallback, not a replacement for it, which is why none of those lifts is deleted.

   The condition tests THREE properties, and the third is not padding. `anchor-scope` shipped in
   Chromium 131; `anchor-name` and `position-area` shipped in 125. Test only the first two and
   Chrome 125-130 PASS the query, apply this block, and then ignore the one declaration that makes
   the anchoring per-row -- so every panel resolves to whichever cell came last in the document and
   opens detached, under the wrong row. That version window is realistic for the lagging enterprise
   environments this product serves. Testing all three sends 125-130 down the `:has()` fallback,
   which works. Raised by Grayson Wiggins on PR #1395. Do NOT simplify the query back to two tests. */
@supports (anchor-name: --a) and (position-area: block-end) and (anchor-scope: --a) {
    .row-actions-cell {
        anchor-name: --row-actions-trigger;
        anchor-scope: --row-actions-trigger;
    }

    .row-actions-menu {
        position: fixed;
        position-anchor: --row-actions-trigger;
        position-area: block-end span-inline-start;
        position-try-fallbacks: flip-block;
        top: auto;
        right: auto;
        margin-block-start: 4px;
    }
}

/* Telerik clips an in-cell popup at FIVE ancestors between the cell and the page — measured in the
   dev app: td.k-table-td (hidden), .k-grid-content (auto scroll), .k-grid-container (hidden),
   .k-grid-aria-root (hidden) and .k-grid itself (hidden). Without this the panel renders but is
   invisible. Lifting the clip is scoped with :has() so it applies ONLY while a panel is mounted:
   with the menu closed .k-grid-content keeps its own overflow-y: scroll and the grid behaves exactly
   as Telerik ships it. Verified both ways in the dev app (closed -> "scroll", open -> "visible").

   :has() rather than position: fixed on the panel. Fixed would also escape all five (none of the
   ancestors sets a transform, so none creates a containing block), but it detaches the panel from the
   trigger on any scroll, and re-anchoring it needs JS interop plus a scroll listener plus a
   DotNetObjectReference callback to close — three new failure modes on a Blazor circuit, for a
   presentation fix. This keeps the whole feature JS-free.

   That objection is answered, and the choice is no longer either/or: the `@supports` block above
   DOES apply `position: fixed`, and the anchor engine re-positions on scroll with no JS. So on
   Chromium these lifts are dead while a menu is open -- the panel already escapes all five
   ancestors on its own. They stay because they are the ENTIRE mechanism on any browser without
   anchor positioning, which is the only place the objection above still reads true.

   Scoped to a .k-grid that actually contains one of these panels, so no other Telerik grid is
   affected. The CELL flip is additionally scoped with its own :has(), so only the Actions cell holding
   the open panel loses its clip and every other cell in the row keeps Telerik's overflow: hidden
   (raised by Dean Kohler on PR #1209; verified both ways in the dev app).

   Worth recording what that narrowing does and does NOT fix here, because the wider selector looks
   more dangerous than it measured. Telerik ships `.k-table-td { white-space: nowrap; text-overflow:
   ellipsis }` and then overrides it with `.k-grid .k-table-td { white-space: unset }`, so cells inside
   a grid WRAP rather than truncate — computed `white-space` on these cells is `normal`, and a long
   Name or Composer tooltip grows the row's height instead of ellipsing. There is therefore no
   single-line truncation for an overflow flip to break, and the predicted overlapping-text failure
   does not reproduce on this surface. The narrowing is kept because it is strictly more precise and
   removes the hazard if anyone later restores nowrap on these cells, not because it repairs an
   observed defect. */
/* SPEC-015 AC-2 note: on the Notes admin page the note-types grid now carries Telerik's own
   `k-grid-no-scrollbar` class, so `.k-grid-content` no longer clips at rest there — one of the five
   ancestors this block lists is released independently of the menu-open state. This block still wins
   while a panel is mounted (`app.css` loads after the theme) and both values are non-clipping, so the
   two do not fight. Do not "simplify" either one by assuming the other covers it. */
.k-grid:has(.row-actions-menu),
.k-grid:has(.row-actions-menu) .k-grid-aria-root,
.k-grid:has(.row-actions-menu) .k-grid-container,
.k-grid:has(.row-actions-menu) .k-grid-content,
.k-grid:has(.row-actions-menu) .k-table-td:has(.row-actions-menu) {
    overflow: visible;
}

/* Issue #1666: Telerik ships `.k-grid .k-table-td { white-space: unset }` (see the comment two
   blocks up), which already makes DATA cells wrap instead of truncate — but header cells stay on
   Telerik's own `.k-table-th { white-space: nowrap; text-overflow: ellipsis }`, unmodified by that
   override. Paired with the Width= values NotesAdminPage.razor now sets on every GridColumn (a
   table-layout: fixed column with no Width divides the grid's OWN width evenly, collapsing to a
   few px at a narrow viewport with nothing to actually scroll to), an unwrapped header truncates
   the moment its column narrows below the header text's single-line width. This unsets nowrap the
   same way Telerik's own override does for cells, so headers wrap instead. Scoped to .k-grid, the
   only TelerikGrid in this codebase (confirmed via `grep -rln "<TelerikGrid" src/`, SPEC-022 Task
   7), so this reaches no other surface.

   overflow-wrap: anywhere was tried for the Visibility column's longer values, which carry a
   single unbroken capability code (e.g. "notes.view_private_judicial") — dropped after mutation
   testing showed it changes nothing observable: the surrounding spaces in "...roles with
   notes.view_private_judicial" already give white-space: normal a wrap point right before the
   token, and at the Width="220px" NotesAdminPage.razor now sets, the token itself fits on its own
   line without needing a mid-word break. Kept out rather than shipped unproven. */
.k-grid .k-table-th {
    white-space: normal;
}

/* ---- Notes admin: Note Types table presentation (SPEC-015 AC-2) ------- */
/*
   The Source column's BUILT-IN / CUSTOM pill reuses the shipped `.status-pill` base plus two EXISTING
   tint pairs rather than defining a third: info-blue (the pair `.status-pill--pending` carries) for
   BUILT-IN, amber (`.status-pill--locked`) for CUSTOM. `.status-pill` supplies the uppercase, which is
   why the markup keeps the label proper-case — see the `.provenance-tag` comment below for the
   convention: the model stores proper-case for screen-reader textContent, CSS presents the all-caps.

   No Notes-specific pill class is introduced. The markup carries `.status-pill` plus the tint modifier
   and nothing else, so there is no class here with no rule behind it — which is the exact smell the
   `note-type-kind-badge` this replaces had (Pre-Kickoff Callout 1). Tests locate the pill through the
   Source cell and assert its computed background, not a bespoke hook class.
*/

/* The type name and its composer tooltip share one cell (AC-2 column 1). The tooltip renders as
   italicized quoted subtext beneath the name; when no tooltip is configured the element is omitted
   entirely rather than rendered empty, so there is no reserved blank line to style. */
.note-type-name {
    font-weight: 600;
    color: #1E3A5F;
}
.note-type-tooltip-subtext {
    margin-top: 2px;
    color: #5A6779;
    font-size: 12px;
    line-height: 16px;
}

/* ---- Notes admin page + card chrome (SPEC-015 AC-27 / AC-28, Task 22) ------------------------
   AC-27's card treatment is the one already shipped for .conditions-empty-state — white surface,
   1px #E1E5EB, 8px radius (Style Guide v5 §1.5). Reused as values rather than by extending that
   selector: .conditions-empty-state is an EMPTY-STATE panel (40px padding, centred, muted text) and
   these are content cards, so sharing the selector would drag three rules that are wrong here. */
.notes-admin-card {
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    padding: 20px 24px;
}

/* Vertical separation between the two cards (AC-27). On the last card the margin is harmless; the
   sibling selector keeps it off a single-card page if one ever exists. */
.notes-admin-card + .notes-admin-card {
    margin-top: 20px;
}

/* AC-27 card header row: heading + description at the left, the card's primary action right-aligned
   on the same row.

   space-between, with one child when the action slot is empty: the Note types card renders NO action
   child while its add form is open, and the banner card renders none ever.

   MEASURED, because the first rationale written here was wrong. It claimed a grid with a reserved
   action track "would leave a visible gap" where flex "collapses cleanly". Probing both in the dev app
   at a 1400px viewport: heading block 641px under this flex rule and 850px under `grid-template-columns:
   1fr 200px`, each IDENTICAL between the closed and open states. Neither shape reflows when the slot
   empties — the flex item is content-sized either way — so the gap argument does not hold and is not
   the reason for this rule. Flex is kept because it is the simpler expression of "action right-aligned
   on the same row" and needs no track sized to a button whose label may change.

   What the E2E fact actually pins is that emptying the slot causes NO layout shift: the heading does not
   move and the row does not grow. Stated narrowly on purpose — no mutant was found that fails it, so it
   should not be sold as a guard against the fixed-track shape. */
.notes-admin-card-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}

/* The heading block. min-width:0 lets the description line wrap inside the flex row rather than
   forcing the row wider than the card. */
.notes-admin-card-heading {
    min-width: 0;
}

.notes-admin-card-heading h2 {
    margin: 0;
}

/* AC-28 breadcrumb. Structure mirrors .user-detail-breadcrumb; the separator is "/" per Style Guide
   v5 §2.5, which reads "separator: '/' in Border/Strong" — AC-28's slash AGREES with the Style Guide
   rather than diverging from it, and every *-breadcrumb rule in this file renders the same "/".
   (Corrected under issue #1659: this comment previously claimed §2.5 rendered "›" and that the two
   breadcrumbs intentionally differed. Verified against docs/planning/Justice_Portal_Style_Guide_v5.txt.)
   The separator is generated content on the <li>, so it is decorative and never enters the accessible
   name of the crumb. */
.notes-admin-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    font-size: 13px;
    line-height: 18px;
    color: #5A6779;
}

.notes-admin-breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-left: 6px;
    color: #A0AAB8;
}

.notes-admin-breadcrumb li[aria-current="page"] {
    color: #1A202C;
    font-weight: 600;
}

/* AC-28's page description, beneath the <h1>. Sits outside the load-error conditional in the markup,
   so it is styled here rather than inside any state-specific block.

   NOTE: .notes-admin-page deliberately carries NO max-width. AC-28 pins the absence of a cap so this
   page fills the admin content area like SPEC-003 AC-16 / SPEC-006 / SPEC-014. Do not add one while
   adding card rules — the cards size themselves within that full-width area. */
.notes-admin-page-description {
    margin: 4px 0 24px;
    color: #5A6779;
    font-size: 14px;
    line-height: 20px;
}

/* AC-2 / AC-6 section copy: the description line under each heading and the banner field's helper text. */
.notes-admin-section-description,
.notes-admin-footnote,
.notes-admin-field-help {
    color: #5A6779;
    font-size: 13px;
    line-height: 18px;
}
.notes-admin-section-description {
    margin: 4px 0 12px;
}
.notes-admin-footnote {
    margin: 12px 0 0;
}
.notes-admin-field-help {
    margin: 6px 0 12px;
}

/* Issue #2179: #notes-banner-text is a bare <label>+<textarea> pair (NotesAdminPage.razor), not
   wrapped in a .form-field like #role-description / #queue-banner, so it carried NO app styling at
   all -- it fell through to the browser's UA default box AND the UA default monospace <textarea>
   font (SPEC-022 AC-1/AC-3/AC-6 regression, same root cause as the other two). Same box treatment
   as .form-field textarea (app.css), reproduced here rather than adding a .form-field wrapper in
   markup, which would also pull in .form-field label's uppercase/11px treatment -- a visual change
   to AC-6's pinned "Banner text" label this fix does not need to make. */
#notes-banner-text {
    display: block;
    width: 100%;
    padding: 8px 12px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 15px;
    line-height: 22px;
    color: #1A202C;
    background: #FFFFFF;
    box-sizing: border-box;
    font-family: var(--font-product);
    transition: border-color 0.15s ease;
    resize: vertical;
}

#notes-banner-text:hover {
    border-color: #8A94A6;
}

#notes-banner-text:focus-visible,
#notes-banner-text:focus {
    outline: none;
    border-color: #1E3A5F;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
}

.conditions-empty-state {
    margin-top: 32px;
    padding: 40px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    text-align: center;
    color: #5A6779;
    font-size: 14px;
}

/* Soft-blue placeholder chip (Style Guide v5 §1.2 InfoTint/InfoPrimary — the same info-blue pair
   as the Awaiting-Input pill; SPEC-014 AC-4 "soft-blue chips"). */
.condition-chip {
    display: inline-block;
    padding: 1px 8px;
    margin: 0 1px;
    border-radius: 9999px;
    background: #E6F0FA;
    color: #2B6CB0;
    font-size: 12px;
    font-weight: 600;
    line-height: 18px;
    white-space: nowrap;
}

/* ---- Read-only applied-conditions view (SPEC-014 AC-22 / AC-23) -------- */
/* .applied-conditions-view is the docked summary panel — SPEC-014 AC-10, Issue #1164. Before the
   combined-layout amendment this section was the tab's ONLY content for a given viewer, so it relied
   entirely on .defendant-tab-content's padding for spacing. It now docks directly above the picker
   composer for the picker-capable holder, with no wrapper between them, so the --docked modifier (applied
   only when a composer actually renders below, via the Docked parameter) carries its own bottom margin +
   rule to separate it from the composer (PR #1176 review, Dean Kohler). The base class carries none —
   every other viewer (read-only, holder without conditions.apply, post-publish) has no composer below and
   must not get a bare divider with nothing following it (PR #1176 review round 2, Dean Kohler — this was a
   round-1 regression: the base class had no rule at all before this PR docked the panel for the first
   time, so there was nothing to accidentally scope until the divider was added). */
.applied-conditions-view--docked {
    margin-bottom: 24px;
    padding-bottom: 20px;
    border-bottom: 1px solid #DDDDDD;
}

.applied-conditions-view h2 {
    font-size: 16px;
    color: #1E3A5F;
    margin: 0;
}

.applied-conditions-list {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.applied-condition-row {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: baseline;
    gap: 12px;
    padding: 10px 12px;
    background: #FFFFFF;
    border: 1px solid #DDDDDD;
    border-radius: 6px;
}

/* SPEC-014 Task 5.2 (AC-24) — a fourth grid column for the per-row Remove/Edit actions, applied
   only when the viewer can manage conditions; every other viewer keeps the base 3-column grid
   with no empty trailing cell. */
.applied-condition-row--manageable {
    grid-template-columns: auto 1fr auto auto;
}

.applied-condition-actions {
    display: flex;
    gap: 8px;
    align-items: baseline;
}

.applied-condition-edit-form {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.applied-condition-edit-actions {
    justify-content: flex-start;
}

.applied-condition-text {
    margin: 0;
    color: #1F2933;
    font-size: 14px;
    line-height: 20px;
}

.applied-condition-time {
    color: #5A6779;
    font-size: 12px;
    white-space: nowrap;
}

/* Provenance tag — pill off the .status-pill family; shown only on the read-only view.
   Uppercased for the AC-22 label contract (FROM LIBRARY / VIA PRETRIAL / CUSTOM) the same
   way .status-pill renders its labels — the mapper stores proper-case for screen-reader
   textContent, CSS presents the all-caps visual. */
.provenance-tag {
    font-family: var(--font-accent);
    display: inline-block;
    padding: 2px 10px;
    border-radius: 9999px;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    white-space: nowrap;
}

.provenance-tag--library  { background: #E6F0FA; color: #2B6CB0; }
.provenance-tag--pretrial { background: #E6F4EF; color: #0F7B5C; }
.provenance-tag--custom   { background: #EEF0F3; color: #5A6779; }

.conditions-readonly-loading {
    margin: 12px 0 0;
    color: #5A6779;
    font-size: 14px;
    font-style: italic;
}

.conditions-readonly-error {
    margin: 12px 0 0;
    padding: 10px 12px;
    background: #FDECEA;
    color: #B42318;
    border: 1px solid #F3B4AD;
    border-radius: 6px;
    font-size: 14px;
}

/* ---- Condition picker (SPEC-014 AC-11..AC-21) ------------------------- */
.conditions-picker-columns {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 20px;
    align-items: start;
}

@media (max-width: 900px) {
    .conditions-picker-columns { grid-template-columns: minmax(0, 1fr); }
}

.condition-library-column,
.conditions-picker-order {
    background: #FFFFFF;
    border: 1px solid #DDDDDD;
    border-radius: 6px;
    padding: 14px;
}

.conditions-picker-order > h3 { margin: 0 0 10px; font-size: 15px; }

.condition-select-all {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 10px;
    margin-bottom: 8px;
    border-bottom: 1px solid #EEF0F3;
    font-weight: 600;
    font-size: 13px;
}

.condition-library-section { margin-top: 8px; }

.condition-section-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 6px 0;
    border: none;
    background: none;
    font-size: 14px;
    font-weight: 600;
    color: #1F2933;
    cursor: pointer;
    text-align: left;
}

.condition-section-chevron { width: 12px; color: #5A6779; }

.condition-library-list {
    list-style: none;
    margin: 4px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.condition-library-row label {
    display: flex;
    align-items: baseline;
    gap: 8px;
    font-size: 14px;
    line-height: 20px;
    cursor: pointer;
}

/* A row already in the order pane: muted + not selectable (its checkbox is disabled). */
.condition-library-row--added label {
    cursor: default;
    color: #6E6E6E;
}

.condition-library-added-tag {
    font-family: var(--font-accent);
    margin-left: auto;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #2E7D32;
    align-self: center;
}

.condition-library-empty {
    margin: 6px 0 0;
    color: #6E6E6E;
    font-style: italic;
    font-size: 13px;
}

.condition-order-empty {
    color: #6E6E6E;
    font-style: italic;
    font-size: 13px;
}

.condition-order-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.condition-order-item {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 10px 12px;
    background: #F7F9FC;
    border: 1px solid #E1E7EF;
    border-radius: 6px;
}

.condition-order-item-body { flex: 1 1 auto; min-width: 0; }

.condition-order-sentence {
    font-size: 14px;
    line-height: 28px;
}

.condition-order-input {
    display: inline-flex;
    flex-direction: column;
    vertical-align: baseline;
    margin: 0 2px;
}

.condition-order-input input {
    height: 28px;
    padding: 0 8px;
    border: 1px solid #CBD2DC;
    border-radius: 4px;
    font-size: 13px;
}

.condition-order-hint {
    font-size: 11px;
    color: #6E6E6E;
}

.condition-order-preview {
    margin: 8px 0 0;
    padding-top: 8px;
    border-top: 1px dashed #E1E7EF;
    font-size: 13px;
    color: #1F2933;
}

.condition-order-stub {
    color: #9AA5B1;
    font-style: italic;
}

.condition-order-static {
    margin: 0;
    font-size: 14px;
    line-height: 20px;
}

.condition-custom-entry {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid #EEF0F3;
}

.condition-custom-entry label { font-size: 13px; font-weight: 600; }

.condition-custom-entry textarea {
    border: 1px solid #CBD2DC;
    border-radius: 4px;
    padding: 6px 8px;
    font: inherit;
    font-size: 13px;
    resize: vertical;
}

.conditions-add-to-order,
.conditions-review-apply {
    margin-top: 12px;
}

.conditions-review-apply:disabled,
.conditions-add-to-order:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Apply confirmation — full-screen step (SPEC-014 AC-19/AC-20) */
.apply-confirmation {
    background: #FFFFFF;
    border: 1px solid #DDDDDD;
    border-radius: 6px;
    padding: 20px;
}

.apply-confirmation h2 { margin: 0 0 12px; outline: none; }

.apply-confirmation-alert { margin-bottom: 12px; }

.apply-confirmation-list {
    margin: 0 0 16px;
    padding-left: 20px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    font-size: 14px;
    line-height: 20px;
}

.apply-confirmation-unapplied {
    margin: 12px 0;
    padding: 12px;
    background: #FDF5E6;
    border: 1px solid #E7D9B5;
    border-radius: 6px;
}

.apply-confirmation-unapplied h3 { margin: 0 0 6px; font-size: 14px; }

.apply-confirmation-unapplied-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 4px 0;
}

.apply-confirmation-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 16px;
}

.link-button {
    padding: 0;
    border: none;
    background: none;
    color: #2B6CB0;
    font-size: 14px;
    cursor: pointer;
    text-decoration: underline;
}

.link-button:hover {
    color: #1E3A5F;
}

.link-button:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 2px;
}

.link-button--danger {
    color: #B42318;
}

/* The paired [aria-disabled] CSS the accessible-disabled house rule requires. The holiday Remove button is
   aria-disabled while queues reference the holiday (SPEC-011 FR-37), so without this it is computed-style
   identical to a live one and reads as operable. The visible reason sits beside it, never in a title. */
.link-button.holiday-remove[aria-disabled="true"] {
    cursor: not-allowed;
    opacity: 0.4;
    text-decoration: none;
}

.holiday-remove-reason {
    font-size: 14px;
    color: #4A5568;
}

.link-button--danger:hover {
    color: #8A1A12;
}

.btn-secondary {
    height: 36px;
    padding: 0 14px;
    border: 1px solid #CBD2DC;
    border-radius: 6px;
    background: #FFFFFF;
    font-size: 14px;
    color: #1A202C;
    cursor: pointer;
}

.btn-secondary:hover {
    background: #F7F9FB;
}

.btn-secondary:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 1px;
}

/* Placed AFTER :hover and :focus-visible on purpose. A disabled button is still hoverable, and
   `.btn-secondary:hover` carries the same specificity (0,2,0) -- declared earlier it would repaint
   a disabled control back to an enabled-looking background on hover. Ordering is the whole
   mechanism here; do not move this block above them.

   Why it exists: `.btn-secondary` shipped no `:disabled` rule at all, and the element's class list
   is `btn-secondary` alone -- not `btn btn-secondary` -- so the generic `.btn:disabled { opacity:
   0.5 }` never matched either. Every disabled `.btn-secondary` in the app therefore rendered
   pixel-identical to an enabled one. Found the hard way during issue #1387's manual walkthrough:
   Case Lookup's Export CSV button is disabled for the entire time an export is in flight, and a
   human watching it for 30 seconds correctly reported that it never appeared to disable.

   Values are `.audit-page`'s, which had already carved out this exact fix locally for its
   Previous/Next pagination (where the disabled state IS the last-page signal). That scoped
   override is now redundant and has been retired in favour of this one. Fourteen call sites
   across the app disable a `.btn-secondary`; all of them gain the affordance.

   No contrast obligation is being dodged: WCAG 2.1 SC 1.4.3 exempts incidental text in an
   inactive control, so #8A93A3 on #EEF0F3 is permitted for a disabled control specifically. The
   affordance being communicated by more than colour alone is `cursor: not-allowed` plus the
   control's own inert behaviour (SC 1.4.1). */
.btn-secondary:disabled {
    background: #EEF0F3;
    color: #8A93A3;
    border-color: #E1E5EB;
    cursor: not-allowed;
}

.field-hint {
    display: block;
    margin-top: 4px;
    font-size: 12px;
    color: #5A6779;
}

/* ---- Condition editor + placeholder + confirm dialogs ----
   Sectioned header/body/footer layout (padding:0 on the dialog, each section owns its padding +
   divider), overriding the flat dialog.modal-dialog default (padding:32px, gap:16px) which reads
   cramped for a multi-field form.

   This block used to cite "the InviteUserModal quality bar" as the standard it matched. It was not
   one: InviteUserModal asks for the same sectioned treatment with a bare `.invite-modal` selector,
   which loses to the frame, so the exemplar has always shipped the flat 32px padding these rules
   deliberately override. The four dialogs below are the sectioned treatment's only real
   implementation, and they are correct on their own terms rather than by reference to it.
   Corrected on the PO ruling in Issue #1295, which also decided the invite modal keeps the flat
   frame — so the bar it was cited for is not coming back. The invite modal's own sectioned
   declarations are deleted rather than activated, which is what makes that permanent. */

/* The `dialog` element prefix is REQUIRED: the base rule `dialog.modal-dialog` is specificity
   (0,1,1), so a bare `.condition-editor-dialog` (0,1,0) would lose and the flat padding:32px/gap:16px
   would win — leaving the sectioned layout inert. Prefixing restores (0,1,1) so these override. Same
   specificity note as the `dialog.modal-dialog[open]` rule above. */
dialog.condition-editor-dialog,
dialog.placeholder-dialog,
dialog.confirm-dialog,
dialog.rule-editor-dialog,
dialog.note-type-editor-dialog {
    padding: 0;
    gap: 0;
    max-width: 600px;
    width: calc(100% - 48px);
}

dialog.placeholder-dialog {
    max-width: 520px;
}

dialog.confirm-dialog {
    max-width: 440px;
}

/* PO ruling 2026-09-16: wider than the shared 600px frame, so the condition-text/preview
   fields read as genuinely full-width rather than cramped. */
dialog.condition-editor-dialog {
    max-width: 720px;
}

.condition-editor-header,
.placeholder-dialog-header,
.confirm-dialog-header,
.rule-editor-header,
.note-type-editor-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px 24px;
    border-bottom: 1px solid #E1E5EB;
}

.condition-editor-header h3,
.placeholder-dialog-header h3,
.confirm-dialog-header h3,
.rule-editor-header h3,
.note-type-editor-header h3 {
    margin: 0;
    font-size: 18px;
    color: #1A202C;
}

/* PO ruling 2026-09-16: navy header band for the three "editor" dialogs (Condition Editor,
   Insert Placeholder, Rule Editor) only -- NOT .confirm-dialog-header, which is a generic
   confirm/delete dialog reused app-wide (Notifications rule-delete/template-reset,
   DefendantDetails condition-remove/edit and document-delete, Conditions condition-delete)
   and stays on the flat white treatment above. Declared after the shared block above so these
   same-specificity overrides win by source order (see the dialog.modal-dialog note above on
   why type-qualified/source-order rules are how this file resolves these clashes). */
.condition-editor-header,
.placeholder-dialog-header,
.rule-editor-header,
.note-type-editor-header {
    background: #1E3A5F;
    border-bottom: none;
    border-radius: 8px 8px 0 0;
}

/* `dialog.` qualified: the bare `.condition-editor-header h3` form (0,1,1) loses to
   `dialog.modal-dialog h3` (0,1,2) above whatever the source order, so the title stayed
   #1A202C on the navy band -- a 1.4:1 contrast the axe gates flag as serious. */
dialog.modal-dialog .condition-editor-header h3,
dialog.modal-dialog .placeholder-dialog-header h3,
dialog.modal-dialog .rule-editor-header h3,
dialog.modal-dialog .note-type-editor-header h3 {
    color: #FFFFFF;
}

.condition-editor-header .dialog-close,
.placeholder-dialog-header .dialog-close,
.rule-editor-header .dialog-close,
.note-type-editor-header .dialog-close {
    color: #FFFFFF;
}

.condition-editor-header .dialog-close:hover,
.placeholder-dialog-header .dialog-close:hover,
.rule-editor-header .dialog-close:hover,
.note-type-editor-header .dialog-close:hover {
    color: #FFFFFF;
    background: rgba(255, 255, 255, 0.15);
}

.condition-editor-header .dialog-close:focus-visible,
.placeholder-dialog-header .dialog-close:focus-visible,
.rule-editor-header .dialog-close:focus-visible,
.note-type-editor-header .dialog-close:focus-visible {
    outline-color: #FFFFFF;
}

.condition-editor-body,
.placeholder-dialog-body,
.confirm-dialog-body,
.rule-editor-body,
.note-type-editor-body {
    padding: 20px 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.confirm-dialog-body p {
    margin: 0;
    font-size: 14px;
    line-height: 22px;
    color: #5A6779;
}

/* SPEC-014 Task 5.2 (AC-24) — the current-vs-revised comparison block in the shared Remove/Edit-save
   confirm dialog's EditSave mode, distinguishing the label rows from the quoted condition text. */
.confirm-dialog-comparison-label {
    font-family: var(--font-accent);
    margin: 0;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: #5A6779;
}

.confirm-dialog-comparison-text {
    margin: 0 0 8px;
    font-size: 14px;
    line-height: 20px;
    color: #1F2933;
}

.condition-editor-footer,
.placeholder-dialog-footer,
.confirm-dialog-footer,
.rule-editor-footer,
.note-type-editor-footer {
    padding: 16px 24px;
    border-top: 1px solid #E1E5EB;
}

/* PO ruling 2026-09-16: no footer divider for the three navy-banded dialogs (see the header
   rule above for why .confirm-dialog-footer is excluded and keeps its border). */
.condition-editor-footer,
.placeholder-dialog-footer,
.rule-editor-footer,
.note-type-editor-footer {
    border-top: none;
}

.condition-editor-toolbar {
    display: flex;
    justify-content: flex-end;
}

/* SPEC-015 AC-30 — the note-type editor's own two rules. Everything else this dialog renders
   (frame, navy band, body, footer, inputs) comes from the shared selector lists above, which is
   what makes AC-30's "does not restate that chrome" true in the stylesheet rather than only in
   prose: a later restyle of the condition editor carries this dialog with it. */
.note-type-editor-field-help {
    margin: 4px 0 0;
    font-size: 12px;
    line-height: 18px;
    color: #5A6779;
}

/* AC-30's read-only Behavior/Visibility/Source block. Same inset surface as .condition-preview,
   which is the nearest shipped precedent for "read-only derived text inside an editor dialog". */
.note-type-editor-summary {
    padding: 12px 14px;
    background: #F7F9FB;
    border: 1px solid #E1E5EB;
    border-radius: 6px;
}

.note-type-editor-summary-label {
    font-family: var(--font-accent);
    margin: 0 0 8px;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: #5A6779;
}

/* A two-column term/description grid: the <dl> carries the screen-reader association, the grid
   carries the visual alignment, and neither depends on the other. */
.note-type-editor-summary dl {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 4px 16px;
    margin: 0;
}

.note-type-editor-summary dt {
    font-size: 13px;
    font-weight: 600;
    color: #5A6779;
}

.note-type-editor-summary dd {
    margin: 0;
    font-size: 13px;
    line-height: 20px;
    color: #1F2933;
}

.condition-editor-body textarea,
.placeholder-dialog-body input,
.placeholder-dialog-body select,
.note-type-editor-body input {
    width: 100%;
    box-sizing: border-box;
    font-family: inherit;
    font-size: 14px;
    color: #1A202C;
    border: 1px solid #CBD2DC;
    border-radius: 6px;
    padding: 8px 10px;
}

/* PO ruling 2026-09-16: a fixed, non-resizable height rather than resize:vertical +
   min-height -- the box's size is now entirely CSS-controlled and can never change as text
   is typed (the reported "expands as text is added" symptom). */
.condition-editor-body textarea {
    resize: none;
    height: 160px;
    line-height: 22px;
}

.condition-editor-body textarea:focus-visible,
.placeholder-dialog-body input:focus-visible,
.placeholder-dialog-body select:focus-visible,
.note-type-editor-body input:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 1px;
}

.condition-preview,
.placeholder-preview {
    padding: 12px 14px;
    background: #F7F9FB;
    border: 1px solid #E1E5EB;
    border-radius: 6px;
}

.condition-preview-label,
.placeholder-preview-label {
    font-family: var(--font-accent);
    display: block;
    margin-bottom: 6px;
    font-size: 11px;
    font-weight: 600;
    color: #5A6779;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.condition-preview-body,
.placeholder-preview-body {
    font-size: 14px;
    line-height: 24px;
    color: #1A202C;
}

/* Issue #2735: the second preview line in the condition editor renders placeholders as unpadded italic
   stubs, so a token glued to the next word reads glued. #5A6779 (not .condition-order-stub's #9AA5B1)
   keeps the stub at WCAG 2.1 SC 1.4.3 contrast on the #F7F9FB preview surface. */
.condition-preview-label--ruling {
    margin-top: 10px;
}

.condition-preview-stub {
    font-style: italic;
    color: #5A6779;
}

.condition-placeholder-list-label {
    font-family: var(--font-accent);
    display: block;
    margin-bottom: 6px;
    font-size: 11px;
    font-weight: 600;
    color: #5A6779;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.condition-placeholder-list ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.condition-placeholder-list li {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    background: #F7F9FB;
    border: 1px solid #E1E5EB;
    border-radius: 6px;
}

.condition-placeholder-list li .link-button {
    margin-left: auto;
}

.condition-placeholder-type {
    font-size: 12px;
    color: #5A6779;
}

/* ── SPEC-011 Queue Views admin (PR 5) ─────────────────────────────────────
   Read-only queue list page. Mirrors the Conditions admin table contract
   (Style Guide v5 table styling): white surface, 8px radius, header row on
   the neutral tint, alternating-friendly row borders. */
.queue-views-page {
    padding: 24px 32px;
}

/* AC-32 breadcrumb. Structure and rule shapes mirror .notes-admin-breadcrumb (SPEC-015 AC-28) --
   the "/" separator is Style Guide v5 §2.5's, generated as decorative ::after content so it never
   enters the crumb's accessible name. */
.queue-views-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    font-size: 13px;
    line-height: 18px;
    color: #5A6779;
}

.queue-views-breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-left: 6px;
    color: #A0AAB8;
}

.queue-views-breadcrumb li[aria-current="page"] {
    color: #1A202C;
    font-weight: 600;
}

.queue-views-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}

.queue-views-header h1 {
    margin: 0;
    font-size: 24px;
    color: #1A202C;
}

/* AC-33's page description, beneath the header. AC-34 pins .queue-views-page as already carrying
   no max-width -- do not add one here. */
.queue-views-page-description {
    margin: 4px 0 24px;
    color: #5A6779;
    font-size: 14px;
    line-height: 20px;
}

.queue-views-table {
    width: 100%;
    border-collapse: collapse;
    background: #FFFFFF;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid #E1E5EB;
}

.queue-views-table th,
.queue-views-table td {
    text-align: left;
    padding: 12px 16px;
    border-bottom: 1px solid #EEF0F3;
    font-size: 14px;
    color: #1A202C;
    vertical-align: top;
}

.queue-views-table th {
    font-weight: 600;
    color: #5A6779;
    background: #F7F9FB;
}

.queue-views-numeric-cell {
    font-family: var(--font-accent);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.queue-views-empty-state {
    margin-top: 32px;
    padding: 40px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    text-align: center;
    color: #5A6779;
    font-size: 14px;
}

/* FR-28 coverage-gap warning — amber InfoTint pairing (Style Guide v5 §1.2, the
   same amber as the overdue chip / locked status pill). */
.queue-coverage-banner {
    margin-bottom: 16px;
    padding: 12px 16px;
    background: #FDF5E6;
    border: 1px solid #E8D9B5;
    border-radius: 8px;
    color: #8A6B25;
    font-size: 14px;
}

.queue-coverage-banner-title {
    margin: 0 0 8px;
    font-weight: 600;
}

/* Issue #2671: the uncovered windows lay out as a wrapping row of per-day boxes rather than one bullet
   per window, so a typical 12-window Mon-Fri gap set reads a few lines tall instead of twelve. Both lists
   drop their markers and indent -- the day name heads its own box and the ranges sit under it, so bullets
   would only add noise. */
.queue-coverage-banner-days {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.queue-coverage-day {
    flex: 0 0 auto;
    min-width: 96px;
    padding: 6px 10px;
    background: rgba(255, 255, 255, 0.55);
    border: 1px solid #E8D9B5;
    border-radius: 6px;
}

.queue-coverage-day-name {
    display: block;
    margin-bottom: 2px;
    font-weight: 600;
}

.queue-coverage-day-ranges {
    margin: 0;
    padding: 0;
    list-style: none;
}

.queue-coverage-day-ranges li {
    font-family: var(--font-accent);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* FR-13 / AC-13 guided overlap resolution — same amber InfoTint pairing as the coverage banner (Style Guide
   v5 §1.2). Rendered inline in the Time frame section after a submit returns OverlapResolutionMissing; each
   conflict row pairs its window description with a native winner selector. */
.queue-overlap-banner {
    margin-top: 12px;
    padding: 12px 16px;
    background: #FDF5E6;
    border: 1px solid #E8D9B5;
    border-radius: 8px;
    color: #8A6B25;
    font-size: 14px;
}

.queue-overlap-banner-title {
    margin: 0 0 8px;
    font-weight: 600;
}

.queue-overlap-banner-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.queue-overlap-conflict {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 6px 0;
}

.queue-overlap-conflict + .queue-overlap-conflict {
    border-top: 1px solid #E8D9B5;
}

.queue-overlap-winner-select {
    flex: 0 0 auto;
    min-width: 180px;
}

/* ---- Queue configuration dialog (SPEC-011 PR 5b: Task 5.2 / 5.5 / 5.6) ---- */

/* Wider than the default 480px modal — the config form carries several sections. The dialog itself does
   NOT scroll; the header (title) and footer (Cancel/Create) are pinned and only the body scrolls, so the
   title and actions stay visible on a form taller than the viewport. Scoped to this dialog — the shorter
   shared modals keep the base whole-dialog scroll. */
dialog.modal-dialog.queue-config-dialog {
    /* Wider than the 480px default so a Calendar specific-date row (date + hours + start + end + remove)
       lays out on one line without wrapping. */
    max-width: 720px;
    overflow: hidden;
}

.queue-config-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex: 0 0 auto;
}

.queue-config-header h3 {
    margin: 0;
    font-size: 18px;
    color: #1A202C;
}

.queue-config-body {
    display: flex;
    flex-direction: column;
    gap: 20px;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* Reserve a gutter so the scrollbar sits beside the fields, not on top of them (e.g. the "Sat" checkbox). */
    padding-right: 16px;
}

.queue-config-footer {
    flex: 0 0 auto;
    /* Issue #2770 — the disabled Delete now carries a visible reason; on a narrow dialog the footer wraps
       rather than squeezing that text into a sliver beside the buttons. */
    flex-wrap: wrap;
}

/* Task 5.10 — the Delete affordance sits at the left edge of the footer, away from Cancel/Save on the right
   (the footer is a flex-end row; margin-right:auto pushes this first child to the left). The disabled variant
   (#2770) is a same-classed .queue-delete-blocked group holding the button, wrapped in a span that carries
   the tooltip so it stays hover-reachable while the button is disabled, plus the visible reason text. */
.queue-delete {
    margin-right: auto;
}

/* Issue #2770 — the disabled Delete's reason is visible text beside the button rather than a hover-only
   tooltip. The group takes the left slot (.queue-delete's margin-right:auto) and the message wraps within it
   so a long reason never pushes Cancel/Save off the footer. */
.queue-delete-blocked {
    display: flex;
    align-items: center;
    flex: 1 1 280px;
    gap: 12px;
    min-width: 0;
}

/* Scoped under dialog.modal-dialog: the shared `dialog.modal-dialog p` rule (14px/22px) has higher specificity
   than a bare class and would otherwise win. */
dialog.modal-dialog .queue-delete-reason {
    margin: 0;
    font-size: 13px;
    line-height: 1.4;
    color: #5A6779; /* Text/Secondary token on White */
}

/* Pinned between the header and the scrolling body — a submit error stays on screen regardless of scroll. */
.queue-config-errors {
    flex: 0 0 auto;
}

.queue-config-error-list {
    margin: 0;
    padding-left: 18px;
}

.queue-editor-section {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-top: 16px;
    border-top: 1px solid #EEF0F3;
}

.queue-editor-section:first-child {
    padding-top: 0;
    border-top: none;
}

.queue-editor-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.queue-editor-section-label {
    font-family: var(--font-accent);
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779;
}

.queue-editor-note {
    margin: 0;
    font-size: 12px;
    color: #595F6B; /* WCAG 1.4.3 AA: #595F6B on #FFFFFF ≈ 6.4:1 (was #8A94A6 ≈ 3.1:1) */
}

.queue-editor-empty-hint {
    margin: 0;
    font-size: 13px;
    color: #8A6B25;
}

.field-optional {
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    color: #595F6B; /* WCAG 1.4.3 AA: #595F6B on #FFFFFF ≈ 6.4:1 (was #8A94A6 ≈ 3.1:1) */
}

/* Day-of-week + behavior checkbox rows */
.queue-days-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    border: none;
    padding: 0;
    margin: 0;
}

.queue-checkbox-label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    color: #1A202C;
    cursor: pointer;
}

.queue-checkbox-label input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: #1E3A5F;
    cursor: pointer;
}

.queue-time-row {
    display: flex;
    gap: 16px;
}

.queue-time-row .form-field {
    flex: 1;
}

.queue-time-row input[type="time"] {
    height: 44px;
    padding: 0 12px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 15px;
    color: #1A202C;
    background: #FFFFFF;
    box-sizing: border-box;
}

.queue-behavior-grid {
    gap: 14px;
}

/* Decision options editor */
.decision-options-list,
.assigned-judges-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.decision-option-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.decision-option-label {
    flex: 1;
    height: 38px;
    padding: 0 10px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 14px;
    box-sizing: border-box;
}

.decision-option-code {
    height: 38px;
    padding: 0 8px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 14px;
    background: #FFFFFF;
}

.decision-option-remove {
    color: #B84D4D;
}

/* Assigned judges picker */
.assigned-judge-row {
    font-size: 14px;
}

/* Notification-destination phone list (mirrors the decision-options list layout) */
.notification-phones-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.notification-phone-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.notification-phone-input {
    flex: 1;
    height: 38px;
    padding: 0 10px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 14px;
    box-sizing: border-box;
}

.notification-phone-remove {
    color: #B84D4D;
}

.banner-counter {
    font-family: var(--font-accent);
    align-self: flex-end;
    font-size: 12px;
    color: #595F6B; /* WCAG 1.4.3 AA: #595F6B on #FFFFFF ≈ 6.4:1 (was #8A94A6 ≈ 3.1:1) */
    font-variant-numeric: tabular-nums;
}

/* The queue-name cell edit affordance reuses .link-button; align it left and inherit the row font. */
.queue-name-edit {
    padding: 0;
    font-size: 14px;
    text-align: left;
}

/* Native radiogroups styled as a segmented control (arrow-key operable) — the Time-frame mode toggle, the
   Notification-destination mode toggle, and the Require-signature toggle (AC-35, Issue #2259) share the
   layout; individual .queue-tab styling is global below. */
.queue-timeframe-tabs,
.notification-destination-tabs,
.queue-signature-tabs {
    display: flex;
    gap: 8px;
}

/* Require-signature toggle (AC-35, Issue #2259) — label-above-control, same shape as .form-field. */
.queue-signature-section {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.queue-tab {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 14px;
    color: #1A202C;
    cursor: pointer;
}

.queue-tab input[type="radio"] {
    accent-color: #1E3A5F;
    cursor: pointer;
}

.queue-tab:has(input:checked) {
    border-color: #1E3A5F;
    background: #EEF2F7;
    font-weight: 600;
}

/* Calendar-entries editor */
.calendar-entries-actions {
    display: flex;
    gap: 8px;
}

.calendar-entries-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

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

.calendar-entry-holiday,
.calendar-entry-hours {
    height: 38px;
    padding: 0 8px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 14px;
    background: #FFFFFF;
}

.calendar-entry-holiday {
    flex: 1;
    min-width: 160px;
}

.calendar-entry-date,
.calendar-entry-time {
    height: 38px;
    padding: 0 10px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 14px;
    color: #1A202C;
    background: #FFFFFF;
    box-sizing: border-box;
}

.calendar-entry-observed {
    font-family: var(--font-accent);
    font-size: 12px;
    color: #595F6B; /* WCAG 1.4.3 AA: #595F6B on #FFFFFF ≈ 6.4:1 (was #8A94A6 ≈ 3.1:1) */
    font-variant-numeric: tabular-nums;
}

.calendar-entry-remove {
    color: #B84D4D;
}

/* Inline holiday-library management section (Task 5.4). A native <details> accordion inside the Calendar block;
   the shared .queue-editor-section class already supplies display:flex + gap, so no section-level rule is needed. */
.holiday-library-summary {
    cursor: pointer;
    list-style-position: inside;
}

.holiday-library-summary:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: 2px;
    border-radius: 4px;
}

.holiday-library-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.holiday-library-row {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

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

.holiday-name {
    font-size: 14px;
    color: #1A202C;
}

.holiday-name-input {
    height: 38px;
    padding: 0 10px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 14px;
    box-sizing: border-box;
    min-width: 200px;
}

.holiday-system-badge {
    font-family: var(--font-accent);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    color: #2C3E50;
    background: #E6EBF2;
    border-radius: 4px;
    padding: 2px 6px;
}

.holiday-observed {
    font-family: var(--font-accent);
    font-size: 12px;
    color: #595F6B;
    font-variant-numeric: tabular-nums;
    margin-right: auto;
}

.holiday-remove,
.holiday-remove-confirm {
    color: #B84D4D;
}

.holiday-row-error {
    font-size: 13px;
}

.holiday-add-toggle {
    align-self: flex-start;
}

.holiday-add-form {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px;
    border: 1px solid #E6EBF2;
    border-radius: 6px;
    background: #FAFBFC;
}

.holiday-recurrence-fields {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}

.holiday-recurrence-fields .form-field {
    flex: 1;
    min-width: 120px;
}

.holiday-recurrence-fields input[type="number"],
.holiday-recurrence-fields select,
.holiday-add-form > .form-field input,
.holiday-add-form > .form-field select {
    height: 38px;
    padding: 0 10px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 14px;
    box-sizing: border-box;
}

/* ---------------------------------------------------------------------------
   Top app bar + user chip — SPEC-001 AC-15/16/17 (voluntary sign-out)

   Issue #1143 (delta log Entry 211): navy fill ratified over Style Guide v5
   §2.5's literal "white fill" text — the PO-approved reference screenshot
   pairs a navy top app bar with the (now-reverted) white left nav. Every
   foreground color below is inverted from its original white-bar authoring
   to stay WCAG-compliant against the new navy background.
   --------------------------------------------------------------------------- */

.top-app-bar {
    display: flex;
    flex: 0 0 auto;
    /* space-between, not flex-end (SPEC-001 AC-18): the lockup anchors the left edge (Style
       Guide v5 §2.5, "Left: logo + wordmark") and the user chip stays right-anchored — flex-end
       alone had nothing at the left edge to space against until the lockup existed. */
    justify-content: space-between;
    align-items: center;
    height: 56px;
    padding: 0 24px;
    background: #1E3A5F;
    border-bottom: 1px solid #142640; /* Navy/Hover — subtle edge against the navy fill */
    box-sizing: border-box;
    position: sticky;
    top: 0;
    /* Issue: the bell's dropdown panel (.notification-bell-panel, z-index: 20) was rendering behind
       DefendantDetails' own sticky header (.defendant-sticky-region, z-index: 10) — a numeric tie
       with THIS rule, broken in .defendant-sticky-region's favor because it is later in DOM order,
       which traps the panel's z-index inside the losing stacking context regardless of its own
       value. Master Design Summary §6.2 makes the top app bar "global, fixed" — it and everything
       it drops down (this panel, .user-chip-menu) must outrank every per-page sticky region, not
       just today's one instance, so this raises the BAR's own z-index above the whole in-page
       10-20 band (notification-bell-panel, user-chip-menu) documented at .row-actions-menu, rather
       than lowering .defendant-sticky-region — the same class of collision would otherwise
       resurface the next time a page adds its own z-index: 10+ sticky region. Still well below the
       900+ overlay band (toasts/dialogs/compose).

       This raise also has to stay BELOW the transient popover layer at 50-51. Going above it puts
       the bar on top of .row-actions-backdrop, and outside-click dismissal on the row-actions menu
       dies silently while Escape keeps working — that is issue #2523, which this rule caused when
       the pair still sat at 30-31 and this value first went to 40. Read the band table at
       .row-actions-menu before you raise this again.
    */
    z-index: 40;
}

.top-app-bar-lockup {
    display: flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    border-radius: 4px; /* focus-ring shape only — the lockup has no visible chrome at rest */
}

.top-app-bar-lockup:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px #FFFFFF; /* mirrors .user-chip-trigger's focus ring on the same navy bar */
}

.top-app-bar-mark {
    height: 32px;
    width: auto;
}

.top-app-bar-wordmark {
    font-family: var(--font-product);
    font-size: 15px;
    font-weight: 700;
    color: #FFFFFF; /* White on Navy — Style Guide v5 contrast table: 10.7:1, Pass AAA (mirrors .user-chip-name) */
}

.top-app-bar-actions {
    display: flex;
    align-items: center;
    gap: 16px;
}

.notification-bell {
    position: relative;
}

.notification-bell-trigger {
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 50%;
    width: 36px;
    height: 36px;
    padding: 0;
    cursor: pointer;
    color: #FFFFFF; /* White on Navy — mirrors .top-app-bar-wordmark's contrast pairing */
}

.notification-bell-trigger:hover {
    background: rgba(255, 255, 255, 0.06); /* mirrors .user-chip-trigger:hover */
}

.notification-bell-trigger:focus-visible,
.notification-bell-trigger:focus {
    outline: none;
    box-shadow: 0 0 0 2px #FFFFFF; /* mirrors .user-chip-trigger's focus ring on the same navy bar */
}

.notification-bell-badge {
    /* Overlay pill adapting .count-badge's shape (border-radius/font-size/padding) to sit anchored
       on the bell icon's corner instead of inline after text. */
    position: absolute;
    top: -4px;
    right: -4px;
    display: inline-block;
    min-width: 16px;
    background: #C0362C; /* Style Guide v5 alert/danger red — an unread badge is attention-seeking,
                             unlike .count-badge's neutral navy count on a white card. */
    color: #FFFFFF;
    border: 2px solid #1E3A5F; /* separates the badge from the navy bar it sits on */
    border-radius: 999px;
    padding: 0 4px;
    font-size: 10px;
    font-weight: 700;
    line-height: 14px;
    text-align: center;
    box-sizing: border-box;
}

/* Shared by NotificationBell.razor and UserChip.razor (Issue #2596) -- the fixed transparent
   backdrop that gives both top-app-bar dropdowns JS-free outside-click dismissal, the same
   pattern .row-actions-backdrop already uses. Sits BELOW its own panel (z-index 20) but does not
   need the global 50/51 band: both panels already live INSIDE .top-app-bar's own stacking
   context (see the z-index band table at .row-actions-menu below), so this backdrop rides along
   on the bar's 40 and only needs to outrank ordinary page content, not the bar itself. position:
   fixed still sizes to the full viewport from inside that nested context -- stacking order and
   containing-block are separate concerns -- so a click anywhere on the page still reaches it. */
.topnav-menu-backdrop {
    position: fixed;
    inset: 0;
    z-index: 15;
    background: transparent;
}

.notification-bell-panel {
    /* Mirrors .user-chip-menu's absolute anchoring, wider to fit a trigger-event label + record
       label + timestamp per row, and scrollable since AC-9's retention is unbounded. */
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    width: 320px;
    max-height: 420px;
    overflow-y: auto;
    background: #FFFFFF;
    border: 1px solid #E2E5EA;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
    padding: 6px;
    margin: 0;
    list-style: none;
    z-index: 20;
}

.notification-bell-error {
    display: block;
    background: #FDECEA;
    border: 1px solid #C0362C;
    border-radius: 6px;
    padding: 8px 12px;
    margin-bottom: 4px;
    font-size: 13px;
    color: #7A1E17;
}

.notification-bell-status {
    display: block;
    padding: 12px;
    font-size: 13px;
    color: #6B7280;
    text-align: center;
}

.notification-bell-row-item {
    position: relative;
}

.notification-bell-row {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    border-radius: 6px;
    padding: 8px 34px 8px 12px; /* right-padded to clear .notification-bell-row-dismiss */
    font-family: inherit;
    color: #1F2937;
    cursor: pointer;
}

.notification-bell-row:hover,
.notification-bell-row:focus-visible {
    background: #F3F4F6; /* mirrors .user-chip-menu-item's hover/focus fill */
    outline: none;
}

.notification-bell-row[aria-disabled="true"] {
    cursor: default;
    color: #9CA3AF;
}

.notification-bell-row-event {
    font-size: 12px;
    font-weight: 600;
    color: #1E3A5F;
}

.notification-bell-row-label {
    font-size: 13px;
}

.notification-bell-row-time {
    font-size: 11px;
    color: #6B7280;
}

.notification-bell-load-more {
    display: block;
    width: 100%;
    text-align: center;
    background: transparent;
    border: none;
    padding: 8px 12px;
    border-radius: 6px;
    font-size: 13px;
    font-family: inherit;
    color: #1E3A5F;
    cursor: pointer;
}

.notification-bell-load-more:hover,
.notification-bell-load-more:focus-visible {
    background: #F3F4F6;
    outline: none;
}

.notification-bell-load-more:disabled {
    color: #9CA3AF;
    cursor: default;
}

.notification-bell-row-dismiss {
    /* Small icon-only button, absolutely positioned at the row's right edge, mirroring
       .row-actions-trigger's hit-target-and-hover-affordance shape scaled down for this
       compact 320px-wide panel. */
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    background: transparent;
    color: #5A6779;
    border: 1px solid transparent;
    border-radius: 6px;
    cursor: pointer;
}

.notification-bell-row-dismiss:hover {
    background: #F7F9FB;
    border-color: #E1E5EB;
}

/* Outline-only, and declared on :focus-visible alone — mirrors .row-actions-trigger's own
   focus-visible-only rule (WCAG 2.4.7), never overriding the framework's bare :focus state. */
.notification-bell-row-dismiss:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 2px;
}

.notification-bell-header {
    display: flex;
    justify-content: flex-end;
    padding: 0 4px 4px;
}

.notification-bell-clear-all {
    /* Text-link-style button mirroring .user-chip-menu-item's typography, without its
       display:block/width:100% full-width row treatment (design.md UI Component Breakdown). */
    display: inline-block;
    background: transparent;
    border: none;
    padding: 4px 8px;
    border-radius: 6px;
    font-size: 14px;
    font-family: inherit;
    color: #1F2937;
    cursor: pointer;
}

.notification-bell-clear-all:hover,
.notification-bell-clear-all:focus-visible {
    background: #F3F4F6;
    outline: none;
}

.user-chip {
    position: relative;
}

.user-chip-trigger {
    display: flex;
    align-items: center;
    gap: 10px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 20px;
    padding: 6px 12px 6px 6px;
    cursor: pointer;
    font-family: var(--font-product);
}

.user-chip-trigger:hover {
    background: rgba(255, 255, 255, 0.06);
}

.user-chip-trigger:focus-visible,
.user-chip-trigger:focus {
    outline: none;
    box-shadow: 0 0 0 2px #FFFFFF; /* Navy ring would vanish against the now-navy app bar */
}

.user-chip-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: #FFFFFF; /* inverted from navy — a navy avatar would vanish on the navy bar */
    color: #1E3A5F;
    font-size: 13px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}

.user-chip-label {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: 1.2;
}

.user-chip-name {
    font-size: 13px;
    font-weight: 600;
    color: #FFFFFF; /* White on Navy — Style Guide v5 contrast table: 10.7:1, Pass AAA */
}

.user-chip-role {
    font-size: 11px;
    color: rgba(255, 255, 255, 0.75); /* ~7.2:1 on #1E3A5F at 11px — mirrors the prior white-bar AA-at-11px treatment */
}

.user-chip-menu {
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    min-width: 160px;
    background: #FFFFFF;
    border: 1px solid #E2E5EA;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
    padding: 6px;
    margin: 0;
    list-style: none;
    z-index: 20;
}

.user-chip-menu-item {
    display: block;
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    padding: 8px 12px;
    border-radius: 6px;
    font-size: 14px;
    font-family: inherit;
    color: #1F2937;
    cursor: pointer;
}

.user-chip-menu-item:hover,
.user-chip-menu-item:focus-visible {
    background: #F3F4F6;
    outline: none;
}

/* Confirm dialog's "Log out" submit button rides inside its own <form> (see UserChip.razor) so
   the browser can POST to /account/signout directly; display:contents keeps the form's own box
   out of the .dialog-buttons flex layout so the button aligns like a normal sibling. */
.dialog-buttons form {
    display: contents;
}

/* Tablet-portrait and below (Style Guide v5 §2.5 responsive rules): collapse to avatar-only. */
@media (max-width: 768px) {
    .user-chip-label {
        display: none;
    }
}

.holiday-add-actions {
    display: flex;
    gap: 8px;
}

/* ---- Notes composer + write affordances (SPEC-015 PR 4c) ------------- */
.notes-tab-heading-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}
.notes-summary-actions {
    display: flex;
    align-items: center;
    gap: 10px;
}
.notes-add-btn,
.notes-summary-add {
    padding: 6px 14px;
    border: 1px solid #2B6CB0;
    border-radius: 6px;
    background: #2B6CB0;
    color: #FFFFFF;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}
.notes-add-btn:hover,
.notes-summary-add:hover {
    background: #24578F;
}
/* SPEC-015 FR-13 / AC-14 — attachment chips on a published note's card, with the author-only remove
   control. Visually quieter than the composer's editable chips: these are a read surface first. */
.note-card-attachments {
    list-style: none;
    margin: 10px 0 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.note-card-attachment {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    max-width: 100%;
    padding: 3px 6px 3px 10px;
    border: 1px solid #E1E7EF;
    border-radius: 999px;
    background: #F7F9FC;
    font-size: 12px;
    color: #1E3A5F;
}
/* Filenames are user-supplied and can be long — truncate rather than let one chip reflow the card.
   The full name stays available via the remove control's accessible name. */
.note-card-attachment-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 240px;
}
.note-card-attachment-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    border: none;
    border-radius: 999px;
    background: none;
    color: #5A6779;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
}
.note-card-attachment-remove:hover {
    background: #E1E7EF;
    color: #1E3A5F;
}
/* WCAG 2.4.7 — an 18px target on a tinted chip needs its own ring. */
.note-card-attachment-remove:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 2px;
}
.note-card-actions {
    display: flex;
    gap: 8px;
    margin-top: 10px;
}
/* SPEC-015 AC-32 — the author's own unpublished drafts, pinned above the published note list. Visually
   set apart from a note card (dashed border, tinted surface) so an unfinished draft is never mistaken
   for a published note; the "Draft" pill carries the same signal as text, so colour and border are not
   the sole indicator (WCAG 1.4.1). */
.note-draft-list {
    list-style: none;
    margin: 0 0 16px 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.note-draft-row {
    padding: 12px 14px;
    border: 1px dashed #C9CED8;
    border-radius: 8px;
    background: #FBFCFE;
}
.note-draft-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 6px;
}
.note-type-pill--draft {
    background: #EEF1F6;
    color: #5A6779;
}
.note-draft-preview {
    margin: 0;
    color: #5A6779;
    font-size: 13px;
    font-style: italic;
}
.note-draft-edit,
.note-draft-delete {
    padding: 4px 12px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    background: #FFFFFF;
    color: #1E3A5F;
    font-size: 12px;
    cursor: pointer;
}
.note-draft-edit:hover,
.note-draft-delete:hover {
    background: #F4F7FB;
}
.note-draft-delete {
    color: #B00020;
    border-color: #E3B4BC;
}
.note-card-edit,
.note-card-delete {
    padding: 4px 12px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    background: #FFFFFF;
    color: #1E3A5F;
    font-size: 12px;
    cursor: pointer;
}
.note-card-edit:hover,
.note-card-delete:hover {
    background: #F4F7FB;
}
.note-card-delete {
    color: #B00020;
    border-color: #E3B4BC;
}
.note-card-close-request {
    padding: 4px 12px;
    border: 1px solid #86EFAC;
    border-radius: 6px;
    background: #FFFFFF;
    color: #15803D;
    font-size: 12px;
    cursor: pointer;
}
.note-card-close-request:hover {
    background: #F0FDF4;
}

/* Inline Request-info "Pretrial response" card (FR-22/AC-22) — green nested card inside the parent
   note. The "Pretrial response" text label is the explicit signal (WCAG 1.4.1); green reinforces, it
   is not the sole indicator. Palette matches .success-message. */
.note-response-card {
    margin-top: 10px;
    padding: 10px 12px;
    background: #F0FDF4;
    border: 1px solid #86EFAC;
    border-left-width: 4px;
    border-radius: 6px;
    color: #15803D;
}
.note-response-header {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 6px;
}
.note-response-label {
    font-family: var(--font-accent);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    font-size: 11px;
}
.note-response-attribution {
    font-size: 12px;
    font-weight: 500;
}
.note-response-time {
    font-size: 12px;
    color: #4B5563;
}
.note-response-content {
    color: #1E293B;
    font-size: 14px;
    line-height: 20px;
}
.note-response-card--compact {
    margin-top: 6px;
    padding: 6px 8px;
}
.note-response-card--compact .note-response-content {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Docked composer panel — page-level (FR-9), persists across tab nav. Stacks at the bottom-right of
   the viewport (SPEC-015 AC-10 — restacked from the top per Issue #2176 / spec-delta-log.md
   Entry 270) — the same `bottom: 24px` position `.note-composer--collapsed` (below) already uses,
   so toggling minimize/restore never moves the panel's bottom edge, only its width and which of its
   own children are visible. Sized to its own content (`height: fit-content`) rather than stretched
   to the full viewport (Issue #1986) — `max-height` + `.note-composer-body`'s existing
   `overflow-y: auto` (below) are the same size-to-content-then-clamp-and-scroll pattern
   `dialog.modal-dialog` already uses, so a composer whose content genuinely exceeds the viewport
   still scrolls internally rather than running off screen. `max-height` subtracts the same
   `calc(100vh - 48px)` the modal uses (24px for the panel's own `bottom` offset, mirrored as a
   matching top margin) rather than the full `100vh` the old top-anchored rule used — uncapped, a
   tall composer would grow upward past the top of the viewport now that `bottom` is no longer 0. */
.note-composer {
    position: fixed;
    bottom: 24px;
    right: 0;
    height: fit-content;
    max-height: calc(100vh - 48px);
    width: 420px;
    max-width: 100%;
    background: #FFFFFF;
    border-left: 1px solid #C9CED8;
    box-shadow: -4px 0 16px rgba(30, 58, 95, 0.12);
    display: flex;
    flex-direction: column;
    z-index: 1200;
}
/* Issue #2194 — the expanded COMPOSE panel gets a deterministic height instead of its own
   content's. Anchored at `bottom`, a panel sized to its content moves its TOP edge whenever that
   content changes, which takes the header, the minimize toggle and the type pills with it. The
   trigger that made this a defect rather than a wart is the type tooltip: it renders on hover,
   below the fieldset, so the panel grows upward and the pill slides out from under a pointer that
   never moved — @onmouseleave fires, the tooltip clears, the panel shrinks, the pill returns, and
   @onmouseenter starts it again. Measured at 1280x800: 616px at rest, 640px with a one-line
   tooltip, 654px with a two-line one.

   640px is that one-line-tooltip height, so the common hover consumes the 24px of slack the panel
   rests with and changes nothing. THE LIMIT, stated rather than glossed: content taller than this
   — a tooltip that wraps past one line, a jurisdiction with enough note types to wrap the pill row,
   or a long list of attachment chips — scrolls `.note-composer-body` instead of growing the panel.
   That is the same size-to-a-clamp-then-scroll behaviour the `max-height` above already gave a tall
   composer, and it keeps the tooltip itself in view because the tooltip sits ABOVE the editor and
   the attach section, so the overflow is clipped from the bottom.

   Scoped to compose mode rather than applied to `.note-composer`, because only compose mode can
   change height after its loads land. Edit mode renders no tooltip and no attach section, so it
   settles once and is correctly left sized to its own content. */
.note-composer--compose {
    height: min(640px, calc(100vh - 48px));
}
/*
   Navy composer header (SPEC-015 AC-24). #1E3A5F is the portal's primary navy — the same token as
   the active tab, the KPI counts, and the bulk-action bar; white title text on it is White on Navy,
   10.7:1 per the Style Guide v5 contrast table, Pass AAA (WCAG 2.1 SC 1.4.3, AA).

   `gap` + `margin-right: auto` on the h2 rather than `justify-content: space-between`: the header now
   holds THREE children in a pinned order (title, minimize/restore, Close — AC-24), and
   space-between would spread the two buttons to opposite ends of the bar instead of grouping them
   at the trailing edge.

   `border-radius: 8px 0 0 0` (Issue #1986) matches the 8px radius `dialog.modal-dialog` uses
   elsewhere — only the top-left corner, since the panel is docked flush against the viewport's
   right edge (top-right is off-screen) and the bottom corners belong to whichever of
   `.note-composer-body` / `.note-composer-footer` is currently the panel's last child.
*/
.note-composer-header {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 14px 18px;
    background: #1E3A5F;
    border-bottom: 1px solid #EEEEEE;
    border-radius: 8px 0 0 0;
}
.note-composer-header h2 {
    font-size: 16px;
    color: #FFFFFF;
    margin: 0;
    margin-right: auto;
}
/*
   Both header controls are reverse-contrast on the navy fill: white glyph on transparent, the same
   inverted White-on-Navy pair the bulk-action bar uses (10.7:1 either way round).
*/
.note-composer-close,
.note-composer-minimize {
    border: none;
    background: none;
    line-height: 1;
    color: #FFFFFF;
    cursor: pointer;
}
.note-composer-close {
    font-size: 22px;
    /* SPEC-021 Task 5: raised to the Style Guide's own 40px pointer minimum (AC-7). */
    min-width: 40px;
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
/* Issue #2658: the X is disabled while a write or a Cancel-time discard is in flight; without this it
   renders unchanged and pointer-cursored while inert. Disabled controls are exempt from WCAG 1.4.3. */
.note-composer-close:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}
/*
   The minimize glyph is a character (– / +), not an SVG — SPEC-021 AC-2 forbids per-page inline SVG
   iconography. Sized a little smaller than the × so the two read as a matched pair rather than the
   dash looking like a stray rule.
*/
.note-composer-minimize {
    font-size: 20px;
    padding: 0 4px;
}
/*
   White focus ring — the page's #1E3A5F ring would vanish against the navy header. Same rule and
   same reason as `.bulk-action-push:focus-visible`, which is the shipped precedent AC-24 points at.
   WCAG 2.1 SC 1.4.11 (Non-text Contrast, AA) for the focus indicator against the navy fill.
*/
.note-composer-close:focus-visible,
.note-composer-minimize:focus-visible {
    outline: 2px solid #FFFFFF;
    outline-offset: 2px;
}
/*
   Collapsed composer (AC-26). CSS-ONLY: the body and footer are hidden, never unmounted, so the
   TelerikEditor keeps its value, cursor, and undo history and the minimize button stays the same DOM
   element (focus survives with no focus management). See design.md OQ-D9 and the comment on the
   <aside> in NoteComposer.razor.

   `display: none` rather than visibility/clipping, so the collapsed body also leaves the
   ACCESSIBILITY TREE — a screen reader is not offered a hidden editor it cannot reach.

   The panel drops its full-height stretch and becomes a small dock at the bottom of the right edge,
   showing the navy header alone. It keeps the composer title, so a user who minimized and then
   navigated tabs can still see what is parked there.
*/
.note-composer--collapsed {
    /* Overrides `.note-composer--compose` above, which the collapsed panel still carries — minimize
       is a display state, not a different panel. Without this the dock would keep the expanded
       panel's 640px as empty space below a header that is all it still shows. Issue #2194. */
    height: auto;
    bottom: 24px;
    width: auto;
    max-width: 320px;
    border-radius: 8px 0 0 8px;
}
.note-composer--collapsed .note-composer-body,
.note-composer--collapsed .note-composer-footer {
    display: none;
}
.note-composer--collapsed .note-composer-header {
    border-bottom: none;
    /* Matches the collapsed dock's own `border-radius: 8px 0 0 8px` above. The header's background
       fills its own box, so left uncorrected its new top-left-only radius (Issue #1986) would paint
       a square corner over the dock's existing rounded bottom-left — the header IS the dock's entire
       visible extent once the body/footer are hidden. */
    border-radius: 8px 0 0 8px;
}
/*
   Composer author identity block (SPEC-015 AC-25) — avatar + display name + role(s), above the type
   selector. Reuses the generic `.avatar` circle (UserChip / UsersListPage / LinkedNoteCard precedent)
   rather than declaring another 32px circle, so only the surrounding row and the two text lines are
   new here.
*/
.note-composer-identity {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-bottom: 12px;
    border-bottom: 1px solid #EEEEEE;
}
.note-composer-identity-text {
    display: flex;
    flex-direction: column;
    /* min-width: 0 lets a long name or a many-role label ellipsize inside the flex row instead of
       widening the fixed-width docked panel. */
    min-width: 0;
}
.note-composer-identity-name {
    font-size: 14px;
    font-weight: 600;
    color: #1E3A5F;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/*
   Roles render comma-joined (AC-25 / OQ-9), so this line can be long for a multi-role user. Truncated
   rather than wrapped, to keep the block one row tall regardless of role count.
*/
.note-composer-identity-role {
    font-size: 12px;
    color: #5A6779;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* `scrollbar-gutter` is load-bearing, not polish (issue #2194). The pill row above is
   `display: flex; flex-wrap: wrap`, so the ~15px a scrollbar takes off this box's inner width the
   first time content overflows is enough to rewrap it — which moves a pill sideways and
   reintroduces, on the horizontal axis, exactly the instability the fixed height removes from the
   vertical one. Reserving the gutter unconditionally means the overflow costs no width. */
.note-composer-body {
    flex: 1;
    overflow-y: auto;
    scrollbar-gutter: stable;
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.note-composer-field-label {
    font-size: 13px;
    font-weight: 600;
    color: #1E3A5F;
}
/* Note-type pill selector (SPEC-015 AC-4/AC-5/AC-9/AC-13, Issue #1433 — replaced a <select>).
   Shares the rounded-pill language of .note-type-pill used on the notes list rows, so a type reads the
   same in the composer as it does on the note it produces. The native radio is visually hidden rather
   than display:none — display:none would drop it out of the tab order and take the browser's arrow-key
   group navigation with it, which is the entire reason for using radios here. */
.note-composer-type-fieldset {
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;
}
.note-composer-type-fieldset > legend {
    padding: 0;
    margin-bottom: 6px;
}
.note-composer-type-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.note-composer-type-pill {
    display: inline-flex;
    align-items: center;
    /* Positioning context for the clipped radio below. Without it the radio's 1px box anchors to whichever
       ancestor happens to be positioned, which can put it outside the viewport — and the browser scrolls to
       a focused element, so arrow-keying the group would scroll the page for no visible reason. */
    position: relative;
    /* Style Guide v5 §3.3: 40px minimum hit area on pointer devices. The <select> this replaced was 38px. */
    min-height: 40px;
    padding: 0 14px;
    border: 1px solid #C9CED8;
    border-radius: 999px;
    background: #FFFFFF;
    color: #1A202C;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}
.note-composer-type-pill:hover {
    background: #F5F7FA;
}
.note-composer-type-pill--selected {
    background: #E6F0FA;
    border-color: #2B6CB0;
    /* #2B6CB0 on #E6F0FA — the same pair .note-type-pill already ships on the notes list. */
    color: #2B6CB0;
}
/* Declared after --selected, which otherwise wins the equal-specificity tie and leaves the selected pill
   the only one in the group with no hover feedback. The feedback lands on the border rather than the fill:
   #2B6CB0 on #E6F0FA is 4.70:1, only 0.2 above the 4.5:1 floor for 13px text, so any tint deep enough to be
   a visible hover would spend that margin (#D7E7F7 measures 4.30:1 and fails). Navy border + the matching
   inset keeps the pill reading as selected and costs the label nothing. */
.note-composer-type-pill--selected:hover {
    border-color: #1E3A5F;
    box-shadow: inset 0 0 0 1px #1E3A5F;
}
/* The focus ring has to land on the label, since the radio that actually receives focus is clipped to a
   1px box. :focus-within is what carries it across (WCAG 2.1 SC 2.4.7). 3px Navy per Style Guide v5. */
.note-composer-type-pill:focus-within {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}
.note-composer-type-pill > input[type="radio"] {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
.note-composer-type-readonly {
    margin: 0;
    font-weight: 600;
    color: #1E3A5F;
}
.note-composer-type-tooltip {
    /* <output> is inline by default; the old <p> was block. */
    display: block;
    margin: 0;
    font-size: 12px;
    font-style: italic;
    color: #5A6779;
}
.note-composer-error {
    color: #B00020;
    font-style: italic;
    margin: 0;
}

/* SPEC-015 FR-13 / AC-14 — attach-document affordance and attachment chips. Tokens match the
   composer's existing controls (#C9CED8 borders, 6px radii, 13-14px type) so the attach row reads
   as part of the same form rather than a bolt-on. */
.note-composer-attach {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.note-composer-attach-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.note-composer-attach-select {
    flex: 1 1 240px;
    min-width: 0;
    height: 38px;
    padding: 0 10px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    font-size: 14px;
}
/* The native file input is kept in the accessibility tree (never display:none) so it stays
   keyboard-reachable and screen-reader-announceable; the label supplies the visible affordance. */
.note-composer-attach-upload {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: #1E3A5F;
    cursor: pointer;
}
.note-composer-attach-upload input[type="file"] {
    font-size: 12px;
    max-width: 200px;
}
.note-composer-chips {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.note-composer-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    max-width: 100%;
    padding: 4px 6px 4px 12px;
    border: 1px solid #C9CED8;
    border-radius: 999px;
    background: #F4F7FA;
    font-size: 13px;
    color: #1E3A5F;
}
/* Filenames are user-supplied and can be long: truncate rather than let one chip push the
   composer's layout. The full name stays available via the remove control's accessible name. */
.note-composer-chip-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 220px;
}
.note-composer-chip-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    border: none;
    border-radius: 999px;
    background: none;
    color: #5A6779;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
}
.note-composer-chip-remove:hover:not(:disabled) {
    background: #E1E7EF;
    color: #1E3A5F;
}
.note-composer-chip-remove:disabled {
    color: #A9BDD4;
    cursor: not-allowed;
}
/* WCAG 2.4.7: the chip's remove control is a 20px target inside a tinted chip, so it does not
   inherit a usable ring from the page default — give it its own. */
.note-composer-chip-remove:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 2px;
}
.note-composer-attach-select:focus-visible,
.note-composer-attach-upload input[type="file"]:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 2px;
}
/* AC-17 / ADR-0039 §6 — a chip whose document has not reached Clean. flex-wrap lets the reason
   line wrap onto its own row without a second element type. The chip root keeps the normal chip
   colours: the amber carries a message about the scan state, not about the document, so tinting the
   whole chip (filename included) reads as "this document is the problem". */
.note-composer-chip--blocked {
    flex-wrap: wrap;
    align-items: center;
}
/* Reuses StyleGuide.cs's WarningPrimary/WarningTint pair (#8A6B25 on #FDF5E6, the same 4.6:1-AA
   tokens .document-scan-state already uses for the identical concept on the Documents tab) rather
   than inventing a second colour for one state. order:1 puts the reason after the remove control
   visually, so the remove button keeps the position it holds on a normal chip, while the DOM order
   (name, reason, remove) still reads the reason before its control to assistive tech. flex-basis
   forces the wrap; max-width clamps the tint to the message text. */
.note-composer-chip-reason {
    order: 1;
    flex-basis: 100%;
    max-width: fit-content;
    padding: 1px 8px;
    border-radius: 999px;
    background: #FDF5E6;
    font-size: 12px;
    color: #8A6B25;
}
/* The draft-restore "N attachment(s) no longer available" announcement (ADR-0039 §6) — informational
   (role=status, not role=alert), so it takes the muted secondary text colour already used for
   .note-composer-type-tooltip rather than the error red below. */
.note-composer-notice {
    color: #5A6779;
    font-style: italic;
    margin: 0;
}
.note-composer-footer {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 14px 18px;
    border-top: 1px solid #EEEEEE;
}
.note-composer-cancel,
.note-composer-draft {
    padding: 8px 16px;
    border: 1px solid #C9CED8;
    border-radius: 6px;
    background: #FFFFFF;
    color: #1E3A5F;
    font-size: 13px;
    cursor: pointer;
}
.note-composer-submit {
    padding: 8px 18px;
    border: 1px solid #2B6CB0;
    border-radius: 6px;
    background: #2B6CB0;
    color: #FFFFFF;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}
.note-composer-submit:disabled {
    background: #A9BDD4;
    border-color: #A9BDD4;
    cursor: not-allowed;
}

/* ---------------------------------------------------------------------------
   SPEC-018 — Notification host: pop-up dialog + in-app toast stack
   (AC-19 modal presentation, FR-31 toasts). Rendered by NotificationHost,
   which AuthenticatedRootLayout mounts on every authenticated surface.
   --------------------------------------------------------------------------- */

/* ---- Pop-up notification dialog (AC-19, AC-20) ----------------------- */

/*
   Layers on the shared dialog.modal-dialog frame (white card, 8px radius, centered via
   position:fixed + inset:0 + margin:auto). AC-19's "translucent navy backdrop" is the ::backdrop
   below rather than a hand-rolled overlay div: the browser paints ::backdrop for a showModal()
   dialog and makes everything outside the dialog genuinely inert, which an overlay div only
   simulates visually. #1E3A5F is the portal's primary navy (same token as the active tab and the
   selection bar); at 0.55 alpha the page reads as suppressed while staying legible behind the card.
*/
/*
   Width comes from the shared frame: 480px content, 544px rendered. A bare
   `.popup-notification-dialog { max-width: 520px }` used to sit here and never applied — (0,1,0)
   against the frame's (0,1,1) — so the card has always shipped at 480. Deleted rather than
   activated on the PO ruling in Issue #1295: Style Guide v5 §2.7 permits 480–640px, so both
   widths comply and 544px rendered has been through visual review since the component landed.
   If the pop-up ever gains content that feels tight, 520 is a one-line change — as
   `dialog.popup-notification-dialog`, not a bare class. Note the ::backdrop rule below IS
   prefixed and does apply.
*/

dialog.popup-notification-dialog::backdrop {
    background: rgba(30, 58, 95, 0.55);
}

.popup-notification-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}

/* No ✕ / close affordance by design: AC-20 admits exactly two exits, Snooze and Dismiss, and both
   write an audit row. A close button would be a third, silent one. */
.popup-notification-body {
    font-size: 14px;
    line-height: 22px;
    color: #2D3748;
    margin: 0;
}

.popup-notification-error {
    font-size: 13px;
    line-height: 20px;
    color: #9B2C2C; /* #9B2C2C on #FFFFFF — 6.3:1, Pass AA */
    margin: 0;
}

.popup-notification-snooze {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding-top: 4px;
    border-top: 1px solid #E2E8F0;
}

.popup-notification-snooze-label {
    font-size: 13px;
    font-weight: 600;
    color: #5A6779;
    margin-right: 4px;
}

.popup-notification-actions {
    display: flex;
    flex-direction: row;
    justify-content: flex-end;
    gap: 8px;
}

/* ---- In-app toast stack (FR-31) -------------------------------------- */

/*
   Fixed to the top-right of the viewport, above page chrome but below the browser's top layer — a
   showModal() dialog is promoted to the top layer and paints over this regardless of z-index, which
   is the right precedence: a pop-up requires a decision, a toast does not.

   pointer-events:none on the (permanently rendered, usually empty) region so an empty live region
   cannot swallow clicks on the page beneath it; re-enabled on each toast card.
*/
.notification-toasts {
    position: fixed;
    top: 72px;
    right: 24px;
    z-index: 900;
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 340px;
    max-width: calc(100vw - 48px);
    pointer-events: none;
}

.toast-notification {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 14px;
    border: 1px solid #C9CED8;
    border-left: 4px solid #1E3A5F;
    border-radius: 6px;
    background: #FFFFFF;
    box-shadow: 0 4px 12px rgba(15, 23, 42, 0.14);
    pointer-events: auto;
}

.toast-notification-content {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.toast-notification-heading {
    font-size: 13px;
    font-weight: 700;
    color: #1E3A5F;
    margin: 0;
    line-height: 18px;
}

.toast-notification-body {
    font-size: 13px;
    color: #2D3748;
    margin: 0;
    line-height: 19px;
    overflow-wrap: anywhere;
}

.toast-notification-close {
    flex: 0 0 auto;
    padding: 0 4px;
    border: none;
    background: transparent;
    color: #5A6779;
    font-size: 13px;
    line-height: 18px;
    cursor: pointer;
    /* SPEC-021 Task 5: raised to the Style Guide's own 40px pointer minimum (AC-7). */
    min-width: 40px;
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.toast-notification-close:focus-visible {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}


/* ---------------------------------------------------------------------------
   SPEC-018 — Notifications admin page shell (FR-1 / AC-1). Tab strip + panel
   for Admin -> Notifications; the per-tab content (Rules / Templates /
   Delivery log) lands with Task 6.3 and reuses the shared .tab-stub frame
   until then.
   --------------------------------------------------------------------------- */

.notifications-admin-page {
    /* No page padding: AdminLayout's .admin-main-content already pads 32px, and the tab
       strip must sit flush against that padding like the defendant tab strip does. */
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* AC-23 breadcrumb. Structure and rule shapes mirror .notes-admin-breadcrumb (SPEC-015 AC-28) --
   the "/" separator is Style Guide v5 §2.5's, generated as decorative ::after content so it never
   enters the crumb's accessible name. Margins are 0 here (not 16px like the Notes/Queue Views
   pattern) because .notifications-admin-page is a flex column with its own gap:16px already
   spacing every direct child -- an additional margin would double the gap. */
.notifications-admin-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 13px;
    line-height: 18px;
    color: #5A6779;
}

.notifications-admin-breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-left: 6px;
    color: #A0AAB8;
}

.notifications-admin-breadcrumb li[aria-current="page"] {
    color: #1A202C;
    font-weight: 600;
}

.notifications-admin-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.notifications-admin-header h1 {
    margin: 0;
    font-size: 24px;
    color: #1A202C;
}

/* AC-24's page description. Same zero-margin reasoning as the breadcrumb above -- the flex column's
   own gap:16px provides the spacing. AC-25 pins .notifications-admin-page as already carrying no
   max-width -- do not add one here. */
.notifications-admin-page-description {
    margin: 0;
    color: #5A6779;
    font-size: 14px;
    line-height: 20px;
}

.notifications-admin-no-tabs {
    margin: 0;
    color: #5A6779;
}

/* Mirrors .defendant-tab-strip's contract (Style Guide v5 tab treatment) without inheriting
   its horizontal page padding — this strip is already inside .admin-main-content. */
.notifications-tab-strip {
    display: flex;
    gap: 4px;
    background: #F5F5F5;
    border-bottom: 1px solid #DDDDDD;
}

.notifications-tab {
    appearance: none;
    background: transparent;
    border: none;
    border-bottom: 3px solid transparent;
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 600;
    color: #666666;
    cursor: pointer;
}

.notifications-tab:hover { color: #1E3A5F; }

.notifications-tab:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: -2px;
}

.notifications-tab-active {
    color: #1E3A5F;
    border-bottom-color: #1E3A5F;
}

/* AC-26's per-tab description. .notifications-tab-content had no layout rule of its own before
   this -- a plain <section> whose one prior child (the active tab's own component) needed none.
   Flex column + gap:16px is the same spacing pattern every other container on this page already
   uses (.notifications-admin-page, .notifications-rules-tab) instead of margins, so the new
   paragraph and the tab component below it space themselves the same way the page-level chrome
   above them does. */
.notifications-tab-content {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* Same secondary-text treatment as AC-24's .notifications-admin-page-description -- both are
   Style Guide v5 Body/Small descriptive copy, just at different scopes (page-level vs. tab-level). */
.notifications-tab-description {
    margin: 0;
    color: #5A6779;
    font-size: 14px;
    line-height: 20px;
}

/* ---------------------------------------------------------------------------
   SPEC-018 — Notifications admin, Rules tab (FR-2 / FR-7 / FR-8; AC-2, AC-7,
   AC-8). Table shape mirrors the shipped .conditions-table contract (Style
   Guide v5 admin table) and reuses the shared .status-pill / .link-button /
   .sr-only treatments rather than introducing notifications-only variants.
   --------------------------------------------------------------------------- */

/* No top padding here: .notifications-tab-content is a direct child of the flex-column
   .notifications-admin-page, whose gap:16px already separates the panel from the tab strip.
   Adding padding on top of that gap doubles the space to 32px. (The .tab-stub siblings look
   inset only because the stub frame carries its own padding:32px internally.) */
.notifications-rules-tab {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.notifications-rules-loading {
    margin: 0;
    color: #5A6779;
}

.notifications-rules-empty-state {
    padding: 40px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    text-align: center;
    color: #5A6779;
}

.notifications-rules-empty-state p { margin: 0; }

.notifications-rules-table {
    width: 100%;
    border-collapse: collapse;
    background: #FFFFFF;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid #E1E5EB;
}

.notifications-rules-table th,
.notifications-rules-table td {
    text-align: left;
    padding: 12px 16px;
    border-bottom: 1px solid #EEF0F3;
    font-size: 14px;
    color: #1A202C;
    vertical-align: top;
}

.notifications-rules-table th {
    font-weight: 600;
    color: #5A6779;
    background: #F7F9FB;
}

/* No `display: flex` here: a flex <td> stops being a table-cell and drops out of the column
   width algorithm, so the Channels column would size independently of its header. The chips
   are inline-block with margin spacing instead, which keeps the cell a real table-cell. */
.notifications-rule-channels-cell {
    max-width: 320px;
}

/* Reads as a channel tag, deliberately quieter than .status-pill — the Status column is the
   scannable signal in this table and two pill treatments at equal weight would compete. */
.notifications-rule-channel-chip {
    display: inline-block;
    margin: 0 6px 4px 0;
    padding: 3px 9px;
    border-radius: 4px;
    background: #EEF2F7;
    color: #2D3B4E;
    font-size: 12px;
    line-height: 16px;
    white-space: nowrap;
}

.notifications-rule-channels-none {
    color: #5A6779;
    font-size: 12px;
    font-style: italic;
}

/* One kebab, not three link-buttons, since Issue #1277. Right-aligned to match .row-actions-cell's
   own justify-content: flex-end. */
.notifications-rule-actions-cell {
    white-space: nowrap;
    text-align: right;
}

/* .notifications-rules-table sets `overflow: hidden` to clip its corner radius, which also clips the
   absolutely-positioned row-actions panel -- the same defect .conditions-table causes, and the same
   defect Telerik's five grid ancestors cause on the Notes surface. Measured here by reading the rule
   rather than assumed from those cases. Lifting the clip is scoped with :has() so it applies ONLY
   while a panel is mounted: with every menu closed the table keeps `overflow: hidden` and its corner
   clip exactly as before.

   Trade-off to verify by hand: while a panel is open the table's own corner clip is suspended, so the
   last row's square background corner can peek past the radius. Cosmetic, and only for as long as a
   menu is open. */
.notifications-rules-table:has(.row-actions-menu) {
    overflow: visible;
}

.notifications-rules-toolbar {
    display: flex;
    justify-content: flex-end;
}

/* ---------------------------------------------------------------------------
   SPEC-018 — Notifications admin, rule editor modal (FR-3 / FR-4 / FR-6 / FR-9
   / FR-27; AC-3, AC-4, AC-6, AC-9). The dialog frame (padding, header, body,
   footer) is the shipped sectioned-dialog treatment shared with the condition
   editor — this block adds only what a multi-field rule form needs on top.
   --------------------------------------------------------------------------- */

/* The `dialog` element prefix is REQUIRED here for the same reason as the sectioned rules above:
   `dialog.modal-dialog` is (0,1,1), so a bare class selector would lose. */
dialog.rule-editor-dialog {
    /* Taller than the condition editor (three pickers + four channel toggles + five delivery
       controls), so the body scrolls rather than the dialog overflowing a short viewport. */
    max-height: calc(100vh - 64px);
}

.rule-editor-body {
    overflow-y: auto;
}

.rule-editor-loading {
    margin: 0;
    color: #5A6779;
}

.rule-editor-body select,
.rule-editor-body input[type="number"],
.rule-editor-body input[type="time"] {
    width: 100%;
    box-sizing: border-box;
    font-family: inherit;
    font-size: 14px;
    color: #1A202C;
    background: #FFFFFF;
    border: 1px solid #CBD2DC;
    border-radius: 6px;
    padding: 8px 10px;
    /* Neutralizes the global `.form-field input { height: 44px }`, which these controls inherit
       through their .form-field wrappers and which reads oversized next to the select rows. */
    height: auto;
}

.rule-editor-body select:focus-visible,
.rule-editor-body input:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 1px;
}

/* <fieldset> defaults (border, inline-block sizing) fight the .form-field flex column the channel and
   quiet-hours groups reuse; reset them and let <legend> carry the same treatment as a field label. */
.rule-editor-channels,
.rule-editor-quiet-hours,
.rule-editor-scope {
    border: none;
    margin: 0;
    padding: 0;
    min-width: 0;
}

/* Issue #2263: the recipient-role / queue-scope checkbox groups scroll rather than growing the modal
   unboundedly when a jurisdiction has many roles or queues — the same overflow treatment as any other
   bounded picker list in this admin surface.
   `flex-shrink: 0` is REQUIRED alongside `overflow-y: auto`: as a flex item of `.rule-editor-body`'s
   column, `overflow` other than `visible` sets this fieldset's automatic minimum size to 0 (CSS
   Flexbox §4.5), so with the default `flex-shrink: 1` a body whose total content exceeds the dialog's
   available height (any jurisdiction with enough channels/quiet-hours content below it) squeezes THIS
   element down to a sliver — its legend's line-height — before shrinking any sibling, since every
   sibling here keeps `overflow: visible` and so keeps its content size as its floor. The squeezed
   fieldset's checkbox rows still paint at their natural size past that collapsed border-box, landing on
   top of `.rule-editor-channels` below and stealing its clicks. Pinning `flex-shrink: 0` keeps this
   fieldset at its own content height — up to `max-height` for a genuinely long role/queue list, where
   its own overflow-y then scrolls as intended — and leaves `.rule-editor-body`'s own `overflow-y: auto`
   to absorb any overall deficit instead. Found via Issue #2263 Task 10.4 E2E failures
   (RuleEditorConfirmFocusE2ETests): getBoundingClientRect showed both scope fieldsets rendered at
   height:16px while their own scrollHeight (54px / 29px) said otherwise. */
.rule-editor-scope {
    max-height: 200px;
    overflow-y: auto;
    flex-shrink: 0;
}

.rule-editor-channels legend,
.rule-editor-quiet-hours legend,
.rule-editor-scope legend {
    font-family: var(--font-accent);
    padding: 0;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779;
}

/* The `.form-field` prefix is REQUIRED. These are <label> elements inside a fieldset that also
   carries .form-field, so the base `.form-field label` rule (0,1,1) matches them and uppercases
   their text. A bare `.rule-editor-channel` is (0,1,0) — equal on class count but losing on the
   element component — so it would NOT override, and the modal would render EMAIL / IN-APP TOAST
   while the Rules table renders the same ChannelPresentation strings as Email / In-app toast.
   The prefixed form is (0,2,0) and wins outright, rather than depending on source order.
   These are checkbox option labels, not field labels; the <legend> carries the group's label
   treatment. Caught in the PR 6d manual walkthrough. */
.form-field .rule-editor-channel,
.form-field .rule-editor-scope-option {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    font-size: 14px;
    color: #1A202C;
    text-transform: none;
    font-weight: 400;
    letter-spacing: normal;
}

/* The global `.form-field input { height: 44px; padding: 0 12px }` would blow the checkboxes up
   into 44px boxes; restore the native control size. */
.rule-editor-channel input[type="checkbox"],
.rule-editor-scope-option input[type="checkbox"] {
    width: 16px;
    height: 16px;
    padding: 0;
    margin: 0;
    accent-color: #1E3A5F;
}

/* Issue #2263: the standalone All-queues toggle sits visually apart from the individual queue
   checkboxes it disables/clears, so the mutual-exclusivity reads before a user tries both. */
.rule-editor-all-queues {
    padding-bottom: 8px;
    margin-bottom: 4px;
    border-bottom: 1px solid #E2E8F0;
}

/* The AC-4 "use sparingly" indicator on the pop-up channel. Amber rather than the navy chip palette:
   this is a caution about recipient interruption, not another neutral tag. */
.rule-editor-sparingly {
    font-family: var(--font-accent);
    padding: 2px 8px;
    border-radius: 4px;
    background: #FDF3E0;
    color: #8A5A00;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.3px;
    text-transform: uppercase;
}

.rule-editor-hint {
    margin: 4px 0 0 0;
    font-size: 12px;
    line-height: 18px;
    color: #5A6779;
}

.rule-editor-quiet-hours-inputs {
    display: flex;
    gap: 12px;
    margin-top: 6px;
}

.rule-editor-quiet-hours-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1;
    min-width: 0;
}

.rule-editor-quiet-hours-field label {
    font-family: var(--font-accent);
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779;
}

/* ---------------------------------------------------------------------------
   SPEC-018 — Notifications admin, Templates tab (FR-10 / FR-12 / FR-13 / FR-14;
   AC-10, AC-12, AC-13, AC-14). Master rail + detail editor. Reuses the shared
   .form-field / .dialog-buttons / .success-message / .error-message treatments
   rather than introducing templates-only variants; this block adds only the
   two-pane layout, the rail, and the merge-field chip row.
   --------------------------------------------------------------------------- */

/* No top padding: .notifications-tab-content is a direct child of the flex-column
   .notifications-admin-page, whose gap:16px already separates the panel from the tab strip
   (the same note the Rules tab carries — padding here doubles that gap to 32px). */
.notifications-templates-tab {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.notifications-templates-loading,
.notifications-template-detail-prompt {
    margin: 0;
    color: #5A6779;
}

.notifications-templates-empty-state {
    padding: 40px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    text-align: center;
    color: #5A6779;
}

.notifications-templates-empty-state p { margin: 0; }

/* Wraps rather than scrolls on a narrow viewport: the rail is a list of 20 short labels, so
   stacking it above the editor stays usable where a horizontal scroll would not. */
.notifications-templates-layout {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 16px;
}

.notifications-templates-rail {
    flex: 0 0 240px;
    min-width: 0;
    padding: 8px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
}

.notifications-templates-group + .notifications-templates-group {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid #EEF0F3;
}

/* The group heading is the trigger event (AC-10's grouping), deliberately quieter than the
   detail pane's own <h3> — it labels a section of the rail, it is not the page's subject. */
.notifications-templates-group-heading {
    font-family: var(--font-accent);
    margin: 0 0 6px 0;
    padding: 0 8px;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779;
}

.notifications-templates-rail ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.notifications-template-rail-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
    appearance: none;
    background: transparent;
    border: none;
    border-radius: 4px;
    padding: 7px 8px;
    font-size: 14px;
    color: #1A202C;
    text-align: left;
    cursor: pointer;
}

.notifications-template-rail-item:hover:not(:disabled) { background: #F2F5F9; }

.notifications-template-rail-item:disabled {
    color: #8A95A5;
    cursor: default;
}

/* Restored in PR 6f. PR 6e's app.css hunk ended on this selector and wrote it OVER the
   `/* ---` opener of the SPEC-017 comment below, which left this rule with no declarations
   (no focus ring on a rail item — WCAG 2.4.7) and left the comment text parsing as CSS
   inside this dangling block. Body matches the shipped .notifications-tab:focus-visible
   treatment, the same inset navy outline the tab strip above the rail uses. */
.notifications-template-rail-item:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: -2px;
}

/* ---------------------------------------------------------------------------
   SPEC-018 — Notifications admin, Delivery log tab (FR-15 / FR-16 / FR-17;
   AC-15, AC-16, AC-17). Stats strip + filter bar + newest-first table. Table
   shape mirrors the sibling .notifications-rules-table contract exactly rather
   than restating it in a second vocabulary, and the row actions reuse the
   shared .link-button / .status-pill / .pagination treatments.
   --------------------------------------------------------------------------- */

/* No top padding: .notifications-tab-content is a direct child of the flex-column
   .notifications-admin-page, whose gap:16px already separates the panel from the tab strip
   (the same note the Rules and Templates tabs carry — padding here doubles that gap to 32px). */
.notifications-delivery-tab {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.notifications-delivery-loading {
    margin: 0;
    color: #5A6779;
}

/* A <ul> rather than a row of <div>s: the strip is four related values, and the list
   semantics plus its aria-label give a screen-reader user the count and the grouping
   for free (WCAG 1.3.1). */
.notifications-delivery-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.notifications-delivery-stat {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 120px;
    padding: 12px 16px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-left-width: 4px;
    border-radius: 8px;
    /* Button-element resets (AC-29): each tile is a <button> toggle for the Status filter, so strip
       the UA form-control defaults the same way button.kpi-tile does, and let the <li> wrapper stretch
       the button to the full tile height. */
    height: 100%;
    box-sizing: border-box;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
    appearance: none;
}

button.notifications-delivery-stat:focus-visible {
    outline: 2px solid #2B6CB0;
    outline-offset: 2px;
}

/* AC-29 active tile — the Pending Decisions .kpi-tile-active navy, drawn as a box-shadow ring
   rather than a thicker border so the layout does not shift and the status-colored left border
   stays. Named --filtering, not --active: --active is already the Delivered status color. */
.notifications-delivery-stat.notifications-delivery-stat--filtering {
    box-shadow: 0 0 0 2px #1E3A5F;
}

.notifications-delivery-stat-count {
    font-size: 24px;
    font-weight: 600;
    line-height: 1;
    color: #1A202C;
}

.notifications-delivery-stat-label {
    font-family: var(--font-accent);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779;
}

/* The left border carries the status color, keyed to the same modifier vocabulary the row
   pills use — so a tile and the rows it counts read as the same status without the tile
   having to shout in a filled color. */
.notifications-delivery-stat--active  { border-left-color: #0F7B5C; }
.notifications-delivery-stat--failed  { border-left-color: #B03030; }
.notifications-delivery-stat--pending { border-left-color: #2B6CB0; }

.notifications-delivery-filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 12px;
}

/* Each filter is a <label> wrapping its own control, so the visible caption IS the
   accessible name — no aria-label duplicating text already on screen (WCAG 1.3.1). */
.notifications-delivery-filter {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 12px;
    font-weight: 600;
    color: #5A6779;
}

.notifications-delivery-filter-input {
    min-width: 150px;
    padding: 7px 10px;
    border: 1px solid #CBD2DC;
    border-radius: 4px;
    font-size: 14px;
    font-weight: 400;
    color: #1A202C;
    background: #FFFFFF;
}

.notifications-delivery-filter-input:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: 1px;
}

/* Pushed to the far end of the bar: it acts on the whole log, not on the filters beside
   it, and sitting flush against the Recipient picker would imply otherwise. */
.notifications-delivery-retry-all {
    margin-left: auto;
}

.notifications-delivery-empty-state {
    padding: 40px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    text-align: center;
    color: #5A6779;
}

.notifications-delivery-empty-state p { margin: 0 0 12px; }

.notifications-delivery-table {
    width: 100%;
    border-collapse: collapse;
    background: #FFFFFF;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid #E1E5EB;
}

.notifications-delivery-table th,
.notifications-delivery-table td {
    text-align: left;
    padding: 12px 16px;
    border-bottom: 1px solid #EEF0F3;
    font-size: 14px;
    color: #1A202C;
    vertical-align: top;
}

.notifications-delivery-table th {
    font-weight: 600;
    color: #5A6779;
    background: #F7F9FB;
}

/* Bounded and wrapped: a provider failure string runs to 500 chars (the column's own cap),
   and an unbounded cell would push the Actions column off the viewport. */
.notifications-delivery-response-cell {
    max-width: 280px;
    overflow-wrap: anywhere;
    color: #5A6779;
}

.notifications-delivery-actions-cell {
    white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   SPEC-017 — Case Lookup page (Task 8). Two-tab shell (New search / Recent),
   filter form, results table, status pills. Own class namespace
   (case-lookup-*) — deliberately matching neither the record-status family
   (.status-pill-awaiting_input etc.) nor the BEM family (.status-pill--active
   etc.): CaseLookupStatusPillWireName's own doc comment notes this page owns
   the CSS and matches neither existing family on purpose.
   --------------------------------------------------------------------------- */

.case-lookup-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}

.case-lookup-header h1 {
    margin: 0;
    font-size: 24px;
    color: #1A202C;
}

/* Mirrors .notifications-tab-strip's contract (Style Guide v5 tab treatment). */
.case-lookup-tab-strip {
    display: flex;
    gap: 4px;
    background: #F5F5F5;
    border-bottom: 1px solid #DDDDDD;
    margin-bottom: 16px;
}

.case-lookup-tab {
    appearance: none;
    background: transparent;
    border: none;
    border-bottom: 3px solid transparent;
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 600;
    color: #666666;
    cursor: pointer;
}

.case-lookup-tab:hover { color: #1E3A5F; }

.case-lookup-tab:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: -2px;
}

/* Selection is carried by BOTH the fill and the left bar, not colour alone (WCAG 1.4.1 Use of
   Colour); aria-current="true" carries it to assistive tech. */
.notifications-template-rail-item--active {
    background: #EEF2F7;
    box-shadow: inset 3px 0 0 0 #1E3A5F;
    font-weight: 600;
    color: #1E3A5F;
}

/* The label half of the rail item's space-between row; the Customized badge is the other half. Kept a
   real element so the badge is pushed right by the flex layout rather than by a margin, and min-width:0
   lets a long event label shrink instead of forcing the badge out of the item. */
.notifications-template-rail-channel {
    min-width: 0;
}

.notifications-template-customized-badge {
    font-family: var(--font-accent);
    flex: none;
    padding: 2px 7px;
    border-radius: 4px;
    background: #FDF3E0;
    color: #8A5A00;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.3px;
    text-transform: uppercase;
}

.notifications-template-detail {
    flex: 1 1 420px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 20px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
}

.notifications-template-detail-header {
    display: flex;
    align-items: center;
    gap: 12px;
}

.notifications-template-detail-header h2 {
    margin: 0;
    font-size: 16px;
    color: #1A202C;
}

.notifications-template-shared-note {
    margin: 0;
    font-size: 12px;
    line-height: 18px;
    color: #5A6779;
}

.notifications-template-detail textarea,
.notifications-template-detail input[type="text"] {
    width: 100%;
    box-sizing: border-box;
    padding: 8px 10px;
    border: 1px solid #C9D2DE;
    border-radius: 4px;
    font-family: inherit;
    font-size: 14px;
    line-height: 20px;
    color: #1A202C;
    background: #FFFFFF;
}

.notifications-template-detail textarea:disabled,
.notifications-template-detail input[type="text"]:disabled {
    background: #F5F7FA;
    color: #5A6779;
}

.notifications-template-detail textarea:focus-visible,
.notifications-template-detail input[type="text"]:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: 1px;
    border-color: #1E3A5F;
}

.notifications-template-char-count {
    font-family: var(--font-accent);
    margin: 4px 0 0 0;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    color: #5A6779;
}

/* Over one segment is advisory, not an error — nothing rejects a long SMS body (the CJIS control
   on this channel is the merge-field allowlist, not a length), so this reads as a caution rather
   than borrowing the .field-error red. */
.notifications-template-char-count--over {
    color: #8A5A00;
    font-weight: 600;
}

.notifications-template-hint {
    margin: 4px 0 0 0;
    font-size: 12px;
    line-height: 18px;
    color: #5A6779;
}

.notifications-template-merge-fields ul {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 6px 0 0 0;
    padding: 0;
    list-style: none;
}

/* Matches the .form-field label treatment by hand: this label is a <span> outside a .form-field,
   so it does not inherit that rule and would otherwise read at body weight next to the two field
   labels above it. */
.notifications-template-merge-fields-label {
    font-family: var(--font-accent);
    display: block;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779;
}

/* The chip IS the insert control (AC-12), so it carries a button's affordances — hover, focus ring,
   and a disabled treatment for a caller who may view but not manage. */
.notifications-template-merge-chip {
    appearance: none;
    padding: 3px 9px;
    border: 1px solid #D5DEEA;
    border-radius: 4px;
    background: #EEF2F7;
    color: #2D3B4E;
    font-family: inherit;
    font-size: 12px;
    line-height: 16px;
    white-space: nowrap;
    cursor: pointer;
}

.notifications-template-merge-chip:hover:not(:disabled) {
    background: #E1E9F3;
    border-color: #B9C7D9;
}

.notifications-template-merge-chip:disabled {
    color: #8A95A5;
    cursor: default;
}

.notifications-template-merge-chip:focus-visible {
    outline: 2px solid #1E3A5F;
    outline-offset: 1px;
}

.notifications-template-detail-footer {
    margin-top: 4px;
}
.case-lookup-tab-active {
    color: #1E3A5F;
    border-bottom-color: #1E3A5F;
}

.case-lookup-filter-form {
    display: flex;
    flex-wrap: wrap;
    align-items: end;
    gap: 12px;
    margin-bottom: 16px;
}

.case-lookup-filter-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.case-lookup-filter-field label {
    font-size: 12px;
    font-weight: 600;
    color: #5A6779;
}

.case-lookup-filter-field input,
.case-lookup-filter-field select {
    padding: 8px 10px;
    border: 1px solid #CCCCCC;
    border-radius: 4px;
    font-size: 14px;
}

.case-lookup-rate-limit-banner {
    background: #FDF5E6;
    color: #8A6B25;
    border: 1px solid #F0DCA0;
    border-radius: 4px;
    padding: 10px 14px;
    margin-bottom: 16px;
}

.case-lookup-empty {
    color: #5A6779;
    padding: 24px 0;
}

.case-lookup-table {
    width: 100%;
    border-collapse: collapse;
}

.case-lookup-table th,
.case-lookup-table td {
    text-align: left;
    padding: 10px 12px;
    border-bottom: 1px solid #EEEEEE;
}

/* AC-7 (v1.16) / FR-19 -- a sortable heading's label starts at the same edge as its column's
   cells. The rule above pads every th and td 10px 12px; a sortable heading then nests a
   .sort-header button carrying its own padding, and the two compound (10px 12px + 10px 16px put
   the label 28px in, against 12px for the data). Neither value is wrong alone, which is why this
   shipped and survived review. The fix is the pattern .users-table already uses for the same
   button: the cell contributes nothing and the inner control owns the inset, so nesting cannot
   double-pad.

   Scoped two ways on purpose. The class (rather than a bare .case-lookup-table th) keeps the
   Recent tab's plain headings, which share this table's class and have no nested control to
   re-supply the inset. The descendant selector on .sort-header keeps the Users list, which shares
   that class and is correct at its own 10px 16px against 16px cells -- an unscoped override would
   misalign that table by 4px in the act of fixing this one. Both alternatives are recorded as
   rejected in SPEC-017 design.md.

   The zeroing selector is element-qualified (th.case-lookup-sortable-th) because the rule it
   overrides is .case-lookup-table th, at specificity 0-1-1. A bare .case-lookup-sortable-th is
   0-1-0 and silently loses, leaving the cell's own 12px in place under a control that has just
   dropped to 12px -- a 24px label against a 12px cell, which is a NEW misalignment rather than
   the old one. Caught by CaseLookupHeaderAlignmentE2ETests against this very change. */
.case-lookup-table th.case-lookup-sortable-th {
    padding: 0;
}

.case-lookup-table .case-lookup-sortable-th .sort-header {
    padding: 10px 12px;
}

.case-lookup-row:hover {
    background: #F9FAFB;
    cursor: pointer;
}

.case-lookup-row-link {
    display: block;
    color: #1E3A5F;
    text-decoration: none;
    font-weight: 600;
}

.case-lookup-row-link:hover,
.case-lookup-row-link:focus-visible {
    text-decoration: underline;
}

.case-lookup-status-pill {
    font-family: var(--font-accent);
    display: inline-block;
    padding: 4px 10px;
    border-radius: 9999px;
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    white-space: nowrap;
}

.case-lookup-status-pill-blue  { background: #E6F0FA; color: #2B6CB0; }
.case-lookup-status-pill-amber { background: #FDF5E6; color: #8A6B25; }
/* AC-9: "Released" AND "Released w/ conditions" both map here — CaseLookupStatusMapper.ToPill
   returns CaseLookupStatusPill.Green for each. Nothing about the pill separates the two, so the
   visible label is the SINGLE differentiator, and it is what satisfies WCAG 1.4.1 for this pair. */
.case-lookup-status-pill-green { background: #E6F4EF; color: #0F7B5C; }
/* AC-9: "Ready for Review" is the only status that maps here (CaseLookupStatusMapper.ToPill). It
   shares the green hue with the two Released statuses above; the outline (vs. filled background)
   plus the visible label text are its two non-color differentiators (WCAG 1.4.1). */
.case-lookup-status-pill-green-outline {
    background: #FFFFFF;
    color: #0F7B5C;
    border: 1.5px solid #0F7B5C;
}
.case-lookup-status-pill-red   { background: #FBEAEA; color: #B42318; }

/* AC-18 pager — match-count/"Showing" lines + the ellipsis-collapsed pager. .pagination/.page-btn
   are the shared Users/Roles/Delivery-Log pager treatment; only the ellipsis glyph is new here. */
.case-lookup-match-count {
    color: #1E3A5F;
    font-weight: 600;
    margin: 16px 0 4px;
}

.case-lookup-showing-count {
    color: #5A6779;
    margin: 0 0 8px;
}

/* The paired [aria-disabled] CSS the accessible-disabled house rule requires (PR #1865 review,
   Dean Kohler finding 4) — without it, the prev/next arrows at a page boundary are computed-style
   identical to a live sibling (cursor: pointer, opacity: 1) and axe has no rule that catches an
   aria-disabled control that still LOOKS operable. Mirrors the other controls that SHIP the paired CSS:
   .queue-row-select, .btn-primary, .audit-stats-strip .kpi-tile, and the three write-gate-locked
   admin links (.roles-table td a, .row-link, .user-detail-breadcrumb a).
   Phrased as neither a count nor an 'every', because this comment has now been wrong three times
   and each rewrite found the next way to be wrong: it gave two when there were three (PR #1865
   review round 2, Dean Kohler finding 6, added the missed .btn-primary); the #1387 enhanced-nav
   sweep added the three admin links, which had no paired CSS at all; and that sweep's own
   replacement text claimed 'every other aria-disabled control in the tree' while TWO still ship
   with none — AuditFilterBar's export button (.btn-secondary) and AuditHistoryTab's load-more
   (.audit-history-more). Those two are open gaps in the house rule, not exceptions to it, and are
   named here rather than silently covered by a quantifier. */
.page-btn[aria-disabled="true"],
.page-btn[aria-disabled="true"]:hover {
    cursor: not-allowed;
    opacity: 0.4;
    background: #FFFFFF;
    border-color: #E1E5EB;
    color: #5A6779;
}

.pagination-ellipsis {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    color: #5A6779;
    font-size: 13px;
}

/* ── SPEC-019 Admin / Audit Log (AC-1..AC-5) ─────────────────────────────── */

.audit-page {
    /* Wider than the 1040-1100px sibling admin pages (Users, User detail, Role detail) because
       this is the densest grid in the admin area: six columns, two of which carry free-form text
       (Actor, Target) and one a dotted event-type token. Still capped rather than full-bleed --
       an unbounded measure on an ultrawide display strands the Criticality column a screen away
       from the Timestamp it belongs to. */
    max-width: 1520px;
}

.audit-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    font-size: 13px;
    line-height: 18px;
    color: #5A6779;
}

.audit-breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-left: 6px;
    color: #A0AAB8;
}

.audit-breadcrumb li[aria-current="page"] {
    color: #1A202C;
    font-weight: 600;
}

/* AC-16 static page description, directly beneath the <h1> and above the AC-2 stats strip. */
.audit-page-description {
    margin: 0 0 16px;
    color: #5A6779;
    font-size: 14px;
    line-height: 20px;
}

.audit-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 24px;
}

.audit-header h1 {
    font-size: 22px;
    font-weight: 700;
    line-height: 30px;
    color: #1A202C;
    margin: 0;
}

/* `.audit-export-error` joins this family rather than the amber `.audit-stats-error` one: a refused
   or failed export is a refusal of a gesture the reader just made, which is `.audit-filter-error`'s
   shape, not an unrequested degradation. It carries both AC-7 notices — the bound-exceeded refusal
   and the generic failure — which differ in text, not in treatment. */
.audit-load-error,
.audit-filter-error,
.audit-export-error {
    margin: 0 0 16px;
    padding: 10px 14px;
    font-size: 14px;
    line-height: 20px;
    color: #B42318;
    background: #FBEAEA;
    border: 1px solid #F3C6C2;
    border-radius: 6px;
}

.audit-loading {
    margin: 0;
    padding: 24px 0;
    font-size: 14px;
    line-height: 20px;
    color: #5A6779;
}

/* Stats strip — three tiles (AC-2). The tiles themselves reuse the `.kpi-tile` treatment the
   Pending Decisions KPI row established, so the two summary strips in the app read as the same
   control and the `button.kpi-tile` element resets, the `.kpi-tile-active` border and the
   `.kpi-count` / `.kpi-delta` type scale are defined once. Only the grid is owned here: the KPI
   row is four columns and this strip is three, and `.kpi-tile-row`'s own 880px breakpoint drops
   to a 2x2 that would leave this strip with an orphan tile on its own row. */
.audit-stats-strip {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
    margin-bottom: 12px;
}

/* Single column below the table-readable width, not 2+1: three tiles never divide into two
   columns without orphaning one, and the tile's 28px count stays legible stacked. */
@media (max-width: 880px) {
    .audit-stats-strip {
        grid-template-columns: 1fr;
    }
}

/* All three tiles take ONE layout model, so the <button> and the two <article>s cannot align
   differently. A <button>'s content box is vertically centred by default while an <article>'s
   is top-aligned, and the grid stretches every tile to the tallest one -- which is Events today,
   the only tile carrying a third line. Left alone, the critical tile's header and count render
   ~10px below its neighbours'. Declared here rather than on `.kpi-tile` so the Pending Decisions
   row keeps exactly the rendering it has today. */
.audit-stats-strip .kpi-tile {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
}

/* The critical tile goes inert while a load is in flight (the filter bar's posture). Keyed on
   `aria-disabled`, NOT `:disabled` -- the tile must stay focusable, because activating it is what
   sets the loading flag, and a real `disabled` attribute landing mid-handler blurs the control and
   never gives focus back. See AuditStatsStrip's `Disabled` remarks. Scoped to this strip rather
   than applied to `button.kpi-tile` globally so the Pending Decisions tiles, which are never
   disabled, keep exactly the rendering they have today. */
.audit-stats-strip .kpi-tile[aria-disabled="true"] {
    cursor: not-allowed;
    opacity: 0.6;
}

/* AC-2's two disclosures in one line: the ~60-second cache lag, and that the tiles count the
   whole stream while the table below is default-suppressed (OQ-5). Muted to match
   `.audit-loading` — it is standing context, not a state change. */
.audit-stats-note {
    margin: 0 0 20px;
    font-size: 12px;
    line-height: 16px;
    color: #5A6779;
}

/* Tile counts unavailable. Amber InfoTint pairing (Style Guide v5 §1.2), NOT the red
   `.audit-load-error` treatment: the table below still rendered, so this is a partial
   degradation and dressing it as a page failure would overstate it. */
.audit-stats-error {
    margin: 0 0 20px;
    padding: 10px 14px;
    font-size: 13px;
    line-height: 20px;
    color: #8A6B25;
    background: #FDF5E6;
    border: 1px solid #E8D9B5;
    border-radius: 6px;
}

/* Filter bar — six controls plus Refresh (AC-3). */
.audit-filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 12px 16px;
    margin-bottom: 20px;
    padding: 16px;
    background: #F5F6F8;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
}

.audit-filter {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.audit-filter label {
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779;
}

.audit-filter input,
.audit-filter select {
    padding: 8px 12px;
    font-size: 14px;
    line-height: 20px;
    color: #1A202C;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 6px;
    font-family: inherit;
    box-sizing: border-box;
}

.audit-filter input[type="search"] {
    /* Sized on the WIDTH axis explicitly, never with flex-basis. The parent .audit-filter is
       flex-direction: column, so a `flex: 1 1 200px` here sets the child's HEIGHT basis, not its
       width -- which rendered both search boxes ~200px tall and stretched the whole filter row. */
    width: 200px;
    max-width: 100%;
}

.audit-filter select[multiple] {
    min-width: 240px;
    padding: 4px;
}

.audit-filter input:focus-visible,
.audit-filter select:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
    border-color: #1E3A5F;
}

/* RETIRED (issue #1387). This surface used to carry its own `.btn-secondary:disabled` override
   because the base class shipped none, and on this page the disabled state IS the last-page
   signal. `.btn-secondary:disabled` now exists globally with these exact values, so the scoped
   copy was redundant -- and a redundant override is the kind that drifts from the rule it
   duplicates. The Previous/Next affordance is unchanged: same four declarations, applied by the
   global rule instead. Its note that "six other components disable a .btn-secondary and restyling
   them all is not this PR's business" was correct at the time; #1387 is the change that took that
   business on, after a manual walkthrough hit the same defect on Case Lookup's Export CSV. */

.audit-filter input:disabled,
.audit-filter select:disabled {
    background: #EEF0F3;
    color: #8A93A3;
    cursor: not-allowed;
}

.audit-filter-hint {
    margin: 2px 0 0;
    max-width: 260px;
    font-size: 11px;
    line-height: 16px;
    color: #5A6779;
}

.audit-filter-hint code {
    font-size: 11px;
    color: #1A202C;
}

.audit-filter-actions {
    /* Top-aligned and pushed down by exactly one label row, so Refresh's top edge lands level
       with the inputs' rather than with the bottom of the tallest column (the event-type
       multi-select plus its hint). 20px = the label's 16px line-height + .audit-filter's 4px gap. */
    align-self: flex-start;
    margin-top: 20px;
    /* Flex row so Refresh and the AC-7 Export CSV button sit side by side with a real gap. Two
       inline-block buttons would otherwise be separated only by collapsed markup whitespace.
       flex-direction is REQUIRED here and is not redundant: this element also carries
       .audit-filter, which sets flex-direction: column to stack a label above its control. That
       declaration still applies to this element, so `display: flex` alone leaves the two buttons
       stacked vertically -- which is what shipped until the browser walkthrough caught it. */
    display: flex;
    flex-direction: row;
    gap: 8px;
}

/* Events table (AC-4). */
.audit-table-wrap {
    overflow-x: auto;
}

.audit-table {
    width: 100%;
    border-collapse: collapse;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
    overflow: hidden;
}

.audit-table thead tr {
    background: #F5F6F8;
}

.audit-table th {
    padding: 10px 16px;
    text-align: left;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779;
    border-bottom: 1px solid #E1E5EB;
    white-space: nowrap;
}

.audit-table td {
    padding: 10px 16px;
    font-size: 14px;
    line-height: 20px;
    color: #1A202C;
    border-bottom: 1px solid #EEF0F3;
    vertical-align: middle;
}

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

.audit-row.critical {
    background: #FCFDFC;
}

.audit-table-empty {
    padding: 32px 16px;
    text-align: center;
    color: #5A6779;
}

/* The row primary action. A real <button> restyled to read as the timestamp cell, so the row is
   activatable by native semantics with no implicit-role override (see AuditEventTable header). */
.audit-row-activate {
    padding: 0;
    font-family: inherit;
    font-size: 14px;
    line-height: 20px;
    color: #1E3A5F;
    font-weight: 600;
    background: none;
    border: none;
    cursor: pointer;
    text-align: left;
    white-space: nowrap;
}

.audit-row-activate:hover:not(:disabled) {
    text-decoration: underline;
}

.audit-row-activate:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
    border-radius: 4px;
}

.audit-row-activate:disabled {
    color: #8A93A3;
    cursor: not-allowed;
}

/* Surface chip — an activatable filter control on every row (AC-4). */
.audit-surface-chip {
    display: inline-block;
    padding: 3px 10px;
    font-family: inherit;
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
    color: #2B6CB0;
    background: #E6F0FA;
    border: 1px solid transparent;
    border-radius: 9999px;
    cursor: pointer;
    white-space: nowrap;
}

.audit-surface-chip:hover:not(:disabled) {
    border-color: #2B6CB0;
}

.audit-surface-chip:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(30, 58, 95, 0.18);
    border-color: #1E3A5F;
}

.audit-surface-chip:disabled {
    color: #8A93A3;
    background: #EEF0F3;
    cursor: not-allowed;
}

.audit-surface-unclassified {
    font-size: 12px;
    line-height: 16px;
    color: #8A93A3;
    font-style: italic;
}

.audit-event-type {
    font-size: 12px;
    line-height: 16px;
    color: #1A202C;
}

/* CRITICAL pill (AC-5). Green, not red, per master 12.4 / Figure 12.1: it marks importance, not
   failure. Failed actions surface in the stats strip, never as a pill. Reuses the house green
   pair (#E6F4EF / #0F7B5C) the status pills already use. */
.audit-critical-pill {
    display: inline-block;
    padding: 4px 10px;
    border-radius: 9999px;
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    white-space: nowrap;
    background: #E6F4EF;
    color: #0F7B5C;
}

/* Keyset paging — next/previous, no page numbers (OQ-D2). */
.audit-paging-count {
    margin: 0 0 0 4px;
    font-size: 13px;
    line-height: 20px;
    color: #5A6779;
}

.audit-paging {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
}

/* ── SPEC-019 AC-6: the shared audit event detail panel ─────────────────────────────────────────
   A PANEL, NOT A MODAL (FR-6: "not a modal — the table stays visible"), so the layout is a flex ROW
   with the table beside it rather than an overlay above it.

   The basis units below are WIDTHS because .audit-results is flex-direction: row. Stated explicitly
   because the reverse bit this surface once already: PR #1617's first walkthrough finding was
   `flex: 1 1 200px` on a child of a flex-direction: COLUMN parent, where the basis is a HEIGHT — it
   rendered both audit search inputs 200px tall. Check the parent's direction before reading a
   basis. */
.audit-results {
    display: flex;
    align-items: flex-start;
    gap: 16px;
}

/* The table component renders TWO root elements — .audit-table-wrap and the .audit-paging nav — so
   it needs this wrapper to be one flex child. Without it the paging controls become a third column
   beside the table. min-width: 0 is load-bearing: a flex item's default min-width: auto refuses to
   shrink below its content, which would defeat .audit-table-wrap's own overflow-x: auto and push the
   page into a horizontal scroll instead of scrolling the table. */
.audit-results-main {
    flex: 1 1 auto;
    min-width: 0;
}

.audit-detail-panel {
    flex: 0 0 380px;
    align-self: stretch;
    position: sticky;
    top: 16px;
    max-height: calc(100vh - 32px);
    overflow-y: auto;
    padding: 16px;
    background: #FFFFFF;
    border: 1px solid #E1E5EB;
    border-radius: 8px;
}

/* The container is the focus target on open (tabindex="-1"), so the ring has to be visible on it:
   a focus placement the reader cannot see is not a focus placement (WCAG 2.4.7). */
.audit-detail-panel:focus-visible {
    outline: 2px solid #1F6FEB;
    outline-offset: 2px;
}

.audit-detail-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 12px;
    border-bottom: 1px solid #E1E5EB;
}

.audit-detail-header h2 {
    margin: 0;
    flex: 1 1 auto;
    min-width: 0;
    font-size: 14px;
    line-height: 20px;
    font-weight: 600;
    /* The title is the stored event type in a code span; a long one wraps rather than pushing the
       Close button off the panel. */
    overflow-wrap: anywhere;
}

.audit-detail-close {
    flex: 0 0 auto;
    padding: 4px 10px;
    font-family: inherit;
    font-size: 13px;
    line-height: 20px;
    color: #1A202C;
    background: #FFFFFF;
    border: 1px solid #C7CDD8;
    border-radius: 6px;
    cursor: pointer;
}

.audit-detail-close:hover {
    background: #F5F6F8;
}

.audit-detail-close:focus-visible {
    outline: 2px solid #1F6FEB;
    outline-offset: 2px;
}

.audit-detail-loading,
.audit-detail-empty {
    margin: 12px 0 0;
    font-size: 13px;
    line-height: 20px;
    color: #5A6779;
}

.audit-detail-error {
    margin: 12px 0 0;
    padding: 8px 12px;
    font-size: 13px;
    line-height: 20px;
    color: #8C2C2C;
    background: #FCEDED;
    border: 1px solid #F2C7C7;
    border-radius: 6px;
}

/* Two columns: the stored key, then its value. A definition list rather than a table because these
   are name/value pairs and not tabular data — the native semantics already say "term, description"
   to a screen reader with no ARIA (WCAG 1.3.1). */
.audit-detail-summary {
    display: grid;
    grid-template-columns: minmax(0, 8rem) minmax(0, 1fr);
    gap: 4px 12px;
    margin: 12px 0 0;
}

.audit-detail-summary dt {
    font-size: 11px;
    font-weight: 600;
    line-height: 20px;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    color: #5A6779;
    overflow-wrap: anywhere;
}

.audit-detail-summary dd {
    margin: 0;
    font-size: 13px;
    line-height: 20px;
    color: #1A202C;
    /* A payload value can be a long opaque string (a user agent, a GUID); it wraps inside its column
       rather than widening the panel. */
    overflow-wrap: anywhere;
}

.audit-detail-section {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid #EEF0F3;
}

.audit-detail-section h3 {
    margin: 0;
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779;
}

/* Before/after diff for an edit event (AC-6). */
.audit-diff-table {
    width: 100%;
    margin-top: 8px;
    border-collapse: collapse;
}

.audit-diff-table th,
.audit-diff-table td {
    padding: 6px 8px;
    font-size: 13px;
    line-height: 20px;
    text-align: left;
    vertical-align: top;
    border-bottom: 1px solid #EEF0F3;
    overflow-wrap: anywhere;
}

.audit-diff-table thead th {
    font-size: 11px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #5A6779;
}

.audit-diff-table tbody th {
    font-weight: 400;
    color: #5A6779;
}

.audit-diff-table tbody td {
    color: #1A202C;
}

.audit-detail-content-key {
    margin: 8px 0 4px;
    font-size: 12px;
    line-height: 16px;
    color: #5A6779;
}

/* Person-authored free text, rendered as a block. pre-wrap so the author's own line breaks survive
   — this is a forensic record of what someone wrote, and collapsing its whitespace would render a
   different text than was stored. */
.audit-detail-content {
    margin: 0;
    padding: 8px 10px;
    font-size: 13px;
    line-height: 20px;
    color: #1A202C;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    background: #F9FAFB;
    border: 1px solid #EEF0F3;
    border-radius: 6px;
}

/* A withheld value. The MARKER TEXT is the contract — Task 23's CJIS line requires a redaction to
   render as an explicit marker and never as a blank that reads as "no data" — and this styling is
   reinforcement on top of it, never the signal itself. Muted italic, matching
   .audit-surface-unclassified, so a redaction is visibly not a stored value; it is deliberately not
   a warning colour, because a withholding is the system working correctly rather than an error. */
.audit-payload-value.redacted,
.audit-detail-content.redacted {
    color: #8A93A3;
    font-style: italic;
}

/* Below this width the panel would squeeze the six-column table into unreadable columns, so it
   stacks under the table instead. Column direction here, which is why the panel's basis switches to
   auto — a width basis in a column parent is a HEIGHT (see the note at the top of this block). */
@media (max-width: 1100px) {
    .audit-results {
        flex-direction: column;
    }

    .audit-detail-panel {
        flex: 1 1 auto;
        width: 100%;
        position: static;
        max-height: none;
    }
}

/* ── SPEC-019 AC-9 / AC-10: the Audit History tab on Defendant Details ──────────────────────────
   A plain chronological list, not the admin table: this surface has no filter bar (AC-10, "the
   scope is implicit"), so there is no surface chip to place and no column a reader would sort or
   filter by. The row is one <button> laying its four values out in a grid, which keeps ONE
   activatable control per row — the admin table needs two only because its surface chip is a second
   action, and a second control here would have nothing to do.

   .audit-history-results reuses .audit-results' flex-row arrangement so the shared detail panel
   docks the same way on both surfaces; the panel's own rules (flex basis, sticky, the 1100px column
   fallback) are declared once in the AC-6 block above and are not repeated here. */
.audit-history-tab {
    padding: 16px 0;
}

.audit-history-scope {
    margin: 4px 0 16px;
    font-size: 13px;
    line-height: 20px;
    color: #5A6779;
}

.audit-history-loading,
.audit-history-empty {
    padding: 32px 16px;
    text-align: center;
    color: #5A6779;
}

.audit-history-error {
    margin: 0 0 16px;
    padding: 12px 16px;
    border-radius: 6px;
    background: #FDECEC;
    color: #9B1C1C;
    font-size: 14px;
    line-height: 20px;
}

.audit-history-results {
    display: flex;
    align-items: flex-start;
    gap: 16px;
}

/* min-width: 0 is load-bearing for the same reason it is on .audit-results-main: a flex item's
   default min-width: auto refuses to shrink below its content, which would push the page into a
   horizontal scroll rather than letting a long event type wrap. */
.audit-history-main {
    flex: 1 1 auto;
    min-width: 0;
}

.audit-history-list {
    margin: 0;
    padding: 0;
    list-style: none;
    border-top: 1px solid #E1E5EB;
}

.audit-history-item {
    border-bottom: 1px solid #E1E5EB;
}

.audit-history-item.critical {
    background: #FCFDFC;
}

/* The row primary action, restyled to read as a list row. A real <button>, so activation is native
   (WCAG 2.1.1) with no implicit-role override — the same decision the admin table records. */
.audit-history-activate {
    display: grid;
    /* FIVE columns, not four: a critical row renders a fifth child (the CRITICAL pill) and a
       non-critical row renders four. With only four tracks the pill auto-places into an implicit
       SECOND row and the timestamp column pushes it under the date — found in the walkthrough, not
       by a lint. The fifth track collapses to zero width on the rows that omit the pill, so every
       row still aligns on the first four. */
    grid-template-columns: minmax(0, auto) minmax(0, 1fr) minmax(0, auto) minmax(0, auto) minmax(0, auto);
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 10px 8px;
    font-family: inherit;
    font-size: 14px;
    line-height: 20px;
    color: #1A202C;
    text-align: left;
    background: none;
    border: none;
    cursor: pointer;
}

.audit-history-activate:hover {
    background: #F5F7FA;
}

.audit-history-activate:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 3px rgba(30, 58, 95, 0.18);
}

.audit-history-timestamp {
    color: #1E3A5F;
    font-weight: 600;
    white-space: nowrap;
}

.audit-history-surface,
.audit-history-actor {
    font-size: 13px;
    line-height: 20px;
    color: #5A6779;
    white-space: nowrap;
}

.audit-history-more {
    margin-top: 16px;
}

.audit-history-count {
    margin: 8px 0 0;
    font-size: 13px;
    line-height: 20px;
    color: #5A6779;
}

/* Below this width the four-value row and the docked panel both stop fitting. The panel's own
   column-direction fallback is declared in the AC-6 block; this adds the row's, which drops the
   fixed columns so the values stack rather than crushing the event type to nothing. */
@media (max-width: 1100px) {
    .audit-history-results {
        flex-direction: column;
    }

    .audit-history-activate {
        grid-template-columns: 1fr;
        gap: 4px;
    }

    .audit-history-timestamp,
    .audit-history-surface,
    .audit-history-actor {
        white-space: normal;
    }
}

/* ── SPEC-019 AC-6: payload keys stack above their values ───────────────────────────────────────
   The summary block above this one has short fixed keys (TIMESTAMP, ACTOR, ROLE AT EVENT TIME) and
   reads well as two columns. Payload keys do not: they are event-authored snake_case, and the
   longest in AuditPayloadClassification is `inactivity_timeout_minutes_applied` at 34 characters —
   roughly 250px at this type size, inside a 348px content box. Two columns cannot fit that, and the
   dt's `overflow-wrap: anywhere` then breaks it MID-WORD (`DECISION_OPTION_LAB` / `EL`), which is
   what the Task 24b walkthrough caught on the Audit History tab and which reproduces identically on
   the admin Audit Log page.

   Widening the shared column was rejected: it would leave under 90px for the value and would still
   break on the 34-character key. Stacking is length-independent — it is correct for every key the
   classification holds today and for any a future event adds. */
.audit-detail-payload {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
}

.audit-detail-payload dt {
    margin-top: 10px;
    /* Back to the default: with a full-width track there is nothing to break against, so the
       anywhere-break that caused the mid-word split is no longer needed as an overflow guard. */
    overflow-wrap: normal;
}

.audit-detail-payload dt:first-of-type {
    margin-top: 0;
}

/* ============================================================================
   SPEC-024 — Branding admin page (/admin/branding)
   ============================================================================ */

/* Breadcrumb. Structure and rule shapes mirror .notes-admin-breadcrumb (SPEC-015 AC-28), including
   the "/" separator per Style Guide v5 §2.5. The separator is generated content on the <li>, so it
   stays decorative and never enters the crumb's accessible name.

   Kept as its own block rather than folded into a shared selector list: AdminBreadcrumb's CssClass
   parameter exists precisely because app.css keeps one block per page (spacing needs differ), and
   every sibling page follows that. */
.branding-admin-breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    font-size: 13px;
    line-height: 18px;
    color: #5A6779;
}

.branding-admin-breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-left: 6px;
    color: #A0AAB8;
}

.branding-admin-breadcrumb li[aria-current="page"] {
    color: #1A202C;
    font-weight: 600;
}

/* The page description under the <h1>. Sits outside the load-state conditionals in the markup, so
   it is styled here rather than in any state-specific block.

   NOTE: .branding-admin-page deliberately carries NO max-width, matching .notes-admin-page — the
   cards size themselves within the full-width admin content area. */
.branding-admin-page-description {
    margin: 4px 0 24px;
    color: #5A6779;
    font-size: 14px;
    line-height: 20px;
}

/* FR-3 Loading state. */
.branding-admin-loading {
    padding: 24px 0;
    color: #5A6779;
    font-size: 14px;
}

/* FR-3 Load-failed state — the banner plus its Retry button, stacked. */
.branding-admin-load-error {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    padding: 16px 0 24px;
}

/* One card per field group (identity / hero / callouts / seal). */
.branding-admin-card {
    border: 1px solid #E2E6EC;
    border-radius: 6px;
    padding: 20px;
    margin-bottom: 20px;
    background: #FFFFFF;
}

.branding-admin-card h2 {
    margin: 0 0 16px;
    font-size: 16px;
    line-height: 22px;
    color: #1A202C;
}

/* Seal card. Tokens mirror SPEC-009's .signature-seal-* rules (above) token-for-token, per
   spec.md's own UI/UX Notes: "Seal area empty/filled states... mirror SPEC-009's Signature &
   seal card pattern for visual and copy consistency across the two upload surfaces." */
.branding-admin-seal-preview {
    display: block;
    max-width: 120px;
    height: auto;
    margin-bottom: 12px;
}

.branding-admin-seal-meta,
.branding-admin-seal-pending-meta {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 4px 12px;
    margin: 0;
    font-size: 13px;
    line-height: 18px;
}

.branding-admin-seal-meta dt,
.branding-admin-seal-pending-meta dt {
    color: #5A6779;
}

.branding-admin-seal-meta dd,
.branding-admin-seal-pending-meta dd {
    margin: 0;
    color: #1A202C;
}

.branding-admin-seal-empty {
    margin: 0;
    color: #5A6779;
    font-size: 14px;
    line-height: 20px;
}

.branding-admin-seal-error {
    padding: 8px 12px;
    margin: 0 0 12px;
    background: #FCEBEA;
    color: #8A1A12;
    border-radius: 6px;
    font-size: 13px;
}

.branding-admin-seal-actions {
    display: flex;
    gap: 10px;
    margin-top: 12px;
}

.branding-admin-seal-replace-label {
    position: relative;
    display: inline-flex;
    align-items: center;
    height: 36px;
    padding: 0 14px;
    border: 1px solid #CBD2DC;
    border-radius: 6px;
    background: #FFFFFF;
    font-size: 14px;
    color: #1A202C;
    cursor: pointer;
}

.branding-admin-seal-replace-label:hover {
    background: #F7F9FB;
}

/* WCAG 2.4.7 (Focus Visible) — the file input underneath is opacity:0, so :focus lands on an
   invisible element with nothing visible to a keyboard user. Renders the ring on the visible
   label instead, matching .signature-seal-replace-label's precedent. */
.branding-admin-seal-replace-label:has(input:focus-visible) {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}

.branding-admin-seal-dropzone {
    position: relative;
    padding: 20px;
    text-align: center;
    border: 2px dashed #C3CAD6;
    border-radius: 8px;
    background: #FAFBFC;
}

.branding-admin-seal-dropzone:has(.branding-admin-seal-dropzone-input:hover) {
    border-color: #2B6CB0;
    background: #F4F8FC;
}

/* WCAG 2.4.7 (Focus Visible) — same rationale as .branding-admin-seal-replace-label above. */
.branding-admin-seal-dropzone:has(.branding-admin-seal-dropzone-input:focus-visible) {
    outline: 3px solid #1E3A5F;
    outline-offset: 2px;
}

.branding-admin-seal-dropzone-copy {
    margin: 0 0 4px;
    font-size: 14px;
    color: #1A202C;
}

.branding-admin-seal-upload-cta {
    color: #1E3A5F;
    font-weight: 600;
    text-decoration: underline;
}

.branding-admin-seal-hint {
    margin: 0;
    font-size: 12px;
    color: #5A6779;
}

/* The actual <input type="file"> InputFile renders is stretched invisibly over the whole
   dropzone/replace-label so both click-to-browse and native OS drag-and-drop onto the element
   fire the same InputFile OnChange handler (AC-4) — mirrors .signature-seal-dropzone-input. */
.branding-admin-seal-dropzone-input,
.branding-admin-seal-hidden-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

/* AC-3's in-flight submission — a first-ever upload (no served seal yet) or a replacement of an
   already-served one; either way there is no preview to show for the submitted bytes, which sit
   in quarantine (design.md OQ-D13). Vertical stack, mirrors .signature-seal-row-pending. */
.branding-admin-seal-pending {
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: flex-start;
    margin-top: 12px;
}

.branding-admin-seal-pending-note {
    margin: 0;
    font-size: 13px;
    color: #8A6B25;
    background: #FDF5E6;
    border-radius: 6px;
    padding: 6px 10px;
}

/* AC-3's adverse-outcome notice (issue #2344) — one generic alert for all four terminal scan
   states, mirrors .branding-admin-seal-error's palette (this is also a failure state) but keeps
   its own class so the two can't be confused: -error is a synchronous validation rejection,
   -rejected is an async scan-verdict outcome arriving after the fact. */
.branding-admin-seal-rejected {
    margin-top: 12px;
}

.branding-admin-seal-rejected-note {
    margin: 0;
    padding: 8px 12px;
    background: #FCEBEA;
    color: #8A1A12;
    border-radius: 6px;
    font-size: 13px;
}

/* Live character counter (AC-14). The over-limit variant is a colour AND a weight change, not colour
   alone — colour is not the only carrier of the state (WCAG 2.1 SC 1.4.1 Use of Color, Level A), and
   the paired role=alert message carries it in text besides. */
.branding-field-counter {
    display: block;
    margin-top: 4px;
    color: #5A6779;
    font-size: 12px;
    line-height: 16px;
}

.branding-field-counter-over {
    color: #B3261E;
    font-weight: 600;
}

/* Role Description counter (SPEC-004 AC-18). Always in the DOM so its live region can announce; an empty
   block has no height, so it takes no space until it has text. It is deliberately NOT display:none while
   empty: a live region that leaves the accessibility tree is not reliably announced when text returns.
   #595F6B on white is ~6.4:1 (WCAG 1.4.3 AA), the same value the other form counters use. The limit-reached variant changes weight as well as colour, and its text
   says "0 characters remaining", so colour is not the only carrier (WCAG 2.1 SC 1.4.1). */
.role-description-counter {
    display: block;
    font-size: 12px;
    line-height: 16px;
    color: #595F6B;
    font-variant-numeric: tabular-nums;
}

.role-description-counter-limit {
    color: #B3261E;
    font-weight: 600;
}

.branding-admin-actions {
    display: flex;
    gap: 12px;
    padding-top: 4px;
}
