/* =============================================================================
   PMS — design system
   -----------------------------------------------------------------------------
   Hand-written, dependency-free CSS. No framework and no CDN, deliberately:
     - A strict Content-Security-Policy with no third-party origins is only
       possible if nothing is fetched from one.
     - PHI-handling software should not load styling from an external host that
       could be compromised or that logs referrers.
     - A licensed on-premise install must work with no build step and no network.

   Theming: the two brand colors are injected per tenant as --brand-* custom
   properties by the layout (inside a nonce'd <style>), so re-skinning for a new
   clinic is a settings change, not a stylesheet edit.

   Dark mode is a selected set of values, not an inversion: each token has its own
   dark step chosen against the dark surface.
   ========================================================================== */

/* ---------------------------------------------------------------- tokens ---- */

:root {
    color-scheme: light;

    /* Brand defaults. The layout overrides --brand-primary / --brand-accent from
       tenant settings; everything else derives from them. */
    --brand-primary: #2563eb;
    --brand-accent: #0d9488;

    /* Surfaces */
    --page: #f7f8fa;
    --surface: #ffffff;
    --surface-2: #f2f4f7;
    --surface-3: #e8ebef;
    --surface-inverse: #12151b;

    /* Ink */
    --ink: #10141b;
    --ink-secondary: #4a5261;
    --ink-muted: #6f7887;
    --ink-inverse: #ffffff;

    /* Lines */
    --line: #dfe3e9;
    --line-strong: #c6ccd6;
    --focus-ring: color-mix(in oklab, var(--brand-primary) 55%, white);

    /* Status — fixed, never themed. ALWAYS paired with an icon and a text label:
       red/green are indistinguishable under deuteranopia (measured ΔE 4.1), so
       color alone can never be the channel. */
    --status-good: #0ca30c;
    --status-good-bg: #e8f7e8;
    --status-warning: #b06f00;
    --status-warning-mark: #fab219;
    --status-warning-bg: #fdf4e3;
    --status-critical: #d03b3b;
    --status-critical-bg: #fdecec;
    --status-info: #2563eb;
    --status-info-bg: #eaf1fe;

    /* Chart data marks. A fixed, validated blue — deliberately NOT the tenant's
       brand color: an arbitrary admin-chosen hex cannot be checked for
       lightness band, chroma and CVD separation, and data encoding is the one
       place where "on brand" must lose to "readable". Branding drives chrome. */
    --viz-series: #2a78d6;
    --viz-ordinal-1: #86b6ef;
    --viz-ordinal-2: #3987e5;
    --viz-ordinal-3: #256abf;
    --viz-ordinal-4: #0d366b;
    --viz-grid: #e6e9ee;
    --viz-axis: #c6ccd6;
    --viz-track: #eef1f5;

    /* Shape & depth */
    --radius-sm: 6px;
    --radius: 10px;
    --radius-lg: 14px;
    --shadow-sm: 0 1px 2px rgba(16, 20, 27, 0.06);
    --shadow: 0 1px 3px rgba(16, 20, 27, 0.08), 0 4px 12px rgba(16, 20, 27, 0.05);
    --shadow-lg: 0 8px 32px rgba(16, 20, 27, 0.14);

    /* Type */
    --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

    --sidebar-w: 244px;
    --topbar-h: 56px;
}

/* Dark mode: OS preference, unless the user has explicitly chosen light. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;

        --page: #0d0f13;
        --surface: #171a1f;
        --surface-2: #1f232a;
        --surface-3: #272c34;
        --surface-inverse: #f2f4f7;

        --ink: #f4f6f8;
        --ink-secondary: #b3bcc9;
        --ink-muted: #8b95a3;
        --ink-inverse: #10141b;

        --line: #2b3038;
        --line-strong: #3a4149;

        --status-good: #4ec44e;
        --status-good-bg: #14261a;
        --status-warning: #f0b429;
        --status-warning-mark: #fab219;
        --status-warning-bg: #2a2113;
        --status-critical: #f07171;
        --status-critical-bg: #2c1719;
        --status-info: #6da7ec;
        --status-info-bg: #16202f;

        --viz-series: #3987e5;
        --viz-ordinal-1: #184f95;
        --viz-ordinal-2: #2a78d6;
        --viz-ordinal-3: #5598e7;
        --viz-ordinal-4: #9ec5f4;
        --viz-grid: #262b33;
        --viz-axis: #3a4149;
        --viz-track: #232830;

        --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
        --shadow: 0 1px 3px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.35);
        --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.6);
    }
}

/* Explicit dark choice must win over an OS light preference. */
:root[data-theme="dark"] {
    color-scheme: dark;

    --page: #0d0f13;
    --surface: #171a1f;
    --surface-2: #1f232a;
    --surface-3: #272c34;
    --surface-inverse: #f2f4f7;

    --ink: #f4f6f8;
    --ink-secondary: #b3bcc9;
    --ink-muted: #8b95a3;
    --ink-inverse: #10141b;

    --line: #2b3038;
    --line-strong: #3a4149;

    --status-good: #4ec44e;
    --status-good-bg: #14261a;
    --status-warning: #f0b429;
    --status-warning-mark: #fab219;
    --status-warning-bg: #2a2113;
    --status-critical: #f07171;
    --status-critical-bg: #2c1719;
    --status-info: #6da7ec;
    --status-info-bg: #16202f;

    --viz-series: #3987e5;
    --viz-ordinal-1: #184f95;
    --viz-ordinal-2: #2a78d6;
    --viz-ordinal-3: #5598e7;
    --viz-ordinal-4: #9ec5f4;
    --viz-grid: #262b33;
    --viz-axis: #3a4149;
    --viz-track: #232830;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow: 0 1px 3px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.35);
    --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.6);
}

/* ----------------------------------------------------------------- reset ---- */

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

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    font-family: var(--font);
    font-size: 15px;
    line-height: 1.55;
    color: var(--ink);
    background: var(--page);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.3; letter-spacing: -0.011em; }
h1 { font-size: 1.4rem; }
h2 { font-size: 1.125rem; }
h3 { font-size: 1rem; }
h4 { font-size: 0.875rem; }
p { margin: 0 0 0.75rem; }
p:last-child { margin-bottom: 0; }

a { color: var(--brand-primary); text-decoration: none; }
a:hover { text-decoration: underline; }

hr { border: 0; border-top: 1px solid var(--line); margin: 1.25rem 0; }

code, pre, .mono { font-family: var(--font-mono); font-size: 0.85em; }

/* Visible focus for keyboard users, suppressed for mouse clicks. */
:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

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

.skip-link {
    position: absolute; left: 0.5rem; top: -3rem; z-index: 100;
    background: var(--surface); color: var(--ink);
    padding: 0.5rem 0.875rem; border-radius: var(--radius);
    box-shadow: var(--shadow); transition: top 0.15s;
}
.skip-link:focus { top: 0.5rem; }

/* ----------------------------------------------------------------- shell ---- */

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

.sidebar {
    width: var(--sidebar-w);
    flex: 0 0 var(--sidebar-w);
    background: var(--surface-inverse);
    color: rgba(255, 255, 255, 0.72);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

/* A clinic that prefers a light chrome sets brand.sidebar_style = light. */
.sidebar[data-style="light"] {
    background: var(--surface);
    color: var(--ink-secondary);
    border-right: 1px solid var(--line);
}

.sidebar__brand {
    display: flex; align-items: center; gap: 0.625rem;
    padding: 1rem 1rem 0.875rem;
    font-weight: 600; font-size: 0.95rem;
    color: #fff;
    min-height: var(--topbar-h);
}
.sidebar[data-style="light"] .sidebar__brand { color: var(--ink); }

.sidebar__mark {
    width: 30px; height: 30px; flex: 0 0 30px;
    border-radius: 8px;
    background: var(--brand-primary);
    color: #fff;
    display: grid; place-items: center;
    font-size: 0.8rem; font-weight: 700; letter-spacing: -0.02em;
}
.sidebar__mark img { width: 100%; height: 100%; object-fit: contain; border-radius: 8px; }

.sidebar__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.nav { padding: 0.5rem 0.5rem 1rem; display: flex; flex-direction: column; gap: 1px; }

.nav__heading {
    font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.07em;
    color: rgba(255, 255, 255, 0.38);
    padding: 1rem 0.625rem 0.375rem;
    font-weight: 600;
}
.sidebar[data-style="light"] .nav__heading { color: var(--ink-muted); }

.nav__link {
    display: flex; align-items: center; gap: 0.625rem;
    padding: 0.5rem 0.625rem;
    border-radius: var(--radius-sm);
    color: inherit;
    font-size: 0.875rem;
    font-weight: 500;
}
.nav__link:hover { background: rgba(255, 255, 255, 0.07); text-decoration: none; color: #fff; }
.sidebar[data-style="light"] .nav__link:hover { background: var(--surface-2); color: var(--ink); }

.nav__link[aria-current="page"] {
    background: rgba(255, 255, 255, 0.11);
    color: #fff;
    font-weight: 600;
}
.sidebar[data-style="light"] .nav__link[aria-current="page"] {
    background: color-mix(in oklab, var(--brand-primary) 12%, transparent);
    color: var(--brand-primary);
}

.nav__link svg { flex: 0 0 17px; width: 17px; height: 17px; opacity: 0.85; }

.nav__badge {
    margin-left: auto;
    background: var(--brand-primary); color: #fff;
    font-size: 0.6875rem; font-weight: 700;
    min-width: 19px; height: 19px; padding: 0 5px;
    border-radius: 999px;
    display: grid; place-items: center;
}

.sidebar__footer {
    margin-top: auto;
    padding: 0.75rem;
    border-top: 1px solid rgba(255, 255, 255, 0.09);
    font-size: 0.75rem;
    color: rgba(255, 255, 255, 0.45);
}
.sidebar[data-style="light"] .sidebar__footer { border-color: var(--line); color: var(--ink-muted); }

.main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

.topbar {
    height: var(--topbar-h);
    display: flex; align-items: center; gap: 0.75rem;
    padding: 0 1rem;
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    position: sticky; top: 0; z-index: 20;
}

.topbar__title { font-size: 0.95rem; font-weight: 600; }
.topbar__spacer { flex: 1 1 auto; }
/* Wide enough for a name and an MRN, never wide enough to crowd the account
   controls beside it. */
.topbar__search { min-width: 150px; max-width: 230px; }

.menu-toggle {
    display: none;
    background: none; border: 0; padding: 0.375rem;
    color: var(--ink); cursor: pointer; border-radius: var(--radius-sm);
}
.menu-toggle:hover { background: var(--surface-2); }

.content { padding: 1.25rem; max-width: 1500px; width: 100%; }

.page-head {
    display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.75rem;
    margin-bottom: 1.25rem;
}
.page-head__text { flex: 1 1 320px; min-width: 0; }
.page-head__sub { color: var(--ink-secondary); font-size: 0.875rem; margin-top: 0.25rem; }
.page-head__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* --------------------------------------------------------------- buttons ---- */

.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
    padding: 0.5rem 0.875rem;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--ink);
    font: inherit; font-size: 0.875rem; font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    text-decoration: none;
    transition: background 0.12s, border-color 0.12s;
}
.btn:hover { background: var(--surface-2); text-decoration: none; }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }
.btn svg { width: 15px; height: 15px; }

.btn--primary {
    background: var(--brand-primary);
    border-color: var(--brand-primary);
    color: #fff;
}
.btn--primary:hover { background: color-mix(in oklab, var(--brand-primary) 88%, black); }

.btn--danger { background: var(--status-critical); border-color: var(--status-critical); color: #fff; }
.btn--danger:hover { background: color-mix(in oklab, var(--status-critical) 88%, black); }

.btn--ghost { background: transparent; border-color: transparent; }
.btn--ghost:hover { background: var(--surface-2); }

.btn--sm { padding: 0.3rem 0.55rem; font-size: 0.8125rem; }
.btn--block { width: 100%; }

.btn-group { display: inline-flex; gap: 0.375rem; flex-wrap: wrap; }

/* ----------------------------------------------------------------- cards ---- */

.card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}
.card + .card { margin-top: 1rem; }

.card__head {
    display: flex; align-items: center; gap: 0.625rem; flex-wrap: wrap;
    padding: 0.875rem 1rem;
    border-bottom: 1px solid var(--line);
}
.card__head h2, .card__head h3 { font-size: 0.9375rem; }
/* Direct child only: a button nested in a form or a span is not the thing being
   aligned — that wrapper takes .push instead, and two elements both claiming the
   free space is how a head ends up looking crooked. */
.card__head > .btn { margin-left: auto; }
.card__body { padding: 1rem; }
.card__body--flush { padding: 0; }
/* Two bodies in one card — a summary above, a table or a form below. */
.card__body--divided { border-bottom: 1px solid var(--line); }
.card__foot {
    padding: 0.75rem 1rem;
    border-top: 1px solid var(--line);
    background: var(--surface-2);
    border-radius: 0 0 var(--radius) var(--radius);
    font-size: 0.875rem;
}

/* A card whose whole subject is destructive or resolved. The border is a second
   signal only — the heading and its status chip still say which it is. */
.card--danger { border-color: var(--status-critical); }
.card--good { border-color: var(--status-good); }

/* A bordered block *inside* a card body: one coverage record, one template. Not a
   nested card — no shadow, so the hierarchy stays one level deep. */
.panel {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 0.875rem;
}
.panel + .panel { margin-top: 0.75rem; }

/* A reading-width card for a single message (credentials handover, confirmation). */
.narrow { max-width: 640px; }

.grid { display: grid; gap: 1rem; }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.grid--sidebar { grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr); align-items: start; }

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

/* ------------------------------------------------------------ stat tiles ---- */

.stat {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 0.875rem 1rem;
    box-shadow: var(--shadow-sm);
    display: flex; flex-direction: column; gap: 0.125rem;
    min-width: 0;
}
.stat--link:hover { border-color: var(--line-strong); text-decoration: none; }

.stat__label {
    font-size: 0.75rem; font-weight: 600;
    color: var(--ink-secondary);
    text-transform: uppercase; letter-spacing: 0.045em;
    display: flex; align-items: center; gap: 0.3rem;
}
/* Proportional figures: this is a standalone number, not a column. */
.stat__value { font-size: 1.75rem; font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; }
/* For a value that is a pair or a fraction ("4/7") rather than one number. */
.stat__value--sm { font-size: 1.25rem; }
.stat__meta { font-size: 0.8125rem; color: var(--ink-muted); }
/* A chip standing in for the value, on its own line and optically centered. */
.stat__mark { margin: 0.3rem 0; }

.stat--good .stat__value { color: var(--status-good); }
.stat--warning .stat__value { color: var(--status-warning); }
.stat--critical .stat__value { color: var(--status-critical); }

/* Hero figure — exactly one per view. */
.hero-figure { font-size: 3rem; font-weight: 600; letter-spacing: -0.03em; line-height: 1; }

/* A single value that is the point of the block it sits in — a start date, a
   temporary password. Larger than body text, well short of a stat tile. */
.figure { font-size: 1.125rem; line-height: 1.35; }

/* ---------------------------------------------------------------- tables ---- */

.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

table.data {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}
table.data th, table.data td {
    padding: 0.6rem 0.75rem;
    text-align: left;
    border-bottom: 1px solid var(--line);
    vertical-align: middle;
}
table.data thead th {
    font-size: 0.6875rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--ink-secondary);
    background: var(--surface-2);
    white-space: nowrap;
    position: sticky; top: 0; z-index: 1;
}
table.data thead th a { color: inherit; }
table.data tbody tr:hover { background: var(--surface-2); }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.data td.nowrap { white-space: nowrap; }
table.data .row-link { color: var(--ink); font-weight: 600; }

/* Left edge carries the patient's attention state. Never the only signal —
   the row also shows a status chip with an icon and a word. */
table.data tr[data-flag="red"] td:first-child { box-shadow: inset 3px 0 0 var(--status-critical); }
table.data tr[data-flag="amber"] td:first-child { box-shadow: inset 3px 0 0 var(--status-warning-mark); }
table.data tr[data-flag="green"] td:first-child { box-shadow: inset 3px 0 0 transparent; }

.empty {
    padding: 2.5rem 1.25rem;
    text-align: center;
    color: var(--ink-muted);
}
.empty h3 { color: var(--ink); margin-bottom: 0.375rem; }
.empty svg { width: 34px; height: 34px; opacity: 0.35; margin-bottom: 0.625rem; }
/* For an empty state inside a card that already has a heading and a body padding
   of its own — the full 2.5rem would read as a gap, not as emptiness. */
.empty--tight { padding: 1.5rem 1rem; }

/* --------------------------------------------------- badges, chips, status --- */

.badge {
    display: inline-flex; align-items: center; gap: 0.3rem;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    font-size: 0.75rem; font-weight: 600;
    background: var(--surface-2);
    color: var(--ink-secondary);
    border: 1px solid var(--line);
    white-space: nowrap;
    max-width: 100%;
}
.badge__dot { width: 7px; height: 7px; border-radius: 999px; flex: 0 0 7px; background: currentColor; }

/* Status chip. The glyph is load-bearing accessibility, not decoration:
   red and green measure ΔE 4.1 apart under deuteranopia, so the shape and the
   word are what actually distinguish them. Never render one of these
   icon-less or label-less. */
.status {
    display: inline-flex; align-items: center; gap: 0.3rem;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    font-size: 0.75rem; font-weight: 600;
    white-space: nowrap;
}
.status__glyph { font-size: 0.8em; line-height: 1; }
.status--green { background: var(--status-good-bg); color: var(--status-good); }
.status--amber { background: var(--status-warning-bg); color: var(--status-warning); }
.status--red { background: var(--status-critical-bg); color: var(--status-critical); }
.status--info { background: var(--status-info-bg); color: var(--status-info); }
.status--neutral { background: var(--surface-2); color: var(--ink-secondary); }

.chips { display: flex; flex-wrap: wrap; gap: 0.3rem; }

.chip {
    display: inline-flex; align-items: center; gap: 0.3rem;
    padding: 0.1rem 0.45rem;
    border-radius: var(--radius-sm);
    font-size: 0.7188rem; font-weight: 600;
    border: 1px solid var(--line);
    background: var(--surface-2);
    color: var(--ink-secondary);
    white-space: nowrap;
}

.phase-pill {
    display: inline-flex; align-items: center; gap: 0.375rem;
    font-size: 0.75rem; font-weight: 600;
    padding: 0.15rem 0.5rem 0.15rem 0.35rem;
    border-radius: 999px;
    background: var(--surface-2);
    border: 1px solid var(--line);
    color: var(--ink-secondary);
    white-space: nowrap;
}
.phase-pill__dot { width: 8px; height: 8px; border-radius: 999px; flex: 0 0 8px; }
.phase-pill__num {
    font-variant-numeric: tabular-nums;
    opacity: 0.65;
}

/* ----------------------------------------------------------------- forms ---- */

.form { display: grid; gap: 1rem; }
.form__grid { display: grid; gap: 0.875rem 1rem; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.form__row { display: grid; gap: 0.3rem; min-width: 0; }
.form__row--wide { grid-column: 1 / -1; }

.form__section {
    border-top: 1px solid var(--line);
    padding-top: 1rem;
    margin-top: 0.25rem;
}
.form__section:first-child { border-top: 0; padding-top: 0; margin-top: 0; }
.form__section-title {
    font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--ink-muted);
    margin-bottom: 0.625rem;
}

label { font-size: 0.8125rem; font-weight: 600; color: var(--ink-secondary); }
.label-hint { font-weight: 400; color: var(--ink-muted); }

/* Heads a group of controls rather than one control. Deliberately not a <label>:
   a label may only point at a single field, and a group of checkboxes needs
   role="group" + aria-labelledby to be announced as one thing. */
.field-label { font-size: 0.8125rem; font-weight: 600; color: var(--ink-secondary); }

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="date"], input[type="datetime-local"], input[type="tel"], input[type="url"],
input[type="search"], input[type="color"], select, textarea {
    width: 100%;
    padding: 0.5rem 0.625rem;
    font: inherit; font-size: 0.875rem;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    min-height: 38px;
}
input[type="color"] { padding: 0.2rem; height: 38px; cursor: pointer; }
textarea { min-height: 92px; resize: vertical; line-height: 1.5; }

input:focus, select:focus, textarea:focus {
    outline: 2px solid var(--focus-ring);
    outline-offset: 0;
    border-color: var(--brand-primary);
}

input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
    border-color: var(--status-critical);
}

input::placeholder, textarea::placeholder { color: var(--ink-muted); }
input:disabled, select:disabled, textarea:disabled { background: var(--surface-2); color: var(--ink-muted); }

select[multiple] { min-height: 130px; padding: 0.25rem; }

/* Width by content, not by grid cell: a color swatch, a two-digit day count and
   a date all look wrong stretched to a 220px column. Three sizes, so these stay
   consistent between screens. */
.input--xs { max-width: 68px; }
.input--sm { max-width: 120px; }
.input--md { max-width: 200px; }

.field-error {
    font-size: 0.8125rem; font-weight: 500;
    color: var(--status-critical);
    display: flex; align-items: flex-start; gap: 0.25rem;
}
/* Keeps a leading icon at full size and on the first line of a wrapped message. */
.field-error svg { flex: 0 0 13px; width: 13px; height: 13px; margin-top: 3px; }
.field-help { font-size: 0.8125rem; color: var(--ink-muted); }

.check {
    display: flex; align-items: flex-start; gap: 0.5rem;
    font-size: 0.875rem; font-weight: 400; color: var(--ink);
    cursor: pointer;
}
.check input[type="checkbox"], .check input[type="radio"] {
    width: 16px; height: 16px; margin: 0.2rem 0 0; flex: 0 0 16px;
    accent-color: var(--brand-primary); cursor: pointer;
}
.check__text { min-width: 0; }
.check__title { font-weight: 500; }
.check__desc { font-size: 0.8125rem; color: var(--ink-muted); }

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

/* A checkbox occupying a .form__grid cell beside fields that have a label above
   them: drop it to sit on their baseline instead of floating at the cell top. */
.check--aligned { margin-top: 1.4rem; }
@media (max-width: 560px) {
    /* One column — there is nothing left to align with. */
    .check--aligned { margin-top: 0; }
}

.form__actions {
    display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center;
    border-top: 1px solid var(--line);
    padding-top: 1rem;
}
.form__actions .spacer { flex: 1 1 auto; }

/* --------------------------------------------------------------- filters ---- */

/* One row above the content, per the interaction spec. */
.filters {
    display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: flex-end;
    padding: 0.875rem 1rem;
    border-bottom: 1px solid var(--line);
    background: var(--surface-2);
    border-radius: var(--radius) var(--radius) 0 0;
}
.filters__field { display: grid; gap: 0.2rem; min-width: 0; }
.filters__field label { font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.05em; }
.filters__field--grow { flex: 1 1 200px; }
.filters input, .filters select { min-height: 34px; padding: 0.3rem 0.5rem; font-size: 0.8125rem; }
.filters__actions { display: flex; gap: 0.375rem; }

.active-filters { display: flex; flex-wrap: wrap; gap: 0.375rem; padding: 0.625rem 1rem 0; }

/* ----------------------------------------------------------------- alerts --- */

.alert {
    display: flex; gap: 0.625rem; align-items: flex-start;
    padding: 0.75rem 0.875rem;
    border-radius: var(--radius);
    border: 1px solid;
    font-size: 0.875rem;
    margin-bottom: 1rem;
}
.alert svg { width: 17px; height: 17px; flex: 0 0 17px; margin-top: 1px; }
.alert__body { min-width: 0; }
.alert__title { font-weight: 600; }
.alert--success { background: var(--status-good-bg); border-color: color-mix(in oklab, var(--status-good) 32%, transparent); color: var(--status-good); }
.alert--error { background: var(--status-critical-bg); border-color: color-mix(in oklab, var(--status-critical) 32%, transparent); color: var(--status-critical); }
.alert--warning { background: var(--status-warning-bg); border-color: color-mix(in oklab, var(--status-warning-mark) 42%, transparent); color: var(--status-warning); }
.alert--info { background: var(--status-info-bg); border-color: color-mix(in oklab, var(--status-info) 32%, transparent); color: var(--status-info); }
.alert a { color: inherit; text-decoration: underline; }

.flashes { position: sticky; top: calc(var(--topbar-h) + 0.5rem); z-index: 15; }

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

.tabs {
    display: flex; gap: 0.125rem; overflow-x: auto;
    border-bottom: 1px solid var(--line);
    margin-bottom: 1rem;
}
.tabs__link {
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem; font-weight: 500;
    color: var(--ink-secondary);
    border-bottom: 2px solid transparent;
    white-space: nowrap;
}
.tabs__link:hover { color: var(--ink); text-decoration: none; }
.tabs__link[aria-current="page"] {
    color: var(--brand-primary);
    border-bottom-color: var(--brand-primary);
    font-weight: 600;
}

/* ----------------------------------------------- disclosures & popovers ----- */

/* <details> is the whole mechanism for "reveal the form that records this".
   Native, so it needs no JavaScript and no CSP exemption. */
.disclosure {
    cursor: pointer;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--ink-secondary);
}
.disclosure:hover { color: var(--ink); }
.disclosure::marker { color: var(--ink-muted); }
details[open] > .disclosure { margin-bottom: 0.5rem; }

/* When the <details> *is* the card, its summary is the card head and carries the
   head's padding — the margin below would double the border gap, so drop it. */
.disclosure--padded { padding: 0.875rem 1rem; }
details[open] > .disclosure--padded { margin-bottom: 0; }
.card__body--topline { border-top: 1px solid var(--line); }

/* A <summary> styled as a button opens a small panel of controls — the row-level
   "Cancel with a reason" and "Reset password" affordances.

   The panel stays in normal flow rather than being absolutely positioned: these
   live in the last cell of a table inside .table-wrap, whose overflow-x would
   clip a positioned panel and add a scrollbar instead of showing it. */
.popover { display: inline-block; }
.popover > summary { list-style: none; }
.popover > summary::-webkit-details-marker { display: none; }

.popover__panel {
    margin-top: 0.375rem;
    padding: 0.75rem;
    min-width: 240px;
    text-align: left;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

/* ------------------------------------------------- definition/detail lists --- */

.dl { display: grid; gap: 0.625rem 1rem; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.dl__item { min-width: 0; }
.dl__key {
    font-size: 0.6875rem; font-weight: 600; text-transform: uppercase;
    letter-spacing: 0.05em; color: var(--ink-muted);
}
.dl__val { font-size: 0.875rem; overflow-wrap: break-word; }
.dl__val--strong { font-weight: 600; }

/* -------------------------------------------------------------- timeline ---- */

.timeline { display: grid; gap: 0; }
.timeline__item {
    display: grid; grid-template-columns: 22px 1fr; gap: 0.625rem;
    padding-bottom: 1rem;
    position: relative;
}
.timeline__item:not(:last-child)::before {
    content: ""; position: absolute;
    left: 10px; top: 20px; bottom: 0;
    width: 1px; background: var(--line);
}
.timeline__dot {
    width: 9px; height: 9px; border-radius: 999px;
    background: var(--viz-series);
    margin: 6px 0 0 6px;
    /* 2px surface ring so the dot stays legible over the connector line. */
    box-shadow: 0 0 0 2px var(--surface);
}
/* The dot states an outcome where the entry has one — a pinned note, a message
   that failed. The row text always says the same thing in words. */
.timeline__dot--good { background: var(--status-good); }
.timeline__dot--warning, .timeline__dot--pinned { background: var(--status-warning-mark); }
.timeline__dot--critical { background: var(--status-critical); }

.timeline__body { min-width: 0; font-size: 0.875rem; padding-top: 1px; }
.timeline__meta { font-size: 0.75rem; color: var(--ink-muted); }

/* ------------------------------------------------------------- checklist ---- */

.checklist { display: grid; gap: 0.125rem; }
.checklist__item {
    display: flex; align-items: flex-start; gap: 0.5rem;
    padding: 0.5rem;
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
}
.checklist__item:hover { background: var(--surface-2); }

/* Each item is its own POST form, so the tick is a submit button rather than a
   checkbox — a checkbox would imply a change that only takes effect on save. */
.checklist__toggle { padding: 0.1rem; min-width: 22px; }
.checklist__box {
    display: inline-grid; place-items: center;
    width: 17px; height: 17px;
    border-radius: 4px;
    border: 1.5px solid var(--line-strong);
    /* Flips with the theme so the tick holds contrast on both greens. */
    color: var(--ink-inverse);
}
.checklist__box--done { border-color: var(--status-good); background: var(--status-good); }
/* Only the step text is struck through. The line used to be set on the whole
   label, and text-decoration propagates to in-flow descendants — so it ran through
   the help text and through the name of whoever completed it, which reads as if
   the person had been crossed out too. */
.checklist__item--done .checklist__label { color: var(--ink-muted); }
.checklist__item--done .checklist__text { text-decoration: line-through; }
.checklist__meta { font-size: 0.75rem; color: var(--ink-muted); }
.checklist__req { color: var(--status-critical); font-weight: 700; }

/* ----------------------------------------------------- document requirements - */

/* "What does this record still need?" — one row per required document, stating
   plainly whether it is on file and what it is for. Three channels again: the
   left border, the marker glyph, and the words "On file"/"Not on file yet". */

.req-list { display: grid; gap: 0.5rem; list-style: none; margin: 0; padding: 0; }

.req {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    padding: 0.625rem 0.75rem;
    border: 1px solid var(--line);
    border-left-width: 3px;
    border-radius: var(--radius-sm);
    background: var(--surface);
}
.req--met { border-left-color: var(--status-good); }
.req--missing { border-left-color: var(--status-warning-mark); }

.req__mark {
    flex: 0 0 20px;
    display: grid;
    place-items: center;
    width: 20px;
    height: 20px;
    margin-top: 1px;
    border-radius: 999px;
}
.req__mark svg { width: 13px; height: 13px; }
.req--met .req__mark { background: var(--status-good-bg); color: var(--status-good); }
.req--missing .req__mark { background: var(--status-warning-bg); color: var(--status-warning); }

.req__text { flex: 1 1 auto; min-width: 0; }
.req__name {
    display: flex; align-items: center; flex-wrap: wrap; gap: 0.375rem;
    font-size: 0.875rem; font-weight: 600;
}
.req__why { font-size: 0.8125rem; color: var(--ink-secondary); }
.req__state { font-size: 0.75rem; color: var(--ink-muted); }
.req__action { flex: 0 0 auto; }

.req-list__foot {
    margin-top: 0.625rem;
    font-size: 0.75rem;
    color: var(--ink-muted);
}

@media (max-width: 560px) {
    .req { flex-wrap: wrap; }
    .req__action { width: 100%; }
    .req__action .btn { width: 100%; }
}

/* ------------------------------------------------------------------ meter --- */

.meter {
    height: 7px; border-radius: 999px;
    background: var(--viz-track);
    overflow: hidden;
}
.meter__fill { height: 100%; border-radius: 999px; background: var(--viz-series); }
.meter__fill--good { background: var(--status-good); }
.meter__fill--warning { background: var(--status-warning-mark); }
.meter__fill--critical { background: var(--status-critical); }

/* ----------------------------------------------------------------- charts --- */

.chart { width: 100%; }
.chart svg { display: block; width: 100%; height: auto; overflow: visible; }

.chart__grid line { stroke: var(--viz-grid); stroke-width: 1; }
.chart__axis line { stroke: var(--viz-axis); stroke-width: 1; }

/* Text on a chart wears text tokens, never the series color. */
.chart__label { fill: var(--ink-secondary); font-size: 11.5px; }
.chart__tick { fill: var(--ink-muted); font-size: 10.5px; font-variant-numeric: tabular-nums; }
.chart__value { fill: var(--ink); font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; }

.chart__bar { fill: var(--viz-series); }
.chart__bar-track { fill: var(--viz-track); }
.chart__bar:hover { fill: color-mix(in oklab, var(--viz-series) 82%, black); }

.chart-legend {
    display: flex; flex-wrap: wrap; gap: 0.75rem;
    font-size: 0.8125rem; color: var(--ink-secondary);
    margin-top: 0.5rem;
}
.chart-legend__item { display: inline-flex; align-items: center; gap: 0.35rem; }
.chart-legend__swatch { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 10px; }

/* Raw audit metadata: wraps, but never widens the row it sits in. */
.audit-meta { max-width: 280px; margin: 0.25rem 0 0; }

/* A table view of every chart, so nothing is gated behind color perception. */
.chart-table summary {
    cursor: pointer; font-size: 0.8125rem; color: var(--ink-secondary);
    padding: 0.375rem 0; font-weight: 500;
}
.chart-table summary:hover { color: var(--ink); }
.chart-table[open] summary { margin-bottom: 0.5rem; }

/* Horizontal bar rows, built in HTML rather than SVG where a row also needs
   links and badges — same visual spec: capped thickness, rounded data-end. */
.barlist { display: grid; gap: 0.5rem; }
.barlist__row { display: grid; grid-template-columns: minmax(110px, 1.4fr) minmax(0, 3fr) auto; gap: 0.625rem; align-items: center; font-size: 0.875rem; }
.barlist__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.barlist__track { background: var(--viz-track); border-radius: 4px; height: 18px; position: relative; overflow: hidden; }
.barlist__fill { position: absolute; inset: 0 auto 0 0; border-radius: 0 4px 4px 0; background: var(--viz-series); min-width: 2px; }
.barlist__value { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 2.5rem; text-align: right; }

@media (max-width: 560px) {
    .barlist__row { grid-template-columns: 1fr auto; }
    .barlist__track { grid-column: 1 / -1; }
}

/* --------------------------------------------------------- pipeline board --- */

.board { display: flex; gap: 0.75rem; overflow-x: auto; padding-bottom: 0.75rem; }
.board__col {
    flex: 0 0 268px;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    display: flex; flex-direction: column;
    max-height: 74vh;
}
.board__head { padding: 0.625rem 0.75rem; border-bottom: 1px solid var(--line); }
.board__title { display: flex; align-items: center; gap: 0.4rem; font-size: 0.8125rem; font-weight: 600; }
.board__count { margin-left: auto; font-size: 0.75rem; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.board__body { overflow-y: auto; padding: 0.5rem; display: grid; gap: 0.5rem; align-content: start; }
.board__none { padding: 1rem 0.5rem; }

.board__card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    padding: 0.55rem 0.625rem;
    display: grid; gap: 0.3rem;
    font-size: 0.8125rem;
    box-shadow: var(--shadow-sm);
}
.board__card:hover { border-color: var(--line-strong); text-decoration: none; }
.board__card[data-flag="red"] { border-left: 3px solid var(--status-critical); }
.board__card[data-flag="amber"] { border-left: 3px solid var(--status-warning-mark); }
.board__card-name { font-weight: 600; color: var(--ink); }
.board__card-meta { font-size: 0.75rem; color: var(--ink-muted); display: flex; flex-wrap: wrap; gap: 0.375rem; }

/* --------------------------------------------------- phase progress track --- */

/* The chart header's answer to "where is this family in the process?".
   An ordered list, because that is what it is: the phases in order, each either
   behind, current, or ahead.

   Three channels per step, never color alone:
     - the marker glyph differs by state (tick / ring / hollow number),
     - the label's weight and ink differ,
     - a visually hidden word states the state for a screen reader, and
       aria-current="step" marks the one the record is in. */

.track {
    display: flex;
    align-items: flex-start;
    list-style: none;
    margin: 0;
    padding: 0.25rem 0 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* The base step is the "ahead" state (.track__step--ahead carries no rules of its
   own); --done and --current style themselves on top of it. */
.track__step {
    position: relative;
    flex: 1 1 0;
    min-width: 96px;
    padding: 0 0.25rem;
    text-align: center;
}

/* The connector runs from this marker's center to the next one's, at marker
   height, and is drawn *behind* both (the marker is z-indexed above it). A step
   fills the segment leaving it once the record has passed through, so the filled
   run always ends at the current phase. */
.track__step:not(:last-child)::after {
    content: "";
    position: absolute;
    z-index: 0;
    top: 10px;
    left: 50%;
    right: -50%;
    height: 2px;
    background: var(--line-strong);
}
.track__step--done::after { background: var(--status-good); }

.track__marker {
    position: relative;
    z-index: 1;
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    margin: 0 auto 0.4rem;
    border-radius: 999px;
    border: 2px solid var(--line-strong);
    background: var(--surface);
    color: var(--ink-muted);
    font-size: 0.6875rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.track__marker svg { width: 12px; height: 12px; stroke-width: 3; }

.track__step--done .track__marker {
    border-color: var(--status-good);
    background: var(--status-good);
    /* Not #fff: the dark-mode green is light, and a white tick on it measures
       2.3:1 — under the 3:1 a graphical object needs. --ink-inverse flips with the
       theme, so the tick stays legible in both. */
    color: var(--ink-inverse);
}
.track__step--current .track__marker {
    border-color: var(--brand-primary);
    color: var(--brand-primary);
    /* Halo rather than a size change, so the row of markers stays on one line. */
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--brand-primary) 20%, transparent);
}

.track__label {
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--ink-muted);
    overflow-wrap: break-word;
}
.track__step--done .track__label { color: var(--ink-secondary); }
.track__step--current .track__label { color: var(--ink); }

.track__meta {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.6875rem;
    color: var(--ink-muted);
}

/* The summary line above the track: how far along, and how long here. */
.track-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.5rem;
    font-size: 0.8125rem;
    color: var(--ink-secondary);
}
.track-head__count { font-weight: 600; color: var(--ink); }

/* ------------------------------------------------------------- pagination --- */

.pagination {
    display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
    padding: 0.75rem 1rem;
    border-top: 1px solid var(--line);
    font-size: 0.875rem;
    color: var(--ink-secondary);
}
.pagination__spacer { flex: 1 1 auto; }

/* ---------------------------------------------------------------- avatars --- */

.avatar {
    width: 30px; height: 30px; flex: 0 0 30px;
    border-radius: 999px;
    background: color-mix(in oklab, var(--brand-primary) 16%, transparent);
    color: var(--brand-primary);
    display: grid; place-items: center;
    font-size: 0.6875rem; font-weight: 700;
}
.avatar--lg { width: 42px; height: 42px; flex-basis: 42px; font-size: 0.875rem; }

.person { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.person__name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.person__meta { font-size: 0.75rem; color: var(--ink-muted); }

/* ------------------------------------------------------------------ misc ---- */

/* Utilities exist so a template never needs a style attribute: the CSP has no
   'unsafe-inline' in style-src and a nonce cannot cover an attribute, so a
   style="…" is dropped by the browser and the rule silently does nothing.
   Anything genuinely dynamic goes through Ui::dyn() instead. */

.muted { color: var(--ink-muted); }
.small { font-size: 0.8125rem; }
.tiny { font-size: 0.75rem; }
.strong { font-weight: 600; }
.right { text-align: right; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.pre-wrap { white-space: pre-wrap; }
.pre { white-space: pre; }
.break-any { overflow-wrap: anywhere; }
.tabular { font-variant-numeric: tabular-nums; }

.text-secondary { color: var(--ink-secondary); }
.text-brand { color: var(--brand-primary); }
.text-good { color: var(--status-good); }
.text-warning { color: var(--status-warning); }
.text-critical { color: var(--status-critical); }

.stack { display: grid; gap: 1rem; }
.stack--sm { display: grid; gap: 0.5rem; }
.row { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.row--tight { gap: 0.3rem; }
.row--wide { gap: 1rem; }
.row--between { justify-content: space-between; }
.row--top { align-items: flex-start; }

/* Pushes what follows to the far end of a flex row — a card action, a meta note. */
.push { margin-left: auto; }
.grow { flex: 1 1 auto; }
.min-0 { min-width: 0; }

.m-0 { margin: 0; }
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: 0.5rem; }
.mt-2 { margin-top: 1rem; }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: 0.5rem; }
.mb-2 { margin-bottom: 1rem; }
.my-1 { margin: 0.5rem 0; }

.divider { border-top: 1px solid var(--line); margin: 1rem 0; }
.divider--sm { margin: 0.5rem 0; }
.divider--xs { margin: 0.25rem 0; }

/* A form wrapping a single button, sitting in a row of other buttons. */
.inline-form { display: inline-block; }

/* A whole block that is one link — a settings tile. The child heading carries
   the link color instead, so the tile does not read as a wall of blue. */
.plain-link { color: inherit; text-decoration: none; }
.plain-link:hover { text-decoration: none; }

/* Prose bullets inside a card: the browser default indent is far too deep. */
.bullets { margin: 0.4rem 0 0; padding-left: 1.15rem; }
.bullets li + li { margin-top: 0.2rem; }

/* A long log that must not push the page height — the panel scrolls instead. */
.scroll-y { max-height: 320px; overflow-y: auto; }

.ml-xs { margin-left: 0.25rem; }
/* A flex child that fills the row but wraps to its own line before going narrow. */
.grow-260 { flex: 1 1 260px; min-width: 0; }
/* A table cell that should be exactly as wide as its buttons. */
table.data td.shrink, table.data th.shrink { width: 1%; }
/* A key column in a two-column detail table — keeps the values aligned. */
table.data th.col-200 { width: 200px; }

.phi-note {
    font-size: 0.75rem; color: var(--ink-muted);
    display: inline-flex; align-items: center; gap: 0.3rem;
}

.kbd {
    font-family: var(--font-mono); font-size: 0.75rem;
    padding: 0.1rem 0.3rem;
    border: 1px solid var(--line-strong);
    border-bottom-width: 2px;
    border-radius: 4px;
    background: var(--surface-2);
}

.copy-box {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.625rem 0.75rem;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    font-family: var(--font-mono); font-size: 0.8125rem;
    overflow-x: auto;
}
/* A value someone has to read aloud or type by hand — a temporary password. */
.copy-box--lg { font-size: 1rem; font-weight: 600; letter-spacing: 0.02em; }

/* ------------------------------------------------------------------ auth ---- */

.auth {
    min-height: 100vh;
    display: grid; place-items: center;
    padding: 1.5rem;
    background: var(--page);
}
.auth__card {
    width: 100%; max-width: 400px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: 1.75rem;
}
.auth__brand { display: flex; align-items: center; gap: 0.625rem; margin-bottom: 1.25rem; }
.auth__brand .sidebar__mark { width: 34px; height: 34px; flex-basis: 34px; }
.auth__title { font-size: 1.125rem; }
.auth__divider {
    display: flex; align-items: center; gap: 0.625rem;
    margin: 1.25rem 0;
    font-size: 0.75rem; color: var(--ink-muted);
    text-transform: uppercase; letter-spacing: 0.05em;
}
.auth__divider::before, .auth__divider::after {
    content: ""; flex: 1 1 auto; border-top: 1px solid var(--line);
}
.auth__foot { margin-top: 1.25rem; font-size: 0.75rem; color: var(--ink-muted); text-align: center; }

.google-btn {
    display: flex; align-items: center; justify-content: center; gap: 0.5rem;
    width: 100%;
    padding: 0.625rem;
    background: var(--surface);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    font: inherit; font-size: 0.9375rem; font-weight: 500;
    color: var(--ink);
    cursor: pointer;
}
.google-btn:hover { background: var(--surface-2); text-decoration: none; }
.google-btn svg { width: 18px; height: 18px; }

/* ---------------------------------------------------------- error / minimal - */

/* The explicit minmax(0, 1fr) column is what makes .error-detail's overflow-x
   actually scroll. Without it the single implicit track is auto-sized, so a long
   stack-trace line grew the track past the viewport and pushed the whole page
   into a horizontal scroll on narrow screens instead of scrolling inside the
   trace block. */
.minimal {
    min-height: 100vh;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    place-items: center;
    padding: 1.5rem;
}
.minimal__card { width: 100%; max-width: 560px; }
.error-code { font-size: 3rem; font-weight: 600; line-height: 1; color: var(--ink-muted); }
.error-detail {
    margin-top: 1rem; padding: 0.75rem;
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    font-family: var(--font-mono); font-size: 0.6875rem;
    white-space: pre-wrap; overflow-x: auto;
    color: var(--status-critical);
    max-height: 340px;
}

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

@media (max-width: 900px) {
    .menu-toggle { display: inline-flex; }

    .sidebar {
        position: fixed; z-index: 40;
        inset: 0 auto 0 0;
        transform: translateX(-100%);
        transition: transform 0.18s ease-out;
        box-shadow: var(--shadow-lg);
    }
    /* Toggled with :target so the mobile menu needs no JavaScript — which keeps
       the CSP free of any script exemption for navigation. */
    .sidebar:target { transform: translateX(0); }

    .sidebar__close { display: inline-flex !important; }

    .content { padding: 1rem; }
    .grid--4, .grid--3 { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
    .stat__value { font-size: 1.5rem; }
}

@media (min-width: 901px) {
    .sidebar__close { display: none !important; }
}

@media (max-width: 560px) {
    body { font-size: 14.5px; }
    .page-head__actions { width: 100%; }
    .page-head__actions .btn { flex: 1 1 auto; }
    .grid--4, .grid--3, .grid--2 { grid-template-columns: 1fr; }
    table.data th, table.data td { padding: 0.5rem; }
    .hide-sm { display: none !important; }
}

@media (max-width: 400px) {
    .hide-xs { display: none !important; }
}

/* ------------------------------------------------------------ file upload --- */

/* Toggled from app.js. Presentation only ever changes by class, because the CSP
   has no 'unsafe-inline' for styles. */
.is-hidden { display: none !important; }

.dropzone__target {
    border: 1.5px dashed var(--line-strong);
    border-radius: var(--radius);
    background: var(--surface-2);
    padding: 1.25rem 1rem;
    text-align: center;
    cursor: pointer;
    display: block;
    transition: border-color 0.15s, background 0.15s;
}

.dropzone__target:hover { border-color: var(--brand-primary); }

.dropzone__target:focus-within {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
    border-color: var(--brand-primary);
}

.dropzone__target.is-dragging {
    border-color: var(--brand-primary);
    border-style: solid;
    background: var(--status-info-bg);
}

.dropzone__icon { color: var(--ink-muted); display: block; margin: 0 auto 0.4rem; }
.dropzone__lead { font-weight: 600; font-size: 0.875rem; }
.dropzone__hint { font-size: 0.75rem; color: var(--ink-muted); margin-top: 0.2rem; }

/* The real input stays in the DOM and keyboard-reachable — it is what actually
   submits — but the label above is the visible affordance. */
.dropzone__input {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* Without JS the input must be visible, or there is no way to choose a file. */
.dropzone:not(.is-enhanced) .dropzone__input {
    position: static;
    width: auto; height: auto;
    margin: 0.5rem 0 0;
    clip: auto;
    overflow: visible;
}

.dropzone:not(.is-enhanced) .dropzone__lead,
.dropzone:not(.is-enhanced) .dropzone__icon { display: none; }

.upload-list { display: grid; gap: 0.5rem; margin-top: 0.75rem; }

.upload-item {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.625rem;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--surface);
}

.upload-item__thumb {
    flex: 0 0 auto;
    width: 56px; height: 56px;
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    border: 1px solid var(--line);
    overflow: hidden;
    display: flex; align-items: center; justify-content: center;
}

.upload-item__thumb img { width: 100%; height: 100%; object-fit: cover; }

.upload-item__ext {
    font-size: 0.625rem; font-weight: 700; letter-spacing: 0.03em;
    color: var(--ink-muted);
}

.upload-item__fields { flex: 1 1 auto; min-width: 0; display: grid; gap: 0.375rem; }
.upload-item__field { display: grid; gap: 0.15rem; }
.upload-item__field input, .upload-item__field select { width: 100%; }
.upload-item__meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upload-item__remove { flex: 0 0 auto; align-self: center; }

.upload-errors {
    margin-top: 0.5rem;
    font-size: 0.75rem;
    color: var(--status-critical);
    display: grid; gap: 0.15rem;
}

.upload-summary { font-size: 0.75rem; color: var(--ink-muted); margin-top: 0.5rem; }

/* Thumbnails in the stored-document table. */
.doc-thumb {
    width: 40px; height: 40px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--line);
    background: var(--surface-2);
    object-fit: cover;
    display: block;
}

.doc-thumb--icon {
    display: flex; align-items: center; justify-content: center;
    color: var(--ink-muted);
}

.doc-cell { display: flex; align-items: flex-start; gap: 0.5rem; min-width: 0; }
.doc-cell__text { min-width: 0; }
.doc-actions { flex-wrap: nowrap; justify-content: flex-end; }
.doc-row { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }

/* ---------------------------------------------------- document preview modal --- */

.doc-modal {
    /* Big enough to actually read a scanned page, but never edge-to-edge. */
    width: min(1100px, 94vw);
    height: min(88vh, 1000px);
    max-width: none;
    max-height: none;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--surface);
    color: var(--ink);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}

/* Only laid out as a column once open — a closed dialog must stay display:none. */
.doc-modal[open] { display: flex; flex-direction: column; }

.doc-modal::backdrop {
    background: rgba(16, 20, 27, 0.55);
    backdrop-filter: blur(2px);
}

.doc-modal__head {
    display: flex; align-items: flex-start; gap: 0.75rem;
    padding: 0.875rem 1rem;
    border-bottom: 1px solid var(--line);
    background: var(--surface-2);
    flex: 0 0 auto;
}

.doc-modal__heading { min-width: 0; flex: 1 1 auto; }

.doc-modal__title {
    font-size: 0.9375rem; font-weight: 600; margin: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.doc-modal__close {
    flex: 0 0 auto;
    width: 30px; height: 30px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.25rem; line-height: 1;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--ink-secondary);
    cursor: pointer;
}

.doc-modal__close:hover { background: var(--surface-3); color: var(--ink); }

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

.doc-modal__body {
    flex: 1 1 auto;
    min-height: 0;              /* lets the iframe shrink instead of overflowing */
    overflow: auto;
    background: var(--surface-3);
    display: flex; align-items: center; justify-content: center;
    padding: 0.75rem;
}

.doc-modal__status { margin: 0; }

.doc-modal__image {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: var(--radius-sm);
    background: #fff;
    box-shadow: var(--shadow-sm);
}

.doc-modal__frame {
    width: 100%; height: 100%;
    border: 0;
    border-radius: var(--radius-sm);
    background: #fff;
}

.doc-modal__foot {
    flex: 0 0 auto;
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.75rem; flex-wrap: wrap;
    padding: 0.75rem 1rem;
    border-top: 1px solid var(--line);
    background: var(--surface-2);
}

.doc-modal__nav,
.doc-modal__actions { display: flex; align-items: center; gap: 0.5rem; }
.doc-modal__position { min-width: 5.5rem; text-align: center; }
.doc-modal__nav .btn[disabled] { opacity: 0.45; pointer-events: none; }

@media (max-width: 640px) {
    .doc-modal { width: 100vw; height: 100vh; border-radius: 0; border: 0; }
    .doc-modal__foot { justify-content: center; }
    .doc-modal__nav, .doc-modal__actions { flex: 1 1 100%; justify-content: center; }
    .doc-actions { flex-wrap: wrap; }
}

@media (max-width: 640px) {
    .upload-item { flex-wrap: wrap; }
    .upload-item__remove { align-self: flex-start; }
}

/* --------------------------------------------------------------- printing --- */

@media print {
    .sidebar, .topbar, .page-head__actions, .filters, .pagination, .btn { display: none !important; }
    body { background: #fff; font-size: 11pt; }
    .card { border: 1px solid #999; box-shadow: none; break-inside: avoid; }
    .panel, .popover__panel { box-shadow: none; }
    /* A printed chart is a record: the whole phase track belongs on the page, not
       scrolled out of it. */
    .track { overflow-x: visible; }
    .scroll-y { max-height: none; overflow: visible; }
    /* Forced-colors/print fallback: the status word carries the meaning, since
       the background tint will not survive. */
    .status { border: 1px solid #666; }
    .content { padding: 0; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* High-contrast / forced-colors mode: let the OS palette through, and lean on
   the glyph + label pairing that status chips already carry. */
@media (forced-colors: active) {
    .status, .badge, .chip, .card, .btn, .panel, .req { border: 1px solid CanvasText; }
    .chart__bar { fill: CanvasText; }
    .meter__fill { background: Highlight; }
    /* The tick and the number survive; the fill colors do not. */
    .track__marker { border: 2px solid CanvasText; }
    .track__step--current .track__marker { border-color: Highlight; }
}
