/* One block per shared component (docs/design/03-design-system.md). Tokens only: no literal colours or sizes. */

/* === Icon === */
/* {% icon %} / zukoIcon (apps/core/icons.py): a line icon the size of the text it sits in, in its
   colour. A rule elsewhere sizes one with font-size. */
.icon {
    display: inline-block;
    flex: none;
    width: 1em;
    height: 1em;
    vertical-align: -0.125em;
    overflow: visible;
}
.icon-xs { font-size: 0.75em; }
/* A column of icons beside text: a 1.25em box, so the text after each starts in line. */
.icon-fw { box-sizing: content-box; padding-inline: 0.125em; }
/* A mark cut out of a filled disc (circle-check-solid). */
.icon .icon-knockout { stroke: var(--surface); }
.icon-spin { animation: icon-spin 1s linear infinite; }
@keyframes icon-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .icon-spin { animation-duration: 3s; }
}

/* === Button === */
/* Bootstrap's .btn in four looks: primary, secondary (.btn-outline-secondary), destructive, and solid
   danger (.btn-danger) for a confirm that deletes or loses something. */
.btn-primary,
.btn-outline-secondary,
.btn-destructive,
.btn-danger {
    --bs-btn-font-weight: 600;
    --bs-btn-border-radius: var(--radius-control);
    --bs-btn-focus-box-shadow: 0 0 0 var(--space-1) var(--accent-tint);
    --bs-btn-disabled-opacity: 1;
    --bs-btn-disabled-color: var(--ink-3);
    --bs-btn-disabled-bg: var(--fill-disabled);
    --bs-btn-disabled-border-color: var(--fill-disabled);
}
/* Padding-free and line-height-sized, so one line of text lands exactly on --control-h. */
.btn:not(.btn-sm, .btn-lg, .btn-compact, .btn-group-sm > *, .input-group-sm > *):is(.btn-primary, .btn-outline-secondary, .btn-destructive, .btn-danger) {
    --bs-btn-padding-y: 0;
    --bs-btn-font-size: var(--control-font);
    --bs-btn-line-height: calc(var(--control-h) - 2 * var(--bs-btn-border-width));
}
/* A row's own action (Review in a list or request cell): 28px under a mouse, a control high on touch. */
.btn.btn-compact {
    --bs-btn-padding-y: 0;
    --bs-btn-padding-x: calc(var(--space-3) + var(--space-1) / 2);
    --bs-btn-font-size: 0.78125rem;
    --bs-btn-font-weight: 600;
    --bs-btn-line-height: calc(var(--space-6) - var(--space-1) - 2 * var(--bs-btn-border-width));
    white-space: nowrap;
}
@media (pointer: coarse) {
    .btn.btn-compact { --bs-btn-line-height: calc(var(--control-h) - 2 * var(--bs-btn-border-width)); }
}
.btn-primary {
    --bs-btn-color: var(--surface);
    --bs-btn-bg: var(--accent);
    --bs-btn-border-color: var(--accent);
    --bs-btn-hover-color: var(--surface);
    --bs-btn-hover-bg: var(--accent-hover);
    --bs-btn-hover-border-color: var(--accent-hover);
    --bs-btn-active-color: var(--surface);
    --bs-btn-active-bg: var(--accent-hover);
    --bs-btn-active-border-color: var(--accent-hover);
}
.btn-outline-secondary {
    --bs-btn-color: var(--ink);
    --bs-btn-bg: var(--surface);
    --bs-btn-border-color: var(--line-strong);
    --bs-btn-hover-color: var(--ink);
    --bs-btn-hover-bg: var(--sunken);
    --bs-btn-hover-border-color: var(--line-strong);
    --bs-btn-active-color: var(--accent-ink);
    --bs-btn-active-bg: var(--accent-wash);
    --bs-btn-active-border-color: var(--accent);
}
.btn-destructive {
    --bs-btn-color: var(--danger);
    --bs-btn-bg: var(--surface);
    --bs-btn-border-color: var(--line-strong);
    --bs-btn-hover-color: var(--danger);
    --bs-btn-hover-bg: var(--sunken);
    --bs-btn-hover-border-color: var(--danger);
    --bs-btn-active-color: var(--danger);
    --bs-btn-active-bg: var(--sunken);
    --bs-btn-active-border-color: var(--danger);
}
/* A secondary square action (Today's Log beside a visit): the accent's wash, an accent icon. */
.btn-wash {
    --bs-btn-color: var(--accent-ink);
    --bs-btn-bg: var(--accent-wash);
    --bs-btn-border-color: var(--accent-tint);
    --bs-btn-hover-color: var(--accent-hover);
    --bs-btn-hover-bg: var(--accent-tint);
    --bs-btn-hover-border-color: var(--accent-tint);
    --bs-btn-active-color: var(--accent-hover);
    --bs-btn-active-bg: var(--accent-tint);
    --bs-btn-active-border-color: var(--accent);
}
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: var(--control-h);
    height: var(--control-h);
    padding: 0;
    line-height: 1;
}
.btn-icon.btn-outline-secondary {
    --bs-btn-color: var(--ink-2);
}
/* A text action in the accent (Edit, + Add, Show more): no box. */
.link-action {
    padding: 0;
    border: 0;
    background: none;
    color: var(--accent-ink);
    font: var(--text-small);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}
.link-action:hover { color: var(--accent-hover); }
.link-action:disabled { color: var(--ink-3); cursor: not-allowed; }
/* A collapse toggle's two labels: Show … while closed, Hide … while open. */
.when-closed,
.collapsed > .when-open { display: none; }
.collapsed > .when-closed { display: inline; }

/* A chip-sized action inside a card ("Credit pending · Review"): the state pill's size in the
   accent's wash, never a state's colour. */
.action-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.15em 0.7em;
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--accent-wash);
    color: var(--accent-ink);
    font: var(--text-micro);
    font-weight: 600;
    white-space: nowrap;
}
.action-chip:hover { background: var(--accent-tint); }

/* On touch a small control takes a finger: a transparent hit area at least the control's height
   (44px) square, centred on it, grows the target and leaves the look alone. .hit-target opts any
   other small text action or icon button in. */
@media (pointer: coarse) {
    :is(.hit-target, .link-action, .action-chip, .timeline-entry-action, .timeline-reply-toggle,
        .selection-head-all, .form-check-input) {
        position: relative;
    }
    :is(.hit-target, .link-action, .action-chip, .timeline-entry-action, .timeline-reply-toggle,
        .selection-head-all, .form-check-input)::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        width: max(100%, var(--control-h));
        height: max(100%, var(--control-h));
        transform: translate(-50%, -50%);
    }
}

/* A decision on a row or card (approve / refuse a PO): a compact ✓ or ✗ in the done and refused
   tones, the outcome it records. */
.btn-decide {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: calc(var(--control-h) * 0.95);
    height: calc(var(--control-h) * 0.8);
    padding: 0;
    border: thin solid color-mix(in srgb, currentColor 35%, transparent);
    border-radius: var(--radius-control);
    font-size: 0.875rem;
    line-height: 1;
}
.btn-decide--approve { background: var(--tone-done-fill); color: var(--tone-done-ink); }
.btn-decide--refuse { background: var(--tone-refused-fill); color: var(--tone-refused-ink); }
.btn-decide:hover { border-color: currentColor; }

/* === State pill === */
/* components/_state_pill.html. `badge` stays on the markup: the e2e suites locate status through it. */
.state-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.34em;
    padding: 0.15em 0.7em;
    border-radius: var(--radius-pill);
    font: var(--text-micro);
    font-weight: 600;
    white-space: nowrap;
    background: var(--sp-bg, var(--tone-closed-fill));
    color: var(--sp-fg, var(--tone-closed-ink));
    border: thin solid var(--sp-bd, transparent);
}
.state-pill--draft {
    --sp-bg: var(--tone-draft-fill);
    --sp-fg: var(--tone-draft-ink);
    --sp-bd: var(--line-strong);
    border-style: dashed;
}
.state-pill--pending {
    --sp-bg: var(--tone-pending-fill);
    --sp-fg: var(--tone-pending-ink);
}
/* Decided yes but not yet written to SAP: discounts only; cases has no in-flight state. */
.state-pill--inflight {
    --sp-bg: var(--tone-inflight-fill);
    --sp-fg: var(--tone-inflight-ink);
}
.state-pill--done {
    --sp-bg: var(--tone-done-fill);
    --sp-fg: var(--tone-done-ink);
}
/* A person saying no is tonal; SAP refusing the write is solid. They must not match. */
.state-pill--refused {
    --sp-bg: var(--tone-refused-fill);
    --sp-fg: var(--tone-refused-ink);
}
.state-pill--failed {
    --sp-bg: var(--tone-failed-fill);
    --sp-fg: var(--tone-failed-ink);
}
.state-pill--closed {
    --sp-bg: var(--tone-closed-fill);
    --sp-fg: var(--tone-closed-ink);
}
/* A pill that opens its record is a <button>. */
button.state-pill {
    cursor: pointer;
}

/* === Stage band === */
/* components/stage_band.html; refused / failed reuse the state-pill tones. */
.stageband-steps {
    display: flex;
    margin: 0;
    padding: 0;
    list-style: none;
}
.stageband-step {
    --node: var(--space-5);
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    color: var(--ink-3);
    font: var(--text-small);
    font-weight: 600;
    text-align: center;
}
/* The connector: the left half by ::before, the right half by ::after, a gap either side of the node.
   The line into a stage is the accent once that stage is reached, and on out of it once the next is. */
.stageband-step::before,
.stageband-step::after {
    content: "";
    position: absolute;
    top: calc(var(--node) / 2 - var(--space-1) / 4);
    height: calc(var(--space-1) / 2);
    background: var(--line-strong);
}
.stageband-step::before {
    left: 0;
    right: calc(50% + var(--node) / 2 + var(--space-1));
}
.stageband-step::after {
    left: calc(50% + var(--node) / 2 + var(--space-1));
    right: 0;
}
.stageband-step:first-child::before,
.stageband-step:last-child::after {
    content: none;
}
.stageband-step:is(.stageband-step--done, .stageband-step--current, .stageband-step--refused, .stageband-step--failed)::before,
.stageband-step--onward::after {
    background: var(--accent);
}
.stageband-step > form {
    min-width: 0;
    display: flex;
}
.stageband-step > form > button {
    flex: 1;
}
.stageband-step > :not(form, .stageband-detail),
.stageband-step > form > button {
    min-width: 0;
    min-height: var(--control-h);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    line-height: 1.2;
    text-decoration: none;
}
.stageband-node {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--node);
    height: var(--node);
    border: calc(var(--space-1) * 3 / 8) solid var(--line-strong);
    border-radius: var(--radius-pill);
    background: var(--surface);
    color: var(--ink-3);
    font: var(--text-small);
    font-weight: 700;
}
.stageband-label {
    display: -webkit-box;
    max-width: 100%;
    padding: 0 var(--space-1);
    overflow: hidden;
    overflow-wrap: anywhere;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}
.stageband-step--done {
    color: var(--ink-2);
}
.stageband-step--done .stageband-node {
    border-color: transparent;
    background: var(--accent-tint);
    color: var(--accent-ink);
}
.stageband-step--current {
    color: var(--accent-ink);
    font-weight: 700;
}
.stageband-step--current .stageband-node {
    border-color: var(--accent);
    background: var(--accent);
    color: var(--surface);
    box-shadow: 0 0 0 var(--space-1) var(--accent-wash);
}
.stageband-step:is(.stageband-step--refused, .stageband-step--failed),
.stageband-name:is(.stageband-name--refused, .stageband-name--failed) {
    color: var(--tone-refused-ink);
    font-weight: 700;
}
.stageband-step--refused .stageband-node {
    border-color: transparent;
    background: var(--tone-refused-fill);
    color: var(--tone-refused-ink);
}
.stageband-step--failed .stageband-node {
    border-color: var(--tone-failed-fill);
    background: var(--tone-failed-fill);
    color: var(--tone-failed-ink);
    box-shadow: 0 0 0 var(--space-1) var(--tone-refused-fill);
}
/* A stage that doesn't apply to this record, or was never reached after a refusal. */
.stageband-step--skipped .stageband-node {
    border-style: dashed;
}
.stageband-step--skipped .stageband-label {
    text-decoration: line-through;
}
/* A stage's details under its label (Discount codes' outcome, who and comment). */
.stageband-detail {
    margin-top: var(--space-1);
    padding: 0 var(--space-2);
    color: var(--ink-2);
    font-weight: 400;
    overflow-wrap: anywhere;
}
.stageband-step :is(a, button) {
    cursor: pointer;
}
.stageband-step :is(button:disabled, [aria-disabled="true"]) {
    cursor: not-allowed;
}
.stageband-step :is(a, button:enabled):hover .stageband-label {
    text-decoration: underline;
}
.stageband-step :is(a, button:enabled):hover .stageband-node {
    box-shadow: 0 0 0 var(--space-1) var(--accent-wash);
}
.stageband-step :is(a, button):focus-visible {
    outline: 0;
}
.stageband-step :is(a, button):focus-visible .stageband-node {
    outline: calc(var(--space-1) / 2) solid var(--accent);
    outline-offset: calc(var(--space-1) / 2);
}
.stageband-name {
    display: none;
}
@media (pointer: coarse) {
    .stageband-step {
        --node: calc(var(--space-5) + var(--space-1) / 2);
    }
}
@media (max-width: 599.98px) {
    /* numbered: the nodes alone, the current (or failed or refused) stage, or the caption, named under them. */
    .stageband--numbered .stageband-label {
        display: none;
    }
    .stageband--numbered .stageband-name {
        display: block;
        margin-top: var(--space-1);
        font: var(--text-small);
        font-weight: 700;
        color: var(--accent-ink);
        text-align: center;
    }
    .stageband--numbered .stageband-name:is(.stageband-name--refused, .stageband-name--failed) {
        color: var(--tone-refused-ink);
    }
    /* vertical: the stages in a column joined by a 2px line, each name and its details beside its node. */
    .stageband--vertical .stageband-steps {
        flex-direction: column;
    }
    .stageband--vertical .stageband-step {
        padding-bottom: var(--space-4);
        font: var(--text-body);
        font-weight: 600;
        text-align: left;
    }
    .stageband--vertical .stageband-step:is(.stageband-step--current, .stageband-step--refused, .stageband-step--failed) {
        font-weight: 700;
    }
    .stageband--vertical .stageband-step:last-child {
        padding-bottom: 0;
    }
    .stageband--vertical .stageband-step::before {
        content: none;
    }
    .stageband--vertical .stageband-step::after {
        top: calc(var(--node) + var(--space-1));
        bottom: var(--space-1);
        left: calc(var(--node) / 2 - var(--space-1) / 4);
        right: auto;
        width: calc(var(--space-1) / 2);
        height: auto;
    }
    .stageband--vertical .stageband-step > :not(form, .stageband-detail),
    .stageband--vertical .stageband-step > form > button {
        min-height: 0;
        flex-direction: row;
        gap: var(--space-3);
    }
    .stageband--vertical .stageband-label {
        padding: 0;
    }
    .stageband--vertical .stageband-detail {
        margin-top: 0;
        padding: 0 0 0 calc(var(--node) + var(--space-3));
        font: var(--text-small);
    }
}

/* === Breadcrumb === */
.crumb {
    font: var(--text-body);
    color: var(--ink-2);
}

.crumb-back {
    font-weight: 600;
    color: var(--accent-ink);
    text-decoration: none;
    white-space: nowrap;
}

.crumb-back:hover,
.crumb-back:focus-visible {
    color: var(--accent-hover);
}

.crumb-sep {
    margin: 0 var(--space-1);
    color: var(--ink-3);
}

/* A record's ⋯ (and a diet plan's save status) at the right of a phone's top bar: the bar is a
   row, the breadcrumb shrinks to an ellipsis and the ⋯ always shows. */
.app-header:has(> .topbar-more) {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
.app-header:has(> .topbar-more) > .crumb {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.topbar-more {
    display: flex;
    flex: none;
    margin-left: auto;
    align-items: center;
    gap: var(--space-2);
    height: var(--topbar-h);
    line-height: normal;
}
.topbar-more-toggle {
    --bs-btn-color: var(--ink);
    --bs-btn-hover-color: var(--ink);
}

/* === Search box and filter chips === */
/* components/_list_search_bar.html: .search-input-wrap is the visible box, the chips sit inside it. */
.search-box {
    display: flex;
    width: 100%;
    align-items: flex-start;
    gap: var(--space-2);
}
.search-input-wrap {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    min-height: var(--control-h);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1) var(--space-2);
    padding: var(--space-1) var(--space-3);
    background: var(--surface);
    border: thin solid var(--line-strong);
    border-radius: var(--radius-control);
    cursor: text;
}
.search-input-wrap:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 var(--space-1) var(--accent-wash);
}
.search-box-icon { flex: none; color: var(--ink-3); }
.search-relevance { display: contents; }
.search-input-wrap-inner { flex: 1 1 calc(var(--space-7) * 2); min-width: calc(var(--space-7) * 2); }
.search-input-bare {
    width: 100%;
    padding: 0;
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--ink);
    font: var(--text-body);
    font-size: var(--control-font);
}
.search-input-bare::placeholder { color: var(--ink-3); }
.search-combinator { font: var(--text-small); color: var(--ink-2); text-decoration: none; }

.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    min-width: 0;
    max-width: calc(var(--space-7) * 6);
    min-height: calc(var(--control-h) - var(--space-3));
    padding: 0 var(--space-3);
    border-radius: var(--radius-pill);
    background: var(--accent-wash);
    color: var(--accent-ink);
    font: var(--text-small);
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none;
}
.filter-chip--group { background: var(--sunken); color: var(--ink-2); }
.filter-chip--muted { background: var(--surface); border: thin solid var(--line); color: var(--ink-2); }
a.filter-chip:hover { color: var(--accent-hover); }
.filter-chip .chip-label,
.filter-chip .chip-remove {
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-decoration: none;
}
.filter-chip .chip-label { flex: none; cursor: pointer; }
/* The whole chip opens its rule; the × keeps its own job. */
.search-chip:has(.chip-label[data-edit-rules]) { cursor: pointer; }
.filter-chip .chip-values { display: inline-flex; align-items: center; gap: var(--space-1); min-width: 0; }
.filter-chip .chip-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.filter-chip .chip-or { font-style: normal; font-weight: 400; color: var(--ink-2); }
/* A wide hit target for the ×, pulled back out of the chip's own padding. */
.filter-chip .chip-remove {
    flex: none;
    align-self: stretch;
    display: inline-flex;
    align-items: center;
    padding-inline: var(--space-2);
    margin-inline-end: calc(-1 * var(--space-2));
    cursor: pointer;
}

.search-filter-btn {
    flex: none;
    min-height: var(--control-h);
    padding: 0 var(--space-3);
    border: thin dashed var(--line-strong);
    border-radius: var(--radius-pill);
    background: var(--surface);
    color: var(--ink-2);
    font: var(--text-small);
    font-weight: 600;
    white-space: nowrap;
}
.search-filter-btn:hover,
.search-filter-btn[aria-expanded="true"] { border-color: var(--accent); color: var(--accent-ink); }
.search-menu-btn {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--control-h);
    height: var(--control-h);
    padding: 0;
    border: thin solid var(--line-strong);
    border-radius: var(--radius-control);
    background: var(--surface);
    color: var(--ink-2);
}
.search-menu-btn:hover,
.search-menu-btn[aria-expanded="true"] { border-color: var(--accent); background: var(--accent-wash); color: var(--accent-ink); }

/* One-tap presets beside the box (quick_filters). On a narrow screen the box takes its own
   line and they wrap under it, with + Filter. */
.search-quick { flex: none; align-self: center; }
@media not all and (pointer: fine), (max-width: 1023.98px) {
    .search-box--quick { flex-wrap: wrap; }
    .search-box--quick .search-input-wrap { flex-basis: 100%; }
}

/* The typeahead, anchored to the whole box. */
.search-autocomplete {
    display: block;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin-top: var(--space-1);
    z-index: var(--z-dropdown);
    max-height: calc(var(--space-7) * 7);
    overflow-y: auto;
}
.search-autocomplete .ac-item { padding: var(--space-2) var(--space-3); cursor: pointer; }
.search-autocomplete .ac-item.active,
.search-autocomplete .ac-item:hover { background: var(--accent-wash); }
/* A suggestion's name, then the line that tells two of the same name apart. */
.search-autocomplete .ac-item .ac-label { display: block; font-weight: 600; }
.search-autocomplete .ac-item .ac-sub { display: block; font: var(--text-small); }

/* The ▾'s Filters / Group By / Favorites menu, from the box's left edge: over the rail where it
   reaches it (Bootstrap's 1000 is under the shell). */
.search-bar-menu {
    z-index: var(--z-dropdown);
    min-width: min(calc(var(--space-7) * 16), calc(100vw - var(--space-6)));
}
.search-bar-menu-favorites { min-height: 0; }
.search-bar-menu-saved { max-height: calc(var(--space-7) * 5); }
@media (min-width: 768px) {
    .search-bar-menu-col { border-right: thin solid var(--line); }
}

/* Custom Filter rows. select2 writes an inline width, which min/max-width outrank. */
.custom-filter-row { display: flex; align-items: center; gap: var(--space-2); }
/* Under a mouse a thin rule between rules; on touch each is a card (below). */
@media (pointer: fine) {
    #customFilterRules .custom-filter-row + .custom-filter-row { padding-top: var(--space-2); border-top: thin solid var(--line-soft); }
}
.custom-filter-row .field-select { flex: 0 0 auto; width: auto; }
.custom-filter-row .field-select + .select2-container {
    flex: 0 0 calc(var(--space-7) * 5);
    min-width: calc(var(--space-7) * 5);
    max-width: calc(var(--space-7) * 5);
}
.custom-filter-row .op-select { flex: 0 0 auto; width: auto; max-width: calc(var(--space-6) * 6); }
.custom-filter-row .op-select + .select2-container { flex: 0 0 auto; max-width: calc(var(--space-6) * 6); }
.custom-filter-row .value-cell { flex: 1 1 0; min-width: 0; }
.custom-filter-row .value-cell > * { width: 100%; }
/* Below lg the modal narrows: field and operator take a line each. */
@media (max-width: 991.98px) {
    .custom-filter-row { flex-wrap: wrap; }
    .custom-filter-row .field-select,
    .custom-filter-row .op-select { flex: 1 1 100%; width: 100%; max-width: none; min-width: 0; }
    .custom-filter-row :is(.field-select, .op-select) + .select2-container { flex: 1 1 100%; min-width: 100%; max-width: 100%; }
}
/* Full screen on touch: a card per rule, the field and its trash can over the operator and value. */
@media (pointer: coarse) {
    .modal-sheet--full .custom-filter-row {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
        align-items: center;
    }
    .modal-sheet--full .custom-filter-row :is(.field-select, .field-select + .select2-container) { grid-area: 1 / 1 / 2 / 3; width: 100%; min-width: 0; max-width: none; }
    .modal-sheet--full .custom-filter-row .row-remove { grid-area: 1 / 3; padding: var(--space-2); }
    .modal-sheet--full .custom-filter-row :is(.op-select, .op-select + .select2-container) { grid-area: 2 / 1; width: 100%; max-width: none; }
    .modal-sheet--full .custom-filter-row .value-cell { grid-area: 2 / 2 / 3 / 4; }
}

/* Quick-search hits (quick_highlight.js, search_autocomplete.js). */
.search-autocomplete mark.quick-hit,
.list-table mark.quick-hit,
.list-cards mark.quick-hit { padding: 0; background: var(--tone-pending-fill); color: inherit; }

/* === List: table, cards, count, pages === */
/* components/list.html: cards first; a table under a fine pointer from 1024px. */
.list { display: flex; flex-direction: column; gap: var(--space-3); }
.list-count { font: var(--text-small); color: var(--ink-2); }

.list-cards { display: flex; flex-direction: column; gap: var(--space-2); }
/* The title's link is stretched over the card; a control inside (a status chip that is a
   button) sits above it. */
.list-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-3);
    background: var(--surface);
    border: thin solid var(--line);
    border-radius: var(--radius-card);
    color: var(--ink);
}
.list-card:hover { border-color: var(--line-strong); }
/* The row a pane beside the list shows (pane_target, current_url). */
.list-card[aria-current="true"] { background: var(--accent-wash); border-color: var(--accent); box-shadow: inset calc(var(--space-1) * 3 / 4) 0 0 var(--accent); }
.list-card-kicker {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    min-width: 0;
    font: var(--text-small);
    color: var(--ink-3);
}
.list-card-kicker > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-card-kicker > .mono { flex: none; color: var(--ink-2); }
.list-card-corner { flex: none; margin-left: auto; }
.list-card-title {
    font: var(--text-body);
    font-weight: 600;
    color: var(--ink);
    text-decoration: none;
    overflow-wrap: anywhere;
}
a.list-card-title::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.list-card-title:hover { color: var(--ink); }
.list-card-subtitle { font: var(--text-small); color: var(--ink-2); }
.list-card-meta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
    font: var(--text-small);
    color: var(--ink-2);
}
.list-card-meta-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-card-meta-text .list-cell-main { display: inline; max-width: none; }
.list-card-aside { flex: none; display: inline-flex; }
.list-card-status { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.list-card-status :is(a, button) { position: relative; z-index: 1; }
.list-more {
    padding: var(--space-2) 0;
    font: var(--text-small);
    color: var(--ink-3);
    text-align: center;
}
.list-more-btn {
    padding: 0;
    border: 0;
    background: none;
    color: var(--accent-ink);
    font: inherit;
    font-weight: 600;
}
.list-more.htmx-request { opacity: 0.6; }

.list-table-card,
.list-table-frame { display: none; }
.list-table { width: 100%; border-collapse: separate; border-spacing: 0; }
.list-table th {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: calc(var(--space-2) + var(--space-1) / 2) var(--space-2);
    background: var(--table-head);
    border-bottom: thin solid var(--line);
    color: var(--ink-2);
    font: var(--text-micro);
    letter-spacing: var(--micro-tracking);
    text-transform: uppercase;
    text-align: left;
    white-space: nowrap;
}
.list-table th a { color: inherit; text-decoration: none; }
/* Cells in ink; a secondary column (Column.muted: a date, a phone) in --ink-2; an empty one's dash faint. */
.list-table td {
    padding: var(--space-2);
    border-bottom: thin solid var(--line-soft);
    color: var(--ink);
    vertical-align: middle;
}
.list-table td.is-muted { color: var(--ink-2); }
.list-dash { color: var(--line-strong); }
.list-table tbody tr:last-child td { border-bottom: 0; }
.list-table tr[data-href] { cursor: pointer; }
.list-table tbody tr:hover { background: var(--page); }
.list-table tbody tr[data-href] { user-select: none; }
.list-table [data-col].col-hidden { display: none; }
.list-table .is-num { text-align: right; font-variant-numeric: tabular-nums; }
/* A wide table scrolls sideways rather than squeezing its title into a column of short lines. */
:is(.list--scroll, .list--fill) .list-table td.list-title { min-width: calc(var(--space-7) * 5); }
.list-row-link { color: var(--ink); font-weight: 600; text-decoration: none; }
.list-row-link:hover { color: var(--accent-ink); }
/* A cell's own pieces (a cell_template): a second line under the first, a person with their
   avatar, a record number that links. Long text truncates rather than widen the table. */
.list-cell-main,
.list-cell-sub {
    display: block;
    max-width: calc(var(--space-7) * 6);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.list-cell-sub { font: var(--text-small); font-weight: 400; color: var(--ink-2); }
.list-person { display: flex; align-items: center; gap: var(--space-2); white-space: nowrap; }
/* A fixed circle round an avatar: a missing photo's alt text must not widen a card. */
.avatar-circle { flex: none; display: inline-flex; border-radius: 50%; overflow: hidden; }
.list-person-name { max-width: calc(var(--space-7) * 3); overflow: hidden; text-overflow: ellipsis; }
/* Several people in one cell (display_tags.people_html), and a person inside a line of text. */
.list-people { display: inline-flex; flex-wrap: wrap; vertical-align: middle; gap: var(--space-1) var(--space-3); }
.list-person--inline { display: inline-flex; gap: var(--space-1); vertical-align: middle; }
:is(.list-person--inline, .fact-value) .list-person-name { max-width: none; }
/* After an imported free-text customer (components/_unlinked.html). */
.unlinked-tag {
    margin-left: var(--space-2);
    padding: 0 var(--space-2);
    border: thin solid var(--line);
    border-radius: var(--radius-pill);
    background: var(--page);
    color: var(--ink-2);
    font: var(--text-micro);
    white-space: nowrap;
}
.list-number-link { color: var(--accent-ink); text-decoration: none; white-space: nowrap; }
.list-number-link:hover { color: var(--accent-hover); }
/* A confidential case's lock after its number (cases/_confidential_lock.html). */
.case-lock { margin-left: var(--space-1); color: var(--ink-2); }
.case-lock svg {
    display: inline-block;
    width: 12px;
    height: 12px;
    vertical-align: -1px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
}
/* The grouped table (components/_grouped_table.html) is a table at every width. */
.list-grouped .list-table-frame {
    display: block;
    overflow-x: auto;
    background: var(--surface);
    border: thin solid var(--line);
    border-radius: var(--radius-card);
}

.list-page-size {
    height: var(--control-h);
    padding: 0 var(--space-2);
    border: thin solid var(--line-strong);
    border-radius: var(--radius-control);
    background: var(--surface);
    color: var(--ink);
    font: inherit;
}
.list-page-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: calc(var(--space-6) - var(--space-1) / 2);
    height: calc(var(--space-6) - var(--space-1) / 2);
    border: thin solid var(--line-strong);
    border-radius: var(--radius-control);
    background: var(--surface);
    color: var(--ink-2);
}
.list-page-btn:disabled { background: var(--page); color: var(--ink-3); }

.list-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-6) var(--space-4);
    background: var(--surface);
    border: thin dashed var(--line-strong);
    border-radius: var(--radius-card);
    color: var(--ink-2);
    text-align: center;
}
.list-empty p { margin: 0; }
.list-empty-clear { color: var(--accent-ink); font-weight: 600; }

/* A badge at the end of the card's title line (a SAP code). */
.list-card-body { display: contents; }
.list-card-head { display: flex; align-items: baseline; gap: var(--space-2); min-width: 0; }
.list-card-head .list-card-title { flex: 1 1 auto; min-width: 0; }
.list-card-badge { flex: none; max-width: 50%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--text-small); color: var(--ink-2); }

/* selectable: .is-selecting shows the cards' ticks; .has-selection swaps the header row for the bulk bar. */
.list-card--selectable { flex-direction: row; align-items: flex-start; gap: var(--space-2); }
.list-card--selectable .list-card-body { display: flex; flex: 1 1 auto; flex-direction: column; gap: var(--space-1); min-width: 0; }
.list-card-check {
    position: relative;
    z-index: 1;
    display: none;
    flex: none;
    align-items: center;
    justify-content: center;
    width: var(--control-h);
    height: var(--control-h);
    margin: calc(-1 * var(--space-2)) 0 calc(-1 * var(--space-2)) calc(-1 * var(--space-2));
    color: var(--ink-3);
}
.list-card-check .form-check-input { width: calc(var(--space-4) + var(--space-1)); height: calc(var(--space-4) + var(--space-1)); margin: 0; }
.is-selecting .list-card-check { display: inline-flex; }
.list-card:has(.row-check:checked) { border-color: var(--accent); box-shadow: inset 0 0 0 calc(var(--space-1) / 4) var(--accent); }
.list-table .list-select { width: var(--space-6); padding-right: 0; }
.list-table .list-select .form-check-input { margin: 0; }
.list-table .list-lock { color: var(--ink-3); }
.list-table tbody tr:has(.row-check:checked) { background: var(--accent-wash); }
.list-table .list-bulk-row { display: none; }
/* collapse, not none: the header row still sizes the columns, so they hold still. */
.has-selection .list-table .list-head-row { visibility: collapse; }
.has-selection .list-table .list-bulk-row { display: table-row; }
/* The selection head (Forage-PO-Desk): the count, Select all and × as one accent chip, then the
   inline actions and More, outlined. */
.list-table th.list-bulk-cell {
    padding: var(--space-1) var(--space-2);
    color: var(--ink);
    font: var(--text-small);
    font-weight: 600;
    letter-spacing: normal;
    text-transform: none;
}
.list-bulk {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--control-h);
}
.list-bulk-chip {
    display: inline-flex;
    align-items: stretch;
    height: var(--control-h);
    overflow: hidden;
    border: thin solid var(--accent);
    border-radius: var(--radius-control);
    background: var(--accent-wash);
    color: var(--accent-ink);
}
.list-bulk-chip > * {
    display: inline-flex;
    align-items: center;
    padding: 0 var(--space-3);
    white-space: nowrap;
}
.list-bulk-chip > [hidden] { display: none; }
.list-bulk-chip > * + * { border-left: thin solid var(--accent-divider); }
.list-bulk-chip-btn {
    column-gap: 0.25em;   /* a flex box drops the spaces around "Select all <n> matching"'s count */
    border-top: 0;
    border-right: 0;
    border-bottom: 0;
    background: none;
    color: inherit;
    font: inherit;
}
.list-bulk-chip-btn:hover { background: var(--accent-tint); }
.list-bulk-chip-btn--clear { padding: 0 var(--space-2); color: var(--ink-2); }
.list-bulk-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    height: var(--control-h);
    padding: 0 var(--space-3);
    border: thin solid var(--line-strong);
    border-radius: var(--radius-control);
    background: var(--surface);
    color: var(--ink);
    font: inherit;
    text-decoration: none;
    white-space: nowrap;
}
.list-bulk-btn:hover { color: var(--ink); background: var(--sunken); }
.list-bulk-btn.disabled { opacity: 0.5; }
.list-bulk .form-check-input { margin: 0; }
.list-bulk .dropdown-menu { font-weight: 400; }

/* .list--cards keeps the cards at any width (a narrow pane). */
@media (pointer: fine) and (min-width: 1024px) {
    .list:not(.list--cards) .list-cards { display: none; }
    /* The table's card, the pager its footer. clip, not hidden: the card must not become the
       header's sticky container. */
    .list:not(.list--cards) .list-table-card {
        display: flex;
        flex-direction: column;
        background: var(--surface);
        border: thin solid var(--line);
        border-radius: var(--radius-card);
        overflow: clip;
    }
    .list:not(.list--cards) .list-table-frame { display: block; }
    .list.list--scroll .list-table-frame { overflow-x: auto; }
    /* fill: the page holds still and the table scrolls inside, both ways, under its header. */
    .list.list--fill { flex: 1 1 auto; min-height: 0; }
    .list.list--fill .list-table-card { flex: 1 1 auto; min-height: 0; }
    .list.list--fill .list-table-frame { flex: 1 1 auto; min-height: 0; overflow: auto; }
    .list-pager {
        flex: none;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        gap: var(--space-2);
        padding: calc(var(--space-2) + var(--space-1) / 2) calc(var(--space-3) + var(--space-1) / 2);
        border-top: thin solid var(--line);
        font: var(--text-small);
        color: var(--ink-2);
    }
}

/* === Grouped list === */
/* components/_grouped_table.html (a full-width header row per group in the tbody) and
   _grouped_cards.html (a header spanning every column). */
.grouped-table .group-header-row > .grp-cell {
    padding-top: 0.4rem;
    padding-bottom: 0.4rem;
    background-color: var(--page);
    border-top: thin solid var(--line);
    border-bottom: thin solid var(--line);
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
}
/* Flex on an inner div: on the <td> it breaks the table layout and collapses the row's target. */
.grouped-table .grp-cell-inner { display: flex; align-items: center; }
.grouped-table .group-header-row:hover > .grp-cell { background-color: var(--sunken); }
.grouped-table .group-header-row[data-level="0"] > .grp-cell { padding-left: var(--space-2); }
.grouped-table .group-header-row[data-level="1"] > .grp-cell { padding-left: 1.75rem; }
.grouped-table .group-header-row[data-level="2"] > .grp-cell { padding-left: var(--space-7); }
.grouped-table .group-header-row[data-level="3"] > .grp-cell { padding-left: 4.25rem; }
.group-chevron {
    width: 0.9rem;
    margin-right: 0.4rem;
    font-size: 0.72rem;
    color: var(--ink-2);
    transition: transform 0.12s ease;
}
.group-header.collapsed .group-chevron { transform: rotate(-90deg); }
.grp-count { margin-left: auto; color: var(--ink-2); font-weight: 400; font-variant-numeric: tabular-nums; }
.grp-hidden { display: none !important; }
.grouped-cards { align-items: start; }
.grouped-cards > .group-header-card,
.grouped-cards > .grouped-cards-full { grid-column: 1 / -1; }
/* A list's grouped cards (contacts on a narrow screen): one column, full width. */
.grouped-cards.list-cards { align-items: stretch; }
.group-header-card {
    display: flex;
    align-items: center;
    padding: 0.4rem 0.6rem;
    background-color: var(--page);
    border: thin solid var(--line);
    border-radius: var(--radius-control);
    font-weight: 500;
    cursor: pointer;
    user-select: none;
}
.group-header-card:hover { background-color: var(--sunken); }
.group-header-card[data-level="1"] { margin-left: 1.25rem; }
.group-header-card[data-level="2"] { margin-left: 2.5rem; }
.group-header-card[data-level="3"] { margin-left: 3.75rem; }
/* A group of people's avatar (core.search.groups.build_groups). */
.group-header .rounded-circle { margin-right: var(--space-2); }

/* === List page === */
/* A list's page region (the *_page_region.html templates; list_page.js, spa_navigate.js). It dims while
   a swap is in flight, and after 150ms a spinner says so: re-rendering 100 grouped rows takes about a
   second, and dimming alone reads as nothing happening. */
[data-spa-region].htmx-request { cursor: progress; }
[data-spa-region].htmx-request > * { opacity: 0.55; pointer-events: none; transition: opacity 0.1s ease-in-out; }
[data-spa-region].htmx-request::after {
    content: "";
    position: fixed;
    top: 50%;
    left: 50%;
    z-index: var(--z-dropdown);
    width: 2.5rem;
    height: 2.5rem;
    margin: -1.25rem 0 0 -1.25rem;
    border: 3px solid var(--line);
    border-top-color: var(--accent);
    border-radius: 50%;
    opacity: 0;
    pointer-events: none;
    animation: region-spin 0.7s linear infinite, region-spinner-in 0.15s linear 0.15s forwards;
}
@keyframes region-spin { to { transform: rotate(360deg); } }
@keyframes region-spinner-in { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
    [data-spa-region].htmx-request::after { animation-duration: 2.4s, 0.15s; }
}

/* Selecting on a narrow screen (list_page.js .is-selecting): the head becomes Cancel / N selected /
   Clear and the selection bar, in the accent, covers the tab bar. */
.selection-head,
.selection-bar { display: none; }
@media not all and (pointer: fine), (max-width: 1023.98px) {
    .is-selecting > .page-head { display: none; }
    .is-selecting .selection-head { display: flex; align-items: center; gap: var(--space-3); }
    .is-selecting .selection-bar {
        position: fixed;
        inset: auto 0 0 0;
        z-index: calc(var(--z-sticky) + 1);
        display: flex;
        gap: var(--space-2);
        min-height: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
        padding: var(--space-2) calc(var(--space-3) + env(safe-area-inset-right)) calc(var(--space-2) + env(safe-area-inset-bottom)) calc(var(--space-3) + env(safe-area-inset-left));
        background: var(--accent);
    }
}
.selection-head-title { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; min-width: 0; }
.selection-head-btn,
.selection-head-all {
    min-height: var(--control-h);
    padding: 0;
    border: 0;
    background: none;
    color: var(--accent-ink);
    font: var(--text-body);
    font-weight: 600;
}
.selection-head-all { min-height: 0; font: var(--text-small); font-weight: 600; }
.selection-head-btn { min-width: var(--control-h); }
.selection-head-btn--quiet { color: var(--ink-3); }
.selection-bar-btn {
    flex: 1 1 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    min-height: var(--control-h);
    padding: 0 var(--space-2);
    border: 0;
    border-radius: var(--radius-control);
    background: var(--accent-hover);
    color: var(--surface);
    font: var(--text-small);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}
.selection-bar-btn:hover { color: var(--surface); }
.selection-bar-btn.disabled { opacity: 0.5; }
/* A bulk action's glyph (components/_bulk_action.html), in its state tone. */
.bulk-action-icon { margin-right: var(--space-2); }
.bulk-action-icon--done { color: var(--tone-done-ink); }
.bulk-action-icon--refused { color: var(--tone-refused-ink); }

/* === Board === */
/* A kanban (cases/_case_board_region.html, pipeline/_board_region.html; static/js/board.js): a column
   per stage, its cards. Wide, the columns side by side, each scrolling inside the viewport; narrow, the
   current column alone under the stage tabs, moved with Move to…. */
.board { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.board-columns { display: flex; gap: var(--space-3); min-height: 0; }
.board-col { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.board-col-head { display: flex; align-items: baseline; gap: var(--space-2); }
.board-col-name { font-weight: 700; overflow-wrap: anywhere; }
.board-col-count { font: var(--text-small); color: var(--ink-2); }
.opportunity-cards { display: flex; flex-direction: column; gap: var(--space-2); min-height: 0; }
/* Nothing on a card may widen it: text wraps or truncates, the avatar is a fixed circle. */
.board-card {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
    padding: var(--space-2) var(--space-3);
    background: var(--surface);
    border: thin solid var(--line);
    border-radius: var(--radius-card);
    color: var(--ink);
    font: var(--text-small);
    cursor: pointer;
}
.board-card:hover { border-color: var(--line-strong); }
.board-card-title { color: var(--ink); font-weight: 600; text-decoration: none; overflow-wrap: anywhere; }
.board-card-move {
    min-height: var(--control-h);
    padding: 0;
    border: 0;
    background: none;
    color: var(--accent-ink);
    font: inherit;
    font-weight: 600;
    white-space: nowrap;
}
/* A drag: the clone following the pointer stays opaque and lifted (will-change gives it its own
   layer); the card it left is a blank slot of its size. */
.opportunity-drag-card {
    opacity: 1 !important;
    box-shadow: var(--shadow) !important;
    will-change: transform;
    pointer-events: none;
}
.opportunity-cards .opportunity-drop-slot {
    opacity: 1;
    background: var(--sunken) !important;
    border: thin dashed var(--line-strong);
    box-shadow: none !important;
}
.opportunity-cards .opportunity-drop-slot > * { visibility: hidden; }
@media (pointer: fine) and (min-width: 1024px) {
    .board-col {
        padding: var(--space-3);
        background: var(--sunken);
        border-radius: var(--radius-card);
    }
    .board .opportunity-cards { flex-grow: 1; overflow-y: auto; }
}
@media not all and (pointer: fine), (max-width: 1023.98px) {
    .board-col { flex: 1 1 100%; }
    .board:not(.board-stage-edit) .board-col:not(.is-current) { display: none; }
    .board-card { font: var(--text-body); }
}

/* === Timeline === */
/* components/timeline_header.html, _timeline_entry.html and _timeline_month.html. */
.timeline-header {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-bottom: var(--space-2);
}
.timeline-actions,
.timeline-kinds {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}
.timeline-kind {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
    background: var(--fill-muted);
    color: var(--ink-2);
    font: var(--text-small);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}
.timeline-kind:hover {
    color: var(--ink);
}
.timeline-kind[aria-current="true"] {
    background: var(--accent);
    color: var(--surface);
}
.timeline-filter-toggle {
    padding: var(--space-1);
}
@media (pointer: coarse) {
    .timeline-kind,
    .timeline-filter-toggle {
        min-height: var(--control-h);
    }
}
.timeline-entry {
    display: flex;
    gap: var(--space-3);
    padding: var(--space-2) 0;
    border-top: thin solid var(--line-soft);
}
.timeline-entry-body {
    flex: 1;
    min-width: 0;
}
.timeline-entry-who {
    font-weight: 600;
}
.timeline-entry-when {
    font: var(--text-small);
    color: var(--ink-3);
}
.timeline-entry-glyph {
    margin-right: var(--space-1);
    color: var(--ink-3);
}
.timeline-entry-detail {
    color: var(--ink);
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}
/* A fact on the label line (a channel, an outcome, a drop's brand): components/_meta_pill.html. */
.meta-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0 var(--space-2);
    border: thin solid var(--line);
    border-radius: var(--radius-pill);
    color: var(--ink-2);
    font: 400 0.71875rem/1.125rem var(--font-sans);
    white-space: nowrap;
    vertical-align: baseline;
}
/* A control on the label line (the creator's edit pencil, an email's subject). */
.timeline-entry-action {
    padding: 0 var(--space-1);
    border: 0;
    background: none;
    color: var(--accent-ink);
    font: inherit;
    text-align: left;
}
.timeline-entry-action:hover {
    color: var(--accent-hover);
}
.timeline-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
    padding: var(--space-3);
    background: var(--page);
    border-radius: var(--radius-card);
}
.timeline-filters > * {
    flex: 1 1 calc(var(--space-7) * 4);
    min-width: 0;
}
.timeline-filters > .timeline-filters-actions {
    flex: none;
    display: flex;
    gap: var(--space-2);
}
.timeline-pages {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding-top: var(--space-3);
    border-top: thin solid var(--line-soft);
    font: var(--text-small);
    color: var(--ink-2);
}
.timeline-empty {
    margin: 0;
    padding: var(--space-3) 0;
    color: var(--ink-2);
}
.timeline-month {
    padding: var(--space-2) 0 var(--space-1);
    font: var(--text-micro);
    letter-spacing: var(--micro-tracking);
    text-transform: uppercase;
    color: var(--ink-3);
}
/* A timeline on its own panel, under its Planned strip (the contact page). */
.timeline-stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}
.timeline-entry-headline {
    font-weight: 600;
}
/* A row rolled up from a related record (a child contact): its colour on a left rail, each run
   headed by .timeline-rail-head naming the record. */
.timeline-entry--rail,
.timeline-rail-head {
    padding-left: var(--space-3);
    border-left: calc(var(--space-1) - 1px) solid var(--entry-rail);
    background: var(--page);
}
.timeline-rail-head {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    padding-top: var(--space-2);
    border-top: thin solid var(--line-soft);
    color: var(--entry-rail);
    font: var(--text-small);
    font-weight: 600;
    text-decoration: none;
}
.timeline-rail-head + .timeline-entry {
    border-top: 0;
}
/* Under an entry: its details, stock drops, attachments and reply thread. */
.timeline-details {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-4);
    margin-top: var(--space-1);
    font: var(--text-small);
}
.timeline-detail-label {
    color: var(--ink-2);
}
.timeline-drop {
    margin-top: var(--space-2);
    padding: var(--space-2) var(--space-3);
    background: var(--page);
    border: thin solid var(--line);
    border-radius: var(--radius-control);
    font: var(--text-small);
}
.timeline-drop-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-2);
}
.timeline-drop-text {
    margin-top: var(--space-1);
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}
.timeline-drop-note {
    color: var(--ink-2);
}
.timeline-attachments {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-2);
}
.timeline-attachment {
    position: relative;
    padding: var(--space-2);
    background: var(--surface);
    border: thin solid var(--line);
    border-radius: var(--radius-control);
}
.timeline-attachment > a {
    display: block;
    color: var(--ink);
    text-align: center;
    text-decoration: none;
}
.timeline-attachment img {
    display: block;
    width: auto;
    max-width: calc(var(--space-7) * 6);
    max-height: calc(var(--space-7) * 3);
    border-radius: var(--radius-control);
}
.timeline-attachment-icon {
    padding: 0 var(--space-5);
    font-size: 2rem;
    color: var(--ink-3);
}
.timeline-attachment-name {
    max-width: calc(var(--space-7) * 4);
    margin-top: var(--space-1);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font: var(--text-small);
}
.timeline-attachment .attachment-delete {
    position: absolute;
    top: var(--space-1);
    right: var(--space-1);
    padding: 0;
    border: 0;
    background: none;
    color: var(--danger);
    line-height: 1;
}
.timeline-reply {
    display: flex;
    gap: var(--space-2);
    margin-top: var(--space-2);
    padding-left: var(--space-3);
    border-left: thin solid var(--line);
}
.timeline-reply-body {
    flex: 1;
    min-width: 0;
}
.timeline-reply-text {
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}
.timeline-reply-form .btn {
    margin-top: var(--space-1);
}
.timeline-reply-toggle {
    display: inline-block;
    margin-top: var(--space-1);
    color: var(--accent-ink);
    font: var(--text-small);
    font-weight: 600;
    text-decoration: none;
}
.timeline-reply-toggle:hover {
    color: var(--accent-hover);
}

/* === Form fields === */
/* .form-grid: one column on a phone, two from 768px; components/choices.html; .form-card. */
.form-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-4) var(--space-5);
}
@media (min-width: 768px) {
    .form-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .form-grid--3 {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
    .form-field--wide {
        grid-column: 1 / -1;
    }
}
.form-field {
    min-width: 0;
}
/* A field that is one of several alternatives (a horse's Details per type): gone while none shows. */
.form-field--alts:not(:has(> .form-field-alt:not(.d-none))) {
    display: none;
}
/* Labels are the micro label (vendor-overrides.css .form-label); a form whose board labels in sentence
   case (Cases-Add, Cases-Review) takes .form-labels-sentence. */
.form-labels-sentence .form-label {
    font: var(--text-small);
    font-weight: 600;
    letter-spacing: normal;
    text-transform: none;
    color: var(--ink);
}
.form-rule {
    margin: var(--space-4) 0;
    border: 0;
    border-top: thin solid var(--line);
    opacity: 1;
}
.form-section-title {
    margin-bottom: var(--space-2);
}
.choices {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(calc(var(--space-7) * 2.5), 1fr));
    column-gap: var(--space-3);
}
.choice {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: var(--control-h);
    margin: 0;
    cursor: pointer;
}
.choice > .form-check-input {
    flex: none;
    margin: 0;
}
/* choices--toggles: each option a bordered toggle, filled in the accent while ticked. */
.choices--toggles {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}
.choices--toggles .choice {
    min-height: calc(var(--control-h) - var(--space-1));
    padding: 0 var(--space-3);
    border: thin solid var(--line-strong);
    border-radius: var(--radius-control);
    background: var(--surface);
    font-weight: 600;
}
.choices--toggles .choice:has(> :checked) {
    border-color: var(--accent);
    background: var(--accent-wash);
    color: var(--accent-ink);
}
.form-cards {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}
.form-cards:has(> .form-card) {
    margin-bottom: var(--space-3);
}
.form-card {
    position: relative;
    padding: var(--space-3);
    background: var(--page);
    border: thin solid var(--line);
    border-radius: var(--radius-card);
}
.form-card-remove {
    position: absolute;
    top: var(--space-1);
    right: var(--space-2);
    padding: 0;
    border: 0;
    background: none;
    color: var(--danger);
    font-size: 1.25rem;
    line-height: 1;
}

/* === Money table === */
/* components/money_table.html: lines, a thin rule, Subtotal, Freight, then Total double-underlined. */
.money-table {
    width: 100%;
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
}
.money-table :is(td, th) {
    padding: var(--space-2) 0;
    vertical-align: top;
}
.money-table tbody td {
    border-top: thin solid var(--line-soft);
}
.money-table-label {
    font-weight: 600;
}
.money-table-sub {
    font: var(--text-small);
    color: var(--ink-2);
}
.money-table .money-table-amount {
    padding-left: var(--space-3);
    text-align: right;
    font-weight: 600;
    white-space: nowrap;
}
.money-table tfoot th {
    text-align: right;
    font-weight: 600;
}
.money-table tfoot tr:first-child > * {
    border-top: thin solid var(--ink-3);
}
.money-table-total > * {
    font-weight: 700;
}
.money-table-total .money-table-amount > span {
    border-bottom: medium double var(--ink-2);
}
.money-table--compact {
    font: var(--text-small);
}
.money-table--compact .money-table-total > * {
    font: var(--text-body);
    font-weight: 700;
}

/* priced=True: the claim columns, the currency in the headings. A frame narrower than the columns
   (a phone, a pane, a request card) stacks each line (08-cases "Product and request lines on the
   phone"): its name, its code and source muted, then Qty · Cost per unit · Value as labelled
   columns that line up down the list, the SAP price under them; the totals keep the columns. */
.money-table-frame {
    container-type: inline-size;
}
.money-table--priced thead th {
    padding: 0 var(--space-2) var(--space-2) 0;
    border-bottom: thin solid var(--line);
    font: var(--text-micro);
    letter-spacing: var(--micro-tracking);
    text-transform: uppercase;
    color: var(--ink-2);
    text-align: left;
    vertical-align: bottom;
}
.money-table--priced tbody td {
    padding-right: var(--space-2);
    vertical-align: baseline;
}
.money-table--priced tbody tr:first-child td {
    border-top: 0;
}
.money-table--priced :is(th, td):last-child {
    padding-right: 0;
}
.money-table--priced .money-table-num,
.money-table--priced thead .money-table-num {
    text-align: right;
}
.money-table--priced tbody :is(.money-table-label, .money-table-amount),
.money-table-freight .money-table-amount {
    font-weight: 400;
}
.money-table--priced :is(.money-table-unit, .money-table-symbol) {
    display: none;
}
@container (min-width: 640px) {
    .money-table--priced tr.labelled-cols { display: table-row; }
    .money-table--priced .labelled-cols [data-label]::before { content: none; }
}
@container (max-width: 639.98px) {
    .money-table--priced,
    .money-table--priced :is(tbody, tfoot) {
        display: block;
    }
    .money-table--priced :is(thead, .money-table-unit-col, .money-table-code, .money-table-sub:empty, .money-table-none, [data-label="Invoiced"]) {
        display: none;
    }
    .money-table--priced :is(.money-table-unit, .money-table-symbol) {
        display: inline;
    }
    .money-table--priced {
        --labelled-cols: minmax(0, 1fr) calc(var(--space-7) * 2 + var(--space-1)) calc(var(--space-7) + var(--space-6) + var(--space-2));
    }
    .money-table--priced tr.labelled-cols {
        align-items: baseline;
    }
    .money-table--priced :is(td, th),
    .money-table--priced tfoot tr:first-child > * {
        padding: 0;
        border-top: 0;
    }
    .money-table--priced :is(tbody tr, .money-table-freight) {
        padding: var(--space-2) 0;
        border-top: thin solid var(--line-soft);
    }
    .money-table--priced tbody tr:first-child {
        border-top: 0;
    }
    .money-table--priced :is(.money-table-label, .money-table-sub) {
        grid-column: 1 / -1;
    }
    .money-table--priced :is(tbody, .money-table-freight) .money-table-label {
        font-weight: 600;
    }
    .money-table--priced td.money-table-sub {
        margin-bottom: var(--space-2);
    }
    .money-table--priced .money-table-sub[data-code]::before {
        content: attr(data-code) " · ";
    }
    .money-table--priced .money-table-qty {
        grid-column: 1;
        text-align: left;
    }
    .money-table--priced .money-table-price {
        grid-column: 2;
    }
    .money-table--priced .money-table-amount {
        grid-column: 3;
        text-align: right;
    }
    .money-table--priced tbody .money-table-amount,
    .money-table-freight .money-table-amount {
        font-weight: 700;
    }
    /* "SAP price £12.82 / EA" under the columns, so the price used reads against it. */
    .money-table--priced .money-table-quote {
        order: 1;
        grid-column: 1 / -1;
        margin-top: var(--space-1);
        font: var(--text-small);
        color: var(--ink-2);
        text-align: left;
    }
    .money-table--priced td.money-table-quote::before {
        display: inline;
        margin: 0 var(--space-1) 0 0;
        font: inherit;
        letter-spacing: normal;
        text-transform: none;
        color: inherit;
    }
    .money-table--priced tfoot tr:not(.money-table-freight) {
        padding-top: var(--space-2);
    }
    .money-table--priced tfoot tr:not(.money-table-freight) > th {
        grid-column: 2;
    }
    .money-table--priced tfoot tr:first-child {
        border-top: thin solid var(--ink-3);
    }
}

/* === Bottom sheet === */
/* components/sheet.html: a dialog under a mouse, a bottom sheet on touch; .modal-sheet--full fills a phone. */
.modal-sheet .modal-content {
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow);
}

.modal-sheet .modal-title {
    font: var(--text-section);
}

.modal-sheet .modal-heading {
    min-width: 0;
}
/* A tabbed head (modal-header--tabs): the title shares the close button's line on a phone; the tabs
   go below. */
.modal-header--tabs > .modal-heading {
    flex: 1 1 0;
}

/* A head's own actions (_sheet_head.html actions_template), between the title and the close
   button; on the full-screen sheet, where the close button leads, they sit on the right. */
.modal-sheet .modal-header:has(> .sheet-head-actions) {
    gap: var(--space-2);
}

.modal-sheet .modal-heading:has(~ .sheet-head-actions) {
    flex: 1;
}

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

.modal-sheet .modal-subtitle {
    margin: 0;
    font: var(--text-small);
    color: var(--ink-2);
}

/* What only the full-screen phone sheet shows, and what only the dialog does. */
.modal-sheet .sheet-full-only {
    display: none;
}

/* A form around the head, body and footer (content_template) lays out as if absent, so the body
   still scrolls between them. */
.modal-sheet .modal-content > form {
    display: contents;
}

.sheet-loading {
    display: grid;
    gap: var(--space-3);
}

.sheet-loading span {
    height: var(--space-5);
    border-radius: var(--radius-control);
    background: var(--sunken);
}

.sheet-loading span:last-child {
    width: 60%;
}

@media (pointer: coarse) {
    /* On the on-screen keyboard when one is up (helpers.js --keyboard-h, --viewport-h). */
    .modal-sheet .modal-dialog {
        position: absolute;
        inset: auto 0 var(--keyboard-h, 0px);
        width: auto;
        max-width: none;
        height: auto;
        min-height: 0;
        margin: 0;
    }

    .modal-sheet.fade .modal-dialog {
        transform: translateY(100%);
    }

    .modal-sheet.show .modal-dialog {
        transform: none;
    }

    .modal-sheet .modal-content {
        max-height: calc(var(--viewport-h, 100dvh) * 0.9);
        border: 0;
        border-radius: var(--radius-card) var(--radius-card) 0 0;
        padding-bottom: env(safe-area-inset-bottom);
    }

    /* The grab handle on every flex-column touch sheet. */
    .modal-sheet .modal-content::before,
    .select2-container--open:has(> .select2-sheet) .select2-sheet::before,
    .filter-pop::before {
        content: "";
        flex: none;
        align-self: center;
        width: var(--space-6);
        height: var(--space-1);
        margin-top: var(--space-2);
        border-radius: var(--radius-pill);
        background: var(--line-strong);
    }

    .modal-sheet--full .modal-dialog {
        top: 0;
    }

    .modal-sheet--full .modal-content {
        height: 100%;
        max-height: none;
        border-radius: 0;
        padding-top: env(safe-area-inset-top);
    }

    .modal-sheet--full .modal-content::before {
        content: none;
    }

    .modal-sheet--full .modal-header .btn-close {
        order: -1;
        margin: 0 var(--space-3) 0 0;
    }

    /* Grey under white cards, as the phone's pages; the footer is the sticky action bar. */
    .modal-sheet--full .modal-body {
        background: var(--page);
    }

    .modal-sheet--full .sheet-card {
        padding: var(--space-3) var(--space-4);
        background: var(--surface);
        border: thin solid var(--line);
        border-radius: var(--radius-card);
    }

    .modal-sheet--full .sheet-full-only {
        display: revert;
    }

    .modal-sheet--full .sheet-dialog-only {
        display: none;
    }

    .modal-sheet--full .modal-footer {
        flex-wrap: nowrap;
    }

    .modal-sheet--full .modal-footer > .btn {
        flex: 1 1 0;
    }

    .modal-sheet--full .modal-footer > .btn-primary {
        flex-grow: 1.6;
    }

    .modal-sheet--full .modal-header--tabs > .tabs {
        order: 1;
        flex-basis: 100%;
    }

    .modal-sheet--full .modal-header--tabs .tab {
        flex: 1;
        justify-content: center;
    }
}

/* The two bulk sheets (contacts' Bulk edit, forage's Bulk update): the body is sized by hand, and
   their form around head, body and footer joins the flex chain, or the body grows unbounded. */
:is(#bulkUpdateModal, #bulkEditModal) .modal-content {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
/* The dialog's cap alone: on touch the sheet's own height holds (a full sheet fills the screen). */
@media (pointer: fine) {
    :is(#bulkUpdateModal, #bulkEditModal) .modal-content { max-height: calc(100vh - 3.5rem); }
}
:is(#bulkUpdateModal, #bulkEditModal) .modal-content > form {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}
:is(#bulkUpdateModal, #bulkEditModal) .modal-body {
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}

/* Tabbed forms in one sheet: the panes lay out as if absent, so the open one's body scrolls. */
.modal-header--tabs {
    flex-wrap: wrap;
    row-gap: var(--space-2);
    padding-bottom: 0;
}

.modal-header--tabs > .tabs {
    flex: 1;
    min-width: 0;
    border-bottom: 0;
}

.modal-sheet .modal-content > .tab-content,
.modal-sheet .modal-content > .tab-content > .tab-pane.active,
.modal-sheet .modal-content > .tab-content > .tab-pane.active > form {
    display: contents;
}


/* A bulk action asked first (components/_bulk_confirm.html): the question, then the ticked rows,
   one line each; the row's note (its PO) only under a mouse. */
.bulk-confirm-message { margin: 0 0 var(--space-3); }
.bulk-confirm-list { margin: 0; padding: 0; list-style: none; }
.bulk-confirm-list:empty { display: none; }
.bulk-confirm-list li {
    display: flex;
    align-items: baseline;
    gap: var(--space-3);
    padding: var(--space-1) 0;
    border-top: thin solid var(--line-soft);
    font: var(--text-small);
}
.bulk-confirm-list .mono { flex: none; color: var(--ink); }
.bulk-confirm-detail { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bulk-confirm-note { flex: none; margin-left: auto; color: var(--ink-2); }
@media (pointer: coarse) {
    .bulk-confirm-note { display: none; }
}


/* === Facts === */
/* A record's read-only fields: a micro label over each value. */
.facts {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
    gap: var(--space-3) var(--space-5);
    margin: 0;
}
.fact {
    min-width: 0;
}
.fact--wide {
    grid-column: 1 / -1;
}
.fact-label {
    margin-bottom: var(--space-1);
    font: var(--text-micro);
    letter-spacing: var(--micro-tracking);
    text-transform: uppercase;
    color: var(--ink-2);
}
.fact-value {
    margin: 0;
    overflow-wrap: anywhere;
}
.fact-value--prose {
    white-space: pre-wrap;
}
.fact-sub {
    font: var(--text-small);
    color: var(--ink-2);
}
.fact-link {
    font-weight: 600;
    text-decoration: none;
}
.fact-empty {
    color: var(--ink-3);
}

/* === Link card === */
/* contacts/_website_preview.html: a site's preview (image, name, title, description, address) as one link. */
.link-card {
    display: flex;
    max-width: 32rem;
    overflow: hidden;
    border: thin solid var(--line);
    border-radius: var(--radius-card);
    background: var(--surface);
    color: var(--ink);
    text-decoration: none;
}
.link-card:hover,
.link-card:focus-visible {
    border-color: var(--accent);
    color: var(--ink);
}
.link-card-image {
    flex: 0 0 33%;
    min-height: calc(var(--space-7) * 2);
    object-fit: cover;
    background: var(--sunken);
}
.link-card-body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: calc(var(--space-1) / 2);
    min-width: 0;
    padding: var(--space-2) var(--space-3);
}
.link-card-site {
    font: var(--text-micro);
    letter-spacing: var(--micro-tracking);
    text-transform: uppercase;
    color: var(--ink-2);
}
.link-card-title {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.link-card-text {
    display: -webkit-box;
    overflow: hidden;
    font: var(--text-small);
    color: var(--ink-2);
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}
.link-card-url {
    overflow: hidden;
    font: var(--text-small);
    color: var(--accent-ink);
    text-overflow: ellipsis;
    white-space: nowrap;
}
.link-card-note {
    font: var(--text-small);
    color: var(--ink-2);
}
.link-card-note--error {
    color: var(--danger);
}

/* === Panel === */
/* A card on the page: cards get a border, never a shadow. Over its content a micro .panel-title or a
   .section-title, in a .panel-head when tools share its line. */
.panel {
    min-width: 0;
    padding: var(--space-3) var(--space-4);
    background: var(--surface);
    border: thin solid var(--line);
    border-radius: var(--radius-card);
}
.panel-head {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-2);
}
.panel-title { margin: 0 0 var(--space-2); }
.panel-head > .panel-title { flex: 1; margin: 0; }
.section-title { margin: 0; font: var(--text-section); font-weight: 700; }
/* What a panel, section or list says when it has nothing to show. */
.empty-note { margin: 0; color: var(--ink-2); }

/* === Record page === */
/* A record's page (a case, opportunity, discount request, forage sample or contact). It sizes to its own
   box, so it reads the same on its page and in a queue's pane: narrow, a column of panels; from 720px,
   the title and actions on one row over the stage band, and .record-main's panels as one card. */
.record-page {
    container: record-page / inline-size;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
}
.record-head {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}
.record-head-text { min-width: 0; }
.record-kicker {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
    font: var(--text-small);
    color: var(--ink-2);
}
.record-title {
    margin: 0;
    font: var(--text-heading);
    font-weight: 700;
    letter-spacing: var(--title-tracking);
    overflow-wrap: anywhere;
}
.record-actions { display: flex; align-items: center; gap: var(--space-2); }
.record-actions > .btn { flex: 1; white-space: nowrap; }
.record-actions > .btn-icon { flex: none; }
.record-main {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}
@container record-page (min-width: 720px) {
    .record-head {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            "text actions"
            "band band";
        align-items: center;
        gap: 0 var(--space-3);
    }
    .record-head-text { grid-area: text; }
    .record-title { font: var(--text-title); }
    .record-actions { grid-area: actions; }
    .record-actions > .btn { flex: none; }
    .record-band {
        grid-area: band;
        margin: calc(var(--space-3) + var(--space-1)) 0 var(--space-3);
    }
    .record-main {
        gap: 0;
        background: var(--surface);
        border: thin solid var(--line);
        border-radius: var(--radius-card);
    }
    .record-main > .panel {
        padding: var(--space-4);
        background: none;
        border: 0;
        border-radius: 0;
    }
    .record-main > .panel + .panel { border-top: thin solid var(--line-soft); }
}

/* === Record section === */
/* components/record_section.html */
.record-section.is-editing {
    border: calc(var(--space-1) / 2) solid var(--accent);
}
.record-section-tools {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-left: auto;
}
.record-section-badge {
    padding: 0 var(--space-2);
    border-radius: var(--radius-pill);
    background: var(--accent-wash);
    color: var(--accent-ink);
    font: var(--text-small);
    font-weight: 600;
}
.record-section-close,
.record-section-subtitle {
    display: none;
}
.record-section .facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.record-fields {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-3) var(--space-6);
}
.record-field-col {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 0;
}
.record-field {
    min-width: 0;
}
.record-field--wide {
    grid-column: 1 / -1;
}
.record-field-error {
    margin-top: var(--space-1);
    font: var(--text-small);
    color: var(--danger);
}
.record-textarea {
    field-sizing: content;
    min-height: calc(var(--space-7) * 2);
}
.record-section-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    margin-top: var(--space-4);
}
/* Chips for a many-to-many value; a person's carries their avatar. */
.value-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-2);
}
.value-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    max-width: 100%;
    padding: calc(var(--space-1) * 3 / 4) calc(var(--space-2) + var(--space-1) / 2);
    border-radius: var(--radius-pill);
    background: var(--fill-muted);
    font: 400 0.875rem/1.25rem var(--font-sans);
    white-space: nowrap;
}
.value-chip--person {
    padding-left: calc(var(--space-1) / 2);
}
@media not all and (pointer: fine), (max-width: 1023.98px) {
    .record-section .facts {
        grid-template-columns: minmax(0, 1fr);
        gap: 0;
    }
    .record-section .fact {
        padding: var(--space-2) 0;
        border-top: thin solid var(--line-soft);
    }
    .record-fields {
        grid-template-columns: minmax(0, 1fr);
    }
    .record-section-actions > .btn {
        flex: 1 1 0;
    }
    /* phone_full: the section editing fills the screen, above the shell's bars and under its
       pickers' dropdowns and the date field's calendar. */
    body:has(.record-section--phone-full) {
        overflow: hidden;
    }
    .record-section--phone-full {
        position: fixed;
        inset: 0;
        z-index: calc(var(--z-dropdown) - 1);
        display: flex;
        flex-direction: column;
        padding: 0;
        border: 0;
        border-radius: 0;
    }
    .record-section--phone-full > .panel-head {
        flex: none;
        margin: 0;
        padding: var(--space-2) var(--space-4);
        border-bottom: thin solid var(--line);
    }
    .record-section--phone-full .record-section-close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: var(--control-h);
        height: var(--control-h);
        margin-left: calc(-1 * var(--space-3));
        padding: 0;
        border: 0;
        background: none;
        color: var(--ink-2);
        font: var(--text-heading);
    }
    .record-section--phone-full .record-section-subtitle {
        display: block;
        font: var(--text-small);
        font-family: var(--font-mono);
        color: var(--ink-2);
    }
    .record-section--phone-full .record-section-tools {
        display: none;
    }
    .record-section--phone-full > .record-section-form {
        flex: 1 1 auto;
        display: flex;
        flex-direction: column;
        min-height: 0;
        padding: var(--space-4) var(--space-4) 0;
        overflow-y: auto;
    }
    .record-section--phone-full .record-section-actions {
        position: sticky;
        bottom: 0;
        margin: auto calc(-1 * var(--space-4)) 0;
        padding: var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom));
        background: var(--surface);
        border-top: thin solid var(--line);
    }
}

/* === Planned strip === */
/* calendar/_planned_events.html: a record's upcoming events above its timeline. */
.planned-strip-head {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-width: 0;
}
.planned-strip-head:has(+ .planned-strip-row) { margin-bottom: var(--space-1); }
.planned-strip-empty {
    min-width: 0;
    overflow: hidden;
    color: var(--ink-2);
    font: var(--text-small);
    text-overflow: ellipsis;
    white-space: nowrap;
}
.planned-strip-add { margin-left: auto; }
@media (pointer: coarse) {
    .planned-strip-add { min-height: var(--control-h); }
}
.planned-strip-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-width: 0;
    padding: var(--space-2) 0;
    border-top: thin solid var(--line-soft);
}
.planned-strip-row[role="button"] {
    cursor: pointer;
}
.planned-strip-row[role="button"]:hover .planned-strip-title {
    color: var(--accent-ink);
}
.planned-strip-icon {
    flex: none;
    color: var(--accent);
}
.planned-strip-what {
    display: flex;
    flex: 1;
    align-items: baseline;
    gap: var(--space-3);
    min-width: 0;
}
.planned-strip-when {
    flex: none;
    min-width: 8.5em;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.planned-strip-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.planned-strip-title.is-busy {
    color: var(--ink-2);
}
.planned-strip-who {
    flex: none;
    color: var(--ink-2);
    white-space: nowrap;
}
@media (max-width: 767.98px) {
    .planned-strip-row {
        align-items: flex-start;
    }
    .planned-strip-icon {
        margin-top: var(--space-1);
    }
    .planned-strip-what {
        flex-direction: column;
        gap: 0;
    }
    .planned-strip-when {
        min-width: 0;
    }
    .planned-strip-title {
        max-width: 100%;
    }
    .planned-strip-who {
        font: var(--text-small);
    }
}

/* === Event chip === */
/* components/event_chip.html: the Calendar's chip outside the Calendar (vendor-overrides.css draws the grid's). */
.event-chip {
    --event-colour: var(--calendar-self);
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    padding: var(--space-1) calc(var(--space-1) * 3 / 2) var(--space-1) calc(var(--space-2) + var(--space-1) / 4);
    border: thin solid color-mix(in srgb, var(--event-colour) 30%, var(--surface));
    border-radius: calc(var(--radius-control) - var(--space-1) / 4);
    background: color-mix(in srgb, var(--event-colour) 14%, var(--surface));
    box-shadow: inset calc(var(--space-1) * 3 / 4) 0 0 var(--event-colour);
    color: var(--ink);
    font: var(--text-small);
}
.event-chip[role="button"] { cursor: pointer; }
.event-chip[role="button"]:hover { border-color: color-mix(in srgb, var(--event-colour) 55%, var(--surface)); }
.event-chip > * {
    flex: none;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.event-chip-title { font-weight: 600; }
.event-chip-time { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.event-chip-line { color: var(--ink-2); }
.event-chip.is-invite {
    border: thin dashed var(--event-colour);
    background: var(--surface);
}
.event-chip.is-past { opacity: 0.55; }
@media (hover: none) {
    .event-chip.is-past { opacity: 0.7; }
}

/* === Picker === */
/* components/picker.html over select2. select2.css loads after this file, so each rule outweighs
   select2's own selector rather than relying on order. */
select[data-picker] + .select2-container .select2-selection {
    min-height: var(--control-h);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-control);
    background: var(--surface);
    font-size: var(--control-font);
}

/* A long pick wraps onto more lines; it never widens the field (and with it the page). */
select[data-picker] + .select2-container .select2-selection--single {
    display: flex;
    align-items: center;
    height: auto;
}

select[data-picker] + .select2-container .select2-selection--single .select2-selection__rendered {
    flex: 1;
    min-width: 0;
    padding: var(--space-1) var(--space-6) var(--space-1) var(--space-3);
    color: var(--ink);
    line-height: var(--space-5);
    white-space: normal;
    overflow-wrap: anywhere;
}

select[data-picker] + .select2-container .select2-selection__placeholder,
select[data-picker] + .select2-container .select2-selection__clear {
    color: var(--ink-3);
}

/* The clear × is a control-sized square left of the chevron, not a glyph wide. */
select[data-picker] + .select2-container .select2-selection--single .select2-selection__clear {
    position: absolute;
    top: 0;
    right: var(--space-5);
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--control-h);
    height: 100%;
    float: none;
    margin: 0;
}

select[data-picker] + .select2-container .select2-selection--single .select2-selection__rendered:has(> .select2-selection__clear) {
    padding-right: calc(var(--space-5) + var(--control-h));
}

select[data-picker] + .select2-container .select2-selection__arrow {
    top: 0;
    right: var(--space-3);
    width: var(--space-3);
    height: 100%;
    background: var(--ink-3);
    mask: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m6 3 5 5-5 5'/%3e%3c/svg%3e") center / contain no-repeat;
}

select[data-picker] + .select2-container .select2-selection__arrow b {
    display: none;
}

select[data-picker] + .select2-container .select2-selection--multiple {
    display: flex;
    align-items: center;
    cursor: pointer;
}

/* A compact picker in a table row matches the .form-control-sm beside it. */
select[data-picker].form-select-sm + .select2-container .select2-selection {
    min-height: calc(1.5em + var(--space-2) + 2px);
    font-size: 0.875rem;
}

select[data-picker].form-select-sm + .select2-container .select2-selection--single {
    height: calc(1.5em + var(--space-2) + 2px);
}

/* A <select> hidden by its page takes its picker with it. */
select[data-picker]:is([hidden], .d-none, [style*="display: none"]) + .select2-container {
    display: none;
}

select[data-picker] + .select2-container .select2-selection--multiple .select2-selection__rendered {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
}

select[data-picker] + .select2-container .select2-selection__choice {
    float: none;
    max-width: 100%;
    margin: 0;
    white-space: normal;
    overflow-wrap: anywhere;
    padding: 0 var(--space-2);
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--sunken);
    font: var(--text-small);
    line-height: var(--space-5);
}

select[data-picker] + .select2-container .select2-selection__choice__remove {
    position: relative;
    margin-right: var(--space-1);
    color: var(--ink-3);
}

/* On touch a chip's × takes a finger: its hit area runs the control's height. */
@media (pointer: coarse) {
    select[data-picker] + .select2-container .select2-selection__choice__remove::after {
        content: "";
        position: absolute;
        inset: calc(-1 * var(--space-3)) calc(-1 * var(--space-2));
    }
}

select[data-picker] + .select2-container.select2-container--focus .select2-selection,
select[data-picker] + .select2-container.select2-container--open .select2-selection {
    border-color: var(--accent);
    border-radius: var(--radius-control);
    box-shadow: 0 0 0 var(--space-1) var(--accent-wash);
    outline: 0;
}

select[data-picker].is-invalid + .select2-container.select2-container .select2-selection {
    border-color: var(--danger);
}

select[data-picker] + .select2-container--disabled .select2-selection {
    background: var(--sunken);
    color: var(--ink-3);
    cursor: not-allowed;
}

.select2-container.select2-container--open .picker-dropdown {
    border: 1px solid var(--line);
    border-radius: var(--radius-control);
    box-shadow: var(--shadow);
    overflow: hidden;
    font-size: var(--control-font);
}

.select2-container--open .picker-dropdown.select2-dropdown--below {
    margin-top: var(--space-1);
}

.select2-container--open .picker-dropdown.select2-dropdown--above {
    margin-top: calc(-1 * var(--space-1));
}

.select2-container .picker-dropdown .select2-search--dropdown {
    padding: var(--space-2);
}

.select2-container .picker-dropdown .select2-search--dropdown .select2-search__field {
    height: var(--control-h);
    padding: 0 var(--space-3);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-control);
    font-size: var(--control-font);
    outline: 0;
}

.select2-container .picker-dropdown .select2-search--dropdown .select2-search__field:focus {
    border-color: var(--accent);
}

.select2-container .picker-dropdown .select2-results > .select2-results__options {
    max-height: calc(var(--space-7) * 6);
}

.select2-container .picker-dropdown .select2-results__option {
    padding: var(--space-2) var(--space-3);
}

.select2-container .picker-dropdown .select2-results__option[aria-selected=true] {
    background: none;
    color: var(--accent-ink);
    font-weight: 600;
}

.select2-container .picker-dropdown .select2-results__option.select2-results__option--highlighted[aria-selected] {
    background: var(--accent-wash);
    color: var(--ink);
}

.select2-container .picker-dropdown .select2-results__group {
    padding: var(--space-3) var(--space-3) var(--space-1);
    font: var(--text-micro);
    letter-spacing: var(--micro-tracking);
    text-transform: uppercase;
    color: var(--ink-2);
}

.select2-container .picker-dropdown .select2-results__message {
    color: var(--ink-3);
}

/* select2Sheet() builds this header on open; it shows on touch only. */
.select2-sheet-header {
    display: none;
}

/* Touch: a bottom sheet over a scrim, on the keyboard when one is up (pinned in
   vendor-overrides.css "Select2"); a plain one is as tall as its list, a searchable one as tall
   as the screen allows, so its search box holds still as matches come and go. Its list alone
   scrolls. */
@media (pointer: coarse) {
    .select2-container--open:has(> .select2-sheet)::before {
        content: "";
        position: fixed;
        inset: 0;
        z-index: -1;
        background: color-mix(in srgb, var(--ink) 42%, transparent);
    }

    .select2-container.select2-container--open:has(> .select2-sheet) .select2-sheet {
        display: flex;
        flex-direction: column;
        max-height: calc(var(--viewport-h, 100dvh) * 0.9);
        margin: 0;
        border: 0;
        border-radius: var(--radius-card) var(--radius-card) 0 0;
        box-shadow: var(--shadow);
        padding-bottom: env(safe-area-inset-bottom);
        overflow: hidden;
    }

    .select2-container.select2-container--open:has(> .select2-sheet) .select2-sheet.picker-dropdown--search {
        height: calc(var(--viewport-h, 100dvh) * 0.9);
    }

    .select2-container--open:has(> .select2-sheet) .select2-sheet-header {
        display: flex;
        flex: none;
        align-items: center;
        justify-content: space-between;
        padding: 0 var(--space-1) 0 var(--space-4);
        border-bottom: 1px solid var(--line-soft);
        font: var(--text-section);
    }

    .select2-container--open:has(> .select2-sheet) .select2-results {
        display: flex;
        flex: 1;
        flex-direction: column;
        min-height: 0;
    }

    .select2-container--open:has(> .select2-sheet) .select2-results > .select2-results__options {
        flex: 1;
        min-height: 0;
        max-height: none;
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    /* One inset down the sheet: the title, the search box and the rows all start 16px in. */
    .select2-container .picker-dropdown.select2-sheet .select2-search--dropdown {
        padding: var(--space-2) var(--space-4);
    }

    .select2-container .picker-dropdown.select2-sheet .select2-results__option:not([role="group"]) {
        padding-inline: var(--space-4);
    }

    .select2-container .picker-dropdown.select2-sheet .select2-results__group {
        padding-inline: var(--space-4);
    }

    /* Every row a finger picks, in a sheet or a list anchored in a menu, is a control high. */
    .select2-container .picker-dropdown .select2-results__option:not([role="group"]) {
        display: flex;
        flex-direction: column;
        justify-content: center;
        min-height: var(--control-h);
    }

    .select2-sheet .select2-results__option + .select2-results__option {
        border-top: 1px solid var(--line-soft);
    }

    .select2-sheet .select2-search--dropdown .select2-search__field {
        padding: var(--space-2);
        font-size: var(--control-font);
    }

    /* Room for the sticky top bar and the field's label. */
    .select2-container {
        scroll-margin-top: calc(var(--topbar-h) + var(--space-5));
    }
}

/* The list slides in and out (0.2s, as the menu's rail): a few px under a mouse, the whole sheet
   on touch. picker-leaving (select2_pickers.js) holds the close until it has played. */
.select2-container.picker-leaving {
    pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
    .select2-container--open .picker-dropdown {
        animation: picker-in 0.2s ease;
    }

    .select2-container--open .picker-dropdown.select2-dropdown--above {
        animation-name: picker-in-above;
    }

    .select2-container.picker-leaving .picker-dropdown {
        animation: picker-out 0.2s ease forwards;
    }

    .select2-container.picker-leaving .picker-dropdown.select2-dropdown--above {
        animation-name: picker-out-above;
    }
}

@media (pointer: coarse) and (prefers-reduced-motion: no-preference) {
    .select2-container--open:has(> .select2-sheet)::before {
        animation: scrim-in 0.2s ease;
    }

    .select2-container.picker-leaving:has(> .select2-sheet)::before {
        animation: scrim-out 0.2s ease forwards;
    }

    .select2-container--open .picker-dropdown.select2-sheet {
        animation: sheet-in 0.2s ease;
    }

    .select2-container.picker-leaving .picker-dropdown.select2-sheet {
        animation: sheet-out 0.2s ease forwards;
    }
}

@keyframes picker-in { from { opacity: 0; transform: translateY(calc(-1 * var(--space-1))); } }
@keyframes picker-in-above { from { opacity: 0; transform: translateY(var(--space-1)); } }
@keyframes picker-out { to { opacity: 0; transform: translateY(calc(-1 * var(--space-1))); } }
@keyframes picker-out-above { to { opacity: 0; transform: translateY(var(--space-1)); } }
@keyframes sheet-in { from { transform: translateY(100%); } }
@keyframes sheet-out { to { transform: translateY(100%); } }
@keyframes scrim-in { from { opacity: 0; } }
@keyframes scrim-out { to { opacity: 0; } }

/* template="kicker": "Brand > Name" reads inline. On a narrow screen, a page that lifts the
   brand over the name (.picker-kicker-stacked on an ancestor) drops the separator. */
@media not all and (pointer: fine), (max-width: 1023.98px) {
    .picker-kicker-stacked .picker-kicker {
        display: block;
        font: var(--text-small);
        color: var(--ink-2);
    }
    .picker-kicker-stacked .picker-kicker-sep {
        display: none;
    }
    .picker-kicker-stacked .picker-kicker-name {
        font-weight: 600;
    }
    .picker-kicker-stacked select[data-picker] + .select2-container .select2-selection--single {
        height: auto;
        padding: var(--space-1) 0;
    }
}

/* template="person": an initials circle before each name. A locked pick (data-locked-note) reads
   its note after the name and has no ×; the × sits after a person's name. */
.person-avatar {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: var(--space-5);
    height: var(--space-5);
    border-radius: var(--radius-pill);
    background: var(--accent-wash);
    color: var(--accent-ink);
    font: var(--text-micro);
}
img.person-avatar { object-fit: cover; }

.person-pick {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}

.person-note {
    color: var(--ink-2);
}
.person-star {
    margin-left: var(--space-1);
    color: var(--accent);
}

select[data-picker] + .select2-container .select2-selection__choice:has(.person-pick) {
    display: inline-flex;
    align-items: center;
    padding: calc(var(--space-1) / 2) var(--space-2) calc(var(--space-1) / 2) calc(var(--space-1) / 2);
    font: var(--text-body);
}

select[data-picker] + .select2-container .select2-selection__choice:has(.person-pick) .select2-selection__choice__remove {
    order: 1;
    margin: 0 0 0 var(--space-2);
}

select[data-picker] + .select2-container .select2-selection__choice.is-locked .select2-selection__choice__remove {
    display: none;
}

select[data-picker] + .select2-container .select2-selection--single .person-avatar {
    margin-left: calc(-1 * var(--space-1));
}

/* checklist: the touch sheet of ticks, picks first. */
.picker-checklist {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

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

.picker-checklist-list > li + li {
    border-top: thin solid var(--line-soft);
}

.picker-checklist-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: calc(var(--control-h) + var(--space-2));
    margin: 0;
    font-size: var(--control-font);
    cursor: pointer;
}

.picker-checklist-row .form-check-input {
    flex: none;
    width: calc(var(--space-5) - var(--space-1) / 2);
    height: calc(var(--space-5) - var(--space-1) / 2);
    margin: 0;
}

.picker-checklist-row .person-avatar {
    width: calc(var(--space-5) + var(--space-1));
    height: calc(var(--space-5) + var(--space-1));
}

.picker-checklist-name {
    flex: 1;
    min-width: 0;
}

/* === Date field === */
/* components/date_field.html + date_field.js: anchored under a mouse, a bottom sheet on touch. */
.date-field {
    min-width: 0;
}

.date-field-trigger {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    height: var(--control-h);
    padding: 0 var(--space-3);
    text-align: left;
    cursor: pointer;
}

.date-field-trigger[aria-expanded="true"] {
    border-color: var(--accent);
    box-shadow: 0 0 0 var(--space-1) var(--accent-wash);
}

.date-field-trigger:disabled {
    background: var(--sunken);
    color: var(--ink-3);
    cursor: not-allowed;
}

.date-field-icon,
.date-field-chevron {
    flex: none;
    color: var(--ink-2);
}

.date-field-chevron {
    font-size: var(--space-3);
}

.date-field-text {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.date-field-text.is-empty {
    color: var(--ink-3);
}

.date-field-pop {
    position: fixed;
    z-index: var(--z-dropdown);
    padding: var(--space-3);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow);
    color: var(--ink);
    font: var(--text-body);
}

.date-field-sheet-head,
.date-field-scrim {
    display: none;
}

.date-field-nav {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
}

.date-field-month {
    flex: 1;
    text-align: center;
    font-weight: 700;
}

.date-field-step {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: calc(var(--space-6) - var(--space-1) / 2);
    height: calc(var(--space-6) - var(--space-1) / 2);
    padding: 0;
    border: 0;
    border-radius: var(--radius-control);
    background: none;
    color: var(--ink-2);
    font-size: var(--space-3);
}

.date-field-step:hover {
    background: var(--sunken);
    color: var(--ink);
}

.date-field-grid {
    display: grid;
    grid-template-columns: repeat(7, calc(var(--space-6) + var(--space-1) / 2));
}

.date-field-dow {
    padding-bottom: var(--space-1);
    text-align: center;
    font: var(--text-micro);
    color: var(--ink-2);
}

.date-field-day {
    height: calc(var(--space-6) - var(--space-1) / 2);
    padding: 0;
    border: 0;
    border-radius: var(--radius-control);
    background: none;
    color: var(--ink);
    font: var(--text-small);
    font-variant-numeric: tabular-nums;
}

.date-field-day:hover {
    background: var(--accent-wash);
    color: var(--accent-ink);
}

.date-field-day:focus-visible,
.date-field-step:focus-visible {
    outline: medium solid var(--accent-tint);
}

.date-field-day[aria-current="date"] {
    color: var(--accent-ink);
    font-weight: 700;
}

.date-field-day[aria-pressed="true"] {
    background: var(--accent);
    color: var(--surface);
    font-weight: 700;
}

.date-field-foot {
    display: flex;
    justify-content: flex-end;
    margin-top: var(--space-2);
    padding-top: var(--space-2);
    border-top: 1px solid var(--line-soft);
}

@media (pointer: coarse) {
    .date-field-scrim {
        display: block;
        position: fixed;
        inset: 0;
        z-index: var(--z-dropdown);
        background: color-mix(in srgb, var(--ink) 42%, transparent);
    }

    .date-field-pop {
        inset: auto 0 0;
        padding: 0 var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom));
        border: 0;
        border-radius: var(--radius-card) var(--radius-card) 0 0;
    }

    .date-field-pop::before {
        content: "";
        display: block;
        width: var(--space-6);
        height: var(--space-1);
        margin: var(--space-2) auto 0;
        border-radius: var(--radius-pill);
        background: var(--line-strong);
    }

    .date-field-sheet-head {
        display: flex;
        align-items: center;
        margin: 0 calc(-1 * var(--space-4)) var(--space-3);
        padding: 0 var(--space-1) 0 var(--space-4);
        border-bottom: 1px solid var(--line-soft);
        font: var(--text-section);
    }

    .date-field-sheet-title {
        flex: 1;
        min-width: 0;
    }

    .date-field-step {
        width: var(--control-h);
        height: var(--control-h);
    }

    .date-field-grid {
        grid-template-columns: repeat(7, minmax(0, 1fr));
    }

    .date-field-day {
        height: var(--control-h);
        font: var(--text-body);
    }

    .date-field-foot .btn {
        flex: 1;
    }
}

/* === Time field === */
/* components/time_field.html + time_field.js: reuses the date field's overlay and sheet. */
.time-field {
    position: relative;
    min-width: 0;
}

.time-field .time-field-input {
    height: var(--control-h);
    padding-left: calc(var(--space-3) + var(--space-4) + var(--space-1));
    padding-right: calc(var(--space-3) * 2 + var(--space-1));
    font-variant-numeric: tabular-nums;
}

.time-field .time-field-input.is-invalid {
    padding-right: calc(var(--space-3) * 2 + var(--space-1));
    background-image: none;
}

.time-field-input[aria-expanded="true"] {
    border-color: var(--accent);
    box-shadow: 0 0 0 var(--space-1) var(--accent-wash);
}

.time-field-input:disabled {
    background: var(--sunken);
    color: var(--ink-3);
}

.time-field-icon,
.time-field-chevron {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    color: var(--ink-2);
    pointer-events: none;
}

.time-field-icon {
    left: var(--space-3);
}

.time-field-chevron {
    right: var(--space-3);
    font-size: var(--space-3);
}

.time-field-cols {
    display: flex;
    gap: var(--space-2);
}

.time-field-col {
    display: flex;
    flex-direction: column;
}

.time-field-col + .time-field-col {
    padding-left: var(--space-2);
    border-left: 1px solid var(--line-soft);
}

.time-field-head {
    padding-bottom: var(--space-1);
    text-align: center;
    font: var(--text-micro);
    color: var(--ink-2);
}

.time-field-list {
    position: relative;
    display: flex;
    flex-direction: column;
    width: calc(var(--space-7) + var(--space-2));
    max-height: calc((var(--space-6) - var(--space-1) / 2) * 7);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

.time-field-option {
    flex: none;
    height: calc(var(--space-6) - var(--space-1) / 2);
    padding: 0;
    border: 0;
    border-radius: var(--radius-control);
    background: none;
    color: var(--ink);
    font: var(--text-small);
    font-variant-numeric: tabular-nums;
}

.time-field-option:hover {
    background: var(--accent-wash);
    color: var(--accent-ink);
}

.time-field-option:focus-visible {
    outline: medium solid var(--accent-tint);
    outline-offset: calc(-1 * var(--space-1) / 2);
}

.time-field-option[aria-selected="true"] {
    background: var(--accent);
    color: var(--surface);
    font-weight: 700;
}

/* A DateTimeField (apps.core.widgets.DateTimeFieldInput): the day, then its time. */
.date-time-field {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 8rem);
    gap: var(--space-2);
}

@media (pointer: coarse) {
    .time-field-cols {
        justify-content: center;
        gap: var(--space-4);
    }

    .time-field-col {
        flex: 1;
        max-width: calc(var(--space-7) * 3);
    }

    .time-field-col + .time-field-col {
        padding-left: var(--space-4);
    }

    .time-field-list {
        width: auto;
        max-height: calc(var(--control-h) * 5);
    }

    .time-field-option {
        height: var(--control-h);
        font: var(--text-body);
    }
}

/* === Switch === */
/* An on/off field: <label class="switch"><input type="checkbox" class="switch-input" role="switch"> Name</label>. */
.switch {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    min-height: var(--control-h);
    margin: 0;
    font-weight: 600;
    font-size: var(--control-font);
    cursor: pointer;
}

.switch-input {
    appearance: none;
    position: relative;
    flex: none;
    width: calc(var(--space-6) + var(--space-2));
    height: var(--space-5);
    margin: 0;
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--line-strong);
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.switch-input::before {
    content: "";
    position: absolute;
    top: calc(var(--space-1) * 0.75);
    left: calc(var(--space-1) * 0.75);
    width: calc(var(--space-5) - var(--space-1) * 1.5);
    height: calc(var(--space-5) - var(--space-1) * 1.5);
    border-radius: var(--radius-pill);
    background: var(--surface);
    box-shadow: var(--shadow);
    transition: transform 0.15s ease;
}

.switch-input:checked {
    background: var(--accent);
}

.switch-input:checked::before {
    transform: translateX(var(--space-4));
}

.switch-input:focus-visible {
    outline: 0;
    box-shadow: 0 0 0 var(--space-1) var(--accent-wash);
}

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

/* === Reveal === */
/* A block that expands and collapses at the menu's pace: .reveal > .reveal-inner, open with
   .is-open. Collapsed, its fields are hidden but still in the form, as display: none left them. */
.reveal {
    display: grid;
    grid-template-rows: 0fr;
    visibility: hidden;
    transition: grid-template-rows var(--rail-motion), visibility var(--rail-motion);
}

.reveal.is-open {
    grid-template-rows: 1fr;
    visibility: visible;
}

/* relative: its clip takes positioned content too (select2's hidden <select>). */
.reveal > .reveal-inner {
    position: relative;
    min-height: 0;
    overflow: hidden;
}

/* Clipped only while it grows, so focus rings and pop-ups show once it is open. */
.reveal.is-open > .reveal-inner {
    overflow: visible;
    animation: reveal-clip var(--rail-motion);
}

@keyframes reveal-clip {
    from, to { overflow: hidden; }
}

@media (prefers-reduced-motion: reduce) {
    .reveal,
    .check-cards > .check-card {
        transition: none;
    }

    .reveal.is-open > .reveal-inner {
        animation: none;
    }
}

/* === Check card === */
/* A section a tick box turns on (.is-on), its body a .reveal. On, it spans the row at once;
   off, only once its body has collapsed. */
.check-cards {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-3);
}

.check-cards > .check-card {
    transition: grid-column var(--rail-motion) allow-discrete;
    transition-timing-function: step-end;
}

.check-cards > .check-card.is-on {
    grid-column: 1 / -1;
    transition-timing-function: step-start;
}

.check-card.is-on {
    border-color: var(--accent);
    box-shadow: 0 0 0 calc(var(--space-1) / 4) var(--accent);
}

.check-card-head {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin: 0;
    font: var(--text-section);
    font-weight: 700;
    cursor: pointer;
}

.check-card-head .form-check-input {
    flex: none;
    width: calc(var(--space-5) - var(--space-1));
    height: calc(var(--space-5) - var(--space-1));
    margin: 0;
}

.check-card-body {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-top: var(--space-3);
}

@media (max-width: 767.98px) {
    .check-cards {
        grid-template-columns: minmax(0, 1fr);
    }

    .check-card {
        padding: var(--space-3);
    }
}

/* === Action bar === */
/* A form's actions: Cancel or Back, then its one primary action, at the end of the form. On a
   phone it pins above the tab bar (on Steps, to the screen's foot, over the safe area), edge to
   edge of main's p-3, and the buttons fill it. */
.action-bar {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-2);
}

@media (max-width: 767.98px) {
    .action-bar {
        position: sticky;
        bottom: var(--shell-bottom);
        z-index: var(--z-sticky);
        margin: var(--space-4) calc(-1 * var(--space-4)) calc(-1 * var(--space-4));
        padding: var(--space-3) var(--space-4);
        background: var(--surface);
        border-top: thin solid var(--line);
        box-shadow: var(--shadow);
    }

    .action-bar > .btn {
        flex: 1 1 0;
    }

    .action-bar > .btn-primary {
        flex-grow: 1.6;
    }
}

/* === Steps === */
/* components/steps.html + steps.js: one [data-step] at a time on a phone; every step from 768px. */
.steps {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: var(--topbar-h);
    font: var(--text-section);
}

.steps-close {
    flex: none;
    color: var(--ink);
    font-size: 1.5rem;
    line-height: 1;
    text-decoration: none;
}

.steps-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 700;
}

.steps-count {
    flex: none;
    font: var(--text-small);
    color: var(--ink-2);
}

.steps-bar {
    position: absolute;
    inset: auto 0 var(--space-1);
    display: flex;
    gap: var(--space-1);
}

.steps-bar > span {
    flex: 1;
    height: var(--space-1);
    border-radius: var(--radius-pill);
    background: var(--line);
}

.steps-bar > .is-done {
    background: var(--accent);
}

/* steps.html track=True: the named bars inside a sheet. */
.steps-track {
    display: flex;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}

.steps-track-step {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
    font: var(--text-small);
    font-weight: 600;
    color: var(--ink-2);
}

.steps-track-step::before {
    content: "";
    height: var(--space-1);
    border-radius: var(--radius-pill);
    background: var(--line);
}

.steps-track-step.is-done::before {
    background: var(--accent);
}

.steps-track-step.is-current {
    color: var(--accent-ink);
}

@media (max-width: 767.98px) {
    /* No tab bar: the action bar covers the safe area itself. */
    :root:has(.app-header .steps) {
        --shell-bottom: 0rem;
    }

    :root:has(.app-header .steps) .action-bar {
        padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom));
    }

    body:has(.app-header .steps) .app-tabbar,
    .app-header:has(.steps) .crumb {
        display: none;
    }

    [data-stepper] [data-step]:not(.is-current),
    [data-stepper] .is-step-hidden {
        display: none;
    }
}

@media (min-width: 768px) {
    .app-header .steps,
    [data-stepper] .steps-only {
        display: none;
    }
}

/* === Form page === */
/* An Add or Edit page over Steps (a case, contact, discount request, forage sample, opportunity): on a
   phone one step at a time on the grey page, the top bar naming it; from 768px the title over every
   step, each on its own card. */
.form-page { display: flex; flex-direction: column; gap: var(--space-4); }
.form-page-title { margin: 0; }
.form-page .form-label { display: block; }
.step-card { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.step-card-head { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-3); }
.step-card-head > .step-card-title { margin-right: auto; }
@media (max-width: 767.98px) {
    .form-page-title,
    .step-card-title { display: none; }
    /* Its action bar sits at the screen's foot however short the step (main's p-3 either side). */
    .form-page:has(> .action-bar) {
        min-height: calc(100dvh - var(--topbar-h) - var(--shell-bottom) - 2 * var(--space-4));
    }
    .form-page > .action-bar { margin-top: auto; }
}
@media (min-width: 768px) {
    .step-card {
        padding: var(--space-4) var(--space-5);
        background: var(--surface);
        border: thin solid var(--line);
        border-radius: var(--radius-card);
    }
}

/* === Quantity stepper === */
/* A whole-number box with − and + either side on a phone (static/js/qty_stepper.js); a plain box
   from 768px. */
.qty-stepper {
    display: inline-flex;
    align-items: stretch;
    min-width: 0;
}

.qty-stepper-btn {
    display: none;
}

@media (max-width: 767.98px) {
    .qty-stepper {
        border: thin solid var(--line-strong);
        border-radius: var(--radius-control);
        background: var(--surface);
        overflow: hidden;
    }

    .qty-stepper > input {
        width: calc(var(--space-6) + var(--space-1));
        padding: 0;
        border: 0;
        border-radius: 0;
        text-align: center;
        font-weight: 600;
        -moz-appearance: textfield;
    }

    .qty-stepper > input::-webkit-inner-spin-button,
    .qty-stepper > input::-webkit-outer-spin-button {
        appearance: none;
        margin: 0;
    }

    .qty-stepper-btn {
        display: flex;
        flex: none;
        align-items: center;
        justify-content: center;
        width: calc(var(--space-6) + var(--space-1) / 2);
        padding: 0;
        border: 0;
        background: none;
        color: var(--accent-ink);
        font-size: 1.125rem;
    }

    .qty-stepper-btn[data-qty-step="-1"] {
        color: var(--ink-2);
    }

    .qty-stepper-btn:disabled {
        color: var(--ink-3);
    }
}

/* === Files === */
/* components/file_tiles.html + static/js/file_tiles.js: what is on file as thumbnails, the files
   picked for this save beside them (each with an ×), then "+ Add". */
.file-tiles {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.file-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    width: calc(var(--space-7) + var(--space-4));
    height: calc(var(--space-7) + var(--space-4));
    padding: var(--space-1);
    overflow: hidden;
    border: thin solid var(--line);
    border-radius: var(--radius-control);
    background: var(--sunken);
    color: var(--ink-2);
    font: var(--text-small);
    text-align: center;
    text-decoration: none;
}

.file-tiles-picked {
    display: contents;
}

.file-tile > img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.file-tile-name {
    max-width: 100%;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.file-tile-remove {
    position: absolute;
    top: var(--space-1);
    right: var(--space-1);
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--space-5);
    height: var(--space-5);
    padding: 0;
    border: 0;
    border-radius: var(--radius-pill);
    background: var(--surface);
    color: var(--danger);
    box-shadow: var(--shadow);
}

.file-tile-add {
    margin: 0;
    border: thin dashed var(--ink-3);
    background: var(--surface);
    color: var(--accent-ink);
    font-weight: 600;
    cursor: pointer;
}

.file-tile-add:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 var(--space-1) var(--accent-wash);
}

/* === Page head === */
/* components/page_head.html: title and count, the page's controls, then Add (a + alone on a
   narrow screen). */
.page-head {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}
.page-head-title {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.page-head-name { margin: 0; font: var(--text-heading); }
/* A list page's rows under its head (.page-stack), and a row of controls spread across it. */
.page-stack { display: flex; flex-direction: column; gap: var(--space-3); }
.page-tools { display: flex; flex-direction: column; gap: var(--space-2); }
.page-tools-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
@media (pointer: fine) and (min-width: 1024px) {
    .page-stack > .search-box { max-width: calc(var(--space-7) * 15); }
}
.page-head-count { font: var(--text-small); color: var(--ink-2); }
.page-head-actions {
    flex: none;
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
.page-head-meta { display: flex; align-items: baseline; gap: var(--space-2); min-width: 0; }
@media (pointer: fine) and (min-width: 1024px) {
    .page-head-title { flex-direction: row; align-items: baseline; gap: var(--space-3); }
    .page-head-add .icon-plus { display: none; }
}
@media not all and (pointer: fine), (max-width: 1023.98px) {
    .page-head-add { width: var(--control-h); padding: 0; }
    .page-head-name { font-weight: 700; }
    /* The page's head as a white band under the top bar (Today, Dashboards, Reports phone boards),
       stepping back over main's p-3: a .page-band (the head and what scopes the page: tabs, filters),
       or a page head that opens the page. */
    .page-band,
    :is(main, main > :first-child) > .page-head:first-child {
        margin: calc(-1 * var(--space-4)) calc(-1 * var(--space-4)) 0;
        padding: var(--space-3);
        background: var(--surface);
        border-bottom: thin solid var(--line);
    }
    /* Tabs closing a band underline on its edge. */
    .page-band > .tabs:last-child {
        margin-bottom: calc(-1 * var(--space-3));
        border-bottom: 0;
    }
    /* The link's aria-label still names it. */
    .page-head-add-label { display: none; }
}

/* === Tabs === */
/* components/tabs.html: underlined, scrolling sideways when they overflow. .tabs--chips draws
   them as chips on a narrow screen (a list's saved views); a record's panes stay tabs. */
.tabs {
    display: flex;
    align-items: flex-end;
    gap: var(--space-1);
    overflow-x: auto;
    scrollbar-width: none;
    border-bottom: thin solid var(--line);
}
.tab {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: calc(var(--space-2) + var(--space-1) / 2) calc(var(--space-3) + var(--space-1) / 2);
    border: 0;
    border-bottom: calc(var(--space-1) / 2) solid transparent;
    background: none;
    color: var(--ink-2);
    font: 600 0.875rem/1.25rem var(--font-sans);
    white-space: nowrap;
    text-decoration: none;
}
.tab:hover { color: var(--ink); }
.tab[aria-current="page"],
.tab[aria-pressed="true"],
.tab[aria-selected="true"] {
    border-bottom-color: var(--accent);
    color: var(--accent-ink);
}
.tab:disabled { color: var(--ink-3); }
.tab-note { font-weight: 400; color: var(--ink-3); }
.tab-done { color: var(--tone-done-ink); }
.tab-save-menu { min-width: calc(var(--space-7) * 6); }
@media (pointer: coarse) {
    .tab { min-height: var(--control-h); }
}
@media not all and (pointer: fine), (max-width: 1023.98px) {
    .tabs--chips { align-items: center; gap: var(--space-2); border-bottom: 0; }
    .tabs--chips .tab {
        min-height: calc(var(--control-h) - var(--space-3));
        padding: 0 calc(var(--space-3) - var(--space-1) / 4);
        border: 0;
        border-radius: var(--radius-pill);
        background: var(--accent-wash);
        color: var(--accent-ink);
        font: var(--text-small);
        font-weight: 600;
    }
    .tabs--chips .tab[aria-current="page"],
    .tabs--chips .tab[aria-selected="true"] {
        border-color: var(--accent);
        background: var(--accent);
        color: var(--surface);
    }
    .tabs--chips .tab[aria-selected="true"] .tab-done { color: inherit; }
}

/* === Segmented control === */
/* components/_view_switcher.html: List | Board, or a page's view_choices. Also a choice of one
   (radios, below), Bootstrap pills (.active) and buttons for a page's own switch (pressed, not current). */
.segmented {
    display: inline-flex;
    flex: none;
    padding: calc(var(--space-1) / 2);
    background: var(--sunken);
    border-radius: var(--radius-control);
}
.segmented-item {
    display: inline-flex;
    align-items: center;
    min-height: calc(var(--control-h) - var(--space-1));
    padding: 0 var(--space-3);
    border-radius: var(--radius-control);
    color: var(--ink-2);
    font: var(--text-small);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}
.segmented-item:hover { color: var(--ink); }
button.segmented-item { border: 0; background: none; }
.segmented-item[aria-current="page"],
.segmented-item[aria-pressed="true"],
.segmented-item.active,
.segmented-input:checked + .segmented-item {
    background: var(--surface);
    color: var(--ink);
    box-shadow: var(--shadow);
}
/* A choice of one value: a radio (.segmented-input) before each label.segmented-item. .segmented--fill
   takes the row's width, its items sharing it. */
.segmented-input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
label.segmented-item {
    margin: 0;
    cursor: pointer;
}
.segmented-input:focus-visible + .segmented-item {
    outline: calc(var(--space-1) / 2) solid var(--accent);
}
.segmented--fill {
    display: flex;
}
.segmented--fill > .segmented-item {
    flex: 1 1 0;
    justify-content: center;
}

/* === List controls === */
/* components/_column_picker.html (Columns: show, hide, drag to reorder) and _sort_menu.html
   (Sort, over cards). */
/* Capped, so a tall menu (contacts' 45 columns) scrolls itself rather than the page behind it. */
.column-picker-menu {
    max-height: min(60vh, 26rem);
    overflow-y: auto;
    overscroll-behavior: contain;
}
/* A filter box (contacts only) sticks to the menu's padding box: no padding above it, or the rows
   scroll through a strip in plain sight. Opaque, so they pass under it. */
.column-picker-menu:has(.column-picker-filter) { padding-top: 0; }
.column-picker-menu > li:has(> .column-picker-filter) {
    position: sticky;
    top: 0;
    z-index: 2;
    padding-top: var(--space-2);
    background-color: var(--surface);
    box-shadow: 0 var(--space-2) var(--space-2) calc(-1 * var(--space-2)) rgb(0 0 0 / 15%);
}
/* Drag an item by its grip to reorder (list_page.js keeps the order). */
.column-picker-menu[data-column-reorder] > li { cursor: grab; }
.column-picker-menu[data-column-reorder] > li.column-dragging { opacity: 0.5; cursor: grabbing; }
.column-picker-menu .column-grip { color: var(--ink-3); cursor: grab; }
.sort-menu-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    min-height: var(--control-h);
    padding: 0;
    border: 0;
    background: none;
    color: var(--ink-2);
    font: var(--text-small);
}
.sort-menu-btn strong { color: var(--ink); font-weight: 600; }
.sort-menu-chevron { font-size: 0.75em; }
.sort-menu .dropdown-item[aria-current] { color: var(--accent-ink); font-weight: 600; }

/* === Sheet choices === */
/* components/_sheet_choices.html: a sheet's rows to pick one from. A radio circle, filled on
   the current row; or (--check) a tick on it; or (--none) no mark, a ⋯ menu's actions. */
.sheet-choices { display: flex; flex-direction: column; }
.sheet-choice {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    min-height: var(--control-h);
    padding: var(--space-2) 0;
    border: 0;
    border-bottom: thin solid var(--line-soft);
    background: none;
    color: var(--ink);
    font: var(--text-body);
    font-size: var(--control-font);
    text-align: left;
    text-decoration: none;
}
.sheet-choice:last-child { border-bottom: 0; }
.sheet-choice:hover { color: var(--accent-ink); }
.sheet-choice[aria-current="true"] { font-weight: 600; }
.sheet-choice--danger, .sheet-choice--danger:hover { color: var(--danger); }
.sheet-choice-mark {
    flex: none;
    width: calc(var(--space-4) + var(--space-1));
    height: calc(var(--space-4) + var(--space-1));
    border-radius: 50%;
}
.sheet-choices--radio .sheet-choice-mark { border: calc(var(--space-1) * 3 / 8) solid var(--line-strong); }
.sheet-choices--radio .sheet-choice[aria-current="true"] .sheet-choice-mark { border: calc(var(--space-1) * 3 / 2) solid var(--accent); }
.sheet-choices--check .sheet-choice-mark { display: inline-flex; align-items: center; justify-content: center; color: var(--accent); }
.sheet-choices--check .sheet-choice[aria-current="true"] .sheet-choice-mark::before { content: "\2713"; font-weight: 700; }
/* Won… / Lost… under the choices, side by side; a footer that only cancels fills its row. */
.sheet-choice-actions { display: flex; gap: var(--space-3); margin-top: var(--space-3); }
.sheet-choice-actions > .btn { flex: 1 1 0; }
.modal-sheet .modal-footer:has(> .sheet-cancel:only-child) > .sheet-cancel { flex: 1 1 auto; }

/* === Filter sheet === */
/* components/_list_filter_sheet.html: Filters, Group by and Favorites behind a segmented control,
   a row per choice with one thin line between rows. */
.filter-sheet { display: flex; flex-direction: column; gap: var(--space-5); }
.filter-sheet-section { display: flex; flex-direction: column; gap: var(--space-2); }
.filter-sheet-label {
    margin: 0;
    color: var(--ink-2);
    font: var(--text-micro);
    letter-spacing: var(--micro-tracking);
    text-transform: uppercase;
}
.filter-sheet-favorites { margin: 0; padding: 0; list-style: none; }
.filter-sheet-favorites > li { padding: var(--space-1) 0; border-bottom: thin solid var(--line-soft); font-size: var(--control-font); }
.filter-sheet-switch { display: flex; }
.filter-sheet-switch > .segmented-item { flex: 1 1 0; justify-content: center; border: 0; background: none; }
.filter-sheet-rows { display: flex; flex-direction: column; }
.filter-sheet-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: var(--control-h);
    padding: var(--space-2) 0;
    border: 0;
    border-bottom: thin solid var(--line-soft);
    background: none;
    color: var(--ink);
    font-size: var(--control-font);
    text-align: left;
    text-decoration: none;
}
.filter-sheet-row:last-child { border-bottom: 0; }
.filter-sheet-row > .icon { color: var(--ink-3); }
.filter-sheet-row[aria-current="true"] { color: var(--accent-ink); font-weight: 600; }
.filter-sheet-row[aria-current="true"] > .icon { color: var(--tone-done-ink); }
.filter-sheet-row--add { color: var(--accent-ink); font-weight: 600; }
.filter-sheet-row--add > .icon { color: var(--accent); }
.filter-sheet-group-add { margin-top: var(--space-2); }

/* === Queue === */
/* components/queue.html (a To decide queue): the list on the left, scrolling on its own, and the
   selected record's page beside it. Stacked below 1024px. The list is one white column of rows
   (Cases-Queue-Desk, Discounts-Queue-Desk); from 1024px it steps back over main's gutter to sit
   flush against the rail. */
.queue {
    display: grid;
    gap: var(--space-4);
}
.queue-list {
    display: flex;
    flex-direction: column;
    min-width: 0;
    background: var(--surface);
    border: thin solid var(--line);
    border-radius: var(--radius-card);
    overflow: hidden;
}
.queue-head {
    display: flex;
    flex-direction: column;
    gap: calc(var(--space-2) + var(--space-1) / 2);
    padding: var(--space-4) calc(var(--space-3) + var(--space-1) / 2) calc(var(--space-2) + var(--space-1) / 2);
    border-bottom: thin solid var(--line);
}
.queue-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
}
.queue-tools .search-filter-btn {
    min-height: calc(var(--control-h) - var(--space-3));
}
.queue-tools .filter-chip.queue-scope {
    background: var(--accent);
    color: var(--surface);
}
/* The sort as a neutral pill beside the chips (Cases-Queue-Desk). */
.queue-tools .sort-menu-btn {
    min-height: calc(var(--control-h) - var(--space-3));
    padding: 0 calc(var(--space-2) + var(--space-1) / 2);
    border-radius: var(--radius-pill);
    background: var(--fill-muted);
    font-weight: 600;
}
.queue-tools .sort-menu-btn strong { color: inherit; }
/* The column holds ~302px: its tools fit one row as the board draws them, 12.5px chips and a sort
   pill that names the order alone ("Oldest first ˅"). */
.queue-tools :is(.filter-chip, .search-filter-btn, .sort-menu-btn) {
    padding-inline: var(--space-2);
    font-size: 0.78125rem;
}
.queue-tools .sort-menu-prefix { display: none; }
/* Rows, not cards: divided by a rule, the selected one washed with the accent's bar. */
.queue-list .list-cards { gap: 0; }
.queue-list .list-card {
    padding: calc(var(--space-2) + var(--space-1) / 2) calc(var(--space-3) + var(--space-1) / 2);
    border: 0;
    border-bottom: thin solid var(--sunken);
    border-radius: 0;
}
.queue-list .list-card[aria-current="true"] {
    background: var(--page);
    box-shadow: inset calc(var(--space-1) * 3 / 4) 0 0 var(--accent);
}
.queue-list .list-empty { padding: var(--space-4) calc(var(--space-3) + var(--space-1) / 2); }
.queue-late {
    color: var(--tone-refused-ink);
    font-weight: 600;
}
.queue-pane {
    min-width: 0;
}
.queue-pane-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
}
@media (min-width: 1024px) {
    .queue {
        --queue-gutter-x: calc(var(--space-5) + var(--space-1));
        --queue-gutter-y: calc(var(--space-4) + var(--space-1));
        grid-template-columns: var(--queue-list-w) minmax(0, 1fr);
        column-gap: calc(var(--space-5) - var(--space-1) / 2);
        align-items: start;
    }
    .queue-list {
        position: sticky;
        top: var(--space-3);
        max-height: calc(100dvh - 2 * var(--space-3));
        overflow-y: auto;
    }
    /* The page's own queue (Discounts) or one under a list's head (Cases): flush to the rail, the
       gutter it steps over counted in its width. */
    main > .queue,
    .list-page .queue {
        grid-template-columns: calc(var(--queue-list-w) - var(--queue-gutter-x)) minmax(0, 1fr);
    }
    main > .queue > .queue-list,
    .list-page .queue-list {
        top: 0;
        height: 100dvh;
        max-height: none;
        margin: calc(-1 * var(--queue-gutter-y)) 0 calc(-1 * var(--queue-gutter-y)) calc(-1 * var(--queue-gutter-x));
        border-width: 0 thin 0 0;
        border-radius: 0;
    }
    /* Under the list's head and search bar, ruled off above. */
    .list-page .queue-list {
        margin-top: 0;
        border-top-width: thin;
    }
}

/* === Report sheet === */
/* The shared A4 report sheet (10-forage.md). The PDF is Chromium printing the page; @page can't
   read a token, hence its literal 12mm. */
@page {
    size: A4;
    margin: 12mm;
}

/* The page around a sheet: its controls and actions in one row, then the sheet. On a phone the
   actions (an .action-bar) go last and pin above the tab bar. */
.report-page {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4) var(--space-3);
}
.report-page > .report-body {
    flex: 1 1 100%;
    min-width: 0;
}
.report-page > .action-bar {
    flex: none;
}
.report-controls {
    flex: 1 1 auto;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3) var(--space-5);
}
.report-control {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
.report-banner {
    margin-bottom: var(--space-4);
}

.report-sheet {
    display: flex;
    flex-direction: column;
    width: var(--sheet-width);
    max-width: 100%;
    margin: 0 auto;
    padding: var(--sheet-margin);
    background: var(--surface);
    border: thin solid var(--line-strong);
    color: var(--ink);
    font: 400 var(--sheet-size-body)/1.45 var(--font-sans);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}
/* :where, so a block's own class sets its margin. */
:where(.report-sheet) p {
    margin: 0;
}

.report-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-5);
    min-height: calc(var(--sheet-band-h) + var(--space-3));
    padding-bottom: var(--space-3);
    border-bottom: thin solid var(--ink-3);
    break-inside: avoid;
}
.report-head-text {
    min-width: 0;
}
.report-title {
    margin: 0;
    font: 700 var(--sheet-size-title)/1.15 var(--font-sans);
    letter-spacing: -0.01em;
}
.report-meta {
    margin-top: var(--space-1);
    font-size: var(--sheet-size-heading);
    color: var(--ink-2);
}
.report-brand {
    flex: none;
    display: block;
    width: auto;
    max-width: 100%;
    height: var(--sheet-logo-h);
}
.report-brand--band {
    height: var(--sheet-band-h);
}

.report-panels {
    display: flex;
    gap: var(--space-3);
    margin-top: var(--space-3);
    break-inside: avoid;
}
.report-panel {
    flex: 1 1 0;
    min-width: 0;
    padding: var(--space-2) var(--space-3);
    border: thin solid var(--line-strong);
    border-radius: var(--space-1);
}
.report-panel-title {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-2);
    font-size: var(--sheet-size-label);
    font-weight: 700;
}
.report-cols {
    display: flex;
    gap: var(--space-5);
}
.report-cols > * {
    flex: 1 1 0;
    min-width: 0;
}
.report-dl {
    display: grid;
    grid-template-columns: minmax(6em, max-content) minmax(0, 1fr);
    align-content: start;
    gap: var(--space-1) var(--space-3);
    margin: 0;
}
.report-dl dt {
    font-size: var(--sheet-size-small);
    font-weight: 400;
    color: var(--ink-2);
    white-space: nowrap;
}
.report-dl dd {
    margin: 0;
    overflow-wrap: anywhere;
}

.report-heading {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: var(--space-4) 0 0;
    padding-bottom: var(--space-1);
    border-bottom: thin solid var(--ink-3);
    font: 700 var(--sheet-size-heading)/1.3 var(--font-sans);
    break-after: avoid;
}
/* A heading's or a panel's round icon; --slot recolours it (a macro card takes its pie slice's). */
.report-icon {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6em;
    height: 1.6em;
    border-radius: var(--radius-pill);
    background: var(--slot, var(--sheet-icon));
    font-size: var(--sheet-size-label);
}
.report-icon img {
    width: 60%;
    height: 60%;
    object-fit: contain;
}

/* A value's band in the state tones, no glyph: it measures a nutrient, not a workflow state. */
.report-band {
    display: inline-block;
    min-width: 6em;
    padding: 0 var(--space-2);
    border-radius: var(--radius-pill);
    background: var(--tone-closed-fill);
    color: var(--tone-closed-ink);
    font-size: var(--sheet-size-small);
    font-weight: 700;
    line-height: 1.6;
    text-align: center;
    white-space: nowrap;
}
.report-band--ok {
    background: var(--tone-done-fill);
    color: var(--tone-done-ink);
}
.report-band--warn {
    background: var(--tone-pending-fill);
    color: var(--tone-pending-ink);
}
.report-band--alert {
    background: var(--tone-refused-fill);
    color: var(--tone-refused-ink);
}

/* One result: its name, value, typical range and band; its meter; its text. */
.report-row {
    padding: var(--space-2) 0;
    border-bottom: thin solid var(--line-soft);
}
.report-row:last-child {
    border-bottom: 0;
}
/* The head and meter stay with the first lines of the text. */
.report-row-top {
    break-inside: avoid;
    break-after: avoid;
}
.report-row-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1) var(--space-2);
}
.report-row-head > strong,
.report-row-value {
    font-size: var(--sheet-size-label);
}
.report-row-value {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.report-row-typical {
    font-size: var(--sheet-size-small);
    color: var(--ink-2);
    white-space: nowrap;
}
.report-row-head > .report-band {
    margin-left: auto;
}
.report-pen {
    font-size: var(--sheet-size-small);
    color: var(--ink-3);
    text-decoration: none;
}
.report-pen:hover,
.report-pen:focus-visible {
    color: var(--accent-ink);
}
.report-flag {
    color: var(--danger);
}
.report-meter {
    position: relative;
    width: 60%;
    height: var(--space-2);
    margin: var(--space-1) 0 var(--space-2);
    border-radius: var(--space-1);
    background: var(--sunken);
}
.report-meter-zone {
    position: absolute;
    top: 0;
    bottom: 0;
    border-radius: var(--space-1);
    background: var(--sheet-zone);
}
.report-meter-mark {
    position: absolute;
    top: calc(1px - var(--space-1));
    width: var(--space-1);
    height: calc(var(--space-2) + var(--space-1) + 2px);
    margin-left: calc(-1 * var(--space-1) / 2);
    border-radius: calc(var(--space-1) / 2);
    background: var(--outcome-closed);
}
.report-meter-mark--ok {
    background: var(--outcome-done);
}
.report-meter-mark--warn {
    background: var(--outcome-pending);
}
.report-meter-mark--alert {
    background: var(--outcome-refused);
}
.report-text {
    font-size: var(--sheet-size-small);
    color: var(--sheet-text);
    white-space: pre-wrap;
    orphans: 3;
    widows: 3;
}
.report-note {
    font-size: var(--sheet-size-small);
    font-style: italic;
    color: var(--ink-2);
}
.report-fine {
    margin-top: var(--space-2);
    font-size: var(--sheet-size-fine);
    color: var(--sheet-text);
}

/* components/money_table.html on a sheet: the sheet's full width, its type, plain lines, labels left. */
.report-sheet .money-table {
    margin-top: var(--space-2);
    font-size: var(--sheet-size-body);
}
.report-sheet .money-table :is(td, th) {
    padding: calc(var(--space-1) - 1px) 0;
}
.report-sheet .money-table tbody :is(.money-table-label, .money-table-amount) {
    font-weight: 400;
}
.report-sheet .money-table tfoot :is(th, td) {
    text-align: left;
    font-weight: 400;
}
.report-sheet .money-table tfoot .money-table-amount {
    text-align: right;
}
.report-sheet .money-table .money-table-total > * {
    font-weight: 700;
}
.report-sheet .money-table-total > * {
    padding-top: var(--space-1);
}

/* A diet plan's text block, edited where it stands; the PDF draws it plain. */
.report-editable {
    margin-top: var(--space-3);
    padding: var(--space-2);
    border: thin dashed var(--ink-3);
    border-radius: var(--space-1);
    cursor: text;
}
.report-editable:hover {
    background: var(--page);
}
.report-editable[contenteditable="true"] {
    background: var(--surface);
    outline: calc(var(--space-1) / 2) solid var(--accent);
}
.report-editable:empty::before {
    content: "Click to edit this text field";
    color: var(--ink-3);
}
.report-sheet--page .report-editable {
    padding: 0;
    border: 0;
}
/* A heading and the chart or table under it, never split across a printed page. */
.report-keep {
    break-inside: avoid;
}
.report-chart {
    margin-top: var(--space-2);
}
.report-table-frame {
    overflow-x: auto;
}
.report-table {
    width: 100%;
    max-width: 74%;
    margin: var(--space-2) auto 0;
    border-collapse: collapse;
    font-size: var(--sheet-size-small);
    font-variant-numeric: tabular-nums;
}
.report-table th {
    padding: calc(var(--space-1) - 1px) var(--space-2);
    border-bottom: thin solid var(--ink-3);
    font-weight: 700;
    text-align: right;
    white-space: nowrap;
}
.report-table td {
    padding: calc(var(--space-1) / 2) var(--space-2);
    text-align: right;
}
.report-table :is(th, td):is(:first-child, :last-child) {
    text-align: left;
}
.report-ratios {
    display: flex;
    gap: var(--space-5);
    margin-top: var(--space-2);
    break-inside: avoid;
}
.report-ratios > * {
    flex: 1 1 0;
    min-width: 0;
}
.report-ratio-title {
    font-size: var(--sheet-size-heading);
    font-weight: 700;
}
.report-ratio-result {
    font-weight: 600;
}
.report-macro {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-top: var(--space-2);
}
.report-state-text {
    margin-top: var(--space-1);
}

.report-close {
    padding-top: var(--space-4);
    break-inside: avoid;
}
.report-disclaimer {
    margin-bottom: var(--space-3);
    font-size: var(--sheet-size-fine);
    color: var(--sheet-text);
}
.report-disclaimer > strong {
    color: var(--ink);
}
.report-footer-image {
    display: block;
    width: 100%;
}
.report-footer {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    padding-top: var(--space-1);
    font-size: var(--sheet-size-fine);
    color: var(--sheet-text);
}
.report-footer > :last-child {
    text-align: right;
}

/* The bare page a diet plan's PDF is taken from: the sheet is the page, its margin @page's. */
.report-pdf {
    margin: 0;
    padding: 0;
    background: var(--surface);
}
.report-sheet--page {
    width: calc(var(--sheet-width) - 2 * var(--sheet-margin));
    max-width: none;
    margin: 0;
    padding: 0;
    border: 0;
}
.report-sheet--page .report-page-alone {
    break-before: page;
    break-after: page;
}

@media screen and (max-width: 767.98px) {
    .report-page > .action-bar {
        order: 1;
        flex: 1 1 100%;
    }
    .report-controls:has(.report-control + .report-control) .report-control {
        flex-direction: column;
        align-items: flex-start;
    }
    .report-sheet {
        --sheet-size-title: 20px;
        --sheet-size-heading: 15px;
        --sheet-size-label: 13px;
        --sheet-size-body: 13px;
        --sheet-size-small: 12.5px;
        --sheet-size-fine: 12px;
        --sheet-logo-h: 52px;
        --sheet-band-h: 64px;
        padding: var(--space-4) var(--space-3);
        border-color: var(--line);
        border-radius: var(--radius-card);
    }
    .report-head {
        flex-direction: column-reverse;
        align-items: stretch;
        gap: var(--space-3);
        min-height: 0;
    }
    .report-head > .report-brand {
        align-self: flex-end;
    }
    .report-head > .report-brand--band {
        align-self: flex-start;
    }
    .report-panels,
    .report-cols,
    .report-ratios,
    .report-footer {
        flex-direction: column;
    }
    .report-cols {
        gap: var(--space-2);
    }
    .report-meter {
        width: 80%;
    }
    .report-sheet .money-table,
    .report-table {
        max-width: none;
    }
    .report-table :is(th, td) {
        padding-inline: var(--space-1);
    }
    .report-table th {
        white-space: normal;
    }
    .report-footer > :last-child {
        text-align: left;
    }
}

@media print {
    /* main's p-3 is Bootstrap's !important padding, so the page steps back over it instead. */
    .report-page {
        margin: calc(-1 * var(--space-4));
    }
    .report-page > :not(.report-body) {
        display: none;
    }
    .report-sheet {
        width: auto;
        max-width: none;
        margin: 0;
        padding: 0;
        border: 0;
    }
    .report-editable {
        padding: 0;
        border: 0;
    }
    .report-page-alone {
        break-before: page;
        break-after: page;
    }
}

/* === Filter row === */
/* components/filter_row.html; its pops (.filter-pop) anchor under a mouse and are sheets on touch. */
.filter-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-3);
}
/* Positioned, so a narrow screen's hidden label stays inside the scrolling row. */
.filter-row-item {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-width: 0;
}
.filter-row-label {
    margin: 0;
    font: var(--text-small);
    font-weight: 600;
    color: var(--ink);
}
.filter-row-control { position: relative; }
.filter-trigger {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    height: var(--control-h);
    padding: 0 var(--space-3);
    border: thin solid var(--line-strong);
    border-radius: var(--radius-control);
    background: var(--surface);
    color: var(--ink);
    font: var(--text-body);
    font-size: var(--control-font);
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
}
.filter-trigger:hover { border-color: var(--accent); }
.filter-trigger[aria-expanded="true"] {
    border-color: var(--accent);
    box-shadow: 0 0 0 var(--space-1) var(--accent-wash);
}
.filter-trigger-icon,
.filter-trigger-chevron { flex: none; color: var(--ink-2); }
.filter-trigger-chevron { margin-left: auto; font-size: var(--space-3); }
.filter-trigger-value {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    font-variant-numeric: tabular-nums;
}
.filter-trigger-label,
.filter-row-reset { display: none; }
.filter-row .filter-trigger {
    min-width: calc(var(--space-7) * 3);
    max-width: calc(var(--space-7) * 6);
}

.filter-pop {
    display: none;
    position: absolute;
    top: calc(100% + var(--space-1));
    left: 0;
    z-index: var(--z-dropdown);
    flex-direction: column;
    min-width: 100%;
    overflow: hidden;
    background: var(--surface);
    border: thin solid var(--line);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow);
    color: var(--ink);
    font: var(--text-body);
}
.filter-pop.open { display: flex; }
.filter-pop-head,
.filter-pop-foot,
.filter-scrim { display: none; }
.filter-pop-title { flex: 1 1 auto; min-width: 0; }
.filter-pop-meta { font: var(--text-small); color: var(--ink-2); }
/* A touch sheet's × (its head is hidden under a mouse). */
.filter-pop-close,
.date-field-close,
.select2-sheet-close {
    flex: none;
    width: var(--control-h);
    height: var(--control-h);
    padding: 0;
    border: 0;
    background: none;
    color: var(--ink-2);
    font-size: 1.5rem;
    line-height: 1;
}

/* A single choice (components/filter_choice.html): a list whose pick applies. */
.filter-choice { position: relative; }
.filter-choice-options {
    display: flex;
    flex-direction: column;
    min-width: calc(var(--space-7) * 4);
    padding: var(--space-1) 0;
}
.filter-choice-option {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: calc(var(--space-6) + var(--space-1) / 2);
    padding: 0 var(--space-3);
    border: 0;
    background: none;
    color: var(--ink);
    font: inherit;
    font-size: var(--control-font);
    text-align: left;
    white-space: nowrap;
}
.filter-choice-option:hover { background: var(--page); }
.filter-choice-option .icon-check { margin-left: auto; color: var(--accent); visibility: hidden; }
.filter-choice-option[aria-pressed="true"] { font-weight: 600; }
.filter-choice-option[aria-pressed="true"] .icon-check { visibility: visible; }

@media not all and (pointer: fine), (max-width: 1023.98px) {
    .filter-row { align-items: center; gap: var(--space-2); }
    .filter-row-label {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
    .filter-row .filter-trigger {
        gap: var(--space-1);
        width: auto;
        min-width: 0;
        max-width: none;
        height: auto;
        min-height: calc(var(--control-h) - var(--space-1));
        padding: 0 var(--space-3);
        border: thin dashed var(--line-strong);
        border-radius: var(--radius-pill);
        color: var(--ink-2);
        font: var(--text-small);
        font-size: 0.875rem;
        font-weight: 600;
    }
    .filter-row .filter-trigger.filter-active {
        border: thin solid transparent;
        background: var(--accent-wash);
        color: var(--accent-ink);
    }
    .filter-row .filter-trigger-label { display: inline; }
    .filter-row .filter-trigger.filter-active .filter-trigger-label::after { content: ":"; }
    .filter-row .filter-trigger:not(.filter-active) .filter-trigger-value { display: none; }
    .filter-row .filter-trigger-value { flex: 0 1 auto; }
    .filter-row :is(.filter-trigger-icon, .filter-trigger-chevron) { margin-left: 0; color: inherit; }
    .filter-row-reset {
        display: inline-flex;
        flex: none;
        align-items: center;
        gap: var(--space-1);
        padding: 0 var(--space-2);
        color: var(--accent-ink);
        font: var(--text-small);
        font-size: 0.875rem;
        font-weight: 600;
        text-decoration: none;
        white-space: nowrap;
    }
}

@media (pointer: coarse) {
    .filter-row { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
    .filter-row-item { flex: none; }
    .filter-scrim {
        position: fixed;
        inset: 0;
        z-index: var(--z-dropdown);
        background: color-mix(in srgb, var(--ink) 42%, transparent);
    }
    :has(> .filter-pop.open) > .filter-scrim { display: block; }
    .filter-pop {
        position: fixed;
        inset: auto 0 var(--keyboard-h, 0px);
        width: auto;
        min-width: 0;
        max-width: none;
        max-height: calc(var(--viewport-h, 100dvh) * 0.85);
        padding-bottom: env(safe-area-inset-bottom);
        border: 0;
        border-radius: var(--radius-card) var(--radius-card) 0 0;
    }
    .filter-pop-head {
        display: flex;
        flex: none;
        align-items: center;
        gap: var(--space-2);
        padding: 0 var(--space-1) 0 var(--space-4);
        border-bottom: thin solid var(--line-soft);
    }
    .filter-pop-title { font: var(--text-section); }
    .filter-pop-foot {
        display: flex;
        flex: none;
        gap: var(--space-2);
        padding: var(--space-3) var(--space-4);
        border-top: thin solid var(--line-soft);
    }
    .filter-pop-foot .btn { flex: 1; }
    .filter-choice-options { overflow-y: auto; padding: 0; }
    .filter-choice-option {
        min-height: calc(var(--control-h) + var(--space-1));
        padding: 0 var(--space-4);
        border-bottom: thin solid var(--line-soft);
    }
}

/* === Date range === */
/* components/date_range.html + filter_row.js */
.date-range { position: relative; }
.date-range-pop { width: max-content; }
.date-range-body {
    display: flex;
    gap: var(--space-4);
    padding: var(--space-3);
}
.date-range-presets {
    flex: none;
    display: flex;
    flex-direction: column;
    gap: calc(var(--space-1) / 2);
    width: calc(var(--space-7) * 3);
    padding-right: var(--space-3);
    border-right: thin solid var(--line-soft);
}
.date-range-preset {
    display: flex;
    align-items: center;
    min-height: calc(var(--space-6) + var(--space-1) / 2);
    padding: 0 var(--space-3);
    border: 0;
    border-radius: var(--radius-control);
    background: none;
    color: var(--ink);
    font: var(--text-body);
    font-size: var(--control-font);
    text-align: left;
    white-space: nowrap;
}
button.date-range-preset:hover { background: var(--page); }
.date-range-preset--custom { color: var(--ink-2); }
.date-range-preset[aria-pressed="true"],
.date-range-preset--custom.is-current {
    background: var(--accent-wash);
    color: var(--accent-ink);
    font-weight: 600;
}
.date-range-months {
    position: relative;
    display: flex;
    gap: var(--space-5);
}
.date-range-nav {
    position: absolute;
    inset: 0 0 auto;
    display: flex;
    justify-content: space-between;
    pointer-events: none;
}
.date-range-nav .date-field-step { pointer-events: auto; }
.date-range-month .date-field-month {
    margin-bottom: var(--space-2);
    line-height: calc(var(--space-6) - var(--space-1) / 2);
}
.date-field-day.is-in-range {
    border-radius: 0;
    background: var(--accent-wash);
    color: var(--accent-ink);
}
.date-range-fields { display: none; }
.date-range-pop .filter-pop-foot {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-top: thin solid var(--line-soft);
}
.date-range-summary {
    margin-right: auto;
    font: var(--text-small);
    color: var(--ink-2);
    font-variant-numeric: tabular-nums;
}
@media (pointer: coarse) {
    .date-range-pop { width: auto; }
    .date-range-body {
        flex-direction: column;
        gap: var(--space-3);
        padding: 0 var(--space-4) var(--space-3);
        overflow-y: auto;
    }
    .date-range-presets {
        width: auto;
        gap: 0;
        padding: 0;
        border: 0;
    }
    .date-range-preset {
        min-height: calc(var(--control-h) + var(--space-1));
        padding: 0;
        border-bottom: thin solid var(--line-soft);
        border-radius: 0;
    }
    .date-range-preset[aria-pressed="true"] { background: none; }
    .date-range-preset--custom,
    .date-range-months,
    .date-range-summary { display: none; }
    .date-range-fields {
        display: flex;
        flex-direction: column;
        gap: var(--space-2);
    }
    .date-range-fields-row {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: var(--space-3);
    }
}

/* === Multi-select === */
/* components/multi_select.html + multi_select.js (a .filter-pop) */
.excel-filter { position: relative; min-width: 0; }
.excel-filter:not(.filter-row-control) .excel-filter-btn { min-width: calc(var(--space-7) * 3.5); }
.excel-filter-dropdown {
    width: max-content;
    min-width: max(100%, calc(var(--space-7) * 6));
    max-width: min(calc(var(--space-7) * 8), calc(100vw - var(--space-6)));
}
.excel-filter-search { flex: none; padding: var(--space-2); }
.excel-filter-actions { flex: none; }
.excel-filter-select-all,
.excel-filter-search-actions {
    border-top: thin solid var(--line-soft);
    border-bottom: thin solid var(--line-soft);
}
.excel-filter-select-all label,
.excel-filter-option label,
.excel-filter-action {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    min-height: calc(var(--space-6) + var(--space-1) / 2);
    margin: 0;
    padding: 0 var(--space-3);
    font: var(--text-body);
    font-size: var(--control-font);
    cursor: pointer;
}
.excel-filter-select-all label { font-weight: 600; }
.excel-filter-action {
    border: 0;
    background: none;
    color: var(--accent-ink);
    font-weight: 600;
    text-align: left;
}
.excel-filter-action .action-icon { flex: none; width: var(--space-4); text-align: center; }
.excel-filter-option:hover,
.excel-filter-action:hover { background: var(--page); }
.excel-filter .form-check-input { flex: none; margin: 0; }
.excel-filter-options {
    flex: 1 1 auto;
    max-height: calc(var(--space-7) * 6);
    padding: var(--space-1) 0;
    overflow-y: auto;
}
.excel-filter-search-actions.hidden,
.excel-filter-select-all.hidden,
.excel-filter-option.hidden { display: none; }
@media (pointer: coarse) {
    .excel-filter-dropdown { width: auto; min-width: 0; max-width: none; }
    .excel-filter-search { padding: var(--space-3) var(--space-4) var(--space-2); }
    .excel-filter-options { min-height: 0; max-height: none; padding: 0; }
    .excel-filter-select-all label,
    .excel-filter-option label,
    .excel-filter-action {
        min-height: calc(var(--control-h) + var(--space-1));
        padding: 0 var(--space-4);
    }
    .excel-filter-option + .excel-filter-option { border-top: thin solid var(--line-soft); }
    .excel-filter .form-check-input {
        width: calc(var(--space-4) + var(--space-1));
        height: calc(var(--space-4) + var(--space-1));
    }
}

/* === Charts === */
/* Charts (03 "Charts and filter rows"). Plotly takes the same colours from apps/core/charts.py. */
.chart-card {
    display: flex;
    flex-direction: column;
    min-width: 0;
    padding: var(--space-4);
    background: var(--surface);
    border: thin solid var(--line);
    border-radius: var(--radius-card);
}
.chart-card-head {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: var(--space-5);
    margin-bottom: var(--space-3);
}
.chart-card-title { margin: 0; font: var(--text-body); font-weight: 700; }
.chart-card-tools {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-left: auto;
}
.chart-card-help {
    margin: calc(-1 * var(--space-2)) 0 var(--space-3);
    font: var(--text-small);
    color: var(--ink-2);
}
.chart-stat {
    font: var(--text-display);
    letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}
.chart-stat-sub { margin-top: calc(var(--space-1) / 2); font: var(--text-small); color: var(--ink-2); }
.chart-empty { padding: var(--space-3) 0; color: var(--ink-2); }
.chart-section-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-1) var(--space-3);
}
.chart-section-head h2 { margin: 0; font: var(--text-section); }
.chart-section-head span { font: var(--text-small); color: var(--ink-2); }
.chart-swatch {
    flex: none;
    width: calc(var(--space-2) + var(--space-1) / 2);
    height: calc(var(--space-2) + var(--space-1) / 2);
    border-radius: calc(var(--space-1) / 2);
}
.chart-swatch--round { border-radius: 50%; }
.chart-legend { display: flex; flex-direction: column; gap: var(--space-2); }
.chart-legend-row { display: flex; align-items: center; gap: var(--space-2); }
.chart-legend-row.is-zero { opacity: 0.45; }
.chart-legend-label { flex: 1 1 auto; min-width: 0; }
.chart-legend-value { color: var(--ink-2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.chart-donut {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4) var(--space-6);
}
.chart-donut-figure { flex: none; width: calc(var(--space-7) * 4); height: calc(var(--space-7) * 4); }
.chart-donut .chart-legend { flex: 1 1 calc(var(--space-7) * 4); max-width: calc(var(--space-7) * 6); }
.chart-stack { display: flex; gap: calc(var(--space-1) / 2); margin-bottom: var(--space-3); }
.chart-stack > span {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: calc(var(--space-1) / 2);
    height: var(--space-5);
    overflow: hidden;
    color: var(--surface);
    font: var(--text-small);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.chart-stack > span:first-child { border-radius: var(--space-1) 0 0 var(--space-1); }
.chart-stack > span:last-child { border-radius: 0 var(--space-1) var(--space-1) 0; }
.chart-stack > span:only-child { border-radius: var(--space-1); }
.chart-stack > .is-light { color: var(--ink); }
.chart-bars { display: flex; flex-direction: column; gap: var(--space-1); }
.chart-bars-row {
    display: grid;
    grid-template-columns: calc(var(--space-7) * 3) minmax(0, 1fr);
    align-items: center;
    gap: var(--space-3);
    min-height: calc(var(--space-6) - var(--space-1) / 2);
}
.chart-bars-label { justify-self: end; text-align: right; }
.chart-bars-track {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: calc(var(--space-5) + var(--space-1) / 2);
    border-left: thin solid var(--line-strong);
}
.chart-bars-bar {
    flex: none;
    height: calc(var(--space-3) + var(--space-1) / 4);
    background: var(--chart-1);
    border-radius: 0 var(--space-1) var(--space-1) 0;
}
.chart-bars-value { color: var(--ink-2); white-space: nowrap; font-variant-numeric: tabular-nums; }

/* === Tables === */
/* A table that isn't a list (dashboards, reports); a card per row (.data-cards) on a narrow screen. */
.data-table {
    width: 100%;
    border-collapse: collapse;
    font: var(--text-body);
}
.data-table th {
    padding: 0 var(--space-2) calc(var(--space-2) - var(--space-1) / 4);
    border-bottom: thin solid var(--line);
    background: var(--surface);
    color: var(--ink-2);
    font: var(--text-micro);
    letter-spacing: var(--micro-tracking);
    text-align: left;
    text-transform: uppercase;
    vertical-align: bottom;
    white-space: nowrap;
}
.data-table td {
    height: calc(var(--space-6) + var(--space-1) / 2);
    padding: var(--space-1) var(--space-2);
    border-bottom: thin solid var(--line-soft);
    vertical-align: middle;
}
.data-table :is(th, td):first-child { padding-left: 0; }
.data-table :is(th, td):last-child { padding-right: 0; }
:is(.data-table, .record-table) .is-num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.data-table .is-nowrap { white-space: nowrap; }
.data-table-scroll { position: relative; overflow: auto; max-height: calc(var(--space-7) * 12); }
.data-table-scroll .data-table th { position: sticky; top: 0; z-index: 1; }
.data-table th[aria-sort] { color: var(--ink); }
.data-table-sort {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
}
.data-table-sort .sort-indicator { color: var(--accent); visibility: hidden; }
.data-table th[aria-sort] .sort-indicator { visibility: visible; }
.data-pager {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font: var(--text-small);
    color: var(--ink-2);
    font-variant-numeric: tabular-nums;
}
.data-cards-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
    font: var(--text-small);
    color: var(--ink-2);
}
.data-card {
    display: flex;
    flex-direction: column;
    gap: calc(var(--space-1) / 2);
    padding: var(--space-3) 0;
    border-top: thin solid var(--line-soft);
}
.data-card-head { display: flex; align-items: baseline; gap: var(--space-2); }
.data-card-title { flex: 1 1 auto; min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
a.data-card-title { color: var(--accent-ink); text-decoration: none; }
.data-card-figure { flex: none; font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums; }
.data-card-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    min-height: calc(var(--space-5) + var(--space-1) / 2);
}
.data-card-row > :first-child { color: var(--ink-2); }
.data-cards-more {
    display: flex;
    justify-content: center;
    padding-top: var(--space-3);
    border-top: thin solid var(--line-soft);
}
.data-cards-empty { padding: var(--space-3) 0; color: var(--ink-2); }

/* === Labelled columns === */
/* Fields side by side, each under its label in the micro bold caps, so the figures line up down a
   list: a case's product and request lines on a phone (08-cases), a report card's fields. Cells
   sit on --labelled-cols; a [data-label] cell names itself. A table row that is a table on a wide
   screen takes the class and turns it off there (display: table-row, its labels content: none). */
.labelled-cols {
    display: grid;
    grid-template-columns: var(--labelled-cols, repeat(3, minmax(0, 1fr)));
    column-gap: calc(var(--space-2) + var(--space-1) / 2);
    align-items: end;
}
.labelled-cols [data-label]::before {
    content: attr(data-label);
    display: block;
    margin-bottom: calc(var(--space-1) / 2);
    font: var(--text-micro);
    letter-spacing: var(--micro-tracking);
    text-transform: uppercase;
    color: var(--ink-2);
    white-space: nowrap;
}
.labelled-cols--2 { --labelled-cols: repeat(2, minmax(0, 1fr)); }
.labelled-cols--4 { --labelled-cols: repeat(4, minmax(0, 1fr)); }
.labelled-cols--wrap [data-label]::before { white-space: normal; }
.labelled-cols > .labelled-cols-wide { grid-column: 1 / -1; }
/* A heading over the two fields under it, as a desktop table groups its headings. */
.labelled-cols-group {
    grid-column: span 2;
    padding-bottom: calc(var(--space-1) / 2);
    border-bottom: thin solid var(--line-soft);
    font: var(--text-micro);
    letter-spacing: var(--micro-tracking);
    text-transform: uppercase;
    color: var(--ink-2);
}
.data-card .labelled-cols { row-gap: var(--space-2); margin-top: var(--space-1); }

/* A table inside a record's panel (a case's items, a request's condition records, a contact's SAP
   figures): small type; on a narrow screen a card per row, each cell under its data-label, unless
   .record-table--grid keeps it a table, or .record-table--lines makes each row (a .labelled-cols)
   a line block: its .record-table-title, a muted .record-table-meta (led by data-lead), then its
   labelled cells as columns. */
.record-table {
    width: 100%;
    border-collapse: collapse;
    font: var(--text-small);
}
.record-table th {
    padding: 0 var(--space-3) var(--space-2) 0;
    border-bottom: thin solid var(--line);
    color: var(--ink-2);
    font: var(--text-micro);
    letter-spacing: var(--micro-tracking);
    text-align: left;
    text-transform: uppercase;
    white-space: nowrap;
}
.record-table td,
.record-table tfoot th {
    padding: var(--space-2) var(--space-3) var(--space-2) 0;
    border-bottom: thin solid var(--line-soft);
    vertical-align: top;
}
.record-table-scroll { overflow-x: auto; }
@media not all and (pointer: fine), (max-width: 1023.98px) {
    .record-table:not(.record-table--grid) thead { display: none; }
    .record-table:not(.record-table--grid),
    .record-table:not(.record-table--grid) :is(tbody, tfoot) { display: block; }
    .record-table:not(.record-table--grid, .record-table--lines) tr {
        display: block;
        padding: var(--space-2) 0;
        border-bottom: thin solid var(--line-soft);
    }
    .record-table:not(.record-table--grid, .record-table--lines) :is(td, tfoot th) {
        display: flex;
        justify-content: space-between;
        gap: var(--space-3);
        padding: var(--space-1) 0;
        border: 0;
        text-align: right;
    }
    .record-table:not(.record-table--grid, .record-table--lines) td::before {
        content: attr(data-label);
        color: var(--ink-2);
        text-align: left;
    }
    .record-table--lines tr {
        align-items: baseline;
        padding: var(--space-2) 0;
        border-top: thin solid var(--line-soft);
        font: var(--text-body);
    }
    .record-table--lines tr:first-child { border-top: 0; }
    .record-table--lines td {
        padding: 0;
        border: 0;
    }
    .record-table--lines :is(.record-table-title, .record-table-meta) { grid-column: 1 / -1; }
    .record-table--lines .record-table-title { font-weight: 600; }
    .record-table--lines .record-table-title .record-table-code { display: none; }
    .record-table--lines .record-table-meta {
        margin-bottom: var(--space-2);
        font: var(--text-small);
        color: var(--ink-2);
    }
    .record-table--lines .record-table-meta[data-lead]:not([data-lead=""])::before { content: attr(data-lead) " · "; }
}
@media (pointer: fine) and (min-width: 1024px) {
    .record-table--lines tr.labelled-cols { display: table-row; }
    .record-table--lines .labelled-cols [data-label]::before { content: none; }
}

/* === Wide and narrow === */
/* Last, so it outranks a component's own display. Wide is the table's presentation: a fine
   pointer from 1024px. */
@media (pointer: fine) and (min-width: 1024px) {
    .narrow-only { display: none; }
}
@media not all and (pointer: fine), (max-width: 1023.98px) {
    .wide-only { display: none; }
}
