/*
 * CASCADE LAYER (B-139, 2026-08-03) — this sheet is wrapped in
 * `@layer tav-components` so the precompiled UTILITIES can override it.
 *
 * Before this, the sheet was UNLAYERED while the utilities sat in
 * `@layer tav-precompiled`. Unlayered beats every layer regardless of
 * specificity, so `class="tav-input tav-pl-10"` silently lost its indent and
 * the search glyph rendered on top of the placeholder. Longhand padding would
 * NOT have fixed it — a layered utility loses to an unlayered declaration
 * whatever its shape.
 *
 * The consumer declares the order (`@layer tav-preflight, tav-components,
 * tav-utilities;`). The preflight had to be split out of the utilities sheet
 * first: it lives in the same file, and putting the whole file last would let
 * its element reset (`* { border-width: 0 }`) beat these components — the very
 * bug the old unlayered arrangement existed to prevent.
 *
 * Measured before flipping: of 616 elements carrying a component class, 286
 * utility overrides are byte-identical to what the component already sets
 * (160 `tav-w-full` against `width:100%`; 126 `text-sm`/`text-xs` against
 * type tokens that resolve to the same rem values). ~23 genuinely differ —
 * each one an author's intent that used to be discarded.
 */
@layer tav-components {
/*
 * tav-components.css — Tavuni UI component layer (ADR-0361).
 *
 * Hand-authored NATIVE CSS — no preprocessor, no build step. Every component
 * reads ONLY `--tav-*` design tokens (ADR-0359), which are injected at runtime
 * per brand scope by the `tavuni-common::theme` engine (ADR-0360). There is not
 * a single hard-coded colour here: brand colour lives entirely in the runtime
 * custom properties, so this one stylesheet themes for every reseller/tenant in
 * both light and dark mode without recompilation. (The `check-no-hardcoded-color`
 * CI gate enforces the "tokens only" invariant.)
 *
 * State changes (hover/press) are derived from the role + its on-colour via
 * `color-mix` at the `--tav-state-*` opacity, so they track the active theme
 * automatically — no per-component hover colour anywhere.
 *
 * LAYERED by design — see the `@layer tav-components` wrapper at the top of
 * this file. This paragraph used to argue the opposite ("unlayered by design"),
 * on the grounds that a consumer's preflight is emitted UNLAYERED and unlayered
 * beats any `@layer`, so wrapping these components would let `button {
 * background: transparent }` / `* { border-width: 0 }` override every tav-*
 * control. The premise was real; the conclusion was the wrong fix. Staying
 * unlayered to out-rank a reset also out-ranks the consumer's UTILITIES, which
 * is what silently discarded `class="tav-input tav-pl-10"`.
 *
 * The right fix belongs on the consumer: it declares
 * `@layer tav-preflight, tav-components, tav-utilities` and puts its reset in
 * the bottom layer, so this sheet needs no specificity games. Note that a
 * consumer CANNOT do that with `<link rel=stylesheet layer="...">` — that
 * attribute is unimplemented in every browser and fails silently. The layer
 * must be assigned by an `@layer` block INSIDE the reset stylesheet, exactly as
 * this file does. tavuni-workspace shipped that as tav-preflight-r2 /
 * tav-utilities-r2 after the unassigned layers cost `.tav-btn-primary` its
 * colour (3.25:1 black-on-blue) and its fill.
 *
 * Do not re-unlayer this sheet to work around a consumer's reset. Fix the
 * consumer's layer assignment instead.
 */

    :root {
        color-scheme: light;
        /* Haarlijnen als INKT op het blad, niet als `outline-variant`.
           Die rol staat op toon 80 van het merkgekleurde neutrale palet — in het
           groene thema een mintgrijs op L* 80, dat op een wit blad een
           getekende lijn wordt. Het goedgekeurde ontwerp tekent zijn scheiders
           op L* 93 en zijn randen op L* 89, allebei vrijwel zonder tint. Een mengsel van
           de tekstkleur met doorzichtig volgt het thema, is in donkere modus
           vanzelf een lichte lijn op een donker blad, en draagt geen merktint.
             --tav-hairline         scheiding binnen een blok (≈ L* 93)
             --tav-hairline-strong  de rand van een vlak, onder tabs (≈ L* 89) */
        --tav-hairline: color-mix(in oklab, var(--tav-on-surface) 8%, transparent);
        --tav-hairline-strong: color-mix(in oklab, var(--tav-on-surface) 13%, transparent);
        /* De twee tussentinten van het ontwerp, afgeleid van de tekstkleur op
           dezelfde manier als de haarlijnen. `on-surface-variant` is toon 30 van
           het merkgekleurde palet — donkerder dan de "ink2" van het ontwerp
           (L* 41) en met merktint. Deze twee zijn het neutrale grijs dat de fiche
           gebruikt voor labels en voetnoten.
             --tav-ink-muted  label, onderregel, secundaire tekst   (≈ L* 41)
             --tav-ink-faint  sectiekop, tijdstip, lege telling      (≈ L* 60)
           Gemeten tegen de ink2- en ink3-tinten van het ontwerp op wit. */
        --tav-ink-muted: color-mix(in oklab, var(--tav-on-surface) 66%, var(--tav-surface));
        --tav-ink-faint: color-mix(in oklab, var(--tav-on-surface) 45%, var(--tav-surface));
    }

    /* One dark selector for every shell (B-831). This used to read `:root.dark`,
       which was true for workspace and portal and false for console and site —
       they carried `data-theme="tavuni-dark"`. So this single declaration, the
       one that tells the browser to render native controls, scrollbars and form
       widgets dark, fired on two of four surfaces. `[data-theme="dark"]` is the
       theming engine's own default selector; all four now use it. */
    :root[data-theme="dark"] {
        color-scheme: dark;
    }

    .tav-app {
        background: var(--tav-surface-1);
        color: var(--tav-on-surface);
        font-family: var(--tav-font-sans, "Inter", system-ui, sans-serif);
        font-size: var(--tav-type-body-size);
        line-height: var(--tav-type-body-line);
    }

    /* Keyboard-only focus ring, theme-coloured. */
    :where(a, button, input, select, textarea, summary, [role="button"], [tabindex]):focus-visible {
        outline: 2px solid var(--tav-primary);
        outline-offset: 2px;
        border-radius: var(--tav-radius-xs);
    }

    @media (prefers-reduced-motion: reduce) {
        *,
        *::before,
        *::after {
            animation-duration: 0.01ms !important;
            animation-iteration-count: 1 !important;
            transition-duration: 0.01ms !important;
            scroll-behavior: auto !important;
        }
    }

    /* ── Buttons ─────────────────────────────────────────────────────── */
    /* Structural box rides on the base AND every colour variant / size
       modifier. Templates and the btn_* macros apply a single class bare
       (`class="tav-btn-primary"`), so padding/shape/flex must sit on the
       variant too — not only on `.tav-btn`. A bare variant otherwise sets
       colour but inherits the unlayered preflight's stripped box (border:0,
       no padding) → a filled label instead of a button. `[class*=…]` is 0-1-0
       (same as `.tav-btn`, still beats the `button` preflight 0-0-1) and
       covers current + future variants without enumerating them. */
    [class*="tav-btn"] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 0.5rem;
        /* B-828: height comes from the shared control rhythm, not from padding
           arithmetic. `tav-btn` used to compute to 30px while `tav-input` came
           out at 38px, so a button beside a field did not line up — which is
           why workspace grew twelve hand-rolled `py-2` buttons next to the real
           one, each with its own radius and border colour. Both now sit on
           `--tav-control-h`; a shell that raises that token (the consumer
           portal, for touch) moves every control together. */
        min-height: var(--tav-control-h);
        padding: 0.375rem 0.875rem;
        border: 1px solid transparent;
        border-radius: var(--tav-radius-md);
        font-size: var(--tav-type-body-size);
        font-weight: var(--tav-type-title-weight);
        line-height: 1;
        /* A label never breaks inside the word (tavuni-docs issue 2345): "Verplaa/tsen"
           in a narrow table cell read as a rendering fault. The cell or the row
           gives way, not the control. */
        white-space: nowrap;
        text-decoration: none;
        cursor: pointer;
        transition:
            background-color 0.15s ease,
            color 0.15s ease,
            border-color 0.15s ease,
            box-shadow 0.15s ease;
    }

    [class*="tav-btn"]:disabled,
    [class*="tav-btn"][aria-disabled="true"] {
        opacity: 0.5;
        cursor: not-allowed;
    }

    .tav-btn-primary {
        background: var(--tav-primary);
        color: var(--tav-on-primary);
    }
    .tav-btn-primary:hover {
        background: color-mix(
            in oklab,
            var(--tav-primary),
            var(--tav-on-primary) calc(var(--tav-state-hover) * 100%)
        );
    }
    /* In dark mode `--tav-primary` is a LIGHT tone: it also has to read as link
       text on the dark sheet. As a button fill that light tone looked like the
       outlined buttons beside it, and the brand colour was gone
       (tavuni-docs issue 2341). The container pair is the deep brand tone with its
       own gated on-colour, so the primary action stays the one filled, branded
       control in both modes. */
    :root[data-theme="dark"] .tav-btn-primary {
        background: var(--tav-primary-container);
        color: var(--tav-on-primary-container);
    }
    :root[data-theme="dark"] .tav-btn-primary:hover {
        background: color-mix(
            in oklab,
            var(--tav-primary-container),
            var(--tav-on-primary-container) calc(var(--tav-state-hover) * 100%)
        );
    }

    .tav-btn-secondary {
        background: var(--tav-surface-1);
        color: var(--tav-on-surface);
        border-color: var(--tav-outline);
    }
    .tav-btn-secondary:hover {
        background: color-mix(
            in oklab,
            var(--tav-surface-1),
            var(--tav-on-surface) calc(var(--tav-state-hover) * 100%)
        );
    }

    /* Destructive action — deliberately LIGHTER than `tav-btn-primary` (B-828).
       A filled error beside a filled primary gave "delete" exactly the weight of
       the page's main action; a container fill keeps it unmistakably red without
       competing for the eye. Contrast is not the trade: on-error-container over
       error-container measures 13.3:1 light and 7.2:1 dark, both ABOVE what the
       filled variant scored.

       When the destructive action IS the main action — the confirm button in a
       delete dialog — reach for `tav-btn-danger-strong`. That is the only place
       a full error fill belongs. */
    .tav-btn-danger {
        background: var(--tav-error-container);
        color: var(--tav-on-error-container);
        border-color: color-mix(in oklab, var(--tav-error) 35%, transparent);
    }
    .tav-btn-danger-strong {
        background: var(--tav-error);
        color: var(--tav-on-error);
    }
    .tav-btn-danger-strong:hover {
        background: color-mix(
            in oklab,
            var(--tav-error),
            var(--tav-on-error) calc(var(--tav-state-hover) * 100%)
        );
    }
    .tav-btn-danger:hover {
        background: color-mix(
            in oklab,
            var(--tav-error-container),
            var(--tav-on-error-container) calc(var(--tav-state-hover) * 100%)
        );
    }

    /* Same reasoning as `tav-btn-danger`: a warning action is a caution, not a
       call to action, so it carries the container fill. */
    .tav-btn-warning {
        background: var(--tav-warning-container);
        color: var(--tav-on-warning-container);
        border-color: color-mix(in oklab, var(--tav-warning) 35%, transparent);
    }
    /* Affirmative action that is NOT the primary one — "approve", "mark paid".
       The badge vocabulary has had `success` since day one and the button
       vocabulary did not, so templates reached for `btn-primary` and lost the
       distinction (B-828). */
    .tav-btn-success {
        background: var(--tav-success-container);
        color: var(--tav-on-success-container);
        border-color: color-mix(in oklab, var(--tav-success) 35%, transparent);
    }
    .tav-btn-success:hover {
        background: color-mix(
            in oklab,
            var(--tav-success-container),
            var(--tav-on-success-container) calc(var(--tav-state-hover) * 100%)
        );
    }
    .tav-btn-warning:hover {
        background: color-mix(
            in oklab,
            var(--tav-warning-container),
            var(--tav-on-warning-container) calc(var(--tav-state-hover) * 100%)
        );
    }

    .tav-btn-ghost {
        background: transparent;
        color: var(--tav-on-surface-variant);
    }
    .tav-btn-ghost:hover {
        background: color-mix(
            in oklab,
            transparent,
            var(--tav-on-surface) calc(var(--tav-state-hover) * 100%)
        );
    }

    /* ── Badges ──────────────────────────────────────────────────────── */
    /* Single-class contract (see buttons): a bare `tav-badge-success` etc.
       must carry the pill box, not only `.tav-badge`. */
    [class*="tav-badge"] {
        display: inline-flex;
        align-items: center;
        gap: 0.25rem;
        padding: 0.125rem 0.5rem;
        border-radius: var(--tav-radius-full);
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-label-weight);
        line-height: 1.25;
        /* A status is one word-shape; "Aangevraa/gd" is two (tavuni-docs issue 2345). */
        white-space: nowrap;
    }
    .tav-badge-success {
        background: var(--tav-success-container);
        color: var(--tav-on-success-container);
    }
    .tav-badge-warning {
        background: var(--tav-warning-container);
        color: var(--tav-on-warning-container);
    }
    .tav-badge-error {
        background: var(--tav-error-container);
        color: var(--tav-on-error-container);
    }
    .tav-badge-info {
        background: var(--tav-info-container);
        color: var(--tav-on-info-container);
    }
    .tav-badge-neutral {
        background: var(--tav-surface-variant);
        color: var(--tav-on-surface-variant);
    }

    /* ── Card ────────────────────────────────────────────────────────── */
    /* NOTE: no `overflow: hidden` (B-827). It was here so a table running to the
       card's edge would be clipped by the radius — decoration for the 578 cards
       whose content sits inside a padded wrapper, and a trap for the 31 that
       hold a dropdown, popover or `x-show` panel: those got silently cut off at
       the card's edge, with correct markup and nothing in the console.

       That single declaration is also what kept 817 hand-rolled cards in
       workspace from being folded into this component at all — every one of
       them would have had to be checked by hand for a positioned child, and
       "check 817 templates by eye" is not a migration anyone finishes.

       Content that genuinely reaches the edge takes `tav-card-flush` below.
       Measured: 59 of 651 cards, 57 of them in console. */
    /* The card is the white object, the page is the lower ground it lies on
       (tavuni-docs issue 2333). It used to be the reverse — a grey card sunk
       into a white sheet, with a border AND a shadow — and on a list or a
       dashboard every block was the same grey box: nothing stood out, and a
       screen of them read as dull and tiring. Every shell now grounds its
       scroll area on `surface-1`, as the record fiche already did; the card
       needs no shadow to stand off it, the hairline is enough. */
    .tav-card {
        background: var(--tav-surface);
        border: 1px solid var(--tav-outline-variant);
        border-radius: var(--tav-radius-md);
    }
    /* A card whose content runs to its edge — a bare `<table>`, an image, a
       scroll wrapper around either. Clips them to the radius so the corners stay
       round. Do NOT reach for this on a card that holds a menu or a tooltip. */
    .tav-card-flush {
        overflow: hidden;
    }
    .tav-card-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        padding: 0.875rem 1.25rem;
        border-bottom: 1px solid var(--tav-outline-variant);
    }
    .tav-card-title {
        margin: 0;
        font-size: var(--tav-type-title-size);
        font-weight: var(--tav-type-title-weight);
        line-height: var(--tav-type-title-line);
        color: var(--tav-on-surface);
    }
    .tav-card-body {
        padding: 1.25rem;
    }

    /* ── Form field ──────────────────────────────────────────────────── */
    .tav-field {
        display: grid;
        gap: 0.375rem;
    }
    .tav-label {
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-label-weight);
        color: var(--tav-on-surface-variant);
    }
    .tav-required {
        color: var(--tav-error);
    }
    .tav-input,
    .tav-textarea {
        width: 100%;
        /* Same rhythm as every button (B-828). A textarea grows past it — the
           token is a floor, not a fixed height. */
        min-height: var(--tav-control-h);
        padding: 0.5rem 0.75rem;
        /* Faintly brand-tinted edge so form fields carry a hint of the tenant
           brand at rest (Style-2 "more accent" feedback) — still reads neutral,
           the focus ring below is the full brand statement. */
        border: 1px solid color-mix(in oklab, var(--tav-primary) 28%, var(--tav-outline));
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
        line-height: var(--tav-type-body-line);
        transition:
            border-color 0.15s ease,
            box-shadow 0.15s ease;
    }
    .tav-input:focus,
    .tav-textarea:focus {
        outline: none;
        border-color: var(--tav-primary);
        box-shadow: 0 0 0 1px var(--tav-primary);
    }
    .tav-input[aria-invalid="true"],
    .tav-textarea[aria-invalid="true"] {
        border-color: var(--tav-error);
    }
    .tav-help {
        font-size: var(--tav-type-label-size);
        color: var(--tav-on-surface-variant);
    }
    .tav-error-text {
        font-size: var(--tav-type-label-size);
        color: var(--tav-error);
    }

    /* ── Flash / callout ─────────────────────────────────────────────── */
    .tav-flash {
        display: flex;
        align-items: flex-start;
        gap: 0.75rem;
        padding: 0.75rem 1rem;
        border: 1px solid transparent;
        border-radius: var(--tav-radius-md);
        font-size: var(--tav-type-body-size);
    }
    .tav-flash-success {
        background: var(--tav-success-container);
        color: var(--tav-on-success-container);
    }
    .tav-flash-warning {
        background: var(--tav-warning-container);
        color: var(--tav-on-warning-container);
    }
    .tav-flash-error {
        background: var(--tav-error-container);
        color: var(--tav-on-error-container);
    }
    .tav-flash-info {
        background: var(--tav-info-container);
        color: var(--tav-on-info-container);
    }

    /* ── Link ────────────────────────────────────────────────────────── */
    .tav-link {
        color: var(--tav-primary);
        text-decoration: none;
        font-weight: var(--tav-type-label-weight);
    }
    .tav-link:hover {
        text-decoration: underline;
    }

    /* ── Divider ─────────────────────────────────────────────────────── */
    .tav-divider {
        height: 0;
        margin: 1rem 0;
        border: 0;
        border-top: 1px solid var(--tav-outline-variant);
    }

    /* ── Keyboard key ────────────────────────────────────────────────── */
    .tav-kbd {
        display: inline-flex;
        align-items: center;
        padding: 0.0625rem 0.375rem;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-xs);
        background: var(--tav-surface-2);
        color: var(--tav-on-surface-variant);
        font-family: ui-monospace, monospace;
        font-size: 0.6875rem;
        line-height: 1.25;
    }

    /* ── Avatar (initials) ───────────────────────────────────────────── */
    .tav-avatar {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 2rem;
        height: 2rem;
        border-radius: var(--tav-radius-full);
        background: var(--tav-primary);
        color: var(--tav-on-primary);
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-title-weight);
        user-select: none;
    }

    /* ── Breadcrumb ──────────────────────────────────────────────────── */
    .tav-breadcrumb {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 0.5rem;
        font-size: var(--tav-type-label-size);
        color: var(--tav-on-surface-variant);
    }
    .tav-breadcrumb a {
        color: var(--tav-on-surface-variant);
        text-decoration: none;
    }
    .tav-breadcrumb a:hover {
        color: var(--tav-primary);
    }
    .tav-breadcrumb-sep {
        color: var(--tav-outline);
    }
    .tav-breadcrumb-current {
        color: var(--tav-on-surface);
        font-weight: var(--tav-type-label-weight);
    }

    /* ── Sidebar link (with active state — workspace audit #1) ───────── */
    .tav-sidebar-link {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        padding: 0.5rem 0.75rem;
        border-radius: var(--tav-radius-sm);
        color: var(--tav-on-surface-variant);
        font-size: var(--tav-type-body-size);
        font-weight: var(--tav-type-label-weight);
        text-decoration: none;
        transition:
            background-color 0.15s ease,
            color 0.15s ease;
    }
    .tav-sidebar-link:hover {
        background: color-mix(
            in oklab,
            transparent,
            var(--tav-on-surface) calc(var(--tav-state-hover) * 100%)
        );
        color: var(--tav-on-surface);
    }
    .tav-sidebar-link.active,
    .tav-sidebar-link[aria-current="page"] {
        background: var(--tav-primary-container);
        color: var(--tav-on-primary-container);
        font-weight: var(--tav-type-title-weight);
    }

    /* ── Tabs ────────────────────────────────────────────────────────── */
    .tav-tabs {
        display: flex;
        gap: 0.25rem;
        border-bottom: 1px solid var(--tav-hairline-strong);
    }
    .tav-tab {
        padding: 0.5rem 0.875rem;
        border-bottom: 2px solid transparent;
        color: var(--tav-on-surface-variant);
        font-size: var(--tav-type-body-size);
        font-weight: var(--tav-type-label-weight);
        text-decoration: none;
        cursor: pointer;
    }
    .tav-tab:hover {
        color: var(--tav-on-surface);
    }
    .tav-tab.active,
    .tav-tab[aria-current="page"] {
        border-bottom-color: var(--tav-primary);
        color: var(--tav-on-surface);
        font-weight: var(--tav-type-title-weight);
    }
    /* De telling naast een tablabel. Mono met tabular-nums, zodat "3" en "12"
       in een rij tabs dezelfde breedte per cijfer krijgen en de balk niet
       verspringt zodra er een rij bijkomt. */
    .tav-tab .tav-badge {
        font-family: var(--tav-font-mono);
        font-variant-numeric: tabular-nums;
        font-weight: 500;
        letter-spacing: 0;
    }

    /* ── Tab count ───────────────────────────────────────────────────
       De telling naast een tablabel, zoals het ontwerp hem tekent: een klein
       mono-pilletje in de haarlijntint, dat in de accenttint kleurt zodra de
       tab open staat. Je weet vóór het klikken of er iets in zit.

         .is-zero     een lege tab: een grijze 0 zonder vlak — de tab staat er,
                      en zegt meteen dat er niets in zit
         .is-warning  de ENE tab waar iets schuurt ("Vloot 104" in oker omdat
                      een keuring vervalt). Eén gekleurde telling tegelijk,
                      anders is het weer chip-inflatie. */
    .tav-tab-count {
        font-family: var(--tav-font-mono);
        font-size: 0.6875rem;
        font-variant-numeric: tabular-nums;
        font-weight: 500;
        line-height: 1.45;
        letter-spacing: 0;
        padding: 0.0625rem 0.375rem;
        border-radius: var(--tav-radius-full);
        background: var(--tav-hairline);
        color: var(--tav-ink-muted);
    }
    .tav-tab.active .tav-tab-count,
    .tav-tab[aria-selected="true"] .tav-tab-count {
        background: color-mix(in oklab, var(--tav-primary) 12%, var(--tav-surface));
        color: var(--tav-primary);
    }
    .tav-tab-count.is-zero,
    .tav-tab.active .tav-tab-count.is-zero,
    .tav-tab[aria-selected="true"] .tav-tab-count.is-zero {
        background: none;
        color: var(--tav-ink-faint);
    }
    .tav-tab-count.is-warning {
        background: color-mix(in oklab, var(--tav-warning) 14%, var(--tav-surface));
        color: var(--tav-warning);
    }

    /* ── Page head (tavuni-docs#3680) ─────────────────────────────────
       The one head every page carries (`m::page_head`): "‹ back" above the
       title, the title and its subtitle on the left, the page's actions on
       the right of the title. It lives in the app shell's `.app-page-frame`,
       which is exactly as wide as the content, so the right-most action
       stands above the right edge of what it acts on. */
    .tav-page-head {
        display: flex;
        flex-direction: column;
        gap: 0.25rem;
        width: 100%;
    }
    .tav-page-head-back {
        display: inline-flex;
        align-items: center;
        gap: 0.25rem;
        align-self: flex-start;
        font-size: 0.875rem;
        color: var(--tav-on-surface-variant);
        text-decoration: none;
        transition: color 120ms ease;
    }
    .tav-page-head-back:hover {
        color: var(--tav-primary);
    }
    .tav-page-head-row {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: 0.5rem 1rem;
        flex-wrap: wrap;
    }
    /* tavuni-docs#3898 — the title keeps a floor. As `min-width: 0;
       flex: 1 1 0` it shrank to nothing beside four action buttons at 800 px
       ("Vandaag" became one glyph, its date three lines); with a basis the
       row wraps instead and the actions move under the title. */
    .tav-page-head-title {
        flex: 1 1 16rem;
        min-width: 0;
    }
    .tav-page-head-actions {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        gap: 0.5rem;
        flex-wrap: wrap;
        margin-left: auto;
    }
    .tav-page-head-actions:empty {
        display: none;
    }
    /* ── Form actions (tavuni-docs#3680) ──────────────────────────────
       The foot of every page form (`c::form_actions`): cancel and submit on
       the right, sticking to the bottom of the scroll area so the submit of
       a long form is always in reach. */
    .tav-form-actions {
        position: sticky;
        bottom: 0;
        z-index: 10;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        flex-wrap: wrap;
        gap: 0.5rem;
        margin-top: 1.5rem;
        padding: 0.75rem 0;
        border-top: 1px solid var(--tav-hairline);
        background: var(--tav-surface);
    }
    /* ── Record hero ─────────────────────────────────────────────────
       De kop van een dossier is één wit vlak: identiteit, kerncijfers en
       tabs, met één lijn eronder. Het vlak blijft staan bij elke tab — "de kop
       is de constante" — en alles wat eronder ligt, ligt op de ondergrond.

       De tabs zitten ÓP die lijn: geen eigen onderrand (de lijn van het vlak
       is de snede) en geen ruimte eronder. */
    .tav-record-hero .tav-tabs {
        margin-top: 0.875rem;
        gap: 0.125rem;
        border-bottom: 0;
        overflow-x: auto;
    }
    .tav-record-hero .tav-tab {
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.5625rem 0.875rem 0.6875rem;
        font-size: 0.875rem;
        font-weight: 500;
        color: var(--tav-ink-muted);
        background: none;
        border-top: 0;
        border-left: 0;
        border-right: 0;
        white-space: nowrap;
    }
    .tav-record-hero .tav-tab:hover {
        color: var(--tav-on-surface);
    }
    .tav-record-hero .tav-tab.active,
    .tav-record-hero .tav-tab[aria-selected="true"] {
        color: var(--tav-on-surface);
        border-bottom-color: var(--tav-primary);
        font-weight: 600;
    }

    /* ── Toggle / switch ─────────────────────────────────────────────── */
    /* The off state has to be a visible control, not an absence of one. Measured
       in the light theme: the track was `--tav-surface-variant` at 1.23:1 against
       the page and the thumb was `--tav-surface` — the page colour exactly — so
       an unchecked switch was very nearly not there. WCAG 1.4.11 asks 3:1 for the
       visual information that identifies a control; the border carries that, and
       `--tav-outline` measures 4.08:1 light and 5.40:1 dark. `box-sizing:
       border-box` from the reset keeps 40x24 the outside size either way. */
    .tav-toggle {
        position: relative;
        display: inline-flex;
        align-items: center;
        width: 2.5rem;
        height: 1.5rem;
        flex-shrink: 0;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-full);
        background: var(--tav-surface-variant);
        cursor: pointer;
        transition: background-color 0.15s ease, border-color 0.15s ease;
    }
    .tav-toggle::after {
        content: "";
        position: absolute;
        left: 0.1875rem;
        width: 1.125rem;
        height: 1.125rem;
        border-radius: var(--tav-radius-full);
        background: var(--tav-surface);
        transition: transform 0.15s ease;
    }
    .tav-toggle[aria-checked="true"] {
        border-color: var(--tav-primary);
        background: var(--tav-primary);
    }
    .tav-toggle[aria-checked="true"]::after {
        transform: translateX(1rem);
        background: var(--tav-on-primary);
    }

    /* ── Record identity: crest + display title ──────────────────────
       De kop van een fiche. Het monogram is een VLAK, geen rondje met een
       letter erin: op een lijst van tien dossiers is een vierkant met een
       accentvlak het enige dat je van een afstand uit elkaar houdt.

       De titel staat in de display-face (Fraunces, optical sizing). Dat is
       geen versiering maar het onderscheid dat een fiche nodig heeft: een
       naam en een getal staan hier centimeters uit elkaar en mogen niet als
       dezelfde soort ding lezen. */
    .tav-crest {
        width: 3.875rem;
        height: 3.875rem;
        flex: none;
        border-radius: var(--tav-radius-md);
        background: var(--tav-primary);
        color: var(--tav-on-primary);
        display: grid;
        place-items: center;
        font-family: var(--tav-font-display);
        font-optical-sizing: auto;
        font-weight: 600;
        font-size: 1.5rem;
        letter-spacing: -0.02em;
    }
    .tav-crest-sm {
        width: 2.25rem;
        height: 2.25rem;
        font-size: 0.9375rem;
        border-radius: var(--tav-radius-sm);
    }
    /* Het wapen op een FICHEKOP. Groot genoeg om het dossier te zijn en niet
       een icoontje ernaast — op de schets is dit het eerste wat je ziet. */
    .tav-crest-lg {
        width: 5.25rem;
        height: 5.25rem;
        font-size: 2rem;
    }
    @media (max-width: 48rem) {
        .tav-crest-lg {
            width: 3.25rem;
            height: 3.25rem;
            font-size: 1.25rem;
        }
    }
    .tav-record-title {
        font-family: var(--tav-font-display);
        font-optical-sizing: auto;
        font-weight: 600;
        font-size: var(--tav-type-size-3xl);
        line-height: 1.06;
        letter-spacing: -0.018em;
        color: var(--tav-on-surface);
        text-wrap: balance;
    }
    .tav-record-kind {
        margin-top: 0.3125rem;
        font-size: 0.84375rem;
        line-height: 1.45;
        color: var(--tav-ink-muted);
    }
    /* De scheiding tussen de delen van de onderregel (handelsnaam · sector ·
       dossierbeheerder) in de gedempte toon, zodat de punt ordent zonder mee
       te lezen. */
    .tav-record-kind .tav-record-sep {
        color: var(--tav-ink-faint);
        margin: 0 0.4375rem;
    }

    /* De regel BOVEN de naam: soort record + sinds wanneer. Small caps met
       ruime letterafstand, zodat hij als kader leest en niet als titel.

       Dit was de opmaak van `tav-record-kind`. Die twee stonden omgekeerd:
       de subtitel (handelsnaam, sectorcode) werd in kapitalen gezet en de
       kaderregel als lopende tekst — waardoor het scherm zijn duiding schreeuwde
       en zijn identificatie fluisterde. */
    .tav-record-eyebrow {
        font-size: 0.6875rem;
        letter-spacing: 0.13em;
        text-transform: uppercase;
        color: var(--tav-ink-faint);
        font-weight: 600;
        margin-bottom: 0.25rem;
    }

    /* ── Record head ─────────────────────────────────────────────────
       De kop als GRID, niet als flexrij: het wapen staat links over de volle
       hoogte van de drie tekstregels, de acties rechts op de eerste regel.
       Met flex ging het wapen verticaal midden staan en zakte de eyebrow
       scheef weg zodra de subtitel afwezig was. */
    .tav-record-head {
        display: grid;
        grid-template-columns: auto auto minmax(0, 1fr) auto;
        align-items: start;
        gap: 0 1rem;
        width: 100%;
    }
    .tav-record-back {
        color: var(--tav-on-surface-variant);
        margin-top: 1.25rem;
        transition: color 120ms ease;
    }
    .tav-record-back:hover {
        color: var(--tav-primary);
    }
    .tav-record-actions {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        flex: none;
        margin-top: 0.125rem;
    }
    /* Een kop zonder wapen: één kolom minder. Niet elk record heeft een naam
       waar een monogram iets van maakt — een werkbonnummer of een datum levert
       twee betekenisloze tekens op, en dan is het vlak alleen ruis. */
    .tav-record-head--nocrest {
        grid-template-columns: auto minmax(0, 1fr) auto;
    }
    .tav-record-head--nocrest .tav-record-back {
        margin-top: 0.5rem;
    }
    /* ── Record hero ─────────────────────────────────────────────────
       De kop van een dossier, zoals het contactdossier-ontwerp hem tekent: één
       wit vlak met het wapen, de naam, de kerncijfers en de tabs, en één lijn
       eronder. Hij staat in de vaste paginakop van de app-shell, dus hij blijft
       staan terwijl het dossier eronder scrolt en de tabs wisselen.

       Geen terugpijl: het wapen staat op de linkerrand, zodat wapen, kerncijfers
       en de eerste tab op één lijn beginnen. Terug is de zijbalk en de browser. */
    .tav-record-hero .tav-record-head {
        grid-template-columns: auto minmax(0, 1fr) auto;
        gap: 0 1.25rem;
    }
    .tav-record-hero .tav-record-eyebrow {
        margin: 0.0625rem 0 0;
    }
    .tav-record-hero .tav-record-title {
        margin-top: 0.25rem;
        font-size: 1.875rem;
    }
    .tav-record-hero .tav-record-actions {
        margin-top: 0;
    }
    .tav-record-hero .tav-record-kind {
        margin: 0.3125rem 0 0;
    }
    /* On a phone the actions take their own row under the name, and the four
       figures wrap two by two instead of pushing the page sideways. */
    @media (max-width: 48rem) {
        .tav-record-hero .tav-record-head {
            grid-template-columns: auto minmax(0, 1fr);
            gap: 0 0.875rem;
        }
        .tav-record-hero .tav-crest {
            width: 2.75rem;
            height: 2.75rem;
            font-size: 1.0625rem;
        }
        .tav-record-hero .tav-record-title {
            font-size: 1.5rem;
        }
        .tav-record-hero .tav-stat-strip > * {
            flex: 1 1 50%;
            padding: 0.75rem 1rem 0.75rem 0;
            border-right: 0;
        }
    }

    /* Het menu achter ⋯: de uitgangen naar andere schermen die aan deze partij
       hangen, en onderaan de ene onomkeerbare actie. Een lijst links, geen
       knoppenrij — het zijn plaatsen om naartoe te gaan. */
    .tav-record-menu {
        position: absolute;
        right: 0;
        top: 100%;
        z-index: 30;
        margin-top: 0.375rem;
        min-width: 14rem;
        padding: 0.375rem;
        border: 1px solid var(--tav-hairline-strong);
        border-radius: 0.4375rem;
        background: var(--tav-surface);
        box-shadow: var(--tav-elevation-2);
    }
    .tav-record-menu > a,
    .tav-record-menu button {
        display: block;
        width: 100%;
        padding: 0.4375rem 0.625rem;
        border: 0;
        border-radius: 0.3125rem;
        background: none;
        font: inherit;
        font-size: 0.84375rem;
        text-align: left;
        color: var(--tav-on-surface);
        text-decoration: none;
        cursor: pointer;
    }
    .tav-record-menu > a:hover,
    .tav-record-menu button:hover {
        background: var(--tav-surface-1);
    }
    .tav-record-menu hr {
        margin: 0.375rem 0;
        border: 0;
        border-top: 1px solid var(--tav-hairline);
    }
    .tav-record-menu .is-danger {
        color: var(--tav-error);
    }

    @media (max-width: 48rem) {
        .tav-record-head {
            grid-template-columns: auto minmax(0, 1fr);
        }
        .tav-record-actions {
            grid-column: 1 / -1;
            margin-top: 0.875rem;
        }
        .tav-record-back {
            display: none;
        }
    }

    /* ── Verdict line ────────────────────────────────────────────────
       Het antwoord op de vraag van dit scherm, in één regel, vóór alles
       andere. Groter dan de lopende tekst omdat het GELEZEN moet worden en
       niet overgeslagen. `tav-verdict-blocking` kleurt hem pas wanneer de
       regel een probleem beschrijft — kleur je hem altijd, dan draagt de
       kleur geen informatie meer. */
    .tav-verdict {
        font-size: var(--tav-type-size-lg);
        line-height: var(--tav-type-line-lg);
        color: var(--tav-on-surface);
        font-weight: 500;
        letter-spacing: -0.008em;
        text-wrap: balance;
    }
    .tav-verdict-blocking {
        color: var(--tav-warning);
        font-weight: 600;
    }

    /* ── Stat strip ──────────────────────────────────────────────────
       Kerncijfers als STROOK, niet als kaarten. Vier omkaderde hokjes naast
       elkaar lezen als vier losse objecten; vier cellen achter één haarlijn
       lezen als één meting van hetzelfde ding. De waarde staat in de
       display-face met tabular-nums, zodat een kolom cijfers uitlijnt. */
    .tav-stat-strip {
        display: flex;
        flex-wrap: wrap;
        align-items: stretch;
        margin-top: 1.25rem;
        border-top: 1px solid var(--tav-hairline);
    }
    /* Elke cel is een KNOP naar de tab die het detail draagt: een kop die
       alleen getallen toont veroudert tot behang, een kop die je ergens brengt
       gebruik je. Een cel zonder bestemming blijft een <div> en krijgt dan ook
       geen onderstreping bij hover. */
    .tav-stat-strip > * {
        padding: 0.875rem 1.625rem 0.9375rem;
        border: 0;
        border-right: 1px solid var(--tav-hairline);
        background: none;
        font: inherit;
        color: inherit;
        text-align: left;
        align-self: stretch;
    }
    .tav-stat-strip > button {
        cursor: pointer;
    }
    .tav-stat-strip > :first-child {
        padding-left: 0;
    }
    .tav-stat-strip > :last-child {
        border-right: 0;
    }
    .tav-stat-strip > button:hover .tav-stat-value {
        text-decoration: underline;
        text-decoration-thickness: 1.5px;
        text-underline-offset: 3px;
    }
    .tav-stat-strip .tav-stat-label {
        display: block;
        font-size: 0.6875rem;
        letter-spacing: 0.1em;
        text-transform: uppercase;
        font-weight: 600;
        color: var(--tav-ink-faint);
    }
    .tav-stat-strip .tav-stat-value {
        display: block;
        margin-top: 0.25rem;
        font-family: var(--tav-font-display);
        font-optical-sizing: auto;
        font-weight: 600;
        font-size: 1.375rem;
        line-height: 1.1;
        letter-spacing: -0.016em;
        font-variant-numeric: tabular-nums;
        color: var(--tav-on-surface);
    }
    .tav-stat-strip .tav-stat-caption {
        display: block;
        margin-top: 0.1875rem;
        font-size: 0.75rem;
        color: var(--tav-ink-muted);
    }

    /* ── Work row ────────────────────────────────────────────────────
       Eén regel werk: wat het is, hoeveel het kost, en de weg ernaartoe.
       De gekleurde linkerrand draagt de urgentie — dat is de enige plek waar
       kleur op deze rij iets betekent, zodat een lijst van tien in één blik
       te sorteren is op wat brandt. */
    .tav-work-row {
        display: flex;
        align-items: center;
        gap: 1rem;
        padding: 0.75rem 0.9375rem;
        background: var(--tav-surface-1);
        border: 1px solid var(--tav-outline-variant);
        border-left-width: 3px;
        border-radius: var(--tav-radius-sm);
    }
    .tav-work-row-due {
        border-left-color: var(--tav-error);
    }
    .tav-work-row-soon {
        border-left-color: var(--tav-warning);
    }
    .tav-work-row-info {
        border-left-color: var(--tav-outline-variant);
    }
    .tav-work-row .tav-work-amount {
        font-family: var(--tav-font-mono);
        font-variant-numeric: tabular-nums;
        font-size: var(--tav-type-size-base);
        font-weight: 600;
        letter-spacing: -0.015em;
        flex: none;
    }

    /* ── Registration plate ──────────────────────────────────────────
       Een kenteken is geen gewone tekst: het is het ding waarop een monteur,
       een verzekeraar en een klant elkaar vinden. Het krijgt dus de vorm die
       iedereen herkent — omkaderd, mono, uitgelijnd — zodat je het in een
       tabel van dertig rijen terugvindt zonder te lezen. */
    .tav-plate {
        display: inline-block;
        font-family: var(--tav-font-mono);
        font-size: var(--tav-type-size-xs);
        font-weight: 600;
        letter-spacing: 0.03em;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-xs);
        padding: 0.0625rem 0.375rem;
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        white-space: nowrap;
    }

    /* ── Timeline ────────────────────────────────────────────────────
       Wat er gebeurd is, op één verticale lijn. De bolletjes zitten ÓP de
       lijn en niet ernaast, want de lijn is de tijd; een bolletje ernaast is
       een opsommingsteken en draagt geen volgorde. */
    .tav-timeline {
        list-style: none;
        margin: 0;
        padding: 0 0 0 1.0625rem;
        border-left: 1px solid var(--tav-hairline-strong);
        display: grid;
        gap: 0.9375rem;
    }
    .tav-timeline > li,
    .tav-timeline-item {
        position: relative;
        font-size: 0.84375rem;
        line-height: 1.42;
        color: var(--tav-on-surface);
    }
    /* Het bolletje in de tint van de ONDERGROND, niet van het blad: het zit
       op de lijn en snijdt die door, zoals het ontwerp hem tekent. */
    .tav-timeline > li::before {
        content: "";
        position: absolute;
        left: -1.3125rem;
        top: 0.3125rem;
        width: 0.4375rem;
        height: 0.4375rem;
        border-radius: var(--tav-radius-full);
        background: var(--tav-timeline-ring, var(--tav-surface-1));
        border: 1.5px solid var(--tav-ink-faint);
    }
    .tav-timeline > li.tav-timeline-current::before {
        background: var(--tav-primary);
        border-color: var(--tav-primary);
    }
    .tav-timeline b {
        font-weight: 600;
    }
    .tav-timeline time {
        display: block;
        margin-top: 0.125rem;
        font-family: var(--tav-font-mono);
        font-size: 0.6875rem;
        letter-spacing: 0.03em;
        color: var(--tav-ink-faint);
    }
    .tav-timeline p {
        margin: 0.1875rem 0 0;
        font-size: 0.78125rem;
        color: var(--tav-ink-muted);
    }

    /* ── Stat card ───────────────────────────────────────────────────── */
    .tav-stat-card {
        padding: 1.25rem;
        background: var(--tav-surface-1);
        border: 1px solid var(--tav-outline-variant);
        border-radius: var(--tav-radius-md);
    }
    .tav-stat-label {
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-label-weight);
        color: var(--tav-on-surface-variant);
    }
    .tav-stat-value {
        margin-top: 0.25rem;
        font-size: var(--tav-type-headline-size);
        font-weight: var(--tav-type-headline-weight);
        line-height: var(--tav-type-headline-line);
        color: var(--tav-on-surface);
        font-variant-numeric: tabular-nums;
    }
    .tav-stat-caption {
        margin-top: 0.25rem;
        font-size: var(--tav-type-label-size);
        color: var(--tav-on-surface-variant);
    }

    /* ── Record ground ───────────────────────────────────────────────
       Alles ONDER de kop ligt op de ondergrond: het dossier zelf. De kop (wit,
       met de lijn eronder) is het deksel, de inhoud ligt erin.

       De ondergrond kleurt het SCROLLVLAK, niet dit element — de app-shell
       zet `surface-1` op `.app-scroll`, sinds tavuni-docs issue 2333 op elke
       pagina en niet alleen op een fiche. Een
       achtergrond op dit element zelf liet links, rechts en onderaan een witte
       rand staan, en de negatieve marges die dat moesten verbergen braken op
       elke andere schermbreedte. */
    .tav-record-ground > * + * {
        margin-top: 1.5rem;
    }
    /* Tab panels are siblings of which only one shows; a sibling margin would
       push every panel but the first down. */
    .tav-record-ground > [role="tabpanel"] {
        margin-top: 0;
    }
    /* Inside a panel, stacked sections breathe the same way. */
    .tav-record-ground [role="tabpanel"] > section + section,
    .tav-record-column > * + * {
        margin-top: 1.75rem;
    }
    /* A panel that is ONE reading column (a timeline, a list of notes): a line
       of text wider than this is not read, it is scanned. */
    .tav-record-column {
        max-width: 47.5rem;
    }
    .tav-record-aside > * + * {
        margin-top: 1.5rem;
    }

    /* Een sectiekop OP de ondergrond, zoals het ontwerp hem tekent: klein,
       kapitaal, ruim gespatieerd, gedempt — en ZONDER lijn. De scheiding
       tussen velden draagt het ritme; een lijn onder de kop erbovenop maakte
       van elke sectie een tabel met een kader. */
    .tav-record-ground .tav-section-head,
    .tav-record-ground .tav-section-head-row > h2 {
        margin: 0 0 0.5rem;
        padding: 0;
        border: 0;
        font-size: 0.75rem;
        line-height: 1.4;
        letter-spacing: 0.12em;
        text-transform: uppercase;
        font-weight: 600;
        color: var(--tav-ink-faint);
    }
    .tav-record-ground .tav-section-head-row {
        display: flex;
        align-items: baseline;
        gap: 0.75rem;
        margin: 0 0 0.5rem;
        padding: 0;
        border: 0;
    }
    .tav-record-ground .tav-section-head-row > h2 {
        margin: 0;
    }
    .tav-record-ground .tav-section-head-row > a,
    .tav-record-ground .tav-section-head-row > button {
        margin-left: auto;
        padding: 0;
        border: 0;
        background: none;
        font: inherit;
        font-size: 0.8125rem;
        font-weight: 500;
        color: var(--tav-primary);
        text-decoration: none;
        cursor: pointer;
    }
    .tav-record-ground .tav-section-head-row > a:hover,
    .tav-record-ground .tav-section-head-row > button:hover {
        text-decoration: underline;
    }
    .tav-section-count {
        color: var(--tav-ink-faint);
        font-family: var(--tav-font-mono);
        letter-spacing: 0;
    }

    /* ── Record split ────────────────────────────────────────────────
       De twee kanten van een dossier: links wat vastligt, rechts wat er
       gebeurd is. De rechterkolom heeft een VASTE breedte (316px in het
       ontwerp), zodat een tijdlijn met regels van wisselende lengte de
       linkerkolom niet meesleurt bij elke nieuwe gebeurtenis. */
    .tav-record-split {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 19.75rem;
        gap: 0 2.25rem;
        align-items: start;
    }
    /* De blokken van de linkerkolom staan ONDER elkaar, elk met zijn velden in
       twee kolommen. Naast elkaar (drie secties op een breed scherm) lijnden de
       velden van de ene sectie niet uit met die van de volgende, en werd het
       scherm op elke breedte een ander scherm. */
    .tav-record-sections {
        display: block;
        min-width: 0;
    }
    .tav-record-sections > * + * {
        margin-top: 1.5rem;
    }
    .tav-record-sections dl,
    .tav-record-sections .tav-field-grid {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0 2rem;
        margin: 0;
    }
    .tav-record-aside {
        min-width: 0;
    }
    @media (max-width: 66rem) {
        .tav-record-split {
            grid-template-columns: minmax(0, 1fr);
            gap: 2rem 0;
        }
        .tav-record-sections dl,
        .tav-record-sections .tav-field-grid {
            grid-template-columns: minmax(0, 1fr);
        }
    }

    /* Het blok "Vraagt aandacht" staat bovenaan het overzicht, over de volle
       breedte; het raster met de velden volgt eronder. */
    .tav-record-split {
        margin-top: 1.625rem;
    }
    .tav-record-ground > .tav-record-split:first-child,
    [role="tabpanel"] > .tav-record-split:first-child {
        margin-top: 0;
    }

    /* ── Attention rows ──────────────────────────────────────────────
       "Vraagt aandacht": de reden dat je dit scherm opent. Elke rij is werk —
       wat het is, waarom, eventueel het bedrag, en de knop die het oplost. De
       gekleurde linkerrand draagt de urgentie en is de ENIGE kleur op de rij,
       zodat een lijst van tien in één blik te sorteren is op wat brandt.

       Een rij is een los object op de ondergrond, dus hier hoort wél een
       vlak, een rand en een schaduw bij. */
    .tav-attention {
        display: grid;
        gap: 0.5rem;
    }
    .tav-attention-item {
        display: flex;
        align-items: center;
        gap: 1rem;
        padding: 0.75rem 0.9375rem;
        background: var(--tav-surface);
        border: 1px solid var(--tav-hairline-strong);
        border-left-width: 3px;
        border-radius: 0.375rem;
        box-shadow: var(--tav-elevation-1);
    }
    .tav-attention-item.is-error {
        border-left-color: var(--tav-error);
    }
    .tav-attention-item.is-warning {
        border-left-color: var(--tav-warning);
    }
    /* Info houdt de gewone lijnkleur: het minst dringende punt heeft geen
       eigen categoriekleur nodig, alleen zijn plaats in de lijst. */
    .tav-attention-item.is-info {
        border-left-color: var(--tav-hairline-strong);
    }
    .tav-attention-body {
        min-width: 0;
        flex: 1;
    }
    .tav-attention-title {
        display: block;
        margin: 0;
        font-size: 0.875rem;
        line-height: 1.35;
        font-weight: 600;
        color: var(--tav-on-surface);
    }
    .tav-attention-detail {
        margin: 0;
        font-size: 0.8125rem;
        line-height: 1.45;
        color: var(--tav-ink-muted);
    }
    .tav-attention-amount {
        font-family: var(--tav-font-mono);
        font-variant-numeric: tabular-nums;
        font-size: 0.9375rem;
        font-weight: 600;
        letter-spacing: -0.015em;
        color: var(--tav-on-surface);
        flex: none;
        white-space: nowrap;
    }
    .tav-attention-item.is-error .tav-attention-amount {
        color: var(--tav-error);
    }
    /* De actieknop van een rij: kleiner dan een paginaknop, op het blad. */
    .tav-attention-action {
        flex: none;
        display: inline-flex;
        align-items: center;
        height: 1.875rem;
        padding: 0 0.75rem;
        border-radius: 0.3125rem;
        border: 1px solid var(--tav-hairline-strong);
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        font: inherit;
        font-size: 0.8125rem;
        text-decoration: none;
        white-space: nowrap;
        cursor: pointer;
    }
    .tav-attention-action:hover {
        border-color: var(--tav-ink-faint);
    }
    /* Geen openstaande punten: het blok krimpt tot één groene regel. Een fiche
       zonder gaten zegt dat ook — dat iemand gekeken heeft en het in orde was,
       is informatie. */
    .tav-attention-clear {
        display: flex;
        align-items: center;
        gap: 0.625rem;
        padding: 0.8125rem 0.9375rem;
        border-radius: 0.375rem;
        background: color-mix(in oklab, var(--tav-success) 12%, var(--tav-surface));
        color: var(--tav-success);
        font-size: 0.84375rem;
        font-weight: 600;
    }
    @media (max-width: 40rem) {
        .tav-attention-item {
            flex-wrap: wrap;
        }
        .tav-attention-body {
            flex: 1 1 100%;
        }
        .tav-attention-amount {
            order: 3;
        }
        .tav-attention-action {
            order: 4;
            margin-left: auto;
        }
    }

    /* ── Record panel: toolbar, filter chips ─────────────────────────
       Boven een lijst in een tab: zoeken, filteren op wat telt, en rechts de
       actie die er iets aan toevoegt. Een chip draagt zijn telling, zodat je
       vóór het klikken ziet hoeveel rijen er overblijven. */
    .tav-record-toolbar {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 0.5625rem;
        margin-bottom: 0.875rem;
    }
    .tav-record-toolbar-end {
        margin-left: auto;
        display: flex;
        align-items: center;
        gap: 0.5625rem;
    }
    .tav-filter-chip {
        display: inline-flex;
        align-items: center;
        gap: 0.375rem;
        height: 1.875rem;
        padding: 0 0.75rem;
        border-radius: var(--tav-radius-full);
        border: 1px solid var(--tav-hairline-strong);
        background: var(--tav-surface);
        color: var(--tav-ink-muted);
        font: inherit;
        font-size: 0.8125rem;
        text-decoration: none;
        white-space: nowrap;
        cursor: pointer;
    }
    .tav-filter-chip:hover {
        border-color: var(--tav-ink-faint);
        color: var(--tav-on-surface);
    }
    .tav-filter-chip[aria-pressed="true"],
    .tav-filter-chip.active {
        background: color-mix(in oklab, var(--tav-primary) 12%, var(--tav-surface));
        border-color: color-mix(in oklab, var(--tav-primary) 30%, var(--tav-surface));
        color: var(--tav-primary);
        font-weight: 600;
    }
    .tav-filter-chip.is-warning[aria-pressed="true"],
    .tav-filter-chip.is-warning.active {
        background: color-mix(in oklab, var(--tav-warning) 14%, var(--tav-surface));
        border-color: color-mix(in oklab, var(--tav-warning) 34%, var(--tav-surface));
        color: var(--tav-warning);
    }

    /* ── Record table ────────────────────────────────────────────────
       Een lijst in een tab: één omkaderd vlak op de ondergrond, met een
       kapitale kop in de zachtste tint en een voetregel die zegt wat je ziet
       ("1–10 van 104 voertuigen · gesorteerd op keuringsdatum").

       Een rij die aandacht vraagt krijgt een smalle kleurstreep links in de
       eerste cel — dezelfde taal als de aandachtsrijen op het overzicht, zodat
       je de drie keuringen die vervallen in een lijst van honderd terugvindt. */
    .tav-record-table {
        border: 1px solid var(--tav-hairline-strong);
        border-radius: 0.4375rem;
        overflow: hidden;
        background: var(--tav-surface);
        box-shadow: var(--tav-elevation-1);
    }
    .tav-record-table-scroll {
        overflow-x: auto;
    }
    .tav-record-table table {
        width: 100%;
        border-collapse: collapse;
    }
    .tav-record-table thead th {
        text-align: left;
        font-size: 0.6875rem;
        letter-spacing: 0.1em;
        text-transform: uppercase;
        color: var(--tav-ink-faint);
        font-weight: 600;
        padding: 0.5625rem 0.875rem;
        background: color-mix(in oklab, var(--tav-surface) 50%, var(--tav-surface-1));
        border-bottom: 1px solid var(--tav-hairline-strong);
        white-space: nowrap;
    }
    .tav-record-table tbody td {
        padding: 0.625rem 0.875rem;
        border-bottom: 1px solid var(--tav-hairline);
        font-size: 0.84375rem;
        vertical-align: middle;
        color: var(--tav-on-surface);
    }
    .tav-record-table tbody tr:last-child td {
        border-bottom: 0;
    }
    .tav-record-table tbody tr:hover td {
        background: color-mix(in oklab, var(--tav-surface) 50%, var(--tav-surface-1));
    }
    .tav-record-table tbody tr.is-warning td:first-child {
        box-shadow: inset 3px 0 0 var(--tav-warning);
    }
    .tav-record-table tbody tr.is-error td:first-child {
        box-shadow: inset 3px 0 0 var(--tav-error);
    }
    .tav-record-table tbody tr.is-off td {
        color: var(--tav-ink-faint);
    }
    .tav-record-table td a {
        color: var(--tav-primary);
        text-decoration: none;
    }
    .tav-record-table td a:hover {
        text-decoration: underline;
    }
    .tav-record-table-num {
        font-family: var(--tav-font-mono);
        font-variant-numeric: tabular-nums;
        letter-spacing: -0.01em;
    }
    .tav-record-table-foot {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        padding: 0.5625rem 0.875rem;
        background: color-mix(in oklab, var(--tav-surface) 50%, var(--tav-surface-1));
        border-top: 1px solid var(--tav-hairline-strong);
        font-size: 0.78125rem;
        color: var(--tav-ink-muted);
    }
    .tav-record-table-foot > :first-child {
        flex: 1;
    }
    /* Een lege lijst: een gestippeld vlak met één zin, geen lege tabel met
       alleen een kop. */
    .tav-record-empty {
        border: 1px dashed var(--tav-hairline-strong);
        border-radius: 0.4375rem;
        padding: 1.375rem;
        text-align: center;
        color: var(--tav-ink-faint);
        font-size: 0.84375rem;
    }
    /* Een toelichting onder een lijst ("Klanten krijgen geen account…"). */
    .tav-record-footnote {
        margin: 0.875rem 0 0;
        max-width: 62ch;
        font-size: 0.8125rem;
        color: var(--tav-ink-faint);
    }

    /* ── Access row ──────────────────────────────────────────────────
       Wie bij dit dossier kan. Medewerkers ROND, teams VIERKANT, externen
       (klantlinks, portaalgasten) in oker — drie soorten toegang in één lijst,
       aan hun vorm te onderscheiden zonder een legende. */
    .tav-access-row {
        display: flex;
        align-items: center;
        gap: 0.875rem;
        padding: 0.75rem 0;
        border-bottom: 1px solid var(--tav-hairline);
    }
    .tav-access-avatar {
        width: 2rem;
        height: 2rem;
        flex: none;
        display: grid;
        place-items: center;
        border-radius: var(--tav-radius-full);
        font-size: 0.75rem;
        font-weight: 600;
        background: color-mix(in oklab, var(--tav-primary) 12%, var(--tav-surface));
        color: var(--tav-primary);
    }
    .tav-access-avatar.is-team {
        border-radius: 0.4375rem;
        background: var(--tav-hairline);
        color: var(--tav-ink-muted);
    }
    .tav-access-avatar.is-external {
        background: color-mix(in oklab, var(--tav-warning) 14%, var(--tav-surface));
        color: var(--tav-warning);
    }
    .tav-access-who {
        flex: 1;
        min-width: 0;
    }
    .tav-access-who > b {
        display: block;
        font-size: 0.875rem;
        font-weight: 600;
        color: var(--tav-on-surface);
    }
    .tav-access-who > span {
        font-size: 0.78125rem;
        color: var(--tav-ink-muted);
    }
    .tav-access-perm {
        flex: none;
        text-align: right;
        font-size: 0.78125rem;
        color: var(--tav-ink-muted);
    }
    .tav-access-perm > b {
        display: block;
        font-size: 0.8125rem;
        font-weight: 600;
        color: var(--tav-on-surface);
    }
    .tav-access-action {
        flex: none;
        display: inline-flex;
        align-items: center;
        height: 1.75rem;
        padding: 0 0.625rem;
        border-radius: 0.3125rem;
        border: 1px solid var(--tav-hairline-strong);
        background: var(--tav-surface);
        color: var(--tav-ink-muted);
        font: inherit;
        font-size: 0.78125rem;
        cursor: pointer;
    }
    .tav-access-action:hover {
        border-color: var(--tav-ink-faint);
        color: var(--tav-on-surface);
    }

    /* ── Record note ─────────────────────────────────────────────────
       Een kort feit met zijn uitleg in de zijkolom ("Zichtbaar binnen de eigen
       organisatie", "7 jaar na laatste factuur"). De accentstreep links alleen
       bij het feit dat iets toestaat; de rest staat neutraal. */
    .tav-record-note {
        border: 1px solid var(--tav-hairline-strong);
        border-left: 3px solid var(--tav-primary);
        border-radius: 0.375rem;
        padding: 0.8125rem 0.9375rem;
        background: var(--tav-surface);
        font-size: 0.8125rem;
        line-height: 1.5;
        color: var(--tav-ink-muted);
    }
    .tav-record-note.is-quiet {
        border-left-color: var(--tav-hairline-strong);
    }
    .tav-record-note > b {
        display: block;
        margin-bottom: 0.1875rem;
        font-size: 0.84375rem;
        color: var(--tav-on-surface);
    }
    .tav-record-note code {
        font-family: var(--tav-font-mono);
        font-size: 0.75rem;
        color: var(--tav-primary);
    }

    /* Gekleurde onderregel van een kerncijfer: "1 vervallen" hoort rood te
       zijn, "alles afgehandeld" groen. Zonder die kleur draagt de strook vier
       getallen en geen enkel oordeel. */
    .tav-stat-caption.is-warning {
        color: var(--tav-warning);
        font-weight: 600;
    }
    .tav-stat-caption.is-error {
        color: var(--tav-error);
        font-weight: 600;
    }
    .tav-stat-caption.is-success {
        color: var(--tav-success);
        font-weight: 600;
    }

    /* ── Empty state ─────────────────────────────────────────────────── */
    .tav-empty {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 3rem 1rem;
        text-align: center;
    }
    .tav-empty-icon {
        width: 3rem;
        height: 3rem;
        color: color-mix(in oklab, var(--tav-on-surface-variant), transparent 40%);
    }
    .tav-empty-title {
        margin-top: 1rem;
        font-size: var(--tav-type-title-size);
        font-weight: var(--tav-type-title-weight);
        color: var(--tav-on-surface);
    }
    .tav-empty-text {
        margin-top: 0.25rem;
        font-size: var(--tav-type-body-size);
        color: var(--tav-on-surface-variant);
    }

    /* ── Pagination ──────────────────────────────────────────────────── */
    .tav-pagination {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        gap: 0.25rem;
    }
    .tav-page-btn {
        display: inline-flex;
        align-items: center;
        padding: 0.375rem 0.625rem;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-label-size);
        text-decoration: none;
    }
    .tav-page-btn:hover {
        background: var(--tav-surface-2);
    }
    .tav-page-btn.active,
    .tav-page-btn[aria-current="page"] {
        background: var(--tav-primary);
        color: var(--tav-on-primary);
        border-color: var(--tav-primary);
    }
    .tav-page-btn[aria-disabled="true"] {
        opacity: 0.5;
        pointer-events: none;
    }

    /* ── Table ───────────────────────────────────────────────────────── */
    .tav-table {
        width: 100%;
        border-collapse: collapse;
        font-size: var(--tav-type-body-size);
    }
    .tav-table thead {
        background: var(--tav-surface-2);
    }
    /* Dense by default: header and body rows carry the SAME padding so a data
       row is no taller than its header. Sentence case, not caps — all-caps
       headers shout, cost horizontal room and hurt scanning of Dutch compound
       words ("Voertuighistoriek"). Weight + muted colour carry the hierarchy
       instead; the tiny positive tracking that made caps legible is gone. */
    .tav-table th {
        padding: 0.375rem 0.75rem;
        text-align: left;
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-title-weight);
        color: var(--tav-on-surface-variant);
    }
    .tav-table td {
        padding: 0.375rem 0.75rem;
        border-top: 1px solid var(--tav-outline-variant);
        color: var(--tav-on-surface);
    }
    /* The component defaults th to left (browser th-default is center, wrong for
       a data table). But an amount/number column marks itself right with a
       tav-text-right utility, which a bare `.tav-table th` (0,1,1) would
       override back to left. Honour the explicit alignment via an
       attribute-selector so a right-aligned header stays right. */
    /* An amount or a count never breaks inside the number: "€ 329,7/1" is not
       a figure any more (tavuni-docs issue 2345). Numeric cells mark themselves with
       `tav-tabular-nums` or the mono face. */
    .tav-table td[class*="tav-tabular-nums"],
    .tav-table td[class*="tav-font-mono"] {
        white-space: nowrap;
    }
    .tav-table th[class*="tav-text-right"] {
        text-align: right;
    }
    .tav-table th[class*="tav-text-center"] {
        text-align: center;
    }
    /* Opt-in breathing room for tables whose rows carry two lines of content. */
    .tav-table-comfortable th,
    .tav-table-comfortable td {
        padding: 0.625rem 1rem;
    }
    .tav-table tbody tr:hover {
        background: color-mix(
            in oklab,
            transparent,
            var(--tav-on-surface) calc(var(--tav-state-hover) * 100%)
        );
    }
    /* Sticky header for tall scrolling tables (workspace audit #19). */
    .tav-table-sticky thead th {
        position: sticky;
        top: 0;
        z-index: 1;
        background: var(--tav-surface-2);
    }
    /* Sortable column header — the whole label is the sort link and the active
       column's direction arrow is tinted. base.html carries the ?sort=&dir=
       navigation; this only makes every sortable table LOOK identical instead
       of each hand-rolling its own header anchor. */
    .tav-table th a {
        display: inline-flex;
        align-items: center;
        gap: 0.25rem;
        color: inherit;
        text-decoration: none;
    }
    .tav-table th a:hover {
        color: var(--tav-on-surface);
    }
    /* Row navigation — a row marked data-row-href IS a link. The keyboard nav
       (j/k, focus roving) already lives in base.html; the component only makes
       it read as clickable and keeps the focus ring visible. Non-navigation
       actions go in the last cell as `.tav-row-actions`, which sits above the
       row so it stays independently clickable (the norm: the row navigates,
       the action column carries only NON-navigation actions). */
    .tav-table tbody tr[data-row-href] {
        cursor: pointer;
    }
    .tav-table tbody tr[data-row-href]:focus-visible {
        outline: 2px solid var(--tav-primary);
        outline-offset: -2px;
    }
    .tav-table .tav-row-actions {
        position: relative;
        z-index: 1;
    }

    /* ── Modal / dialog shell ────────────────────────────────────────── */
    .tav-modal-backdrop {
        position: fixed;
        inset: 0;
        z-index: 60;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 1rem;
        background: color-mix(in oklab, var(--tav-on-surface) 45%, transparent);
    }
    .tav-modal {
        width: 100%;
        max-width: 32rem;
        background: var(--tav-surface-1);
        border: 1px solid var(--tav-outline-variant);
        border-radius: var(--tav-radius-md);
        box-shadow: var(--tav-elevation-3);
        overflow: hidden;
    }

    /* Responsive table → stacked cards below the small breakpoint
       (workspace audit: ~43/48 tables not mobile-safe). Add
       `tav-table-responsive` and give every <td> a `data-label`. */
    @media (max-width: 639px) {
        .tav-table-responsive thead {
            display: none;
        }
        .tav-table-responsive tr {
            display: block;
            margin-bottom: 0.75rem;
            border: 1px solid var(--tav-outline-variant);
            border-radius: var(--tav-radius-sm);
            background: var(--tav-surface-1);
        }
        .tav-table-responsive td {
            display: flex;
            justify-content: space-between;
            gap: 1rem;
            border-top: 0;
            text-align: right;
        }
        .tav-table-responsive td::before {
            content: attr(data-label);
            font-weight: var(--tav-type-label-weight);
            color: var(--tav-on-surface-variant);
            text-align: left;
        }
    }

/* Animations live outside the cascade layer (keyframes are not layered).
   Both are neutralised by the prefers-reduced-motion rule in `tav-base`. */
@keyframes tav-spin {
    to {
        transform: rotate(360deg);
    }
}
@keyframes tav-pulse {
    50% {
        opacity: 0.5;
    }
}

    /* ── Callout (subtle, left-accent — distinct from the filled flash) ── */
    /* Single-class contract (see buttons): a bare `tav-callout-info` etc.
       must carry the callout box, not only `.tav-callout`. */
    [class*="tav-callout"] {
        display: flex;
        gap: 0.75rem;
        padding: 0.75rem 1rem;
        border-left: 3px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface-1);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
    }
    .tav-callout-info {
        border-left-color: var(--tav-info);
        background: color-mix(in oklab, var(--tav-surface-1), var(--tav-info) 8%);
    }
    .tav-callout-success {
        border-left-color: var(--tav-success);
        background: color-mix(in oklab, var(--tav-surface-1), var(--tav-success) 8%);
    }
    .tav-callout-warning {
        border-left-color: var(--tav-warning);
        background: color-mix(in oklab, var(--tav-surface-1), var(--tav-warning) 8%);
    }
    .tav-callout-error {
        border-left-color: var(--tav-error);
        background: color-mix(in oklab, var(--tav-surface-1), var(--tav-error) 8%);
    }

    /* ── Chip / tag ──────────────────────────────────────────────────── */
    .tav-chip {
        display: inline-flex;
        align-items: center;
        gap: 0.375rem;
        padding: 0.1875rem 0.625rem;
        border-radius: var(--tav-radius-full);
        background: var(--tav-surface-variant);
        color: var(--tav-on-surface-variant);
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-label-weight);
    }
    .tav-chip-remove {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 1rem;
        height: 1rem;
        border-radius: var(--tav-radius-full);
        color: var(--tav-on-surface-variant);
        cursor: pointer;
        background: transparent;
        border: 0;
    }
    .tav-chip-remove:hover {
        background: color-mix(
            in oklab,
            transparent,
            var(--tav-on-surface) calc(var(--tav-state-hover) * 100%)
        );
    }

    /* ── Spinner ─────────────────────────────────────────────────────── */
    .tav-spinner {
        display: inline-block;
        width: 1.25rem;
        height: 1.25rem;
        border: 2px solid var(--tav-outline-variant);
        border-top-color: var(--tav-primary);
        border-radius: var(--tav-radius-full);
        animation: tav-spin 0.6s linear infinite;
    }

    /* ── Progress bar ────────────────────────────────────────────────── */
    .tav-progress {
        width: 100%;
        height: 0.5rem;
        border-radius: var(--tav-radius-full);
        background: var(--tav-surface-variant);
        overflow: hidden;
    }
    .tav-progress-bar {
        height: 100%;
        border-radius: var(--tav-radius-full);
        background: var(--tav-primary);
        transition: width 0.2s ease;
    }

    /* ── Skeleton ────────────────────────────────────────────────────── */
    .tav-skeleton {
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface-2);
        animation: tav-pulse 1.5s ease-in-out infinite;
    }

    /* ── Dropdown menu (pairs with tavDisclosure) ────────────────────── */
    .tav-menu {
        min-width: 12rem;
        padding: 0.25rem;
        border: 1px solid var(--tav-outline-variant);
        border-radius: var(--tav-radius-md);
        background: var(--tav-surface-1);
        box-shadow: var(--tav-elevation-2);
    }
    .tav-menu-item {
        display: flex;
        align-items: center;
        gap: 0.625rem;
        width: 100%;
        padding: 0.5rem 0.625rem;
        border-radius: var(--tav-radius-sm);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
        text-decoration: none;
        text-align: left;
        background: transparent;
        border: 0;
        cursor: pointer;
    }
    .tav-menu-item:hover {
        background: color-mix(
            in oklab,
            transparent,
            var(--tav-on-surface) calc(var(--tav-state-hover) * 100%)
        );
    }
    .tav-menu-divider {
        height: 1px;
        margin: 0.25rem 0;
        background: var(--tav-outline-variant);
    }

    /* ── List ────────────────────────────────────────────────────────── */
    .tav-list {
        list-style: none;
        margin: 0;
        padding: 0;
    }
    .tav-list-item {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        padding: 0.75rem 0;
        border-bottom: 1px solid var(--tav-outline-variant);
    }
    .tav-list-item:last-child {
        border-bottom: 0;
    }

    /* ── Description list ─────────────────────────────────────────────── */
    .tav-dl {
        display: grid;
        grid-template-columns: minmax(8rem, max-content) 1fr;
        gap: 0.5rem 1.5rem;
        margin: 0;
    }
    .tav-dt {
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-label-weight);
        color: var(--tav-on-surface-variant);
    }
    .tav-dd {
        margin: 0;
        color: var(--tav-on-surface);
    }

    /* ── Checkbox / radio — drawn by the library, not by the browser ────
       Dirk, 2026-10-13 (tavuni-docs#2636): no native component anywhere. The
       element stays an `<input>` (form value, label click, keyboard, x-model
       and every `:checked` reader keep working), but `appearance: none` takes
       the widget away from the browser and the box, the check, the dot and
       the indeterminate bar are painted here. Gradients, not a data: image:
       the services do not share one CSP, and `img-src` without `data:` would
       blank the check where it applies. Gradients, not `::before`: a
       pseudo-element on `<input>` is not rendered in every engine.

       THREE STATES THAT NEVER LOOK ALIKE (tavuni-docs#3897). A ticked
       "Kinderzitje" next to an unavailable "Winterbanden" read as two grey
       boxes: the brand primary of a muted brand is a near-black, and disabled
       was the same box at half opacity — a ticked disabled box was a faded
       ticked one. Now: unchecked is a 2px on-surface-variant frame on the
       sheet; checked is a solid primary fill with a heavy on-primary check;
       disabled is its own look, never an opacity — a faintly tinted sheet in
       a light frame, ticked or not (ticked shows the check in that frame's
       grey, never a fill). WCAG 1.4.11 (3:1 non-text), measured in the
       browser on the default theme: checked against unchecked 11.6:1 light /
       9.9:1 dark, against disabled 9.7:1 / 8.4:1. For any brand: the theme
       keeps a brand's primary only when it reads 4.5:1 as text on the sheet
       (`theme/roles.rs`), and the disabled tint is 8 % off that sheet, so
       checked against disabled stays above 3.9:1 in both modes. A filled
       grey for disabled-and-ticked would not: a mid-tone brand sits at the
       same luminance as a 38 % grey. */
    .tav-checkbox,
    .tav-radio {
        --tav-check-ink: var(--tav-on-primary);
        appearance: none;
        -webkit-appearance: none;
        display: inline-block;
        flex-shrink: 0;
        box-sizing: border-box;
        width: 1rem;
        height: 1rem;
        margin: 0;
        vertical-align: middle;
        border: 2px solid var(--tav-on-surface-variant);
        background-color: var(--tav-surface);
        background-repeat: no-repeat;
        cursor: pointer;
        transition: background-color 0.15s ease, border-color 0.15s ease;
    }
    .tav-checkbox {
        border-radius: var(--tav-radius-xs);
    }
    .tav-radio {
        border-radius: var(--tav-radius-full);
    }
    .tav-checkbox:hover:not(:disabled),
    .tav-radio:hover:not(:disabled) {
        border-color: var(--tav-primary);
    }
    .tav-checkbox:checked,
    .tav-checkbox:indeterminate,
    .tav-radio:checked {
        border-color: var(--tav-primary);
        background-color: var(--tav-primary);
    }
    /* The check: two strokes, each the diagonal of its own box ("to top
       right" puts the 50% line through the top-left and bottom-right
       corners, "to bottom right" through the other two). */
    .tav-checkbox:checked {
        background-image:
            linear-gradient(to top right, transparent calc(50% - 1.4px), var(--tav-check-ink) calc(50% - 1.4px) calc(50% + 1.4px), transparent calc(50% + 1.4px)),
            linear-gradient(to bottom right, transparent calc(50% - 1.4px), var(--tav-check-ink) calc(50% - 1.4px) calc(50% + 1.4px), transparent calc(50% + 1.4px));
        background-size: 40% 40%, 62% 76%;
        background-position: 6% 64%, 88% 30%;
    }
    .tav-checkbox:indeterminate {
        background-image: linear-gradient(var(--tav-check-ink), var(--tav-check-ink));
        background-size: 64% 2px;
        background-position: center;
    }
    .tav-radio:checked {
        background-image: radial-gradient(circle, var(--tav-check-ink) 0 34%, transparent 40%);
    }
    .tav-checkbox:disabled,
    .tav-radio:disabled {
        cursor: not-allowed;
        border-color: color-mix(in oklab, var(--tav-on-surface) 30%, var(--tav-surface));
        background-color: color-mix(in oklab, var(--tav-on-surface) 8%, var(--tav-surface));
    }
    .tav-checkbox:checked:disabled,
    .tav-checkbox:indeterminate:disabled,
    .tav-radio:checked:disabled {
        --tav-check-ink: color-mix(in oklab, var(--tav-on-surface) 50%, var(--tav-surface));
        border-color: color-mix(in oklab, var(--tav-on-surface) 30%, var(--tav-surface));
        background-color: color-mix(in oklab, var(--tav-on-surface) 8%, var(--tav-surface));
    }
    .tav-checkbox[aria-invalid="true"],
    .tav-radio[aria-invalid="true"] {
        border-color: var(--tav-error);
    }

    /* ── Inline input — a field that reads as the text it edits ─────────
       A label renamed in place (a canvas group title, a sticky note): at
       rest it is the text, in its own font and colour; hover shows the
       box, focus the brand edge. Works on `<input>` and `<textarea>`. */
    .tav-inline-input {
        width: 100%;
        margin: 0;
        padding: 0.125rem 0.25rem;
        border: 1px solid transparent;
        border-radius: var(--tav-radius-xs);
        background: transparent;
        color: inherit;
        font: inherit;
        resize: none;
        transition: border-color 0.15s ease, background-color 0.15s ease;
    }
    .tav-inline-input:hover {
        border-color: color-mix(in oklab, currentColor 25%, transparent);
    }
    .tav-inline-input:focus {
        outline: none;
        border-color: var(--tav-primary);
        background: color-mix(in oklab, var(--tav-surface) 70%, transparent);
    }

    /* ── Disclosure — any `<details>` that is not a collapse/accordion ────
       The bare variant: the library takes the browser's triangle away and
       draws its own chevron at the end of the summary; box, padding and
       layout stay with the page. A `<details>` without a Tavuni disclosure
       class shows the UA marker, which is a native component. */
    .tav-disclosure > summary {
        list-style: none;
        cursor: pointer;
    }
    .tav-disclosure > summary::-webkit-details-marker {
        display: none;
    }
    .tav-disclosure > summary::marker {
        content: "";
    }
    .tav-disclosure:not(.tav-disclosure-plain) > summary::after {
        content: "";
        display: inline-block;
        flex-shrink: 0;
        width: 0.4375rem;
        height: 0.4375rem;
        margin-inline-start: 0.5rem;
        border-right: 2px solid currentColor;
        border-bottom: 2px solid currentColor;
        opacity: 0.6;
        transform: translateY(-0.125rem) rotate(45deg);
        transition: transform 0.15s ease;
        vertical-align: middle;
    }
    .tav-disclosure[open]:not(.tav-disclosure-plain) > summary::after {
        transform: translateY(0.0625rem) rotate(-135deg);
    }

    /* ── Segmented control ───────────────────────────────────────────── */
    .tav-segmented {
        display: inline-flex;
        padding: 0.1875rem;
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface-variant);
    }
    .tav-segmented-item {
        padding: 0.3125rem 0.75rem;
        border-radius: var(--tav-radius-xs);
        color: var(--tav-on-surface-variant);
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-label-weight);
        text-decoration: none;
        border: 0;
        background: transparent;
        cursor: pointer;
    }
    /* A segment can also BE a radio group: each item a <label> around a
       visually hidden radio (vehicles/_holding_role.html). The checked radio
       is the active segment, and its keyboard focus has to show on the label,
       because the radio itself is not drawn (tavuni-docs#3186). */
    .tav-segmented-item.active,
    .tav-segmented-item[aria-selected="true"],
    .tav-segmented-item:has(> input[type="radio"]:checked) {
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        box-shadow: var(--tav-elevation-1);
    }
    .tav-segmented-item:has(> input[type="radio"]:focus-visible) {
        outline: 2px solid var(--tav-primary);
        outline-offset: 2px;
    }

    /* ── Page header ─────────────────────────────────────────────────── */
    .tav-page-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        flex-wrap: wrap;
        margin-bottom: 1.5rem;
    }
    .tav-page-title {
        margin: 0;
        font-size: var(--tav-type-headline-size);
        line-height: var(--tav-type-headline-line);
        font-weight: var(--tav-type-headline-weight);
        color: var(--tav-on-surface);
    }
    .tav-page-subtitle {
        margin: 0.25rem 0 0;
        font-size: var(--tav-type-body-size);
        color: var(--tav-on-surface-variant);
    }
    /* Headings INSIDE a page. `page_header` owns the single `<h1>`; everything
       below it was left to improvise, and workspace grew 55 distinct class
       combinations for what are three kinds of heading (B-831). These three
       carry the values those combinations already rendered, so adopting them
       changes nothing visually and collapses the vocabulary.

       `-title`   16px semibold — a real section, the kind that owns a card.
       `-label`   14px semibold — a sub-heading inside one. The commonest of the
                  three by far, and the one most often written out by hand.
       `-eyebrow` 12px medium uppercase — the small-caps label above a block.

       The eyebrow used to be 14px semibold in `--tav-on-surface`, and the claim
       above ("adopting them changes nothing visually") was true of `-title` and
       `-label` but not of it. Measured 2026-08-27: the product wrote the small
       muted form 236 times against 37 uses of the component — and across SIX
       class combinations, with three tracking values and three weights, which is
       exactly the drift a component exists to stop. It also made this the only
       one of the four small-text roles off the shared base: `tav-label`,
       `tav-dt` and `tav-help` all sit on label-size + on-surface-variant. An
       eyebrow is by definition secondary to the heading it announces, so the
       component moved rather than the markup — the one place in this sweep
       where the measurement went against the library (B-863). */
    .tav-section-title {
        margin: 0;
        font-size: var(--tav-type-title-size);
        line-height: var(--tav-type-title-line);
        font-weight: var(--tav-type-title-weight);
        color: var(--tav-on-surface);
    }
    /* Het veldraster van een sectie: twee kolommen op een breed scherm, één op
       een smal. Elke sectie draagt hem, zodat velden in ALLE secties op dezelfde
       twee kolommen uitlijnen — dat is wat een fiche één blad maakt in plaats
       van een stapel losse lijstjes.

       `column-gap` is ruim en `row-gap` nul: de haarlijn van elke rij levert de
       verticale ritmiek al, en een extra gat zou hem van zijn veld losmaken. */
    .tav-field-grid {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        gap: 0 2.5rem;
    }
    @media (min-width: 64rem) {
        .tav-field-grid {
            grid-template-columns: repeat(2, minmax(0, 1fr));
        }
    }

    /* ── Field row ───────────────────────────────────────────────────
       Eén regel van een dossier: een label, zijn waarde, en de haarlijn
       eronder. Dit is DE leesvorm van een fiche.

       Er stonden twee vormtalen op één scherm. De vaste velden (kerngegevens)
       waren label/waarde-paren met haarlijnen; identificatienummers,
       contactgegevens en adressen waren CHIPS met een verwijderkruis per rij.
       Dat leest niet als hetzelfde dossier maar als een leesscherm waar
       iemand een editor in geplakt heeft — en de chip maakt van een veldnaam
       een badge, een vorm die in de rest van de app een STATUS betekent.

       De actie (verwijderen) blijft bestaan maar verschijnt pas bij hover of
       toetsenbordfocus. Op een aanraakscherm bestaat hover niet, dus daar
       staat hij altijd: `@media (hover: hover)` verbergt hem alleen waar er
       een muis is om hem terug te halen. */
    .tav-field-row {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: start;
        gap: 0 0.75rem;
        /* Het veldpaar van het ontwerp: 10px boven en onder, en de scheider
           (de lichtste lijn, ≈ L* 93) eronder. Zonder die lijn liepen de
           velden van twee kolommen in elkaar over zodra één waarde twee regels
           besloeg — de lijn is wat een paar een paar maakt. */
        padding: 0.625rem 0;
        border-bottom: 1px solid var(--tav-hairline);
    }
    /* Label BOVEN de waarde, niet ernaast. Naast elkaar dwingt een vaste
       labelkolom af, en dan breekt "Ondernemingsnummer (KBO)" over twee regels
       terwijl de waarde ernaast in de leegte hangt. */
    .tav-field-row > dt,
    .tav-field-label {
        grid-column: 1;
        font-size: 0.78125rem;
        line-height: 1.4;
        color: var(--tav-ink-muted);
        margin: 0 0 0.0625rem;
    }
    .tav-field-row > dd,
    .tav-field-value {
        grid-column: 1;
        min-width: 0;
        margin: 0;
        font-size: 0.90625rem;
        line-height: 1.4;
        color: var(--tav-on-surface);
        overflow-wrap: anywhere;
    }
    /* Een waarde die ONTBREEKT en dat hoort te melden ("Onbekend" bij de
       voorkeurstaal) in de waarschuwingstint — het ontwerp tekent een gat,
       niet een lege plek. */
    .tav-field-row > dd.is-gap,
    .tav-field-value.is-gap {
        color: var(--tav-warning);
    }
    /* Een toelichting achter een waarde ("art. 20 KB nr. 1", "33 % benut"). */
    .tav-field-note {
        margin-left: 0.25rem;
        color: var(--tav-ink-faint);
        font-size: 0.78125rem;
    }
    .tav-field-row > dd a {
        color: var(--tav-primary);
        text-decoration: none;
    }
    .tav-field-row > dd a:hover {
        text-decoration: underline;
    }
    /* `span 2`, NIET `1 / -1`. De rijen van dit raster zijn IMPLICIET, en een
       negatieve lijn telt alleen expliciete rijen — `1 / -1` werd dus één rij.
       De knop (38px) zat daarmee naast het label (17px) en rekte die rij op,
       waardoor de waarde 21px onder zijn label kwam te hangen. Gemeten met
       echte breedte: 21px gat → 3px met span 2. */
    .tav-field-row > .tav-field-row-action {
        grid-column: 2;
        grid-row: 1 / span 2;
        align-self: center;
    }
    /* De waarde van een NUMMER (btw, KBO, telefoon, IBAN) in mono met
       tabular-nums: cijferreeksen lijnen dan onder elkaar uit en je leest ze
       als één soort ding. */
    .tav-field-value-num {
        font-family: var(--tav-font-mono);
        font-variant-numeric: tabular-nums;
    }
    /* Wijzigen en verwijderen naast elkaar: een potlood dat de bewerkpopup
       opent en een kruis achter een bevestiging. Eén houder, zodat ze samen
       verschijnen bij hover en samen blijven staan op touch. */
    .tav-field-row-action {
        display: flex;
        align-items: center;
        gap: 0.125rem;
        flex: none;
        opacity: 1;
        transition: opacity 120ms ease;
    }
    @media (hover: hover) {
        .tav-field-row-action {
            opacity: 0;
        }
        .tav-field-row:hover .tav-field-row-action,
        .tav-field-row:focus-within .tav-field-row-action {
            opacity: 1;
        }
    }

    /* Een rij die op een LOSSE regel meer draagt dan een waarde (een adres van
       drie regels): label boven, inhoud eronder, zelfde haarlijn. */
    .tav-field-block {
        padding: 0.625rem 0;
        border-bottom: 1px solid var(--tav-outline-variant);
    }
    .tav-field-block > :first-child {
        font-size: var(--tav-type-size-xs);
        line-height: 1.5;
        color: var(--tav-on-surface-variant);
        margin: 0 0 0.1875rem;
    }

    /* ── Related links ───────────────────────────────────────────────
       De uitgangen van een fiche. Waren zes omkaderde hokjes in een raster —
       elk vakje las als een knop met evenveel gewicht als de acties bovenaan.
       Het zijn verwijzingen, dus ze krijgen de vorm van verwijzingen. */
    .tav-related-links {
        display: flex;
        flex-wrap: wrap;
        gap: 0.375rem 1.25rem;
    }
    .tav-related-links > a {
        font-size: var(--tav-type-size-sm);
        color: var(--tav-primary);
        text-decoration: none;
    }
    .tav-related-links > a:hover {
        text-decoration: underline;
    }

    /* ── Section head ────────────────────────────────────────────────
       DE sectiekop. Eén component, met zijn haarlijn en zijn marge erin.

       Er waren er drie — `tav-section-label`, `tav-section-eyebrow`,
       `tav-section-title` — plus 135 handgemaakte varianten, samen 68
       verschillende manieren om een <h2> te schrijven. Dat is wat een
       gebruiker "rommelig" noemt: dezelfde soort kop is op het ene scherm
       klein en kapitaal, op het andere groot en vet, hier met een lijn en daar
       zonder.

       De typografie is die van de klantfiche, het scherm waarvan de vorm is
       goedgekeurd: klein, kapitaal, ruime letterafstand, in de variant-kleur.
       Een sectiekop is een LABEL boven een groep velden, geen titel die met de
       recordnaam concurreert — die staat al bovenaan in de display-face.

       De haarlijn hoort BIJ de kop en niet bij de aanroeper: 26 van de 68
       vormen verschilden alleen in of ze `border-b pb-2 mb-3` meedroegen, en
       in welke volgorde. Wie een kop zonder lijn wil, gebruikt
       `tav-section-eyebrow`. */
    .tav-section-head {
        margin: 0 0 0.75rem;
        padding-bottom: 0.5rem;
        border-bottom: 1px solid var(--tav-hairline);
        font-size: var(--tav-type-label-size);
        line-height: var(--tav-type-label-line);
        font-weight: var(--tav-type-label-weight);
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: var(--tav-on-surface-variant);
    }
    /* Een sectiekop met een actie ernaast (Alles bekijken, + Toevoegen). De
       lijn loopt onder allebei door, anders zweeft de knop los boven de
       inhoud. */
    .tav-section-head-row {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 1rem;
        margin: 0 0 0.75rem;
        padding-bottom: 0.5rem;
        border-bottom: 1px solid var(--tav-outline-variant);
    }
    .tav-section-head-row > :first-child {
        margin: 0;
        padding: 0;
        border: 0;
        font-size: var(--tav-type-label-size);
        line-height: var(--tav-type-label-line);
        font-weight: var(--tav-type-label-weight);
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: var(--tav-on-surface-variant);
    }

    .tav-section-label {
        margin: 0;
        font-size: var(--tav-type-body-size);
        line-height: var(--tav-type-body-line);
        font-weight: var(--tav-type-title-weight);
        color: var(--tav-on-surface);
    }
    .tav-section-eyebrow {
        margin: 0;
        font-size: var(--tav-type-label-size);
        line-height: var(--tav-type-label-line);
        font-weight: var(--tav-type-label-weight);
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: var(--tav-on-surface-variant);
    }

    /* ── App shell (layout structure) ────────────────────────────────── */
    .tav-shell {
        display: flex;
        min-height: 100vh;
        background: var(--tav-surface-1);
        color: var(--tav-on-surface);
    }
    .tav-app-sidebar {
        display: flex;
        flex-direction: column;
        width: 16rem;
        flex-shrink: 0;
        background: var(--tav-surface-1);
        border-right: 1px solid var(--tav-outline-variant);
    }
    .tav-app-main {
        display: flex;
        flex-direction: column;
        flex: 1;
        min-width: 0;
    }
    .tav-app-topbar {
        display: flex;
        align-items: center;
        gap: 1rem;
        height: 4rem;
        padding: 0 1.5rem;
        background: var(--tav-surface-1);
        border-bottom: 1px solid var(--tav-outline-variant);
    }
    .tav-app-content {
        flex: 1;
        overflow-y: auto;
        padding: 2rem 1.5rem;
    }

/*
 * Token utilities — single-property helpers for the long tail (inline accents,
 * ad-hoc surfaces, links) where a full component is overkill. They sit in the
 * `tav-utilities` layer so a utility always wins over a component default, and
 * read ONLY `--tav-*` roles, so each recolours per brand. These are what a
 * ramp-utility migration (ADR-0359 phase 3: `text-tavuni-600` → `tav-text-primary`)
 * maps onto — reach for a component (`tav-btn`, `tav-badge`, `tav-link`, …) first;
 * use these only when no component fits the surface.
 */
    /* Foreground — text + icon `currentColor`. */
    .tav-text-primary { color: var(--tav-primary); }
    .tav-text-on-surface { color: var(--tav-on-surface); }
    .tav-text-muted { color: var(--tav-on-surface-variant); }
    .tav-text-success { color: var(--tav-success); }
    .tav-text-warning { color: var(--tav-warning); }
    .tav-text-error { color: var(--tav-error); }
    .tav-text-info { color: var(--tav-info); }
    .tav-text-accent { color: var(--tav-accent); }

    /* Surfaces — background, paired with its on-colour for filled roles so text
       stays legible no matter the brand. */
    .tav-bg-surface { background-color: var(--tav-surface); }
    .tav-bg-surface-1 { background-color: var(--tav-surface-1); }
    .tav-bg-surface-2 { background-color: var(--tav-surface-2); }
    .tav-bg-surface-3 { background-color: var(--tav-surface-3); }
    .tav-bg-primary { background-color: var(--tav-primary); color: var(--tav-on-primary); }
    .tav-bg-primary-container { background-color: var(--tav-primary-container); color: var(--tav-on-primary-container); }
    .tav-bg-success-container { background-color: var(--tav-success-container); color: var(--tav-on-success-container); }
    .tav-bg-warning-container { background-color: var(--tav-warning-container); color: var(--tav-on-warning-container); }
    .tav-bg-error-container { background-color: var(--tav-error-container); color: var(--tav-on-error-container); }
    .tav-bg-info-container { background-color: var(--tav-info-container); color: var(--tav-on-info-container); }
    .tav-bg-accent-container { background-color: var(--tav-accent-container); color: var(--tav-on-accent-container); }

    /* Borders. */
    /* No border-COLOR here: this sheet is served UNLAYERED, so a color longhand
       would beat the layered tav-base companion utilities (.tav-border-outline-variant,
       .tav-border-<color>) and force every `tav-border tav-border-*` element to one
       fixed color. Width+style only → companions (and the tav-base preflight default,
       now var(--tav-outline-variant)) own the color. */
    .tav-border { border-width: 1px; border-style: solid; }
    .tav-border-subtle { border: 1px solid var(--tav-outline-variant); }
    .tav-border-primary { border-color: var(--tav-primary); }

/*
 * Custom select (`<tav-select>`) — a fully-managed dropdown. A native `<select>`
 * draws its option list with the OS/UA, which ignores `accent-color`, so the
 * selected option stays the system blue no matter the brand. This renders the
 * list in the page instead, so EVERY part — including the selected + active
 * option — reads the `--tav-*` roles and recolours per brand. The custom element
 * (js/tav-elements.js) builds the trigger + listbox + a hidden form input from
 * `<tav-option>` children; the styling lives here so it themes like every other
 * component.
 */
    tav-select {
        position: relative;
        display: block;
    }
    .tav-select-trigger {
        display: inline-flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.5rem;
        width: 100%;
        padding: 0.5rem 0.75rem;
        border: 1px solid color-mix(in oklab, var(--tav-primary) 28%, var(--tav-outline));
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
        line-height: var(--tav-type-body-line);
        text-align: left;
        cursor: pointer;
    }
    .tav-select-trigger[aria-expanded="true"] {
        border-color: var(--tav-primary);
        box-shadow: 0 0 0 1px var(--tav-primary);
    }
    .tav-select-caret {
        inline-size: 1rem;
        block-size: 1rem;
        flex-shrink: 0;
        color: var(--tav-on-surface-variant);
        transition: transform 0.15s ease;
    }
    .tav-select-trigger[aria-expanded="true"] .tav-select-caret {
        transform: rotate(180deg);
    }
    /* Viewport-fixed and placed by the element against its trigger. As a
       `popover` it renders in the top layer, so no ancestor's overflow — a
       scrolling `<dialog>` included — can clip it. `--tav-select-room` is the
       space the element measured on the side it opened towards. */
    .tav-select-listbox {
        position: fixed;
        z-index: 50;
        inset: auto;
        box-sizing: border-box;
        max-block-size: min(15rem, var(--tav-select-room, 15rem));
        overflow-y: auto;
        overscroll-behavior: contain;
        margin: 0;
        padding: 0.25rem;
        list-style: none;
        background: var(--tav-surface);
        border: 1px solid var(--tav-outline-variant);
        border-radius: var(--tav-radius-sm);
        box-shadow: var(--tav-elevation-2);
    }
    .tav-select-option {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.4rem 0.6rem;
        border-radius: var(--tav-radius-xs);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
        cursor: pointer;
    }
    /* Keyboard-roving / hover highlight — a subtle brand tint. */
    .tav-select-option:hover,
    .tav-select-option[data-active="true"] {
        background: color-mix(in oklab, var(--tav-primary), transparent 88%);
    }
    /* The SELECTED option — full brand colour. This is the surface a native
       `<select>` cannot theme; here it tracks the active brand in both modes. */
    .tav-select-option[aria-selected="true"] {
        background: var(--tav-primary);
        color: var(--tav-on-primary);
    }
    .tav-select-option[aria-selected="true"]:hover,
    .tav-select-option[aria-selected="true"][data-active="true"] {
        background: color-mix(in oklab, var(--tav-primary), var(--tav-on-primary) 12%);
    }
    .tav-select-option[hidden] {
        display: none;
    }
    .tav-select-empty {
        padding: 0.4rem 0.6rem;
        color: var(--tav-on-surface-variant);
        font-size: var(--tav-type-body-size);
    }
    /* The searchable trigger is a text input: same box as the button, the
       text cursor where you type, and the button's own caret laid over its
       end (tavuni-docs#3900: a painted triangle beside a chevron read as two
       kinds of list in one dialog). The caret lets clicks through to the
       input. */
    .tav-select-search {
        cursor: text;
        padding-inline-end: 2rem;
    }
    .tav-select-search-caret {
        position: absolute;
        inset-inline-end: 0.75rem;
        top: 50%;
        translate: 0 -50%;
        pointer-events: none;
    }
    .tav-select-search[aria-expanded="true"] + .tav-select-search-caret {
        transform: rotate(180deg);
    }
    .tav-select-search:focus {
        outline: none;
        border-color: var(--tav-primary);
        box-shadow: 0 0 0 1px var(--tav-primary);
    }
    .tav-select-search::placeholder {
        color: var(--tav-on-surface-variant);
    }
    .tav-select-check {
        inline-size: 1rem;
        block-size: 1rem;
        margin-inline-start: auto;
        opacity: 0;
    }
    .tav-select-option[aria-selected="true"] .tav-select-check {
        opacity: 1;
    }
    /* `<tav-option disabled>` — visible, not pickable (native `<option disabled>`). */
    .tav-select-option[aria-disabled="true"] {
        color: var(--tav-on-surface-variant);
        opacity: 0.55;
        cursor: not-allowed;
    }
    .tav-select-option[aria-disabled="true"]:hover {
        background: none;
    }
    /* `<tav-optgroup label>` heading — not an option. */
    .tav-select-group {
        padding: 0.5rem 0.6rem 0.2rem;
        color: var(--tav-on-surface-variant);
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-label-weight);
    }
    .tav-select-group[hidden] {
        display: none;
    }
    /* A `multiple` trigger lists every chosen label; it stays one line. */
    .tav-select-trigger > span {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

/*
 * Custom date picker (`<tav-date>`) — a native `<input type="date">` opens an
 * OS/UA calendar that can't be themed; this renders the calendar in the page so
 * the selected day, the today marker and the keyboard-roving cell all read the
 * `--tav-*` roles and recolour per brand. (js/tav-elements.js)
 */
    tav-date {
        position: relative;
        display: block;
    }
    /* The field: a text box you type the date into, the calendar button at
       its end. The ring is on the field, for either part. */
    .tav-date-field {
        display: flex;
        align-items: stretch;
        width: 100%;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        color: var(--tav-on-surface);
    }
    .tav-date-field:focus-within,
    .tav-date-field:has(.tav-date-trigger[aria-expanded="true"]) {
        border-color: var(--tav-primary);
        box-shadow: 0 0 0 1px var(--tav-primary);
    }
    .tav-date-field.is-invalid {
        border-color: var(--tav-error);
        box-shadow: 0 0 0 1px var(--tav-error);
    }
    .tav-date-input {
        flex: 1 1 auto;
        min-width: 0;
        padding: 0.5rem 0.75rem;
        border: 0;
        background: transparent;
        color: inherit;
        font: inherit;
        font-size: var(--tav-type-body-size);
        line-height: var(--tav-type-body-line);
        outline: none;
    }
    .tav-date-input::placeholder {
        color: var(--tav-on-surface-variant);
        opacity: 1;
    }
    .tav-date-trigger {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        flex: 0 0 auto;
        padding: 0 0.75rem;
        border: 0;
        border-radius: 0 var(--tav-radius-sm) var(--tav-radius-sm) 0;
        background: transparent;
        color: var(--tav-on-surface-variant);
        cursor: pointer;
    }
    .tav-date-trigger:hover {
        color: var(--tav-on-surface);
    }
    .tav-date-trigger:focus-visible {
        outline: 2px solid var(--tav-primary);
        outline-offset: -2px;
    }
    .tav-date-icon {
        inline-size: 1rem;
        block-size: 1rem;
        flex-shrink: 0;
        color: var(--tav-on-surface-variant);
    }
    /* Viewport-fixed and placed by the element against its field, in the
       top layer as a `popover` (tavuni-docs#3897): no dialog clips it and it
       adds nothing to a dialog's scroll height. `--tav-date-room` is the
       space the element measured on the side it opened towards. */
    .tav-date-popup {
        position: fixed;
        z-index: 50;
        inset: auto;
        box-sizing: border-box;
        margin: 0;
        inline-size: 17rem;
        max-block-size: var(--tav-date-room, none);
        overflow-y: auto;
        overscroll-behavior: contain;
        color: var(--tav-on-surface);
        padding: 0.75rem;
        background: var(--tav-surface);
        border: 1px solid var(--tav-outline-variant);
        border-radius: var(--tav-radius-sm);
        box-shadow: var(--tav-elevation-2);
    }
    .tav-date-head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-block-end: 0.5rem;
    }
    .tav-date-title {
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-title-weight);
        color: var(--tav-on-surface);
    }
    /* The title goes up a level: month → years → a year's months. */
    .tav-date-titlebtn {
        padding: 0.25rem 0.5rem;
        border: 0;
        border-radius: var(--tav-radius-sm);
        background: transparent;
        color: inherit;
        font: inherit;
        cursor: pointer;
    }
    .tav-date-titlebtn:hover:not(:disabled) {
        background: color-mix(in oklab, var(--tav-on-surface), transparent 92%);
    }
    .tav-date-titlebtn:disabled {
        cursor: default;
    }
    .tav-date-navbtn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: 1.75rem;
        block-size: 1.75rem;
        border: 0;
        border-radius: var(--tav-radius-sm);
        background: transparent;
        color: var(--tav-on-surface-variant);
        cursor: pointer;
    }
    .tav-date-navbtn:hover {
        background: color-mix(in oklab, var(--tav-on-surface), transparent 92%);
        color: var(--tav-on-surface);
    }
    .tav-date-grid {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        gap: 2px;
    }
    /* role=row for assistive tech only; the days stay cells of the grid. */
    .tav-date-row {
        display: contents;
    }
    .tav-date-dow {
        padding-block: 0.25rem;
        text-align: center;
        font-size: 0.6875rem;
        font-weight: var(--tav-type-label-weight);
        color: var(--tav-on-surface-variant);
    }
    .tav-date-day {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        aspect-ratio: 1;
        border: 0;
        border-radius: var(--tav-radius-sm);
        background: transparent;
        color: var(--tav-on-surface);
        font-size: var(--tav-type-label-size);
        cursor: pointer;
    }
    .tav-date-day:hover,
    .tav-date-day[data-active="true"] {
        background: color-mix(in oklab, var(--tav-primary), transparent 88%);
    }
    /* A day of the next or previous month can still be picked, so its text
       keeps 4.5:1 (WCAG 1.4.3): the muted ink alone sets it apart — at half
       opacity it measured about 2.5:1. */
    .tav-date-day.is-outside {
        color: var(--tav-on-surface-variant);
    }
    .tav-date-day.is-today {
        box-shadow: inset 0 0 0 1px var(--tav-primary);
    }
    .tav-date-day[aria-selected="true"] {
        background: var(--tav-primary);
        color: var(--tav-on-primary);
    }
    .tav-date-day[aria-selected="true"]:hover,
    .tav-date-day[aria-selected="true"][data-active="true"] {
        background: color-mix(in oklab, var(--tav-primary), var(--tav-on-primary) 12%);
    }
    /* A period (`<tav-date-range>`): the days between its two ends, the two
       ends themselves, and — in the end's picker — the period under the
       pointer before it is picked. A light tint and a ring, never a solid
       fill: the day's ink stays on (nearly) the surface it has 4.5:1 against,
       in light and dark alike (WCAG 1.4.3). */
    tav-date-range {
        display: contents;
    }
    .tav-date-day.is-in-range,
    .tav-date-day.is-in-preview {
        background: color-mix(in oklab, var(--tav-primary), transparent 85%);
    }
    .tav-date-day.is-range-start:not([aria-selected="true"]),
    .tav-date-day.is-range-end:not([aria-selected="true"]) {
        background: color-mix(in oklab, var(--tav-primary), transparent 80%);
        box-shadow: inset 0 0 0 2px var(--tav-primary);
        font-weight: var(--tav-type-label-weight);
    }
    /* A day outside `min` / `max`. */
    .tav-date-day:disabled {
        color: var(--tav-on-surface-variant);
        opacity: 0.4;
        cursor: not-allowed;
    }
    .tav-date-day:disabled:hover {
        background: none;
    }
    .tav-date-foot {
        display: flex;
        justify-content: flex-end;
        padding-top: 0.25rem;
    }
    /* Twelve months or twenty years, four to a row. */
    .tav-date-grid.is-cells {
        grid-template-columns: repeat(4, 1fr);
        gap: 0.25rem;
    }
    .tav-date-cell {
        padding: 0.625rem 0;
        border: 0;
        border-radius: var(--tav-radius-sm);
        background: transparent;
        color: var(--tav-on-surface);
        font: inherit;
        font-size: var(--tav-type-label-size);
        cursor: pointer;
    }
    .tav-date-cell:hover,
    .tav-date-cell:focus-visible {
        background: color-mix(in oklab, var(--tav-primary), transparent 88%);
    }
    .tav-date-cell[aria-current="true"] {
        background: var(--tav-primary);
        color: var(--tav-on-primary);
    }
    .tav-date-cell:disabled {
        color: var(--tav-on-surface-variant);
        opacity: 0.4;
        cursor: not-allowed;
    }
    /* A text button: no browser chrome (border, grey fill) — the sheet
       draws it, as everywhere (tavuni-docs#2636). */
    .tav-date-clear {
        padding: 0.25rem 0.5rem;
        border: 0;
        border-radius: var(--tav-radius-xs);
        background: transparent;
        color: var(--tav-primary);
        font: inherit;
        font-size: var(--tav-type-label-size);
        cursor: pointer;
    }
    .tav-date-clear:hover {
        background: color-mix(in oklab, var(--tav-primary), transparent 88%);
    }
    .tav-date-clear[hidden] {
        display: none;
    }

/*
 * Custom colour picker (`<tav-color>`) — a native `<input type="color">` opens
 * the OS colour dialog; this is a full in-page HSV picker (saturation/value
 * area + hue slider + hex). Only LAYOUT lives here (token-only, so the no-colour
 * gate stays green); the spectrum gradients, the swatch fill and the drag thumbs
 * are inherently spectrum colours and are set inline by js/tav-elements.js.
 */
    tav-color {
        position: relative;
        display: block;
    }
    .tav-color-trigger {
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
        width: 100%;
        padding: 0.375rem 0.5rem;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
        text-align: left;
        cursor: pointer;
    }
    .tav-color-trigger[aria-expanded="true"] {
        border-color: var(--tav-primary);
        box-shadow: 0 0 0 1px var(--tav-primary);
    }
    .tav-color-swatch {
        inline-size: 1.25rem;
        block-size: 1.25rem;
        flex-shrink: 0;
        border-radius: var(--tav-radius-xs);
        box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--tav-on-surface), transparent 80%);
        /* fill colour set inline */
    }
    .tav-color-value {
        font-variant-numeric: tabular-nums;
        text-transform: uppercase;
    }
    .tav-color-popup {
        position: absolute;
        z-index: 50;
        inset-block-start: calc(100% + 0.25rem);
        inset-inline-start: 0;
        inline-size: 15rem;
        padding: 0.75rem;
        background: var(--tav-surface);
        border: 1px solid var(--tav-outline-variant);
        border-radius: var(--tav-radius-sm);
        box-shadow: var(--tav-elevation-2);
    }
    .tav-color-area {
        position: relative;
        inline-size: 100%;
        block-size: 9rem;
        border-radius: var(--tav-radius-xs);
        cursor: crosshair;
        touch-action: none;
        /* SV gradient set inline */
    }
    .tav-color-hue {
        position: relative;
        inline-size: 100%;
        block-size: 0.75rem;
        margin-block-start: 0.625rem;
        border-radius: var(--tav-radius-full);
        cursor: ew-resize;
        touch-action: none;
        /* spectrum gradient set inline */
    }
    .tav-color-thumb {
        position: absolute;
        inline-size: 0.85rem;
        block-size: 0.85rem;
        border-radius: 50%;
        transform: translate(-50%, -50%);
        pointer-events: none;
        /* contrast ring set inline (must read on any picked colour) */
    }
    .tav-color-row {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        margin-block-start: 0.625rem;
    }
    .tav-color-hex {
        flex: 1;
        min-inline-size: 0;
        padding: 0.35rem 0.5rem;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
        font-variant-numeric: tabular-nums;
        text-transform: uppercase;
    }
    .tav-color-hex:focus {
        outline: none;
        border-color: var(--tav-primary);
        box-shadow: 0 0 0 1px var(--tav-primary);
    }

/*
 * Custom file upload (`<tav-file>`) — wraps a real (hidden) `<input type="file">`
 * with a themed dropzone + file list, so the OS-styled "Choose file" button is
 * replaced by on-brand chrome while the input still carries the file into a
 * normal form submit. (js/tav-elements.js)
 */
    tav-file {
        display: block;
    }
    .tav-file {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 0.4rem;
        padding: 1.25rem 1rem;
        text-align: center;
        border: 1.5px dashed var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        cursor: pointer;
        transition: border-color 0.15s ease, background 0.15s ease;
    }
    .tav-file:hover,
    .tav-file.is-drag {
        border-color: var(--tav-primary);
        background: color-mix(in oklab, var(--tav-primary), transparent 94%);
    }
    .tav-file-icon {
        inline-size: 1.5rem;
        block-size: 1.5rem;
        color: var(--tav-on-surface-variant);
    }
    .tav-file-text {
        font-size: var(--tav-type-body-size);
        color: var(--tav-on-surface);
    }
    .tav-file-em {
        color: var(--tav-primary);
        font-weight: var(--tav-type-title-weight);
    }
    .tav-file-hint {
        font-size: var(--tav-type-label-size);
        color: var(--tav-on-surface-variant);
    }
    .tav-file-list {
        display: flex;
        flex-direction: column;
        gap: 0.25rem;
        inline-size: 100%;
        margin-block-start: 0.5rem;
    }
    .tav-file-item {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.35rem 0.5rem;
        border-radius: var(--tav-radius-xs);
        background: var(--tav-surface-1);
        font-size: var(--tav-type-label-size);
        color: var(--tav-on-surface);
    }
    .tav-file-item-name {
        flex: 1;
        min-inline-size: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        text-align: start;
    }
    .tav-file-item-icon {
        flex-shrink: 0;
        color: var(--tav-on-surface-variant);
    }
    .tav-file-size {
        color: var(--tav-on-surface-variant);
    }
    /* <tav-signature> (tavuni-docs#3178 part 5) — the drawing surface: the ink
       is `color`, so a theme's on-surface draws the line. `touch-action: none`
       keeps a finger drawing instead of scrolling the page. */
    tav-signature {
        display: flex;
        flex-direction: column;
        gap: 0.4rem;
    }
    .tav-signature-pad {
        display: block;
        inline-size: 100%;
        block-size: 10rem;
        border: 1.5px dashed var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        touch-action: none;
        cursor: crosshair;
    }
    .tav-signature-pad:focus-visible {
        outline: 2px solid var(--tav-primary);
        outline-offset: 2px;
    }
    .tav-signature-bar {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.5rem;
    }
    .tav-signature-hint {
        font-size: var(--tav-type-label-size);
        color: var(--tav-on-surface-variant);
    }
    /* <tav-plan> (ADR-0522 §10, tavuni-docs#3519) — a site's drawn plan. The
       stage keeps the image's proportions (`aspect-ratio` set by the element);
       every place is a polygon coloured by its state on the role matrix:
       free = success, occupied = info, full = warning, over capacity = error,
       nothing known = neutral. An area or a building is drawn lighter and
       dashed so the lanes and spaces on it stay readable; the searched
       vehicle's place is outlined in primary. */
    tav-plan {
        display: flex;
        flex-direction: column;
        gap: 0.4rem;
    }
    tav-plan-shape,
    tav-plan-marker {
        display: none;
    }
    .tav-plan-stage {
        position: relative;
        inline-size: 100%;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface-variant);
        overflow: hidden;
    }
    .tav-plan-svg {
        display: block;
        inline-size: 100%;
        block-size: 100%;
        touch-action: none;
    }
    .tav-plan-svg[role="application"] {
        cursor: crosshair;
    }
    .tav-plan-svg[role="application"] .tav-plan-shapes,
    .tav-plan-svg[role="application"] .tav-plan-markers {
        pointer-events: none;
    }
    .tav-plan-svg:focus-visible {
        outline: 2px solid var(--tav-primary);
        outline-offset: -2px;
    }
    .tav-plan-shape {
        stroke-width: 1.5;
        fill-opacity: 0.55;
        fill: var(--tav-surface);
        stroke: var(--tav-outline);
    }
    .tav-plan-shape[data-kind="yard_area"],
    .tav-plan-shape[data-kind="building"] {
        fill-opacity: 0.18;
        stroke-dasharray: 6 4;
    }
    .tav-plan-shape[data-state="free"] {
        fill: var(--tav-success-container);
        stroke: var(--tav-success);
    }
    .tav-plan-shape[data-state="occupied"] {
        fill: var(--tav-info-container);
        stroke: var(--tav-info);
    }
    .tav-plan-shape[data-state="full"] {
        fill: var(--tav-warning-container);
        stroke: var(--tav-warning);
    }
    .tav-plan-shape[data-state="blocked"] {
        fill: var(--tav-secondary-container);
        stroke: var(--tav-secondary);
        stroke-dasharray: 3 3;
    }
    .tav-plan-shape[data-state="over"] {
        fill: var(--tav-error-container);
        stroke: var(--tav-error);
    }
    .tav-plan-shape[data-kind="parking_space"][data-state="occupied"],
    .tav-plan-shape[data-kind="parking_lane"][data-state="occupied"] {
        fill-opacity: 0.75;
    }
    .tav-plan-shape.is-highlighted {
        stroke: var(--tav-primary);
        stroke-width: 4;
        fill-opacity: 0.85;
        animation: tav-plan-pulse 1.4s ease-in-out infinite;
    }
    @keyframes tav-plan-pulse {
        50% {
            stroke-width: 1.5;
        }
    }
    @media (prefers-reduced-motion: reduce) {
        .tav-plan-shape.is-highlighted {
            animation: none;
        }
    }
    .tav-plan-link:focus-visible .tav-plan-shape,
    .tav-plan-link:hover .tav-plan-shape {
        stroke: var(--tav-primary);
        stroke-width: 3;
    }
    .tav-plan-label {
        fill: var(--tav-on-surface);
        stroke: var(--tav-surface);
        stroke-width: 3px;
        paint-order: stroke;
        font-family: inherit;
        font-weight: 600;
        pointer-events: none;
    }
    .tav-plan-marker circle {
        fill: var(--tav-primary);
        stroke: var(--tav-surface);
        stroke-width: 2px;
    }
    .tav-plan-marker[data-kind="fix"] circle {
        fill: var(--tav-error);
    }
    .tav-plan-draft-shape {
        fill: var(--tav-primary-container);
        fill-opacity: 0.35;
        stroke: var(--tav-primary);
        stroke-width: 2;
        stroke-dasharray: 5 3;
    }
    .tav-plan-draft-space {
        fill: none;
        stroke: var(--tav-primary);
        stroke-width: 1;
    }
    .tav-plan-vertex {
        fill: var(--tav-primary);
        stroke: var(--tav-surface);
        stroke-width: 2px;
    }
    .tav-plan-cursor {
        stroke: var(--tav-primary);
        stroke-width: 2;
        fill: none;
    }
    .tav-plan-bar {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 0.5rem;
    }
    .tav-plan-hint {
        flex: 1;
        min-inline-size: 12rem;
        font-size: var(--tav-type-label-size);
        color: var(--tav-on-surface-variant);
    }
    .tav-plan-status {
        font-size: var(--tav-type-label-size);
        color: var(--tav-on-surface-variant);
    }
    .tav-file-remove {
        display: inline-flex;
        border: 0;
        background: transparent;
        color: var(--tav-on-surface-variant);
        cursor: pointer;
        line-height: 1;
    }
    .tav-file-remove:hover {
        color: var(--tav-error);
    }

/*
 * Custom range slider (`<tav-range>`) — a track + fill + thumb we fully control
 * (the native range thumb/track only partly honour CSS). Hidden input carries
 * the value. (js/tav-elements.js)
 */
    tav-range {
        display: block;
        padding-block: 0.5rem;
    }
    .tav-range-track {
        position: relative;
        inline-size: 100%;
        block-size: 0.375rem;
        border-radius: var(--tav-radius-full);
        background: var(--tav-surface-3);
        cursor: pointer;
        touch-action: none;
    }
    .tav-range-fill {
        position: absolute;
        inset-block: 0;
        inset-inline-start: 0;
        border-radius: var(--tav-radius-full);
        background: var(--tav-primary);
    }
    .tav-range-thumb {
        position: absolute;
        inset-block-start: 50%;
        inline-size: 1rem;
        block-size: 1rem;
        border-radius: 50%;
        background: var(--tav-primary);
        transform: translate(-50%, -50%);
        /* Same story as the timeline dot: the ring hides the track behind the
           thumb, so it must be the colour of the GROUND. A slider lives in a
           form, and a form lives on a card — `--tav-surface-1`, not
           `--tav-surface`. Overridable for the rare slider on a bare surface. */
        box-shadow: 0 0 0 3px var(--tav-range-ring, var(--tav-surface-1));
        cursor: grab;
    }
    .tav-range-thumb:active {
        cursor: grabbing;
    }

/*
 * Custom number input (`<tav-number>`) — a token-themed numeric field with our
 * own −/+ steppers (the native spinners are tiny + OS-styled). (js/tav-elements.js)
 */
    tav-number {
        display: block;
    }
    .tav-number {
        display: inline-flex;
        align-items: stretch;
        inline-size: 100%;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        overflow: hidden;
    }
    .tav-number:focus-within {
        border-color: var(--tav-primary);
        box-shadow: 0 0 0 1px var(--tav-primary);
    }
    /* tavuni-docs#3954 — a typed value that is no number, or carries two
       decimal marks, until it is corrected. */
    .tav-number:has(.tav-number-input[aria-invalid="true"]) {
        border-color: var(--tav-error);
        box-shadow: 0 0 0 1px var(--tav-error);
    }
    .tav-number-input {
        flex: 1;
        min-inline-size: 0;
        border: 0;
        padding: 0.5rem 0.75rem;
        background: transparent;
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
        font-variant-numeric: tabular-nums;
        text-align: center;
        appearance: textfield;
        -moz-appearance: textfield;
    }
    /* `<tav-number plain>` — a typed number reads left to right like text. */
    .tav-number.is-plain .tav-number-input {
        text-align: start;
    }
    .tav-number-input:focus {
        outline: none;
    }
    .tav-number-input::-webkit-outer-spin-button,
    .tav-number-input::-webkit-inner-spin-button {
        -webkit-appearance: none;
        margin: 0;
    }
    .tav-number-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: 2.25rem;
        border: 0;
        background: transparent;
        color: var(--tav-on-surface-variant);
        font-size: 1.125rem;
        line-height: 1;
        cursor: pointer;
        user-select: none;
    }
    .tav-number-btn:hover:not(:disabled) {
        background: color-mix(in oklab, var(--tav-on-surface), transparent 92%);
        color: var(--tav-on-surface);
    }
    .tav-number-btn:disabled {
        opacity: 0.4;
        cursor: not-allowed;
    }

/*
 * Steps / stepper (`.tav-steps`) — a static progress indicator for wizards
 * (onboarding). Pure CSS + markup (the app marks each step `is-done`/`is-active`);
 * no JS. Connector + dot + label all read the `--tav-*` roles.
 */
    .tav-steps {
        display: flex;
        align-items: flex-start;
    }
    .tav-step {
        position: relative;
        flex: 1;
        display: flex;
        flex-direction: column;
        align-items: center;
        text-align: center;
    }
    .tav-step:not(:first-child)::before {
        content: "";
        position: absolute;
        inset-block-start: 0.8125rem;
        inset-inline-end: 50%;
        inline-size: 100%;
        block-size: 2px;
        background: var(--tav-outline-variant);
    }
    .tav-step.is-done:not(:first-child)::before,
    .tav-step.is-active:not(:first-child)::before {
        background: var(--tav-primary);
    }
    .tav-step-dot {
        position: relative;
        z-index: 1;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: 1.75rem;
        block-size: 1.75rem;
        border-radius: 50%;
        border: 2px solid var(--tav-outline-variant);
        background: var(--tav-surface);
        color: var(--tav-on-surface-variant);
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-title-weight);
    }
    .tav-step.is-active .tav-step-dot {
        border-color: var(--tav-primary);
        color: var(--tav-primary);
    }
    .tav-step.is-done .tav-step-dot {
        border-color: var(--tav-primary);
        background: var(--tav-primary);
        color: var(--tav-on-primary);
    }
    .tav-step-label {
        margin-block-start: 0.375rem;
        font-size: var(--tav-type-label-size);
        color: var(--tav-on-surface-variant);
    }
    .tav-step.is-active .tav-step-label {
        color: var(--tav-on-surface);
        font-weight: var(--tav-type-title-weight);
    }

/*
 * Tree (`<tav-tree>`) — a hierarchical, expand/collapse + selectable view, built
 * for the Master→Reseller→Tenant party hierarchy. Declarative `<tav-treenode
 * label="" [expanded] [selected]>` children; the element renders the WAI-ARIA
 * tree (roving tabindex, arrow keys). Selected row = `--tav-primary`. (js)
 */
    tav-tree {
        display: block;
    }
    .tav-tree-root,
    .tav-tree-group {
        list-style: none;
        margin: 0;
        padding: 0;
    }
    .tav-tree-row {
        display: flex;
        align-items: center;
        gap: 0.375rem;
        padding: 0.3rem 0.5rem;
        border-radius: var(--tav-radius-xs);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
        cursor: pointer;
    }
    .tav-tree-row:hover {
        background: color-mix(in oklab, var(--tav-on-surface), transparent 94%);
    }
    li[role="treeitem"][aria-selected="true"] > .tav-tree-row {
        background: var(--tav-primary);
        color: var(--tav-on-primary);
    }
    li[role="treeitem"] > .tav-tree-row:focus-visible,
    li[role="treeitem"]:focus-visible > .tav-tree-row {
        outline: 2px solid var(--tav-primary);
        outline-offset: -2px;
    }
    li[role="treeitem"][aria-selected="true"]:focus-visible > .tav-tree-row {
        outline-color: var(--tav-on-primary);
    }
    .tav-tree-toggle {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: 1rem;
        block-size: 1rem;
        flex-shrink: 0;
        color: var(--tav-on-surface-variant);
        transition: transform 0.15s ease;
    }
    li[role="treeitem"][aria-expanded="true"] > .tav-tree-row > .tav-tree-toggle {
        transform: rotate(90deg);
    }
    li[role="treeitem"][aria-selected="true"] > .tav-tree-row > .tav-tree-toggle {
        color: var(--tav-on-primary);
    }
    .tav-tree-label {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

/*
 * Table enhancements (`<tav-table>`) — wraps a `.tav-table` and adds client-side
 * column SORT (`<th data-sort[="number"]>`) + an optional text FILTER (`filter`
 * attribute). The active sort arrow + focus ring read `--tav-primary`. The JS
 * (tav-elements.js) reorders/hides the already-rendered rows; for large sets the
 * server still paginates. (CSS token-only.)
 */
    tav-table {
        display: block;
    }
    .tav-table-filter {
        margin-block-end: 0.625rem;
        max-inline-size: 18rem;
    }
    .tav-table th.tav-th-sort {
        cursor: pointer;
        user-select: none;
        white-space: nowrap;
    }
    .tav-table th.tav-th-sort::after {
        content: "↕";
        margin-inline-start: 0.25rem;
        font-size: 0.85em;
        opacity: 0.35;
    }
    .tav-table th.tav-th-sort[aria-sort="ascending"]::after {
        content: "↑";
        color: var(--tav-primary);
        opacity: 1;
    }
    .tav-table th.tav-th-sort[aria-sort="descending"]::after {
        content: "↓";
        color: var(--tav-primary);
        opacity: 1;
    }
    .tav-table th.tav-th-sort:focus-visible {
        outline: 2px solid var(--tav-primary);
        outline-offset: -2px;
    }

/*
 * Tooltip (`[data-tav-tooltip]`) — a themed hover/focus tip on any element,
 * replacing the slow OS `title` bubble. One reused floating node, positioned by
 * the JS (tav-elements.js). Neutral surface (a tip is info, not brand).
 */
    .tav-tooltip {
        position: fixed;
        z-index: 100;
        max-inline-size: 16rem;
        padding: 0.35rem 0.6rem;
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface-3);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-label-size);
        line-height: 1.35;
        box-shadow: var(--tav-elevation-2);
        pointer-events: none;
    }

/*
 * Popconfirm (`[data-tav-confirm]`) — an inline "are you sure?" popover that
 * defers a button's action (delete / destructive) until confirmed. The JS
 * intercepts the click, shows this, and re-fires on confirm.
 */
    .tav-confirm {
        position: fixed;
        z-index: 100;
        inline-size: 15rem;
        padding: 0.75rem;
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        border: 1px solid var(--tav-outline-variant);
        box-shadow: var(--tav-elevation-3);
    }
    .tav-confirm-msg {
        display: flex;
        gap: 0.5rem;
        margin-block-end: 0.625rem;
        font-size: var(--tav-type-body-size);
        color: var(--tav-on-surface);
    }
    .tav-confirm-icon {
        flex-shrink: 0;
        inline-size: 1.1rem;
        block-size: 1.1rem;
        color: var(--tav-warning);
    }
    .tav-confirm-actions {
        display: flex;
        justify-content: flex-end;
        gap: 0.5rem;
    }

/*
 * Drawer (`<tav-drawer id title>`) — a slide-in side panel + backdrop, opened by
 * `[data-tav-drawer="id"]` triggers. For detail/edit without leaving the list.
 * Token-only (the backdrop scrim is a color-mix of on-surface). (js)
 */
    .tav-drawer-backdrop {
        position: fixed;
        inset: 0;
        z-index: 90;
        background: color-mix(in oklab, var(--tav-on-surface), transparent 55%);
        opacity: 0;
        transition: opacity 0.2s ease;
    }
    .tav-drawer-backdrop.is-open {
        opacity: 1;
    }
    .tav-drawer-panel {
        position: fixed;
        inset-block: 0;
        inset-inline-end: 0;
        z-index: 91;
        inline-size: min(26rem, 100%);
        display: flex;
        flex-direction: column;
        background: var(--tav-surface);
        box-shadow: var(--tav-elevation-3);
        transform: translateX(100%);
        transition: transform 0.25s ease;
    }
    .tav-drawer-panel.is-open {
        transform: translateX(0);
    }
    .tav-drawer-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        padding: 1rem 1.25rem;
        border-block-end: 1px solid var(--tav-outline-variant);
    }
    .tav-drawer-title {
        margin: 0;
        font-size: var(--tav-type-title-size);
        font-weight: var(--tav-type-title-weight);
        color: var(--tav-on-surface);
    }
    .tav-drawer-close {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: 2rem;
        block-size: 2rem;
        flex-shrink: 0;
        border: 0;
        border-radius: var(--tav-radius-sm);
        background: transparent;
        color: var(--tav-on-surface-variant);
        cursor: pointer;
    }
    .tav-drawer-close:hover {
        background: color-mix(in oklab, var(--tav-on-surface), transparent 92%);
        color: var(--tav-on-surface);
    }
    .tav-drawer-body {
        flex: 1;
        overflow-y: auto;
        padding: 1.25rem;
    }

/*
 * Cascader (`<tav-cascader>`) — multi-level selection in one dropdown (columns),
 * for hierarchical picks like Reseller → Tenant. Declarative nested `<tav-option
 * value label>`; value = the leaf, label = the path. Active column item + leaf
 * selection read `--tav-primary`. (js)
 */
    tav-cascader {
        position: relative;
        display: block;
    }
    .tav-cascader-trigger {
        display: inline-flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.5rem;
        width: 100%;
        padding: 0.5rem 0.75rem;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
        text-align: left;
        cursor: pointer;
    }
    .tav-cascader-trigger[aria-expanded="true"] {
        border-color: var(--tav-primary);
        box-shadow: 0 0 0 1px var(--tav-primary);
    }
    .tav-cascader-trigger.is-empty {
        color: var(--tav-on-surface-variant);
    }
    .tav-cascader-caret {
        inline-size: 1rem;
        block-size: 1rem;
        flex-shrink: 0;
        color: var(--tav-on-surface-variant);
    }
    .tav-cascader-popup {
        position: absolute;
        z-index: 50;
        inset-block-start: calc(100% + 0.25rem);
        inset-inline-start: 0;
        display: flex;
        max-block-size: 16rem;
        background: var(--tav-surface);
        border: 1px solid var(--tav-outline-variant);
        border-radius: var(--tav-radius-sm);
        box-shadow: var(--tav-elevation-2);
    }
    .tav-cascader-col {
        min-inline-size: 11rem;
        overflow-y: auto;
        padding: 0.25rem;
        border-inline-end: 1px solid var(--tav-outline-variant);
    }
    .tav-cascader-col:last-child {
        border-inline-end: 0;
    }
    .tav-cascader-option {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.5rem;
        padding: 0.4rem 0.6rem;
        border-radius: var(--tav-radius-xs);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
        cursor: pointer;
    }
    .tav-cascader-option:hover {
        background: color-mix(in oklab, var(--tav-on-surface), transparent 94%);
    }
    .tav-cascader-option.is-active {
        background: color-mix(in oklab, var(--tav-primary), transparent 88%);
    }
    .tav-cascader-option.is-leaf-selected {
        color: var(--tav-primary);
        font-weight: var(--tav-type-title-weight);
    }
    .tav-cascader-opt-caret {
        inline-size: 0.85rem;
        block-size: 0.85rem;
        flex-shrink: 0;
        color: var(--tav-on-surface-variant);
    }

/*
 * Collapse / Accordion — a styled native `<details class="tav-collapse">`. No JS;
 * the chevron rotates on `[open]`.
 */
    .tav-collapse {
        border: 1px solid var(--tav-outline-variant);
        border-radius: var(--tav-radius-sm);
        overflow: hidden;
    }
    .tav-collapse + .tav-collapse {
        margin-block-start: 0.5rem;
    }
    .tav-collapse > summary {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.5rem;
        padding: 0.75rem 1rem;
        background: var(--tav-surface-1);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
        font-weight: var(--tav-type-title-weight);
        cursor: pointer;
        list-style: none;
    }
    .tav-collapse > summary::-webkit-details-marker {
        display: none;
    }
    .tav-collapse > summary::after {
        content: "›";
        color: var(--tav-on-surface-variant);
        font-size: 1.25em;
        line-height: 1;
        transition: transform 0.15s ease;
    }
    .tav-collapse[open] > summary::after {
        transform: rotate(90deg);
    }
    .tav-collapse-body {
        padding: 0.75rem 1rem;
        border-block-start: 1px solid var(--tav-outline-variant);
        color: var(--tav-on-surface);
        font-size: var(--tav-type-body-size);
    }

/*
 * Result (`.tav-result.tav-result-{success,error,info}`) — a full-width
 * success / error / empty state (e.g. "Payment received", a 404). Static markup.
 */
    .tav-result {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 0.4rem;
        padding: 2.5rem 1.5rem;
        text-align: center;
    }
    .tav-result-icon {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: 3rem;
        block-size: 3rem;
        margin-block-end: 0.5rem;
        border-radius: 50%;
    }
    .tav-result-success .tav-result-icon {
        background: var(--tav-success-container);
        color: var(--tav-on-success-container);
    }
    .tav-result-error .tav-result-icon {
        background: var(--tav-error-container);
        color: var(--tav-on-error-container);
    }
    .tav-result-info .tav-result-icon {
        background: var(--tav-primary-container);
        color: var(--tav-on-primary-container);
    }
    .tav-result-title {
        font-size: var(--tav-type-headline-size);
        font-weight: var(--tav-type-title-weight);
        color: var(--tav-on-surface);
    }
    .tav-result-text {
        max-inline-size: 28rem;
        font-size: var(--tav-type-body-size);
        color: var(--tav-on-surface-variant);
    }
    .tav-result-actions {
        display: flex;
        gap: 0.5rem;
        margin-block-start: 0.75rem;
    }

/*
 * Rate (`<tav-rate>`) — star rating. Filled stars are brand, empty are outline;
 * the group carries the focus ring (slider semantics live on it).
 */
    .tav-rate {
        display: inline-flex;
        gap: 0.15rem;
        font-size: 1.5rem;
        line-height: 1;
        cursor: pointer;
        border-radius: var(--tav-radius-sm);
    }
    .tav-rate:focus-visible {
        outline: 2px solid var(--tav-primary);
        outline-offset: 3px;
    }
    /* An empty star has to be distinguishable from the page behind it, because
       the row of stars IS the value — `aria-hidden` on each one means a screen
       reader gets it from the slider, but a sighted reader gets it only here.
       `--tav-outline-variant` measured 1.46:1; 1.4.11 asks 3:1 for a graphical
       object you need to read the content. `--tav-outline` measures 4.08:1. */
    .tav-rate-star {
        color: var(--tav-outline);
        transition: color 0.1s ease;
    }
    .tav-rate-star.is-on {
        color: var(--tav-primary);
    }

/*
 * Tag input (`<tav-tag-input>`) — chips in a text field; chips use the brand
 * container tone, the field grows to fill.
 */
    .tav-taginput {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 0.35rem;
        min-block-size: 2.5rem;
        padding: 0.3rem 0.5rem;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        cursor: text;
    }
    .tav-taginput:focus-within {
        border-color: var(--tav-primary);
        box-shadow: 0 0 0 3px color-mix(in oklab, var(--tav-primary) 18%, transparent);
    }
    .tav-taginput-field {
        flex: 1;
        min-inline-size: 6rem;
        border: 0;
        outline: 0;
        background: transparent;
        color: var(--tav-on-surface);
        font: inherit;
    }
    .tav-tag {
        display: inline-flex;
        align-items: center;
        gap: 0.25rem;
        padding: 0.1rem 0.2rem 0.1rem 0.55rem;
        border-radius: 999px;
        background: var(--tav-primary-container);
        color: var(--tav-on-primary-container);
        font-size: var(--tav-type-label-size);
    }
    .tav-tag-x {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: 1.15rem;
        block-size: 1.15rem;
        padding: 0;
        border: 0;
        border-radius: 50%;
        background: transparent;
        color: inherit;
        cursor: pointer;
    }
    .tav-tag-x:hover {
        background: color-mix(in oklab, var(--tav-on-primary-container) 20%, transparent);
    }
    .tav-tag-x svg {
        inline-size: 0.8rem;
        block-size: 0.8rem;
    }

/*
 * Autocomplete (`<tav-autocomplete>`) — free-text field with a filtered popup;
 * active/hover option uses the brand container tone.
 */
    .tav-ac {
        position: relative;
    }
    .tav-ac-field {
        inline-size: 100%;
        padding: 0.5rem 0.75rem;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        font: inherit;
    }
    .tav-ac-field:focus {
        outline: 0;
        border-color: var(--tav-primary);
        box-shadow: 0 0 0 3px color-mix(in oklab, var(--tav-primary) 18%, transparent);
    }
    .tav-ac-list {
        position: absolute;
        inset-inline: 0;
        inset-block-start: calc(100% + 4px);
        z-index: 30;
        max-block-size: 14rem;
        overflow: auto;
        padding: 0.25rem;
        background: var(--tav-surface);
        border: 1px solid var(--tav-outline-variant);
        border-radius: var(--tav-radius-sm);
        /* elevation-2 like every sibling panel. This was the last hand-rolled
           shadow in the sheet: `tav-select-listbox`, `tav-date-popup` and
           `tav-menu` all take the token, and a dropdown that sits one step
           higher than the other dropdowns reads as a rendering accident rather
           than a decision (review 2026-08-24 §E, "two elevation systems"). */
        box-shadow: var(--tav-elevation-2);
    }
    .tav-ac-option {
        padding: 0.45rem 0.6rem;
        border-radius: calc(var(--tav-radius-sm) - 2px);
        color: var(--tav-on-surface);
        cursor: pointer;
    }
    .tav-ac-option:hover,
    .tav-ac-option.is-active {
        background: var(--tav-primary-container);
        color: var(--tav-on-primary-container);
    }

/*
 * Time (`<tav-time>`) — HH:MM segmented spinbuttons; tabular figures, each
 * segment focusable, the active segment carries the ring.
 */
    .tav-time {
        display: inline-flex;
        align-items: center;
        gap: 0.1rem;
        padding: 0.35rem 0.55rem;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        font-variant-numeric: tabular-nums;
    }
    /* tav-datetime lays its child <tav-date> + <tav-time> out side by side. */
    .tav-datetime {
        display: inline-flex;
        align-items: center;
        gap: 0.5rem;
        flex-wrap: wrap;
    }
    .tav-time-seg {
        min-inline-size: 1.6rem;
        padding: 0.1rem 0.25rem;
        text-align: center;
        color: var(--tav-on-surface);
        border-radius: calc(var(--tav-radius-sm) - 3px);
        cursor: ns-resize;
    }
    /* An unanswered segment (`--`): a placeholder, not a value. */
    .tav-time-seg.is-empty {
        color: var(--tav-on-surface-variant);
    }
    .tav-time-seg:hover {
        background: var(--tav-surface-2);
    }
    .tav-time-seg:focus-visible {
        outline: 2px solid var(--tav-primary);
        outline-offset: 1px;
    }
    .tav-time-sep {
        color: var(--tav-on-surface-variant);
    }

/*
 * Transfer (`<tav-transfer>`) — dual list with move buttons; marked rows and the
 * hovered move button use the brand container tone.
 */
    .tav-transfer {
        display: grid;
        grid-template-columns: 1fr auto 1fr;
        gap: 0.75rem;
        align-items: stretch;
    }
    .tav-transfer-pane {
        display: flex;
        flex-direction: column;
        min-block-size: 11rem;
        border: 1px solid var(--tav-outline-variant);
        border-radius: var(--tav-radius-sm);
        overflow: hidden;
    }
    .tav-transfer-title {
        padding: 0.5rem 0.75rem;
        background: var(--tav-surface-1);
        color: var(--tav-on-surface-variant);
        font-size: var(--tav-type-label-size);
        font-weight: var(--tav-type-title-weight);
        border-block-end: 1px solid var(--tav-outline-variant);
    }
    .tav-transfer-list {
        flex: 1;
        list-style: none;
        margin: 0;
        padding: 0.25rem;
        overflow: auto;
    }
    .tav-transfer-item {
        padding: 0.4rem 0.6rem;
        border-radius: calc(var(--tav-radius-sm) - 2px);
        color: var(--tav-on-surface);
        cursor: pointer;
    }
    .tav-transfer-item:hover {
        background: var(--tav-surface-2);
    }
    .tav-transfer-item.is-marked {
        background: var(--tav-primary-container);
        color: var(--tav-on-primary-container);
    }
    .tav-transfer-item:focus-visible {
        outline: 2px solid var(--tav-primary);
        outline-offset: -2px;
    }
    .tav-transfer-mid {
        display: flex;
        flex-direction: column;
        justify-content: center;
        gap: 0.5rem;
    }
    .tav-transfer-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: 2.25rem;
        block-size: 2.25rem;
        border: 1px solid var(--tav-outline);
        border-radius: var(--tav-radius-sm);
        background: var(--tav-surface);
        color: var(--tav-on-surface);
        cursor: pointer;
    }
    .tav-transfer-btn:hover:not(:disabled) {
        background: var(--tav-primary-container);
        color: var(--tav-on-primary-container);
        border-color: transparent;
    }
    .tav-transfer-btn:disabled {
        opacity: 0.4;
        cursor: not-allowed;
    }
    .tav-transfer-btn svg {
        inline-size: 1.1rem;
        block-size: 1.1rem;
    }

/*
 * Unified disabled state for every form-associated custom element. The base
 * class reflects the `disabled` property to the host attribute, so `[disabled]`
 * dims + inerts the whole control uniformly — one rule, every surface (also
 * fires for a `<fieldset disabled>` ancestor via `formDisabledCallback`).
 */
    :is(
        tav-select,
        tav-date,
        tav-color,
        tav-range,
        tav-number,
        tav-time,
        tav-rate,
        tav-tag-input,
        tav-autocomplete,
        tav-cascader,
        tav-transfer
    )[disabled] {
        opacity: 0.55;
        pointer-events: none;
    }

/* ════════════════════════════════════════════════════════════════════════
   CONSOLE VOCABULARY — components ported from the console's component
   layer (console input.css) into the shared tav-ui set, re-tokenised onto
   `--tav-*`. The console authored these as `tavuni-*`; the big-bang migration
   (ADR-0361) renamed them to `tav-*`. Token-only — no
   build step, so they render identically in either host.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Table cell colour variants ──────────────────────────────────────────
   The base table look comes from the element-scoped `.tav-table th/td/tr`
   rules above: a `<table class="tav-table">` styles its bare cells, so the
   renamed per-cell `.tav-th`/`.tav-td`/`.tav-tr`/`.tav-thead`/`.tav-tbody`
   classes need no rule of their own (inert by design). Only the colour
   *overrides* are declared, and they must out-rank `.tav-table td` (0,1,1) —
   `td.tav-td-muted` matches that specificity and wins on source order. */
td.tav-td-muted {
    color: var(--tav-on-surface-variant);
}
td.tav-td-mono {
    color: var(--tav-on-surface-variant);
    font-family: ui-monospace, monospace;
    font-size: var(--tav-type-label-size);
}

/* ── Pivot table with sticky first/last columns (Translation Manager) ────
   Self-contained (does not lean on `.tav-table`): base look + pinned code /
   actions columns so a wide one-column-per-locale grid keeps the row anchor
   and the action buttons in view while the middle scrolls. */
.tav-table-pivot {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--tav-type-body-size);
}
.tav-table-pivot thead {
    background: var(--tav-surface-2);
}
.tav-table-pivot th {
    padding: 0.625rem 1rem;
    text-align: left;
    font-size: var(--tav-type-label-size);
    font-weight: var(--tav-type-title-weight);
    color: var(--tav-on-surface-variant);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.tav-table-pivot td {
    padding: 0.625rem 1rem;
    border-top: 1px solid var(--tav-outline-variant);
    color: var(--tav-on-surface);
}
.tav-table-pivot .tav-th-sticky-left,
.tav-table-pivot .tav-td-sticky-left {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--tav-surface);
    box-shadow: inset -1px 0 0 0 var(--tav-outline-variant);
}
.tav-table-pivot .tav-th-sticky-right,
.tav-table-pivot .tav-td-sticky-right {
    position: sticky;
    right: 0;
    z-index: 1;
    background: var(--tav-surface);
    box-shadow: inset 1px 0 0 0 var(--tav-outline-variant);
}
.tav-table-pivot thead .tav-th-sticky-left,
.tav-table-pivot thead .tav-th-sticky-right {
    z-index: 2;
    background: var(--tav-surface-2);
}
.tav-table-pivot tr:hover .tav-td-sticky-left,
.tav-table-pivot tr:hover .tav-td-sticky-right {
    background: color-mix(
        in oklab,
        var(--tav-surface),
        var(--tav-on-surface) calc(var(--tav-state-hover) * 100%)
    );
}

/* ── Card footer (header / body / title already shared above) ──────────── */
.tav-card-footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
    padding: 0.875rem 1.25rem;
    border-top: 1px solid var(--tav-outline-variant);
}

/* ── Sidebar section heading ─────────────────────────────────────────────
   Uppercase group label between nav clusters. The muted role is the ≥4.5:1
   `on-surface-variant` (the console bumped this off /40 for axe-core AA). */
.tav-sidebar-section {
    padding: 1.5rem 0.75rem 0.5rem;
    font-size: var(--tav-type-label-size);
    font-weight: var(--tav-type-title-weight);
    color: var(--tav-on-surface-variant);
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

/* ── Active text-link for sub-nav tabs — pairs with `.tav-link` ─────────── */
.tav-link-active {
    color: var(--tav-on-surface);
    font-weight: var(--tav-type-title-weight);
    border-bottom: 2px solid var(--tav-primary);
    padding-bottom: 0.125rem;
}

/* ── Badge variants (base + success/warning/error/info/neutral above) ──── */
.tav-badge-secondary {
    background: var(--tav-secondary-container);
    color: var(--tav-on-secondary-container);
}

    /* The variant the family was missing. Every filter chip that marks the
       ACTIVE selection hand-rolled `tav-bg-tavuni-600 tav-text-white` because
       there was nothing to call — 103 times across the repo. A fixed white
       foreground on a brand-derived background is unreadable the moment a
       tenant picks a light primary; `--tav-on-primary-container` is computed
       against its own background, so it cannot be. Container tones, like every
       sibling above: a chip marks state, it does not shout. */
    .tav-badge-primary { background: var(--tav-primary-container); color: var(--tav-on-primary-container); }

/* ── Inline code — sibling of `.tav-kbd` (keystrokes) for code spans ───── */
.tav-code {
    padding: 0.0625rem 0.375rem;
    border-radius: var(--tav-radius-xs);
    background: var(--tav-surface-2);
    color: var(--tav-on-surface-variant);
    font-family: ui-monospace, monospace;
    font-size: 0.8125rem;
}

/* ── Locale picker (Translation Manager — `<details>`-driven, no JS) ──────
   `<details class="tav-locale-picker">` with a summary chip and an absolute
   popout on a raised surface tier so it reads against both the page and the
   card it sits inside. The container is the positioning context. */
.tav-locale-picker {
    position: relative;
    display: inline-block;
}
.tav-locale-picker > .tav-locale-picker-summary {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--tav-outline-variant);
    border-radius: var(--tav-radius-sm);
    background: var(--tav-surface);
    color: var(--tav-on-surface);
    font-size: var(--tav-type-body-size);
    font-weight: var(--tav-type-label-weight);
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
    list-style: none;
}
.tav-locale-picker > .tav-locale-picker-summary::-webkit-details-marker {
    display: none;
}
.tav-locale-picker[open] > .tav-locale-picker-summary {
    background: var(--tav-surface-1);
}
.tav-locale-picker-badge {
    padding: 0.0625rem 0.375rem;
    border-radius: var(--tav-radius-xs);
    background: var(--tav-surface-variant);
    color: var(--tav-on-surface-variant);
    font-family: ui-monospace, monospace;
    font-size: var(--tav-type-label-size);
}
.tav-locale-picker-chevron {
    color: var(--tav-on-surface-variant);
    transition: transform 0.15s ease;
}
.tav-locale-picker[open] .tav-locale-picker-chevron {
    transform: rotate(180deg);
}
.tav-locale-picker-popout {
    position: absolute;
    z-index: 20;
    margin-top: 0.5rem;
    min-width: 16rem;
    max-height: 18rem;
    padding: 0.75rem;
    overflow-y: auto;
    border: 1px solid var(--tav-outline-variant);
    border-radius: var(--tav-radius-md);
    background: var(--tav-surface-3);
    box-shadow: var(--tav-elevation-3);
}
.tav-locale-picker-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--tav-outline-variant);
    font-size: var(--tav-type-label-size);
}
.tav-locale-picker-list {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.tav-locale-picker-row {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.125rem 0.25rem;
    border-radius: var(--tav-radius-xs);
    font-size: var(--tav-type-body-size);
    white-space: nowrap;
    cursor: pointer;
}
.tav-locale-picker-row:hover {
    background: color-mix(
        in oklab,
        transparent,
        var(--tav-on-surface) calc(var(--tav-state-hover) * 100%)
    );
}

/* ── Size & style variants (btn-sm/-xs/-outline, badge-sm/
   -outline, input-sm) ───────────────────── */
/* Dense row action — table cells and toolbars, where the control is secondary. */
.tav-btn-sm {
    min-height: var(--tav-control-h-sm);
    padding: 0.25rem 0.625rem;
    font-size: var(--tav-type-label-size);
}
.tav-btn-xs {
    min-height: var(--tav-control-h-xs);
    padding: 0.125rem 0.5rem;
    font-size: 0.6875rem;
}
/* Large CTA — marketing hero/pricing, and the TOUCH size. 44px is the Apple HIG
   minimum target; `--tav-control-h-lg` is what a finger-first shell promotes to
   its default so every control clears the bar at once (B-828). */
.tav-btn-lg {
    min-height: var(--tav-control-h-lg);
    padding: 0.625rem 1.25rem;
    font-size: var(--tav-type-title-size);
}
/* Icon-only square button. */
.tav-btn-icon {
    padding: 0.5rem;
    aspect-ratio: 1 / 1;
}
/* Neutral outlined button: transparent fill, visible
   edge, subtle hover wash — distinct from the filled primary/secondary. */
.tav-btn-outline {
    background: transparent;
    border-color: var(--tav-outline);
    color: var(--tav-on-surface);
}
.tav-btn-outline:hover {
    background: color-mix(
        in oklab,
        transparent,
        var(--tav-on-surface) calc(var(--tav-state-hover) * 100%)
    );
    border-color: var(--tav-on-surface);
}
.tav-badge-sm {
    padding: 0.0625rem 0.375rem;
    font-size: 0.6875rem;
}
/* Outlined badge: edge, no fill. */
.tav-badge-outline {
    background: transparent;
    border: 1px solid var(--tav-outline-variant);
    color: var(--tav-on-surface-variant);
}
.tav-input-sm {
    padding: 0.375rem 0.625rem;
    font-size: var(--tav-type-label-size);
}

/* ── Native <dialog> modal ──────
   The browser supplies centring + a ::backdrop + Esc-to-close for a
   `<dialog>` opened via showModal(); we only reset its chrome and tint the
   backdrop. The inner card keeps `.tav-modal`; the button row is
   `.tav-modal-actions`; a `<form method="dialog" class="tav-dialog-backdrop">`
   stays the click-outside-to-close catcher. */
dialog.tav-modal-dialog {
    max-width: min(32rem, 92vw);
    max-height: 90vh;
    margin: auto;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    overflow: visible;
}
dialog.tav-modal-dialog::backdrop {
    background: color-mix(in oklab, var(--tav-on-surface) 45%, transparent);
}
.tav-modal-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1rem;
}
.tav-dialog-backdrop {
    position: fixed;
    inset: 0;
    z-index: -1;
}

/* ── Form dialog (create / edit in a pop-up) ──────
   `ui::form_dialog`. Three bands: a head that says what is being made and
   why, a body of fields, and a foot that stays put while a long body
   scrolls.

   Wider than the confirm dialog: an address is a street, a number and a bus
   on one line, and at 32rem the number field wrapped under the street.

   The DIALOG scrolls, not the body. A scrolling body is a clipping ancestor,
   and the address typeahead's suggestion list is an absolutely positioned
   child of a field in that body — it was cut off at the body's edge. */
dialog.tav-form-dialog {
    width: min(36rem, 92vw);
    max-width: min(36rem, 92vw);
    overflow-y: auto;
}
.tav-form-dialog > .tav-modal {
    max-width: none;
    overflow: visible;
}
.tav-form-dialog-head {
    padding: 1.25rem 1.5rem 0;
}
.tav-form-dialog-title {
    font-size: var(--tav-type-title-size);
    line-height: var(--tav-type-title-line);
    font-weight: var(--tav-type-title-weight);
    color: var(--tav-on-surface);
    text-wrap: balance;
}
.tav-form-dialog-lead {
    margin-top: 0.25rem;
    max-width: 60ch;
    font-size: var(--tav-type-body-size);
    line-height: var(--tav-type-body-line);
    color: var(--tav-on-surface-variant);
}
/* The refusal of the attempt that just failed, set by `Tavuni.formDialog.settle`. */
.tav-form-dialog-error {
    margin-top: 0.75rem;
    padding: 0.5rem 0.75rem;
    border-radius: var(--tav-radius-sm);
    background: var(--tav-error-container);
    color: var(--tav-on-error-container);
    font-size: var(--tav-type-body-size);
    line-height: var(--tav-type-body-line);
    overflow-wrap: anywhere;
}
.tav-form-dialog-body {
    display: grid;
    gap: 1rem;
    padding: 1.25rem 1.5rem;
}
/* A group of fields inside the body that needs its own scope — the address
   typeahead's Alpine root — keeps the body's rhythm. */
.tav-form-dialog-fields {
    display: grid;
    gap: 1rem;
}
/* A read-only fact inside an edit dialog: what this record IS and cannot be
   changed into something else here (the type of an identifier, the other
   party of a relationship). Text, not a disabled input — a greyed-out field
   invites the question of how to enable it. */
.tav-form-dialog-fact {
    display: grid;
    gap: 0.125rem;
}
.tav-form-dialog-fact > dt {
    font-size: var(--tav-type-label-size);
    font-weight: var(--tav-type-label-weight);
    color: var(--tav-on-surface-variant);
}
.tav-form-dialog-fact > dd {
    font-size: var(--tav-type-body-size);
    color: var(--tav-on-surface);
    overflow-wrap: anywhere;
}
.tav-form-dialog-foot {
    position: sticky;
    bottom: 0;
    margin-top: 0;
    padding: 0.875rem 1.5rem;
    border-top: 1px solid var(--tav-outline-variant);
    background: var(--tav-surface-1);
}
/* Fields that belong on one line (street · number · bus; postcode · city).
   Wraps under ~28rem, so on a phone each field still gets a full row. */
.tav-form-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}
.tav-form-row > .tav-field {
    flex: 1 1 10rem;
    min-width: 0;
}
.tav-form-row > .tav-field-narrow {
    flex: 0 1 6.5rem;
}

/* ── Add link ──────
   The quiet way into a form dialog, under the list it adds to. Aligned with
   the list's labels — not indented, no "+" glyph, no button chrome: on a
   fiche with five sections, five outlined buttons outshouted the data they
   sat under. Still a real <button>, so it has a focus ring and a hit area. */
.tav-add-link {
    display: inline-flex;
    align-items: center;
    margin-top: 0.6875rem;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 500;
    text-decoration: none;
    color: var(--tav-primary);
    cursor: pointer;
}
.tav-add-link:hover {
    text-decoration: underline;
    text-underline-offset: 0.2em;
}
.tav-add-link:focus-visible {
    outline: 2px solid var(--tav-primary);
    outline-offset: 2px;
    border-radius: var(--tav-radius-xs);
}

/* ════════════════════════════════════════════════════════════════════════
   v2 COMPONENTS — gaps surfaced by the shadcn comparison (2026-06-19).
   Token-only, unlayered, house style. The interactive ones are driven by Web
   Components in tav-elements.js (light DOM, so these classes style them); the
   rest are pure CSS.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Input group (input + leading/trailing addons) ──────────────────────
   <div class="tav-input-group"><span class="tav-input-addon">€</span>
     <input class="tav-input"><button class="tav-btn tav-btn-primary">Go</button></div> */
.tav-input-group {
    display: flex;
    align-items: stretch;
}
.tav-input-group > * {
    border-radius: 0;
}
.tav-input-group > :first-child {
    border-top-left-radius: var(--tav-radius-sm);
    border-bottom-left-radius: var(--tav-radius-sm);
}
.tav-input-group > :last-child {
    border-top-right-radius: var(--tav-radius-sm);
    border-bottom-right-radius: var(--tav-radius-sm);
}
.tav-input-group > :not(:first-child) {
    margin-left: -1px;
}
.tav-input-group .tav-input:focus {
    z-index: 1;
}
.tav-input-addon {
    display: inline-flex;
    align-items: center;
    padding: 0 0.75rem;
    border: 1px solid color-mix(in oklab, var(--tav-primary) 28%, var(--tav-outline));
    background: var(--tav-surface-1);
    color: var(--tav-on-surface-variant);
    font-size: var(--tav-type-body-size);
    white-space: nowrap;
}

/* ── Button group (joined buttons) ──────────────────────────────────── */
.tav-button-group {
    display: inline-flex;
}
.tav-button-group > .tav-btn {
    border-radius: 0;
}
.tav-button-group > .tav-btn:first-child {
    border-top-left-radius: var(--tav-radius-md);
    border-bottom-left-radius: var(--tav-radius-md);
}
.tav-button-group > .tav-btn:last-child {
    border-top-right-radius: var(--tav-radius-md);
    border-bottom-right-radius: var(--tav-radius-md);
}
.tav-button-group > .tav-btn:not(:first-child) {
    margin-left: -1px;
}

/* ── Accordion (<details>-based; <tav-accordion single-open> coordinates) ─ */
.tav-accordion {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--tav-outline-variant);
    border-radius: var(--tav-radius-md);
    overflow: hidden;
}
.tav-accordion-item + .tav-accordion-item {
    border-top: 1px solid var(--tav-outline-variant);
}
.tav-accordion-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    font-weight: var(--tav-type-title-weight);
    color: var(--tav-on-surface);
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.tav-accordion-trigger::-webkit-details-marker {
    display: none;
}
.tav-accordion-trigger::after {
    content: "";
    flex-shrink: 0;
    width: 0.5rem;
    height: 0.5rem;
    border-right: 2px solid var(--tav-on-surface-variant);
    border-bottom: 2px solid var(--tav-on-surface-variant);
    transform: rotate(45deg);
    transition: transform 0.15s ease;
}
.tav-accordion-item[open] > .tav-accordion-trigger::after {
    transform: rotate(-135deg);
}
.tav-accordion-trigger:hover {
    background: color-mix(in oklab, transparent, var(--tav-on-surface) calc(var(--tav-state-hover) * 100%));
}
.tav-accordion-body {
    padding: 0 1rem 0.875rem;
    color: var(--tav-on-surface-variant);
    font-size: var(--tav-type-body-size);
}

/* ── Hover card (CSS reveal on hover / focus-within — no JS) ─────────── */
.tav-hover-card {
    position: relative;
    display: inline-block;
}
.tav-hover-card-panel {
    position: absolute;
    top: calc(100% + 0.5rem);
    left: 0;
    z-index: 30;
    min-width: 16rem;
    max-width: 22rem;
    padding: 0.875rem 1rem;
    border: 1px solid var(--tav-outline-variant);
    border-radius: var(--tav-radius-md);
    background: var(--tav-surface-1);
    box-shadow: var(--tav-elevation-3);
    color: var(--tav-on-surface);
    font-size: var(--tav-type-body-size);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-0.25rem);
    transition:
        opacity 0.15s ease,
        transform 0.15s ease,
        visibility 0.15s;
}
.tav-hover-card:hover .tav-hover-card-panel,
.tav-hover-card:focus-within .tav-hover-card-panel {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

/* ── Carousel (CSS scroll-snap; <tav-carousel> adds buttons + dots) ──── */
.tav-carousel {
    position: relative;
}
.tav-carousel-track {
    display: flex;
    gap: 1rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
}
.tav-carousel-track::-webkit-scrollbar {
    display: none;
}
.tav-carousel-item {
    flex: 0 0 100%;
    scroll-snap-align: start;
}
.tav-carousel-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: 1px solid var(--tav-outline-variant);
    border-radius: var(--tav-radius-full);
    background: var(--tav-surface);
    color: var(--tav-on-surface);
    cursor: pointer;
    box-shadow: var(--tav-elevation-2);
}
.tav-carousel-btn[data-dir="prev"] {
    left: 0.5rem;
}
.tav-carousel-btn[data-dir="next"] {
    right: 0.5rem;
}
.tav-carousel-btn[disabled] {
    opacity: 0.4;
    pointer-events: none;
}
.tav-carousel-dots {
    display: flex;
    justify-content: center;
    gap: 0.375rem;
    margin-top: 0.75rem;
}
.tav-carousel-dot {
    width: 0.5rem;
    height: 0.5rem;
    padding: 0;
    border: 0;
    border-radius: var(--tav-radius-full);
    background: var(--tav-outline-variant);
    cursor: pointer;
}
.tav-carousel-dot.is-active {
    background: var(--tav-primary);
}

/* ── Popover (<tav-popover> positions .tav-popover-panel) ────────────── */
.tav-popover-panel {
    position: absolute;
    z-index: 40;
    min-width: 12rem;
    padding: 0.75rem;
    border: 1px solid var(--tav-outline-variant);
    border-radius: var(--tav-radius-md);
    background: var(--tav-surface-1);
    box-shadow: var(--tav-elevation-3);
    color: var(--tav-on-surface);
    font-size: var(--tav-type-body-size);
}
.tav-popover-panel[hidden] {
    display: none;
}

/* ── Toast (<tav-toast-region> renders .tav-toast on the `tav-toast` event) ─ */
.tav-toast-region {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 80;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    max-width: min(24rem, calc(100vw - 2rem));
    pointer-events: none;
}
.tav-toast {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    padding: 0.75rem 0.875rem;
    border: 1px solid var(--tav-outline-variant);
    border-left-width: 3px;
    border-radius: var(--tav-radius-md);
    background: var(--tav-surface-1);
    box-shadow: var(--tav-elevation-3);
    color: var(--tav-on-surface);
    font-size: var(--tav-type-body-size);
    pointer-events: auto;
    animation: tav-toast-in 0.2s ease;
}
.tav-toast.is-leaving {
    animation: tav-toast-out 0.2s ease forwards;
}
.tav-toast-success {
    border-left-color: var(--tav-success);
}
.tav-toast-error {
    border-left-color: var(--tav-error);
}
.tav-toast-warning {
    border-left-color: var(--tav-warning);
}
.tav-toast-info {
    border-left-color: var(--tav-info);
}
.tav-toast-icon {
    flex-shrink: 0;
    width: 1.125rem;
    height: 1.125rem;
}
.tav-toast-success .tav-toast-icon {
    color: var(--tav-success);
}
.tav-toast-error .tav-toast-icon {
    color: var(--tav-error);
}
.tav-toast-warning .tav-toast-icon {
    color: var(--tav-warning);
}
.tav-toast-info .tav-toast-icon {
    color: var(--tav-info);
}
.tav-toast-msg {
    flex: 1;
    min-width: 0;
}
.tav-toast-close {
    flex-shrink: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--tav-on-surface-variant);
    cursor: pointer;
    line-height: 1;
}
@keyframes tav-toast-in {
    from {
        opacity: 0;
        transform: translateX(1rem);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}
@keyframes tav-toast-out {
    to {
        opacity: 0;
        transform: translateX(1rem);
    }
}

/* ── Command palette (<tav-command>) ────────────────────────────────── */
.tav-command-backdrop {
    position: fixed;
    inset: 0;
    z-index: 90;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 12vh 1rem 1rem;
    background: color-mix(in oklab, var(--tav-on-surface) 40%, transparent);
}
.tav-command {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 36rem;
    max-height: 70vh;
    overflow: hidden;
    border: 1px solid var(--tav-outline-variant);
    border-radius: var(--tav-radius-md);
    background: var(--tav-surface-1);
    box-shadow: var(--tav-elevation-3);
}
.tav-command-input {
    width: 100%;
    padding: 0.875rem 1rem;
    border: 0;
    border-bottom: 1px solid var(--tav-outline-variant);
    background: transparent;
    color: var(--tav-on-surface);
    font-size: var(--tav-type-title-size);
}
/* This used to carry a bare `outline: none`, which beat the generic
   `:focus-visible` ring on specificity and left the field with NO focus
   indicator in any mode — not just in forced colors, where the B-876 gate
   caught it. The intent was defensible: the palette opens with focus already
   here, and a ring around the only focusable thing in a modal reads as noise.
   `:focus-visible` expresses exactly that intent without the side effect —
   programmatic focus draws nothing, a Tab back into the field draws the ring.
   The offset points inward because the field runs edge to edge. */
.tav-command-input:focus-visible {
    outline: 2px solid var(--tav-primary);
    outline-offset: -2px;
}
.tav-command-list {
    overflow-y: auto;
    padding: 0.375rem;
}
/* A search ROW — icon, the input, and a hint key — for a palette that does more
   than filter a static list. `<tav-command>` renders the bare `.tav-command-input`
   on its own; console's server-backed spotlight needs the row, and re-authored it
   out of utilities because the component stopped one class short (B-829). Inside
   the row the input drops its own frame: the row carries the rule. */
.tav-command-search {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding-inline: 1rem;
    block-size: 3.5rem;
    border-block-end: 1px solid var(--tav-outline-variant);
}
.tav-command-search .tav-command-input {
    flex: 1;
    min-inline-size: 0;
    padding: 0;
    border-block-end: 0;
}
.tav-command-search-icon {
    flex-shrink: 0;
    inline-size: 1.25rem;
    block-size: 1.25rem;
    color: var(--tav-on-surface-variant);
}
/* Keyboard-hint strip along the bottom edge. */
.tav-command-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding-inline: 1rem;
    block-size: 2.25rem;
    border-block-start: 1px solid var(--tav-outline-variant);
    background: var(--tav-surface-2);
    font-size: var(--tav-type-size-xs);
    color: var(--tav-on-surface-variant);
}
.tav-command-footer-hints {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}
.tav-command-group-label {
    padding: 0.5rem 0.625rem 0.25rem;
    font-size: var(--tav-type-label-size);
    font-weight: var(--tav-type-title-weight);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--tav-on-surface-variant);
}
.tav-command-item {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem 0.625rem;
    border-radius: var(--tav-radius-sm);
    color: var(--tav-on-surface);
    cursor: pointer;
}
.tav-command-item[aria-selected="true"] {
    background: var(--tav-primary-container);
    color: var(--tav-on-primary-container);
}
.tav-command-item-kbd {
    margin-left: auto;
}
.tav-command-empty {
    padding: 1.5rem;
    text-align: center;
    color: var(--tav-on-surface-variant);
}

/* ── Standalone calendar (<tav-calendar>, form-associated) ──────────── */
.tav-calendar {
    display: inline-block;
    padding: 0.75rem;
    border: 1px solid var(--tav-outline-variant);
    border-radius: var(--tav-radius-md);
    background: var(--tav-surface-1);
}
.tav-calendar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 0.5rem;
}
.tav-calendar-title {
    font-weight: var(--tav-type-title-weight);
    color: var(--tav-on-surface);
}
.tav-calendar-nav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border: 0;
    border-radius: var(--tav-radius-sm);
    background: transparent;
    color: var(--tav-on-surface-variant);
    cursor: pointer;
}
.tav-calendar-nav:hover {
    background: color-mix(in oklab, transparent, var(--tav-on-surface) calc(var(--tav-state-hover) * 100%));
}
.tav-calendar-grid {
    display: grid;
    grid-template-columns: repeat(7, 2rem);
    gap: 2px;
}
.tav-calendar-weekday {
    padding: 0.25rem 0;
    text-align: center;
    font-size: var(--tav-type-label-size);
    color: var(--tav-on-surface-variant);
}
.tav-calendar-day {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 2rem;
    border: 0;
    border-radius: var(--tav-radius-sm);
    background: transparent;
    color: var(--tav-on-surface);
    font-size: var(--tav-type-body-size);
    cursor: pointer;
}
.tav-calendar-day:hover {
    background: color-mix(in oklab, transparent, var(--tav-on-surface) calc(var(--tav-state-hover) * 100%));
}
.tav-calendar-day.is-outside {
    color: var(--tav-outline);
}
.tav-calendar-day.is-today {
    box-shadow: inset 0 0 0 1px var(--tav-outline);
}
.tav-calendar-day.is-selected {
    background: var(--tav-primary);
    color: var(--tav-on-primary);
}

/* ── OTP / code input (<tav-otp>, form-associated) ──────────────────── */
.tav-otp {
    display: inline-flex;
    gap: 0.5rem;
}
.tav-otp-input {
    width: 2.75rem;
    height: 3rem;
    text-align: center;
    border: 1px solid color-mix(in oklab, var(--tav-primary) 28%, var(--tav-outline));
    border-radius: var(--tav-radius-sm);
    background: var(--tav-surface);
    color: var(--tav-on-surface);
    font-size: var(--tav-type-headline-size);
    font-variant-numeric: tabular-nums;
    caret-color: var(--tav-primary);
}
.tav-otp-input:focus {
    outline: none;
    border-color: var(--tav-primary);
    box-shadow: 0 0 0 1px var(--tav-primary);
}

/* ── Resizable split (<tav-resizable>) ──────────────────────────────── */
.tav-resizable {
    display: flex;
    width: 100%;
    overflow: hidden;
}
.tav-resizable-pane {
    min-width: 0;
    overflow: auto;
}
.tav-resizable-handle {
    flex: 0 0 auto;
    width: 0.5rem;
    padding: 0 0.1875rem;
    background: var(--tav-outline-variant);
    background-clip: content-box;
    cursor: col-resize;
    transition: background-color 0.15s ease;
}
.tav-resizable-handle:hover,
.tav-resizable-handle.is-dragging {
    background: var(--tav-primary);
    background-clip: content-box;
}

/* ══════════════════════════════════════════════════════════════════════
 * Damage sketch (tavuni-docs#3615) — the drawing of a vehicle's kind
 * (`catalog_mirror.vehicle_diagram_*`) with the places and wheels a
 * reading's damages stand on: a zone is tinted by the tone of its heaviest
 * damage (`data-tone`, the `status_tone` code: success · warning · error ·
 * info · neutral) and its
 * badge carries the numbers the observations list prints, so the sketch and
 * the list point at each other. One geometry for every surface; this is its
 * one look.
 *
 *   <figure class="tav-sketch">
 *     <svg class="tav-sketch-view" viewBox="0 0 W H" role="img" aria-label="…">
 *       <path class="tav-sketch-silhouette" d="…"/>
 *       <path class="tav-sketch-zone" data-tone="warning" d="…"><title>…</title></path>
 *       <g class="tav-sketch-badge"><rect x y width height rx/><text x y>1,3</text></g>
 *     </svg>
 *   </figure>
 *
 * A zone that opens something (`a.tav-sketch-link` around its path) shows
 * the hand and its outline on hover and focus.
 * ══════════════════════════════════════════════════════════════════════ */
    .tav-sketch {
        display: flex;
        flex-wrap: wrap;
        gap: 1rem;
        margin: 0;
    }
    /* The page sizes each view (`width`/`height` attributes): every view of
       a drawing at one scale. A view never runs wider than its row. */
    .tav-sketch-view {
        max-width: 100%;
        height: auto;
        flex: 0 1 auto;
    }
    .tav-sketch-view path {
        vector-effect: non-scaling-stroke;
        stroke-linejoin: round;
    }
    .tav-sketch-silhouette {
        fill: var(--tav-surface-1);
        stroke: var(--tav-outline);
        stroke-width: 1.2;
    }
    .tav-sketch-zone {
        fill: transparent;
        stroke: var(--tav-outline-variant);
        stroke-width: 0.6;
    }
    .tav-sketch-zone[data-tone="success"] { fill: color-mix(in oklab, var(--tav-success) 35%, transparent); }
    .tav-sketch-zone[data-tone="warning"] { fill: color-mix(in oklab, var(--tav-warning) 45%, transparent); }
    .tav-sketch-zone[data-tone="error"] { fill: color-mix(in oklab, var(--tav-error) 45%, transparent); }
    .tav-sketch-zone[data-tone="info"] { fill: color-mix(in oklab, var(--tav-info) 35%, transparent); }
    .tav-sketch-zone[data-tone="neutral"] { fill: color-mix(in oklab, var(--tav-on-surface) 20%, transparent); }
    .tav-sketch-badge rect {
        fill: var(--tav-on-surface);
        stroke: var(--tav-surface);
        stroke-width: 1.5;
        vector-effect: non-scaling-stroke;
    }
    /* The type size comes with the badge (`font-size` attribute), one size
       per drawing like the badge itself. */
    .tav-sketch-badge text {
        fill: var(--tav-surface);
        font-family: system-ui, sans-serif;
        font-weight: 700;
        pointer-events: none;
    }
    .tav-sketch-link { cursor: pointer; }
    .tav-sketch-link:hover .tav-sketch-zone,
    .tav-sketch-link:focus-visible .tav-sketch-zone {
        stroke: var(--tav-primary);
        stroke-width: 2;
    }

    /* ── Video (<tav-video>, tavuni-docs#3293): the library's own controls ── */
    .tav-video {
        display: block;
        position: relative;
        border-radius: var(--tav-radius-sm);
        overflow: hidden;
        background: var(--tav-surface-2);
    }
    .tav-video-media {
        display: block;
        inline-size: 100%;
        max-block-size: 70vh;
        background: var(--tav-surface-2);
    }
    .tav-video-bar {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.5rem 0.75rem;
        background: var(--tav-surface);
        border-block-start: 1px solid var(--tav-outline-variant);
    }
    .tav-video-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: 2rem;
        block-size: 2rem;
        border: 0;
        border-radius: var(--tav-radius-full);
        background: transparent;
        color: var(--tav-on-surface);
        cursor: pointer;
    }
    .tav-video-btn:hover {
        background: var(--tav-surface-2);
    }
    .tav-video-btn:focus-visible,
    .tav-video-track:focus-visible,
    .tav-spin:focus-visible {
        outline: 2px solid var(--tav-primary);
        outline-offset: 2px;
    }
    .tav-video-track {
        position: relative;
        flex: 1 1 auto;
        block-size: 0.375rem;
        border-radius: var(--tav-radius-full);
        background: var(--tav-outline-variant);
        cursor: pointer;
        touch-action: none;
    }
    .tav-video-fill {
        position: absolute;
        inset-block: 0;
        inset-inline-start: 0;
        border-radius: var(--tav-radius-full);
        background: var(--tav-primary);
    }
    .tav-video-time {
        font-variant-numeric: tabular-nums;
        font-size: 0.75rem;
        color: var(--tav-on-surface-variant);
        white-space: nowrap;
    }

    /* ── 360° series (<tav-spin>, tavuni-docs#3293): one still at a time ──── */
    .tav-spin {
        display: block;
        position: relative;
        border-radius: var(--tav-radius-sm);
        overflow: hidden;
        background: var(--tav-surface-2);
        cursor: grab;
        touch-action: pan-y;
        user-select: none;
    }
    .tav-spin.is-turning {
        cursor: grabbing;
    }
    .tav-spin img {
        display: none;
        inline-size: 100%;
        block-size: auto;
        pointer-events: none;
    }
    .tav-spin img:first-of-type,
    .tav-spin img.is-shown {
        display: block;
    }
    .tav-spin img.is-shown ~ img:first-of-type,
    .tav-spin:has(img.is-shown) img:not(.is-shown) {
        display: none;
    }
    .tav-spin-hint {
        position: absolute;
        inset-block-end: 0.5rem;
        inset-inline-start: 50%;
        transform: translateX(-50%);
        padding: 0.25rem 0.75rem;
        border-radius: var(--tav-radius-full);
        background: var(--tav-surface);
        color: var(--tav-on-surface-variant);
        font-size: 0.75rem;
        box-shadow: var(--tav-elevation-2);
    }

/* ══════════════════════════════════════════════════════════════════════
 * Forced colors — Windows High Contrast and `prefers-contrast: forced`
 * (B-876)
 *
 * In this mode the UA throws away every author colour and repaints the page
 * from the user's own palette. Nothing breaks; the page stays readable and
 * simply stops SAYING what it meant. Every rule below moves a meaning off
 * colour and onto something the repaint cannot erase — an outline, a border
 * style, a system colour that carries semantics by name.
 *
 * Three UA behaviours drive the whole block:
 *
 *   1. `box-shadow` is DISCARDED outright. Any indicator drawn with it is
 *      gone — which is how a focus ring disappears completely.
 *   2. Colours are forced UNLESS the declared value is a system colour
 *      (`Highlight`, `ButtonText`, `GrayText`, …). Naming one is how you
 *      keep a distinction the repaint would otherwise flatten.
 *   3. `border-style` and `border-width` are NOT forced. Style is therefore
 *      the one channel left for encoding a difference that used to be hue.
 *
 * Why a badge gets a border style rather than `forced-color-adjust: none`:
 * a user in this mode asked for their palette, and overriding that to keep
 * a brand hue answers a question they did not ask. Solid / dashed / dotted /
 * double survives the repaint and reads at 12px.
 * ══════════════════════════════════════════════════════════════════════ */
    @media (forced-colors: active) {

        /* tavuni-docs#3615 — a damaged zone of a sketch loses its tint to the
           repaint; a heavy outline keeps it apart from the clean ones. */
        .tav-sketch-zone[data-tone] {
            stroke: CanvasText;
            stroke-width: 2.5;
        }

        /* ── 1. Focus. The blocker. ──────────────────────────────────────
           Every control that sets `outline: none` in the base sheet draws
           its ring with `box-shadow` instead. That shadow is discarded
           here, and the `outline: none` that replaced it is not — so a
           keyboard user gets NO focus indicator at all. This is WCAG 2.4.7
           failing outright, not a cosmetic loss. The generic
           `:focus-visible` ring above already uses a real `outline` and
           survives; these did not.

           The list below is not a count you keep in your head: the test
           `every_control_that_kills_its_outline_restores_one_in_forced_colors`
           derives the offenders from the base sheet and demands a
           `:focus`/`:focus-visible` rule here for each one. `.tav-select-search`
           was added to the sheet later and never landed here — it is a text
           input inside the searchable select, so a keyboard user in high
           contrast had no way to see where they were typing. */
        .tav-input:focus,
        .tav-date-input:focus,
        .tav-textarea:focus,
        .tav-select-search:focus,
        .tav-color-hex:focus,
        .tav-number-input:focus,
        .tav-otp-input:focus,
        .tav-inline-input:focus,
        .tav-command-input:focus-visible {
            outline: 2px solid Highlight;
            outline-offset: 1px;
        }

        /* ── 2. Selection and the active step. ───────────────────────────
           `Highlight`/`HighlightText` is the pair the OS itself uses for a
           selected row, so a selected option reads as selected rather than
           as one more row. */
        .tav-select-option[aria-selected="true"],
        .tav-date-day[aria-selected="true"],
        .tav-date-day.is-range-start,
        .tav-date-day.is-range-end,
        .tav-date-cell[aria-current="true"],
        .tav-segmented-item[aria-selected="true"],
        .tav-segmented-item:has(> input[type="radio"]:checked),
        .tav-tab.active,
        .tav-tab[aria-current="page"],
        .tav-command-item[aria-selected="true"],
        .tav-transfer-item.is-marked,
        li[role="treeitem"][aria-selected="true"] > .tav-tree-row,
        .tav-page-btn[aria-current="page"],
        .tav-sidebar-link.active {
            background: Highlight;
            color: HighlightText;
            forced-color-adjust: none;
        }

        /* ── 3. Status badges. Meaning moves from fill to border style. ──
           All five semantic fills collapse to one colour here, so the border
           carries the distinction instead. Neutral keeps a plain border so
           "no status" still looks like the absence of one. */
        .tav-badge-success,
        .tav-badge-warning,
        .tav-badge-error,
        .tav-badge-info,
        .tav-badge-neutral,
        .tav-badge-primary,
        .tav-badge-secondary {
            border: 1px solid CanvasText;
        }
        .tav-badge-success  { border-style: solid; border-width: 2px; }
        .tav-badge-warning  { border-style: dashed; }
        .tav-badge-error    { border-style: double; border-width: 3px; }
        .tav-badge-info     { border-style: dotted; }
        /* Neutral is the absence of a status, not a fifth one, so it takes the
           palette's own "this is inactive" colour rather than a fifth border
           style. It also keeps `success` from having to be distinguished from
           it by 1px of border width alone. */
        .tav-badge-neutral  { border-style: solid; color: GrayText; border-color: GrayText; }

        /* ── 4. Buttons. ─────────────────────────────────────────────────
           Every variant becomes ButtonFace, so a borderless ghost button
           stops looking like a control at all. The destructive pair keeps
           its distance from the rest through border style — the one channel
           the repaint leaves alone. */
        .tav-btn {
            border: 1px solid ButtonBorder;
        }
        .tav-btn:disabled,
        .tav-btn[aria-disabled="true"] {
            color: GrayText;
            border-color: GrayText;
        }
        .tav-btn-danger,
        .tav-btn-danger-strong {
            border-style: double;
            border-width: 3px;
        }

        /* ── 5. Filled proportions. ──────────────────────────────────────
           A progress bar and a range track say what they say by how much of
           them is filled. Track and fill both go to Canvas, and the reading
           goes with them. */
        .tav-progress,
        .tav-range-track {
            border: 1px solid CanvasText;
        }
        .tav-progress-bar,
        .tav-range-fill {
            background: Highlight;
            forced-color-adjust: none;
        }
        .tav-range-thumb {
            background: ButtonText;
            border: 1px solid ButtonBorder;
            forced-color-adjust: none;
        }
        /* A toggle says on-or-off with two fills and nothing else: track and
           thumb both land on Canvas here, and the switch stops reporting its
           own state. The thumb rides on `::after`, so it needs its own rule. */
        .tav-toggle {
            border: 1px solid CanvasText;
        }
        .tav-toggle::after {
            background: CanvasText;
            forced-color-adjust: none;
        }
        .tav-toggle[aria-checked="true"] {
            background: Highlight;
            forced-color-adjust: none;
        }
        .tav-toggle[aria-checked="true"]::after {
            background: HighlightText;
            forced-color-adjust: none;
        }
        /* The drawn checkbox/radio paint their state with gradients, which
           forced colours drop: keep the box and fill it with Highlight. */
        .tav-checkbox,
        .tav-radio {
            border: 1px solid CanvasText;
        }
        .tav-checkbox:checked,
        .tav-checkbox:indeterminate,
        .tav-radio:checked {
            background-color: Highlight;
            forced-color-adjust: none;
        }
        .tav-checkbox:disabled,
        .tav-radio:disabled {
            border-color: GrayText;
        }
        .tav-checkbox:checked:disabled,
        .tav-checkbox:indeterminate:disabled,
        .tav-radio:checked:disabled {
            --tav-check-ink: GrayText;
            background-color: Canvas;
        }

        /* ── 6. Dots, rails and other pure-colour marks. ─────────────────
           A timeline dot is `aria-hidden` and its category is spelled out in
           the text beside it, so nothing is LOST here — but an unbordered
           dot on Canvas is invisible, which turns a legible chronology into
           a ragged list. The border is what keeps the rail readable. */
        .tav-timeline > li::before,
        .tav-step-dot,
        .tav-avatar {
            border: 1px solid CanvasText;
        }
        .tav-timeline {
            border-inline-start-color: CanvasText;
        }
        .tav-steps::before {
            background: CanvasText;
            forced-color-adjust: none;
        }

        /* ── 7. Surfaces that only exist as a shadow. ────────────────────
           Menus, popovers and toasts float on elevation alone. With
           `box-shadow` discarded they merge into whatever is behind them. */
        .tav-menu,
        .tav-popover-panel,
        .tav-hover-card-panel,
        .tav-toast,
        .tav-command,
        .tav-select-listbox,
        .tav-date-popup,
        .tav-drawer-panel,
        .tav-tooltip {
            border: 1px solid CanvasText;
        }

        /* ── 8. Hover as a state-layer. ──────────────────────────────────
           `color-mix` state layers vanish. Where the hover means "this row
           is a link", say so with the system's own selection colour. */
        .tav-table tbody tr[data-row-href]:hover,
        .tav-select-option:hover,
        .tav-command-item:hover,
        .tav-menu-item:hover {
            background: Highlight;
            color: HighlightText;
            forced-color-adjust: none;
        }

        /* ── 9. Disabled. ────────────────────────────────────────────────
           `GrayText` is the one signal the palette guarantees for this. */
        .tav-input:disabled,
        .tav-textarea:disabled,
        .tav-checkbox:disabled,
        .tav-radio:disabled,
        [aria-disabled="true"] {
            color: GrayText;
        }
    }

/* ══════════════════════════════════════════════════════════════════════
 * Touch targets — WCAG 2.2 SC 2.5.8 (B-862 follow-up)
 *
 * Measured in the browser: the toast dismiss is 9x14 CSS px and the chip and
 * tag removers are 16x16 and 18x18. The success criterion asks for 24x24 and
 * none of its exceptions apply — these are not inline in a sentence, they have
 * no equivalent control elsewhere, their size is not essential, and they are
 * drawn by this sheet rather than by the user agent. A garage tablet is the
 * ordinary case for this product, so a 9x14 dismiss is a real one.
 *
 * The fix keeps the drawn size and grows only the HIT area, with a centred
 * pseudo-element. Making the buttons visually bigger would be the wrong trade:
 * a chip remover the size of the chip stops reading as a remover.
 *
 * Checkbox and radio are deliberately NOT here. They measure 13x16 and 16x16,
 * but their `<label>` wraps the control (74x60 and 120x20 measured), so the
 * label IS the target — and `appearance: auto` puts them under the criterion's
 * user-agent exception besides.
 * ══════════════════════════════════════════════════════════════════════ */
    /* The floor is a token so a shell can raise it the way the portal already
       raises `--tav-control-h`: that shell is the only one a customer reaches,
       on a phone, and 2.5.5 asks 44px there rather than 2.5.8's 24. A hard
       24px here would have been a second place to remember. */
    :root {
        --tav-hit-min: 24px;
    }
    .tav-toast-close,
    .tav-chip-remove,
    .tav-tag-x {
        position: relative;
    }
    .tav-toast-close::after,
    .tav-chip-remove::after,
    .tav-tag-x::after {
        content: "";
        position: absolute;
        inset-block-start: 50%;
        inset-inline-start: 50%;
        transform: translate(-50%, -50%);
        min-inline-size: var(--tav-hit-min);
        min-block-size: var(--tav-hit-min);
        inline-size: 100%;
        block-size: 100%;
    }

    /* A stepper button declares `inline-size: 2.25rem` and means it, but with
       the flex default of `shrink: 1` a narrow column takes it down to 12px
       wide — measured. Not a defect anywhere today (every current caller has
       room), but a component that collapses to a third of its own declared
       size in a table cell is one narrow layout away from being one. */
    .tav-number-btn {
        flex-shrink: 0;
    }

/* ══════════════════════════════════════════════════════════════════════
 * Long unbroken strings — WCAG 1.4.10 Reflow (B-884 follow-up)
 *
 * Measured in a 320px viewport: a bare URL pushes 18px of horizontal overflow
 * onto the page, and this product is full of strings that never wrap on their
 * own — VINs, IBANs, chassis numbers, enterprise numbers, customer e-mail
 * addresses. Sixteen table cells in the product already bind one directly.
 *
 * `anywhere` rather than `break-word`: the latter only breaks a word that
 * would overflow ALONE on its line, so it still lets a long token push a
 * flex or grid track wider than its container. `anywhere` also lets the
 * intrinsic min-content size shrink, which is what actually stops the
 * overflow.
 *
 * Scoped to the components that carry free text and user data, not applied
 * globally: a nav label or a button that wraps mid-word reads as a rendering
 * fault, and those never hold a VIN.
 * ══════════════════════════════════════════════════════════════════════ */
    .tav-dd,
    .tav-card-body,
    .tav-help,
    .tav-error-text,
    .tav-timeline > li,
    .tav-toast-msg,
    .tav-empty-text {
        overflow-wrap: anywhere;
    }
    /* A table cell is the exception. `anywhere` also shrinks a cell's
       min-content to one character, so in a narrow pane (the app beside a
       conversation, ~630px) the table squeezed its columns until every word
       broke letter by letter — "Kleine stadswagen" one letter per line
       (tavuni-docs#2567 point 9). `break-word` keeps a word whole and still
       breaks a token wider than its whole line; a table wider than its pane
       scrolls inside its frame (`list_table`, `.tav-record-table-scroll`),
       which WCAG 1.4.10 allows for data tables. */
    .tav-table td {
        overflow-wrap: break-word;
    }



}
