html, body {
    font-family: 'Inter', system-ui, -apple-system, sans-serif;
}

a, .btn-link {
    color: #1F5533;
}

.btn-primary {
    color: #fff;
    background-color: #1F5533;
    border-color: #163d25;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #4a8a65;
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #22c55e;
}

.invalid {
    outline: 1px solid #ef4444;
}

.validation-message {
    color: #ef4444;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

.blazor-error-boundary::after {
    content: "An error has occurred."
}

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

/* Quieter MudBlazor inputs */
.mud-input.mud-input-outlined .mud-input-outlined-border {
    border-width: 1px !important;
}
.mud-input.mud-input-outlined.mud-input-focused .mud-input-outlined-border {
    border-width: 1px !important;
    border-color: #4a8a65 !important;
}
.mud-input-label-inputcontrol {
    color: #64748b !important;
}

/* Hide number input spinners */
.mud-input-numeric-spin {
    display: none !important;
}

/* Long tables scroll inside their own container instead of stretching the page:
   the whole table box is capped to the viewport and laid out as a column, so
   toolbar, header and pager keep their natural height and the rows take all the
   rest — no guessing at chrome height, and a toolbar that wraps just gives the
   rows less. It's a max-height, so short tables still shrink to their content.

   --zeus-table-reserve is the viewport a page keeps for itself. The default only
   covers .content's top padding plus a little breathing room below, which is
   right when the table is the first thing on the page; pages that stack content
   above a table raise it on the table itself. */
.mud-table-sticky-header {
    display: flex;
    flex-direction: column;
    max-height: calc(100dvh - var(--zeus-table-reserve, 2.75rem));
}

.mud-table-sticky-header > .mud-table-toolbar,
.mud-table-sticky-header > .mud-table-pagination {
    flex: 0 0 auto;
}

.mud-table-sticky-header .mud-table-container {
    flex: 1 1 auto;
    min-height: 0;
    /* Bounds the rows on their own should the container ever stop being a direct
       flex child of the table box, where flex-basis would go ignored. */
    max-height: calc(100dvh - var(--zeus-table-reserve, 2.75rem));
}

/* Dialogs already scroll their own body; keep their tables well inside it. */
.mud-dialog .mud-table-sticky-header,
.mud-dialog .mud-table-sticky-header .mud-table-container {
    max-height: 45dvh;
}

/* ── Support console ─────────────────────────────────────────────────────
   The support chat is a workspace, not a document: the conversation and the
   user's dossier sit side by side and scroll independently, so the composer
   and the identity header never leave the screen. The thread column takes the
   width the rail doesn't, but bubbles stay capped at a readable measure — the
   rail absorbs the extra space instead of the line length growing with it. */
.support-console {
    display: grid;
    grid-template-columns: minmax(0, 54rem) minmax(19rem, 23rem);
    justify-content: center;
    gap: 1rem;
    height: calc(100dvh - var(--zeus-console-reserve, 2.75rem));
}

.support-thread {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* Header and composer carry their own rules. A MudDivider must NOT be used here:
   its default DividerType.FullWidth sets flex-grow:1, which in a flex column
   grows along the main axis and turns the divider into a tall filled band. */
.support-thread__header {
    border-bottom: 1px solid var(--mud-palette-divider);
}

.support-thread__composer {
    border-top: 1px solid var(--mud-palette-divider);
}

.support-thread__log {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* Both bubble rules match .mud-paper's own specificity and app.css loads after
   MudBlazor, so they win on order — which also means --mine must stay below the
   base rule. The two sides read apart by surface colour, not by shadow alone. */
.support-thread__bubble {
    max-width: min(70%, 34rem);
    background-color: var(--mud-palette-background-gray);
}

/* Support's own messages, tinted from the brand rather than the stray Material
   blue this page used to carry. */
.support-thread__bubble--mine {
    background-color: rgba(31, 85, 51, 0.08);
}

.support-rail {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-height: 0;
    overflow-y: auto;
}

.support-rail__label {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* Identifiers operators read aloud or dictate: monospace keeps 0/O and 1/l apart. */
.support-mono {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

/* The support code is the one artifact tying a voice on the phone to a row in
   the database, so it gets the weight of a claim ticket. Click copies it. */
.support-code {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: 100%;
    padding: 0.625rem 0.75rem;
    font: inherit;
    text-align: left;
    color: var(--mud-palette-primary);
    background-color: rgba(31, 85, 51, 0.06);
    border: 1px solid rgba(31, 85, 51, 0.28);
    border-radius: 8px;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.support-code:hover {
    background-color: rgba(31, 85, 51, 0.1);
    border-color: rgba(31, 85, 51, 0.5);
}

.support-code:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.support-code__value {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 1.125rem;
    font-weight: 600;
    letter-spacing: 0.22em;
    text-transform: uppercase;
}

.support-rail__row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.support-rail__row > .support-rail__value {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Rail links behave like rows, not like prose links. */
.support-rail__link {
    display: block;
    padding: 0.375rem 0.5rem;
    margin-inline: -0.5rem;
    border-radius: 6px;
    color: inherit;
    text-decoration: none;
}

.support-rail__link:hover {
    background-color: var(--mud-palette-background-gray);
    color: inherit;
}

.support-rail__link:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

@media (prefers-reduced-motion: reduce) {
    .support-code {
        transition: none;
    }
}

/* Narrow viewports: the rail stops being a column and becomes the page's tail. */
@media (max-width: 1100px) {
    .support-console {
        grid-template-columns: minmax(0, 1fr);
        height: auto;
    }

    .support-rail {
        overflow: visible;
    }

    .support-thread__log {
        max-height: 55dvh;
    }

    .support-thread__bubble {
        max-width: 85%;
    }
}

/* Phones: the console is a messaging surface first. The thread owns the
   viewport minus the app chrome, so the composer never leaves the screen;
   the dossier rail sits past the thread and is reached by page scroll.
   This block must follow the 1100px one — both match on phones and this
   one wins on order (height, log cap). */
@media (max-width: 640.98px) {
    .support-console {
        /* 3.5rem sticky bar + 1.1rem content padding + breathing room. */
        --zeus-console-reserve: 5.25rem;
        height: calc(100dvh - var(--zeus-console-reserve));
        grid-template-rows: 100%;
    }

    .support-thread__log {
        max-height: none;
    }
}

/* ── Mobile utilities (≤640.98px) ────────────────────────────────────────
   The phone tier of the backoffice. Pages opt columns and chrome out of the
   phone with .zx-hide-phone; dialogs and inputs adapt globally. Desktop is
   untouched: everything phone-specific sits behind the same 640.98px boundary
   the layout css uses. */

/* Grids whose rows navigate somewhere advertise it — shared by the support
   chat list and the verification queue (was a local <style> in Chats.razor). */
.clickable-grid .mud-table-row {
    cursor: pointer;
}

/* Counterpart to .zx-hide-phone, for the cases where hiding columns isn't
   enough and the phone needs its own markup: mark the desktop block
   .zx-hide-phone and the phone block .zx-phone-only, and exactly one of the
   two renders. Reach for it only when the two tiers genuinely differ in kind
   (a table vs. a list of touch rows) — a responsive single markup is cheaper
   to keep honest. */
@media (min-width: 641px) {
    .zx-phone-only {
        display: none !important;
    }
}

@media (max-width: 640.98px) {
    .zx-hide-phone {
        display: none !important;
    }

    /* The sticky top bar (3.5rem) joins the chrome full-height tables clear. */
    :root {
        --zeus-table-reserve: 6.25rem;
    }

    /* A 16px page gutter on top of each card's own 16px padding spends 64px
       of a 393px screen before any content. Halving the page side gutter
       gives that width back to the cards; they keep their own padding, so
       text still never runs into the bezel. !important because both
       Bootstrap and MudBlazor ship .px-4 that way. */
    .content.px-4 {
        padding-left: 0.5rem !important;
        padding-right: 0.5rem !important;
    }

    /* ── Tables that restructure instead of scrolling ────────────────────
       Two shapes of MudSimpleTable, both re-laid out in CSS so the markup
       stays single-source: no phone-only copy of the rows to keep in sync.

       Every display here is !important because MudBlazor pins the table
       display roles harder than a single utility class can reach:
           .mud-simple-table table thead  { display: table-header-group }
           .mud-simple-table table * tr   { display: table-row }
       Both are (0,1,2); .zx-def-table tr is (0,1,1) and loses outright,
       while .zx-card-table tbody tr only ties and wins on file order. That
       split is why a card row used to stack its title correctly and then
       collapse every following cell back into one squeezed table row.

       .zx-def-table — a "label | value" record. The label column is pinned
       at 150px, which leaves ~180px for the value on a 375px screen and
       truncates emails and addresses; stacked, both get the full width. */
    .zx-def-table tbody {
        display: block !important;
    }

    .zx-def-table tr {
        display: block !important;
        padding: 0.5rem 0;
        border-bottom: 1px solid var(--mud-palette-lines-default);
    }

    .zx-def-table tr:last-child {
        border-bottom: 0;
    }

    .zx-def-table td {
        display: block !important;
        border: 0;
        padding: 0;
    }

    .zx-def-table td:first-child {
        font-size: 0.75rem;
        color: var(--mud-palette-text-secondary);
    }

    /* .zx-card-table — a list of records. Each row becomes a card and each
       cell carries its own label via data-label, so the header row can go.
       The first cell is the card's title: no label, its own line. Cells with
       nothing to say on a phone (a per-row "open" button when the whole row
       is already tappable) opt out with .zx-hide-phone. */
    .zx-card-table thead {
        display: none !important;
    }

    .zx-card-table tbody {
        display: block !important;
    }

    .zx-card-table tbody tr {
        display: block !important;
        padding: 0.625rem 0;
        border-bottom: 1px solid var(--mud-palette-lines-default);
    }

    .zx-card-table tbody tr:last-child {
        border-bottom: 0;
    }

    .zx-card-table td {
        display: flex !important;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        border: 0;
        padding: 0.125rem 0;
    }

    /* The !important above outranks .zx-hide-phone (0,1,0), which would
       otherwise silently stop hiding the cells that opt out of the phone
       view — a per-row "open" button when the whole row is already tappable.
       These put the opt-out back on top at (0,2,1). */
    .zx-card-table td.zx-hide-phone,
    .zx-def-table td.zx-hide-phone {
        display: none !important;
    }

    .zx-card-table td::before {
        content: attr(data-label);
        flex: 0 0 auto;
        font-size: 0.75rem;
        color: var(--mud-palette-text-secondary);
    }

    .zx-card-table td:first-child {
        display: block !important;
        font-weight: 500;
        padding-bottom: 0.25rem;
    }

    .zx-card-table td:first-child::before {
        content: none;
    }

    /* Dialogs become full-screen sheets: title pinned, body scrolls, actions
       pinned above the home indicator. */
    .mud-dialog-container .mud-dialog {
        width: 100vw !important;
        max-width: 100vw !important;
        height: 100dvh !important;
        max-height: 100dvh !important;
        margin: 0;
        border-radius: 0;
        display: flex;
        flex-direction: column;
    }

    .mud-dialog-container .mud-dialog .mud-dialog-content {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        max-height: none;
    }

    .mud-dialog-container .mud-dialog .mud-dialog-actions {
        flex: 0 0 auto;
        flex-wrap: wrap;
        padding-bottom: max(0.5rem, env(safe-area-inset-bottom));
    }

    /* iOS zooms any focused input under 16px; hold phone inputs at 16px. */
    .mud-input input,
    .mud-input textarea,
    .form-control {
        font-size: 16px !important;
    }
}
