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

html {
    height: 100%;
}

body {
    background: var(--surface-canvas);
    color: var(--text-body);
    font-family: var(--font-sans);
    font-size: var(--text-base);
    line-height: var(--leading-normal);
    margin: 0;
    min-height: 100%;
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4 {
    color: var(--text-strong);
    font-family: var(--font-display);
    font-weight: var(--type-heading-weight);
    letter-spacing: var(--tracking-snug);
    line-height: var(--leading-tight);
    margin: 0;
}

h1:focus {
    outline: none;
}

a {
    color: var(--text-link);
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

::selection {
    background: var(--amber-400);
    color: var(--navy-900);
}

/* ==== Shared UI primitives (used across pages) ============================ */

/* Between the top bar and a page's first content stands the content area's
   padding and nothing else: whatever a page opens with - a paragraph, a
   filter bar - brings no margin of its own above it. */
main.content > :first-child {
    margin-top: 0;
}

.page-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    margin-bottom: var(--space-6);
}

.page-head h1 {
    font-size: var(--text-xl);
}

.eyebrow {
    color: var(--amber-600);
    display: block;
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-eyebrow);
    margin-bottom: var(--space-1);
    text-transform: uppercase;
}

.btn-primary {
    background: var(--accent);
    color: var(--accent-contrast);
    border: none;
    border-radius: var(--radius-md);
    padding: 9px 16px;
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
    cursor: pointer;
    display: inline-block;
    transition: background-color var(--duration-fast) var(--ease-standard);
}

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

.btn-primary:disabled {
    opacity: 0.6;
    cursor: default;
}

.btn-primary:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 2px;
}

.btn-secondary {
    background: transparent;
    color: var(--text-strong);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    padding: 9px 16px;
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    font-weight: var(--fw-medium);
    cursor: pointer;
    display: inline-block;
}

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

.btn-secondary:disabled {
    background: transparent;
    cursor: default;
    opacity: 0.6;
}

/* The quiet button beside a primary one: "Abbrechen", "Schließen". */
.btn-ghost {
    background: none;
    border: 0;
    border-radius: var(--radius-md);
    color: var(--text-muted);
    cursor: pointer;
    font: inherit;
    font-size: 13px;
    font-weight: var(--fw-semibold);
    padding: 10px 14px;
}

.btn-ghost:hover {
    background: var(--surface-sunken);
}

.btn-ghost:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 2px;
}

/* The one button for what cannot be taken back - ending an engagement, taking
   a person off a project; always behind a question. */
.btn-danger {
    background: var(--danger-500);
    border: none;
    border-radius: var(--radius-md);
    color: #fff;
    cursor: pointer;
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
    padding: 10px 16px;
}

.btn-danger:hover {
    background: var(--danger-600);
}

.btn-danger:disabled {
    cursor: default;
    opacity: 0.6;
}

.btn-small {
    font-size: var(--text-xs);
    padding: 6px 10px;
}

/* Stat tiles: a number in the display weight with its caption, tinted by tone;
   the start page and the readiness page share them. */
.start-cards {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    margin-top: var(--space-6);
}

.start-card {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    color: var(--text-strong);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 14rem;
    padding: var(--space-5) var(--space-6);
    text-decoration: none;
}

.start-card:hover {
    border-color: var(--border-default);
    box-shadow: var(--shadow-md);
    text-decoration: none;
}

.start-card-number {
    color: var(--text-strong);
    font-size: var(--text-3xl);
    font-weight: var(--type-display-weight);
    letter-spacing: var(--tracking-tight);
    line-height: var(--leading-tight);
}

.start-card-number.ok { color: var(--success-text); }
.start-card-number.warning { color: var(--warning-text); }
.start-card-number.danger { color: var(--danger-text); }
.start-card-number.info { color: var(--navy-700); }

.start-card-caption {
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.start-card .badge {
    align-self: flex-start;
    margin-top: var(--space-2);
}

/* A number that opens its detail: styled as the link it behaves like. */
.btn-link {
    background: none;
    border: 0;
    padding: 0;
    color: var(--text-strong);
    font-family: var(--font-sans);
    font-size: inherit;
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

.readiness {
    margin-top: 4px;
}

/* The contact block of a project, opened beneath its row. Built for a phone
   in a hand on a site: entries wrap, and every call or mail action is a tap
   target of at least 44px in both directions. */
.row-detail td {
    background: var(--surface-sunken);
    padding: var(--space-3) var(--space-4);
}

.contacts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4) var(--space-8);
}

.contacts-group {
    min-width: 14rem;
    flex: 1 1 14rem;
}

.contacts-heading {
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    margin: 0 0 var(--space-2);
}

.contacts-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.contact {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1) var(--space-3);
    padding: var(--space-1) 0;
}

.contact-who {
    display: flex;
    flex-direction: column;
    min-width: 10rem;
}

.contact-name {
    color: var(--text-strong);
    font-weight: var(--fw-semibold);
}

.contact-company {
    color: var(--text-muted);
    font-size: var(--text-xs);
}

.contact-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

.contact-action {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    min-width: 44px;
    padding: 0 var(--space-3);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    background: var(--surface-card);
    color: var(--text-strong);
    font-size: var(--text-sm);
    text-decoration: none;
    white-space: nowrap;
}

.contact-action:hover {
    background: var(--surface-sunken);
}

.contact-none {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
}

a.btn-primary,
a.btn-secondary {
    text-decoration: none;
}

/* The status pill, the design's signature: a soft fill in the tone's color
   and, for the three states plus "in review", the tone's glyph in a small
   solid circle before the text - check, exclamation, cross, ellipsis.
   Neutral badges carry no glyph; a badge that names a category rather than a
   state (badge-plain) drops it too. */
.badge {
    align-items: center;
    border-radius: var(--radius-pill);
    display: inline-flex;
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    gap: 6px;
    letter-spacing: var(--tracking-snug);
    line-height: 1.25;
    padding: 3px 10px;
    white-space: nowrap;
}

.badge-pending,
.badge-accepted,
.badge-info,
.badge-danger {
    padding-left: 6px;
}

.badge-pending::before,
.badge-accepted::before,
.badge-info::before,
.badge-danger::before {
    align-items: center;
    border-radius: 50%;
    color: var(--white);
    display: inline-flex;
    flex: none;
    font-size: 9px;
    font-weight: var(--fw-bold);
    height: 15px;
    justify-content: center;
    line-height: 1;
    width: 15px;
}

.badge-pending {
    background: var(--warning-100);
    color: var(--warning-text);
}

.badge-pending::before {
    background: var(--warning-500);
    content: "!";
}

.badge-accepted {
    background: var(--success-100);
    color: var(--success-text);
}

.badge-accepted::before {
    background: var(--success-500);
    content: "\2713";
}

.badge-info {
    background: var(--info-100);
    color: var(--info-text);
}

.badge-info::before {
    background: var(--info-500);
    content: "\22EF";
}

.badge-danger {
    background: var(--danger-100);
    color: var(--danger-text);
}

.badge-danger::before {
    background: var(--danger-500);
    content: "\2715";
}

.badge-neutral,
.badge-revoked {
    background: var(--gray-100);
    color: var(--gray-600);
}

.badge-plain {
    padding-left: 10px;
}

.badge-plain::before {
    content: none;
}

/* "Neu" beside a project the firm's administration has not opened yet (NP,
   N1): a small amber pill in capitals, set off from the status badges. */
.new-marker {
    background: var(--amber-500);
    border-radius: var(--radius-pill);
    color: var(--navy-900);
    display: inline-block;
    font-size: 10px;
    font-weight: var(--fw-semibold);
    letter-spacing: .06em;
    line-height: 1.4;
    margin-left: var(--space-2);
    padding: 2px 8px;
    text-transform: uppercase;
    vertical-align: middle;
    white-space: nowrap;
}

/* ==== Auswahlfelder =====================================================
   Every select the app draws, dialogs included: the design system's field
   with its own chevron. The browser's native control wears the operating
   system, which is the one look a design system may not borrow - so the
   native arrow goes and a drawn one takes its place. */
select {
    appearance: none;
    background-color: var(--surface-card);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%236b7484' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-position: right 8px center;
    background-repeat: no-repeat;
    background-size: 14px 14px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    color: var(--text-strong);
    cursor: pointer;
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    line-height: 1.3;
    padding: 7px 28px 7px 10px;
}

select:hover:not(:disabled) {
    border-color: var(--border-strong);
}

select:focus-visible {
    border-color: var(--border-focus);
    box-shadow: 0 0 0 3px var(--ring);
    outline: none;
}

select:disabled {
    background-color: var(--surface-sunken);
    color: var(--text-muted);
    cursor: not-allowed;
}

/* ==== Native controls the app does not draw itself ======================
   A textarea, a number field, a text, phone, e-mail, web address, password or
   date field, a checkbox, a radio, a file picker and a search box that carry no
   class of their own wear the design's dress instead of the browser's. Everything here
   is wrapped in :where(), so it weighs nothing: a dialog's field rule, a
   component's own class, any later rule wins over it. */
:root {
    accent-color: var(--navy-900);
}

/* A text, phone, e-mail, web address, password or date field without a class
   of its own; the marks an EditForm sets on its inputs (valid, invalid,
   modified) are no class of the field's. A field with a class - the date
   field, the catalog's position, the sign-in, the searches - is drawn by that
   class alone. Border, radius, padding and height are a dialog's field
   (INGO-301): the browser keeps its line height, and 9 px above and below
   make the field as tall as one in "Person hinzufügen". */
:where(input:is(:not([type]), [type="text"], [type="tel"], [type="email"], [type="url"], [type="password"], [type="date"]):is(:not([class]), [class=""], [class="valid"], [class="invalid"], [class="modified valid"], [class="modified invalid"])) {
    background-color: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    color: var(--text-strong);
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    padding: 9px 10px;
}

:where(input:is(:not([type]), [type="text"], [type="tel"], [type="email"], [type="url"], [type="password"], [type="date"]):is(:not([class]), [class=""], [class="valid"], [class="invalid"], [class="modified valid"], [class="modified invalid"])):where(:hover:not(:disabled)) {
    border-color: var(--border-strong);
}

:where(input:is(:not([type]), [type="text"], [type="tel"], [type="email"], [type="url"], [type="password"], [type="date"]):is(:not([class]), [class=""], [class="valid"], [class="invalid"], [class="modified valid"], [class="modified invalid"])):where(:focus-visible) {
    border-color: var(--border-focus);
    box-shadow: 0 0 0 3px var(--ring);
    outline: none;
}

:where(input:is(:not([type]), [type="text"], [type="tel"], [type="email"], [type="url"], [type="password"], [type="date"]):is(:not([class]), [class=""], [class="valid"], [class="invalid"], [class="modified valid"], [class="modified invalid"])):where(:disabled) {
    background-color: var(--surface-sunken);
    color: var(--text-muted);
    cursor: not-allowed;
}

:where(textarea, input[type="number"]) {
    background-color: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    color: var(--text-strong);
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    line-height: 1.3;
    padding: 7px 10px;
}

:where(textarea) {
    min-height: 4.5rem;
    resize: vertical;
}

:where(textarea, input[type="number"]):where(:hover:not(:disabled)) {
    border-color: var(--border-strong);
}

:where(textarea, input[type="number"]):where(:focus-visible) {
    border-color: var(--border-focus);
    box-shadow: 0 0 0 3px var(--ring);
    outline: none;
}

:where(textarea, input[type="number"]):where(:disabled) {
    background-color: var(--surface-sunken);
    color: var(--text-muted);
    cursor: not-allowed;
}

/* The stepper arrows are the operating system's; the field is typed into. */
:where(input[type="number"]) {
    -moz-appearance: textfield;
    appearance: textfield;
}

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}

:where(input[type="checkbox"], input[type="radio"]):where(:focus-visible) {
    outline: 2px solid var(--border-focus);
    outline-offset: 2px;
}

/* The file picker's button in the secondary button's dress; what it says
   ("Choose file") is the browser's language and stays so. */
:where(input[type="file"]) {
    color: var(--text-muted);
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    max-width: 100%;
}

:where(input[type="file"])::file-selector-button {
    background: transparent;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    color: var(--text-strong);
    cursor: pointer;
    font: inherit;
    font-weight: var(--fw-medium);
    margin-right: var(--space-3);
    padding: 7px 14px;
}

:where(input[type="file"])::file-selector-button:hover {
    background: var(--surface-sunken);
}

:where(input[type="file"]:disabled)::file-selector-button {
    cursor: not-allowed;
    opacity: 0.6;
}

/* A search box is a field like the others: no system chrome of its own, and
   its clear button drawn like the select's chevron. */
:where(input[type="search"]) {
    -webkit-appearance: none;
    appearance: none;
}

input[type="search"]::-webkit-search-decoration {
    -webkit-appearance: none;
    appearance: none;
}

input[type="search"]::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%236b7484' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18'/%3E%3Cpath d='m6 6 12 12'/%3E%3C/svg%3E") center / 14px 14px no-repeat;
    cursor: pointer;
    height: 18px;
    margin-left: var(--space-1);
    width: 18px;
}

/* A name and the badge that qualifies it, on one line with a gap between
   them - Razor eats the whitespace between an expression and the block
   after it, so the space has to be laid out, not typed. */
.cell-line {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* The card a list sits in, and the one thing that may move sideways. A
   list wider than its place scrolls here; the page behind it stays where
   it is. The edge belongs to this box rather than to the table, so the
   rounding travels with what scrolls. */
.table-scroll {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    max-width: 100%;
    overflow-x: auto;
}

/* A list in a card that runs it to its edges (the company profile's tabs):
   the card draws the edge, so the list draws none of its own. */
.panel-flush > .table-scroll {
    border: 0;
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    box-shadow: none;
}

.data-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
}

.data-table th {
    text-align: left;
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    font-weight: var(--fw-semibold);
    padding: 10px var(--space-4);
    border-bottom: 1px solid var(--border-subtle);
}

.table-scroll .data-table th {
    white-space: nowrap;
}

/* A header that sorts is a th that can be pressed. It keeps the padding the
   table (or the page's own rule) gives it, so it takes no more room than a
   plain header does: the arrow stands in the cell's right-hand padding, and
   an overlay makes the whole cell the thing to click and to focus. The arrow
   is faint until the header is hovered or focused, and full once the list
   stands in that order. */
.data-table th.sortable {
    position: relative;
}

.sort-button {
    display: inline-flex;
    align-items: center;
    padding: 0;
    background: none;
    border: 0;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    text-align: inherit;
    color: inherit;
    cursor: pointer;
}

.sort-button::after {
    content: "";
    position: absolute;
    inset: 0;
}

.sort-button:focus-visible {
    outline: none;
}

.sort-button:focus-visible::after {
    outline: 2px solid var(--border-focus);
    outline-offset: -2px;
}

.sort-button:hover {
    color: var(--text-strong);
}

.sort-mark {
    position: absolute;
    top: 50%;
    right: 2px;
    display: inline-flex;
    transform: translateY(-50%);
    opacity: 0.4;
}

.sort-button:hover .sort-mark,
.sort-button:focus-visible .sort-mark {
    opacity: 0.9;
}

.data-table th[aria-sort] .sort-button {
    color: var(--text-strong);
}

.data-table th[aria-sort] .sort-mark {
    opacity: 1;
}

/* Where a list stands as cards there is no header to press, so the same
   choice is a field - and only there. */
.sort-picker {
    display: none;
    align-items: flex-end;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.sort-picker-field {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: var(--space-1);
    font-size: var(--text-2xs);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--text-muted);
}

.sort-picker-field select {
    width: 100%;
    text-transform: none;
    letter-spacing: normal;
}

@media (max-width: 40rem) {
    .sort-picker {
        display: flex;
    }
}

/* Said to a screen reader, never drawn. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.data-table td {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border-subtle);
    font-size: 13.5px;
}

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

/* A white card on the canvas and a label/value list inside it. Pages set these
   classes themselves, so the base lives here; a component that draws them
   differently - the company profile's three columns of facts - keeps its
   variant beside its markup. */
.panel {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    padding: var(--space-5) var(--space-6);
}

.panel .data-table {
    border: none;
    box-shadow: none;
}

.panel-title {
    color: var(--text-strong);
    font-size: 15px;
    font-weight: var(--fw-semibold);
    margin: 0 0 14px;
}

.facts {
    display: grid;
    gap: var(--space-2) var(--space-5);
    grid-template-columns: max-content 1fr;
    margin: 0;
}

.facts dt {
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.facts dd {
    color: var(--text-strong);
    font-size: var(--text-sm);
    margin: 0;
}

.facts dd .cell-sub {
    display: block;
}

@media (max-width: 40rem) {
    .panel {
        padding: var(--space-4);
    }

    .facts {
        gap: 4px;
        grid-template-columns: minmax(0, 1fr);
    }

    .facts dt:not(:first-child) {
        margin-top: 12px;
    }

    .facts dd {
        overflow-wrap: anywhere;
    }
}

/* Under 640 px a list may stand as cards instead of a table: the same
   rows, with what matters in the first line rather than beyond the
   window's edge. The table and the cards are both rendered; the window
   decides which one shows, so nothing is measured in the circuit. A list
   without a card template has no .card-list and stays a table. */
.card-list {
    display: none;
    list-style: none;
    margin: 0;
    padding: 0;
}

@media (max-width: 40rem) {
    .paged-list-cards > .table-scroll {
        display: none;
    }

    .paged-list-cards > .card-list {
        display: flex;
        flex-direction: column;
        gap: var(--space-2);
    }
}

/* One card, whatever element carries it: a link or a button where the row
   is the way in, a plain box where the actions sit inside. The whole card
   is the surface to tap, so it is never shorter than a finger. */
.list-card {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xs);
    box-sizing: border-box;
    display: block;
    min-height: 44px;
    padding: var(--space-3) var(--space-4);
    width: 100%;
}

a.list-card,
button.list-card {
    color: inherit;
    cursor: pointer;
    font: inherit;
    text-align: left;
    text-decoration: none;
}

a.list-card:hover,
button.list-card:hover {
    background: var(--gray-50);
    border-color: var(--border-default);
}

/* Name and status share the first line; what qualifies them follows in
   smaller type. Spans, because a button may hold nothing else. */
.list-card-head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    justify-content: space-between;
}

.list-card-title {
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
}

.list-card-sub {
    color: var(--text-muted);
    display: block;
    font-size: var(--text-xs);
    margin-top: var(--space-1);
}

.list-card-meta {
    align-items: center;
    color: var(--text-muted);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--text-xs);
    gap: var(--space-1) var(--space-3);
    margin-top: var(--space-2);
}

.list-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-3);
}

.card-group {
    color: var(--text-muted);
    font-size: var(--text-2xs);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-eyebrow);
    padding: var(--space-2) var(--space-1) 0;
    text-transform: uppercase;
}

.card-list-empty {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-4);
}

/* Search, whatever the page puts beside it, and the count. On a narrow
   screen they stand under one another rather than pushing the page out:
   the count keeps its own line, which is the only thing it needs. */
.search-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-bottom: 14px;
}

.search-input {
    flex: 0 1 220px;
    min-width: 12rem;
    padding: 8px 12px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    font-family: var(--font-sans);
    font-size: var(--text-sm);
}

.search-input:focus {
    outline: none;
    border-color: var(--amber-500);
    box-shadow: 0 0 0 3px var(--ring);
}

@media (max-width: 640px) {
    .search-row .search-input {
        flex: 1 1 100%;
        min-width: 0;
        width: 100%;
    }
}

.empty-note {
    color: var(--text-muted);
    max-width: 46rem;
}

.cell-strong {
    color: var(--text-strong);
    font-weight: var(--fw-semibold);
}

.cell-sub {
    color: var(--text-muted);
    font-size: var(--text-xs);
}

.cell-mono {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
}

.type-tag {
    background: var(--surface-sunken);
    border-radius: var(--radius-pill);
    color: var(--text-muted);
    font-size: var(--text-2xs);
    font-weight: var(--fw-medium);
    margin-left: var(--space-1);
    padding: 1px 8px;
    vertical-align: middle;
}

/* Modal - always centered in the viewport, never top-docked. A dialog is
   drawn where it is opened - in a table cell, in a row's menu - and would
   inherit that place's wrapping, alignment and type; it starts from the
   page's own text values instead, so it reads the same wherever it opens. */
.overlay {
    position: fixed;
    inset: 0;
    background: rgba(18, 22, 31, 0.45);
    z-index: var(--z-overlay);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;
    overflow-y: auto;
    color: var(--text-body);
    cursor: auto;
    font-family: var(--font-sans);
    font-size: var(--text-base);
    font-style: normal;
    font-weight: var(--fw-regular);
    letter-spacing: normal;
    line-height: var(--leading-normal);
    text-align: left;
    text-transform: none;
    white-space: normal;
}

.modal {
    background: var(--surface-card);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xl);
    max-height: 90vh;
    overflow-y: auto;
    width: 100%;
    max-width: 560px;
    padding: var(--space-6);
}

.modal-wide {
    max-width: 720px;
}

/* On a phone the dialog takes the window's width: a gutter of a few pixels,
   and nothing inside it wider than the window. */
@media (max-width: 40rem) {
    .overlay {
        padding: 12px 8px;
    }

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

    .modal .table-scroll,
    .modal .data-table {
        max-width: 100%;
    }
}

/* A row that is the way into what it names says so under the pointer. The
   controls inside keep their own cursor and stop the click themselves. */
.row-link {
    cursor: pointer;
}

.row-link:hover {
    background: var(--gray-50);
}

/* An evidence row is a click target (E-227): its name is the keyboard's way
   to the view the row opens, and reads as the name, not as a link. */
.evidence-name {
    background: none;
    border: 0;
    color: inherit;
    cursor: pointer;
    font: inherit;
    font-weight: inherit;
    padding: 0;
    text-align: left;
}

.evidence-name:hover:not(:disabled) {
    text-decoration: underline;
}

.evidence-name:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 2px;
}

/* The review mask: document and decision side by side need the room. */
.modal-review {
    max-width: 1200px;
}

/* The dialog holds the focus while it is open, so Escape reaches it; the
   ring stays on the controls inside, not on the box. */
.modal:focus {
    outline: none;
}

.modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-4);
}

.modal-head h2 {
    font-size: var(--text-md);
}

.modal-close {
    background: none;
    border: none;
    font-size: var(--text-base);
    cursor: pointer;
    color: var(--text-muted);
    text-decoration: none;
}

.modal-intro {
    color: var(--text-muted);
    font-size: var(--text-sm);
    margin: 0 0 var(--space-4);
}

.modal-section {
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
    margin: var(--space-5) 0 var(--space-3);
}

.modal label,
.settings-section label {
    display: block;
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
    color: var(--text-strong);
    margin-bottom: var(--space-4);
}

/* A radio is a choice laid out in a row beside its text, never a field: the
   :where() keeps these selectors as heavy as they were. */
.modal input:not([type="checkbox"]):where(:not([type="radio"])),
.modal select,
.modal textarea,
.settings-section input:where(:not([type="radio"])),
.settings-section textarea {
    display: block;
    width: 100%;
    box-sizing: border-box;
    margin-top: var(--space-1);
    padding: 9px 10px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    /* The colour only - the shorthand would drop the chevron the select
       draws for itself. */
    background-color: var(--surface-card);
}

.modal select {
    padding-right: 28px;
}

.modal textarea,
.settings-section textarea {
    min-height: 5.5rem;
    resize: vertical;
}

.modal input:focus,
.modal select:focus,
.modal textarea:focus,
.settings-section input:focus,
.settings-section textarea:focus {
    outline: none;
    border-color: var(--amber-500);
    box-shadow: 0 0 0 3px var(--ring);
}

/* A checkbox or radio has no field around it to ring: it takes the focus as
   an outline, and only when the keyboard put it there. */
.modal input:is([type="checkbox"], [type="radio"]):focus,
.settings-section input:is([type="checkbox"], [type="radio"]):focus {
    box-shadow: none;
}

.modal input:is([type="checkbox"], [type="radio"]):focus-visible,
.settings-section input:is([type="checkbox"], [type="radio"]):focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 2px;
}

/* A section of the settings page: the dialog's fields, side by side where
   the window allows. */
.settings-section {
    margin-bottom: var(--space-6);
}

.settings-fields {
    display: grid;
    gap: 0 var(--space-4);
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

/* A count of days or the like needs no full row. */
.settings-section input[type="number"] {
    max-width: 220px;
}

.checkbox-label {
    align-items: center;
    display: flex;
    font-weight: var(--fw-regular);
    gap: var(--space-2);
}

.modal-error {
    color: var(--danger-text);
    font-size: var(--text-sm);
    margin: 0 0 var(--space-3);
}

/* An error line inside a row of controls: a line of its own, no margin. */
.modal-error-inline {
    flex-basis: 100%;
    margin: 0;
}

.modal-note {
    color: var(--text-muted);
    font-size: var(--text-sm);
    margin: 0 0 var(--space-3);
}

/* A question that says what an action does, in blocks rather than one run of
   text (E-233): the lead sentence, the firms concerned in a grey box, what
   follows - lost (x) or kept (check) - and, where it cannot be undone, the
   warning in red above the buttons. */
.dialog-lead {
    color: var(--text-body);
    font-size: var(--text-sm);
    line-height: 1.5;
    margin: 0 0 var(--space-4);
}

.dialog-heading {
    color: var(--text-strong);
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
    margin: 0 0 var(--space-2);
}

.dialog-box {
    background: var(--surface-sunken);
    border-radius: var(--radius-md);
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
}

.dialog-box-list,
.dialog-effects {
    display: flex;
    flex-direction: column;
    font-size: var(--text-sm);
    gap: var(--space-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

.dialog-effects {
    margin-bottom: var(--space-4);
}

.dialog-effect {
    align-items: flex-start;
    display: flex;
    gap: var(--space-2);
    line-height: 1.5;
}

.dialog-effect .icon {
    flex: none;
    margin-top: 2px;
}

.dialog-effect-lost .icon {
    color: var(--danger-500);
}

.dialog-effect-kept .icon {
    color: var(--success-500);
}

.dialog-list {
    font-size: var(--text-sm);
    line-height: 1.5;
    margin: 0 0 var(--space-4);
    padding-left: 20px;
}

.dialog-warning {
    align-items: center;
    color: var(--danger-text);
    display: flex;
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
    gap: var(--space-2);
    margin: 0 0 var(--space-3);
}

.dialog-warning .icon {
    flex: none;
}

/* A caution or an empty-state line inside a panel, in the warning tone. In
   the global sheet because it is used by more than one component: a scoped
   rule reaches only the elements of the component that owns it. */
.panel-note {
    color: var(--warning-text);
    font-size: var(--text-sm);
    margin: 0;
}

/* When a site starts or runs out, in the design's mono chip (G1). In the
   global sheet because the project list and the start page's alarms both
   draw it. */
.countdown {
    border-radius: var(--radius-sm);
    display: inline-block;
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: var(--fw-semibold);
    font-variant-numeric: tabular-nums;
    padding: 4px 8px;
    white-space: nowrap;
}

.countdown-neutral {
    background: var(--gray-100);
    color: var(--gray-600);
}

.countdown-warning {
    background: var(--warning-100);
    color: var(--warning-text);
}

.countdown-danger {
    background: var(--danger-100);
    color: var(--danger-text);
}

/* The two ways a dialog can offer: keep it yourself, or invite whoever it is
   about to keep it themselves. Shared, because every add dialog asks it. */
/* "Anlegen · Einladen" at the top of the add dialogs (DS27 G4, G8). */
.add-mode { margin-bottom: var(--space-2); }
.add-mode-note { margin: 0 0 var(--space-4); }

.choice-cards {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
}

/* Three ways in rather than two: the same cards, one column more, and on a
   narrow screen they stack like everything else. */
.choice-cards-three {
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}

.choice-card {
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-5);
    position: relative;
}

.choice-card h3 {
    font-size: 19px;
    font-weight: var(--fw-medium);
    margin: 0;
}

/* The way's sign in a quiet circle over its title (G4, G8). */
.choice-icon {
    align-items: center;
    background: var(--gray-100);
    border-radius: 50%;
    color: var(--gray-600);
    display: inline-flex;
    height: 56px;
    justify-content: center;
    width: 56px;
}

/* A way's one button spans the card. */
.choice-card > .btn-primary,
.choice-card > .btn-secondary,
.choice-card > button {
    width: 100%;
}

.choice-card p {
    color: var(--text-muted);
    flex: 1;
    font-size: var(--text-sm);
    margin: 0;
}

/* The recommended way: the same white card, marked by its amber edge and the dark badge on it. */
.choice-card-primary {
    border: 2px solid var(--amber-400);
}

.choice-badge {
    background: var(--navy-900);
    border-radius: var(--radius-pill);
    color: var(--amber-300);
    font-size: 10.5px;
    font-weight: var(--fw-semibold);
    left: var(--space-5);
    letter-spacing: 0.06em;
    padding: 4px 12px;
    position: absolute;
    text-transform: uppercase;
    top: -12px;
}

@media (max-width: 40rem) {
    .choice-cards {
        grid-template-columns: 1fr;
    }
}

.modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    margin-top: var(--space-2);
}

.toast {
    background: var(--navy-900);
    border-radius: var(--radius-md);
    bottom: var(--space-6);
    box-shadow: var(--shadow-lg);
    color: var(--text-on-dark);
    font-size: var(--text-sm);
    left: 50%;
    padding: 10px 18px;
    position: fixed;
    transform: translateX(-50%);
    z-index: var(--z-modal);
}

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

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

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

.blazor-error-boundary {
    background: var(--danger-600);
    border-radius: var(--radius-sm);
    color: var(--white);
    padding: 1rem;
}

    .blazor-error-boundary::after {
        content: "Ein Fehler ist aufgetreten."
    }

/* The trade of a firm, chosen in its row: the field of the design system at
   list size, and capped, so a long trade name cannot take the width the
   firm's own name needs. */
.trade-select {
    background-position: right 5px center;
    font-size: var(--text-xs);
    max-width: 9.5rem;
    padding: 4px 22px 4px 8px;
}

.pager {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-3);
}

.pager-position {
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-variant-numeric: tabular-nums;
}

/* The list's filters, followed by its search. Page-level actions may have
   their own row above this one; controls inside the filter row wrap together. */
.hero-row {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4) var(--space-6);
    justify-content: space-between;
    margin-bottom: var(--space-5);
}

.hero-row .segments {
    margin-bottom: 0;
}

/* A row's action in words - "Zu den Firmendetails", "Pausieren" - in the
   link colour, never a framed button inside a table row. */
.detail-link {
    background: none;
    border: none;
    color: var(--text-link);
    cursor: pointer;
    font-family: var(--font-sans);
    font-size: 12.5px;
    font-weight: var(--fw-semibold);
    padding: 0;
    text-decoration: none;
    white-space: nowrap;
}

.detail-link:hover {
    color: var(--accent-hover);
    text-decoration: underline;
}

.detail-link:disabled {
    cursor: default;
    opacity: 0.6;
}

/* An entry of the account menu in the sidebar's foot. Global rather than
   scoped to the layout: entries that are NavLinks render their anchor in a
   child component, which the layout's scoped styles do not reach. */
.user-menu-item {
    border-radius: var(--radius-sm);
    color: var(--navy-200);
    display: block;
    font-size: var(--text-xs);
    font-weight: var(--fw-medium);
    padding: 9px 12px;
    text-decoration: none;
    white-space: nowrap;
}

.user-menu-item:hover,
.user-menu-item:focus-visible {
    background: rgb(255 255 255 / 6%);
    color: var(--text-on-dark);
    text-decoration: none;
}

/* The way into a row's details: an arrow at the row's end, no words. The
   whole row opens the same page; the arrow is its keyboard stop and names
   itself through its label. */
.row-arrow {
    align-items: center;
    border-radius: var(--radius-sm);
    color: var(--text-subtle);
    display: inline-flex;
    justify-content: center;
    padding: 2px;
}

.row-link:hover .row-arrow,
.row-arrow:hover,
.row-arrow:focus-visible {
    color: var(--text-strong);
}

.hero-actions {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-left: auto;
}

/* Beneath the hero: the search on the left, how many of how many on the right. */
.toolbar {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-bottom: 14px;
}

.toolbar .search-row {
    flex: 1;
    margin-bottom: 0;
}

/* The filter row above a list: the pill group of segments on the left, any
   further filter on the right. */
.filter-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

/* One pill group: the active segment is filled navy, the others sit quietly
   inside the same rounded container. */
.segments {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-pill);
    padding: 4px;
    max-width: 100%;
    overflow-x: auto;
    margin-bottom: var(--space-4);
}

.filter-row .segments {
    margin-bottom: 0;
}

.segment {
    border: none;
    background: transparent;
    border-radius: var(--radius-pill);
    color: var(--gray-600);
    cursor: pointer;
    flex: none;
    font-family: var(--font-sans);
    font-size: 12.5px;
    font-weight: var(--fw-semibold);
    padding: 8px 16px;
    white-space: nowrap;
}

.segment:hover {
    color: var(--text-strong);
}

.segment-active,
.segment-active:hover {
    background: var(--navy-900);
    color: var(--white);
}

.segment-count {
    font-variant-numeric: tabular-nums;
    margin-left: 2px;
}

.segment-filter {
    margin-left: auto;
}

/* A filter that switches on beside the segments and combines with them -
   "Einladung offen" in the contractor's firm list. */
.filter-chip {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-pill);
    color: var(--gray-600);
    cursor: pointer;
    font-family: var(--font-sans);
    font-size: 12.5px;
    font-weight: var(--fw-semibold);
    padding: 7px 15px;
    white-space: nowrap;
}

.filter-chip:hover {
    color: var(--text-strong);
}

.filter-chip-on,
.filter-chip-on:hover {
    background: var(--navy-900);
    border-color: var(--navy-900);
    color: var(--white);
}

/* Where a firm's invitation stands, in its row: registered, open since a day, or run out since one. */
.invitation-state {
    font-size: var(--text-xs);
    margin-right: var(--space-2);
}

.invitation-open {
    color: var(--warning-600);
    font-weight: var(--fw-semibold);
}

.invitation-expired {
    color: var(--danger-text);
    font-weight: var(--fw-semibold);
}

/* The principal's list has no invitation column: the state stands beneath the firm. */
.company-invitation-under {
    margin-top: var(--space-1);
}

/* A status dot before a name: the row's tone at a glance. */
.dot {
    border-radius: 50%;
    display: inline-block;
    flex: none;
    height: 7px;
    margin-right: 9px;
    vertical-align: middle;
    width: 7px;
}

.dot-ok { background: var(--success-500); }
.dot-warning { background: var(--warning-500); }
.dot-danger { background: var(--danger-500); }
.dot-neutral { background: var(--gray-300); }

/* A satisfied-over-required ratio: colored digits in mono, not a pill. */
.ratio {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.ratio-ok { color: var(--success-text); }
.ratio-warning { color: var(--warning-text); }
.ratio-danger { color: var(--danger-text); }

/* A ratio with a tooltip behind it says so with a dotted line, as the design draws it. */
.ratio[title] {
    border-bottom: 1px dotted currentColor;
    cursor: help;
}

/* The empty state stays inside the table's card. */
.data-table .empty-row td {
    color: var(--text-muted);
    padding: 36px var(--space-4);
    text-align: center;
}

.data-table .empty-row .empty-note {
    margin: 0 auto;
}

/* A picker is one field (E-238): typing shows the hits beneath it, a click or
   Enter takes one. The hits float: wwwroot/js/picker.js places them fixed
   under the field, so they cover what follows instead of pushing it, and a
   dialog's scrolling box does not clip them. Inside a label they keep their
   own type, whatever the label's. */
.picker {
    min-width: 0;
    position: relative;
}

.picker-field {
    position: relative;
}

.picker input.picker-input {
    background-color: var(--surface-card);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7484' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-position: right 10px center;
    background-repeat: no-repeat;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    box-sizing: border-box;
    color: var(--text-strong);
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    font-weight: var(--fw-regular);
    letter-spacing: normal;
    padding: 8px 32px 8px 12px;
    text-overflow: ellipsis;
    text-transform: none;
    width: 100%;
}

/* With a choice that can go, the cross stands where the arrow stood. */
.picker input.picker-input[data-clearable] {
    background-image: none;
}

.picker input.picker-input:focus {
    border-color: var(--amber-500);
    box-shadow: 0 0 0 3px var(--ring);
    outline: none;
}

.picker input.picker-input::placeholder {
    color: var(--text-subtle);
}

.picker-clear {
    background: none;
    border: 0;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    cursor: pointer;
    font-size: var(--text-xs);
    line-height: 1;
    padding: 6px;
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
}

.picker-clear:hover {
    background: var(--gray-100);
    color: var(--text-strong);
}

.picker-clear:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: 1px;
}

.picker-panel {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    box-sizing: border-box;
    color: var(--text-strong);
    font-size: var(--text-sm);
    font-weight: var(--fw-regular);
    letter-spacing: normal;
    max-height: 18rem;
    overflow-y: auto;
    padding: 4px 0;
    position: fixed;
    text-transform: none;
    z-index: calc(var(--z-modal) + 1);
}

.picker-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.picker-option {
    cursor: pointer;
    overflow-wrap: anywhere;
    padding: 8px 12px;
}

.picker-option:hover,
.picker-option.active {
    background: var(--gray-50);
}

.picker-option.active {
    box-shadow: inset 3px 0 0 var(--amber-500);
}

.picker-option.chosen {
    font-weight: var(--fw-semibold);
}

.picker-note {
    color: var(--text-muted);
    font-size: var(--text-xs);
    margin: 0;
    padding: 8px 12px;
}

.picker-more {
    border-top: 1px solid var(--border-subtle);
    margin-top: 4px;
}

/* A picker that filters a list stands in the filter row like the search beside it. */
.filter-row .picker {
    flex: 0 1 260px;
    min-width: 12rem;
}

.pager-size {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--text-muted);
    font-size: var(--text-xs);
}

/* Which commit is running, in the corner where nobody looks until they need it. */
footer.version {
    margin-top: 2rem;
    padding: 0.5rem 1.5rem;
    font-size: 0.75rem;
    color: #7a828b;
    text-align: right;
}

/* Rights overview: roles across, capabilities down, a dot where the role carries it. */
.role-matrix-role,
.role-matrix-cell {
    text-align: center;
}

.role-matrix td .cell-sub {
    display: block;
}

.role-matrix-granted {
    color: var(--accent);
    font-size: 1.1rem;
}

.role-matrix-absent {
    color: var(--text-muted);
}

/* The bell beside the search: the way to the inbox, with the unread count as a pill. */
.topbar-bell {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-md);
    color: var(--text-muted);
    text-decoration: none;
}

.topbar-bell:hover { background: var(--navy-100); }

.topbar-bell-count {
    position: absolute;
    top: 0;
    right: 0;
    box-sizing: border-box;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    border-radius: var(--radius-pill);
    background: var(--danger-500);
    color: var(--white);
    font-size: 11px;
    font-weight: var(--fw-semibold);
    line-height: 18px;
    text-align: center;
}


/* The notification rules: a kind's lead times stand one under the other,
   each a short number beside its name; a rule that deviates from the
   operator's default says so under the kind. */
/* U19: lead times as chips holding their days. */
.rule-lead-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.rule-lead-chip {
    align-items: center; background: var(--gray-100); border: 1px solid var(--border-subtle); border-radius: var(--radius-pill);
    color: var(--text-muted); display: inline-flex; font-size: 12px; gap: 4px; padding: 2px 10px 2px 4px;
}
.rule-days {
    background: transparent; border: none; font-family: var(--font-mono); font-size: 13px; font-weight: var(--fw-semibold);
    color: var(--text-strong); text-align: right; width: 3.2rem;
}
.rule-days:focus { outline: 2px solid var(--ring); border-radius: var(--radius-sm); box-shadow: none; }
/* A yes/no that takes effect at once, drawn as the design's switch. */
input[type="checkbox"].toggle {
    appearance: none; background: var(--gray-300); border-radius: 999px; cursor: pointer; height: 22px; margin: 0;
    position: relative; transition: background 0.15s; width: 40px;
}
input[type="checkbox"].toggle::after {
    background: #fff; border-radius: 50%; box-shadow: var(--shadow-sm); content: ""; height: 18px; left: 2px;
    position: absolute; top: 2px; transition: transform 0.15s; width: 18px;
}
input[type="checkbox"].toggle:checked { background: var(--success-500); }
input[type="checkbox"].toggle:checked::after { transform: translateX(18px); }
input[type="checkbox"].toggle:disabled { cursor: default; opacity: 0.6; }
input[type="checkbox"].toggle:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.rule-reset { white-space: nowrap; }


/* The site channel: the Bauleitung's shell and its screens.

   Built for a phone held at a gate - 390px wide, one column, nothing that
   needs a second hand. Every tappable thing is at least 44px high and no
   type falls under 11px; both are audit fixes the B kit carries (S-02,
   S-15) and both are cheaper to keep than to retrofit. Colours, spacing and
   type come from the tokens, never as literals. */

/* The screen is fixed and only its middle scrolls, the way the kit builds
   the phone: the bar that says where you are and the bar that takes you
   somewhere else both have to stay put. A tab bar you scroll to is not a
   tab bar. */
.site-shell {
    background: var(--surface-canvas);
    display: flex;
    flex-direction: column;
    height: 100dvh;
    margin: 0 auto;
    max-width: 30rem;
    overflow: hidden;
}

.site-topbar {
    align-items: center;
    background: var(--surface-card);
    border-bottom: 1px solid var(--border-subtle);
    display: flex;
    flex: none;
    gap: var(--space-2);
    min-height: 72px;
    padding: var(--space-3) var(--space-4);
    z-index: var(--z-sticky);
}

.site-back {
    align-items: center;
    border-radius: var(--radius-md);
    color: var(--text-strong);
    display: inline-flex;
    flex: none;
    height: 44px;
    justify-content: center;
    margin-left: calc(-1 * var(--space-2));
    width: 44px;
    text-decoration: none;
}

.site-back:hover {
    background: var(--gray-100);
}

.site-topbar-heading {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
}

.site-topbar-eyebrow {
    align-items: center;
    color: var(--text-subtle);
    display: flex;
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: var(--fw-semibold);
    gap: 6px;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.site-topbar-eyebrow .icon {
    flex: none;
}

.site-topbar-title {
    color: var(--text-strong);
    font-size: var(--text-lg);
    font-weight: var(--fw-semibold);
    margin: 0;
    overflow-wrap: anywhere;
}

.site-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: var(--space-4);
}

.site-toolbar {
    background: var(--surface-card);
    border-bottom: 1px solid var(--border-subtle);
    margin: calc(-1 * var(--space-4)) calc(-1 * var(--space-4)) var(--space-3);
    padding: var(--space-3) var(--space-4);
    position: sticky;
    top: calc(-1 * var(--space-4));
    z-index: 1;
}

.site-toolbar .site-search {
    margin-bottom: 0;
}
.site-toolbar .site-chips {
    margin: var(--space-2) 0 0;
}

/* The two ways out of the channel - to the web view, out of the account - as
   buttons, because nothing else on the screen takes the reader out and a
   grey text link went unseen. The row stands on every page; inside a site
   it sits directly above the tab bar, which keeps its place at the very
   bottom. Whichever is last in the shell carries the inset of the home bar. */
.site-foot {
    background: var(--surface-card);
    border-top: 1px solid var(--border-subtle);
    display: flex;
    flex: none;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-4);
}

.site-foot:last-child {
    padding-bottom: max(var(--space-2), env(safe-area-inset-bottom));
}

/* On a person the fixed action carries that inset itself; with the row below
   it, it would leave a gap for a bar that is no longer there. */
.site-shell:has(> .site-foot:last-child) .site-person-actions {
    padding-bottom: var(--space-3);
}

/* Each button takes what its words need and the two share what is left, so
   the longer label never wraps on the narrowest phone while the pair still
   fills the row. */
.site-foot-form {
    display: flex;
    flex: 1 1 auto;
    margin: 0;
}

.site-foot-button {
    align-items: center;
    box-sizing: border-box;
    display: inline-flex;
    flex: 1 1 auto;
    gap: var(--space-2);
    justify-content: center;
    min-height: 44px;
    padding: 0 var(--space-3);
    text-align: center;
}

.site-foot-button .icon {
    flex: none;
}

.site-search {
    margin-bottom: var(--space-4);
}

.site-search-box {
    align-items: center;
    background: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    display: flex;
    gap: var(--space-2);
    min-height: 44px;
    padding: 0 var(--space-3);
}

.site-search-box:focus-within {
    border-color: var(--border-focus);
    outline: 2px solid var(--ring);
    outline-offset: 1px;
}

.site-search-box > .icon {
    color: var(--text-subtle);
    flex: none;
}

.site-search-field {
    background: transparent;
    border: 0;
    color: var(--text-strong);
    flex: 1;
    font: inherit;
    min-width: 0;
    outline: none;
    padding: 0;
}

.site-search-clear {
    align-items: center;
    background: none;
    border: 0;
    color: var(--text-subtle);
    cursor: pointer;
    display: flex;
    flex: none;
    height: 44px;
    justify-content: center;
    padding: 0;
    text-decoration: none;
    width: 32px;
}

.site-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    list-style: none;
    margin: 0;
    padding: 0;
}

.site-card {
    align-items: center;
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    color: var(--text-body);
    display: flex;
    gap: var(--space-3);
    justify-content: space-between;
    min-height: 44px;
    padding: var(--space-4);
}

.site-card:hover {
    border-color: var(--border-strong);
}

.site-card-body {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
}

.site-card-name {
    color: var(--text-strong);
    font-size: var(--text-md);
    font-weight: var(--fw-semibold);
}

/* The site channel's status language: a sign carries the meaning and the
   colour only backs it up, so every state still reads in greyscale, in
   sunlight and for a red-green colour-blind reader. Four classes - in order
   (tick, blue-green), runs out or due (timer, amber), missing or blocked
   (cross, red), cannot be judged (dash, grey). The values are darker than
   the shared status tokens: sign and text share one colour, and the light
   500 tones are too weak for a 2px stroke. The rest of the app keeps its
   tokens; this language is the site channel's. */
:root {
    --site-ok: #0e7490;
    --site-ok-bg: #e6f2f5;
    --site-soon: #98590f;
    --site-soon-bg: #fdf0dd;
    --site-bad: #9e2226;
    --site-bad-bg: #fce7e8;
    --site-np: #6b7280;
    --site-np-bg: #f7f8fa;
    --site-sign-ok: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
    --site-sign-soon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 2h4M12 14l3-3'/%3E%3Ccircle cx='12' cy='14' r='8'/%3E%3C/svg%3E");
    --site-sign-bad: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");
    --site-sign-np: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
}

/* Every status line in the site channel is set in the mono face, uppercase
   and letterspaced - it is the one typographic signal that separates a
   verdict from prose. The tone class colours the line and its sign alike,
   so words and sign can never disagree. */
.site-card-line {
    align-items: center;
    color: var(--text-muted);
    display: flex;
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: var(--fw-semibold);
    gap: var(--space-2);
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

.site-card-line-ok {
    color: var(--site-ok);
}
.site-card-line-warning {
    color: var(--site-soon);
}
.site-card-line-danger {
    color: var(--site-bad);
}
.site-card-line-neutral {
    color: var(--site-np);
}

/* The sign in front of a status line, drawn in the line's colour. */
.site-sign {
    -webkit-mask: var(--site-sign) center / contain no-repeat;
    background: currentColor;
    flex: none;
    height: 13px;
    mask: var(--site-sign) center / contain no-repeat;
    width: 13px;
}

.site-sign-ok {
    --site-sign: var(--site-sign-ok);
}
.site-sign-warning {
    --site-sign: var(--site-sign-soon);
}
.site-sign-danger {
    --site-sign: var(--site-sign-bad);
}
.site-sign-neutral {
    --site-sign: var(--site-sign-np);
}

.site-empty {
    align-items: center;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-12) var(--space-5);
    text-align: center;
}

.site-empty-icon {
    align-items: center;
    background: var(--gray-100);
    border-radius: var(--radius-pill);
    color: var(--text-subtle);
    display: flex;
    height: 52px;
    justify-content: center;
    width: 52px;
}

.site-empty-title {
    color: var(--text-strong);
    font-weight: var(--fw-semibold);
}

.site-empty-text {
    color: var(--text-muted);
    font-size: var(--text-sm);
    max-width: 16rem;
}

.site-list-foot {
    display: block;
    font-size: var(--text-sm);
    margin-top: var(--space-5);
    min-height: 44px;
    padding-top: var(--space-3);
}

.site-chips {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
}

.site-checks {
    margin-bottom: var(--space-5);
}

.site-checks .site-chips {
    flex-wrap: wrap;
}

.site-chip {
    align-items: center;
    flex: none;
    white-space: nowrap;
    background: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-pill);
    color: var(--text-body);
    cursor: pointer;
    display: inline-flex;
    font: inherit;
    font-size: var(--text-sm);
    gap: var(--space-2);
    min-height: 44px;
    padding: 0 var(--space-4);
    text-decoration: none;
}

.site-chip-active {
    background: var(--navy-900);
    border-color: var(--navy-900);
    color: var(--text-on-dark);
}

/* A filter for a state carries that state's sign, not only its fill. */
.site-chip-danger,
.site-chip-warning {
    --site-sign: var(--site-sign-bad);
    background: var(--site-bad-bg);
    border-color: var(--site-bad-bg);
    color: var(--site-bad);
}

.site-chip-warning {
    --site-sign: var(--site-sign-soon);
    background: var(--site-soon-bg);
    border-color: var(--site-soon-bg);
    color: var(--site-soon);
}

.site-chip-danger::before,
.site-chip-warning::before {
    -webkit-mask: var(--site-sign) center / contain no-repeat;
    background: currentColor;
    content: "";
    flex: none;
    height: 14px;
    mask: var(--site-sign) center / contain no-repeat;
    width: 14px;
}

.site-chip-danger.site-chip-active {
    background: var(--site-bad);
    border-color: var(--site-bad);
    color: var(--white);
}

.site-chip-warning.site-chip-active {
    background: var(--site-soon);
    border-color: var(--site-soon);
    color: var(--white);
}

.site-chip-count {
    color: inherit;
    font-weight: var(--fw-semibold);
    opacity: 0.7;
}

/* The chain, one indent per level. The site allows a depth of up to nine,
   so the step stays small enough that the ninth still leaves a readable
   line on a 390px screen. */
/* A firm is one card with its people as rows, not a card each: the kit
   reads the group as a block, and a stack of separate cards loses which
   people belong together. A firm under another sits behind an edge, one
   step per level of the chain - the site allows nine, so the step stays
   small enough that the deepest still leaves a readable line at 390px. */
.site-group {
    margin-bottom: var(--space-4);
}

.site-group-nested {
    border-left: 2px solid var(--border-subtle);
    margin-left: var(--space-3);
    padding-left: var(--space-3);
}

.site-group-name {
    color: var(--text-strong);
    font-size: var(--text-sm);
    font-weight: var(--fw-bold);
    padding: var(--space-3) var(--space-1) var(--space-2);
}

.site-group-state {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0 0 var(--space-2);
    padding: 0 var(--space-1);
}

.site-group-crew {
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-variant-numeric: tabular-nums;
}

.site-group-parent {
    color: var(--text-subtle);
    font-family: var(--font-mono);
    font-size: 10.5px;
    font-weight: var(--fw-medium);
    letter-spacing: 0.05em;
    margin: 0;
    padding: var(--space-2) 0 var(--space-2) 2px;
    text-transform: uppercase;
}

.site-people {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    list-style: none;
    margin: 0;
    overflow: hidden;
    padding: 0;
}

.site-people > li + li {
    border-top: 1px solid var(--border-subtle);
}

.site-person {
    align-items: center;
    color: var(--text-body);
    display: flex;
    gap: var(--space-3);
    justify-content: space-between;
    min-height: 44px;
    padding: var(--space-3) var(--space-4);
}

.site-person:hover {
    background: var(--gray-50);
    text-decoration: none;
}

.site-person-body {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
}

.site-person-name {
    color: var(--text-strong);
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
}

.verdict {
    align-items: flex-start;
    border-radius: var(--radius-lg);
    display: flex;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
    padding: var(--space-4);
}

.verdict > .icon {
    flex: none;
    margin-top: 2px;
}

.verdict-ok {
    background: var(--success-100);
    color: var(--success-text);
}

.verdict-warning {
    background: var(--warning-100);
    color: var(--warning-text);
}

.verdict-danger {
    background: var(--danger-100);
    color: var(--danger-text);
}

.verdict-line {
    font-family: var(--font-display);
    font-size: var(--text-md);
    font-weight: var(--fw-bold);
    margin: 0;
}

.verdict-why {
    font-size: var(--text-sm);
    margin: var(--space-1) 0 0;
}

/* Centred, with the initials over the name: the kit puts the person in the
   middle of the screen because the reader is comparing them with somebody
   standing in front of them. */
.site-person-head {
    align-items: center;
    display: flex;
    flex-direction: column;
    margin-bottom: var(--space-4);
    text-align: center;
}

/* A tint of its own: navy-100 is the page canvas since E-174, and the circle
   vanished into it, leaving the initials bare. */
.site-person-avatar {
    align-items: center;
    background: var(--info-100);
    border-radius: var(--radius-pill);
    color: var(--info-text);
    display: flex;
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: var(--fw-bold);
    height: 56px;
    justify-content: center;
    margin-bottom: var(--space-2);
    width: 56px;
}

.site-person-head-name {
    color: var(--text-strong);
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: var(--fw-bold);
    margin: 0;
}

.site-person-head-sub {
    color: var(--text-body);
    font-size: var(--text-sm);
    margin: 2px 0 0;
}

.site-person-head-role {
    color: var(--text-subtle);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    margin: 1px 0 0;
}

.site-person-head-hint {
    color: var(--text-subtle);
    font-size: var(--text-xs);
    margin: var(--space-2) 0 0;
    max-width: 17rem;
}

.site-section {
    margin-bottom: var(--space-5);
}

.site-section-title {
    color: var(--text-subtle);
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: var(--fw-semibold);
    letter-spacing: .07em;
    margin: 0 0 var(--space-2);
    text-transform: uppercase;
}

.site-section-note {
    color: var(--text-muted);
    font-size: var(--text-xs);
    margin: 0 0 var(--space-2);
}

/* A neutral card: the reason's line carries the verdict, the edge repeats
   nothing. */
.site-reason {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-2);
    padding: var(--space-3) var(--space-4);
}

.site-reason-what {
    color: var(--text-strong);
    font-weight: var(--fw-medium);
    margin: 0;
}

.site-reason-when {
    color: var(--text-muted);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-wide);
    margin: 2px 0 0;
    text-transform: uppercase;
}

/* A state of a card as a label, where `site-reason-when` would set it in capitals:
   a briefing's "Nicht bestätigt" is a word for the badge, never a line of that class. */
.site-reason-state {
    margin: var(--space-1) 0 0;
}

.site-contacts {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

.site-evidence {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    list-style: none;
    margin: 0;
    overflow: hidden;
    padding: 0;
}

.site-evidence > li + li {
    border-top: 1px solid var(--border-subtle);
}

.site-contact {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--space-3) var(--space-4);
}

.site-contact-name {
    color: var(--text-strong);
    font-weight: var(--fw-medium);
}

.site-contact-role {
    color: var(--text-muted);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
}

.site-contact-link {
    font-size: var(--text-sm);
    min-height: 44px;
    padding-top: var(--space-2);
}

.site-evidence-row {
    align-items: center;
    background: none;
    border: 0;
    cursor: pointer;
    display: flex;
    font: inherit;
    gap: var(--space-3);
    min-height: 44px;
    color: inherit;
    padding: var(--space-3) var(--space-4);
    text-align: left;
    text-decoration: none;
    width: 100%;
}

.site-evidence-row:hover {
    background: var(--gray-50);
}

.site-evidence-main {
    flex: 1;
    min-width: 0;
}

.site-evidence-name {
    color: var(--text-strong);
    display: block;
    font-weight: var(--fw-semibold);
}

.site-evidence-valid {
    color: var(--text-subtle);
    display: block;
    font-family: var(--font-mono);
    font-size: 11.5px;
    margin-top: 1px;
}

.site-badge {
    align-items: center;
    border-radius: var(--radius-pill);
    display: inline-flex;
    flex: none;
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
    gap: var(--space-2);
    padding: 3px 9px;
    white-space: nowrap;
}

.site-badge::before {
    -webkit-mask: var(--site-sign) center / contain no-repeat;
    background: currentColor;
    content: "";
    flex: none;
    height: 12px;
    mask: var(--site-sign) center / contain no-repeat;
    width: 12px;
}

.site-badge-ok {
    --site-sign: var(--site-sign-ok);
    background: var(--site-ok-bg);
    color: var(--site-ok);
}
.site-badge-warning {
    --site-sign: var(--site-sign-soon);
    background: var(--site-soon-bg);
    color: var(--site-soon);
}
.site-badge-danger {
    --site-sign: var(--site-sign-bad);
    background: var(--site-bad-bg);
    color: var(--site-bad);
}
.site-badge-neutral {
    --site-sign: var(--site-sign-np);
    background: var(--site-np-bg);
    color: var(--site-np);
}

.site-evidence-row > .icon {
    color: var(--text-subtle);
    flex: none;
}

/* The tuple behind a row: what is known about the evidence without opening
   the document. Two columns, the note under a rule. */
.site-tuple {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-2) 0;
}

.site-tuple + .site-tuple {
    border-top: 1px solid var(--border-subtle);
}

.site-tuple-key {
    color: var(--text-muted);
}

.site-tuple-value {
    color: var(--text-strong);
    font-weight: var(--fw-semibold);
    text-align: right;
}

.site-tuple-note {
    border-top: 1px solid var(--border-subtle);
    color: var(--text-subtle);
    font-size: var(--text-xs);
    margin-top: var(--space-3);
    padding-top: var(--space-3);
}

.site-section-foot {
    color: var(--success-text);
    font-size: var(--text-sm);
    margin-top: var(--space-3);
    text-align: center;
}

/* The framework's error bar and the bare page a visitor can still reach.
   Global on purpose: the bar is one id that can exist once in the document,
   and both shells - the desk's and the site channel's - render it. In a
   scoped stylesheet only the shell it was written for would hide it, and
   the other would show it permanently, which is how it was found. */

#blazor-error-ui {
    color-scheme: light only;
    background: var(--warning-100);
    bottom: 0;
    box-shadow: var(--shadow-lg);
    box-sizing: border-box;
    color: var(--text-strong);
    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;
}

.visitor {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.visitor > h1 {
    margin: var(--space-8) var(--space-8) var(--space-3);
}

.visitor > p {
    margin: 0 var(--space-8);
}


.verdict-neutral {
    background: var(--gray-100);
    color: var(--text-muted);
}

/* The verdict banner in the site channel speaks the channel's status
   language; the office pages keep the shared tones. */
.site-shell .verdict-ok {
    background: var(--site-ok-bg);
    color: var(--site-ok);
}
.site-shell .verdict-warning {
    background: var(--site-soon-bg);
    color: var(--site-soon);
}
.site-shell .verdict-danger {
    background: var(--site-bad-bg);
    color: var(--site-bad);
}
.site-shell .verdict-neutral {
    background: var(--site-np-bg);
    color: var(--site-np);
}

.site-content:has(> .site-person-page) {
    overflow: hidden;
    padding: 0;
}
.site-person-page {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}
.site-person-scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: var(--space-4);
}
.site-person-actions {
    background: var(--surface-card);
    border-top: 1px solid var(--border-subtle);
    flex: none;
    padding: var(--space-3) var(--space-4) max(var(--space-3), env(safe-area-inset-bottom));
}
.site-person-actions .site-verify-button {
    min-height: 44px;
    width: 100%;
}
.site-return {
    align-items: center;
    display: flex;
    font-size: var(--text-xs);
    justify-content: center;
    min-height: 44px;
    text-align: center;
}
.site-person-history {
    align-items: center;
    display: flex;
    font-size: var(--text-sm);
    justify-content: space-between;
    gap: var(--space-2);
    min-height: 44px;
    margin: var(--space-2) 0;
}
.site-person-photo-hint {
    color: var(--text-subtle);
    font-size: var(--text-xs);
    max-width: 260px;
    margin: 0 0 var(--space-2);
}
.site-photo-capture {
    margin: 0;
    width: 100%;
}
.site-photo-capture summary {
    color: var(--text-link);
    justify-content: center;
}
.site-photo-capture .site-field-form {
    margin-top: var(--space-3);
    text-align: left;
}
.site-photo-capture summary,
.site-evidence-disclosure > summary {
    align-items: center;
    cursor: pointer;
    display: flex;
    font-size: var(--text-sm);
    gap: var(--space-2);
    min-height: 44px;
}
.site-evidence-disclosure > summary {
    justify-content: space-between;
    color: var(--text-link);
}
.site-evidence-disclosure[open] > summary {
    margin-bottom: var(--space-3);
}
.site-reason-actions {
    display: grid;
    gap: var(--space-2);
    margin-top: var(--space-3);
}
.site-reason-actions a {
    align-items: center;
    display: flex;
    font-size: var(--text-sm);
    gap: var(--space-2);
    justify-content: center;
    min-height: 44px;
    text-decoration: none;
}
.site-reason {
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}
.site-reason-what {
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
}
.site-case-context {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    margin: 0 0 var(--space-5);
    overflow: hidden;
}
.site-case-context > div {
    display: grid;
    grid-template-columns: 70px minmax(0, 1fr);
    gap: var(--space-3);
    padding: var(--space-3);
    font-size: var(--text-sm);
}
.site-case-context > div + div {
    border-top: 1px solid var(--border-subtle);
}
.site-case-context dt {
    color: var(--text-muted);
}
.site-case-context dd {
    color: var(--text-strong);
    font-weight: var(--fw-medium);
    margin: 0;
    overflow-wrap: anywhere;
    text-align: right;
}
.site-field-form {
    display: grid;
    gap: var(--space-3);
}
.site-field-form label {
    margin: 0;
    min-width: 0;
}
.site-field-form textarea {
    background: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    box-sizing: border-box;
    color: var(--text-body);
    display: block;
    font: inherit;
    font-size: var(--text-sm);
    min-height: 88px;
    padding: var(--space-3);
    resize: vertical;
    width: 100%;
}
.site-field-form select {
    background: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    box-sizing: border-box;
    color: var(--text-body);
    display: block;
    font: inherit;
    font-size: var(--text-sm);
    min-height: 44px;
    padding: var(--space-2) var(--space-3);
    width: 100%;
}
.site-field-form .btn-primary,
.site-field-form .btn-secondary {
    justify-content: center;
    min-height: 44px;
}
.site-case-options {
    border: 0;
    display: grid;
    gap: var(--space-2);
    margin: 0;
    min-width: 0;
    padding: 0;
}
.site-case-option {
    box-sizing: border-box;
    align-items: center;
    background: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    cursor: pointer;
    display: flex;
    font-size: var(--text-sm);
    gap: var(--space-3);
    min-height: 44px;
    padding: var(--space-2) var(--space-3);
}
.site-case-option:has(input:checked) {
    border-color: var(--navy-900);
    background: var(--gray-50);
}
.site-case-option input {
    accent-color: var(--navy-900);
    height: 18px;
    width: 18px;
}
.site-upload {
    background: var(--surface-card);
    border: 1px dashed var(--border-default);
    border-radius: var(--radius-md);
    display: grid;
    font-size: var(--text-sm);
    gap: var(--space-2);
    padding: var(--space-3);
}
.site-upload > span {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}
.site-upload input {
    color: var(--text-muted);
    font: inherit;
    max-width: 100%;
    min-height: 44px;
    width: 100%;
}
.site-upload input::file-selector-button {
    background: var(--gray-50);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    color: var(--text-body);
    cursor: pointer;
    font: inherit;
    margin-right: var(--space-2);
    min-height: 44px;
    padding: var(--space-2);
}
.site-message {
    color: var(--text-muted);
    display: grid;
    font-size: var(--text-xs);
    gap: var(--space-2);
}
.site-form-hint {
    color: var(--text-muted);
    font-size: var(--text-xs);
    margin: 0;
    text-align: center;
}
.site-submitted {
    align-items: flex-start;
    background: var(--success-100);
    border-radius: var(--radius-lg);
    color: var(--success-text);
    display: flex;
    font-size: var(--text-sm);
    gap: var(--space-3);
    margin-bottom: var(--space-4);
    padding: var(--space-4);
}
.site-submitted p {
    margin: var(--space-1) 0 0;
}
.site-submitted .icon {
    flex: none;
}

/* Primary navigation stays on the four project screens. Person checks
   have their own fixed action and return link. */
.site-tabs {
    background: var(--surface-card);
    border-top: 1px solid var(--border-subtle);
    display: flex;
    flex: none;
    padding-bottom: max(var(--space-3), env(safe-area-inset-bottom));
}

.site-tab {
    align-items: center;
    color: var(--text-subtle);
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 3px;
    min-height: 44px;
    padding: 10px 0 2px;
}

.site-tab-active {
    color: var(--text-strong);
}

.site-tab-label {
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: var(--fw-medium);
}

/* The door into the site channel on the start page: the amber of the brand,
   because it is the one card that changes which product you are in. */
.start-card-site {
    background: var(--amber-500);
    border-color: var(--amber-500);
    color: var(--accent-contrast);
}

.start-card-site .start-card-caption,
.start-card-site .start-card-number {
    color: var(--accent-contrast);
}

/* The switch into the site channel, in the top bar beside the search.
   Amber, because it is the one link that changes which product you are in,
   and compact, because it shares the row with the search and the bell. */
.channel-switch {
    align-items: center;
    background: var(--amber-500);
    border-radius: var(--radius-md);
    color: var(--accent-contrast);
    display: inline-flex;
    flex: none;
    font-size: var(--text-sm);
    font-weight: var(--fw-medium);
    gap: var(--space-2);
    height: 40px;
    padding: 0 var(--space-3);
    white-space: nowrap;
}

.channel-switch:hover {
    background: var(--amber-600);
    color: var(--accent-contrast);
}

/* On a narrow window the row is tight: the glyph carries it, the word goes. */
@media (max-width: 48rem) {
    .channel-switch span {
        display: none;
    }

    .channel-switch {
        padding: 0 var(--space-2);
    }
}

/* Aufbewahrung: an undecided period reads as open, quietly - a missing
   decision, not an alarm. */
.retention-open {
    background: var(--gray-100);
    color: var(--text-muted);
}

.retention-note {
    margin: var(--space-3) 0 0;
}

.retention-section + .retention-section {
    margin-top: var(--space-8);
}

/* The check, written down: the line that says when this person was last
   confirmed here, and the one button a thumb reaches - full width, the
   height the kit gives a primary action on a phone. The form posts and
   the address comes back with the line renewed, so there is no state to
   hold between the two. */

.site-verify-last {
    color: var(--text-muted);
    font-size: var(--text-sm);
    margin: 0 0 var(--space-3);
}

.site-verify-done {
    align-items: center;
    color: var(--success-text);
    display: flex;
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
    gap: var(--space-2);
    margin: 0 0 var(--space-2);
}

.site-verify-form {
    margin: 0;
}

.site-verify-button {
    min-height: 48px;
    width: 100%;
}

.site-verify-error {
    color: var(--danger-text);
    font-size: var(--text-sm);
    margin: var(--space-2) 0 0;
}

/* The protocol: a period to narrow by, then the entries by day, each with
   the time in the gutter, the person and firm in the middle, the verdict
   as it was recorded at the edge. The entry links to the person - the
   protocol says what was seen, the person says what stands today. */

.site-log-intro {
    margin-bottom: var(--space-2);
}
.site-log-periods {
    display: flex;
    gap: var(--space-4);
    margin-bottom: var(--space-2);
}
.site-log-periods a {
    align-items: center;
    display: inline-flex;
    font-size: var(--text-xs);
    min-height: 44px;
}
.site-log-filter {
    margin-bottom: var(--space-5);
}
.site-log-filter-card {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}
.site-log-filter-field {
    align-items: center;
    display: grid;
    grid-template-columns: 90px minmax(0, 1fr);
    gap: var(--space-2);
    margin: 0;
    padding: var(--space-2) var(--space-3);
}
.site-log-filter-field + .site-log-filter-field {
    border-top: 1px solid var(--border-subtle);
}
.site-log-filter-field > span {
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: 11px;
    text-transform: uppercase;
}
.site-log-filter-field input,
.site-log-filter-field select {
    background: var(--surface-card);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    box-sizing: border-box;
    color: var(--text-strong);
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    min-height: 44px;
    min-width: 0;
    padding: 0 var(--space-2);
    width: 100%;
}
.site-log-filter-actions {
    display: grid;
    gap: var(--space-2);
    margin-top: var(--space-3);
}
.site-log-filter-actions .btn-primary {
    justify-content: center;
    min-height: 44px;
    width: 100%;
}

.site-log-export {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-2);
    margin: 0 0 var(--space-3);
}

.site-log-export form {
    margin: 0;
    min-width: 0;
}
.site-log-export a,
.site-log-export button {
    box-sizing: border-box;
    justify-content: center;
    min-height: 44px;
    white-space: normal;
    width: 100%;
}


.site-log-export .btn-small {
    align-items: center;
    display: inline-flex;
    gap: 6px;
}

.site-log-mailed {
    align-items: center;
    color: var(--success-text);
    display: flex;
    font-size: var(--text-sm);
    gap: 6px;
    margin: 0 0 var(--space-3);
}

.site-log-mailed-off {
    color: var(--text-muted);
}

.site-log-filter-clear {
    color: var(--text-subtle);
    font-size: var(--text-sm);
    min-height: 40px;
    display: inline-flex;
    align-items: center;
}

.site-log {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Time, who, verdict on one line; the reason and the grounds go under the
   name instead of taking its width - a squeezed name broke one word per line. */
.site-log-entry {
    align-items: center;
    column-gap: var(--space-3);
    display: grid;
    grid-template-columns: 2.8rem minmax(0, 1fr) auto;
    padding: var(--space-3);
    row-gap: var(--space-1);
}

.site-log-entry > .site-log-reason,
.site-log-entry > .cell-sub {
    grid-column: 2 / -1;
}

.site-log-entry + .site-log-entry {
    border-top: 1px solid var(--border-subtle);
}

.site-log-time {
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    width: 2.8rem;
}

.site-log-body {
    color: inherit;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    text-decoration: none;
}

.site-log-name {
    color: var(--text-strong);
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
}

.site-log-firm,
.site-log-by {
    color: var(--text-muted);
    font-size: var(--text-xs);
}

.verdict-gravity {
    font-size: var(--text-sm);
    font-weight: var(--fw-bold);
    margin: 2px 0 0;
}

.verdict-reason {
    font-weight: var(--fw-semibold);
}

.site-reason-hard {
    color: var(--danger-text);
    font-weight: var(--fw-semibold);
}

.site-log-reason {
    color: var(--danger-text);
    font-size: var(--text-xs);
    font-weight: var(--fw-semibold);
}

.site-log-more {
    display: block;
    margin-top: var(--space-3);
    text-align: center;
}

/* The carrier tab on a person: a row's actions - print, and the reason
   before the one button that ends a pointer. */

.carrier-blocked {
    background: var(--warning-100);
    border-radius: var(--radius-md);
    color: var(--warning-text);
    font-size: var(--text-sm);
    margin-top: var(--space-3);
    padding: var(--space-3);
}

.carrier-blocked p {
    margin: 0 0 var(--space-2);
}

.carrier-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-3);
}

.carrier-reason {
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    font-family: var(--font-sans);
    font-size: var(--text-xs);
    margin: 0 var(--space-1);
    padding: 4px 6px;
}

/* The sheet of carriers. On screen a plain page with one button; on paper
   a grid of cards, two per row, each with its code and the sentence under
   it, and never a page break through a card. */

.print-shell {
    margin: 0 auto;
    max-width: 210mm;
    padding: var(--space-6) var(--space-4);
}

.print-head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-bottom: var(--space-5);
    position: relative;
    z-index: 1;
}

.print-brand {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: var(--fw-bold);
    margin: 0;
}

.print-brand span {
    color: var(--accent);
}

.print-meta {
    color: var(--text-muted);
    flex: 1;
    font-size: var(--text-sm);
    margin: 0;
}

.print-cards {
    display: grid;
    gap: var(--space-4);
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    list-style: none;
    margin: 0;
    padding: 0;
}

.print-card {
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    break-inside: avoid;
    display: flex;
    gap: var(--space-3);
    padding: var(--space-3);
    position: relative;
    z-index: 1;
}

/* Tenant and print date across the page, behind everything. Fixed, so each
   printed page repeats it; the QR code's own white field lies over it, so
   no code is ever crossed. */
.print-watermark {
    color: rgba(0, 0, 0, 0.07);
    display: flex;
    flex-direction: column;
    font-family: var(--font-display);
    font-size: 22px;
    font-weight: var(--fw-bold);
    inset: 0;
    justify-content: space-around;
    overflow: hidden;
    pointer-events: none;
    position: fixed;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
    user-select: none;
    white-space: nowrap;
    z-index: 0;
}

.print-watermark p {
    display: flex;
    gap: 64px;
    justify-content: center;
    margin: 0;
    transform: rotate(-24deg);
}

.print-qr {
    background: #fff;
    flex: none;
    width: 120px;
}

.print-qr svg {
    display: block;
    height: auto;
    width: 100%;
}

.print-card-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.print-card-name {
    font-family: var(--font-display);
    font-size: var(--text-md);
    font-weight: var(--fw-bold);
    margin: 0;
}

.print-card-firm,
.print-card-issued,
.print-card-printed {
    color: var(--text-muted);
    font-size: var(--text-sm);
    margin: 0;
}

.print-card-note {
    color: var(--text-subtle);
    font-size: 10px;
    line-height: 1.3;
    margin: var(--space-2) 0 0;
}

/* The person's own door, printed as a line to type rather than a second
   code to scan: the address has to survive a photocopy, so it breaks
   anywhere and stays monospaced. */
.print-card-status {
    color: var(--text-subtle);
    font-size: 10px;
    line-height: 1.3;
    margin: var(--space-1) 0 0;
}

.print-card-status span {
    font-family: var(--font-mono);
    overflow-wrap: anywhere;
}

/* The protocol on paper: the selection as a short list of facts, then one
   table, a heading row per day, and never a page break through a row. */

.protocol-sheet-title {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    margin: 0 0 var(--space-3);
}

.protocol-sheet-facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-5);
    margin: 0 0 var(--space-5);
}

.protocol-sheet-facts dt {
    color: var(--text-muted);
    font-size: var(--text-xs);
}

.protocol-sheet-facts dd {
    font-size: var(--text-sm);
    font-weight: 600;
    margin: 0;
}

.protocol-sheet-table {
    border-collapse: collapse;
    font-size: var(--text-sm);
    width: 100%;
}

.protocol-sheet-table th,
.protocol-sheet-table td {
    border-bottom: 1px solid var(--border-subtle);
    padding: 6px 8px;
    text-align: left;
    vertical-align: top;
}

.protocol-sheet-table thead th {
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-weight: 600;
}

.protocol-sheet-table tr {
    break-inside: avoid;
}

.protocol-sheet-day th {
    background: var(--surface-sunken);
    font-weight: 700;
}

.protocol-sheet-empty,
.protocol-sheet-note {
    color: var(--text-muted);
    font-size: var(--text-sm);
    margin: var(--space-4) 0 0;
}

@media print {
    .print-button,
    #blazor-error-ui {
        display: none !important;
    }

    .print-shell {
        max-width: none;
        padding: 0;
    }

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

/* The scanner: the camera's picture where the browser has one, a line
   under it that says what is going on, and the field for a code typed by
   hand. The picture is square-ish and dark until the stream arrives, so
   the page does not jump when it does. */

.site-scan {
    align-items: center;
    background: var(--navy-800);
    border-radius: var(--radius-lg);
    color: var(--text-on-dark);
    display: flex;
    flex-direction: column;
    justify-content: center;
    margin-bottom: var(--space-4);
    min-height: 280px;
    overflow: hidden;
    padding: var(--space-5);
    position: relative;
}

.site-scan-video {
    height: 100%;
    inset: 0;
    object-fit: cover;
    position: absolute;
    width: 100%;
}

.site-scan-video[hidden] {
    display: none;
}

.site-scan-guide {
    border: 2px solid var(--navy-400);
    border-radius: var(--radius-md);
    height: 144px;
    position: relative;
    width: 144px;
}

.site-scan-instruction,
.site-scan-status {
    background: var(--navy-800);
    border-radius: var(--radius-sm);
    color: var(--text-on-dark);
    font-size: var(--text-sm);
    margin: var(--space-2) 0 0;
    padding: var(--space-1) var(--space-2);
    position: relative;
    text-align: center;
}

.site-scan-status {
    color: var(--text-on-dark-muted);
}

.site-scan-modes {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
}

.site-scan-modes .site-chip {
    justify-content: center;
    padding: 0 var(--space-2);
}

.site-scan-form {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.site-scan-label {
    color: var(--text-muted);
    font-size: var(--text-xs);
}

.site-scan-hint {
    color: var(--text-subtle);
    font-size: var(--text-xs);
    margin: 0;
    text-align: center;
}

.site-verify-scanned {
    align-items: center;
    color: var(--text-muted);
    display: flex;
    font-size: var(--text-sm);
    gap: var(--space-2);
    margin: 0 0 var(--space-2);
}

/* Field forms remain usable with a phone keyboard and without a circuit. */
.site-person-photo {
    object-fit: cover;
    border-radius: 12px;
    max-width: 100%;
}
.site-section form:not(.site-field-form) label {
    display: block;
    margin: 12px 0;
}
.site-section form:not(.site-field-form) textarea {
    display: block;
    width: 100%;
    min-height: 90px;
}
.site-section form select, .site-section form input {
    max-width: 100%;
}

/* The company chain scrolls inside the canvas; opening a branch never widens the shell. */
.hierarchy-filter { display: flex; align-items: end; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-3); }
.hierarchy-filter label { display: flex; flex-direction: column; gap: var(--space-1); font-size: var(--text-sm); }
/* The label stacks its field, so the list search's flex basis would become its height. */
.hierarchy-filter .search-input { flex: none; width: 17.5rem; max-width: 100%; }
.hierarchy-project { min-width: 0; margin-top: var(--space-6); }
.hierarchy-project-title { font-size: var(--text-lg); margin-bottom: var(--space-3); }
.hierarchy-scroll { overflow: auto; max-width: 100%; padding: var(--space-1) var(--space-1) 30px; }
.hierarchy-scroll:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }
/* G11: 2px connectors, 22px apart. A branch hangs below its chevron; the root has none and its first level stays open. */
.hierarchy-tree, .hierarchy-children { display: flex; justify-content: center; list-style: none; padding: 0; margin: 0; width: max-content; min-width: 100%; }
.hierarchy-children { padding-top: 50px; position: relative; }
.hierarchy-children::before { content: ''; position: absolute; top: 28px; left: calc(50% - 1px); height: 22px; border-left: 2px solid var(--border-strong); }
.hierarchy-root ~ .hierarchy-children { padding-top: 22px; }
.hierarchy-root ~ .hierarchy-children::before { top: 0; }
.hierarchy-branch { display: flex; flex-direction: column; align-items: center; position: relative; padding: 0 11px; }
.hierarchy-children > .hierarchy-branch { padding-top: 22px; }
.hierarchy-children > .hierarchy-branch::before { content: ''; position: absolute; left: 0; right: 0; top: 0; border-top: 2px solid var(--border-strong); }
.hierarchy-children > .hierarchy-branch:first-child::before { left: calc(50% - 1px); }
.hierarchy-children > .hierarchy-branch:last-child::before { right: calc(50% - 1px); }
.hierarchy-children > .hierarchy-branch::after { content: ''; position: absolute; height: 22px; top: 0; left: calc(50% - 1px); border-left: 2px solid var(--border-strong); }
.hierarchy-node { position: relative; width: 180px; display: flex; flex-direction: column; gap: 9px; padding: 11px 13px; border: 1px solid var(--border-subtle); border-radius: var(--radius-md); background: var(--surface-card); box-shadow: var(--shadow-xs); }
.hierarchy-node:has(> .hierarchy-company[href]:hover) { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.hierarchy-node > .badge { align-self: flex-start; }
.hierarchy-node > .cell-sub { font-size: 11px; }
.hierarchy-root { width: 200px; }
.hierarchy-company { display: flex; align-items: flex-start; gap: 9px; color: var(--text-strong); }
.hierarchy-company:hover { text-decoration: none; }
/* The whole card opens the profile, as in the design; the meter stays above it for its tooltip. */
.hierarchy-company[href]::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.hierarchy-name { font-size: 12.5px; font-weight: var(--fw-semibold); line-height: 1.3; overflow-wrap: anywhere; }
.hierarchy-avatar { display: grid; place-items: center; width: 30px; height: 30px; flex: none; border-radius: var(--radius-sm); background: var(--navy-900); color: white; font-size: 11.5px; font-weight: var(--fw-semibold); }
.hierarchy-root .hierarchy-avatar { background: var(--accent); color: var(--accent-contrast); }
.hierarchy-meter { position: relative; z-index: 1; display: flex; align-self: flex-start; align-items: center; gap: 5px; cursor: help; }
.hierarchy-bar { display: flex; flex: 0 0 32px; height: 5px; overflow: hidden; border-radius: var(--radius-pill); background: var(--gray-100); }
.hierarchy-bar-ok { background: var(--success-500); }
.hierarchy-bar-open { flex: 1; background: var(--warning-500); }
.hierarchy-bar-danger { background: var(--danger-500); }
.hierarchy-percent { font-size: 10.5px; font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--text-muted); }
.hierarchy-highlight { border-color: var(--amber-500); outline: 2px solid var(--amber-500); outline-offset: -2px; background: color-mix(in srgb, var(--amber-500) 10%, var(--surface-card)); }
.hierarchy-toggle { position: absolute; top: calc(100% + 6px); left: 50%; display: grid; place-items: center; width: 22px; height: 22px; padding: 0; transform: translateX(-50%); border: 1px solid var(--border-default); border-radius: 50%; background: var(--surface-card); color: var(--text-muted); cursor: pointer; }
.hierarchy-toggle:hover { border-color: var(--border-strong); color: var(--text-strong); }
.hierarchy-toggle:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }
.hierarchy-company:focus-visible { outline: none; }
.hierarchy-company:focus-visible::after { outline: 2px solid var(--border-focus); outline-offset: 2px; }

/* Profiles are pages; only document actions open modal dialogs. */
.profile-page { min-width: 0; }
.profile-content { min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr); position: relative; }
.profile-content-with-panel, .person-profile-columns { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--space-5); align-items: start; }
.profile-side-panel { box-sizing: border-box; min-width: 0; width: 320px; padding: var(--space-5); border: 1px solid var(--border-subtle); border-radius: var(--radius-lg); background: var(--surface-card); overflow-wrap: anywhere; }
.profile-side-panel { position: sticky; top: var(--space-4); max-height: calc(100dvh - 100px); overflow-y: auto; }
.profile-side-panel h2 { font-size: var(--text-lg); margin: 0 0 var(--space-3); }
.profile-side-panel h3 { font-size: var(--text-sm); margin: var(--space-5) 0 var(--space-2); }
.profile-panel-close { float: right; margin: -8px -8px 8px 8px; }
.profile-card-badges { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.profile-full-link { display: block; margin-top: var(--space-5); }
.request-evidence-choice { display: block; margin: var(--space-2) 0; }
@media (max-width: 1023px) {
    .profile-content-with-panel { grid-template-columns: minmax(0, 1fr); }
    .profile-side-panel { position: fixed; top: 80px; right: var(--space-4); bottom: var(--space-4); z-index: 30; box-shadow: var(--shadow-lg); max-height: none; }
    .person-profile-columns { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 639px) {
    .profile-side-panel { left: 0; right: 0; width: 100%; bottom: 0; border-radius: 0; }
}

/* Company overview: one compact row; secondary columns disappear in narrow windows. */
.company-list .data-table td { padding: 12px 16px; height: 51px; box-sizing: border-box; white-space: nowrap; }
.company-list .data-table th { white-space: nowrap; }
/* A long firm name moves to a second line rather than push the list past its card. */
.company-list .data-table td:first-child { white-space: normal; }
.company-list .numeric { text-align: right; }
.company-name { display: flex; align-items: center; gap: 9px; }
.company-name .dot { flex: none; margin: 0; }
.company-list .company-action { text-align: right; font-size: var(--text-xs); }
.company-list .company-projects .ratio { font-family: var(--font-sans); font-size: 13px; font-weight: var(--fw-regular); color: var(--text-body); }
.company-contact-cell { display: inline-flex; align-items: center; gap: 8px; }
.company-call {
    align-items: center; background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
    color: var(--gray-600); display: inline-flex; flex: none; height: 26px; justify-content: center; width: 26px;
}
.company-call:hover { background: var(--gray-50); color: var(--text-strong); }
/* The way into the firm: a framed symbol button like the phone beside it (E-232), always in sight; the row under the
   pointer is only lightly lit, the button takes the accent. Only the firm lists - other lists keep their plain arrow. */
.row-arrow.company-arrow {
    background: var(--surface-card); border: 1px solid var(--border-subtle); box-sizing: border-box; color: var(--gray-600);
    flex: none; height: 26px; padding: 0; width: 26px;
}
.row-link:hover .row-arrow.company-arrow, .row-arrow.company-arrow:hover, .row-arrow.company-arrow:focus-visible {
    background: var(--accent); border-color: var(--accent); color: var(--accent-contrast);
}
.company-contact-name {
    color: var(--text-body); font-size: 13px; max-width: 11rem; overflow: hidden; text-overflow: ellipsis; display: inline-block; vertical-align: middle;
}
/* The row's menu and the arrow stand side by side; an open menu floats over the list. */
.company-actions { display: inline-flex; align-items: center; flex-wrap: nowrap; gap: 4px 14px; justify-content: flex-end; }
.company-under { font-size: 12px; margin-left: 16px; }
/* P2: the project's chain as a tree - each firm a step further in than the firm it works under, joined to it by an elbow, as in NP2. */
.company-name-nested { padding-left: calc((var(--indent, 1) - 1) * 24px); }
.company-elbow {
    border-bottom: 2px solid var(--border-strong); border-bottom-left-radius: 4px; border-left: 2px solid var(--border-strong);
    flex: none; height: 14px; margin-top: -10px; width: 14px;
}
/* The header that opens a section or a firm's group in the firm and person lists: quiet, uppercase,
   the way the design separates one group from the next without a box. A section stands out a step more. */
.group-row td {
    background: var(--surface-sunken); color: var(--text-muted); font-size: var(--text-2xs); font-weight: var(--fw-semibold);
    letter-spacing: 0.07em; padding: var(--space-2) var(--space-4); text-transform: uppercase;
}
.section-row td {
    background: var(--surface-card); border-top: 1px solid var(--border-subtle); color: var(--text-strong); font-size: var(--text-xs);
    font-weight: var(--fw-semibold); padding: var(--space-3) var(--space-4) var(--space-2);
}
.group-count { color: var(--text-subtle); font-family: var(--font-mono); font-variant-numeric: tabular-nums; margin-left: var(--space-2); }
.group-under { font-weight: var(--fw-regular); letter-spacing: normal; text-transform: none; }
.card-section { color: var(--text-strong); display: block; margin-bottom: var(--space-1); }
/* The evidence column stacks its count, the exemption and the extra lines, right-aligned like the count. */
.company-documents-stack { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
/* The extra lines beneath the count wrap inside the column rather than widen the list; the count itself stays on one line. */
.company-documents-stack .cell-sub { text-align: right; white-space: normal; }
@media (max-width: 1100px) { .company-list .company-projects { display: none; } }
@media (max-width: 900px) { .company-list .company-contact { display: none; } }
@media (max-width: 640px) {
    .company-list .company-documents, .company-list .company-people { display: none; }
    .company-list .data-table { min-width: 0; width: 100%; }
    .company-list .data-table td, .company-list .data-table th { padding: 12px 10px; }
    .company-list .data-table td:first-child { overflow-wrap: anywhere; }
    .company-list .company-invitation { white-space: normal; }
    .company-list .company-action { width: 1%; }
}

/* The contractor portal shares the shell and the existing tenant workflows. */
.contractor-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: 16px; }
.contractor-card { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; padding: 24px; background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-lg); box-shadow: var(--shadow-xs); color: inherit; text-decoration: none; }
.contractor-card:hover { border-color: var(--border-default); box-shadow: var(--shadow-sm); }
.contractor-card:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 3px; }
.contractor-card h2 { font-size: 18px; margin: 0; }
.contractor-card p { color: var(--text-muted); margin: 0; line-height: 1.6; }
.contractor-card > span:last-child { margin-top: auto; font-weight: 600; padding-top: 8px; }
.contractor-status { margin-bottom: 24px; padding: var(--space-6); background: var(--surface-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-lg); box-shadow: var(--shadow-xs); }
.contractor-status h2 { font-size: var(--text-xl); margin: var(--space-2) 0; }

/* INGO-192: the firms beneath a contractor's own engagement, indented by level. */
.engagement-branch { list-style: none; margin: 0; padding: 0; }
.engagement-branch-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: var(--space-2) 0 var(--space-2) calc(var(--level, 1) * var(--space-5)); border-bottom: 1px solid var(--border-subtle); }
.engagement-branch-row:last-child { border-bottom: none; }
.hierarchy-incoming { margin-top: var(--space-6); }
.hierarchy-incoming-engagement { margin-bottom: var(--space-5); }
.hierarchy-incoming-engagement h3 { font-size: var(--text-md); margin: 0 0 var(--space-2); }

/* NU entry points use the same cards and tokens as the N1 design. */
.contractor-card > .icon { color: var(--navy-700); }
.contractor-status p { line-height: 1.5; }
.contractor-status > .cell-sub:first-child { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: .08em; }
.contractor-own-projects { margin-top: var(--space-6); border-top: 1px solid var(--border-subtle); }
.contractor-own-projects > summary { cursor: pointer; padding: var(--space-5) 0; font-weight: var(--fw-semibold); }
.contractor-own-projects > summary:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }

@media (max-width: 640px) {
    .contractor-cards { gap: var(--space-3); }
    .contractor-card { display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 6px 12px; padding: var(--space-4); }
    .contractor-card > .icon { grid-column: 1; grid-row: 1 / span 3; margin-top: 2px; }
    .contractor-card h2, .contractor-card p, .contractor-card > span:last-child { grid-column: 2; }
    .contractor-card h2 { font-size: var(--text-base); line-height: 1.4; }
    .contractor-card p { font-size: var(--text-sm); line-height: 1.5; }
    .contractor-card > span:last-child { font-size: var(--text-xs); padding-top: 6px; }
    .contractor-status { padding: var(--space-5); margin-bottom: var(--space-5); }
    .contractor-status .btn-primary { width: 100%; box-sizing: border-box; justify-content: center; }
    .contractor-shell :is(.btn-primary, .btn-secondary, .modal-close, .tab, .profile-tab, .segment, .pager-size select) { min-height: 44px; box-sizing: border-box; }
    .contractor-shell .modal-close { min-width: 44px; flex: none; }
    .contractor-shell :is(.search-input, .segment-filter, .trade-select, .modal input:not([type=checkbox]), .modal select, .modal textarea) { font-size: 16px; min-height: 44px; min-width: 0; }
    .contractor-shell .modal { box-sizing: border-box; max-height: calc(100dvh - 24px); overflow-wrap: anywhere; }
    .contractor-shell .modal-head { align-items: flex-start; gap: var(--space-3); }
    .contractor-shell .modal-head h2 { line-height: 1.4; margin: 8px 0; }
    .contractor-shell .modal-actions { flex-wrap: wrap; }
    .contractor-shell .modal-actions > button { flex: 1 1 auto; justify-content: center; }
    .contractor-shell .list-card-actions { flex-wrap: wrap; }
    .contractor-shell .list-card-actions > button { flex: 1 1 auto; justify-content: center; }
    /* Keep one release component and one set of rows: on phones each order
       becomes a card, with its expanded detail immediately below it. */
}

@media (max-width: 640px) {
    .contractor-shell .table-mobile-cards { overflow: visible; border: 0; background: transparent; box-shadow: none; }
    .contractor-shell .table-mobile-cards :is(table, tbody) { display: block; width: 100%; }
    .contractor-shell .table-mobile-cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
    .contractor-shell .table-mobile-cards tr { display: flex; flex-direction: column; gap: 10px; padding: var(--space-4); margin-bottom: var(--space-3); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); background: var(--surface-card); }
    .contractor-shell .table-mobile-cards td { display: block; min-width: 0; padding: 0; border: 0; overflow-wrap: anywhere; }
    .contractor-shell .table-mobile-cards td[data-label]::before { content: attr(data-label); display: block; font: var(--fw-medium) var(--text-2xs) / 1.5 var(--font-sans); color: var(--text-muted); margin-bottom: 2px; }
    .contractor-shell .table-mobile-cards .cell-action { text-align: left; }
    .contractor-shell .table-mobile-cards .cell-action button { width: 100%; justify-content: center; }
    .contractor-shell .table-mobile-cards .btn-link { text-align: left; min-height: 44px; }
}

.profile-more-toggle { display: none; }
.profile-secondary-actions { display: contents; }
.profile-more-toggle[aria-expanded=true] .icon { transform: rotate(180deg); }
@media (max-width: 640px) {
    .contractor-shell .profile-actions:has(.profile-secondary-actions button) .profile-more-toggle { display: flex; grid-column: 1 / -1; justify-content: center; gap: 8px; color: var(--text-muted); background: transparent; border-color: transparent; }
    .contractor-shell .profile-secondary-actions { display: none; }
    .contractor-shell .profile-secondary-actions.open { display: grid; grid-column: 1 / -1; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); }
}

/* The second lock in front of the upload link and the status page (V102):
   the code and, where on file, the birth date, on both account-free doors. */
.access-challenge form + form { margin-top: var(--space-3); }
.access-challenge label {
    display: block;
    font-size: var(--text-sm);
    font-weight: var(--fw-semibold);
    margin: 0 0 var(--space-4);
}
.access-challenge input:not([type="hidden"]) {
    display: block;
    width: 100%;
    box-sizing: border-box;
    min-height: 44px;
    margin-top: var(--space-1);
    padding: 9px 10px;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-md);
    background-color: var(--surface-card);
    font-family: var(--font-sans);
    /* 16px keeps a phone from zooming into the field. */
    font-size: 16px;
}
.access-challenge input[name="code"] { letter-spacing: 0.3em; }
.access-challenge input:focus { outline: none; border-color: var(--amber-500); }
.access-challenge-banner {
    background: var(--danger-100);
    color: var(--danger-text);
    border-radius: var(--radius-md);
    font-size: var(--text-sm);
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
}

/* The two wage administration pages - statutory rates and a person's wage
   classification - share one form layout. */
.wage-admin { display: grid; gap: 24px; max-width: 1120px; }
.wage-fields { display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 20px; }
.wage-field { display: grid; gap: 8px; font-size: .875rem; font-weight: 600; margin-bottom: 20px; }
.wage-field input, .wage-field select, .wage-field textarea { padding: 10px 12px; border: 1px solid var(--border-subtle, #d9dee6); border-radius: 10px; font: inherit; background: white; color: inherit; }
.wage-field textarea { width: 100%; box-sizing: border-box; }
.wage-source { overflow-wrap: anywhere; max-width: 420px; }
@media(max-width: 680px) { .wage-fields { display: grid; } }

/* The expiries' row: hand in the new document first, remind and open in words beside it. */
.expiry-actions { align-items: center; display: flex; gap: 14px; justify-content: flex-end; white-space: nowrap; }

/* How long a piece has waited or has left, in the design's mono chip (U4, G12):
   quiet while there is time, amber when it gets close, red when it is late. */
.waiting {
    border-radius: var(--radius-sm);
    display: inline-block;
    font-family: var(--font-mono);
    font-size: var(--text-2xs);
    font-weight: var(--fw-semibold);
    font-variant-numeric: tabular-nums;
    padding: 4px 8px;
    white-space: nowrap;
}

.waiting-neutral {
    background: var(--gray-100);
    color: var(--gray-500);
}

.waiting-warning {
    background: var(--warning-100);
    color: var(--warning-text);
}

.waiting-danger {
    background: var(--danger-100);
    color: var(--danger-text);
}


/* "Firma" beside a holder that is a firm, not a person. */
.tag {
    background: var(--gray-100);
    border-radius: var(--radius-pill);
    color: var(--gray-600);
    font-size: 10px;
    font-weight: var(--fw-semibold);
    letter-spacing: 0.06em;
    margin-left: 8px;
    padding: 2px 8px;
    text-transform: uppercase;
}

.review-filters label.segment-filter { font-size: 13px; }
.expiry-filters .segment-filter { margin-left: 0; }
.company-engagement-state { margin: 4px 0 0 16px; }

/* A page's one action above its list's head, at the right (G1, G2, G5, G6 in DS26). */
.page-actions {
    display: flex;
    justify-content: flex-end;
    margin-bottom: var(--space-4);
}

.page-actions .btn-primary,
.project-head-actions .btn-primary {
    padding: 11px 18px;
}

/* ==== Page change =========================================================
   One page fading into the next, begun in Routes and held open by
   js/view-transition.js. Browsers without the API change pages as before. */
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
    animation-duration: var(--duration-page);
    animation-timing-function: var(--ease-standard);
}

/* The sidebar is not part of the page: it stands in its own layer and shows
   the state it has after the change - the entry that is now current is lit at
   once, not dissolved into - while the page fades beside it. Every page in
   the circuit has the sidebar on both sides of a change, so there is always
   an old and a new image to choose between. */
::view-transition-old(sidebar) {
    display: none;
}

::view-transition-new(sidebar) {
    animation: none;
}

/* The back of an ID card on site appears with the kind (INGO-321, form-check.js). */
.site-upload[hidden],
.site-verify-error[hidden] {
    display: none;
}

/* The drawing area a person signs on (SignaturePad, js/signature-pad.js):
   a wide, dashed field the finger does not scroll, its buttons in one row.
   A handed-over pad (data-signed) is locked and says so by its border. */
.signature-pad {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.signature-pad-canvas {
    display: block;
    width: 100%;
    height: clamp(140px, 28vw, 280px);
    border: 2px dashed var(--border-strong);
    border-radius: var(--radius-md);
    background: var(--surface-sunken);
    touch-action: none;
    box-sizing: border-box;
}

.signature-pad[data-signed="1"] .signature-pad-canvas {
    border-style: solid;
    border-color: var(--border-default);
}

.signature-pad-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: center;
    justify-content: space-between;
}

.signature-pad-empty {
    color: var(--danger-text);
    font-weight: var(--fw-semibold);
    margin: 0;
}

/* The sheet the person signs a briefing on (V167): wide, the person on top,
   the sentence large enough to read in someone else's hand. Held upright,
   the device asks to be turned. */
.briefing-signature-sheet {
    max-width: 960px;
}

.briefing-signature-sheet [hidden] {
    display: none !important;
}

.briefing-signer {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    margin-bottom: var(--space-3);
}

.briefing-signer .site-person-photo {
    width: 72px;
    height: 90px;
    object-fit: cover;
    border-radius: var(--radius-md);
}

.briefing-signer-name {
    font-size: 1.375rem;
    font-weight: var(--fw-semibold);
    color: var(--text-strong);
    margin: 0;
}

.briefing-declaration {
    font-size: 1.125rem;
    line-height: 1.5;
    color: var(--text-strong);
    margin: 0 0 var(--space-1);
}

.briefing-declaration-meta {
    color: var(--text-muted);
    font-size: var(--text-sm);
    margin: 0 0 var(--space-3);
}

.briefing-rotate-hint {
    display: none;
    color: var(--text-muted);
    font-size: var(--text-sm);
}

@media (orientation: portrait) and (max-width: 40rem) {
    .briefing-rotate-hint {
        display: block;
    }
}

.briefing-handback {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.briefing-unsigned-reasons {
    border: 0;
    padding: 0;
    margin: var(--space-3) 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.briefing-unsigned-reason {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 44px;
}

/* The proof of the briefings confirmed for a person, on the person page. */
.briefing-proof-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.briefing-proof {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--border-subtle);
}

.briefing-proof:last-child {
    border-bottom: 0;
}

.briefing-proof-main {
    min-width: 0;
}

.briefing-proof-name {
    margin: 0;
}

.briefing-proof-main .cell-sub {
    margin: 2px 0 0;
}

.briefing-signature-frame {
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    padding: var(--space-2);
    color: var(--text-strong);
}

.signature-image {
    display: block;
    width: 100%;
    height: auto;
}
