@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Space+Grotesk:wght@400;500;600;700&display=swap");

/* TriArch custom theme — phase 1.
   Scope: color scheme + typography + sidebar/buttons only.
   No structural layout overrides. */

:root {
    --triarch-font-display: "Space Grotesk", "Segoe UI", sans-serif;
    --triarch-font-body: "Space Grotesk", "Segoe UI", sans-serif;
    --triarch-font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    --triarch-primary: #9d4300;
    --triarch-primary-strong: #783200;
    --triarch-accent: #f97316;
    --triarch-accent-hover: #e86b14;
    --triarch-border: #e3e8ee;
    --triarch-text: #171c22;
    --triarch-text-soft: #55637a;
    --triarch-sidebar-bg: #eff3f7;
    --triarch-sidebar-text: #55637a;
    --triarch-sidebar-icon: #6e7b90;
    --triarch-sidebar-active-text: var(--triarch-primary);
    --triarch-sidebar-active-bg: rgba(255, 255, 255, 0.76);
    --triarch-sidebar-hover-bg: rgba(87, 101, 122, 0.1);

    /* LeptonX top bar is ~4rem; 5rem clears it. The extra 1rem is breathing
       room under a sticky rail. Both numbers live here so a header change
       moves the pin and the cap together. */
    --triarch-sticky-top: 5rem;
    --triarch-sticky-gap: 1rem;

    /* ── Design system scales (additive; opt-in via .t-* / .ta-* classes) ── */

    /* Radii. The standard uses four: xs (tags), md (controls, cards), lg (panels, dialogs), pill.
       md is 8px to match what LeptonX renders on cards and buttons (docs/ui-standard.md §4). */
    --radius-xs: 4px;
    --radius-sm: 6px;
    --radius-md: 8px;
    --radius-lg: 14px;
    --radius-xl: 20px;
    --radius-pill: 999px;

    /* Spacing (4px grid) */
    --space-0: 0;
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-8: 32px;
    --space-10: 40px;
    --space-12: 48px;
    --space-16: 64px;

    /* Motion */
    --duration-instant: 80ms;
    --duration-fast: 150ms;
    --duration-base: 220ms;
    --duration-slow: 320ms;
    --duration-slower: 480ms;
    --ease-standard: cubic-bezier(0.2, 0, 0, 1);
    --ease-decelerate: cubic-bezier(0, 0, 0, 1);
    --ease-accelerate: cubic-bezier(0.3, 0, 1, 1);
    --ease-emphasize: cubic-bezier(0.3, 0, 0, 1);
    --transition-color: color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
    --transition-shadow: box-shadow var(--duration-fast) var(--ease-standard);

    /* Icon sizes */
    --icon-size-xs: 12px;
    --icon-size-sm: 14px;
    --icon-size-md: 16px;
    --icon-size-lg: 20px;
    --icon-size-xl: 24px;
    --icon-size-2xl: 32px;
    --icon-size-3xl: 48px;
}

.lpx-theme-light,
.lpx-theme-dim {
    /* Industrial Architect - Light. Semi-dark (dim) keeps light CONTENT — only LeptonX's
       sidebar goes dark — so our content tokens must resolve to the light palette here. */
    --triarch-bg: #f6f8fb;
    --triarch-surface: #ffffff;
    --triarch-surface-soft: #eff3f7;
    --triarch-surface-dim: #d6dade;
    --triarch-border: #e3e8ee;
    --triarch-outline: #c9d1da;
    --triarch-outline-warm: #e0c0b1;
    --triarch-surface-attention: #fff9ef;   /* warm "look here" strip or row (BOM, Estimate) */
    --triarch-border-attention: #f2e6d2;
    --triarch-text: #171c22;
    --triarch-text-soft: #55637a;

    /* ── UI Standard role tokens (docs/ui-standard.md §2) ─────────────────────
       New code uses these. The older names further down are aliases of them, kept so
       existing rules keep working. Every token here also has a value in .lpx-theme-dark. */
    --triarch-action: #9d4300;          /* the one "do this" colour: primary buttons, selection */
    --triarch-action-hover: #7a3400;
    --triarch-action-tint: #fbe8da;     /* selected chip, active row, brand pill fill */
    --triarch-action-outline: #f2c7a8;
    --triarch-action-fg: #8f3b00;       /* text on the action tint */
    --triarch-on-action: #ffffff;       /* text on a solid action fill */
    --triarch-link: #9d4300;
    --triarch-link-hover: #7a3400;
    /* State pairs: -fg is the text or icon, -bg the fill behind it (4.5:1 together).
       Red, amber, green and blue are reserved for these meanings. */
    --triarch-danger-fg: #b42318;
    --triarch-danger-bg: #fdecea;
    --triarch-on-danger: #ffffff;       /* text on a solid danger fill */
    --triarch-warning-fg: #7a5c00;
    --triarch-warning-bg: #fff1d6;
    --triarch-success-fg: #1b6b3f;
    --triarch-success-bg: #dff3e6;
    --triarch-info-fg: #1d5f96;
    --triarch-info-bg: #e2eef9;
    --triarch-neutral-fg: #4b5a6e;
    --triarch-neutral-bg: #edf1f5;
    /* Identity colours for trades, cost segments and chart series. Never used for state. */
    /* Clay, kept browner than the action orange: Fire alarm is on nearly every project row, and in the
       old sienna its fill was the selected-chip tint exactly. */
    --triarch-cat-1-fg: #764229;        /* clay */
    --triarch-cat-1-bg: #efd9cb;
    --triarch-cat-2-fg: #5d6300;        /* olive */
    --triarch-cat-2-bg: #eef0d2;
    --triarch-cat-3-fg: #0f6e63;        /* teal */
    --triarch-cat-3-bg: #d8f1ec;
    --triarch-cat-4-fg: #3f4fb5;        /* indigo */
    --triarch-cat-4-bg: #e5e8fa;
    --triarch-cat-5-fg: #6d3fb0;        /* violet */
    --triarch-cat-5-bg: #efe6fb;
    --triarch-cat-6-fg: #8a2f6e;        /* plum */
    --triarch-cat-6-bg: #f8e3f0;

    /* ── Older names. Aliases where a role token replaces them. ── */
    --triarch-primary: var(--triarch-action);
    --triarch-primary-strong: #783200;
    --triarch-primary-tint: #ffdbca;
    --triarch-primary-dim: #ffb690;
    --triarch-accent: #f97316;
    --triarch-accent-hover: #e86b14;
    --triarch-tertiary: var(--triarch-warning-fg);
    --triarch-inverse-surface: #2c3134;
    --triarch-warning: #f7be1d;

    --triarch-text-muted: #584237;

    --triarch-brand: var(--triarch-action);    /* logos, marketing surfaces, ISSUED status */
    --triarch-brand-strong: #783200;
    --triarch-brand-tint: #ffdbca;
    /* The separate CTA clay (#b8442a) is retired: it sat next to danger red on the colour wheel.
       The cta names now resolve to the action colour. */
    --triarch-cta: var(--triarch-action);
    --triarch-cta-hover: var(--triarch-action-hover);
    --triarch-cta-tint: var(--triarch-action-tint);
    --triarch-cta-outline: var(--triarch-action-outline);
    --triarch-focus: #475569;           /* a11y focus ring — decoupled from brand */
    --triarch-focus-soft: rgba(71, 85, 105, 0.25);
    --triarch-live: #f97316;            /* "new/live" indicators only, never text */
    --triarch-success: #238b45;
    --triarch-danger: var(--triarch-danger-fg);
    --triarch-info: var(--triarch-info-fg);    /* blue; the old teal (#2d7a7a) is identity colour cat-3 now */
    --triarch-text-issued: #7a3400;
    --triarch-text-on-cta: var(--triarch-on-action);
    --triarch-text-on-brand: var(--triarch-on-action);

    /* Permit / workflow status tokens (semantic, not hue-named) */
    --status-submitted: #5b7693;
    --status-in-review: var(--triarch-warning-fg);
    --status-in-review-bg: var(--triarch-warning-bg);
    --status-action-required: var(--triarch-action);
    --status-approved: #238b45;
    --status-paid: var(--triarch-info-fg);
    --status-issued: var(--triarch-action);
    --status-rejected: var(--triarch-danger-fg);

    /* Chart roles (semantic, not hue-named), from the brand palette only: slate carries the data,
       sienna marks the one figure that matters most. Charts never use clay (CTA — data in it reads
       as a button) or the info/success status colours (teal and green are not brand colours), and
       in light never tangerine (hover). Dark differs: the brand token is tangerine there, so the
       sienna roles draw in tangerine. Repeated in the dark block because a custom property resolves
       where it is declared. */
    --triarch-chart-primary: #475569;                   /* slate-500 — the main measured series: realized margin, funnel stages, department share, GC bars */
    --triarch-chart-secondary: var(--triarch-brand);    /* sienna — the series it is compared with: bid margin */
    --triarch-chart-positive: var(--triarch-brand);     /* sienna — the win: awarded, win rate */
    --triarch-chart-muted: var(--triarch-outline);      /* tracks, empty segments, gridlines */

    /* Elevation — cool-tinted, reserve --shadow-brand/--shadow-cta for CTA hover */
    --shadow-xs: 0 1px 2px rgba(23, 28, 31, 0.06);
    --shadow-sm: 0 2px 4px rgba(23, 28, 31, 0.06), 0 1px 2px rgba(23, 28, 31, 0.04);
    --shadow-md: 0 8px 20px rgba(23, 28, 31, 0.08), 0 2px 6px rgba(23, 28, 31, 0.05);
    --shadow-lg: 0 24px 48px -16px rgba(23, 28, 31, 0.18);
    --shadow-brand: 0 25px 50px -12px rgba(157, 67, 0, 0.18);
    --shadow-cta: 0 25px 50px -12px rgba(157, 67, 0, 0.2);

    /* Focus rings — opaque 2-layer (WCAG 2.2 SC 2.4.11 / 2.4.13) */
    --focus-ring:          0 0 0 2px var(--triarch-bg), 0 0 0 4px var(--triarch-focus);
    --focus-ring-danger:   0 0 0 2px var(--triarch-bg), 0 0 0 4px var(--triarch-danger);
    --focus-ring-on-brand: 0 0 0 2px var(--triarch-brand), 0 0 0 4px #ffffff;
    --focus-ring-on-cta:   0 0 0 2px var(--triarch-cta), 0 0 0 4px #ffffff;

    /* LeptonX token bridge */
    --lpx-primary: var(--triarch-primary);
    --lpx-primary-rgb: 157, 67, 0;
    --lpx-secondary: #515f74;
    --lpx-secondary-rgb: 81, 95, 116;
    --lpx-brand: var(--triarch-accent);
    --lpx-brand-rgb: 249, 115, 22;
    --lpx-brand-text: #ffffff;
    --lpx-success: #238b45;
    --lpx-warning: #b88400;
    --lpx-danger: var(--triarch-danger);
    --lpx-navbar-color: var(--triarch-surface);
    --lpx-navbar-text-color: var(--triarch-text-soft);
    --lpx-navbar-active-text-color: var(--triarch-primary);
    --lpx-navbar-active-bg-color: #eef3f7;
    --lpx-content-bg: var(--triarch-bg);
    --lpx-content-text: var(--triarch-text);
    --lpx-card-bg: var(--triarch-surface);
    --lpx-card-title-text-color: var(--triarch-text);
    --lpx-border-color: rgba(23, 28, 31, 0.08);
}

/* Semi-dark (dim): content uses the light palette above, but the LEFT menu + RIGHT toolbar
   must stay DARK (LeptonX's native semi-dark). The shared light block forced the navbar
   surface white (`--lpx-navbar-color: var(--triarch-surface)`), which is what painted the
   sidebars light. Restore LeptonX dim's dark navbar surface (#161616) and make our menu
   text/icons readable on it — content tokens (surface/bg/card) are deliberately untouched. */
.lpx-theme-dim {
    --lpx-navbar-color: #161616;
    --lpx-navbar-text-color: #aebbd0;
    --lpx-navbar-active-text-color: var(--triarch-primary);
    --lpx-navbar-active-bg-color: rgba(255, 255, 255, 0.08);
    --triarch-sidebar-text: #aebbd0;
    --triarch-sidebar-icon: #94a3b8;
    --triarch-sidebar-active-text: var(--triarch-primary);
    --triarch-sidebar-active-bg: rgba(255, 255, 255, 0.06);
    --triarch-sidebar-hover-bg: rgba(179, 192, 205, 0.08);
}

.lpx-theme-dark {
    /* Keep LeptonX dark surfaces, but provide safe custom tokens for our rules.
       NOTE: .lpx-theme-dim (semi-dark) is intentionally NOT here — it takes the light
       palette above so semi-dark content matches light theme. */
    /* ── UI Standard role tokens — dark values (see the light block) ── */
    --triarch-action: #f97316;
    --triarch-action-hover: #ff8a42;
    --triarch-action-tint: rgba(249, 115, 22, 0.16);
    --triarch-action-outline: rgba(249, 115, 22, 0.45);
    --triarch-action-fg: #ffa66b;
    --triarch-on-action: #1a0d03;       /* dark text: white on tangerine is only 2.8:1 */
    --triarch-link: #ff9a52;
    --triarch-link-hover: #ffb690;
    --triarch-danger-fg: #ff8f86;
    --triarch-danger-bg: rgba(255, 128, 118, 0.15);
    --triarch-on-danger: #1a0d03;
    --triarch-warning-fg: #f0c25a;
    --triarch-warning-bg: rgba(240, 194, 90, 0.15);
    --triarch-success-fg: #6fd896;
    --triarch-success-bg: rgba(95, 208, 138, 0.14);
    --triarch-info-fg: #8cc2f2;
    --triarch-info-bg: rgba(124, 184, 240, 0.15);
    --triarch-neutral-fg: #b8c3d1;
    --triarch-neutral-bg: rgba(180, 192, 207, 0.12);
    --triarch-cat-1-fg: #e3ab86;
    --triarch-cat-1-bg: rgba(227, 171, 134, 0.14);
    --triarch-cat-2-fg: #cdd470;
    --triarch-cat-2-bg: rgba(200, 207, 106, 0.14);
    --triarch-cat-3-fg: #5fd6c3;
    --triarch-cat-3-bg: rgba(79, 209, 189, 0.14);
    --triarch-cat-4-fg: #a6b0f6;
    --triarch-cat-4-bg: rgba(154, 166, 245, 0.16);
    --triarch-cat-5-fg: #c8aaf3;
    --triarch-cat-5-bg: rgba(195, 162, 242, 0.16);
    --triarch-cat-6-fg: #eaa9d4;
    --triarch-cat-6-bg: rgba(231, 162, 207, 0.16);

    --triarch-primary: var(--triarch-action);
    --triarch-primary-strong: #ffb690;
    --triarch-primary-tint: rgba(249, 115, 22, 0.15);
    --triarch-primary-dim: #ffb690;
    --triarch-accent: #f97316;
    --triarch-accent-hover: #ff8a42;
    --triarch-tertiary: var(--triarch-warning-fg);
    --triarch-warning: #f7be1d;
    --triarch-inverse-surface: #dce6ef;
    /* Surface / border tokens for dark mode (docs/ui-standard.md, decision 5).
       The surfaces follow LeptonX, not the other way round: its dark Bootstrap hard-codes cards,
       menus and dialogs at #1b1b1b and inputs and content at #121212, and does not read
       --lpx-card-bg, so those cannot be re-pointed from here. Taking LeptonX's values gives one
       neutral grey family: custom panels sit on the same surface as theme cards (they were
       blue-slate #1e2530 / #161d27 beside grey before). */
    --triarch-bg: var(--lpx-content-bg, #121212);        /* page background */
    --triarch-border: rgba(179, 192, 205, 0.18);
    --triarch-outline: rgba(179, 192, 205, 0.3);
    --triarch-outline-warm: rgba(255, 182, 144, 0.25);
    --triarch-surface-attention: var(--triarch-surface-soft);   /* the light cream glares on dark */
    --triarch-border-attention: var(--triarch-border);
    --triarch-surface: var(--lpx-card-bg, #1b1b1b);      /* cards, panels, tables */
    --triarch-surface-soft: #161616;                     /* recessed: wells, table heads */
    --triarch-surface-dim: rgba(255, 255, 255, 0.06);
    /* Text */
    --triarch-text: #dce6ef;
    --triarch-text-soft: #aebbd0;
    --triarch-text-muted: rgba(174, 187, 208, 0.7);
    /* Sidebar */
    --triarch-sidebar-bg: #11161c;
    --triarch-sidebar-text: #aebbd0;
    --triarch-sidebar-icon: #94a3b8;
    --triarch-sidebar-active-text: var(--triarch-primary);
    --triarch-sidebar-active-bg: rgba(255, 255, 255, 0.06);
    --triarch-sidebar-hover-bg: rgba(179, 192, 205, 0.08);
    /* Bridge LeptonX native brand tokens so selected/active items stay orange */
    --lpx-primary: var(--triarch-primary);
    --lpx-primary-rgb: 249, 115, 22;
    --lpx-brand: #f97316;
    --lpx-brand-rgb: 249, 115, 22;
    --lpx-navbar-active-text-color: #f97316;

    /* ── Role-split palette — dark rebase (4.5:1 on dark surfaces) ──────── */
    --triarch-brand: var(--triarch-action);
    --triarch-brand-strong: #ffb690;
    --triarch-brand-tint: rgba(249, 115, 22, 0.15);
    --triarch-cta: var(--triarch-action);
    --triarch-cta-hover: var(--triarch-action-hover);
    --triarch-cta-tint: var(--triarch-action-tint);
    --triarch-cta-outline: var(--triarch-action-outline);
    --triarch-focus: #94a3b8;
    --triarch-focus-soft: rgba(148, 163, 184, 0.3);
    --triarch-live: #f97316;
    --triarch-success: #3dc565;
    --triarch-danger: var(--triarch-danger-fg);
    --triarch-info: var(--triarch-info-fg);
    --triarch-text-issued: #ffd9bf;
    --triarch-text-on-cta: var(--triarch-on-action);
    --triarch-text-on-brand: var(--triarch-on-action);

    --status-submitted: #94a3b8;
    --status-in-review: var(--triarch-warning-fg);
    --status-in-review-bg: var(--triarch-warning-bg);
    --status-action-required: var(--triarch-action);
    --status-approved: #3dc565;
    --status-paid: var(--triarch-info-fg);
    --status-issued: #ffb690;
    --status-rejected: var(--triarch-danger-fg);

    /* Chart roles — see the light block. Slate lifts to slate-400 to stay readable on dark cards;
       the brand token is tangerine in dark, so secondary and positive draw in tangerine here. */
    --triarch-chart-primary: #94a3b8;
    --triarch-chart-secondary: var(--triarch-brand);
    --triarch-chart-positive: var(--triarch-brand);
    --triarch-chart-muted: var(--triarch-outline);

    --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.5);
    --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.5), 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 8px 20px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.4);
    --shadow-lg: 0 24px 48px -16px rgba(0, 0, 0, 0.7);
    --shadow-brand: 0 25px 50px -12px rgba(249, 115, 22, 0.35);
    --shadow-cta: 0 25px 50px -12px rgba(249, 115, 22, 0.35);

    --focus-ring:          0 0 0 2px var(--triarch-bg, #0b1016), 0 0 0 4px var(--triarch-focus);
    --focus-ring-danger:   0 0 0 2px var(--triarch-bg, #0b1016), 0 0 0 4px var(--triarch-danger);
    --focus-ring-on-brand: 0 0 0 2px var(--triarch-brand), 0 0 0 4px #0b1016;
    --focus-ring-on-cta:   0 0 0 2px var(--triarch-cta), 0 0 0 4px #0b1016;
}

/* Typography system */
html,
body,
.lpx-content-container {
    font-family: var(--triarch-font-body);
}

.lpx-main-title,
h1,
h2,
h3,
h4,
h5,
h6,
.btn,
.card-title,
.modal-title,
.lpx-brand-name,
.lpx-topbar {
    font-family: var(--triarch-font-display);
}

/* Sidebar menu text — override LeptonX hardcoded Inter rule (layout-bundle.css:142) */
.lpx-nav-menu .menu-item .menu-item-text,
.lpx-nav-menu .lpx-menu-item-link .lpx-menu-item-text,
.lpx-nav-menu .lpx-inner-menu-item .lpx-menu-item-text {
    font-family: var(--triarch-font-body);
}

.lpx-brand-name {
    color: var(--triarch-text);
    font-weight: 700;
}

.lpx-nav-menu .menu-item > .lpx-menu-item-link,
.lpx-nav-menu .outer-menu-item > .lpx-menu-item-link {
    color: var(--triarch-sidebar-text);
}

.lpx-nav-menu .menu-item > .lpx-menu-item-link .menu-item-icon,
.lpx-nav-menu .outer-menu-item > .lpx-menu-item-link .menu-item-icon,
.lpx-nav-menu .menu-item > .lpx-menu-item-link .lpx-icon,
.lpx-nav-menu .outer-menu-item > .lpx-menu-item-link .lpx-icon {
    color: var(--triarch-sidebar-icon);
}

/* Active/selected link text — LeptonX DOM: .lpx-menu-item-link.selected (class on link itself) */
.lpx-nav-menu .lpx-menu-item-link.selected,
.lpx-nav-menu .lpx-menu-item.selected,
.lpx-nav-menu .menu-item.active > .lpx-menu-item-link,
.lpx-nav-menu .outer-menu-item.active > .lpx-menu-item-link {
    color: var(--triarch-sidebar-active-text) !important;
}

/* Active/selected icon color — target both the span wrapper and the icon directly */
.lpx-nav-menu .lpx-menu-item-link.selected .lpx-menu-item-icon,
.lpx-nav-menu .lpx-menu-item-link.selected .lpx-icon,
.lpx-nav-menu .lpx-menu-item.selected .lpx-menu-item-icon,
.lpx-nav-menu .lpx-menu-item.selected .lpx-icon,
.lpx-nav-menu .menu-item.active > .lpx-menu-item-link .menu-item-icon,
.lpx-nav-menu .outer-menu-item.active > .lpx-menu-item-link .menu-item-icon,
.lpx-nav-menu .menu-item.active > .lpx-menu-item-link .lpx-icon,
.lpx-nav-menu .outer-menu-item.active > .lpx-menu-item-link .lpx-icon {
    color: var(--triarch-sidebar-active-text) !important;
}

/* Sidebar section headers — LeptonX renders each ApplicationMenuGroup as <li class="group-menu-item">
   (the host contributor registers Work / Library / Network / Setup for contractor tenants). The theme
   only gives the element padding and weight; this turns it into a small caption that reads as a
   divider rather than a menu entry. Colour is the item text dimmed, so it tracks light/dark through
   the sidebar tokens. The theme's hidden-in-hover-trigger class already hides it in the collapsed rail. */
.lpx-nav-menu .group-menu-item {
    padding: 1.25rem 0 0.375rem 1.25rem;
    font-family: var(--triarch-font-body);
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--triarch-sidebar-text);
    opacity: 0.65;
    cursor: default;
    user-select: none;
}

.lpx-nav-menu .group-menu-item:first-child {
    padding-top: 0.5rem;
}

/* Pagination color */
.pagination {
    --bs-pagination-active-bg: var(--triarch-primary);
    --bs-pagination-active-border-color: var(--triarch-primary);
    --bs-pagination-active-color: #ffffff;
    --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(157, 67, 0, 0.25);
    --bs-pagination-color: var(--triarch-sidebar-text);
    --bs-pagination-hover-color: var(--triarch-primary);
}

/* Override LeptonX bootstrap-dark.css hardcoded pink (!important) on active page */
.pagination .page-item.active .page-link {
    background-color: var(--triarch-primary) !important;
    border-color: var(--triarch-primary) !important;
    color: var(--triarch-on-action, #ffffff) !important;
}

/* Button color system — matches landing page hl-btn-cta-primary pattern:
   base = dark brown (--triarch-primary), hover = orange (--triarch-accent).
   Text is --triarch-on-action, not a fixed white: the fill is tangerine in dark theme, where white
   text is 2.8:1. The token is white in light and near-black in dark. */
.btn-primary,
.btn-brand {
    --bs-btn-color: var(--triarch-on-action, #ffffff);
    --bs-btn-bg: var(--triarch-primary);
    --bs-btn-border-color: var(--triarch-primary);
    --bs-btn-hover-color: var(--triarch-on-action, #ffffff);
    --bs-btn-hover-bg: color-mix(in srgb, var(--triarch-primary) 88%, #000000);
    --bs-btn-hover-border-color: color-mix(in srgb, var(--triarch-primary) 88%, #000000);
    --bs-btn-active-color: var(--triarch-on-action, #ffffff);
    --bs-btn-active-bg: color-mix(in srgb, var(--triarch-primary) 78%, #000000);
    --bs-btn-active-border-color: color-mix(in srgb, var(--triarch-primary) 78%, #000000);
    --bs-btn-focus-shadow-rgb: var(--lpx-primary-rgb, 157, 67, 0);
    --bs-btn-disabled-color: var(--triarch-on-action, #ffffff);
    --bs-btn-disabled-bg: var(--triarch-primary);
    --bs-btn-disabled-border-color: var(--triarch-primary);
    background-color: var(--bs-btn-bg);
    border-color: var(--bs-btn-border-color);
    color: var(--bs-btn-color);
    cursor: pointer;
    box-shadow: 0 25px 50px -12px rgba(var(--lpx-primary-rgb, 157, 67, 0), 0.18);
    transition: background-color var(--duration-fast) var(--ease-standard),
        border-color var(--duration-fast) var(--ease-standard),
        color var(--duration-fast) var(--ease-standard),
        box-shadow var(--duration-fast) var(--ease-standard),
        transform var(--duration-instant) var(--ease-standard);
}

.btn-primary:hover,
.btn-brand:hover {
    background-color: var(--bs-btn-hover-bg);
    border-color: var(--bs-btn-hover-border-color);
    color: var(--bs-btn-hover-color);
    box-shadow: 0 14px 28px -14px rgba(var(--lpx-primary-rgb, 157, 67, 0), 0.42);
    transform: translateY(-1px);
}

.btn-primary:active,
.btn-brand:active,
.btn-primary.active,
.btn-brand.active,
.btn-primary.show,
.btn-brand.show {
    background-color: var(--bs-btn-active-bg);
    border-color: var(--bs-btn-active-border-color);
    color: var(--bs-btn-active-color);
    box-shadow: 0 8px 18px -12px rgba(var(--lpx-primary-rgb, 157, 67, 0), 0.5);
    transform: translateY(0);
}

.btn-primary:focus,
.btn-brand:focus,
.btn-primary:focus-visible,
.btn-brand:focus-visible {
    background-color: var(--bs-btn-hover-bg);
    border-color: var(--bs-btn-hover-border-color);
    color: var(--bs-btn-hover-color);
    box-shadow: 0 25px 50px -12px rgba(var(--lpx-primary-rgb, 157, 67, 0), 0.28);
}

.btn-primary:disabled,
.btn-primary.disabled,
.btn-brand:disabled,
.btn-brand.disabled {
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

.btn-outline-primary {
    color: var(--triarch-primary);
    border-color: color-mix(in srgb, var(--triarch-primary) 46%, var(--triarch-border));
}

.btn-outline-primary:hover {
    color: var(--triarch-primary-strong);
    background: rgba(157, 67, 0, 0.08);
    border-color: var(--triarch-primary);
}

/* Secondary button — neutral slate, no purple Bootstrap default */
.btn-secondary,
.btn-outline-secondary {
    --bs-btn-color: var(--triarch-text-soft);
    --bs-btn-border-color: var(--triarch-outline, #dfe3e7);
    --bs-btn-hover-color: var(--triarch-text);
    --bs-btn-hover-bg: var(--triarch-border, #eaeef2);
    --bs-btn-hover-border-color: var(--triarch-outline, #dfe3e7);
    --bs-btn-active-color: var(--triarch-text);
    --bs-btn-active-bg: var(--triarch-surface-dim, #d6dade);
    --bs-btn-active-border-color: var(--triarch-outline, #dfe3e7);
    --bs-btn-focus-shadow-rgb: 87, 101, 122;
    --bs-btn-disabled-color: var(--triarch-text-soft);
    --bs-btn-disabled-border-color: var(--triarch-border, #eaeef2);
}

.btn-secondary {
    background: var(--triarch-border, #eaeef2);
    color: var(--triarch-text);
}

/* Form checkboxes and radio buttons */
.form-check-input {
    border: 2px solid color-mix(in srgb, var(--triarch-text, #171c1f) 58%, var(--triarch-surface, #fff));
    background-color: var(--triarch-surface, #fff);
}

.form-check-input:checked {
    background-color: var(--triarch-primary);
    border-color: var(--triarch-primary);
}

.form-check-input:focus {
    border-color: color-mix(in srgb, var(--triarch-primary) 50%, transparent);
    box-shadow: 0 0 0 0.25rem rgba(157, 67, 0, 0.25);
}

.form-check-input:checked:hover {
    background-color: var(--triarch-accent);
    border-color: var(--triarch-accent);
}

.lpx-theme-dark .form-check-input,
[data-bs-theme="dark"] .form-check-input {
    border-color: color-mix(in srgb, var(--triarch-text, #dce6ef) 72%, var(--triarch-surface, #1e2530));
    background-color: color-mix(in srgb, var(--triarch-surface, #1e2530) 88%, #ffffff);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16);
}

/* Form switches */
.form-switch .form-check-input:checked {
    background-color: var(--triarch-primary);
    border-color: var(--triarch-primary);
}

/* Confirm dialogs (abp.message.confirm). LeptonX runs the button row in reverse and draws Cancel as an
   underlined link, so the dialog read "Yes, Cancel". The standard (docs/ui-standard.md §5) puts Cancel first
   and the action last, with Cancel as the outline button. ABP already writes Cancel first in the markup, so
   the row only has to run in document order — which also makes the tab order match what is on screen. */
.swal2-container .swal2-modal .swal2-actions {
    flex-direction: row;
}
.swal2-container .swal2-modal button.swal2-cancel {
    padding: 11px 28px;
    border: 1px solid var(--triarch-outline) !important;
    background-color: transparent;
    color: var(--triarch-text);
    font-size: 16px;
    text-decoration: none;
}
.swal2-container .swal2-modal button.swal2-cancel:hover,
.swal2-container .swal2-modal button.swal2-cancel:focus-visible {
    background-color: var(--triarch-border);
}

/* Locked fields — a disabled input sits on the recessed surface in every theme (Bootstrap's own grey is a
   blue slate in dark). Read-only is not shaded here: date pickers use read-only inputs that still open. */
.form-control:disabled,
.form-select:disabled {
    background-color: var(--triarch-surface-soft);
}

/* Select / input focus ring */
.form-control:focus,
.form-select:focus {
    border-color: color-mix(in srgb, var(--triarch-primary) 50%, transparent);
    box-shadow: 0 0 0 0.25rem rgba(157, 67, 0, 0.2);
}

/* ── LeptonX palette bridge ────────────────────────────────────────────
   LeptonX's bootstrap-light.css / bootstrap-dark.css hard-code its own brand
   pink (#f72585), primary blue (#355dff) and danger crimson (#c00d49) as literal colours — several with
   !important — so --lpx-brand / --lpx-primary never reach them. Without this
   block, active tabs, checked switches/checkboxes, slider thumbs, the "brand"
   and "primary" helper classes and select highlights render pink or blue, and
   danger buttons, text and invalid fields a crimson that isn't ours.
   !important below only where LeptonX's own rule uses it. */
.lpx-theme-light,
.lpx-theme-dim,
.lpx-theme-dark {
    --bs-primary: var(--triarch-primary);
    --bs-primary-rgb: var(--lpx-primary-rgb, 157, 67, 0);
    --bs-danger: var(--triarch-danger);
    --bs-form-invalid-color: var(--triarch-danger);
    --bs-form-invalid-border-color: var(--triarch-danger);
    /* Links and link buttons (.btn-link) take the action colour; LeptonX's are blue. Bootstrap paints
       <a> from the -rgb triplet and .btn-link from the plain colour, so both are set. */
    --bs-link-color: var(--triarch-link);
    --bs-link-hover-color: var(--triarch-link-hover);
}

/* A dropdown menu's chosen item takes the action tint; LeptonX sets its pink on .dropdown-menu, so the
   variables are set there too, where they win. */
.lpx-theme-light .dropdown-menu,
.lpx-theme-dim .dropdown-menu,
.lpx-theme-dark .dropdown-menu {
    --bs-dropdown-link-active-bg: var(--triarch-action-tint);
    --bs-dropdown-link-active-color: var(--triarch-action-fg);
}

.lpx-theme-light,
.lpx-theme-dim {
    --bs-danger-rgb: 180, 35, 24;      /* --triarch-danger-fg #b42318 */
    --bs-link-color-rgb: 157, 67, 0;
    --bs-link-hover-color-rgb: 122, 52, 0;
}

.lpx-theme-dark {
    --bs-danger-rgb: 255, 143, 134;    /* --triarch-danger-fg #ff8f86 */
    --bs-link-color-rgb: 255, 154, 82;
    --bs-link-hover-color-rgb: 255, 182, 144;
}

.form-check-input:checked,
.form-switch .form-check-input:checked,
.form-check-input[type="checkbox"]:indeterminate {
    background-color: var(--triarch-primary) !important;
    border-color: var(--triarch-primary) !important;
}

.form-check-input:checked:hover,
.form-switch .form-check-input:checked:hover {
    background-color: var(--triarch-accent) !important;
    border-color: var(--triarch-accent) !important;
}

.form-check-input:focus,
.nav-link:focus-visible {
    box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--triarch-primary) 25%, transparent);
}

.form-range::-webkit-slider-thumb { background-color: var(--triarch-primary); }
.form-range::-moz-range-thumb { background-color: var(--triarch-primary); }

/* ── Option switch: a two-way switch that names the side it is on ─────────────────────────────────────
   For choosing between two named things (Turnkey / Parts & Smarts), where a plain on/off switch reads as
   "the first one is turned off". The pill is always brand; the knob moves and the name changes. Sized to a
   knob, not a button: the pill fits the name on show (keep it at the end of a flex row so its outer edge
   stays put). Unchecked = the first option, knob right; checked = the second, knob left.
   Markup: <button type="button" class="ta-option-switch" role="switch" aria-checked="false">
             <span class="ta-option-switch__names">
               <span class="ta-option-switch__name" data-for="off">First</span>
               <span class="ta-option-switch__name" data-for="on">Second</span>
             </span>
             <span class="ta-option-switch__knob" aria-hidden="true"></span>
           </button> */
.ta-option-switch {
    position: relative;
    display: inline-flex;
    align-items: center;
    flex: none;
    height: 20px;
    padding: 0 21px 0 8px;
    border: 0;
    border-radius: 999px;
    background: var(--triarch-primary);
    color: var(--triarch-surface);
    font-family: var(--triarch-font-mono);
    font-size: 11px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
    cursor: pointer;
    transition: var(--transition-color), padding var(--duration-fast) var(--ease-standard);
}
.ta-option-switch:hover { background: var(--triarch-accent); }
.ta-option-switch:focus-visible {
    outline: 0;
    box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--triarch-primary) 25%, transparent);
}
.ta-option-switch[aria-checked="true"] { padding: 0 8px 0 21px; }
.ta-option-switch[aria-checked="false"] .ta-option-switch__name[data-for="on"],
.ta-option-switch[aria-checked="true"] .ta-option-switch__name[data-for="off"] { display: none; }
.ta-option-switch__knob {
    position: absolute;
    top: 3px;
    left: calc(100% - 17px);
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--triarch-surface);
    transition: left var(--duration-fast) var(--ease-standard);
}
.ta-option-switch[aria-checked="true"] .ta-option-switch__knob { left: 3px; }
.ta-option-switch.is-busy { opacity: .55; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
    .ta-option-switch, .ta-option-switch__knob { transition: none; }
}

select.form-select option:checked,
select.form-select option:focus,
select.form-select option:active {
    background: var(--triarch-primary) !important;
    color: var(--triarch-on-action, #ffffff) !important;
}

/* Tabs — active underline, tab dropdowns, pills */
.nav-tabs {
    --bs-nav-tabs-link-active-border-color: var(--triarch-accent);
}

.nav-tabs .nav-item .nav-link.active {
    border-bottom-color: var(--triarch-accent);
}

.nav-tabs .dropdown-menu {
    border-top-color: var(--triarch-accent);
}

.nav-pills {
    --bs-nav-pills-link-active-color: var(--triarch-primary);
    --bs-nav-pills-link-active-bg: var(--triarch-primary-tint);
}

.pagination .page-item:not(.active) .page-link:hover,
.pagination .page-item:not(.active) .page-link:focus,
.pagination .page-item:not(.active) .page-link:active {
    color: var(--triarch-primary) !important;
}

/* Helper classes — brand and primary both resolve to the Triarch primary */
.text-primary,
.text-brand {
    color: var(--triarch-primary) !important;
}

.bg-primary,
.bg-brand {
    background-color: var(--triarch-primary) !important;
}

.bg-primary.soft,
.bg-brand.soft,
.badge.bg-primary.soft,
.badge.bg-brand.soft {
    color: var(--triarch-primary) !important;
    background-color: var(--triarch-primary-tint) !important;
}

.badge.bg-primary,
.badge.bg-brand {
    color: var(--triarch-on-action, #ffffff) !important;
    background-color: var(--triarch-primary) !important;
}

.btn-primary.soft,
.btn-brand.soft {
    --bs-btn-color: var(--triarch-primary);
    --bs-btn-bg: var(--triarch-primary-tint);
    --bs-btn-hover-color: var(--triarch-primary-strong);
    --bs-btn-hover-bg: color-mix(in srgb, var(--triarch-primary) 20%, transparent);
    box-shadow: none;
}

.btn-primary.grey,
.btn-brand.grey {
    --bs-btn-color: var(--triarch-primary);
    --bs-btn-hover-color: var(--triarch-primary-strong);
    box-shadow: none;
}

.table-primary,
.table-brand {
    --bs-table-bg: var(--triarch-primary-tint);
    background-color: var(--triarch-primary-tint);
}

.alert-primary,
.alert-brand {
    background: var(--triarch-primary-tint);
    border-color: color-mix(in srgb, var(--triarch-primary) 30%, transparent);
}

/* Danger — LeptonX's crimson (#c00d49) becomes the Triarch danger red */
.text-danger {
    color: var(--triarch-danger) !important;
}

/* Warning — LeptonX's orange (#ff9f38) is 2:1 on white; the warning text token is readable. */
.text-warning {
    color: var(--triarch-warning-fg) !important;
}

.bg-danger {
    background-color: var(--triarch-danger) !important;
}

.bg-danger.soft,
.badge.bg-danger.soft {
    color: var(--triarch-danger) !important;
    background-color: color-mix(in srgb, var(--triarch-danger) 10%, transparent) !important;
}

.badge.bg-danger {
    color: var(--triarch-on-danger, #ffffff) !important;
    background-color: var(--triarch-danger) !important;
}

/* Text on the solid fill is --triarch-on-danger: the fill is a light red in dark theme, where
   white text is under 3:1. */
.btn-danger {
    --bs-btn-color: var(--triarch-on-danger, #ffffff);
    --bs-btn-hover-color: var(--triarch-on-danger, #ffffff);
    --bs-btn-active-color: var(--triarch-on-danger, #ffffff);
    --bs-btn-disabled-color: var(--triarch-on-danger, #ffffff);
    --bs-btn-bg: var(--triarch-danger);
    --bs-btn-border-color: var(--triarch-danger);
    --bs-btn-hover-bg: color-mix(in srgb, var(--triarch-danger) 85%, #000000);
    --bs-btn-hover-border-color: color-mix(in srgb, var(--triarch-danger) 85%, #000000);
    --bs-btn-active-bg: color-mix(in srgb, var(--triarch-danger) 78%, #000000);
    --bs-btn-active-border-color: color-mix(in srgb, var(--triarch-danger) 78%, #000000);
    --bs-btn-disabled-bg: var(--triarch-danger);
    --bs-btn-disabled-border-color: var(--triarch-danger);
    --bs-btn-focus-shadow-rgb: var(--bs-danger-rgb);
}

.btn-outline-danger {
    --bs-btn-color: var(--triarch-danger);
    --bs-btn-border-color: var(--triarch-danger);
    --bs-btn-hover-color: var(--triarch-on-danger, #ffffff);
    --bs-btn-active-color: var(--triarch-on-danger, #ffffff);
    --bs-btn-hover-bg: var(--triarch-danger);
    --bs-btn-hover-border-color: var(--triarch-danger);
    --bs-btn-active-bg: var(--triarch-danger);
    --bs-btn-active-border-color: var(--triarch-danger);
    --bs-btn-disabled-color: var(--triarch-danger);
    --bs-btn-disabled-border-color: var(--triarch-danger);
    --bs-btn-focus-shadow-rgb: var(--bs-danger-rgb);
}

/* LeptonX dark forces every outline button's text white (!important), which left a danger button looking
   like a neutral one with a red rim. Red text at rest; white once it fills red on hover. */
.lpx-theme-dark .btn-outline-danger:not(:hover):not(:active):not(.active) {
    color: var(--triarch-danger) !important;
}

.btn-danger.soft {
    --bs-btn-color: var(--triarch-danger);
    --bs-btn-bg: color-mix(in srgb, var(--triarch-danger) 10%, transparent);
    --bs-btn-hover-color: var(--triarch-danger);
    --bs-btn-hover-bg: color-mix(in srgb, var(--triarch-danger) 20%, transparent);
}

.btn-danger.grey {
    --bs-btn-color: var(--triarch-danger);
    --bs-btn-hover-color: var(--triarch-danger);
}

.table-danger {
    --bs-table-bg: color-mix(in srgb, var(--triarch-danger) 10%, transparent);
    background-color: color-mix(in srgb, var(--triarch-danger) 10%, transparent);
}

.alert-danger {
    background: color-mix(in srgb, var(--triarch-danger) 12%, transparent);
    border-color: color-mix(in srgb, var(--triarch-danger) 30%, transparent);
}

.has-validation .input-group-text {
    border-color: var(--triarch-danger);
}

.was-validated .form-select:invalid,
.form-select.is-invalid,
.custom-select-wrapper.is-invalid > .custom-select-display {
    border-color: var(--triarch-danger) !important;
}

.custom-select-wrapper.is-invalid > .custom-select-display:focus {
    box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--triarch-danger) 25%, transparent);
}

/* LeptonX custom select (searchable dropdowns) */
.custom-select-display:focus {
    border-color: var(--triarch-primary);
    box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--triarch-primary) 25%, transparent);
}

.custom-option:hover,
.custom-option.focused {
    background-color: color-mix(in srgb, var(--triarch-primary) 8%, transparent);
}

.custom-option.focused {
    outline-color: color-mix(in srgb, var(--triarch-primary) 40%, transparent);
}

.custom-option.active {
    background-color: var(--triarch-primary-tint);
    color: var(--triarch-primary);
}

/* ════════════════════════════════════════════════════════════════════════
   Phase A — Design system utility & pattern classes (opt-in).
   Anything below is namespaced .t-* / .ta-* and never applies unless a
   consumer explicitly adopts it. Safe to add without auditing every page.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Typography helpers ─────────────────────────────────────────────── */
.t-h1, .t-h2, .t-h3, .t-h4, .t-h5, .t-h6,
.t-display, .t-display-lg {
    font-family: var(--triarch-font-display);
    color: var(--triarch-text);
    letter-spacing: -0.01em;
}
.t-h1 { font-size: 40px; line-height: 1.1;  font-weight: 700; letter-spacing: -0.02em; }
.t-h2 { font-size: 30px; line-height: 1.15; font-weight: 700; letter-spacing: -0.015em; }
.t-h3 { font-size: 22px; line-height: 1.25; font-weight: 600; }
.t-h4 { font-size: 18px; line-height: 1.3;  font-weight: 600; }
.t-h5 { font-size: 15px; line-height: 1.35; font-weight: 600; }
.t-h6 { font-size: 13px; line-height: 1.4;  font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--triarch-text-soft); }
.t-display    { font-size: 48px; line-height: 1.05; font-weight: 700; letter-spacing: -0.025em; }
.t-display-lg { font-size: 64px; line-height: 1.02; font-weight: 700; letter-spacing: -0.03em; }

.t-body     { font-size: 14px; line-height: 1.55; font-weight: 400; }
.t-figure   { font-family: var(--triarch-font-display); font-size: 24px; line-height: 1.15; font-weight: 700; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; color: var(--triarch-text); }
.t-body-sm  { font-size: 13px; line-height: 1.5;  font-weight: 400; color: var(--triarch-text-soft); }
.t-caption  { font-size: 12px; line-height: 1.4;  font-weight: 500; color: var(--triarch-text-soft); }
.t-label    { font-size: 11px; line-height: 1.2;  font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em; color: var(--triarch-text-soft); }
.t-mono     { font-family: var(--triarch-font-mono); font-size: 12px; font-weight: 500; color: var(--triarch-text-soft); }

/* Shared clickable-identifier style for list-table cells — SR/SD numbers, project
   number, contact names, request-form titles. Neutral at rest so the table stays
   calm; shifts to the brand colour on hover/focus to signal it's a link (replaces
   the generic Bootstrap blue that bare <a> text was inheriting). No underline, so
   it also works on the multi-line block links (SR/SD) without underlining the sub row. */
.ta-cell-link { color: var(--triarch-text); text-decoration: none; }
/* Keep badge/pill chrome on their own colours; title, mono codes, and meta
   (e.g. "Updated …") shift to brand on hover/focus so the whole link reads as one. */
.ta-cell-link:hover,
.ta-cell-link:focus-visible { color: var(--triarch-text); }
.ta-cell-link:hover :where(.t-mono, .ta-tracking-cell__no, .ta-name-cell__title, .ta-name-cell__meta, .ta-name-cell__sub),
.ta-cell-link:focus-visible :where(.t-mono, .ta-tracking-cell__no, .ta-name-cell__title, .ta-name-cell__meta, .ta-name-cell__sub) { color: var(--triarch-primary); }

.ta-list-table.dataTable > thead > tr > th.ta-col-project,
.ta-list-table.dataTable > tbody > tr > td.ta-col-project {
    width: 200px;
    max-width: 200px;
}
.ta-col-project__cell { width: 100%; max-width: 200px; }

/* Fixed column widths for server-rendered list tables (BuildRoom My Work / Estimates / Quotes,
   Workflow templates) and for the lists that set their widths (.ta-list-table--fixed, below) — put
   the class on the <th> instead of an inline style="width:…". */
th.ta-col-version { width: 60px; }
th.ta-col-updated { width: 90px; }
th.ta-col-margin,
th.ta-col-quote   { width: 110px; }
th.ta-col-amount  { width: 120px; }
th.ta-col-status  { width: 130px; }
th.ta-col-trade,
th.ta-col-person  { width: 150px; }
th.ta-col-date,
th.ta-col-phase   { width: 170px; }
th.ta-col-outcome,
th.ta-col-link    { width: 200px; }
th.ta-col-stage   { width: 210px; }
th.ta-col-company { width: 240px; }
th.ta-col-versions { width: 250px; }
th.ta-col-min-md  { min-width: 12rem; }
th.ta-col-min-lg  { min-width: 20rem; }
.ta-col-project__line {
    display: block;
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ta-tracking-cell__no {
    font-family: var(--triarch-font-mono);
    font-weight: 600;
    color: var(--triarch-text);
    line-height: 1.25;
}
.ta-tracking-cell__sub {
    font-size: 11px;
    color: var(--triarch-text-soft);
    margin-top: 1px;
}

/* ── Pills (category / generic) ─────────────────────────────────────── */
.ta-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 9px;
    border-radius: var(--radius-pill);
    background: var(--triarch-neutral-bg);
    color: var(--triarch-neutral-fg);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.5;
    white-space: nowrap;
}
/* One pill per role (docs/ui-standard.md §6). Each takes a role-token pair, so it has a light and a
   dark value and needs no per-page dark override. */
.ta-pill--neutral        { background: var(--triarch-neutral-bg); color: var(--triarch-neutral-fg); }
/* "New": a record that arrived recently, or has nothing before it to compare with. A neutral pill led
   by the live-orange dot, the one place that orange marks newness. Not info blue: that is Submitted. */
.ta-pill--new            { background: var(--triarch-neutral-bg); color: var(--triarch-neutral-fg); }
.ta-pill--new::before {
    content: "";
    flex: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--triarch-live);
}
.ta-pill--brand          { background: var(--triarch-action-tint); color: var(--triarch-action-fg); }
/* What kind of catalog record a row is: "Assembly", with the cubes icon, right after the name. A kind,
   not a state, so neutral; and a filled pill, so it never reads as the outlined brand tag beside it. */
.ta-pill--assembly       { background: var(--triarch-neutral-bg); color: var(--triarch-neutral-fg); }
.ta-pill--info           { background: var(--triarch-info-bg); color: var(--triarch-info-fg); }
.ta-pill--success        { background: var(--triarch-success-bg); color: var(--triarch-success-fg); }
.ta-pill--warn,
.ta-pill--warning        { background: var(--triarch-warning-bg); color: var(--triarch-warning-fg); }
.ta-pill--danger         { background: var(--triarch-danger-bg); color: var(--triarch-danger-fg); }
/* Retired names, kept so existing markup keeps working. New code uses --brand and --info. */
.ta-pill--cta            { background: var(--triarch-action-tint); color: var(--triarch-action-fg); }
.ta-pill--primary        { background: var(--triarch-info-bg); color: var(--triarch-info-fg); }
/* Panel label pill (the kicker in an offcanvas header). It names the panel, it is not a warning, so
   it takes the brand tint. Panels written with --warn in the eyebrow row get the same look. */
.ta-pill--kicker,
.ta-offcanvas-eyebrow .ta-pill--warn { background: var(--triarch-action-tint); color: var(--triarch-action-fg); }
/* A pill whose meaning lives in its tooltip reads as "hover for help". */
.ta-pill[data-bs-toggle="tooltip"] { cursor: help; }

/* Service category tints — reuse on every list/detail that shows category.
   Still fixed light tints in both themes: there are nine categories and six identity colours, so
   moving these to --triarch-cat-* needs a mapping decision (ControlRoom step of the rollout). */
.ta-pill--planreview     { background: #f7e4d4; color: #9d4300; }
.ta-pill--inspection     { background: #d6efeb; color: #0f766e; }
.ta-pill--permit         { background: #fbe4dc; color: #9a3519; }
.ta-pill--certification  { background: #fff1d6; color: #8a5a00; }
.ta-pill--licence        { background: #e0e8f4; color: #475569; }
.ta-pill--complaint      { background: #fbe0e0; color: #ba1a1a; }
.ta-pill--recordsrequest { background: #eef1f5; color: #57657a; }
.ta-pill--zoning         { background: #ece4f4; color: #6b3a5e; }
.ta-pill--specialevent   { background: #ffe9d6; color: #b85b1a; }

/* BuildRoom trade pills: one identity colour per trade (docs/ui-standard.md §2). Identity colours
   never mean a state, so no trade is amber, red, green or blue. */
.ta-pill--firealarm        { background: var(--triarch-cat-1-bg); color: var(--triarch-cat-1-fg); }
.ta-pill--massnotification { background: var(--triarch-cat-2-bg); color: var(--triarch-cat-2-fg); }
.ta-pill--sprinkler        { background: var(--triarch-cat-3-bg); color: var(--triarch-cat-3-fg); }
.ta-pill--lowvoltage       { background: var(--triarch-cat-4-bg); color: var(--triarch-cat-4-fg); }
.ta-pill--firepump         { background: var(--triarch-cat-5-bg); color: var(--triarch-cat-5-fg); }
.ta-pill--security         { background: var(--triarch-cat-6-bg); color: var(--triarch-cat-6-fg); }

/* ── Toolbar icon count badges ──────────────────────────────────────────
   These re-apply LeptonX's own native toolbar-count badge, .menu-item-badge.
   LeptonX defines that badge (size 18px, var(--lpx-radius), brand fill,
   position: absolute; top: 0; right: 10px) in the side-menu layout bundle, but
   gates it behind `.lpx-menu-item-link.active-menu-item` — a state only set on
   the selected left-nav item. Our notification bell and chat are custom toolbar
   widgets, not active nav items, so that selector never matches them; we re-use
   the same class + the same LeptonX values here instead of inventing our own.

   Anchored to the position-relative `.menu-item-icon` wrapper and right-aligned
   (no translate) so multi-digit counts like "99+" grow left over the glyph
   rather than spilling past the toolbar's right edge. Colour follows the
   surface: brand orange for chat (LeptonX's default --lpx-brand), danger red
   for the alert bell. */
.lpx-toolbar .menu-item-badge {
    position: absolute;
    top: -0.45rem;
    right: -0.15rem;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    border-radius: var(--lpx-radius);
    background: var(--lpx-brand);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 18px;
    text-align: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.lpx-toolbar .menu-item-badge--alert {
    background: var(--triarch-danger);
}

/* ── User menu: department (not a second tenant line) ─────────────────
   LeptonX's .lpx-context-menu-user-tenant is the company slot. The
   organisation-unit line must not reuse it — contractors would see two
   identical stacked names and read the department as a second company.
   Muted colour + normal weight, scoped to theme classes (not :root). */
.lpx-theme-light .lpx-context-menu-user-department,
.lpx-theme-dim .lpx-context-menu-user-department {
    display: block;
    font-size: 0.75rem;
    font-weight: 400;
    color: var(--triarch-text-muted);
}

.lpx-theme-dark .lpx-context-menu-user-department {
    display: block;
    font-size: 0.75rem;
    font-weight: 400;
    color: var(--triarch-text-muted);
}

/* ── Runtime-injected toolbar items (ControlRoom page-context icons) ─────
   Injected items always sit at the BOTTOM of the right toolbar, below the
   standing icons (bell, chat, code advisor). Toolbar contributor order is
   not reliable across modules, so placement is enforced visually: the
   toolbar list becomes a flex column and items whose component output
   carries .ta-toolbar-injected get a high flex order. The first injected
   item (DOM order) draws a hairline above itself as the separator; the
   :has() guard means pages where the components render empty show neither
   icons nor a stray divider. */
nav.lpx-toolbar > ul.lpx-nav-menu {
    display: flex;
    flex-direction: column;
}
nav.lpx-toolbar > ul.lpx-nav-menu > li:has(> .ta-toolbar-injected) {
    order: 9;
    border-top: 1px solid var(--triarch-border);
    margin-top: 8px;
    padding-top: 8px;
}
nav.lpx-toolbar > ul.lpx-nav-menu > li:has(> .ta-toolbar-injected) ~ li:has(> .ta-toolbar-injected) {
    border-top: 0;
    margin-top: 0;
    padding-top: 0;
}

/* Defensive pin for the notification bell badge.
   The bell ships from the InApp notification module's compiled Razor view
   (Pages/Shared/Components/Notification/Default.cshtml), which is baked into the
   module DLL. Incremental host builds frequently fail to re-embed a .cshtml
   *content* change, so the module can serve a stale badge markup that lags the
   source (e.g. the old Bootstrap `badge rounded-pill bg-danger` corner pill).
   To keep the bell matching the chat badge regardless of which compiled markup
   the module serves, pin its appearance here by id — `!important` is required to
   override Bootstrap's `top-0 / start-100 / translate-middle` utility classes,
   which are themselves `!important`. Values mirror .menu-item-badge above. The
   badge already sits inside the position-relative .menu-item-icon wrapper, so
   `right` anchors it to the glyph exactly like the chat badge. */
.lpx-toolbar #notifBadge {
    position: absolute !important;
    top: -0.45rem !important;
    left: auto !important;
    right: -0.15rem !important;
    transform: none !important;
    min-width: 18px;
    width: auto !important;
    height: 18px;
    padding: 0 4px !important;
    border-radius: var(--lpx-radius) !important;
    background: var(--triarch-danger) !important;
    color: var(--triarch-on-danger, #ffffff);
    font-size: 10px;
    font-weight: 700;
    line-height: 18px;
    text-align: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* ── Offcanvas panels (chat / code advisor / docs, via offcanvas-manager.js) ──
   The global chat / code-advisor panels run backdrop-less on purpose so the
   user can keep working in the page behind them. Without a backdrop a white
   panel on the light app background nearly vanishes at the seam, so we carry
   the separation entirely in the panel's own edge: a crisp 1px seam line plus a
   deep, soft elevation shadow that makes it read as a surface floating above
   the page. Layered box-shadow — first stop is the hairline seam, second is the
   diffuse lift. Scoped to .ta-offcanvas-panel so LeptonX's own drawers are
   untouched. */
/* Targeted both by the marker class .ta-offcanvas-panel (added by
   offcanvas-manager.js for every AJAX panel) AND by the global panels' stable
   ids — the id selectors mean the treatment lands even if a cached/older
   offcanvas-manager.js hasn't applied the class yet. An id beats LeptonX's
   default `.offcanvas` shadow on specificity, so no !important is needed. */
.ta-offcanvas-panel,
#global-chat-panel.offcanvas,
#code-advisor-panel.offcanvas {
    box-shadow:
        -1px 0 0 0 rgba(23, 28, 31, 0.10),
        -28px 0 60px -18px rgba(23, 28, 31, 0.40);
}

.ta-offcanvas-panel.offcanvas-end,
#global-chat-panel.offcanvas-end,
#code-advisor-panel.offcanvas-end {
    border-left: 1px solid var(--triarch-border, #eaeef2);
}

.ta-offcanvas-panel.offcanvas-start {
    border-right: 1px solid var(--triarch-border, #eaeef2);
    box-shadow:
        1px 0 0 0 rgba(23, 28, 31, 0.10),
        28px 0 60px -18px rgba(23, 28, 31, 0.40);
}

.lpx-theme-dark .ta-offcanvas-panel,
.lpx-theme-dim .ta-offcanvas-panel,
.lpx-theme-dark #global-chat-panel.offcanvas,
.lpx-theme-dim #global-chat-panel.offcanvas,
.lpx-theme-dark #code-advisor-panel.offcanvas,
.lpx-theme-dim #code-advisor-panel.offcanvas {
    box-shadow:
        -1px 0 0 0 rgba(255, 255, 255, 0.08),
        -28px 0 60px -16px rgba(0, 0, 0, 0.60);
    border-color: var(--triarch-border);
}

/* Dark: a side panel sits on the same grey as cards, menus and dialogs. Bootstrap's own panel surface is a
   blue slate (#212529), and so are its secondary and tertiary fills, which left panels a different colour
   family from the page behind them. */
.lpx-theme-dark .ta-offcanvas-panel {
    --bs-offcanvas-bg: var(--triarch-surface);
    --bs-body-bg: var(--triarch-surface);
    --bs-secondary-bg: var(--triarch-surface-soft);
    --bs-tertiary-bg: var(--triarch-surface-soft);
    background-color: var(--triarch-surface);
}

/* ── Status pill (ACTIVE / INACTIVE, permit-state) ──────────────────── */
.ta-status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 9px 3px 7px;
    border-radius: var(--radius-pill);
    background: var(--triarch-neutral-bg);
    color: var(--triarch-neutral-fg);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
}
.ta-status__dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    display: inline-block;
}
.ta-status--active    { background: var(--triarch-success-bg); color: var(--triarch-success-fg); }
.ta-status--inactive  { background: var(--triarch-neutral-bg); color: var(--triarch-neutral-fg); }
.ta-status--submitted { background: var(--triarch-info-bg); color: var(--triarch-info-fg); }
.ta-status--review    { background: var(--triarch-warning-bg); color: var(--triarch-warning-fg); }
.ta-status--action    { background: var(--triarch-action-tint); color: var(--triarch-action-fg); }
.ta-status--approved  { background: var(--triarch-success-bg); color: var(--triarch-success-fg); }
.ta-status--issued    { background: var(--triarch-action-tint); color: var(--triarch-action-fg); }
.ta-status--rejected  { background: var(--triarch-danger-bg); color: var(--triarch-danger-fg); }

/* BuildRoom project phases. One colour per meaning (docs/ui-standard.md §6), not one per phase:
   the label names the phase, the colour says what kind of state it is. Token pairs carry their
   own dark values, so there is no dark block.
     neutral  not started or finished      warning  in progress or under review
     info     sent on, waiting on others    success  a positive outcome
     action   active work                   danger   a negative outcome */
.ta-status--opportunity,
.ta-status--closed,
.ta-status--declined        { background: var(--triarch-neutral-bg); color: var(--triarch-neutral-fg); }
.ta-status--bidding,
.ta-status--leveling        { background: var(--triarch-warning-bg); color: var(--triarch-warning-fg); }
.ta-status--bid-submitted,
.ta-status--handed-off      { background: var(--triarch-info-bg); color: var(--triarch-info-fg); }
.ta-status--awarded,
.ta-status--permitted       { background: var(--triarch-success-bg); color: var(--triarch-success-fg); }
.ta-status--in-construction { background: var(--triarch-action-tint); color: var(--triarch-action-fg); }
.ta-status--lost            { background: var(--triarch-danger-bg); color: var(--triarch-danger-fg); }

/* ── Category icon (rounded square in name cells) ───────────────────── */
.ta-cat-icon {
    width: 30px;
    height: 30px;
    border-radius: var(--radius-sm);
    background: var(--triarch-surface-soft);
    color: var(--triarch-text-soft);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 13px;
}
.ta-cat-icon--planreview     { background: #f7e4d4; color: #9d4300; }
.ta-cat-icon--inspection     { background: #d6efeb; color: #0f766e; }
.ta-cat-icon--permit         { background: #fbe4dc; color: #9a3519; }
.ta-cat-icon--certification  { background: #fff1d6; color: #8a5a00; }
.ta-cat-icon--licence        { background: #e0e8f4; color: #475569; }
.ta-cat-icon--complaint      { background: #fbe0e0; color: #ba1a1a; }
.ta-cat-icon--recordsrequest { background: var(--triarch-surface-soft); color: var(--triarch-text-soft); box-shadow: inset 0 0 0 1px var(--triarch-border); }   /* also the generic row tile */
.ta-cat-icon--zoning         { background: #ece4f4; color: #6b3a5e; }
.ta-cat-icon--specialevent   { background: #ffe9d6; color: #b85b1a; }
/* BuildRoom trade icons: the same identity colour as the trade's pill. */
.ta-cat-icon--firealarm        { background: var(--triarch-cat-1-bg); color: var(--triarch-cat-1-fg); }
.ta-cat-icon--massnotification { background: var(--triarch-cat-2-bg); color: var(--triarch-cat-2-fg); }
.ta-cat-icon--sprinkler        { background: var(--triarch-cat-3-bg); color: var(--triarch-cat-3-fg); }
.ta-cat-icon--lowvoltage       { background: var(--triarch-cat-4-bg); color: var(--triarch-cat-4-fg); }
.ta-cat-icon--firepump         { background: var(--triarch-cat-5-bg); color: var(--triarch-cat-5-fg); }
.ta-cat-icon--security         { background: var(--triarch-cat-6-bg); color: var(--triarch-cat-6-fg); }
.ta-cat-icon--vendor           { background: var(--triarch-cat-6-bg); color: var(--triarch-cat-6-fg); }

/* ── Toolbar pattern (search + chip filters + filters button) ───────── */
.ta-toolbar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
}
.ta-toolbar__spacer { flex: 1 1 auto; }
/* The order menu and the view switch, kept together at the end of a list toolbar. */
.ta-toolbar__views {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}
/* ── Compact toolbar (laptop and below) ─────────────────────────────
   A list toolbar that carries the order menu and the view switch (Projects) needs about 1380px to put
   every word on one row; a laptop with the side menu open has about 1200. Below 1600px the row stays one
   row by giving up the words the icons already carry: "Filters" and List / Cards become their icons (the
   words stay for screen readers and in the tooltips), the sort button keeps only its value, and the
   search box narrows to 280px. The status chips keep their words and counts: they are what a reader
   scans. Under 992px the grid rules further down take over the search box and the filter button. */
@media (max-width: 1599.98px) {
    /* Gaps, chips, the switch and the filter button each give up a few pixels: a 1366px laptop (toolbar
       1101px) then holds the row with the longest sort label, "Project name" and its arrow, at 1093px.
       The search box keeps 8px beyond its placeholder (206px of text, 62px of padding). */
    .ta-toolbar:has(.ta-toolbar__views) {
        column-gap: var(--space-2);
    }

    .ta-toolbar:has(.ta-toolbar__views) .ta-chip.btn {
        padding-left: 10px;
        padding-right: 10px;
    }

    .ta-toolbar:has(.ta-toolbar__views) .ta-toolbar__search {
        flex-basis: 276px;
    }

    .ta-toolbar__views .dropdown-toggle > .ta-soft,
    .ta-toolbar:has(.ta-toolbar__views) .ta-segmented__label,
    .ta-toolbar:has(.ta-toolbar__views) .ta-filters-btn > span:not(.ta-filters-badge) {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }

    .ta-toolbar:has(.ta-toolbar__views) .ta-segmented__option {
        padding: 5px 9px;
    }

    .ta-toolbar:has(.ta-toolbar__views) .ta-filters-btn {
        gap: var(--space-1);
        min-width: 34px;
        padding-left: 9px;
        padding-right: 9px;
        justify-content: center;
    }

    .ta-toolbar:has(.ta-toolbar__views) .ta-filters-btn .fa-angle-down {
        display: none;
    }
}
.ta-toolbar__search {
    position: relative;
    flex: 0 1 340px;
    min-width: 220px;
    margin: 0;
}
.ta-toolbar__search-icon {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--triarch-text-soft);
    font-size: 13px;
    pointer-events: none;
}
.ta-toolbar__search-input {
    padding-left: 34px;
    padding-right: 28px;
    height: 36px;
}
.ta-toolbar__search-input:focus {
    border-color: var(--triarch-focus);
    box-shadow: 0 0 0 3px var(--triarch-focus-soft);
}
.ta-toolbar__search-clear {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    padding: 0 2px;
    line-height: 1;
    color: var(--triarch-text-soft, #6c757d);
    cursor: pointer;
}
.ta-toolbar__search-clear:hover { color: var(--triarch-text, #1f2328); }
.ta-toolbar__chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
}

/* ── Chip filter (apply to <abp-button class="ta-chip">) ────────────── */
.ta-chip.btn {
    border-radius: var(--radius-pill);
    padding: 6px 12px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.2;
    color: var(--triarch-text-soft);
    background: transparent;
    border-color: var(--triarch-border);
    transition: var(--transition-color);
    white-space: nowrap;
}
.ta-chip.btn:hover,
.ta-chip.btn:focus {
    background: var(--triarch-surface-soft);
    color: var(--triarch-text);
    border-color: var(--triarch-border);
    box-shadow: none;
}
/* Reached with the keyboard: hover and focus share a fill, and the rule above clears Bootstrap's focus
   shadow, so without the ring a focused chip could not be told from the one beside it. */
.ta-chip.btn:focus-visible {
    outline: 0;
    box-shadow: var(--focus-ring);
}
.ta-chip__count {
    font-weight: 500;
    color: var(--triarch-text-soft);
    opacity: 0.85;
    font-variant-numeric: tabular-nums;
}

.ta-chip__count:empty {
    display: none;
}

.ta-chip.btn.is-active .ta-chip__count {
    color: var(--triarch-cta);
}

.ta-chip.btn.is-active,
.ta-chip.btn.is-active:hover,
.ta-chip.btn.is-active:focus {
    background: var(--triarch-cta-tint);
    color: var(--triarch-cta-hover);
    border-color: var(--triarch-cta-outline);
}

/* ── Filters button badge ───────────────────────────────────────────── */
.ta-filters-btn.btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: 36px;
}
.ta-filters-badge {
    background: var(--triarch-cta-tint);
    color: var(--triarch-cta-hover);
    font-size: 10px;
    font-weight: 700;
    border-radius: var(--radius-pill);
    padding: 1px 7px;
    line-height: 1.4;
}

/* ── Advanced-filter drawer (inside toolbar card) ─────────────────────
   Goal: keep ABP/LeptonX default look-and-feel for labels and inputs,
   but compact the row so plain inputs, abp-select, abp-date-picker and
   select2-enhanced ajax lookups all render at a uniform 34px height.
   Without these rules LeptonX's layout-bundle.css forces select2 to
   42px + 12px padding, breaking alignment with the smaller controls. */
.ta-advanced-filters {
    margin-top: var(--space-3);
    padding-top: var(--space-4);
    border-top: 1px dashed var(--triarch-border);
}
.ta-advanced-filters .form-label {
    font-size: 13px;
    font-weight: 500;
    margin-bottom: 4px;
}
.ta-advanced-filters .mb-3 { margin-bottom: 0.75rem !important; }

.ta-advanced-filters .form-control,
.ta-advanced-filters .form-select,
.ta-advanced-filters .input-group > .form-control {
    padding: 5px 10px;
    font-size: 13px;
    min-height: 34px;
    height: 34px;
}
.ta-advanced-filters .input-group { width: 100%; flex-wrap: nowrap; }
.ta-advanced-filters .input-group-text,
.ta-advanced-filters .input-group .btn {
    padding: 5px 10px;
    height: 34px;
    min-height: 34px;
    font-size: 13px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Select2 (single-select). LeptonX's js-bundle.css sets
   `.select2 .select2-selection { height: 46px !important; padding:
   0.675rem 3.75rem !important }` so we have to match both the !important
   *and* go one class deeper to win the cascade. */
.ta-advanced-filters .select2-container { width: 100% !important; }
.ta-advanced-filters .select2 .select2-selection,
.ta-advanced-filters .select2-container--default .select2-selection--single {
    height: 34px !important;
    min-height: 34px !important;
    padding: 0 28px 0 10px !important;
    border-radius: var(--radius-md, 6px) !important;
}
.ta-advanced-filters .select2 .select2-selection .select2-selection__rendered,
.ta-advanced-filters .select2-container--default .select2-selection--single .select2-selection__rendered {
    line-height: 32px !important;
    padding-left: 0 !important;
    font-size: 13px !important;
}
.ta-advanced-filters .select2-container--default .select2-selection--single .select2-selection__arrow {
    height: 32px;
}

/* ── Bulk-delete banner (appears above table when rows selected) ────── */
.ta-bulk-banner {
    background: var(--triarch-cta-tint);
    border: 1px solid var(--triarch-cta-outline);
    border-radius: var(--radius-md);
    padding: 10px 14px;
    margin-bottom: var(--space-3);
    display: flex;
    align-items: center;
    gap: var(--space-3, 12px);
}
.ta-bulk-banner hr { display: none; }
.ta-bulk-banner > .d-flex {
    margin-bottom: 0 !important;
    width: 100%;
    align-items: center;
}
.ta-bulk-banner .lead,
.ta-bulk-banner__count {
    font-size: 13px;
    font-weight: 600;
    color: var(--triarch-cta-hover);
    line-height: 1.4;
}
.ta-bulk-banner__actions {
    display: flex;
    align-items: center;
    gap: var(--space-2, 8px);
    margin-left: auto;
}
.ta-bulk-banner__clear.btn {
    color: var(--triarch-cta-hover);
    text-decoration: none;
    font-weight: 600;
}

/* ── List-table polish (clean head, hover rows, optional theme stripe) ─ */
.ta-list-table {
    margin: 0 !important;
    width: 100% !important;
}
/* Column heads use the label recipe (docs/ui-standard.md §3): 11px / 600 / .1em, uppercase. */
.ta-list-table > thead > tr > th {
    background: var(--triarch-surface-soft);
    border-top: none;
    border-bottom: 1px solid var(--triarch-border);
    white-space: nowrap;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ta-list-table > thead > tr > th .dt-column-title {
    font-size: inherit;
    font-weight: inherit;
    letter-spacing: inherit;
}
/* Sorting by keyboard. DataTables puts the control inside the heading as a 12px button
   (span.dt-column-order, reached with Tab, worked with Enter), and the browser's own focus mark is a
   hairline round those 12px. A ring is drawn round the whole heading as well, where it can be seen;
   the control keeps its own mark. An outline, not a shadow: a table cell's shadow is where Bootstrap
   paints its fill. Every DataTable gets it, list page or not. */
table.dataTable > thead > tr > th:has(.dt-column-order:focus-visible) {
    outline: 2px solid var(--triarch-focus);
    outline-offset: -2px;
}

/* Row actions. ABP draws the row menu as a filled "Actions" button on every row; in a list it is a secondary
   control (the page's one primary sits in the header).
   - A row MENU becomes the three-dot icon button (vertical dots, the narrowest form): soft grey at rest, the action colour on hover, on keyboard
     focus and while its menu is open. The word "Actions" stays in the button for screen readers; it is only
     drawn at zero size, and ABP's gear icon and the caret give way to the dots.
   - A row with a single action keeps its label and takes the outline look. */
/* The row-menu column has no visible heading (the header keeps a hidden "Actions" for screen readers) and is
   exactly as wide as its button. The cells on either side give up most of their padding towards it, so the
   dots sit close to the checkbox and to the name instead of in a gap of their own.
   The header paddings need !important: LeptonX sets `table.dataTable thead th { padding-right: 1.5rem
   !important }` to leave room for sort arrows, which these two columns never show. */
.ta-list-table > thead > tr > th.ta-col-actions,
.ta-list-table > tbody > tr > td:has(> .abp-action-button) {
    /* A fixed width, not a share: a table with fixed column widths would squeeze a percentage to nothing. */
    width: 24px;
    min-width: 24px;
    padding-left: 0 !important;
    padding-right: 0 !important;
    white-space: nowrap;
}
/* First column of the table (no checkbox before it): keep the dots off the card edge. */
.ta-list-table > thead > tr > th.ta-col-actions:first-child,
.ta-list-table > tbody > tr > td:first-child:has(> .abp-action-button) {
    width: 34px;
    min-width: 34px;
    padding-left: 10px !important;
}
.ta-list-table > thead > tr > th.select-checkbox:has(+ th.ta-col-actions),
.ta-list-table > tbody > tr > td.select-checkbox:has(+ td > .abp-action-button) {
    /* The width is stated so a fixed-layout table (Vendors) cannot shrink the column under its checkbox. */
    width: 38px;
    min-width: 38px;
    padding-right: 4px !important;
}
.ta-list-table > thead > tr > th.ta-col-actions + th,
.ta-list-table > tbody > tr > td:has(> .abp-action-button) + td {
    padding-left: 6px !important;
}
/* DataTables writes each column's width on its <col>, and in a fixed-layout table (Catalog's lists) that is
   what decides the width: it measured the checkbox column as the bare 16px box. State both columns there too. */
.ta-list-table:has(> thead > tr > th.select-checkbox:first-child + th.ta-col-actions) > colgroup > col:first-child {
    width: 38px !important;
}
.ta-list-table:has(> thead > tr > th.select-checkbox:first-child + th.ta-col-actions) > colgroup > col:nth-child(2) {
    width: 24px !important;
}
.ta-list-table .abp-action-button > .btn-primary.dropdown-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 28px;
    padding: 0;
    border: 0;
    border-radius: var(--radius-md);
    background: transparent;
    box-shadow: none;
    color: var(--triarch-text-soft);
    font-size: 0;
    line-height: 1;
}
.ta-list-table .abp-action-button > .btn-primary.dropdown-toggle > i {
    display: none;
}
.ta-list-table .abp-action-button > .btn-primary.dropdown-toggle::after {
    content: "\f142";
    margin: 0;
    border: 0;
    font-family: "Font Awesome 7 Free", "Font Awesome 5 Free";
    font-size: 14px;
    font-weight: 900;
    line-height: 1;
    vertical-align: 0;
}
.ta-list-table .abp-action-button > .btn-primary.dropdown-toggle:hover,
.ta-list-table .abp-action-button > .btn-primary.dropdown-toggle:focus-visible,
.ta-list-table .abp-action-button > .btn-primary.dropdown-toggle.show,
.ta-list-table .abp-action-button > .btn-primary.dropdown-toggle[aria-expanded="true"] {
    background: var(--triarch-surface-dim);
    box-shadow: none;
    color: var(--triarch-action);
    transform: none;
}
.ta-list-table .abp-action-button > .btn-primary.dropdown-toggle:focus-visible {
    outline: 2px solid var(--triarch-focus);
    outline-offset: 2px;
}
.ta-list-table .btn-primary.abp-action-button {
    --bs-btn-color: var(--triarch-text);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--triarch-outline);
    --bs-btn-hover-color: var(--triarch-text);
    --bs-btn-hover-bg: var(--triarch-border);
    --bs-btn-hover-border-color: var(--triarch-outline);
    --bs-btn-active-color: var(--triarch-text);
    --bs-btn-active-bg: var(--triarch-surface-dim);
    --bs-btn-active-border-color: var(--triarch-outline);
    font-size: 12px;
    box-shadow: none;
}
.ta-list-table .btn-primary.abp-action-button:hover,
.ta-list-table .btn-primary.abp-action-button:focus {
    box-shadow: none;
    transform: none;
}
/* Helper text inside a row sits on the scale (Bootstrap's .small is a fraction of the cell size). */
.ta-list-table > tbody .small,
.ta-list-table > tbody small {
    font-size: 12px;
}
.ta-list-table > tbody > tr > td {
    padding: 13px 14px;
    border-top: none;
    border-bottom: 1px solid var(--triarch-border);
    font-size: 13px;
    vertical-align: middle;
    font-variant-numeric: tabular-nums;   /* amounts and counts line up digit for digit */
}

.ta-list-table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control {
    white-space: nowrap;
}
.ta-list-table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before {
    vertical-align: middle;
}
.ta-list-table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control > .abp-action-button {
    display: inline-block;
    vertical-align: middle;
}
.ta-list-table > tbody > tr:last-child > td { border-bottom: none; }
/* Bootstrap 5.3 paints the stripe as an inset box-shadow from
   --bs-table-bg-type. Stripe uses a Triarch mix, not --bs-table-striped-bg.
   Hover is turned off: --bs-table-hover-bg and --triarch-surface-soft both
   read as a blue wash, and the state variable would cover the stripe. */
.ta-list-table.table-striped {
    --bs-table-striped-bg: color-mix(in srgb, var(--triarch-surface-soft) 45%, var(--triarch-surface));
}
.ta-list-table {
    --bs-table-hover-bg: transparent;
    --bs-table-hover-color: inherit;
}
.ta-list-table > tbody > tr:hover > * {
    --bs-table-bg-state: var(--bs-table-bg-type, transparent);
    --bs-table-color-state: inherit;
}

/* Left-align numeric columns.
   DataTables auto-detects any column whose ordering data is numeric and adds
   .dt-type-numeric, which right-aligns the header, sort arrows, and cells. In
   these list grids that reads as a broken / empty column — the values hug the
   far right edge, leaving a blank gap next to the left-aligned header of the
   neighbouring column (and the header label drifts right under its own sort
   arrows). It also misfires on TEXT columns rendered from a numeric sort key
   (enum codes, "Customer Type", etc.). Force left alignment for visual
   consistency across every list page. This is presentation only — numeric
   ORDERING is unaffected. A column that genuinely wants right-aligned currency
   can opt back in with class="ta-cell-currency" on its column def — see the
   currency opt-in rule below. */
.ta-list-table.dataTable > thead > tr > th.dt-type-numeric,
.ta-list-table.dataTable > tbody > tr > td.dt-type-numeric {
    text-align: left;
}
/* DataTables also reverses the header flex (flex-direction: row-reverse) on
   numeric columns so the sort arrow stays beside a right-aligned number. Since
   we left-align above, undo the reversal too — otherwise the arrow renders on
   the LEFT of the title, butting against the previous column's right-edge arrow
   (the "doubled arrows" / floating-arrow look). Restore normal order so the
   arrow sits after the title on the right, exactly like text columns. */
.ta-list-table.dataTable th.dt-type-numeric div.dt-column-header {
    flex-direction: row;
}
/* Currency opt-in. Genuine money columns DO want the accounting convention —
   right-aligned values with the sort arrow on the left of the number. Add
   class="ta-cell-currency" to the column def to restore DataTables' native
   right-aligned numeric treatment (overriding the left-align defaults above).
   Pair it with a currency-formatted render (symbol + 2 decimals). */
.ta-list-table.dataTable > thead > tr > th.ta-cell-currency,
.ta-list-table.dataTable > tbody > tr > td.ta-cell-currency {
    text-align: right;
}
.ta-list-table.dataTable th.ta-cell-currency div.dt-column-header {
    flex-direction: row-reverse;
}

/* Post-redirect row highlight — applied for ~2.5s by
   triArch.controlRoom.listPage.highlightRowFromUrl() after a create/edit
   save to draw the user's eye to the row they just worked on.

   Uses inset box-shadow rather than background-color because Bootstrap
   tables, LeptonX theme rules, and DataTables striping all set
   background on td / tr at varying specificities — fighting those
   reliably is messy. An inset shadow paints OVER the cell background
   without competing for the same property, so the flash is visible
   regardless of theme. !important is on the animation property (not
   inside the keyframe, which the spec ignores) to defeat any rule that
   tries to set animation: none on tds. */
@keyframes ta-list-row-flash {
    0%, 35%  { box-shadow: inset 0 0 0 9999px var(--triarch-cta-tint, #fff3c4); }
    100%     { box-shadow: inset 0 0 0 9999px transparent; }
}
.ta-list-table > tbody > tr.ta-list-row--flash > td {
    animation: ta-list-row-flash 2.5s ease-out 0s 1 !important;
}

/* Name cell composition (icon + title + subtitle) */
.ta-name-cell {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}
.ta-name-cell__title {
    font-size: 14px;
    font-weight: 600;
    color: var(--triarch-text);
    line-height: 1.25;
}
.ta-name-cell__sub {
    font-size: 11px;
    color: var(--triarch-text-soft);
    margin-top: 1px;
}
/* Title line that carries a badge or a note marker (nameCell({ badges, note })). */
.ta-name-cell__head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
}
.ta-name-cell__head > .ta-name-cell__title { min-width: 0; }
.ta-name-cell__head > .ta-pill { flex: none; }
.ta-name-cell__note {
    flex: none;
    font-size: 12px;
    color: var(--triarch-text-soft);
    cursor: help;
}
/* The marker takes focus where the note cannot be read any other way; the tooltip opens on focus. */
.ta-name-cell__note:focus-visible {
    outline: 0;
    border-radius: var(--radius-xs);
    box-shadow: var(--focus-ring);
}

/* Stacked lines in a cell: a value over its companion (email over phone, published over draft). */
.ta-cell-line { display: block; }
.ta-cell-line--sub {
    font-size: 12px;
    color: var(--triarch-text-soft);
}

/* ── Set column widths (docs/ui-standard.md §7 "List columns") ──────────
   A list that adds .ta-list-table--fixed takes its widths from the classes on its <th>s, not from
   the text in its rows: compact columns are fixed and the name column takes what is left. Text
   stays on one line and is cut with an ellipsis; the full value is in the title. The page passes
   autoWidth: false to listPage.init, so DataTables does not pin its own measurements on the <col>s.
   Below 992px the table keeps the automatic layout and sideways scroll every list has there. */
@media (min-width: 992px) {
    .ta-list-table--fixed {
        table-layout: fixed;
        min-width: 860px;
    }
    .ta-list-table--fixed.ta-list-table--wide { min-width: 1080px; }
    /* The one flexible column besides the name: a share, so the two grow together. */
    .ta-list-table--fixed th.ta-col-contact { width: 30%; }
}
.ta-list-table--fixed .ta-name-cell {
    display: flex;
    min-width: 0;
}
.ta-list-table--fixed .ta-name-cell__text {
    flex: 1 1 auto;
    min-width: 0;
}
.ta-list-table--fixed .ta-name-cell__title,
.ta-list-table--fixed .ta-name-cell__sub,
.ta-list-table--fixed .ta-cell-line {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Bid due as a countdown (Projects list): the days left over the date. Once the bid is out, the date
   leads and the second line says where it stands. */
.ta-due__main,
.ta-value__main {
    font-size: 15px;
    font-weight: 700;
    line-height: 1.2;
    white-space: nowrap;
    /* The strong text colour, stated: a table cell's own colour is a mid grey in dark, which left a live
       figure dimmer than a stale one. */
    color: var(--triarch-text);
}
.ta-due__sub,
.ta-value__sub {
    font-size: 12px;
    color: var(--triarch-text-soft);
    white-space: nowrap;
}
.ta-due--over .ta-due__main { color: var(--triarch-danger-fg); }
.ta-due--soon .ta-due__main { color: var(--triarch-warning-fg); }
/* Passed long enough ago that hurrying no longer helps: the words stay, the alarm goes. */
.ta-due--stale .ta-due__main {
    color: var(--triarch-text-soft);
    font-weight: 600;
}
.ta-due--calm .ta-due__main {
    font-size: 13px;
    font-weight: 600;
}
/* A figure over where it comes from (Projects list: the bid's value over "Quoted · 17.5%"). The same two
   lines as the countdown. With nothing to show, the first line is words at body weight, so it does not
   read as a figure; a second line that needs acting on (.is-low) is the danger colour. */
th.ta-col-due   { width: 150px; }
th.ta-col-value { width: 164px; }
.ta-value__sub {
    overflow: hidden;
    text-overflow: ellipsis;
}
.ta-value--none .ta-value__main {
    font-size: 13px;
    font-weight: 500;
    color: var(--triarch-text-soft);
}
.ta-value__sub.is-low {
    color: var(--triarch-danger-fg);
    font-weight: 600;
}

/* One trade on one line (Projects list): its pill, the stage bar, the stage in words, and who has it.
   A row shows two; any others are one line of words (.ta-scope-more) that opens the row's band.
   Under 1800px the bar goes and the words stay: with the bar a 1600px window left the name column
   425px, and half the project names were cut. */
th.ta-col-trades { width: 392px; }
.ta-scope-line {
    display: grid;
    grid-template-columns: minmax(0, 124px) auto minmax(0, 1fr) 24px;
    align-items: center;
    gap: var(--space-2);
}
.ta-scope-line + .ta-scope-line { margin-top: 6px; }
.ta-scope-line > .ta-pill {
    display: inline-block;
    justify-self: start;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ta-scope-line__stage {
    font-size: 12px;
    font-weight: 600;
    /* Stated, like the figures: a table cell's own colour is dimmer than the soft colour in dark, which
       made a launched trade read quieter than one not launched. */
    color: var(--triarch-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ta-scope-line__stage.is-none {
    font-weight: 400;
    color: var(--triarch-text-soft);
}
@media (max-width: 1799.98px) {
    th.ta-col-trades { width: 272px; }
    .ta-list-table .ta-scope-line { grid-template-columns: minmax(0, 124px) minmax(0, 1fr) 24px; }
    .ta-list-table .ta-scope-line > .ta-stage-bar { display: none; }
}
.ta-scope-more {
    display: block;
    max-width: 100%;
    /* 2px + 4px of padding where 6px of margin was: the same position, and a 24px target. */
    margin-top: 2px;
    padding: 4px 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: 11px;
    font-weight: 600;
    color: var(--triarch-text-soft);
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
button.ta-scope-more {
    color: var(--triarch-link);
    cursor: pointer;
}
button.ta-scope-more:hover { text-decoration: underline; }
button.ta-scope-more:focus-visible {
    outline: 0;
    border-radius: var(--radius-sm);
    box-shadow: var(--focus-ring);
}
/* Soft text for a note where a value is missing ("No trades yet", "No quote yet"). Not Bootstrap's
   .text-muted, which falls under 4.5:1 on a striped row in light. */
.ta-soft { color: var(--triarch-text-soft); }
/* A person as initials, where a name would not fit: a circle is a person, a rounded square (--unit) is
   a department. The dashed form says there is no owner yet. */
.ta-initials {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--triarch-neutral-bg);
    color: var(--triarch-neutral-fg);
    font-size: 11px;
    font-weight: 700;
}
.ta-initials--unit {
    border-radius: var(--radius-sm);
    /* The fill is nearly the stripe colour of a list row; the hairline keeps the square a square. */
    box-shadow: inset 0 0 0 1px var(--triarch-border);
}
.ta-initials--none {
    box-shadow: none;
    background: transparent;
    border: 1.5px dashed var(--triarch-warning-fg);
    color: var(--triarch-warning-fg);
}

/* Row details: the arrow at the end of a row opens a band under it (a DataTables child row) with what
   would otherwise need the record opened. */
th.ta-col-toggle { width: 48px; }
.ta-list-table > thead > tr > th.ta-col-toggle,
.ta-list-table > tbody > tr > td.ta-col-toggle {
    padding-left: 4px !important;
    padding-right: 10px !important;
    text-align: right;
}
.ta-row-toggle > i { transition: transform 0.15s ease; }
.ta-row-toggle[aria-expanded="true"] > i { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
    .ta-row-toggle > i { transition: none; }
}
/* The band is one soft surface. LeptonX makes every table cell inherit its row's background, so the
   colour goes on the row as well as the cell. DataTables clears every row's background, and paints its
   stripe on odd rows as an inset shadow, from selectors this specific; these two match that specificity
   so the band keeps its colour and loses the stripe when it lands on an odd row. */
table.table.ta-list-table.dataTable > tbody > tr.ta-row-details-row { background: var(--triarch-surface-soft); }
table.table.ta-list-table.dataTable > tbody > tr.ta-row-details-row > td { box-shadow: none; }
.ta-list-table > tbody > tr > td.ta-row-details-cell {
    padding: 16px 16px 18px 50px;
    background: var(--triarch-surface-soft);
}
/* On the band itself, not its cell: LeptonX sets the colour of table cells and wins there. */
.ta-row-details { color: var(--triarch-text); }
.ta-row-details__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--space-3) var(--space-6);
}
.ta-row-details__group {
    min-width: 0;
    font-size: 13px;
    overflow-wrap: anywhere;
}
.ta-row-details__group > .t-label { margin-bottom: var(--space-1); }
.ta-row-details__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-3);
}
/* Every trade of the project, one per line: trade, stage, estimator, margin, quote, and a link to open it.
   The tracks are fixed so the lines read as columns. */
.ta-row-details__trades {
    margin-bottom: var(--space-4);
    font-size: 13px;
}
.ta-row-details__trades > .t-label { margin-bottom: var(--space-1); }
.ta-scope-row {
    display: grid;
    grid-template-columns: 132px 210px minmax(0, 180px) 110px minmax(0, 210px) auto;
    justify-content: start;
    align-items: center;
    gap: var(--space-1) var(--space-4);
    padding: 6px 0;
}
.ta-scope-row + .ta-scope-row { border-top: 1px solid var(--triarch-border); }
.ta-scope-row > * {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ta-scope-row__stage {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}
.ta-scope-row > a {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    overflow: visible;
}
.ta-scope-row > a:focus-visible,
a.ta-project-card__title:focus-visible {
    outline: 0;
    border-radius: var(--radius-sm);
    box-shadow: var(--focus-ring);
}
@media (max-width: 991.98px) {
    .ta-scope-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

/* Projects as cards: the page of rows the list holds, one card each (index.js draws both from the same
   table). The list card gives up its own surface so the cards sit on the page, and keeps the pager
   under them. */
.ta-project-cards { display: none; }
.ta-list-card.is-cards {
    border-color: transparent;
    background: transparent;
    box-shadow: none;
}
.ta-list-card.is-cards table.ta-list-table { display: none; }
.ta-list-card.is-cards .ta-project-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr));
    gap: var(--space-4);
    margin-bottom: var(--space-3);
}
.ta-project-card { margin: 0; }
.ta-project-card > .card-body {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: 14px 16px;
}
.ta-project-card__top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
}
.ta-project-card__top .ta-due { text-align: right; }
.ta-project-card__title {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.3;
    /* 2px above and below: a one-line title is a 24px target. The meta line gives the space back. */
    padding: 2px 0 3px;
    color: var(--triarch-text);
    text-decoration: none;
}
a.ta-project-card__title:hover,
a.ta-project-card__title:focus-visible { color: var(--triarch-link); }
.ta-project-card__meta {
    margin-top: 0;
    font-size: 12px;
    color: var(--triarch-text-soft);
}
.ta-project-card__foot {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-3);
    margin-top: auto;
    padding-top: 10px;
    border-top: 1px solid var(--triarch-border);
}
/* The card of a project just created or edited is pointed out as its row would be. */
.ta-project-card--flash { animation: ta-list-row-flash 2.5s ease-out 0s 1; }
/* A card is narrower than the list's column: the pill takes what is left and the bar is shorter. */
.ta-project-card .ta-scope-line { grid-template-columns: minmax(0, 1fr) auto auto 24px; }
.ta-project-card .ta-stage-bar__seg { width: 10px; }

/* A checkbox column with no row menu beside it (Contacts): DataTables writes the column's 0.5rem on
   its <col>, and a fixed layout would honour it. */
.ta-list-table--fixed > thead > tr > th.select-checkbox:first-child { width: 44px; }
.ta-list-table--fixed:has(> thead > tr > th.select-checkbox:first-child) > colgroup > col:first-child {
    width: 44px !important;
}

/* Stacked title + subtitle cell (project name, etc.) */
.t-cell-stack {
    line-height: 1.25;
}
.t-cell-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--triarch-text);
}
.t-cell-sub {
    font-size: 11px;
    color: var(--triarch-text-soft);
    margin-top: 2px;
}

/* Outcome (icon + label) inline cell */
.ta-cell-outcome {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--triarch-text);
}
.ta-cell-outcome > i {
    color: var(--triarch-text-soft);
    font-size: 12px;
}

/* Stacked outcome bar — Import History list (Updated / Added / Skipped / Conflict / Error) */
.ta-outcome-bar {
    display: flex;
    height: 6px;
    border-radius: 3px;
    overflow: hidden;
    background: var(--triarch-surface-dim);
    margin-bottom: 6px;
    min-width: 7.5rem;
}
.ta-outcome-bar__seg {
    display: block;
    height: 100%;
    min-width: 2px;
}
/* Updated/Added = green; Skipped = silver; Conflict = amber; Error = red only */
.ta-outcome-bar__seg--updated  { background: var(--status-approved); }
.ta-outcome-bar__seg--added    { background: var(--status-approved); }
.ta-outcome-bar__seg--skipped  { background: #94a3b8; }
.ta-outcome-bar__seg--conflict { background: var(--status-in-review); }
.ta-outcome-bar__seg--error    { background: var(--status-rejected); }
.ta-outcome-bar__meta {
    font-size: 12px;
    line-height: 1.35;
    color: var(--triarch-text-soft);
}
.ta-outcome-bar__tally--updated,
.ta-outcome-bar__tally--added    { color: var(--status-approved); font-weight: 600; }
.ta-outcome-bar__tally--skipped  { color: #94a3b8; }
.ta-outcome-bar__tally--conflict { color: var(--status-in-review); font-weight: 600; }
.ta-outcome-bar__tally--error    { color: var(--status-rejected); font-weight: 600; }

/* ── SLA cell (service request expiry / status indicator) ───────────── */
.ta-sla {
    font-size: 11.5px;
    font-weight: 600;
    white-space: nowrap;
}
.ta-sla--ok      { color: var(--triarch-text-soft); }
.ta-sla--urgent  { color: var(--status-action-required); }
.ta-sla--overdue { color: var(--status-rejected); font-weight: 700; }
.ta-sla--ready   { color: var(--status-approved); }
.ta-sla--fee     { color: var(--status-action-required); }
.ta-sla--awaiting { color: var(--triarch-text-soft); font-style: italic; }
.ta-sla--paused  { color: var(--triarch-text-soft); }
.ta-sla--closed  { color: var(--triarch-text-soft); }

/* ──────────────────────────────────────────────────────────────────────
   Right-side panel column — reusable hide-on-small utility
   --------------------------------------------------------------------
   Apply .ta-side-panel-col to any column that should render only at
   ≥xl (≥1200px). Below that breakpoint the column is hidden and the
   main content reflows to full width.

   Usage:
       <div class="row g-3">
           <div class="col-12 col-xl-9"> ...main content... </div>
           <div class="col-12 col-xl-3 ta-side-panel-col"> ...panel... </div>
       </div>
   ────────────────────────────────────────────────────────────────────── */
@media (max-width: 1199.98px) {
    .ta-side-panel-col {
        display: none !important;
    }
}

/* On xl+ the rail pins to the top of the viewport so it stays in view
   while the long form scrolls. Opt-in by adding .ta-side-panel-col--sticky
       alongside .ta-side-panel-col. The pin clears the LeptonX top bar
       (--triarch-sticky-top). */
@media (min-width: 1200px) {
    .ta-side-panel-col.ta-side-panel-col--sticky > * {
        position: sticky;
        top: var(--triarch-sticky-top, 5rem);
        max-height: calc(100vh - var(--triarch-sticky-top, 5rem) - var(--triarch-sticky-gap, 1rem));
        overflow-y: auto;
    }
}

/* ── State machine side panel (vertical workflow filter) ────────────── */
.ta-state-machine__head {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding-bottom: 12px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--triarch-surface-dim);
}
.ta-state-machine__icon {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    background: var(--status-in-review-bg);
    color: var(--triarch-text-issued, var(--triarch-accent));
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
}
.ta-state-machine__title {
    font-size: 14px;
    font-weight: 600;
    line-height: 1.2;
}
.ta-state-machine__hint {
    font-size: 11.5px;
    color: var(--triarch-text-soft);
    line-height: 1.3;
}
.ta-state-machine__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.ta-state-machine__item {
    display: grid;
    grid-template-columns: auto auto 1fr auto;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: 8px;
    cursor: pointer;
    user-select: none;
    transition: background-color .12s ease, border-color .12s ease;
    border: 1px solid transparent;
}
.ta-state-machine__item:hover {
    background: var(--triarch-surface-soft);
}
.ta-state-machine__item.is-active {
    background: var(--status-in-review-bg);
    border-color: var(--triarch-surface-dim);
}
.ta-state-machine__item:focus-visible {
    outline: 2px solid var(--triarch-accent);
    outline-offset: 1px;
}
.ta-state-machine__num {
    font-family: var(--triarch-font-mono, ui-monospace, monospace);
    font-size: 11px;
    font-weight: 600;
    color: var(--triarch-text-soft);
    letter-spacing: .03em;
}
.ta-state-machine__item.is-active .ta-state-machine__num {
    color: inherit;
    font-weight: 700;
}
.ta-state-machine__radio {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 1.5px solid var(--triarch-surface-dim);
    background: var(--triarch-surface);
    box-sizing: border-box;
    position: relative;
}
.ta-state-machine__item.is-active .ta-state-machine__radio {
    border-color: var(--triarch-accent);
}
.ta-state-machine__item.is-active .ta-state-machine__radio::after {
    content: "";
    position: absolute;
    inset: 2px;
    border-radius: 50%;
    background: var(--triarch-accent);
}
.ta-state-machine__label {
    font-size: 13px;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ta-state-machine__count {
    min-width: 28px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    text-align: center;
    background: var(--triarch-surface-soft);
    color: var(--triarch-text-soft);
    line-height: 1.4;
}
.ta-state-machine__count:empty::before {
    content: "—";
    opacity: .5;
}

/* Horizontal stepper variant — used on entity detail pages where the state
   machine is informational only (no click-to-filter). Items render in a row
   with dot-over-label and a connector line drawn between adjacent dots. */
.ta-state-machine--horizontal {
    background: color-mix(in srgb, var(--triarch-cta-tint) 35%, var(--triarch-surface));
    border-color: var(--triarch-cta-outline);
}
.ta-state-machine--horizontal .ta-state-machine__head {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 0;
}
.ta-state-machine--horizontal .ta-state-machine__head > div {
    flex: 1 1 auto;
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
}
.ta-state-machine--horizontal .ta-state-machine__title {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 11px;
    font-weight: 700;
    color: var(--triarch-text-soft);
}
.ta-state-machine--horizontal .ta-state-machine__subtitle {
    font-size: 13px;
    color: var(--triarch-text-soft);
}
.ta-state-machine--horizontal .ta-state-machine__subtitle strong {
    color: var(--triarch-text);
    font-weight: 600;
}
.ta-state-machine--horizontal .ta-state-machine__action {
    margin-left: auto;
    font-size: 12px;
    text-decoration: none;
}

/* State machine merged into the detail header card — kept as a tinted footer band (same
   peach as the old standalone card), but full-bleed inside the one card: negative margins
   cancel the card-body padding so the tint reaches the card edges, and the header card's
   overflow:hidden clips it to the rounded corners. Tightened vertical rhythm reclaims the
   space the old card's padding + inter-card gap used to eat. */
.ta-detail-statemachine {
    margin: 14px calc(var(--bs-card-spacer-x, 1rem) * -1) calc(var(--bs-card-spacer-y, 1rem) * -1);
    padding: 12px var(--bs-card-spacer-x, 1rem);
    border-top: 1px solid var(--triarch-border);
    /* Neutral, not tinted — the milestone dots/line carry the colour. Keeps the page calm and
       reserves the warm tint for the one thing that wants attention (the Next Action card). */
    background: var(--triarch-surface);
}
.ta-detail-statemachine .ta-phase-track { margin-top: 6px; }
.ta-detail-statemachine .ta-phase-notes { margin-top: 8px; padding-top: 8px; }

/* Dark theme: drop the peach tint so the band sits flat on the header-card surface (keeps the
   page to two background colours); the milestone dots/line still carry the colour. */
.lpx-theme-dark .ta-detail-statemachine {
    background: transparent;
    border-top-color: var(--triarch-border);
}

/* ── Phase spine ─────────────────────────────────────────────────────
   Replaces the old linear per-status stepper on entity detail pages. Four
   macro-phases (Intake · Review · Decision · Issuance); phase completion is
   driven by the entity's real status history, so a green check means the
   phase was genuinely reached — not merely "earlier in the enum". Loops and
   pauses render as annotation chips below the spine, never as forward steps.
   Markup: <ol class="ta-phase-track"> of <li class="ta-phase">. */
.ta-phase-track {
    list-style: none;
    display: flex;
    align-items: flex-start;
    gap: 0;
    margin: 14px 2px 2px;
    padding: 0;
}
.ta-phase {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 7px;
    padding: 0 4px;
    position: relative;
}
/* Connector to the next phase, anchored on the dot's vertical centre. */
.ta-phase::after {
    content: "";
    position: absolute;
    top: 11px; /* dot-height 24px / 2 − border */
    left: 50%;
    width: 100%;
    height: 2px;
    background: var(--triarch-surface-dim);
    z-index: 0;
}
.ta-phase:last-child::after { display: none; }
.ta-phase__dot {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 2px solid var(--triarch-surface-dim);
    background: var(--triarch-surface);
    color: var(--triarch-text-soft);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 700;
    position: relative;
    z-index: 1;
    flex-shrink: 0;
}
.ta-phase__name {
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.2;
    color: var(--triarch-text-soft);
}
.ta-phase__meta {
    font-size: 10px;
    font-family: var(--triarch-font-mono, ui-monospace, monospace);
    color: var(--triarch-text-soft);
    opacity: 0.85;
}
/* Active-milestone caption — short "time in current status", amber to tie it to
   the current node. The precise status name is in the card subtitle + chips. */
.ta-phase__now {
    font-size: 10px;
    font-weight: 700;
    color: var(--status-in-review);
    background: var(--status-in-review-bg);
    border-radius: 5px;
    padding: 1px 6px;
    white-space: nowrap;
}
/* Completed — and the green connector that follows it (next phase was reached). */
.ta-phase.is-completed::after { background: var(--triarch-success); }
.ta-phase.is-completed .ta-phase__dot {
    border-color: var(--triarch-success);
    background: var(--triarch-success);
    color: #fff;
}
.ta-phase.is-completed .ta-phase__name { color: var(--triarch-text); }
/* Current — amber (matches the in-review status colour). Deliberately NOT the
   danger red the old stepper used, which collided with the rejected colour. */
.ta-phase.is-current .ta-phase__dot {
    border-color: var(--status-in-review);
    background: var(--status-in-review);
    color: #fff;
    box-shadow: 0 0 0 4px var(--status-in-review-bg);
}
.ta-phase.is-current .ta-phase__name {
    color: var(--triarch-text);
    font-weight: 700;
}
/* Positive terminal — approved / closed. */
.ta-phase.is-positive .ta-phase__dot {
    border-color: var(--triarch-success);
    background: var(--triarch-success);
    color: #fff;
    box-shadow: 0 0 0 4px var(--triarch-success-bg);
}
.ta-phase.is-positive .ta-phase__name {
    color: var(--status-approved);
    font-weight: 700;
}
/* Negative terminal — rejected / withdrawn / cancelled / expired. The connector
   after this node stays neutral: the next phase was never reached. */
.ta-phase.is-negative .ta-phase__dot {
    border-color: var(--triarch-danger);
    background: var(--triarch-danger);
    color: var(--triarch-on-danger, #ffffff);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--triarch-danger) 16%, transparent);
}
.ta-phase.is-negative .ta-phase__name {
    color: var(--status-rejected);
    font-weight: 700;
}

/* Annotation row — loop / pause facts and the latest transition summary. */
.ta-phase-notes {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px dashed var(--triarch-cta-outline);
}
.ta-phase-note {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 11.5px;
    font-weight: 600;
    padding: 3px 10px;
    border-radius: 999px;
    border: 1px solid transparent;
}
.ta-phase-note--paused {
    background: rgba(91, 118, 147, 0.14);
    color: var(--status-submitted);
    border-color: rgba(91, 118, 147, 0.3);
}
.ta-phase-note--loop {
    background: var(--triarch-cta-tint);
    color: var(--status-action-required);
    border-color: var(--triarch-cta-outline);
}
.ta-phase-note--info {
    background: var(--status-in-review-bg);
    color: var(--status-in-review);
    border-color: color-mix(in srgb, var(--status-in-review) 30%, transparent);
}
.ta-phase-note--overdue {
    background: color-mix(in srgb, var(--triarch-danger) 12%, var(--triarch-surface));
    color: var(--triarch-danger);
    border-color: color-mix(in srgb, var(--triarch-danger) 32%, transparent);
}
/* Plain-language "what this means / what's next" hint — sits between the chips
   and the timestamp. Deliberately words, not a branch. */
.ta-phase-hint {
    font-size: 12px;
    color: var(--triarch-text-soft);
}
.ta-phase-last {
    margin-left: auto;
    font-size: 11.5px;
    color: var(--triarch-text-soft);
    white-space: nowrap;
}
.ta-phase-last b { color: var(--triarch-text); font-weight: 600; }

/* ── Status-history journey timeline (Alt 2 — inside the "View status history"
   offcanvas). Vertical, newest-first; loops show as repeated rows so there's
   nothing to decode. */
.ta-journey { margin: 0; }
.ta-journey__now {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    border: 1px solid var(--status-in-review);
    background: var(--status-in-review-bg);
    border-radius: 9px;
    margin-bottom: 6px;
}
.ta-journey__now-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--status-in-review);
    flex-shrink: 0;
}
.ta-journey__now-label { font-size: 13px; font-weight: 700; color: var(--triarch-text); }
.ta-journey__now-since { font-size: 11px; color: var(--triarch-text-soft); margin-left: auto; }
.ta-journey__list {
    list-style: none;
    margin: 6px 0 0;
    padding: 0 0 0 6px;
}
.ta-journey__item {
    position: relative;
    padding: 0 0 14px 22px;
}
.ta-journey__item::before {
    content: "";
    position: absolute;
    left: 4px;
    top: 4px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--triarch-surface-dim);
    z-index: 1;
}
.ta-journey__item::after {
    content: "";
    position: absolute;
    left: 8px;
    top: 14px;
    bottom: 0;
    width: 2px;
    background: var(--triarch-border);
}
.ta-journey__item:last-child::after { display: none; }
.ta-journey__item--current::before {
    background: var(--status-in-review);
    box-shadow: 0 0 0 3px var(--status-in-review-bg);
}
.ta-journey__item--good::before { background: var(--triarch-success); }
.ta-journey__item--bad::before { background: var(--triarch-danger); }
.ta-journey__item--loop::before { background: var(--status-action-required); }
.ta-journey__status { font-size: 12.5px; font-weight: 600; color: var(--triarch-text); }
.ta-journey__round {
    font-size: 9.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--status-action-required);
    background: var(--triarch-cta-tint);
    border-radius: 4px;
    padding: 0 5px;
    margin-left: 6px;
}
.ta-journey__meta { font-size: 11px; color: var(--triarch-text-soft); margin-top: 1px; }
.ta-journey__next {
    margin-top: 8px;
    padding-top: 9px;
    border-top: 1px dashed var(--triarch-border);
    font-size: 11.5px;
    color: var(--triarch-text-soft);
}
.ta-journey__next b { color: var(--triarch-text); }

/* ════════════════════════════════════════════════════════════════════
   ControlRoom — Service Request detail page
   Page-specific layout for Pages/ControlRoom/ServiceRequests/Detail/Index.
   Colour tokens come from the variables above so dark mode stays consistent.
   ════════════════════════════════════════════════════════════════════ */

/* Header strip */
.ta-detail-header .ta-detail-id {
    font-family: var(--triarch-font-mono, ui-monospace, "JetBrains Mono", "Cascadia Code", monospace);
    font-size: 1.15rem;
    font-weight: 600;
    letter-spacing: 0.01em;
}
/* Hero subtitle — the service name (the tracking number is now the H1). */
.ta-detail-header .ta-detail-name {
    font-family: var(--triarch-font-display);
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--triarch-text);
    letter-spacing: -0.01em;
    line-height: 1.2;
}
/* Muted empty-field placeholder — replaces bare "—" dashes. */
.ta-empty {
    color: var(--triarch-text-soft, #6b7280);
    font-style: italic;
}
.ta-detail-header .ta-detail-sub {
    font-size: 0.85rem;
    line-height: 1.5;
}
/* Hero header — content-driven flex row: the title/reviewers block grows to fill, the
   metric strip hugs the right and only drops to its own line when the two genuinely can't
   share the row (no fixed column split that wastes the empty left space). */
.ta-detail-header__row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 0.75rem 2rem;
}
.ta-detail-header__main {
    flex: 1 1 260px;
    min-width: 0;
}

/* Content-sized flex cluster (not a shrink-to-fit grid) so cells never collapse below
   their text and overlap — they stay compact, hug the right, and wrap as a unit when
   the container gets narrow. As a row item it keeps its natural width (no shrink) and is
   pushed right by the auto margin; it wraps to its own line only when the row is full. */
.ta-detail-metrics {
    flex: 0 0 auto;
    margin-left: auto;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: flex-start;
    gap: 0.6rem 0;
    text-align: right;
}
.ta-detail-metrics__cell { min-width: 0; }
/* Subtle column separators give the metric strip an engineered rhythm. */
.ta-detail-metrics__cell:not(:first-child) {
    border-left: 1px solid var(--triarch-border);
    padding-left: 1rem;
    margin-left: 1rem;
}
.ta-detail-metrics__label {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bs-secondary-color, #6b7280);
    margin-bottom: 0.15rem;
}
.ta-detail-metrics__value {
    font-size: 1.1rem;
    font-weight: 600;
    line-height: 1.2;
}
.ta-detail-metrics__value--alert  { color: var(--triarch-danger, #b42318); }
.ta-detail-metrics__value--danger { color: var(--triarch-danger, #b42318); }
.ta-detail-metrics__value--warn   { color: var(--status-in-review, #b88400); }
.ta-detail-metrics__value--muted  { color: var(--triarch-text-soft, #6b7280); font-weight: 600; }
/* Free text (e-mail, names) rather than a figure — one step down so long values fit the cell. */
.ta-detail-metrics__value--text   { font-size: 0.95rem; }
/* Compact, colour-coded activity counts (zeros hidden). Wraps within its own cell if
   space is tight rather than overflowing into the neighbouring metric. */
.ta-metric-counts { }
.ta-metric-counts__sep { color: var(--triarch-text-muted, #9aa5b1); margin: 0 3px; }
.ta-count { font-weight: 600; }
.ta-count--active  { color: var(--status-in-review, #b88400); }
.ta-count--pending { color: var(--triarch-text-soft, #6b7280); }
.ta-count--done    { color: var(--status-approved, #1D9E75); }
.ta-detail-metrics__sub {
    font-size: 0.75rem;
    line-height: 1.3;
    margin-top: 0.1rem;
}
@media (max-width: 768px) {
    /* Mobile: left-aligned two-up, full width, no dividers (they read poorly on wrapped rows). */
    .ta-detail-metrics {
        flex-basis: 100%;
        margin-left: 0;
        justify-content: flex-start;
        text-align: left;
        gap: 0.75rem 1.25rem;
    }
    .ta-detail-metrics__cell { flex: 0 0 40%; }
    .ta-detail-metrics__cell:not(:first-child) { border-left: none; padding-left: 0; margin-left: 0; }
}
/* Multi-line read-only field (e.g. Request Scope) — form-control sets a
   single-row fixed height; this override lets the text wrap naturally while
   keeping the surface and border consistent with the form. */
.ta-form-section__readonly-block {
    min-height: 3.5em;
    height: auto;
    white-space: pre-wrap;
    line-height: 1.4;
}
/* Next Action card — right-rail hint pointing the user at the single most-
   important action right now. Background tint matches the SR's "action needed"
   status so it reads as an actionable surface, not chrome. */
.ta-next-action {
    background: color-mix(in srgb, var(--triarch-cta-tint) 50%, var(--triarch-surface));
    border-color: var(--triarch-cta-outline);
}
.ta-next-action__head { margin-bottom: 0; }
.ta-next-action__eyebrow {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 10px;
    font-weight: 700;
    color: var(--triarch-text-soft);
    margin-bottom: 4px;
}
.ta-next-action__title {
    font-size: 14px;
    font-weight: 700;
    color: var(--triarch-text);
    line-height: 1.3;
}
.ta-next-action__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-items: center;
}

/* Per-state tone — lets a coordinator triage the single Next Action card at a glance
   (action = brand, info = in-review blue, muted = passive wait, positive = done/clear,
   danger = blocked or SLA-breached). Modifiers come after the base so they win. */
.ta-next-action--action   { background: color-mix(in srgb, var(--triarch-cta-tint) 50%, var(--triarch-surface)); border-color: var(--triarch-cta-outline); }
.ta-next-action--info     { background: color-mix(in srgb, var(--status-in-review-bg) 60%, var(--triarch-surface)); border-color: color-mix(in srgb, var(--status-in-review) 28%, transparent); }
.ta-next-action--muted    { background: var(--triarch-surface-soft); border-color: var(--triarch-border); }
.ta-next-action--positive { background: color-mix(in srgb, var(--triarch-success-bg) 60%, var(--triarch-surface)); border-color: color-mix(in srgb, var(--triarch-success) 28%, transparent); }
.ta-next-action--danger   { background: color-mix(in srgb, var(--triarch-danger) 10%, var(--triarch-surface)); border-color: color-mix(in srgb, var(--triarch-danger) 32%, transparent); }

/* State icon badge sitting left of the eyebrow/title (reuses the form-section head flex). */
.ta-next-action__icon {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 9px;
    display: grid;
    place-items: center;
    font-size: 14px;
    background: var(--triarch-surface);
    color: var(--triarch-text-soft);
    border: 1px solid var(--triarch-border);
}
.ta-next-action--action .ta-next-action__icon   { color: var(--status-action-required); border-color: var(--triarch-cta-outline); }
.ta-next-action--info .ta-next-action__icon      { color: var(--status-in-review); }
.ta-next-action--positive .ta-next-action__icon  { color: var(--status-approved); }
.ta-next-action--danger .ta-next-action__icon    { color: var(--triarch-danger); border-color: color-mix(in srgb, var(--triarch-danger) 32%, transparent); }

/* SLA-breach note under the chips. */
.ta-next-action__overdue {
    font-size: 12px;
    font-weight: 600;
    color: var(--triarch-danger);
}

/* Dark theme: the per-state background tints fragment the page into many shades. Flatten the
   card to the standard surface and carry state on a left rail + the (already coloured) icon —
   the same pattern the activity cards use — so dark mode stays at two background colours. */
.lpx-theme-dark .ta-next-action {
    background: var(--triarch-surface);
    border-color: var(--triarch-border);
    border-left-width: 3px;
}
.lpx-theme-dark .ta-next-action--action   { border-left-color: var(--status-action-required); }
.lpx-theme-dark .ta-next-action--info     { border-left-color: var(--status-in-review); }
.lpx-theme-dark .ta-next-action--muted    { border-left-color: var(--triarch-outline); }
.lpx-theme-dark .ta-next-action--positive { border-left-color: var(--status-approved); }
.lpx-theme-dark .ta-next-action--danger   { border-left-color: var(--triarch-danger); }
.ta-side-panel-col > .card { box-shadow: none; }
/* BuildRoom-project field card — file-icon + project label rendered as a tile so
   the cross-system link reads as a tangible artifact, not just an inline pill. */
.ta-buildroom-card {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    border: 1px solid var(--triarch-border, #eaeef2);
    border-radius: var(--radius-sm, 6px);
    background: var(--triarch-surface, #fff);
    min-width: 0;
    max-width: 100%;
}
.lpx-theme-dark .ta-buildroom-card,
[data-bs-theme="dark"] .ta-buildroom-card {
    /* Same as .ta-contact: flatten the blue slate #1e2530 onto the neutral card
       surface and drop the border so the tile blends into the card. */
    background: var(--lpx-card-bg, #1b1b1b);
    border-color: transparent;
}
.ta-buildroom-card__icon {
    width: 28px;
    height: 28px;
    border-radius: 6px;
    background: color-mix(in srgb, var(--triarch-cta-tint, #fff3c4) 60%, var(--triarch-surface));
    color: var(--triarch-cta-hover, #a06900);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 13px;
}
.ta-buildroom-card__label {
    font-weight: 600;
    color: var(--triarch-text, inherit);
    font-family: var(--triarch-font-mono, ui-monospace, monospace);
    font-size: 12px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* B4 — header status accent bar. Thin colour strip toned to the state machine's
   outcome; the textual status now lives only in the track. */
.ta-detail-header {
    position: relative;
    overflow: hidden;
}
.ta-detail-header::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: var(--status-in-review, #8a5a00);
}
.ta-detail-header--positive::before { background: var(--triarch-success, #238b45); }
.ta-detail-header--negative::before { background: var(--triarch-danger, #ba1a1a); }
/* B5 — reviewer roster chips in the header */
.ta-reviewer-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 10px;
}
.ta-reviewer-row__label {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bs-secondary-color, #6b7280);
}
.ta-reviewer-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 10px 2px 2px;
    border: 1px solid var(--triarch-border, #eaeef2);
    border-radius: 999px;
    background: var(--triarch-surface, #fff);
    font-size: 12px;
    max-width: 100%;
}
.ta-reviewer-chip__avatar {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--status-in-review-bg, #fff1d6);
    color: var(--status-in-review, #8a5a00);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    font-weight: 700;
    flex-shrink: 0;
}
.ta-reviewer-chip__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--triarch-text, inherit);
}
/* B2 — client contact block in the Applicant & Property card */
.ta-contact-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 10px;
    margin-bottom: 14px;
}
.ta-contact {
    border: 1px solid var(--triarch-border, #eaeef2);
    border-radius: var(--radius-sm, 8px);
    background: var(--triarch-surface, #fff);
    padding: 10px 12px;
    min-width: 0;
}
.lpx-theme-dark .ta-contact,
[data-bs-theme="dark"] .ta-contact {
    /* In dark, --triarch-surface is the blue slate #1e2530 — a bluish box inside the
       neutral #1b1b1b card. Flatten it onto the card surface and drop the border so it
       reads as plain content rather than a panel. */
    background: var(--lpx-card-bg, #1b1b1b);
    border-color: transparent;
}
.ta-contact__role {
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bs-secondary-color, #6b7280);
    margin-bottom: 2px;
}
.ta-contact__primary {
    color: var(--triarch-warning, #f7be1d);
    font-size: 0.7rem;
    margin-left: 3px;
}
.ta-contact__name {
    font-weight: 600;
    font-size: 0.9rem;
    line-height: 1.25;
}
.ta-contact__company {
    font-weight: 400;
    color: var(--triarch-text-soft, #6b7280);
}
.ta-contact__links {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 14px;
    margin-top: 4px;
    font-size: 0.8rem;
}
.ta-contact__links a {
    color: var(--triarch-text-soft, #57657a);
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}
.ta-contact__links a:hover {
    color: var(--triarch-primary, #9d4300);
    text-decoration: underline;
}

/* ── Read-only fact grid (Applicant + property card and friends) ─────────
   Compact two-column key/value display for captured-at-submit data. Keys
   echo .ta-contact__role's uppercase label treatment so the card reads as
   one system; values are plain text — no ghost form-control boxes. */
.ta-fact-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px 16px;
}
.ta-fact--wide {
    grid-column: 1 / -1;
}
.ta-fact__key {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bs-secondary-color, #6b7280);
    margin-bottom: 3px;
}
/* Inline action beside a key (e.g. "open in BuildRoom →") — reads as a
   link, not as part of the uppercase label. */
.ta-fact__key .ta-fact__action {
    font-weight: 500;
    text-transform: none;
    letter-spacing: normal;
    font-size: 0.75rem;
    text-decoration: none;
}
.ta-fact__val {
    font-size: 0.9rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--triarch-text);
    overflow-wrap: anywhere;
}
.ta-fact__val .ta-empty {
    font-weight: 400;
}

/* Mono utility — code-like values (jurisdiction codes, tracking numbers).
   Referenced by detail pages; previously undefined. */
.ta-mono {
    font-family: var(--triarch-font-mono);
    font-size: 0.85em;
    letter-spacing: 0.02em;
}

/* Terminal card tone — a subtle border shift so the whole card reads the outcome. */
.ta-state-machine--positive { border-color: var(--triarch-success); }
.ta-state-machine--negative { border-color: var(--triarch-danger); }

/* Narrow screens — let phase names wrap and drop the transition line below. */
@media (max-width: 575.98px) {
    .ta-phase__name { font-size: 11.5px; }
    .ta-phase-last { margin-left: 0; flex-basis: 100%; }
}

/* ── List card ───────────────────────────────────────────────────────────
   The card that wraps a DataTables list on ~25 pages across Catalog,
   BuildRoom, ControlRoom, Notification and the public site.

   overflow-x on the body lets a table wider than the card scroll sideways
   inside it rather than being cut off — this replaces the DataTables
   Responsive extension, which hid columns behind a +/- expander and at 100%
   zoom swallowed columns users needed.

   Consequence to know about: CSS cannot keep one axis visible while the other
   scrolls, so the body is a clipping container on BOTH axes. Row-action
   dropdown menus are positioned by Popper with `boundary: clippingParents`,
   which treats this body as the boundary and flips a menu upward rather than
   letting it overflow — so menus on the last row open up, not off the card.
   Anything absolutely positioned inside the body that is NOT Popper-managed
   would be clipped; give it a fixed strategy or render it outside the card. */
.ta-list-card {
    min-width: 0;
    max-width: 100%;
}
.ta-list-card > .card-body {
    min-width: 0;
    overflow-x: auto;
}

@media (max-width: 1199.98px) {
    .ta-list-card > .card-body {
        -webkit-overflow-scrolling: touch;
    }
    .ta-list-table {
        border-collapse: separate;
        border-spacing: 0;
    }
    /* Keep header row in normal table flow (no sticky th). Sticky + horizontal
       scroll on .card-body misaligns thead and tbody on phone/tablet; columns stay
       visible via max-content width + overflow-x on the card body. */
    .ta-list-card .ta-list-table {
        width: max-content !important;
        min-width: 100%;
    }
    /* Icon + title stay top-aligned when sibling columns (e.g. Due) stack two lines. */
    .ta-list-table > tbody > tr > td:has(.ta-name-cell) {
        vertical-align: top;
    }
    .ta-list-table .ta-name-cell {
        align-items: flex-start;
    }
    .ta-list-table .ta-name-cell__title {
        display: inline-block;
        max-width: 220px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        vertical-align: top;
    }

    /* List-page KPI stat rows (opt-in via .ta-list-kpi-row on the row wrapper).
       Phone + tablet: one horizontal row with sideways scroll — not a 2×2 column grid
       from row-cols-md-*. Desktop (≥1200px) keeps Bootstrap row-cols-* grid. */
    .ta-list-kpi-row {
        display: flex;
        flex-direction: row !important;
        flex-wrap: nowrap !important;
        gap: 0.5rem;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        margin-inline: 0;
        margin-bottom: 0 !important;
    }
    .ta-list-kpi-row > .col,
    .ta-list-kpi-row > [class*="col-"],
    .ta-list-kpi-row[class*="row-cols-"] > * {
        flex: 0 0 78vw !important;
        width: 78vw !important;
        max-width: 268px !important;
        min-width: 0;
        padding-inline: 0;
    }

    /* Import History: same horizontal KPI strip as Projects (no tablet 2×2 — it crushed labels). */
    #ImportHistorySummary .ta-stat-card--compact .ta-stat__label,
    #ImportHistorySummary .ta-stat-card--compact .ta-stat__sub {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Phone + tablet (< xl): compact list toolbar and Projects table columns.
       iPad Pro class widths (~1024px) sit above the old lg (992px) cut-off. */
    /* Build Room Projects: hide Actions column so the name column stays primary.
       View is the name link; Edit is on Detail. This grid has no bulk select or Delete. */
    #ProjectsTable th.select-checkbox,
    #ProjectsTable td.select-checkbox,
    #ProjectsTable td:has(.abp-action-button),
    #ProjectsTable thead th.select-checkbox + th,
    #ProjectsTable thead:not(:has(th.select-checkbox)) > tr > th:first-child {
        display: none !important;
    }

    /* Project name only (2nd column; 1st is hidden Actions). Avoid nth-child(3) — that is Client. */
    #ProjectsTable thead th:nth-child(2),
    #ProjectsTable tbody td:has(.ta-name-cell) {
        min-width: 12.5rem;
    }

    /* List-page filter card: search + filter icon on one row; chips live in the
       advanced-filter drawer (wired in controlroom-list-page.js). */
    .card .ta-toolbar:has(.ta-filters-btn) {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        column-gap: 0.5rem;
        row-gap: 0;
        align-items: center;
    }

    .card .ta-toolbar:has(.ta-filters-btn) .ta-toolbar__search {
        grid-column: 1;
        grid-row: 1;
        flex: none;
        width: 100%;
        min-width: 0;
        max-width: none;
    }

    .card .ta-toolbar:has(.ta-filters-btn) .ta-filters-btn {
        grid-column: 2;
        grid-row: 1;
        align-self: center;
        font-size: 0;
        gap: 0;
        min-width: 36px;
        padding-left: 10px;
        padding-right: 10px;
        justify-content: center;
    }

    /* The order menu and view switch (Projects) take a row of their own under the search, at their own
       width. Left to the grid they landed in the search column, stretched and touching the box above. */
    .card .ta-toolbar:has(.ta-filters-btn) > .ta-toolbar__views {
        grid-column: 1 / -1;
        grid-row: 2;
        justify-self: start;
        margin-top: var(--space-2);
    }

    .card .ta-toolbar:has(.ta-filters-btn) .ta-filters-btn .fa,
    .card .ta-toolbar:has(.ta-filters-btn) .ta-filters-btn .ta-filters-badge {
        font-size: 14px;
    }

    .card .ta-toolbar:has(.ta-filters-btn) .ta-filters-btn .fa-angle-down {
        display: none !important;
    }

    /* Keep "Filters" in the a11y tree — display:none would leave an unnamed button. */
    .card .ta-toolbar:has(.ta-filters-btn) .ta-filters-btn > span:not(.ta-filters-badge) {
        position: absolute !important;
        width: 1px !important;
        height: 1px !important;
        padding: 0 !important;
        margin: -1px !important;
        overflow: hidden !important;
        clip: rect(0, 0, 0, 0) !important;
        white-space: nowrap !important;
        border: 0 !important;
    }

    .card .ta-toolbar:has(.ta-filters-btn) .ta-toolbar__spacer,
    .card .ta-toolbar:has(.ta-filters-btn) .ta-toolbar__chips {
        display: none;
    }

    body.ta-controlroom-page .lpx-content > .ta-list-kpi-row + .card:has(.ta-toolbar .ta-filters-btn),
    body.ta-controlroom-page .lpx-content > .ta-list-kpi-row + .card.mb-3:has(.ta-toolbar .ta-filters-btn) {
        margin-top: 0 !important;
        margin-bottom: 0.5rem !important;
    }

    .card:has(.ta-toolbar .ta-filters-btn) > .card-body {
        padding-top: 0.5rem;
        padding-bottom: 0.5rem;
    }

    .ta-advanced-filters__chips-slot {
        margin-bottom: 0.75rem;
    }

    .ta-advanced-filters__chips-slot .ta-toolbar__chips {
        display: flex;
        flex-wrap: wrap;
        gap: var(--space-1);
    }

    .ta-advanced-filters .col-3 {
        flex: 0 0 50%;
        max-width: 50%;
    }
}

@media (max-width: 767.98px) {
    .ta-advanced-filters .col-3 {
        flex: 0 0 100%;
        max-width: 100%;
    }
}

/* DT1: .dataTables_wrapper > .row:last-child | DT2: .dt-container > .dataTable_footer */
/* List cards already opt in. Administration lists that are not inside a list card get
   .ta-admin-grid on the page content (see ta-datatables-length-flip.js). */
:is(.ta-list-card, .ta-admin-grid) .dataTables_wrapper > .row:last-child,
:is(.ta-list-card, .ta-admin-grid) .dt-container > .row.dataTable_footer,
:is(.ta-list-card, .ta-admin-grid) .dataTable_footer {
    margin: 0 !important;
    padding: 10px 14px;
    border-top: 1px solid var(--triarch-border);
    background: transparent;
    align-items: center;
}
:is(.ta-list-card, .ta-admin-grid) .dataTables_wrapper > .row:first-child {
    padding: 10px 14px 4px;
}
/* Keep controls snug under the table / scrollbar (DT2 scroll + footer gap). */
:is(.ta-list-card, .ta-admin-grid) .dt-container .dt-scroll {
    margin-bottom: 0 !important;
}
/* A table inside a card already has this inset removed. Administration tables are not
   in a card, so the library's 1.5rem pad was left under the footer. */
.ta-admin-grid .dt-container {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}
/* Audit logs wraps the table in .p-3; payment requests and the notification log use a card.
   That 24px sat under the footer. Users has none of it. */
.ta-admin-grid .card-body:has(.dt-container),
.ta-admin-grid .p-3:has(.dt-container) {
    padding-bottom: 0 !important;
}
:is(.ta-list-card, .ta-admin-grid) .dataTable_footer > [class*="col"],
:is(.ta-list-card, .ta-admin-grid) .dataTables_wrapper > .row:last-child > [class*="col"] {
    padding-left: 0;
    padding-right: 0;
    display: flex;
    align-items: center;
}
:is(.ta-list-card, .ta-admin-grid) .dataTable_footer > [class*="col"] + [class*="col"],
:is(.ta-list-card, .ta-admin-grid) .dataTables_wrapper > .row:last-child > [class*="col"] + [class*="col"] {
    padding-left: 12px;
}

/* Length / info / paging row — shared vertical rhythm */
:is(.ta-list-card, .ta-admin-grid) .dt-length,
:is(.ta-list-card, .ta-admin-grid) .dataTables_length,
:is(.ta-list-card, .ta-admin-grid) .dt-paging .pagination,
:is(.ta-list-card, .ta-admin-grid) .dataTables_paginate {
    display: flex !important;
    align-items: center;
    margin: 0 !important;
}
:is(.ta-list-card, .ta-admin-grid) .dt-length,
:is(.ta-list-card, .ta-admin-grid) .dataTables_length {
    gap: 0.35rem;
    font-size: 12px;
    line-height: 28px;
}
:is(.ta-list-card, .ta-admin-grid) .dt-length label,
:is(.ta-list-card, .ta-admin-grid) .dataTables_length label {
    font-size: inherit;
}
:is(.ta-list-card, .ta-admin-grid) .dt-info,
:is(.ta-list-card, .ta-admin-grid) .dataTables_info {
    font-size: 12px;
    line-height: 28px;
    padding: 0 !important;
    margin: 0 !important;
    color: var(--triarch-text-soft);
}

/* Pagination: plain text; solid CTA only on active page */
:is(.ta-list-card, .ta-admin-grid) .dt-paging .page-item .page-link,
:is(.ta-list-card, .ta-admin-grid) .dt-paging .paginate_button,
:is(.ta-list-card, .ta-admin-grid) .dataTables_paginate .paginate_button {
    min-width: auto;
    height: auto;
    padding: 2px 6px !important;
    margin: 0 2px !important;
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    border: none !important;
    border-radius: var(--radius-sm) !important;
    background: transparent !important;
    color: var(--triarch-text) !important;
    font-size: 12px;
    font-weight: 500;
    box-shadow: none !important;
}
:is(.ta-list-card, .ta-admin-grid) .dt-paging .page-item.active .page-link,
:is(.ta-list-card, .ta-admin-grid) .dt-paging .page-item.active .page-link:hover,
:is(.ta-list-card, .ta-admin-grid) .dt-paging .paginate_button.current,
:is(.ta-list-card, .ta-admin-grid) .dt-paging .paginate_button.current:hover,
:is(.ta-list-card, .ta-admin-grid) .dataTables_paginate .paginate_button.current,
:is(.ta-list-card, .ta-admin-grid) .dataTables_paginate .paginate_button.current:hover {
    background: var(--triarch-cta) !important;
    border: none !important;
    color: var(--triarch-on-action, #ffffff) !important;
    font-weight: 700;
    min-width: 28px;
    height: 28px;
    padding: 0 8px !important;
}
:is(.ta-list-card, .ta-admin-grid) .dt-paging .page-item:not(.active):not(.disabled) .page-link:hover,
:is(.ta-list-card, .ta-admin-grid) .dt-paging .paginate_button:hover,
:is(.ta-list-card, .ta-admin-grid) .dataTables_paginate .paginate_button:hover {
    background: transparent !important;
    color: var(--triarch-cta-hover) !important;
}
:is(.ta-list-card, .ta-admin-grid) .dt-paging .page-item.disabled .page-link,
:is(.ta-list-card, .ta-admin-grid) .dt-paging .page-item.disabled .page-link:hover,
:is(.ta-list-card, .ta-admin-grid) .dt-paging .paginate_button.disabled,
:is(.ta-list-card, .ta-admin-grid) .dataTables_paginate .paginate_button.disabled,
:is(.ta-list-card, .ta-admin-grid) .dataTables_paginate .paginate_button.disabled:hover {
    background: transparent !important;
    color: #c5ccd7 !important;
    cursor: not-allowed;
}

/* Custom length menu (JS: ta-datatables-length-flip.js) */
.ta-length-menu {
    position: relative;
    display: inline-block;
    vertical-align: middle;
}
.ta-length-menu__native {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    border: 0 !important;
}
/* LeptonX re-wraps the native select after our custom menu; hide its duplicate UI. */
.ta-length-menu .custom-select-wrapper {
    display: none !important;
}
.ta-length-menu__btn {
    min-width: 52px;
    height: 28px;
    padding: 0 28px 0 10px;
    border: none;
    border-radius: var(--radius-sm);
    background: var(--triarch-surface-soft)
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b7280' d='M3 4.5L6 7.5L9 4.5'/%3E%3C/svg%3E")
        no-repeat right 8px center;
    color: var(--triarch-text);
    font-size: 12px;
    font-weight: 500;
    line-height: 26px;
    cursor: pointer;
}
.ta-length-menu__list {
    display: none;
    position: absolute;
    left: 0;
    z-index: 1060;
    min-width: 100%;
    margin: 4px 0 0;
    padding: 4px 0;
    list-style: none;
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-sm);
    background: var(--triarch-surface);
    box-shadow: 0 8px 20px rgba(15, 23, 42, 0.12);
}
.ta-length-menu.is-open .ta-length-menu__list { display: block; }
.ta-length-menu--up .ta-length-menu__list {
    top: auto;
    bottom: 100%;
    margin: 0 0 4px;
}
.ta-length-menu__option {
    padding: 6px 12px;
    font-size: 12px;
    color: var(--triarch-text);
    cursor: pointer;
    white-space: nowrap;
}
.ta-length-menu__option:hover,
.ta-length-menu__option.is-selected {
    background: var(--triarch-surface-soft);
}
/* ── KPI / stat card interior (compose inside <abp-card><abp-card-body>) ── */

/* Apply .ta-stat-card to <abp-card> to enable the decorative bg icon */
.ta-stat-card .card-body {
    position: relative;
    overflow: hidden;
}

.ta-stat__bg-icon {
    position: absolute;
    right: -10px;
    bottom: -18px;
    font-size: 92px;
    color: var(--triarch-text-soft);
    opacity: 0.06;
    pointer-events: none;
    line-height: 1;
}

.ta-stat__head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
    position: relative;
}
.ta-stat__icon {
    width: 26px;
    height: 26px;
    border-radius: var(--radius-sm);
    background: var(--triarch-surface-soft);
    color: var(--triarch-focus);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 13px;
}
.ta-stat__label {
    font-size: 11px;
    font-weight: 600;
    color: var(--triarch-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    line-height: 1.2;
}
.ta-stat__value {
    font-family: var(--triarch-font-display);
    font-size: 24px;
    font-weight: 700;
    color: var(--triarch-text);
    letter-spacing: -0.02em;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}
.ta-stat__sub {
    font-size: 12px;
    color: var(--triarch-text-soft);
    margin-top: var(--space-2);
}

/* Compact horizontal variant — opt in by adding .ta-stat-card--compact alongside
   .ta-stat-card. Layout becomes [icon] [label + sub stacked]  [value right-aligned],
   roughly halving the tile height vs. the default stacked layout. Markup adds a
   .ta-stat__meta wrapper around label + sub; the .ta-stat__head is unused here. */
.ta-stat-card--compact {
    /* The tile's own width, not the window's, decides its layout (the stacked form below). A tile always
       sits in a grid column, so its width never depends on what is inside it. */
    container: ta-stat / inline-size;
}
.ta-stat-card--compact .card-body {
    padding: 0.625rem 0.9375rem;
    display: flex;
    /* Last resort: a figure too wide to sit beside the label's longest word drops under it. */
    flex-wrap: wrap;
    align-items: center;
    gap: 2px var(--space-3);
}
.ta-stat-card--compact .ta-stat__icon {
    width: 38px;
    height: 38px;
    font-size: 15px;
    flex-shrink: 0;
}
.ta-stat-card--compact .ta-stat__meta {
    display: flex;
    flex-direction: column;
    /* Never narrower than the label's longest word: the label wraps between words first. */
    min-width: min-content;
    flex: 1 1 0;
}
.ta-stat-card--compact .ta-stat__label {
    font-size: 11px;
    /* Bootstrap's .card lets a word break anywhere; squeezed beside a wide figure, "Total value" read
       "TO TAL VAL UE". A label breaks between words only. */
    overflow-wrap: normal;
    word-break: normal;
}
.ta-stat-card--compact .ta-stat__sub {
    margin-top: 2px;
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* As wide as the label makes the block, without widening it. */
    width: 0;
    min-width: 100%;
}
.ta-stat-card--compact .ta-stat__value {
    font-size: 24px;
    line-height: 1;
    margin-left: auto;
    flex-shrink: 0;
}
.ta-stat-card--compact .ta-stat__bg-icon {
    font-size: 64px;
    right: -8px;
    bottom: -10px;
}

/* Stacked form, for a tile narrower than about 250px (five across on a laptop, six on Tenant setup): the
   figure goes under the label instead of squeezing it. It follows the tile's own width, so every tile
   in a row changes together. */
@container ta-stat (max-width: 15.5rem) {
    .ta-stat-card--compact .card-body {
        display: grid;
        grid-template-columns: minmax(0, 1fr);
        align-items: start;
        gap: 2px 0;
    }
    .ta-stat-card--compact .card-body:has(> .ta-stat__icon) {
        grid-template-columns: auto minmax(0, 1fr);
        column-gap: var(--space-3);
    }
    .ta-stat-card--compact .ta-stat__icon { grid-row: 1 / span 3; }
    .ta-stat-card--compact .ta-stat__meta { display: contents; }
    .ta-stat-card--compact .ta-stat__label,
    .ta-stat-card--compact .ta-stat__value,
    .ta-stat-card--compact .ta-stat__sub { grid-column: -2 / -1; }
    /* Room for two lines of label on every tile, so the figures in a row line up whether or not a label wraps. */
    .ta-stat-card--compact .ta-stat__label {
        grid-row: 1;
        min-height: 2.4em;
    }
    .ta-stat-card--compact .ta-stat__value {
        grid-row: 2;
        margin-left: 0;
    }
    .ta-stat-card--compact .ta-stat__sub {
        grid-row: 3;
        margin-top: 0;
    }
}

/* ── Full-page form patterns (Create / Edit pages) ─────────────────── */

/* Section head — lives at the top of <abp-card-body>, not in a separate
   abp-card-header. Overriding .card-header bg fights LeptonX dark/light
   transitions; this composition lets LeptonX own the card surface. */
.ta-form-section__head {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding-bottom: var(--space-3);
    margin-bottom: var(--space-4);
    border-bottom: 1px dashed var(--triarch-border);
}
.ta-form-section__icon {
    width: 32px;
    height: 32px;
    border-radius: var(--radius-sm);
    background: var(--triarch-surface-soft);
    color: var(--triarch-focus);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 15px;
}
.ta-form-section__title {
    font-family: var(--triarch-font-display);
    font-size: 15px;
    font-weight: 600;
    color: var(--triarch-text);
    letter-spacing: -0.005em;
    line-height: 1.25;
    margin: 0;
}
.ta-form-section__sub {
    font-size: 12.5px;
    color: var(--triarch-text-soft);
    margin-top: 2px;
    line-height: 1.4;
}
.ta-form-section__step {
    margin-left: auto;
    font-size: 11px;
    font-weight: 600;
    color: var(--triarch-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 3px 9px;
    border-radius: var(--radius-pill);
    background: var(--triarch-surface-soft);
    flex-shrink: 0;
}
.ta-form-section__step.is-current {
    background: var(--triarch-cta-tint);
    color: var(--triarch-cta-hover);
}

/* Normalize ABP form info-hint spacing — the gap between a control and its
   <small class="form-text"> info text was inconsistent because ASP.NET renders
   a <span class="field-validation-valid"> placeholder between them. Even when
   "empty" the placeholder often has whitespace content, so :empty doesn't
   collapse it; jquery.validate.unobtrusive normally hides it via inline style
   but only after its script runs. Hiding via CSS makes the layout consistent
   regardless of script timing, and only affects the valid (no-error) state —
   when validation fails the class flips to .field-validation-error and shows.

   The !important on margin-top is deliberate: <abp-select info="…"> emits
   <small class="form-text mt-2"> (Bootstrap utility wins on specificity tie
   + source order), while <abp-input info="…"> emits a bare <small class="form-text">.
   Without the override the dropdown hint sits ~8px below the control and the
   text-input hint sits ~4px below, which reads as misaligned across a form
   row of mixed control types. */
.field-validation-valid {
    display: none !important;
}
.form-text {
    display: block;
    margin-top: 4px !important;
    margin-bottom: 0;
    line-height: 1.4;
}
/* Drop the same gap-introducing utility class on the control itself, so a
   <select class="form-select mb-2"> does not stack its own bottom margin onto
   the form-text top margin. Only takes effect inside ta-form-section to avoid
   accidentally tightening unrelated forms.

   .custom-select-wrapper is a LeptonX-injected <div data-lpx-bound="true">
   that wraps every <select>. Its default margin-bottom: 1rem sits BETWEEN the
   wrapped select and the following <small class="form-text">, so dropdown
   hints rendered ~20px below the control while text-input hints rendered ~4px
   below. Zeroing the wrapper margin restores parity. Confirmed via DevTools:
   the rule originates from bootstrap-…ht.css in the LeptonX theme bundle. */
.ta-form-section .form-control,
.ta-form-section .form-select,
.ta-form-section .custom-select-wrapper {
    margin-bottom: 0;
}

/* Unified control family. Text inputs / textareas / native selects were 8px-radius with
   a faint dark border at 44px; the pickers, tag fields and select2 are 48px with
   --radius-sm corners and a --triarch-outline border. Bring the former to that standard
   so every control on the form reads as one consistent set (both themes). */
.ta-form-section input.form-control,
.ta-form-section textarea.form-control,
.ta-form-section .form-select {
    border-radius: var(--radius-sm);
    border-color: var(--triarch-outline);
}
.ta-form-section input.form-control,
.ta-form-section .form-select {
    min-height: 48px;
}
/* The border above outranks Bootstrap's .is-invalid, which left a refused field inside a form section with
   no red edge — only the message said which field was wrong. */
.ta-form-section input.form-control.is-invalid,
.ta-form-section textarea.form-control.is-invalid,
.ta-form-section .form-select.is-invalid {
    border-color: var(--triarch-danger);
}

/* Resource picker — dashed-bordered field that opens an offcanvas/modal */
.ta-form-section .form-label:has(+ .ta-picker) {
    display: flex;
    /* Bottom-align so a short label with no inline hint hugs its control instead of
       floating at the top of the reserved 36px (min-height stays for row alignment). */
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 4px 8px;
    min-height: 36px;
    margin-bottom: 6px;
    line-height: 1.25;
}
.ta-form-section .form-label:has(+ .ta-picker) small {
    display: inline-block;
    margin-left: 0 !important;
    line-height: 1.25;
}
.ta-form-section .form-label:has(+ .ta-tag-input--inline) {
    display: flex;
    align-items: flex-end;
    min-height: 36px;
    margin-bottom: 6px;
    line-height: 1.25;
}
.ta-form-section .form-label:has(+ select),
.ta-form-section .form-label:has(+ .select2-container) {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 4px 8px;
    min-height: 36px;
    margin-bottom: 6px;
    line-height: 1.25;
}
.ta-form-section .form-label:has(+ select) small,
.ta-form-section .form-label:has(+ .select2-container) small {
    display: inline-block;
    margin-left: 0 !important;
    line-height: 1.25;
}
.ta-form-section .select2-container--default .select2-selection--single {
    min-height: 48px;
    height: 48px;
    border-color: var(--triarch-outline);
    border-radius: var(--radius-sm);
    background: var(--triarch-surface);
}
.ta-form-section .select2-container--default .select2-selection--single .select2-selection__rendered {
    line-height: 46px;
    padding-left: 12px;
    padding-right: 38px;
    color: var(--triarch-text);
}
.ta-form-section .select2-container--default .select2-selection--single .select2-selection__arrow {
    height: 46px;
    right: 8px;
}
.ta-form-section .select2-container--default.select2-container--focus .select2-selection--single,
.ta-form-section .select2-container--default.select2-container--open .select2-selection--single {
    border-color: var(--triarch-cta-outline);
    box-shadow: none;
}
.ta-form-section .select2-container.is-invalid .select2-selection--single {
    border-color: var(--triarch-danger) !important;
}
.ta-field-validation {
    display: block;
    margin-top: 4px;
    font-size: 12px;
    line-height: 1.35;
}
.lpx-theme-dark .ta-form-section .select2-container--default .select2-selection--single,
[data-bs-theme="dark"] .ta-form-section .select2-container--default .select2-selection--single {
    /* Match the LeptonX dark input surface (and this widget's own dropdown panel),
       instead of the white-lifted ~#393f49 box that popped above the text inputs. */
    background: var(--lpx-content-bg, #121212);
    border-color: var(--triarch-outline);
}
.lpx-theme-dark .ta-form-section .select2-container--default.select2-container--focus .select2-selection--single,
.lpx-theme-dark .ta-form-section .select2-container--default.select2-container--open .select2-selection--single,
[data-bs-theme="dark"] .ta-form-section .select2-container--default.select2-container--focus .select2-selection--single,
[data-bs-theme="dark"] .ta-form-section .select2-container--default.select2-container--open .select2-selection--single {
    background: var(--lpx-content-bg, #121212);
    border-color: var(--triarch-cta-outline);
}

/* Select2 dropdown results — all themes.
   select2.min.css sets [aria-selected=true] to #ddd (light-theme flash on hover).
   Select2 keeps --highlighted after mouseleave; Lepton paints orange on that
   class — reset non-selected rows when the pointer is not on the row. */
.lpx-theme-light .select2-container--default .select2-results__option[aria-selected=true],
.lpx-theme-dark .select2-container--default .select2-results__option[aria-selected=true],
.lpx-theme-dim .select2-container--default .select2-results__option[aria-selected=true],
[data-bs-theme="light"] .select2-container--default .select2-results__option[aria-selected=true],
[data-bs-theme="dark"] .select2-container--default .select2-results__option[aria-selected=true] {
    background-color: var(--triarch-brand-tint);
    color: var(--triarch-primary);
}
.lpx-theme-light .select2-container--default .select2-results__option[aria-selected=false],
.lpx-theme-dark .select2-container--default .select2-results__option[aria-selected=false],
.lpx-theme-dim .select2-container--default .select2-results__option[aria-selected=false],
[data-bs-theme="light"] .select2-container--default .select2-results__option[aria-selected=false],
[data-bs-theme="dark"] .select2-container--default .select2-results__option[aria-selected=false] {
    color: var(--triarch-text);
}
.lpx-theme-light .select2-container--default .select2-results__option--highlighted[aria-selected=true]:hover,
.lpx-theme-dark .select2-container--default .select2-results__option--highlighted[aria-selected=true]:hover,
.lpx-theme-dim .select2-container--default .select2-results__option--highlighted[aria-selected=true]:hover,
[data-bs-theme="light"] .select2-container--default .select2-results__option--highlighted[aria-selected=true]:hover,
[data-bs-theme="dark"] .select2-container--default .select2-results__option--highlighted[aria-selected=true]:hover {
    background-color: color-mix(in srgb, var(--triarch-primary) 22%, transparent);
    color: var(--triarch-primary);
}
/* Stuck hover: match normal option text (not text-soft) and clear Lepton tint. */
.lpx-theme-light .select2-container--default .select2-results__option.select2-results__option--highlighted[aria-selected=false]:not(:hover),
.lpx-theme-dark .select2-container--default .select2-results__option.select2-results__option--highlighted[aria-selected=false]:not(:hover),
.lpx-theme-dim .select2-container--default .select2-results__option.select2-results__option--highlighted[aria-selected=false]:not(:hover),
[data-bs-theme="light"] .select2-container--default .select2-results__option.select2-results__option--highlighted[aria-selected=false]:not(:hover),
[data-bs-theme="dark"] .select2-container--default .select2-results__option.select2-results__option--highlighted[aria-selected=false]:not(:hover),
.lpx-theme-light .select2-container--default .select2-results__options:not(:hover) .select2-results__option--highlighted[aria-selected=false],
.lpx-theme-dark .select2-container--default .select2-results__options:not(:hover) .select2-results__option--highlighted[aria-selected=false],
.lpx-theme-dim .select2-container--default .select2-results__options:not(:hover) .select2-results__option--highlighted[aria-selected=false],
[data-bs-theme="light"] .select2-container--default .select2-results__options:not(:hover) .select2-results__option--highlighted[aria-selected=false],
[data-bs-theme="dark"] .select2-container--default .select2-results__options:not(:hover) .select2-results__option--highlighted[aria-selected=false] {
    background-color: transparent !important;
    background-image: none !important;
    color: var(--triarch-text) !important;
}
.lpx-theme-light .select2-container--default .select2-results__option--highlighted[aria-selected=false]:hover,
.lpx-theme-dark .select2-container--default .select2-results__option--highlighted[aria-selected=false]:hover,
.lpx-theme-dim .select2-container--default .select2-results__option--highlighted[aria-selected=false]:hover,
[data-bs-theme="light"] .select2-container--default .select2-results__option--highlighted[aria-selected=false]:hover,
[data-bs-theme="dark"] .select2-container--default .select2-results__option--highlighted[aria-selected=false]:hover {
    background-color: color-mix(in srgb, var(--triarch-primary) 15%, transparent) !important;
    color: var(--triarch-primary) !important;
}

/* Multi-select picker: a <select multiple class="ta-multiselect"> dressed by Select2. The same 48px control
   as the single select above; each pick is a brand-tinted tag that wraps onto more rows. Select2 copies no
   classes to its container, so the rules hang off the select's adjacent sibling. LeptonX's js-bundle.css pins
   every .select2-selection to height 46px and its row to inline-block, both !important — a box of tags has to
   grow and wrap, so those two are overridden the same way. */
select.ta-multiselect + .select2-container--default .select2-selection--multiple {
    min-height: 48px;
    height: auto !important;
    padding: 5px 8px !important;
    border: 1px solid var(--triarch-outline);
    border-radius: var(--radius-sm);
    background: var(--triarch-surface);
    cursor: text;
}
select.ta-multiselect + .select2-container--default.select2-container--focus .select2-selection--multiple,
select.ta-multiselect + .select2-container--default.select2-container--open .select2-selection--multiple {
    border-color: var(--triarch-cta-outline);
    box-shadow: none;
}
select.ta-multiselect + .select2-container--default .select2-selection--multiple .select2-selection__rendered {
    display: flex !important;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    padding: 0;
}
select.ta-multiselect + .select2-container--default .select2-selection--multiple .select2-selection__choice {
    display: inline-flex;
    align-items: center;
    margin: 0;
    padding: 3px 10px;
    border: 1px solid color-mix(in srgb, var(--triarch-primary) 40%, transparent);
    border-radius: 999px;
    background: var(--triarch-brand-tint);
    color: var(--triarch-primary);
    font-size: 0.875rem;
    line-height: 1.3;
}
select.ta-multiselect + .select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
    order: 1;
    margin: 0 0 0 6px;
    color: inherit;
    opacity: 0.7;
    font-weight: 600;
}
select.ta-multiselect + .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
    color: inherit;
    opacity: 1;
}
select.ta-multiselect + .select2-container--default .select2-selection--multiple .select2-search--inline {
    flex: 1 1 8rem;
}
select.ta-multiselect + .select2-container--default .select2-selection--multiple .select2-search__field {
    width: 100% !important;
    margin: 0;
    min-height: 30px;
    padding: 0 4px;
    background: transparent;
    color: var(--triarch-text);
}
select.ta-multiselect + .select2-container--default .select2-selection--multiple .select2-search__field::placeholder {
    color: var(--triarch-text-muted, var(--bs-secondary-color));
}
select.ta-multiselect + .select2-container--default .select2-selection--multiple .select2-selection__clear {
    margin: 0 4px 0 auto;
    order: 2;
}
.lpx-theme-dark select.ta-multiselect + .select2-container--default .select2-selection--multiple,
[data-bs-theme="dark"] select.ta-multiselect + .select2-container--default .select2-selection--multiple {
    /* The LeptonX dark input surface, as the single select above. */
    background: var(--lpx-content-bg, #121212);
}
.ta-multiselect-dropdown {
    border-color: var(--triarch-outline);
    border-radius: var(--radius-sm);
}
.ta-multiselect-dropdown .select2-results__options {
    max-height: 280px;
}

.ta-picker {
    width: 100%;
    min-height: 48px;
    padding: 8px 10px;
    border: 1px solid var(--triarch-outline);
    border-radius: var(--radius-sm);
    background: var(--triarch-surface);
    cursor: pointer;
    display: grid;
    grid-template-columns: 30px minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-2);
    color: inherit;
    text-decoration: none;
    transition: var(--transition-color);
    text-align: left;
}
.ta-picker:hover,
.ta-picker:focus {
    border-color: var(--triarch-cta-outline);
    background: var(--triarch-surface-soft);
    color: var(--triarch-text);
    outline: none;
}
.ta-picker__icon {
    width: 30px;
    height: 30px;
    border-radius: var(--radius-sm);
    background: var(--triarch-surface-soft);
    color: var(--triarch-text-soft);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 14px;
}
.ta-picker__body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    line-height: 1.25;
}
.ta-picker__placeholder {
    display: block;
    font-size: 13px;
    color: var(--triarch-text-soft);
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ta-picker__value {
    font-size: 13px;
    font-weight: 500;
    color: var(--triarch-text);
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ta-picker__sub {
    font-size: 11px;
    color: var(--triarch-text-soft);
    margin-top: 1px;
}
.ta-picker__cta {
    font-size: 11px;
    font-weight: 700;
    color: var(--triarch-cta-hover);
    font-family: var(--triarch-font-display);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    justify-self: end;
    white-space: nowrap;
}

.lpx-theme-dark .ta-picker,
[data-bs-theme="dark"] .ta-picker {
    /* Match the LeptonX dark input surface so the picker reads like the other
       form controls instead of a lifted ~#393f49 box. */
    background: var(--lpx-content-bg, #121212);
    border-color: var(--triarch-outline);
}

.lpx-theme-dark .ta-picker:hover,
.lpx-theme-dark .ta-picker:focus,
[data-bs-theme="dark"] .ta-picker:hover,
[data-bs-theme="dark"] .ta-picker:focus {
    background: var(--lpx-content-bg, #121212);
    border-color: var(--triarch-cta-outline);
}

/* Page action bar (top right above the form, or sticky bottom) */
.ta-page-actions {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

/* ── Page header action buttons — icon-only on phone/tablet ────────────
   Every list/dashboard page puts its header buttons (Export to Excel, New
   Project, Import price, ...) in one of two spots: the LeptonX-rendered
   #AbpContentToolbar column (from @section content_toolbar) or a page's own
   .ta-page-actions wrapper. One rule here covers both — no per-page CSS.

   Below 992px there isn't room for icon + label next to the page title, so
   only the icon stays. font-size:0 (not display:none) hides the label —
   works whether the label is bare text ("New Project") or an abp-button's
   <span> ("Export to Excel"), and unlike display:none it still leaves the
   text exposed as the button's accessible name for screen readers.
   :has() scopes this to buttons that already carry an icon, so text-only
   buttons (e.g. Quotes' "My Work" / "Estimates" links) are left alone —
   there is nothing to fall back to for those. Desktop (≥992px) is untouched. */
@media (max-width: 991.98px) {
    /* Beats controlroom-ui's desktop flex-wrap:wrap on .lpx-content-toolbar. */
    body.ta-controlroom-page .lpx-content-container .lpx-content-toolbar,
    .lpx-content-toolbar {
        flex-wrap: nowrap;
        align-items: center;
    }
    .lpx-content-toolbar > .col {
        min-width: 0;
    }
    .lpx-content-toolbar > .col .lpx-main-title:not(.ta-page-title-with-actions) {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    #AbpContentToolbar,
    .ta-page-actions {
        flex-wrap: nowrap;
        gap: 6px;
    }
    /* 3+ header buttons: two icon buttons (~39px each + gap) is already
       ~84px — reserving the full row for a 3rd/4th button leaves too little
       room for the title and forces it to get hard-clipped mid-word (no
       "…", looks like the buttons are eating the text). Let the group wrap
       onto its own line instead, right-aligned, so the title keeps most of
       the row. Only kicks in for 3+ buttons — 1-2 button pages keep the
       tight one-line layout above. */
    #AbpContentToolbar:has(> :nth-child(3)),
    .ta-page-actions:has(> :nth-child(3)) {
        flex-wrap: wrap;
        justify-content: flex-end;
        max-width: 96px;
        row-gap: 4px;
    }
    #AbpContentToolbar .btn:has(i, .fa),
    .ta-page-actions .btn:has(i, .fa) {
        font-size: 0;
        gap: 0;
        padding-left: 10px;
        padding-right: 10px;
    }
    #AbpContentToolbar .btn:has(i, .fa) i,
    #AbpContentToolbar .btn:has(i, .fa) .fa,
    .ta-page-actions .btn:has(i, .fa) i,
    .ta-page-actions .btn:has(i, .fa) .fa {
        font-size: 14px;
        margin: 0 !important;
    }
}

/* ── Inline tag input (chip row with + button) ─────────────────────── */
.ta-tag-input {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    min-height: 34px;
    padding: 4px 8px;
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-sm);
    background: var(--triarch-surface);
}
/* Inline variant — sits directly under a label inside a form section,
   no extra container chrome, blends into the form. */
.ta-tag-input--inline {
    border-color: transparent;
    padding: 2px 0;
    background: transparent;
}
.ta-form-section .ta-tag-input--inline {
    width: 100%;
    min-height: 48px;
    padding: 8px 10px;
    border: 1px solid var(--triarch-outline);
    border-radius: var(--radius-sm);
    background: var(--triarch-surface);
    gap: var(--space-2);
}
.ta-form-section .ta-tag-input--inline:focus-within {
    border-color: var(--triarch-cta-outline);
    background: var(--triarch-surface-soft);
}
.ta-tag-input__field {
    flex: 1 1 120px;
    min-width: min(100%, 140px);
    color: var(--triarch-text);
}
.ta-form-section .ta-tag-input--inline .ta-tag-input__field {
    min-height: 30px;
    padding: 0 2px;
    font-size: 13px;
    line-height: 30px;
}
.ta-tag-input__field::placeholder {
    color: var(--triarch-text-soft);
}
.ta-tag-input__field:focus {
    outline: none;
    box-shadow: none;
}
.ta-tag-input__empty {
    font-size: 12px;
    color: var(--triarch-text-soft);
    font-style: italic;
}
.ta-tag-input__chip {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px 4px 2px 9px;
    border-radius: var(--radius-sm);
    background: var(--triarch-surface-soft);
    color: var(--triarch-text-soft);
    font-size: 12px;
    font-weight: 500;
    line-height: 1.3;
    border: 1px solid var(--triarch-border);
}
.ta-tag-input__chip-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border-radius: var(--radius-xs);
    background: transparent;
    color: currentColor;
    border: none;
    cursor: pointer;
    font-size: 12px;
    line-height: 1;
    padding: 0;
    opacity: 0.55;
}
.ta-tag-input__chip-remove:hover {
    opacity: 1;
    background: rgba(0, 0, 0, 0.06);
    color: var(--triarch-text);
}
.ta-tag-input__add {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: var(--radius-xs);
    background: var(--triarch-surface);
    color: var(--triarch-text-soft);
    border: 1px dashed var(--triarch-outline);
    cursor: pointer;
    font-size: 10px;
    line-height: 1;
    padding: 0;
    transition: var(--transition-color);
}
.ta-tag-input__add:hover,
.ta-tag-input__add:focus {
    background: var(--triarch-surface-soft);
    color: var(--triarch-text);
    border-color: var(--triarch-focus);
    border-style: solid;
    outline: none;
}

.ta-form-section .ta-tag-input--inline .ta-tag-input__add {
    width: 30px;
    height: 30px;
    margin-left: auto;
    border-style: solid;
    background: var(--triarch-surface-soft);
}

.lpx-theme-dark .ta-form-section .ta-tag-input--inline,
[data-bs-theme="dark"] .ta-form-section .ta-tag-input--inline {
    /* Match the LeptonX dark input surface like the other form controls,
       not the white-lifted ~#393f49 box. */
    background: var(--lpx-content-bg, #121212);
    border-color: var(--triarch-outline);
}

.lpx-theme-dark .ta-form-section .ta-tag-input--inline:focus-within,
[data-bs-theme="dark"] .ta-form-section .ta-tag-input--inline:focus-within {
    background: var(--lpx-content-bg, #121212);
    border-color: var(--triarch-cta-outline);
}

/* Note: row-action dropdown button intentionally left to ABP/LeptonX defaults. */

/* ── Form section head: right-aligned action cluster (meta + CTA) ─────
   Used by the Service Steps section in ServiceDefinitions/Create. */
.ta-form-section__head-actions {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    flex-shrink: 0;
}
.ta-form-section__meta {
    font-size: 11.5px;
    color: var(--triarch-text-soft);
    line-height: 1.3;
}
.ta-form-section__meta-strong {
    color: var(--triarch-text);
    font-weight: 600;
}
.ta-form-section__meta-dot {
    margin: 0 4px;
    opacity: 0.6;
}

/* ── Activity (service-step) list ─────────────────────────────────────
   Vertical stack of step cards + an inline "add" dropzone. The container
   has no chrome of its own; cards carry the surface. */
.ta-activity-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

/* Step card */
.ta-activity-step {
    position: relative;
    display: flex;
    grid-template-columns: 18px 28px 1fr auto;
    align-items: center;
    gap: var(--space-3);
    padding: 12px 12px 12px 8px;
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-sm);
    background: var(--triarch-surface);
    transition: var(--transition-color), var(--transition-shadow);
}
.ta-activity-step:hover {
    border-color: var(--triarch-outline);
    box-shadow: 0 1px 0 var(--triarch-border);
}

.ta-activity-step__handle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 22px;
    border: none;
    background: transparent;
    color: var(--triarch-text-soft);
    opacity: 0.45;
    cursor: grab;
    padding: 0;
    font-size: 12px;
}
.ta-activity-step__handle:hover { opacity: 0.9; }
.ta-activity-step__handle:active { cursor: grabbing; }

.ta-activity-step__num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--triarch-cta-tint);
    color: var(--triarch-cta-hover);
    font-family: var(--triarch-font-display);
    font-size: 12px;
    font-weight: 700;
    flex-shrink: 0;
}

.ta-activity-step__body {
    min-width: 0;
}
.ta-activity-step__title-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.ta-activity-step__title {
    font-family: var(--triarch-font-display);
    font-size: 14px;
    font-weight: 600;
    font-style: italic;
    color: var(--triarch-text);
    letter-spacing: -0.005em;
    line-height: 1.25;
    min-width: 0;
    /* Unbroken tokens (file names, codes) wrap instead of forcing the
       offcanvas into horizontal scroll. */
    overflow-wrap: anywhere;
}
.ta-activity-step__code {
    font-family: var(--triarch-font-mono);
    font-size: 10.5px;
    font-weight: 600;
    color: var(--triarch-text-soft);
    background: var(--triarch-surface-soft);
    border: 1px solid var(--triarch-border);
    padding: 1px 6px;
    border-radius: var(--radius-xs);
    letter-spacing: 0.02em;
}
.ta-activity-step__badge {
    font-size: 10.5px;
    font-weight: 600;
    padding: 2px 9px;
    border-radius: var(--radius-pill);
    line-height: 1.3;
}
.ta-activity-step__badge--fee {
    background: var(--triarch-cta-tint);
    color: var(--triarch-cta-hover);
    border: 1px solid var(--triarch-cta-outline);
}

.ta-activity-step__meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 6px;
    font-size: 11.5px;
    color: var(--triarch-text-soft);
    line-height: 1.4;
}
.ta-activity-step__meta-key {
    font-weight: 600;
    color: var(--triarch-text);
}
.ta-activity-step__meta-val {
    color: var(--triarch-text-soft);
}
.ta-activity-step__meta-sep {
    opacity: 0.5;
    margin: 0 2px;
}

.ta-activity-step__actions {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}
.ta-activity-step__action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: var(--radius-xs);
    background: transparent;
    color: var(--triarch-text-soft);
    border: 1px solid var(--triarch-border);
    cursor: pointer;
    font-size: 11px;
    padding: 0;
    transition: var(--transition-color);
}
.ta-activity-step__action:hover,
.ta-activity-step__action:focus {
    background: var(--triarch-surface-soft);
    color: var(--triarch-text);
    border-color: var(--triarch-outline);
    outline: none;
}
.ta-activity-step__action--danger:hover,
.ta-activity-step__action--danger:focus {
    color: var(--triarch-danger);
    border-color: var(--triarch-danger);
    background: transparent;
}
/* Persistent active state — e.g. the document currently open in review */
.ta-activity-step__action.is-active {
    background: var(--triarch-cta-tint);
    color: var(--triarch-cta-hover);
    border-color: var(--triarch-cta-outline);
}

/* Document variant — file rows in the submittal-documents offcanvas
   (DocumentsPanel.cshtml). Same card anatomy as an activity step, but the
   leading icon is a static glyph (nothing to drag) and the title is an
   upright file name rather than an italic step name. */
.ta-activity-step--document .ta-activity-step__handle {
    cursor: default;
    opacity: 0.6;
}
/* Single-line file name with ellipsis (full name in the title attribute);
   the extension chip keeps its width and the name truncates beside it. */
.ta-activity-step--document .ta-activity-step__title-row {
    flex-wrap: nowrap;
}
.ta-activity-step--document .ta-activity-step__title {
    font-style: normal;
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ta-activity-step--document .ta-activity-step__code {
    flex-shrink: 0;
}
.ta-activity-step--document .ta-activity-step__code:empty {
    display: none;
}

/* Drag-and-drop reorder states */
.ta-activity-step--dragging {
    opacity: 0.4;
}
.ta-activity-step--drop-before {
    box-shadow: inset 0 2px 0 var(--triarch-cta-hover);
}
.ta-activity-step--drop-after {
    box-shadow: inset 0 -2px 0 var(--triarch-cta-hover);
}

/* ─────────────────────────────────────────────────────────────────────
   Step-group wrapper — one per StepOrder, holds 1..N stacked lane cards.

   For sequential (single-lane) steps the wrapper is intentionally
   invisible — the lane card looks like a standalone step matching the
   classic UI. For parallel groups (2+ lanes) the wrapper picks up a
   subtle dashed left border and a small "Parallel" hint chip above the
   cards so the grouping is unmistakable.

   Drag-and-drop attaches at this level: any lane drag-handle inside the
   wrapper moves the whole group as a unit (JS in
   serviceDefinitionWizard.js walks up to find this container).
   ───────────────────────────────────────────────────────────────────── */
.ta-activity-step-group {
    position: relative;
}
.ta-activity-step-group + .ta-activity-step-group {
    margin-top: var(--space-2);
}
.ta-activity-step-group--parallel {
    padding: 6px 0 6px 10px;
    border-left: 2px dashed var(--triarch-cta-outline);
    background: linear-gradient(to right, var(--triarch-cta-tint) 0%, transparent 24px);
    border-radius: var(--radius-sm);
}
.ta-activity-step-group--parallel .ta-activity-lane + .ta-activity-lane {
    margin-top: 6px;
}

/* "X lanes run together" hint chip above a parallel group */
.ta-activity-step-group__hint {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 6px 0;
    padding: 2px 8px;
    font-size: 10.5px;
    font-weight: 600;
    color: var(--triarch-cta-hover);
    background: var(--triarch-surface);
    border: 1px solid var(--triarch-cta-outline);
    border-radius: var(--radius-pill);
    letter-spacing: 0.02em;
}

/* Drag states on the group container */
.ta-activity-step-group--dragging {
    opacity: 0.4;
}
.ta-activity-step-group--drop-before {
    box-shadow: inset 0 2px 0 var(--triarch-cta-hover);
}
.ta-activity-step-group--drop-after {
    box-shadow: inset 0 -2px 0 var(--triarch-cta-hover);
}

/* ─────────────────────────────────────────────────────────────────────
   Lane card — visually identical to the classic step card. Used for
   sequential steps (one card per step) and for each row of a parallel
   group. The repeated step-number circle inside a parallel group is the
   primary visual cue that the rows share an order.
   ───────────────────────────────────────────────────────────────────── */
.ta-activity-lane {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: 12px 12px 12px 8px;
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-sm);
    background: var(--triarch-surface);
    transition: var(--transition-color), var(--transition-shadow);
}
.ta-activity-lane:hover {
    border-color: var(--triarch-outline);
    box-shadow: 0 1px 0 var(--triarch-border);
}

/* Pending lane — previews the auto-scaffolded Certificate Issuance step on the
   ServiceDefinition Create/Edit pages before it is persisted ("added when you
   save"). Dashed + muted so it cannot be mistaken for a saved step. */
.ta-activity-lane--pending {
    border-style: dashed;
    background: transparent;
}
.ta-activity-lane--pending:hover {
    border-color: var(--triarch-border);
    box-shadow: none;
}
.ta-activity-lane--pending .ta-activity-lane__num,
.ta-activity-lane--pending .ta-activity-lane__title {
    color: var(--triarch-text-muted);
}

.ta-activity-lane__handle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 22px;
    border: none;
    background: transparent;
    color: var(--triarch-text-soft);
    opacity: 0.45;
    cursor: grab;
    padding: 0;
    font-size: 12px;
    flex-shrink: 0;
}
.ta-activity-lane__handle:hover { opacity: 0.9; }
.ta-activity-lane__handle:active { cursor: grabbing; }

.ta-activity-lane__num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--triarch-cta-tint);
    color: var(--triarch-cta-hover);
    font-family: var(--triarch-font-display);
    font-size: 12px;
    font-weight: 700;
    flex-shrink: 0;
}

.ta-activity-lane__body {
    min-width: 0;
    flex: 1 1 auto;
}
.ta-activity-lane__title-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.ta-activity-lane__title {
    font-family: var(--triarch-font-display);
    font-size: 14px;
    font-weight: 700;
    font-style: normal;
    color: var(--triarch-text);
    letter-spacing: -0.005em;
    line-height: 1.25;
}
.ta-activity-lane__code {
    font-family: var(--triarch-font-mono);
    font-size: 10.5px;
    font-weight: 600;
    color: var(--triarch-text-soft);
    background: var(--triarch-surface-soft);
    border: 1px solid var(--triarch-border);
    padding: 1px 6px;
    border-radius: var(--radius-xs);
    letter-spacing: 0.02em;
}
.ta-activity-lane__badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 10.5px;
    font-weight: 600;
    padding: 2px 9px;
    border-radius: var(--radius-pill);
    line-height: 1.3;
}
.ta-activity-lane__badge--fee {
    background: var(--triarch-cta-tint);
    color: var(--triarch-cta-hover);
    border: 1px solid var(--triarch-cta-outline);
}
.ta-activity-lane__badge--final {
    background: var(--triarch-cta-hover);
    color: var(--triarch-on-action, #ffffff);
    border: 1px solid var(--triarch-cta-hover);
}

.ta-activity-lane__meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 6px;
    font-size: 11.5px;
    color: var(--triarch-text-soft);
    line-height: 1.4;
}
.ta-activity-lane__meta-key {
    font-weight: 600;
    color: var(--triarch-text);
}
.ta-activity-lane__meta-val {
    color: var(--triarch-text-soft);
}
.ta-activity-lane__meta-sep {
    opacity: 0.5;
    margin: 0 2px;
}

.ta-activity-lane__actions {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}
.ta-activity-lane__action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 28px;
    min-width: 28px;
    padding: 0 8px;
    border-radius: var(--radius-xs);
    background: transparent;
    color: var(--triarch-text-soft);
    border: 1px solid var(--triarch-border);
    cursor: pointer;
    font-size: 11px;
    transition: var(--transition-color);
    gap: 4px;
}
.ta-activity-lane__action:hover,
.ta-activity-lane__action:focus {
    background: var(--triarch-surface-soft);
    color: var(--triarch-text);
    border-color: var(--triarch-outline);
    outline: none;
}
.ta-activity-lane__action--danger:hover,
.ta-activity-lane__action--danger:focus {
    color: var(--triarch-danger);
    border-color: var(--triarch-danger);
    background: transparent;
}
.ta-activity-lane__action--add-lane {
    color: var(--triarch-cta-hover);
    border-color: var(--triarch-cta-outline);
    border-style: dashed;
    background: var(--triarch-cta-tint);
    /* Icon-only — title tooltip carries the meaning. Same square footprint as the other lane actions. */
    width: 28px;
    padding: 0;
}
.ta-activity-lane__action--add-lane:hover,
.ta-activity-lane__action--add-lane:focus {
    background: var(--triarch-cta-hover);
    color: var(--triarch-on-action, #ffffff);
    border-color: var(--triarch-cta-hover);
}

/* ─────────────────────────────────────────────────────────────────────
   Runtime activity card — redesigned three-zone layout (header · signal
   row · meta line · action line) on the Service Request detail workflow
   list. Shares the .ta-activity-lane root (drag/scroll JS + parallel
   grouping) but --runtime flips it to a vertical card with a state rail.
   Colours: triarch token first, reference hex fallback.
   ───────────────────────────────────────────────────────────────────── */
.ta-activity-lane--runtime {
    --ta-actrow-indent: 35px;
    display: block;
    align-items: stretch;
    gap: 0;
    padding: 12px 14px;
    border-left: 3px solid var(--triarch-border);
}
.ta-activity-lane--st-pending  { border-left-color: var(--triarch-outline, #B4B2A9); }
.ta-activity-lane--st-active   { border-left-color: var(--status-in-review, #BA7517); }
.ta-activity-lane--st-hold     { border-left-color: var(--triarch-outline, #B4B2A9); }
.ta-activity-lane--st-approved { border-left-color: var(--status-approved, #1D9E75); }
.ta-activity-lane--st-rejected { border-left-color: var(--status-rejected, #E24B4A); }

.ta-actrow__header {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}
.ta-actrow__type {
    font-size: 11px;
    color: var(--triarch-text-soft);
    border: 1px solid var(--triarch-border);
    padding: 1px 7px;
    border-radius: var(--radius-xs);
    line-height: 1.5;
}
.ta-actrow__actions,
.ta-actrow__header-right {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.ta-actrow__reviewer-label {
    font-size: 11.5px;
    font-weight: 600;
    color: var(--triarch-text-soft);
}

/* Sub-zones align under the activity name, not the step badge. */
.ta-actrow__signals,
.ta-actrow__meta,
.ta-actrow__action {
    padding-left: var(--ta-actrow-indent);
}

.ta-actrow__signals {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 9px;
}
.ta-actrow__sig {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    padding: 2px 9px;
    border-radius: var(--radius-pill);
    line-height: 1.4;
}
.ta-actrow__sig--cycle      { color: var(--status-rejected, #993C1D); background: var(--triarch-cta-tint, #FAECE7); }
.ta-actrow__sig--docs       { color: #185FA5; background: #E6F1FB; }
.ta-actrow__sig--conditions { color: var(--status-in-review, #854F0B); background: var(--triarch-success-bg, #FAEEDA); }

.ta-actrow__meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-top: 10px;
    font-size: 12.5px;
}
.ta-actrow__sla {
    display: inline-flex;
    align-items: center;
    color: var(--triarch-text-soft);
    font-weight: 500;
}
.ta-actrow__sla--ok     { color: var(--triarch-success-fg, #0F6E56); }
.ta-actrow__sla--warn   { color: var(--status-in-review, #854F0B); }
.ta-actrow__sla--danger { color: var(--triarch-danger, #A32D2D); font-weight: 600; }
.ta-actrow__sla--muted  { color: var(--triarch-text-soft); }

.ta-actrow__reviewer {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}
.ta-actrow__avatar {
    position: relative;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: #E6F1FB;
    color: #185FA5;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    font-weight: 600;
}
.ta-actrow__avatar-badge {
    position: absolute;
    bottom: -2px;
    right: -2px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid var(--triarch-surface, #fff);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 7px;
    color: #fff;
}
.ta-actrow__avatar-badge--ok { background: var(--status-approved, #1D9E75); }
.ta-actrow__avatar-badge--no { background: var(--status-rejected, #E24B4A); }
.ta-actrow__avatar-badge--edit { background: var(--triarch-primary, #185FA5); }

/* Editable reviewer avatar — the avatar itself is the "change reviewer" control
   (pending / pre-launch). Button reset over the avatar styling, plus an always-on
   pencil corner and a focus/hover ring so it reads as actionable. */
.ta-actrow__avatar--editable {
    appearance: none;
    border: none;
    padding: 0;
    cursor: pointer;
    font-family: inherit; /* keep .ta-actrow__avatar's own font-size/weight; just drop the UA button family */
    transition: box-shadow .15s ease;
}
.ta-actrow__avatar--editable:hover,
.ta-actrow__avatar--editable:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--triarch-surface, #fff),
                0 0 0 4px var(--triarch-primary, #185FA5);
}

.ta-actrow__action {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 8px;
}
.ta-actrow__bar {
    flex: 1 1 auto;
    height: 5px;
    border-radius: 3px;
    background: var(--triarch-surface-soft, #F1EFE8);
    overflow: hidden;
}
.ta-actrow__bar--paused { opacity: 0.55; }
.ta-actrow__bar-fill { height: 100%; border-radius: 3px; }
.ta-actrow__bar-fill--ok      { background: var(--status-approved, #1D9E75); }
.ta-actrow__bar-fill--warn    { background: var(--status-in-review, #BA7517); }
.ta-actrow__bar-fill--danger  { background: var(--status-rejected, #E24B4A); }
.ta-actrow__bar-fill--neutral { background: transparent; }
.ta-actrow__bar-spacer { flex: 1 1 auto; }

.ta-actrow__open {
    color: var(--triarch-primary);
    border: 1px solid var(--triarch-outline-warm, var(--triarch-border));
    background: var(--triarch-surface);
    font-weight: 500;
}
.ta-actrow__open:hover {
    border-color: var(--triarch-primary);
    background: var(--triarch-primary-tint, var(--triarch-surface-soft));
    color: var(--triarch-primary-strong, var(--triarch-primary));
}
.ta-actrow__cta {
    color: var(--status-rejected, #993C1D);
    background: var(--triarch-cta-tint, #FAECE7);
    border: 1px solid var(--triarch-cta-outline, #F0997B);
    font-weight: 500;
}
.ta-actrow__cta:hover { background: var(--triarch-cta-hover); color: var(--triarch-on-action, #ffffff); }

/* ── Runtime step-card tidy-up ────────────────────────────────────────────
   Replaces the dominating full-width SLA bar with a thin strip on the card's
   bottom edge, adds depth (shadow), a state-coloured step number, a thicker
   state rail, more breathing room between steps, and a connector line so the
   steps read as a sequence rather than a flat stack. ── */
.ta-actrow__edgebar {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background: var(--triarch-surface-soft, #f0f4f8);
    border-bottom-left-radius: var(--radius-sm);
    border-bottom-right-radius: var(--radius-sm);
    overflow: hidden;
}
.ta-actrow__edgebar--paused { opacity: 0.55; }
.ta-actrow__edgebar-fill { display: block; height: 100%; }

/* Depth + a stronger state rail on runtime cards. */
.ta-activity-lane--runtime {
    box-shadow: 0 1px 3px rgba(16, 24, 40, 0.06);
    border-left-width: 4px;
    padding-bottom: 15px;
}
.ta-activity-lane--runtime:hover { box-shadow: 0 2px 8px rgba(16, 24, 40, 0.09); }

/* State-coloured step number so Active/Done/Rejected pop at a glance. */
.ta-activity-lane--runtime.ta-activity-lane--st-active   .ta-activity-lane__num { background: var(--status-in-review); color: #fff; }
.ta-activity-lane--runtime.ta-activity-lane--st-approved .ta-activity-lane__num { background: var(--status-approved); color: #fff; }
.ta-activity-lane--runtime.ta-activity-lane--st-rejected .ta-activity-lane__num { background: var(--status-rejected); color: #fff; }

/* More space between steps + a connector line so 1 → 2 reads as a sequence
   (scoped to runtime groups; parallel siblings inside one group are unaffected). */
.ta-activity-step-group:has(.ta-activity-lane--runtime) + .ta-activity-step-group {
    margin-top: 16px;
}
.ta-activity-step-group:has(.ta-activity-lane--runtime):not(:last-child)::after {
    content: "";
    position: absolute;
    left: 32px;
    bottom: -16px;
    width: 2px;
    height: 16px;
    background: var(--triarch-border);
}

/* Activity work-surface stepper — sequential steps (numbered nodes joined by
   connector lines), NOT a pill/button group. Past = brand node + check (clickable
   back); current = brand node + bold label; future = neutral (enabled) or muted +
   lock. */
.ta-stepper { display: flex; align-items: center; flex-wrap: wrap; gap: 0; }
.ta-step { display: inline-flex; align-items: center; }
.ta-step__link {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    text-decoration: none;
    color: var(--triarch-text-soft);
    font-size: 0.875rem;
    font-weight: 500;
    padding: 0.15rem 0.1rem;
}
.ta-step__num {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 12px;
    font-weight: 700;
    background: var(--triarch-surface);
    color: var(--triarch-text-soft);
    border: 1.5px solid var(--triarch-border);
    transition: background-color var(--duration-fast) var(--ease-standard),
        border-color var(--duration-fast) var(--ease-standard),
        color var(--duration-fast) var(--ease-standard);
}
.ta-step__label { white-space: nowrap; }
.ta-step__lock { font-size: 11px; color: var(--triarch-text-soft); }

/* Connector line between nodes; turns brand once that segment is completed. */
.ta-step__line {
    flex: 0 0 auto;
    width: 32px;
    height: 2px;
    margin: 0 0.4rem;
    background: var(--triarch-border);
}
.ta-step__line--done { background: var(--triarch-primary); }

/* Hover only on the clickable (anchor) steps. */
a.ta-step__link:hover .ta-step__label { color: var(--triarch-primary); }
a.ta-step__link:hover .ta-step__num {
    border-color: var(--triarch-primary);
    color: var(--triarch-primary);
}

/* States */
.ta-step--active .ta-step__num {
    background: var(--triarch-primary);
    border-color: var(--triarch-primary);
    color: var(--triarch-on-action, #ffffff);
}
.ta-step--active .ta-step__label { color: var(--triarch-primary); font-weight: 700; }
.ta-step--done .ta-step__num {
    background: var(--triarch-primary);
    border-color: var(--triarch-primary);
    color: var(--triarch-on-action, #ffffff);
}
.ta-step--done .ta-step__label { color: var(--triarch-text); }
.ta-step--locked { opacity: 0.55; }
.ta-step--locked .ta-step__link { cursor: not-allowed; }

/* "Document under review" chip — sits in the Plan Review topbar's existing row (zero added
   height). Communicates the current submittal and opens the submittals picker to switch. */
.ta-doc-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    max-width: 200px;
    padding: 0.25rem 0.6rem;
    border: 1.5px solid var(--triarch-cta-outline);
    border-radius: 8px;
    background: var(--triarch-cta-tint);
    color: var(--triarch-cta-hover);
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 1.2;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-standard),
        border-color var(--duration-fast) var(--ease-standard);
}
.ta-doc-chip:hover { background: var(--triarch-cta-outline); }
.ta-doc-chip__icon { flex: 0 0 auto; font-size: 0.95rem; }
.ta-doc-chip__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ta-doc-chip__count {
    flex: 0 0 auto;
    font-size: 0.6875rem;
    background: var(--triarch-surface);
    border-radius: 999px;
    padding: 0.05rem 0.4rem;
}
.ta-doc-chip__caret { flex: 0 0 auto; font-size: 0.75rem; opacity: 0.8; }
/* Display-only chip (Report/Verify stages — the document isn't switchable). */
.ta-doc-chip--static { cursor: default; }
.ta-doc-chip--static:hover { background: var(--triarch-cta-tint); }
/* "Frozen" badge inside the chip — shown only once the verdict locks the output. */
.ta-doc-chip__badge {
    flex: 0 0 auto;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--triarch-text-soft);
    background: var(--triarch-surface);
    border-radius: 999px;
    padding: 0.05rem 0.45rem;
}

/* ─────────────────────────────────────────────────────────────────────
   "How to set up this service" — help affordance.

   The trigger is a subtle question-circle icon beside the page title;
   clicking it opens a Bootstrap offcanvas (slide from right) that
   contains the recommended setup sequence as four numbered cards.
   The offcanvas takes zero page space when closed.
   ───────────────────────────────────────────────────────────────────── */

/* Offcanvas chrome — the panel root is <ta-offcanvas>, so width and the widen toggle
   come from the shared scale; the descendant selectors below target the standard
   .offcanvas-header / .offcanvas-body the help partials author. */
.ta-help-offcanvas .offcanvas-header {
    background: var(--triarch-cta-tint);
    color: var(--triarch-cta-hover);
    border-bottom: 1px solid var(--triarch-cta-outline);
}
.ta-help-offcanvas .offcanvas-title {
    font-family: var(--triarch-font-display);
    font-size: 14px;
    font-weight: 600;
}
.ta-help-offcanvas .offcanvas-body {
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--triarch-text);
}

/* Submittal-documents panel. Width comes from the shared offcanvas scale like every
   other panel; the reader widens it with the toggle when file names run long. Make
   the body a flex column so the list can grow to fill available height, eliminating
   the empty gap that appeared between a capped list and the footer. */
.ta-docs-offcanvas .offcanvas-body {
    display: flex;
    flex-direction: column;
}
/* Section labels inside the panel (Project documents / Submittals) */
.ta-docs-section__label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--triarch-text-soft);
}
/* List grows to fill all remaining body height — scrollbar only appears when
   documents genuinely overflow the panel, not when space is left at the bottom. */
.ta-docs-scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: 2px;
    scrollbar-width: thin;
    scrollbar-color: var(--triarch-outline) transparent;
}

/* ── Form-response drawer (FormResponseDrawer.cshtml) ─────────────────────
   Read-only list of the applicant's submitted answers. Question numbers
   reuse .ta-activity-step__num; the 34px indents below align choice/answer
   text under the question title (26px circle + 8px gap). */
.ta-form-response {
    list-style: none;
    margin: 0;
    padding: 0;
}
.ta-form-response__item {
    padding: 14px 0;
    border-bottom: 1px solid var(--triarch-border);
}
.ta-form-response__item:first-child { padding-top: 2px; }
.ta-form-response__item:last-child { border-bottom: 0; }
.ta-form-response__head {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-bottom: 8px;
}
.ta-form-response__question {
    font-family: var(--triarch-font-display);
    font-size: 13.5px;
    font-weight: 600;
    color: var(--triarch-text);
    line-height: 1.35;
    margin: 0;
    padding-top: 4px; /* optically centers against the 26px number circle */
}
.ta-form-response__choices {
    list-style: none;
    margin: 0 0 0 34px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.ta-form-response__choice {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12.5px;
    color: var(--triarch-text-soft);
}
.ta-form-response__choice i {
    font-size: 11px;
    opacity: 0.45;
}
.ta-form-response__choice.is-selected {
    color: var(--status-approved);
    font-weight: 600;
}
.ta-form-response__choice.is-selected i { opacity: 1; }
.ta-form-response__answer {
    margin: 0 0 0 34px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--triarch-text);
    overflow-wrap: anywhere;
}
.ta-form-response__answer--empty {
    color: var(--triarch-text-soft);
    font-style: italic;
}
/* Editable control (text input etc.) aligned under the question title,
   same indent as choices/answers. */
.ta-form-response__control {
    margin: 0 0 0 34px;
}

/* Offcanvas eyebrow header — kicker pill + widen/close buttons + title +
   subtitle + divider: the standard chrome for every panel in the solution
   (the ArchAI assistant is the reference). Defined here and nowhere else;
   the module-local copies were removed once all modules loaded this file. */
.ta-offcanvas-eyebrow {
    margin-top: -4px;
}
/* Panel title: the card and section title size (docs/ui-standard.md §3), so a side panel reads like a card. */
.ta-offcanvas-eyebrow__title {
    font-family: var(--triarch-font-display, inherit);
    font-size: 15px;
    font-weight: 700;
    color: var(--triarch-text, inherit);
    line-height: 1.25;
}
.ta-offcanvas-eyebrow__subtitle {
    max-width: 48ch;
    line-height: 1.4;
    color: var(--triarch-text-soft, inherit);
}
.ta-divider {
    border: 0;
    border-top: 1px solid var(--triarch-border, #eaeef2);
    opacity: 1;
    height: 0;
}

/* Offcanvas split footer — secondary actions (Clear, Remove, Deactivate) on
   the left, Cancel + primary action on the right. Used as
   <ta-offcanvas-footer class="ta-offcanvas-footer--split">; see
   docs/offcanvas-developer-guide.md 8a. Was copied into six module files. */
.ta-offcanvas-footer--split {
    justify-content: flex-start !important;
}
.ta-offcanvas-footer__secondary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2, 0.5rem);
}
.ta-offcanvas-footer__primary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2, 0.5rem);
    margin-left: auto;
}

/* Upload document panel — shared storefront offcanvas (project + service
   request modes, Documents/UploadDocumentPanel) and ControlRoom
   DocumentEditorPanel. Drag-and-drop file target, selected-file chip,
   and the document-type dropdown. */
.ta-upload-dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    width: 100%;
    padding: 28px 16px;
    border: 1.5px dashed var(--triarch-outline);
    border-radius: var(--radius-sm);
    background: var(--triarch-surface-soft);
    color: var(--triarch-text-soft);
    text-align: center;
    cursor: pointer;
    transition: var(--transition-color);
}
.ta-upload-dropzone:hover,
.ta-upload-dropzone:focus-visible,
.ta-upload-dropzone.is-dragover {
    background: var(--triarch-cta-tint);
    border-color: var(--triarch-cta-outline);
    outline: none;
}
.ta-upload-dropzone.is-dragover {
    border-style: solid;
}
.ta-upload-dropzone__icon {
    font-size: 22px;
    opacity: 0.65;
    color: var(--triarch-cta-hover);
}
.ta-upload-dropzone__text {
    font-family: var(--triarch-font-display);
    font-size: 13px;
    font-weight: 600;
    color: var(--triarch-text);
}
.ta-upload-dropzone__hint {
    font-size: 11.5px;
    font-style: italic;
}
.ta-upload-dropzone__file {
    display: flex;
    align-items: center;
    min-width: 0;
    padding: 8px 10px;
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-xs);
    background: var(--triarch-surface-soft);
    font-size: 12.5px;
}
.ta-doc-title-menu {
    max-height: 260px;
    overflow-y: auto;
}

/* Project metadata card — shown under the project select on the storefront
   apply wizard once a project is picked (number, jurisdiction, address,
   building-attribute chips). */
.ta-project-meta {
    margin-top: 10px;
    padding: 10px 12px;
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-sm);
    background: var(--triarch-surface-soft);
}
.ta-project-meta__head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 6px;
}
.ta-project-meta__jurisdiction {
    font-size: 12px;
    font-weight: 600;
    color: var(--triarch-text);
}
.ta-project-meta__link {
    text-decoration: none;
    cursor: pointer;
}
.ta-project-meta__link:hover,
.ta-project-meta__link:focus-visible {
    text-decoration: underline;
    filter: brightness(0.92);
}
.ta-project-meta__link i {
    font-size: 9.5px;
    opacity: 0.7;
}
.ta-project-meta__row {
    display: flex;
    align-items: baseline;
    gap: 6px;
    font-size: 12.5px;
    color: var(--triarch-text-soft);
    line-height: 1.4;
}
.ta-project-meta__row i {
    font-size: 11px;
    opacity: 0.65;
}
.ta-project-meta__chips {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
}
.ta-project-meta__chip {
    font-size: 10.5px;
    font-weight: 600;
    color: var(--triarch-text-soft);
    background: var(--triarch-surface);
    border: 1px solid var(--triarch-border);
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    letter-spacing: 0.02em;
    white-space: nowrap;
}
.ta-project-meta__files {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px dashed var(--triarch-border);
}
.ta-project-meta__files-head {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--triarch-text-soft);
    margin-bottom: 4px;
}
.ta-project-meta__files-list {
    margin: 0;
    padding-left: 18px;
    font-size: 12.5px;
    color: var(--triarch-text);
    line-height: 1.6;
}
.ta-project-meta__file i {
    font-size: 10.5px;
    opacity: 0.6;
    margin-right: 2px;
}

/* Full-page busy overlay with message — shown during the apply wizard's
   SaveDraft server round-trip (draft save + intake-fee resolution). Plays the
   same blocking role as abp.ui.setBusy() but carries an explanatory text. */
.ta-busy-overlay {
    position: fixed;
    inset: 0;
    z-index: 1090;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(16, 24, 32, 0.35);
}
.ta-busy-overlay__card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 22px;
    background: var(--triarch-surface, #fff);
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-sm);
    box-shadow: 0 12px 32px rgba(16, 24, 32, 0.18);
}
.ta-busy-overlay__card i {
    font-size: 16px;
    color: var(--triarch-cta-hover);
}
.ta-busy-overlay__text {
    font-family: var(--triarch-font-display);
    font-size: 13.5px;
    font-weight: 600;
    color: var(--triarch-text);
}

/* Mobile: AJAX offcanvas panels (upload document, add contact …) take the
   full viewport width instead of Bootstrap's fixed 400px, and the busy
   overlay card never exceeds the screen. */
@media (max-width: 575.98px) {
    .ta-offcanvas-panel.offcanvas-end,
    .ta-offcanvas-panel.offcanvas-start {
        width: 100vw;
    }

    .ta-busy-overlay__card {
        max-width: calc(100vw - 32px);
        margin: 0 16px;
    }
}

/* Help callout eyebrow — type from .t-label (§3); spacing only here */
.ta-help-callout__eyebrow {
    margin: 0 0 6px 0;
}
.ta-help-callout__lead {
    margin: 0 0 14px 0;
    font-size: 13px;
    color: var(--triarch-text);
}

/* Step list — reused inside the offcanvas body */
.ta-help-callout__steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.ta-help-callout__step {
    padding: 8px 12px;
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-xs);
    background: var(--triarch-surface-soft);
}
.ta-help-callout__step-title {
    font-weight: 600;
    color: var(--triarch-cta-hover);
    margin-bottom: 2px;
    font-size: 13px;
}
.ta-help-callout__step-body {
    color: var(--triarch-text-soft);
    font-size: 12px;
    line-height: 1.5;
}
.ta-help-callout__footer {
    margin: 12px 0 0 0;
    padding-top: 10px;
    border-top: 1px solid var(--triarch-border);
    color: var(--triarch-text-soft);
    font-size: 12px;
    font-style: italic;
}

/* Empty state — shown when Model.Activities has zero items */
.ta-activity-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: 18px 12px;
    border: 1px dashed var(--triarch-border);
    border-radius: var(--radius-sm);
    color: var(--triarch-text-soft);
    font-size: 12.5px;
    font-style: italic;
}
.ta-activity-empty i {
    opacity: 0.55;
    font-size: 14px;
}

/* Inline "add activity" dropzone — sits at the end of the list */
.ta-activity-dropzone {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    width: 100%;
    padding: 14px 12px;
    border: 1px dashed var(--triarch-outline);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--triarch-cta-hover);
    font-family: var(--triarch-font-display);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: var(--transition-color);
}
.ta-activity-dropzone:hover,
.ta-activity-dropzone:focus {
    background: var(--triarch-cta-tint);
    border-color: var(--triarch-cta-outline);
    border-style: solid;
    outline: none;
}
.ta-activity-dropzone__hint {
    font-family: var(--triarch-font-body);
    font-size: 11.5px;
    font-weight: 400;
    color: var(--triarch-text-soft);
    font-style: italic;
}

/* "Suggested next" quick-add chip row */
.ta-activity-suggested {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px dashed var(--triarch-border);
}
.ta-activity-suggested__label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--triarch-text-soft);
    margin-right: var(--space-2);
}
.ta-activity-suggested__chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 12px;
    border-radius: var(--radius-pill);
    background: var(--triarch-surface);
    color: var(--triarch-text);
    border: 1px solid var(--triarch-border);
    cursor: pointer;
    font-size: 12px;
    font-weight: 500;
    line-height: 1.3;
    transition: var(--transition-color);
}
.ta-activity-suggested__chip:hover,
.ta-activity-suggested__chip:focus {
    background: var(--triarch-cta-tint);
    border-color: var(--triarch-cta-outline);
    color: var(--triarch-cta-hover);
    outline: none;
}
.ta-activity-suggested__chip i {
    font-size: 9px;
    opacity: 0.7;
}

/* ── Busy overlay message (taBusy.js → abp.ui.setBusy + data-text) ────
   The stock abp.css busy overlay renders attr(data-text) via :after,
   styled as a short uppercase label inside the spinner ring. ControlRoom
   busy messages are full sentences ("Submitting your service request —
   please don't navigate away…"), so restyle: theme font, sentence case,
   placed just below the ring. The dark scope fixes the hardcoded white
   overlay background from abp.css. */
.abp-block-area.abp-block-area-busy::after {
    /* min() clamps to the viewport: hosts taller than the screen (dashboards)
       get a viewport-centered message instead of one below the fold, short
       hosts keep element-centering. Same clamp on the spinner below. */
    top: min(calc(50% + 92px), calc(50vh + 92px));
    transform: translateX(-50%);
    max-width: 420px;
    width: max-content;
    font-family: var(--triarch-font-display);
    font-size: 13.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
    text-transform: none;
    color: var(--triarch-text, #343a40);
}

.abp-block-area.abp-block-area-busy::before {
    top: min(calc(50% - 75px), calc(50vh - 75px));
}

.lpx-theme-dark .abp-block-area {
    background-color: #10151f;
}

.lpx-theme-dark .abp-block-area.abp-block-area-busy::after {
    color: #cdd6e3;
}

/* ── Plan Review stage loading overlay (server-rendered → painted at first paint) ──────────
   Shared by every Plan Review stage so Review / Report / Verify behave identically:
     • Report  → #ta-report-loading      (_Report.cshtml / Report/Index.cshtml)
     • Review  → #ta-doc-review-loading   (_Review.cshtml)
     • Verify  → #ta-doc-review-loading   (_Review.cshtml, final-report mode)
   Baked into the stage markup so the busy state is on screen the instant the page paints — no
   dependence on JS timing. Covers the editor / PDF-viewer area while ej2 + the Syncfusion control
   build and the document streams in; the stage script (Report/Index.js, DocumentReview/Index.js)
   removes the node once the document is open. Closes the bare-shell flash measured between a stage
   page's first paint and its DOM-ready script (~200ms). The spinner uses a transform animation
   (compositor-driven) so it keeps spinning even during the control's synchronous build. */
/* Deliberately a pixel match of abp's busy overlay (.abp-block-area.abp-block-area-busy +
   the theme overrides above) so the server-rendered landing loader and the client-side
   taBusy/abp loader used for clicks and Save & Next look IDENTICAL — same fixed full-viewport
   dim, same 150px #228ae6 ring at the same coordinates, same message styling. Otherwise the
   loader visibly swaps style mid-transition (server on landing, client on click). */
.ta-stage-loading {
    position: fixed;
    inset: 0;
    z-index: 102;
    background-color: #fff;
    opacity: 0.8;
}

.lpx-theme-dark .ta-stage-loading {
    background-color: #10151f;
}

.ta-stage-loading__spinner {
    position: absolute;
    top: min(calc(50% - 75px), calc(50vh - 75px));
    left: calc(50% - 75px);
    width: 150px;
    height: 150px;
    border-radius: 50%;
    border: 2px solid;
    border-color: transparent #228ae6 #228ae6 #228ae6;
    will-change: transform;
    animation: ta-stage-loading-spin 0.75s infinite ease-in-out;
}

.ta-stage-loading__text {
    position: absolute;
    top: min(calc(50% + 92px), calc(50vh + 92px));
    left: 50%;
    transform: translateX(-50%);
    max-width: 420px;
    width: max-content;
    font-family: var(--triarch-font-display);
    font-size: 13.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
    text-align: center;
    color: var(--triarch-text, #343a40);
}

.lpx-theme-dark .ta-stage-loading__text {
    color: #cdd6e3;
}

@keyframes ta-stage-loading-spin {
    0% {
        transform: translateZ(0) rotate(0deg);
    }

    100% {
        transform: translateZ(0) rotate(360deg);
    }
}

/* ── Info pages (About / Support) ────────────────────────────────────────────
   Standalone empty-layout pages reached from the LeptonX footer (About, Support),
   matching the Privacy/Terms pattern. Hero + card scaffolding built only from
   --triarch-* tokens so it tracks the active theme (light / dim / dark); fallbacks
   cover the rare case where a non-:root token is unresolved. Icons use the
   Font Awesome glyphs already loaded by LeptonX (same as the .ta-btn-back arrow). */
.ta-info-page {
    max-width: 960px;
    padding-bottom: var(--space-16, 64px);
    color: var(--triarch-text, #171c1f);
}

.ta-info-hero {
    padding: var(--space-6, 24px) 0 var(--space-4, 16px);
}
.ta-info-eyebrow {
    display: inline-block;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--triarch-primary, #9d4300);
    margin-bottom: var(--space-3, 12px);
}
.ta-info-title {
    font-family: var(--triarch-font-display, "Space Grotesk", sans-serif);
    font-weight: 700;
    font-size: clamp(2rem, 4vw, 2.75rem);
    color: var(--triarch-text, #171c1f);
    margin: 0 0 var(--space-4, 16px);
}
.ta-info-lead {
    max-width: 640px;
    font-size: 1.125rem;
    font-weight: 300;
    line-height: 1.6;
    color: var(--triarch-text-soft, #57657a);
    margin: 0;
}

/* Section rhythm */
.ta-info-section {
    margin-top: var(--space-16, 64px);
}
.ta-info-h2 {
    font-family: var(--triarch-font-display, "Space Grotesk", sans-serif);
    font-weight: 700;
    font-size: clamp(1.4rem, 2.4vw, 1.85rem);
    color: var(--triarch-text, #171c1f);
    margin-bottom: var(--space-3, 12px);
}
.ta-info-section-lead {
    max-width: 620px;
    font-weight: 300;
    color: var(--triarch-text-soft, #57657a);
    margin-bottom: var(--space-8, 32px);
}

/* Feature / mission card */
.ta-info-card {
    background: var(--triarch-surface, #ffffff);
    border: 1px solid var(--triarch-border, #eaeef2);
    border-radius: var(--radius-lg, 14px);
    padding: var(--space-8, 32px);
    transition: var(--transition-shadow), border-color var(--duration-fast, 150ms) var(--ease-standard);
}
.ta-info-card:hover {
    border-color: var(--triarch-primary-dim, #ffb690);
    box-shadow: 0 10px 30px -18px rgba(17, 28, 31, 0.35);
}
.ta-info-card__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-md, 10px);
    background: var(--triarch-primary-tint, #ffdbca);
    color: var(--triarch-primary, #9d4300);
    font-size: 18px;
    margin-bottom: var(--space-4, 16px);
}
.ta-info-card__title {
    font-family: var(--triarch-font-display, "Space Grotesk", sans-serif);
    font-weight: 600;
    font-size: 1.25rem;
    color: var(--triarch-text, #171c1f);
    margin-bottom: var(--space-3, 12px);
}
.ta-info-card__body {
    color: var(--triarch-text-soft, #57657a);
    line-height: 1.6;
}

/* Leadership card */
.ta-info-person {
    display: flex;
    gap: var(--space-5, 20px);
    align-items: flex-start;
    background: var(--triarch-surface, #ffffff);
    border: 1px solid var(--triarch-border, #eaeef2);
    border-radius: var(--radius-lg, 14px);
    padding: var(--space-6, 24px);
}
.ta-info-person__avatar {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    border: 2px solid var(--triarch-border, #eaeef2);
}
.ta-info-person__name {
    font-family: var(--triarch-font-display, "Space Grotesk", sans-serif);
    font-weight: 600;
    font-size: 1.15rem;
    margin: 0 0 2px;
    color: var(--triarch-text, #171c1f);
}
.ta-info-person__role {
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--triarch-primary, #9d4300);
    margin: 0 0 var(--space-3, 12px);
}
.ta-info-person__bio {
    font-size: 0.925rem;
    line-height: 1.55;
    color: var(--triarch-text-soft, #57657a);
}

/* Support topic tile */
.ta-info-topic {
    background: var(--triarch-surface, #ffffff);
    border: 1px solid var(--triarch-border, #eaeef2);
    border-radius: var(--radius-md, 10px);
    padding: var(--space-6, 24px);
    transition: var(--transition-shadow), border-color var(--duration-fast, 150ms) var(--ease-standard);
}
.ta-info-topic:hover {
    border-color: var(--triarch-primary-dim, #ffb690);
    box-shadow: 0 8px 24px -18px rgba(17, 28, 31, 0.3);
}
.ta-info-topic__icon {
    color: var(--triarch-primary, #9d4300);
    font-size: 18px;
}
.ta-info-topic__title {
    font-family: var(--triarch-font-display, "Space Grotesk", sans-serif);
    font-weight: 600;
    font-size: 1.05rem;
    margin: var(--space-3, 12px) 0 var(--space-2, 8px);
    color: var(--triarch-text, #171c1f);
}
.ta-info-topic__body {
    font-size: 0.9rem;
    color: var(--triarch-text-soft, #57657a);
    line-height: 1.5;
}

/* Pull-quote */
.ta-info-quote {
    margin: var(--space-16, 64px) auto 0;
    max-width: 760px;
    border-left: 3px solid var(--triarch-accent, #f97316);
    padding: var(--space-2, 8px) var(--space-6, 24px);
    font-family: var(--triarch-font-display, "Space Grotesk", sans-serif);
    font-style: italic;
    font-size: 1.2rem;
    line-height: 1.5;
    color: var(--triarch-text, #171c1f);
}

/* Contact band */
.ta-info-contact {
    margin-top: var(--space-16, 64px);
    background: var(--triarch-surface-soft, #f0f4f8);
    border: 1px solid var(--triarch-border, #eaeef2);
    border-radius: var(--radius-xl, 20px);
    padding: var(--space-12, 48px) var(--space-6, 24px);
}

/* Resource links (Support) */
.ta-info-links {
    list-style: none;
    margin: 0 auto;
    padding: 0;
    max-width: 640px;
}
.ta-info-links li {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--space-4, 16px) 0;
    border-bottom: 1px solid var(--triarch-border, #eaeef2);
}
.ta-info-links li:last-child { border-bottom: 0; }
.ta-info-links a {
    font-weight: 600;
    color: var(--triarch-primary, #9d4300);
    text-decoration: none;
}
.ta-info-links a:hover { color: var(--triarch-accent, #f97316); }
.ta-info-links a i { margin-right: var(--space-2, 8px); }
.ta-info-links span {
    font-size: 0.9rem;
    color: var(--triarch-text-soft, #57657a);
}

/* ── Release notes (/release-notes, TriArchV5.Web/Pages/ReleaseNotes.cshtml) ──
   Release list (.ta-relnotes-nav, sticky) beside one release (.ta-relnote); the others
   carry [hidden] and wwwroot/js/release-notes.js switches them in place. Below lg the
   list gives way to a picker. The body is Markdown rendered server-side (## sections
   arrive as <h3>, feature headings as <p><strong>). Notices use .ta-note; uppercase
   labels use .t-label. The footer version (portal + AuthServer) links here as
   .ta-footer-version. */
.lpx-footbar .ta-footer-version {
    color: var(--triarch-text-soft);
    text-decoration: none;
}
.lpx-footbar .ta-footer-version:hover,
.lpx-footbar .ta-footer-version:focus-visible {
    color: var(--triarch-link);
    text-decoration: underline;
}

.ta-info-page.ta-relnotes-page { max-width: 1180px; }

.ta-relnotes {
    display: grid;
    grid-template-columns: 260px minmax(0, 1fr);
    gap: var(--space-8);
    align-items: start;
    margin-top: var(--space-8);
}

/* Release list */
.ta-relnotes-nav {
    position: sticky;
    top: var(--space-6);
    max-height: calc(100vh - 140px);
    overflow-y: auto;
}
.ta-relnotes-nav__picker { display: none; }
.ta-relnotes-nav__title {
    margin: 0 0 var(--space-3);
    padding-left: var(--space-3);
}
.ta-relnotes-nav__year {
    font-size: 13px;
    font-weight: 600;
    color: var(--triarch-text-soft);
    margin: var(--space-4) 0 var(--space-1);
    padding-left: var(--space-3);
}
.ta-relnotes-nav ul {
    list-style: none;
    margin: 0;
    padding: 0;
}
.ta-relnotes-nav__pending { margin-bottom: var(--space-2); }
.ta-relnotes-nav__item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--space-2) var(--space-3);
    border-left: 3px solid transparent;
    border-radius: var(--radius-md);
    color: var(--triarch-text);
    text-decoration: none;
}
.ta-relnotes-nav__item:hover {
    background: var(--triarch-surface-soft);
    color: var(--triarch-text);
}
.ta-relnotes-nav__item.is-active {
    background: var(--triarch-action-tint);
    border-left-color: var(--triarch-action);
}
.ta-relnotes-nav__item:focus-visible {
    outline: 2px solid var(--triarch-action);
    outline-offset: 1px;
}
.ta-relnotes-nav__line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}
.ta-relnotes-nav__date { font-weight: 600; }
.ta-relnotes-nav__counts {
    font-size: 12px;
    color: var(--triarch-text-soft);
}

/* One release */
.ta-relnote {
    background: var(--triarch-surface);
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-lg);
    scroll-margin-top: 96px;
}
.ta-relnote[hidden] { display: none; }
.ta-relnote__head {
    padding: var(--space-6) var(--space-6) var(--space-4);
    border-bottom: 1px solid var(--triarch-border);
}
.ta-relnote__date {
    font-family: var(--triarch-font-display);
    font-weight: 700;
    font-size: 24px;
    color: var(--triarch-text);
    margin: 0 0 var(--space-2);
}
/* Older/Newer moves focus here (tabindex -1) so keyboard users land on the release they opened. */
.ta-relnote__date:focus-visible {
    outline: 2px solid var(--triarch-action);
    outline-offset: 4px;
    border-radius: var(--radius-md);
}
.ta-relnote__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}
.ta-relnote__version {
    font-size: 13px;
    color: var(--triarch-text-soft);
    font-variant-numeric: tabular-nums;
}
.ta-relnote__summary {
    margin: var(--space-3) 0 0;
    color: var(--triarch-text-soft);
}

/* The running build when it has no notes yet (staging awaiting promotion, .dev, notes unreadable) */
.ta-relnote--pending { border-style: dashed; }
.ta-relnote__pending-message {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    margin: var(--space-4) 0 var(--space-3);
    color: var(--triarch-text);
}
.ta-relnote__pending-message i {
    margin-top: 4px;
    color: var(--triarch-action);
}

.ta-relnote__body {
    padding: var(--space-2) var(--space-6) var(--space-6);
    color: var(--triarch-text-soft);
    line-height: 1.6;
    overflow-wrap: anywhere;
}
.ta-relnote__body h3 {
    font-family: var(--triarch-font-display);
    font-weight: 700;
    font-size: 18px;
    color: var(--triarch-text);
    margin: var(--space-6) 0 var(--space-3);
}
.ta-relnote__body h4 {
    font-weight: 600;
    font-size: 15px;
    color: var(--triarch-text);
    margin: var(--space-4) 0 var(--space-2);
}
.ta-relnote__body p { margin: 0 0 var(--space-3); }
.ta-relnote__body strong { color: var(--triarch-text); }
.ta-relnote__body ul,
.ta-relnote__body ol {
    margin: 0 0 var(--space-3);
    padding-left: var(--space-6);
}
.ta-relnote__body li + li { margin-top: var(--space-1); }
.ta-relnote__body a { color: var(--triarch-link); }
.ta-relnote__body table {
    width: 100%;
    margin: 0 0 var(--space-3);
    border-collapse: collapse;
    font-size: 14px;
}
.ta-relnote__body th,
.ta-relnote__body td {
    padding: var(--space-2);
    border-bottom: 1px solid var(--triarch-border);
    text-align: left;
}

/* Older / Newer */
.ta-relnote__pager {
    display: flex;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-6);
    border-top: 1px solid var(--triarch-border);
}
.ta-relnote__pager-link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    color: var(--triarch-text);
    text-decoration: none;
}
.ta-relnote__pager-link:hover {
    background: var(--triarch-surface-soft);
    color: var(--triarch-text);
}
.ta-relnote__pager-link i { color: var(--triarch-action); }
.ta-relnote__pager-link--newer {
    margin-left: auto;
    text-align: right;
}
.ta-relnote__pager-label,
.ta-relnote__pager-date { display: block; }
.ta-relnote__pager-date { font-weight: 600; }

@media (max-width: 991.98px) {
    .ta-relnotes {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--space-4);
    }
    .ta-relnotes-nav {
        position: static;
        max-height: none;
        overflow: visible;
    }
    .ta-relnotes-nav__list { display: none; }
    .ta-relnotes-nav__picker { display: block; }
}

@media (max-width: 575.98px) {
    .ta-relnote__head { padding: var(--space-4); }
    .ta-relnote__body { padding: var(--space-2) var(--space-4) var(--space-4); }
    .ta-relnote__pager { padding: var(--space-3) var(--space-4); }
}

/* ===== Support page — ticket workspace (SPA: list / create / detail) =====
   Markup in TriArchV5.Web/Pages/Support.cshtml; behaviour in
   wwwroot/js/support-page.js. Status colours reuse the shared
   .ta-pill--info / --warn / --success pills. */
.ta-support { text-align: left; }

.ta-support__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3, 12px);
    flex-wrap: wrap;
    margin-bottom: var(--space-4, 16px);
}

.ta-support__count {
    display: inline-block;
    margin-left: 10px;
    font-size: .8rem;
    font-weight: 600;
    color: var(--triarch-text-soft, #57657a);
    background: var(--triarch-surface-soft, #eef1f5);
    border-radius: 999px;
    padding: 2px 11px;
    vertical-align: middle;
}

/* Filter chips */
.ta-support__filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.ta-support__filter {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border: 1px solid var(--triarch-border, #eaeef2);
    background: transparent;
    color: var(--triarch-text-soft, #57657a);
    border-radius: 999px;
    padding: 5px 14px;
    font-size: .85rem;
    font-weight: 600;
    transition: color .15s ease, border-color .15s ease, background-color .15s ease;
}
.ta-support__filter:hover { color: var(--triarch-text, inherit); border-color: var(--triarch-cta, #b8442a); }
.ta-support__filter.is-active { background: var(--triarch-cta, #b8442a); border-color: var(--triarch-cta, #b8442a); color: var(--triarch-on-action, #ffffff); }
.ta-support__filter-c {
    font-size: .72rem;
    line-height: 1;
    padding: 3px 7px;
    border-radius: 999px;
    background: var(--triarch-surface-soft, #eef1f5);
    color: var(--triarch-text-soft, #57657a);
    min-width: 20px;
    text-align: center;
}
.ta-support__filter.is-active .ta-support__filter-c { background: rgba(255, 255, 255, .22); color: #fff; }

/* Loading skeletons */
.ta-support__skeletons { display: flex; flex-direction: column; gap: 10px; }
.ta-support__skeleton {
    height: 68px;
    border-radius: var(--radius-lg, 14px);
    background: linear-gradient(90deg,
        var(--triarch-surface-soft, #eef1f5) 25%,
        var(--triarch-border, #e3e8ee) 37%,
        var(--triarch-surface-soft, #eef1f5) 63%);
    background-size: 400% 100%;
    animation: ta-support-shimmer 1.4s ease infinite;
}
@keyframes ta-support-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }

.ta-support__list { display: flex; flex-direction: column; gap: 10px; }

.ta-support__row {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 13px 16px;
    border: 1px solid var(--triarch-border, #eaeef2);
    border-radius: var(--radius-lg, 14px);
    background: var(--triarch-surface, #fff);
    cursor: pointer;
    transition: transform .12s ease, border-color .15s ease, box-shadow .15s ease;
}
.ta-support__row:hover,
.ta-support__row:focus-visible {
    border-color: var(--triarch-cta, #b8442a);
    transform: translateY(-1px);
    box-shadow: 0 6px 18px rgba(18, 24, 33, .07);
    outline: none;
}

.ta-support__icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: 11px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 15px;
    background: var(--triarch-surface-soft, #eef1f5);
    color: var(--triarch-cta, #b8442a);
}

.ta-support__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ta-support__title {
    font-weight: 600;
    color: var(--triarch-text, #171c1f);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ta-support__meta-line {
    display: flex;
    align-items: center;
    gap: 7px;
    flex-wrap: wrap;
    font-size: .8rem;
    color: var(--triarch-text-soft, #57657a);
}
.ta-support__rid { font-family: var(--bs-font-monospace, monospace); }
.ta-support__dot { opacity: .45; }
.ta-support__chev { color: var(--triarch-text-soft, #57657a); flex-shrink: 0; }

.ta-support__id {
    font-family: var(--bs-font-monospace, monospace);
    font-size: .78rem;
    color: var(--triarch-text-soft, #57657a);
}

/* Pager */
.ta-support__pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 16px;
}
.ta-support__pager-info { font-size: .82rem; color: var(--triarch-text-soft, #57657a); }
.ta-support__none { text-align: center; color: var(--triarch-text-soft, #57657a); padding: 1.75rem 1rem; }

.lpx-theme-dark .ta-support__icon,
.lpx-theme-dim .ta-support__icon { color: var(--triarch-accent, #f97316); }
.lpx-theme-dark .ta-support__row:hover,
.lpx-theme-dim .ta-support__row:hover { box-shadow: 0 6px 18px rgba(0, 0, 0, .3); }

/* Guided-tour icon, above "Report an issue" in the same cluster. Rendered hidden; ta-tour.js shows it
   only on pages (or open panels) that have a tour. */
#lpx-settings .ta-tour-setting { cursor: pointer; }
#lpx-settings .ta-tour-setting:hover .setting,
#lpx-settings .ta-tour-setting:focus-visible .setting { color: var(--triarch-cta, #e8734d); }
#lpx-settings .ta-tour-setting:focus-visible { outline: 2px solid var(--triarch-focus); outline-offset: 2px; border-radius: var(--radius-sm, 6px); }

/* "Report an issue" icon injected into the LeptonX bottom settings cluster (GeneralSettings override). */
#lpx-settings .ta-report-setting { cursor: pointer; }
#lpx-settings .ta-report-setting:hover .setting,
#lpx-settings .ta-report-setting:focus-visible .setting { color: var(--triarch-cta, #e8734d); }

/* Subtle "crawl": the bug rests, then does a brief wiggle/scuttle every few seconds. Livelier on hover. */
#lpx-settings .ta-report-setting .setting i {
    display: inline-block;
    transform-origin: 50% 70%;
    animation: ta-bug-crawl 3.6s ease-in-out infinite;
}
#lpx-settings .ta-report-setting:hover .setting i { animation-duration: .7s; }
@keyframes ta-bug-crawl {
    0%, 68%, 100% { transform: rotate(0deg) translateX(0); }
    73% { transform: rotate(-8deg) translateX(-1px); }
    79% { transform: rotate(7deg) translateX(1px); }
    85% { transform: rotate(-5deg) translateX(-.5px); }
    91% { transform: rotate(4deg) translateX(.5px); }
}
@media (prefers-reduced-motion: reduce) {
    #lpx-settings .ta-report-setting .setting i { animation: none; }
}

.ta-support__empty,
.ta-support__signin {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 2.5rem 1.5rem;
    color: var(--triarch-text-soft, #57657a);
}
.ta-support__empty-icon {
    width: 64px;
    height: 64px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--triarch-cta-tint, #fbe4dc);
    color: var(--triarch-cta, #b8442a);
    font-size: 26px;
    margin-bottom: 1rem;
}
.ta-support__empty-title {
    font-family: var(--triarch-font-display, inherit);
    font-weight: 700;
    color: var(--triarch-text, inherit);
    margin-bottom: .35rem;
}
.ta-support__empty-body { max-width: 36ch; margin: 0; }

.ta-support__back {
    border: 0;
    background: transparent;
    padding: 0;
    color: var(--triarch-cta, #b8442a);
    font-weight: 600;
    margin-bottom: var(--space-3, 12px);
}
.ta-support__back:hover { color: var(--triarch-cta-hover, #9a3519); }

.ta-support__card {
    background: var(--triarch-surface, #fff);
    border: 1px solid var(--triarch-border, #eaeef2);
    border-radius: var(--radius-lg, 14px);
    padding: var(--space-5, 24px);
}

.ta-support__detail-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3, 12px);
    margin-bottom: var(--space-4, 16px);
}
.ta-support__detail-title {
    font-family: var(--triarch-font-display, inherit);
    font-size: 1.25rem;
    font-weight: 700;
    margin: 4px 0 0;
    color: var(--triarch-text, inherit);
}

.ta-support__timeline { display: flex; align-items: center; gap: 8px; margin: 0 0 var(--space-4, 16px); }
.ta-support__step {
    font-size: .78rem;
    padding: 3px 10px;
    border-radius: 20px;
    background: var(--triarch-surface-soft, #eef1f5);
    color: var(--triarch-text-soft, #57657a);
    white-space: nowrap;
}
.ta-support__step.is-active {
    background: var(--triarch-cta-tint, #fbe4dc);
    color: var(--triarch-cta, #b8442a);
    font-weight: 600;
}
.ta-support__step-sep { flex: 1 1 auto; height: 2px; background: var(--triarch-border, #eaeef2); min-width: 16px; }

.ta-support__meta-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 10px;
    margin-bottom: var(--space-4, 16px);
}
.ta-support__meta { background: var(--triarch-surface-soft, #eef1f5); border-radius: var(--radius-md, 10px); padding: 10px 12px; }
.ta-support__meta-k { font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; color: var(--triarch-text-soft, #57657a); }
.ta-support__meta-v { font-weight: 600; color: var(--triarch-text, inherit); word-break: break-word; }

.ta-support__h4 { font-family: var(--triarch-font-display, inherit); font-size: 1rem; font-weight: 700; margin: 0 0 .5rem; }
.ta-support__desc { line-height: 1.6; color: var(--triarch-text, inherit); word-break: break-word; }
.ta-support__desc hr { border: 0; border-top: 1px solid var(--triarch-border, #eaeef2); margin: .75rem 0; }

.ta-support__atts { display: flex; flex-wrap: wrap; gap: 8px; }
.ta-support__att {
    display: inline-flex;
    align-items: center;
    padding: 6px 10px;
    border-radius: var(--radius-md, 10px);
    border: 1px solid var(--triarch-border, #eaeef2);
    background: var(--triarch-surface, #fff);
    color: var(--triarch-cta, #b8442a);
    text-decoration: none;
    font-size: .85rem;
}
.ta-support__att:hover { border-color: var(--triarch-cta, #b8442a); }

.lpx-theme-dark .ta-support__empty-icon,
.lpx-theme-dim .ta-support__empty-icon { color: var(--triarch-accent, #f97316); }

/* ── Required field indicator (global) ─────────────────────────────────
   Pattern A — ABP tag helpers (abp-input / abp-select):
     <label class="form-label">Name <span> *</span></label>
   Pattern B — Inline marker when label has hints or JS toggles visibility:
     <span class="ta-req-asterisk"> *</span>
   Pattern C — Dynamic / group labels (radio, checkbox):
     <label class="form-label ta-required-label">Question</label>
   Pattern D — Custom control, label is immediate sibling of required field:
     <label for="X">...</label><select required> */
label.form-label > span:last-child {
    color: var(--bs-danger, #dc3545);
}

label.form-label .ta-req-asterisk {
    color: var(--bs-danger, #dc3545);
}

label.form-label.ta-required-label::after {
    content: " *";
    color: var(--bs-danger, #dc3545);
}

label.form-label:has(+ select[required])::after,
label.form-label:has(+ input[required])::after,
label.form-label:has(+ textarea[required])::after {
    content: " *";
    color: var(--bs-danger, #dc3545);
}

/* ── Inline note / callout ────────────────────────────────────────────
   Replacement for Bootstrap `.alert-info` / `.alert-warning` inside TriArch
   surfaces. Those pull --bs-info-bg-subtle / --bs-warning-bg-subtle, which are
   fixed light-mode cyans and ambers: they survive the LeptonX dark switch
   unchanged and read as an off-brand patch. This composes from --triarch-*
   tokens so both themes track the surface.

   .ta-note            neutral — background context
   .ta-note--info      explanatory, nothing to do
   .ta-note--action    something is blocked until the user acts */
.ta-note {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: 0.625rem 0.875rem;
    border-radius: var(--radius-sm);
    border: 1px solid var(--triarch-border);
    background: var(--triarch-surface-soft);
    color: var(--triarch-text-soft);
    font-size: 13px;
    line-height: 1.45;
}
.ta-note__icon {
    flex-shrink: 0;
    margin-top: 1px;
    opacity: 0.8;
}
.ta-note--info {
    border-color: color-mix(in srgb, var(--triarch-info) 32%, transparent);
    background: color-mix(in srgb, var(--triarch-info) 8%, var(--triarch-surface));
}
.ta-note--info .ta-note__icon { color: var(--triarch-info); opacity: 1; }
.ta-note--success {
    border-color: color-mix(in srgb, var(--triarch-success) 32%, transparent);
    background: color-mix(in srgb, var(--triarch-success) 8%, var(--triarch-surface));
}
.ta-note--success .ta-note__icon { color: var(--triarch-success); opacity: 1; }
/* Warning tone — needs attention, expiring, in review. Tones follow the state colours
   (docs/ui-standard.md §7). --action is the older name for the same tone and stays as an alias. */
.ta-note--warning,
.ta-note--action {
    border-color: color-mix(in srgb, var(--triarch-warning-fg) 32%, transparent);
    background: color-mix(in srgb, var(--triarch-warning-fg) 8%, var(--triarch-surface));
}
.ta-note--warning .ta-note__icon,
.ta-note--action .ta-note__icon { color: var(--triarch-warning-fg); opacity: 1; }
/* Danger tone — a rule the user is about to break, not merely something to notice. Added for the
   BuildRoom Approval surface's bonded-margin-floor breach; --info and --action were both too soft for a
   guardrail an approver must consciously override. */
.ta-note--danger {
    border-color: color-mix(in srgb, var(--triarch-danger) 34%, transparent);
    background: color-mix(in srgb, var(--triarch-danger) 8%, var(--triarch-surface));
}
.ta-note--danger .ta-note__icon { color: var(--triarch-danger); opacity: 1; }
/* A note carrying a heading rather than a single line of text. */
.ta-note__title {
    font-weight: 700;
    font-size: 0.82rem;
    line-height: 1.35;
    margin-bottom: 2px;
    color: var(--triarch-text);
}
.ta-note--danger .ta-note__title { color: var(--triarch-danger); }
.ta-note--action .ta-note__title { color: var(--status-action-required); }

/* Note: .ta-stat-card--hug / --depleted were added here for the Review credits settings
   widget and removed again when that widget moved to ABP's flat settings-page markup
   (plain <h4> + form-label + form-text, inheriting the LeptonX type scale). Left as a
   comment only so the same tile is not re-derived: .ta-stat-card--compact assumes a
   narrow grid column — its .ta-stat__value { margin-left: auto } strands the figure at
   the far edge of a full-width container, on top of .ta-stat__bg-icon. */

/* Embed host (BIM / iframe viewers). Child iframe uses height:100% — needs
   an explicit host height (Bootstrap vh-* utilities are not in this build). */
.ta-embed-host {
    position: relative;
    width: 100%;
    height: calc(100vh - 12rem);
    min-height: 28rem;
    background: var(--triarch-inverse-surface, #2c3134);
}

.ta-embed-host > iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
}

/* Reduced motion — respect OS preference */
@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;
    }
}

/* ===== BuildRoom — version badge as a control + Revision Notes trail =====
   Used by the LaunchPhase header (version badge) and RevisionNotesPanel.cshtml. Lives here rather than
   in launchPhase.css because .ta-pill--action extends the global .ta-pill primitive. */

/* Version badge rendered as a <button> (opens the Revision Notes offcanvas). A <button> carries UA chrome
   a <span> does not: an outset border, its own font stack and a default background. Reset ONLY those and
   let everything else keep coming from .ta-pill, so the badge stays pixel-identical to the pills beside
   it. In particular never use the `font` shorthand here — it also resets font-size/font-weight and the
   pill would render at body size. */
.ta-pill--action {
    font-family: inherit;
    border: 0;
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
}

/* Colour-only hover: .ta-pill has no border to tint, and changing the background would make the badge
   read as a different pill variant. */
.ta-pill--action:hover {
    color: var(--triarch-primary);
}

.ta-pill--action:focus-visible {
    outline: 2px solid var(--triarch-primary);
    outline-offset: 2px;
}

/* Revision trail — one entry per estimation version, newest first. */
.ta-revisions {
    list-style: none;
    margin: 0;
    padding: 0 0 0 1rem;
    border-left: 2px solid var(--triarch-border);
}

.ta-revisions__item {
    position: relative;
    padding-bottom: 1.35rem;
}

.ta-revisions__item:last-child {
    padding-bottom: 0;
}

/* The dot sits ON the rail, so it clears the 1rem padding plus half its own width. */
.ta-revisions__item::before {
    content: "";
    position: absolute;
    left: calc(-1rem - 5px);
    top: 0.35rem;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--triarch-border);
}

.ta-revisions__item.is-current::before {
    background: var(--triarch-primary);
}

.ta-revisions__head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}

.ta-revisions__tag {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--triarch-primary);
}

.ta-revisions__tag--muted {
    color: var(--triarch-text-soft);
}

.ta-revisions__stage {
    margin-left: auto;
    font-size: 0.72rem;
    color: var(--triarch-text-soft);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.ta-revisions__meta {
    font-size: 0.76rem;
    color: var(--triarch-text-soft);
    margin-top: 0.25rem;
    display: flex;
    gap: 0.3rem;
    flex-wrap: wrap;
}

.ta-revisions__none {
    font-size: 0.78rem;
    color: var(--triarch-text-soft);
    margin-top: 0.4rem;
    font-style: italic;
}

.ta-revisions__note {
    margin-top: 0.55rem;
    padding: 0.55rem 0.7rem;
    background: var(--triarch-surface-soft);
    border: 1px solid var(--triarch-border);
    border-radius: 0.45rem;
}

.ta-revisions__note-by {
    font-size: 0.78rem;
    font-weight: 600;
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
    align-items: baseline;
}

.ta-revisions__note-step,
.ta-revisions__note-when {
    font-weight: 400;
    color: var(--triarch-text-soft);
    font-size: 0.72rem;
}

.ta-revisions__note-when {
    margin-left: auto;
}

.ta-revisions__note-tx {
    font-size: 0.84rem;
    margin-top: 0.25rem;
    white-space: pre-wrap;
    line-height: 1.45;
}

/* ──────────────────────────────────────────────────────────────────────
   BuildRoom workspace — My Work / Estimates / Quotes & Awards.

   Only the two components the theme did not already have. Everything else on
   those screens uses the existing system: .ta-list-card, .ta-list-table,
   .ta-toolbar__*, .ta-chip, .ta-stat-card, .ta-name-cell, .ta-cell-link,
   .ta-sla--* for deadline urgency, and .ta-pill--* for trade and status.
   ────────────────────────────────────────────────────────────────────── */

/* Pipeline / signature progress — a compact inline bar for a table cell. The
   full-width stepper is .ta-phase-track; this is the miniature used in a grid. */
.ta-stage-bar {
    display: inline-flex;
    align-items: center;
    gap: 3px;
}
.ta-stage-bar__seg {
    width: 16px;
    height: 4px;
    border-radius: 2px;
    /* A step not reached yet. Mixed from the soft text colour so it shows on a dark surface as well as a
       light one: --triarch-surface-dim is 6% white in dark, and the empty steps disappeared. */
    background: color-mix(in srgb, var(--triarch-text-soft) 28%, transparent);
}
.ta-stage-bar__seg--on { background: var(--triarch-focus); }
.ta-stage-bar__pos {
    font-family: var(--triarch-font-mono);
    font-size: 10px;
    color: var(--triarch-text-soft);
    margin-left: 6px;
}
/* Empty state — the block form. .ta-empty is the inline muted note; this is the
   full-panel version for a list with nothing in it yet. */
.ta-empty-state {
    padding: 44px 32px;
    text-align: center;
}
.ta-empty-state__icon {
    font-size: 26px;
    color: var(--triarch-text-soft);
    margin-bottom: 14px;
}
.ta-empty-state__title {
    font-family: var(--triarch-font-display);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--triarch-text);
    margin: 0 0 8px;
}
.ta-empty-state__body {
    font-size: 12.5px;
    color: var(--triarch-text-soft);
    line-height: 1.6;
    max-width: 560px;
    margin: 0 auto 18px;
}
.ta-empty-state__actions {
    display: flex;
    gap: var(--space-2, 8px);
    justify-content: center;
    flex-wrap: wrap;
}

/* ============================================================================
   Labor drawers (BuildRoom M3.5)

   These live here, not in Pages/BuildRoom/Labor/labor.css, because the drawers
   that use them open from the Estimate work surface inside LaunchPhase - a page
   that never loads labor.css, so the readout rendered unstyled exactly where it
   is most used. Tokens only, so they follow .lpx-theme-dark.
   ============================================================================ */

/* The loaded rate is derived, never stored and never typed (invariant I6). Shown
   large and read-only so it reads as an answer, not an input to correct. */
.ta-loaded-readout {
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-md);
    background: var(--triarch-surface-soft);
    padding: var(--space-3) var(--space-4);
}

.ta-loaded-readout__label {
    letter-spacing: 0.12em;
    color: var(--triarch-text-soft);
}

.ta-loaded-readout__calc { margin-top: 0.15rem; color: var(--triarch-text-soft); }

.ta-loaded-readout__value {
    font-size: 26px;
    font-weight: 700;
    line-height: 1.15;
    color: var(--triarch-text);
    font-variant-numeric: tabular-nums;
}

.ta-loaded-readout__hint { margin-top: 0.1rem; color: var(--triarch-text-soft); }

/* ── ArchAI toolbar indexing badge ───────────────────────────────────────────
   Shown on the ArchAI trigger while the open Service Request has documents
   still being indexed, so a long background run is visible without opening the
   AI indexing panel. Deliberately NOT the alert red used by the notification
   bell — indexing in progress is information, not something wrong — and not the
   chat orange either, so the two counts stay distinguishable at a glance.
   Colour comes from --triarch-* brand tokens rather than a Bootstrap subtle
   token, which would drift off-theme in dark mode. */
#btn-code-advisor-panel .archai-indexing-count {
    z-index: 1;
    pointer-events: none;
    background-color: var(--triarch-accent, #6c5ce7);
    color: var(--triarch-on-action, #ffffff);
}

/* ── Offcanvas sizing (ta-offcanvas `size` attribute) ─────────────────────
   One place for panel widths. Each module used to pick its own width class,
   so "standard panel" meant 400px, 560px or 720px depending on where you
   looked; these classes are what CoreOffcanvasSize renders.

   Single-class selectors on purpose: they ship in the global bundle, which
   loads before page-level CSS, so a module stylesheet that sets
   --bs-offcanvas-width itself still wins and no existing panel moves.

   Standard is 560px because that is what Catalog and BuildRoom had already
   converged on by hand; Bootstrap's untouched 400px left forms cramped. */
.ta-oc-size-sm {
    --bs-offcanvas-width: 400px;
}

.ta-oc-size-md {
    --bs-offcanvas-width: 560px;
}

.ta-oc-size-lg {
    --bs-offcanvas-width: min(760px, max(560px, 60vw));
}

.ta-oc-size-full {
    --bs-offcanvas-width: 100vw;
}

/* Widened by the reader (ta-offcanvas-width.js). Paired with each size rather
   than written bare: a bare .ta-oc--widened beats every .ta-oc-size-* at equal
   specificity, so a Full panel would get NARROWER on widen. Full is absent on
   purpose — 100vw has nowhere to go. Panels are backdrop-less, so the page
   behind stays usable, hence the vw caps rather than "as wide as possible". */
.ta-oc-size-sm.ta-oc--widened,
.ta-oc-size-md.ta-oc--widened {
    --bs-offcanvas-width: min(760px, max(560px, 60vw));
}

.ta-oc-size-lg.ta-oc--widened {
    --bs-offcanvas-width: min(1040px, max(760px, 75vw));
}

.offcanvas.ta-oc-size-sm,
.offcanvas.ta-oc-size-md,
.offcanvas.ta-oc-size-lg {
    --bs-offcanvas-transition: transform 0.3s ease-in-out, width 0.2s ease;
}

/* Below lg the toggle is hidden, so a panel widened on a desktop must land back
   on ITS OWN width — not on a shared one. Pinning every widened panel to 560px
   left a widened Compact panel wider than it should be with no control to undo it. */
@media (max-width: 991.98px) {
    .ta-oc-size-sm.ta-oc--widened {
        --bs-offcanvas-width: 400px;
    }

    .ta-oc-size-md.ta-oc--widened {
        --bs-offcanvas-width: 560px;
    }

    .ta-oc-size-lg.ta-oc--widened {
        --bs-offcanvas-width: min(760px, max(560px, 60vw));
    }

    /* Safe to hide outright: ta-offcanvas-width.js never puts the row's auto margin on
       this button, so the close X keeps its place when it goes. */
    .js-ta-offcanvas-widen {
        display: none;
    }
}

@media (max-width: 767.98px) {
    .ta-oc-size-sm,
    .ta-oc-size-md,
    .ta-oc-size-lg,
    .ta-oc-size-sm.ta-oc--widened,
    .ta-oc-size-md.ta-oc--widened,
    .ta-oc-size-lg.ta-oc--widened {
        --bs-offcanvas-width: 100vw;
    }
}

@media (prefers-reduced-motion: reduce) {
    .offcanvas.ta-oc-size-sm,
    .offcanvas.ta-oc-size-md,
    .offcanvas.ta-oc-size-lg {
        --bs-offcanvas-transition: none;
    }
}

/* ════════════════════════════════════════════════════════════════════════
   ArchAI usage page (Administration › ArchAI usage)
   Scope colours match the ArchAI panel's scope chips, so Codes only /
   Project / Request look the same here as where the question was asked.
   Bars are plain CSS: no chart library is added to the global bundle for
   one admin page.
   ════════════════════════════════════════════════════════════════════════ */
.ta-usage-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}

.ta-usage-filters .form-select {
    width: auto;
    min-width: 170px;
}

.ta-usage-note {
    font-size: 13px;
    color: var(--triarch-text-soft, #6b7a8c);
    margin: 0 0 12px;
}

.ta-usage-sub {
    font-size: 12px;
    color: var(--triarch-text-soft, #6b7a8c);
    margin-top: 2px;
}

.ta-usage-card-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 14px;
    margin-bottom: 10px;
}

.ta-usage-card-title {
    font-size: 15px;
    font-weight: 600;
    margin: 0;
}

.ta-usage-card-head .ta-usage-card-title {
    margin-right: auto;
}

.ta-usage-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    font-size: 12px;
    color: var(--triarch-text-soft, #6b7a8c);
}

.ta-usage-legend__item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.ta-usage-swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 2px;
}

.ta-usage-seg--open    { background: #94a3b8; }
.ta-usage-seg--project { background: var(--triarch-cta, #c2410c); }
.ta-usage-seg--request { background: #2563eb; }

.ta-usage-chart {
    display: flex;
    align-items: stretch;
    gap: 4px;
    height: 160px;
    border-bottom: 1px solid var(--triarch-border, #eaeef2);
}

/* column-reverse stacks from the baseline up, so each segment's height is a
   share of the busiest day and the tallest column reaches the top. */
.ta-usage-chart__day {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column-reverse;
    gap: 1px;
}

.ta-usage-chart__day .ta-usage-seg {
    display: block;
}

.ta-usage-chart__day .ta-usage-seg:last-child {
    border-radius: 3px 3px 0 0;
}

.ta-usage-chart__axis {
    display: flex;
    gap: 4px;
    margin-top: 4px;
}

.ta-usage-chart__axis span {
    flex: 1 1 0;
    min-width: 0;
    text-align: center;
    font-size: 11px;
    color: var(--triarch-text-soft, #94a3b8);
}

.ta-usage-bars {
    display: grid;
    grid-template-columns: minmax(110px, max-content) 1fr minmax(56px, max-content);
    gap: 9px 12px;
    align-items: center;
    font-size: 13px;
}

.ta-usage-bars__track {
    display: flex;
    height: 8px;
    border-radius: 4px;
    overflow: hidden;
    background: var(--triarch-surface-2, #f1f4f8);
}

.ta-usage-bars__fill       { height: 100%; background: #64748b; }
.ta-usage-bars__fill--muted { background: #cbd5e1; }
.ta-usage-bars__fill--good { background: #16a34a; }
.ta-usage-bars__fill--bad  { background: #dc2626; }

.ta-usage-bars__value {
    text-align: right;
    color: var(--triarch-text-soft, #6b7a8c);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.ta-usage-meter {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 150px;
}

.ta-usage-meter__track {
    flex: 1;
    height: 6px;
    border-radius: 3px;
    overflow: hidden;
    background: var(--triarch-surface-2, #f1f4f8);
}

.ta-usage-meter__fill {
    display: block;
    height: 100%;
    background: #16a34a;
}

.ta-usage-meter--warn .ta-usage-meter__fill   { background: #d97706; }
.ta-usage-meter--danger .ta-usage-meter__fill { background: #dc2626; }

.ta-usage-meter__text {
    font-size: 12px;
    color: var(--triarch-text-soft, #6b7a8c);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.ta-usage-meter--warn .ta-usage-meter__text   { color: #b45309; }
.ta-usage-meter--danger .ta-usage-meter__text { color: #b91c1c; }

.ta-usage-table th,
.ta-usage-table td {
    white-space: nowrap;
}

.ta-usage-table .text-end {
    font-variant-numeric: tabular-nums;
}

.ta-usage-table .ta-usage-table__wrap {
    white-space: normal;
}

.ta-usage-flags > li + li {
    border-top: 1px solid var(--triarch-border, #eaeef2);
}

.ta-usage-flag {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 12px 0;
}

.ta-usage-flag__icon {
    color: #dc2626;
    margin-top: 3px;
}

.ta-usage-flag__body {
    flex: 1;
    min-width: 0;
}

.ta-usage-flag__question {
    font-weight: 500;
}

.ta-usage-flag__comment {
    margin: 6px 0 0;
    padding-left: 10px;
    border-left: 2px solid var(--triarch-border, #d7dde5);
    font-size: 13px;
    color: var(--triarch-text-soft, #6b7a8c);
}

/* Answers are long and Markdown-shaped; shown as preserved plain text in a
   bounded box so a two-page answer cannot push the sources out of the modal. */
.ta-usage-answer {
    white-space: pre-wrap;
    font-size: 13px;
    max-height: 320px;
    overflow-y: auto;
    padding: 10px 12px;
    border: 1px solid var(--triarch-border, #eaeef2);
    border-radius: 8px;
    background: var(--triarch-surface-2, #f8fafc);
}

.lpx-theme-dark .ta-usage-bars__track,
.lpx-theme-dark .ta-usage-meter__track {
    background: rgba(255, 255, 255, .08);
}

.lpx-theme-dark .ta-usage-answer {
    background: rgba(255, 255, 255, .04);
}

/* ============================================================================
   Offcanvas resource picker — the selectable rows inside *PickerPanel offcanvases
   (search toolbar, active toggle, row, selected / static row, title + meta).
   Was copied into the BuildRoom, Catalog and ControlRoom Shared/ta-form-picker-offcanvas.css
   files; defined once here so every module and host gets the same picker. Kept at the end
   of the theme so it still follows every other theme rule, as the page-level copies did.
   ============================================================================ */

.ta-form-picker-offcanvas__toolbar .input-group-text {
    color: var(--triarch-text-soft);
    border-color: var(--triarch-border);
}
.ta-form-picker-offcanvas__toolbar .form-control {
    border-color: var(--triarch-border);
    background: var(--triarch-surface);
    color: var(--triarch-text);
}
.ta-form-picker-offcanvas__toolbar--compact .ta-form-picker-offcanvas__toolbar-row {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 6px;
}
.ta-form-picker-offcanvas__toolbar--compact .ta-form-picker-offcanvas__toolbar-search {
    flex: 1 1 0;
    min-width: 0;
    width: auto;
}
.ta-form-picker-offcanvas__toolbar--compact .ta-form-picker-offcanvas__toolbar-actions {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}
.ta-form-picker-offcanvas__toolbar--compact .ta-form-picker-offcanvas__toolbar-actions > * {
    flex-shrink: 0;
}
.ta-form-picker-offcanvas__active-toggle.active,
.ta-form-picker-offcanvas__active-toggle[aria-pressed="true"] {
    color: var(--triarch-cta-hover);
    border-color: var(--triarch-cta-outline);
    background: var(--triarch-cta-tint);
}

.ta-form-picker-offcanvas__list-sentinel {
    padding: 8px 0 4px;
    text-align: center;
    font-size: 12px;
    color: var(--triarch-text-soft);
}
.ta-form-picker-offcanvas__row {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin: 0;
    padding: 10px 12px;
    border: 1px dashed var(--triarch-outline);
    border-radius: var(--radius-sm);
    background: var(--triarch-surface);
    cursor: pointer;
    transition: var(--transition-color);
}
.ta-form-picker-offcanvas__row:hover {
    border-color: var(--triarch-focus);
    background: var(--triarch-surface-soft);
}
.ta-form-picker-offcanvas__row--selected {
    background: var(--triarch-cta-tint);
    border-color: var(--triarch-cta-outline);
}
/* Read-only listing (assembly components): the row is information, not a control. Drop the
   pointer and the hover response so it does not advertise a click that does nothing. */
.ta-form-picker-offcanvas__row--static {
    cursor: default;
}
.ta-form-picker-offcanvas__row--static:hover {
    border-color: var(--triarch-outline);
    background: var(--triarch-surface);
}
.ta-form-picker-offcanvas__row-main {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1 1 auto;
}
.ta-form-picker-offcanvas__row-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--triarch-text);
    line-height: 1.3;
}
.ta-form-picker-offcanvas__row-meta {
    font-size: 11px;
    line-height: 1.35;
}
/* Department picker drawn as a parent/child tree. Depth steps the box in
   (--ta-tree-depth). The expand arrow hangs just outside that box, so it
   steps in with the same level. */
.ta-dept-tree__item {
    position: relative;
    display: flex;
    align-items: center;
    min-width: 0;
    margin-left: calc(var(--ta-tree-depth, 0) * var(--space-4));
}
.ta-form-picker-offcanvas__row--tree {
    align-items: center;
    flex: 1 1 auto;
    min-width: 0;
}
.ta-form-picker-offcanvas__tree-choice {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    cursor: pointer;
}
.ta-form-picker-offcanvas__tree-choice .form-check-input {
    margin: 0;
    flex-shrink: 0;
}
.ta-form-picker-offcanvas__tree-choice > .ta-tag {
    margin-left: auto;
    flex-shrink: 0;
}
.ta-dept-tree__toggle {
    position: absolute;
    left: calc(-1 * (16px + var(--space-2)));
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--triarch-text-soft);
    cursor: pointer;
}
.ta-dept-tree__toggle:focus-visible {
    outline: 2px solid var(--triarch-focus);
    outline-offset: 2px;
}
.ta-dept-tree__toggle .fa-angle-down {
    font-size: 12px;
    line-height: 1;
}
@media (prefers-reduced-motion: no-preference) {
    .ta-dept-tree__toggle .fa-angle-down {
        transition: transform var(--duration-fast) var(--ease-standard);
    }
}
.ta-dept-tree__toggle[aria-expanded="false"] .fa-angle-down {
    transform: rotate(-90deg);
}

/* ============================================================================
   Page-title back link — the arrow that page scripts move into the H1
   (BuildRoom Launch Phase index.js, ControlRoom controlroom-ui.js / _PageHeaderBack,
   Catalog Import History). Was defined separately in BuildRoom launchPhase.css,
   ControlRoom controlroom-ui.css and Web.Public global-styles.css. Tokens rebase for
   dark, so no dark-only copy is needed.
   ============================================================================ */
.ta-page-header-back {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    color: var(--triarch-text-soft);
    text-decoration: none;
    font-size: 0.85em;
    vertical-align: middle;
    line-height: 1;
}
.ta-page-header-back:hover,
.ta-page-header-back:focus {
    color: var(--triarch-primary);
    text-decoration: none;
}
.ta-page-header-back:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--triarch-primary) 55%, transparent);
    outline-offset: 2px;
    border-radius: var(--radius-sm, 6px);
}

/* ============================================================================
   Icon buttons — square, icon-only controls in work-surface toolbars and floating tool rails
   (BuildRoom Take-Off plan viewer, Quote Review editor). .ta-icon-btn is the ghost 30px toolbar
   button; add .ta-icon-btn--rail for the bordered 34px buttons stacked in a floating side rail.
   Was defined twice (takeOffStage.css + quote-review.css); pages keep only context sizes and
   their own JS hook classes.
   ============================================================================ */
.ta-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--triarch-text-soft);
    cursor: pointer;
}
.ta-icon-btn:hover,
.ta-icon-btn:focus-visible,
.ta-icon-btn.is-active,
.ta-icon-btn[aria-expanded="true"] {
    background: var(--triarch-surface-dim);
    color: var(--triarch-text);
}
.ta-icon-btn:focus-visible {
    outline: 2px solid var(--triarch-focus);
    outline-offset: 2px;
}
.ta-icon-btn:disabled,
.ta-icon-btn.is-locked {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
}
.ta-icon-btn .e-icons,
.ta-icon-btn .fa {
    font-size: 14px;
    line-height: 1;
}

.ta-icon-btn--rail {
    width: 34px;
    height: 34px;
    border: 1px solid var(--triarch-border);
    border-radius: 8px;
    background: var(--triarch-surface);
    color: var(--triarch-text-soft);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
    transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.ta-icon-btn--rail:hover,
.ta-icon-btn--rail:focus-visible {
    background: var(--triarch-surface-soft);
    border-color: var(--triarch-outline);
    color: var(--triarch-text);
}
/* surface-dim, not outline: outline is barely darker than the resting border, and the selected tool
   must stand out from its neighbours. */
.ta-icon-btn--rail.is-active {
    background: var(--triarch-surface-soft);
    border-color: var(--triarch-surface-dim);
    color: var(--triarch-text);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--triarch-primary) 15%, transparent);
}
.ta-icon-btn--rail:disabled,
.ta-icon-btn--rail.is-locked {
    opacity: 0.45;
}
/* Dark: the rail sits on the plan / document canvas, so it takes the LeptonX body surface and the
   brand accent for hover and the active tool. */
.lpx-theme-dark .ta-icon-btn--rail {
    background: var(--bs-body-bg, #1b1b1f);
    border-color: rgba(255, 255, 255, 0.12);
    color: var(--bs-body-color, #e5e7eb);
    box-shadow: none;
}
.lpx-theme-dark .ta-icon-btn--rail:hover,
.lpx-theme-dark .ta-icon-btn--rail:focus-visible,
.lpx-theme-dark .ta-icon-btn--rail.is-active {
    background: var(--triarch-primary-tint);
    border-color: var(--triarch-accent);
    color: var(--triarch-accent);
}
.lpx-theme-dark .ta-icon-btn--rail.is-active {
    box-shadow: inset 0 0 0 1px var(--triarch-accent);
}

/* ── Page intro — eyebrow + one-paragraph lead under the page title ─────
   For setup screens that need a sentence of context above the grid (Catalog → Cost
   categories, BuildRoom → Estimating templates). Promoted from the two page-local
   copies (.cc-head, .et-head), which were identical. */
.ta-page-intro {
    margin-bottom: var(--space-3);
}
.ta-page-intro__eyebrow {
    margin-bottom: 0.15rem;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--triarch-text-soft);
}
.ta-page-intro__lead {
    max-width: 82ch;
    margin: 0;
    font-size: 13px;
    line-height: 1.6;
    color: var(--triarch-text-soft);
}

/* ── Detail-page tab strip ──────────────────────────────────────────────
   <ul class="nav nav-tabs ta-detail-tabs"> inside the page's ta-list-card. Promoted from
   BuildRoom Projects/Detail/detail.css so every detail page (projects, estimating
   templates) draws the same strip. A tab can carry a count as a neutral .ta-pill. */
.ta-detail-tabs .nav-link {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--triarch-text-soft, #6b7280);
}

.ta-detail-tabs .nav-link.active {
    color: var(--triarch-text, #1f2937);
}

@media (max-width: 1199.98px) {
    /* Opt-in horizontal strip (detail tab bar, search type tabs). Same idea as .ta-list-kpi-row. */
    .ta-hscroll-strip {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    .ta-hscroll-strip .nav-tabs,
    .ta-hscroll-strip.nav-tabs {
        flex-wrap: nowrap;
        width: max-content;
        min-width: 100%;
    }
    .ta-hscroll-strip .nav-item { flex: 0 0 auto; }
    .ta-hscroll-strip .nav-link { white-space: nowrap; }
}

/* Confirm dialogs: abp.message.confirm hands the string to SweetAlert's `text`, which sets textContent,
   so a \n\n in the copy collapsed into a space and ran the figures into the warning after them.
   (abp.message.info/warn/error escape to <br> themselves; confirm does not.) */
.swal2-html-container {
    white-space: pre-line;
}

/* ── BuildRoom global search (header box) ───────────────────────────────────────────────
   Rendered by BuildRoomSearchBoxViewComponent inside the LeptonX BreadCrumb override, next to the
   tenant name. Colours come only from --triarch-* tokens, which each .lpx-theme-* block already
   defines, so light, dim and dark need no separate rules. docs/Architecture/BuildRoomSearch.md §12. */
.ta-header-tools {
    min-width: 0;
}

.ta-global-search {
    position: relative;
    width: min(420px, 42vw);
    min-width: 0;
    transition: width 0.15s ease;
}

/* Open: the box widens (to the left, it is right-aligned in the header) to the dropdown's width, and the
   dropdown spans the box exactly — one column, like GitHub. Phones keep their own rules below. */
@media (min-width: 768px) {
    .ta-global-search.is-open {
        width: min(560px, 60vw);
    }

    .ta-global-search .ta-global-search__panel {
        left: 0;
        right: 0;
        width: auto;
    }
}

/* Sits inside the 35px breadcrumb strip: slimmer than the strip, no fill of its own, and the same
   outline + 7px radius as the page's outline buttons ("Export to Excel"), so it reads as part of the bar.
   Focus uses the app's form-control ring (primary at 50% + soft orange halo), not a separate blue one. */
.ta-global-search__box {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    height: 28px;
    padding: 0 0.4rem 0 0.6rem;
    border: 1px solid var(--triarch-outline);
    border-radius: 7px;
    background: transparent;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}

.ta-global-search__box:hover {
    background: var(--triarch-surface);
}

.ta-global-search.is-open .ta-global-search__box,
.ta-global-search__box:focus-within {
    background: var(--triarch-surface);
    border-color: color-mix(in srgb, var(--triarch-primary) 50%, transparent);
    box-shadow: 0 0 0 0.2rem rgba(157, 67, 0, 0.15);
}

.ta-global-search__icon,
.ta-global-search__glyph {
    color: var(--triarch-text-soft);
    flex: none;
}

.ta-global-search__input {
    flex: 1;
    min-width: 0;
    height: 100%;
    border: 0;
    outline: none;
    background: transparent;
    color: var(--triarch-text);
    font-size: 13px;
}

.ta-global-search__input::placeholder {
    color: var(--triarch-text-soft);
}

.ta-global-search__clear {
    border: 0;
    background: none;
    padding: 0.125rem 0.25rem;
    color: var(--triarch-text-soft);
    line-height: 1;
}

.ta-global-search__kbd {
    font-size: 11px;
    line-height: 16px;
    padding: 0 0.35rem;
    border: 1px solid var(--triarch-outline);
    border-radius: 4px;
    background: transparent;
    color: var(--triarch-text-soft);
    box-shadow: none;
}

/* (i) beside "/": opens the help offcanvas. */
.ta-global-search__help {
    border: 0;
    background: none;
    padding: 0 0.15rem;
    color: var(--triarch-text-soft);
    font-size: 13px;
    line-height: 1;
}

.ta-global-search__help:hover,
.ta-global-search__help:focus-visible {
    color: var(--triarch-primary);
}

.ta-global-search__panel {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 1060;
    width: min(560px, calc(100vw - 32px));
    border: 1px solid var(--triarch-outline);
    border-radius: 10px;
    background: var(--triarch-surface);
    box-shadow: 0 12px 40px rgba(15, 23, 42, 0.18), 0 2px 6px rgba(15, 23, 42, 0.08);
    overflow: hidden;
}

.ta-global-search__list {
    max-height: min(440px, 70vh);
    overflow-y: auto;
    padding: 0.35rem 0;
}

.ta-global-search__section {
    display: flex;
    justify-content: space-between;
    padding: 0.5rem 0.9rem 0.25rem;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--triarch-text-soft);
}

.ta-global-search__item {
    display: grid;
    grid-template-columns: 22px minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.65rem;
    padding: 0.45rem 0.9rem;
    border-left: 2px solid transparent;
    cursor: pointer;
    color: var(--triarch-text);
}

.ta-global-search__item.is-active {
    background: var(--triarch-surface-soft);
    border-left-color: var(--triarch-primary);
}

.ta-global-search__item.is-jump {
    background: var(--triarch-primary-tint);
}

.ta-global-search__item.is-disabled {
    cursor: default;
    color: var(--triarch-text-soft);
}

.ta-global-search__item.is-current .ta-global-search__glyph {
    color: var(--triarch-primary);
}

.ta-global-search__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.ta-global-search__text > span,
.ta-global-search__text > small {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ta-global-search__text > small {
    color: var(--triarch-text-soft);
}

.ta-global-search__key,
.ta-global-search__code {
    font-family: var(--triarch-font-mono);
    font-size: 0.8rem;
}

.ta-global-search__key {
    margin-right: 0.4rem;
    color: var(--triarch-cta);
}

.ta-global-search__code b {
    color: var(--triarch-primary);
    font-weight: 500;
}

.ta-global-search__end {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.ta-global-search__pill,
.ta-global-search__count {
    font-size: 0.7rem;
    padding: 0.05rem 0.5rem;
    border-radius: 999px;
    border: 1px solid var(--triarch-border);
    background: var(--triarch-surface-soft);
    color: var(--triarch-text-soft);
    white-space: nowrap;
}

.ta-global-search__hint {
    font-size: 0.7rem;
    color: var(--triarch-text-soft);
    white-space: nowrap;
}

.ta-global-search__more,
.ta-global-search__back {
    border: 1px solid var(--triarch-outline);
    border-radius: 6px;
    background: var(--triarch-surface);
    color: var(--triarch-text-soft);
    line-height: 1;
    padding: 0.2rem 0.35rem;
}

.ta-global-search__more {
    opacity: 0.55;
}

.ta-global-search__item.is-active .ta-global-search__more,
.ta-global-search__more:hover,
.ta-global-search__back:hover {
    opacity: 1;
    color: var(--triarch-primary);
    border-color: var(--triarch-primary);
}

.ta-global-search__context {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: -0.35rem 0 0.25rem;
    padding: 0.5rem 0.9rem 0.5rem 0.5rem;
    border-bottom: 1px solid var(--triarch-border);
    background: var(--triarch-surface-soft);
}

.ta-global-search__chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.9rem;
}

.ta-global-search__chips-label {
    font-size: 0.7rem;
    color: var(--triarch-text-soft);
}

.ta-global-search__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.1rem 0.2rem 0.1rem 0.6rem;
    border: 1px solid var(--triarch-outline);
    border-radius: 999px;
    font-family: var(--triarch-font-mono);
    font-size: 0.75rem;
    color: var(--triarch-text);
}

.ta-global-search__chip.is-negated {
    border-style: dashed;
}

.ta-global-search__chip button {
    border: 0;
    border-radius: 50%;
    width: 18px;
    height: 18px;
    padding: 0;
    line-height: 1;
    background: var(--triarch-surface-soft);
    color: var(--triarch-text-soft);
}

.ta-global-search__notice {
    margin: 0.25rem 0.9rem;
    padding: 0.35rem 0.6rem;
    border-radius: 6px;
    font-size: 0.8rem;
    background: var(--triarch-surface-soft);
    color: var(--triarch-text-soft);
}

.ta-global-search__notice.is-error {
    color: var(--triarch-danger);
}

.ta-global-search__empty {
    padding: 1rem 0.9rem;
    font-size: 0.85rem;
    color: var(--triarch-text-soft);
}

.ta-global-search__foot {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 0.9rem;
    padding: 0.45rem 0.9rem;
    border-top: 1px solid var(--triarch-border);
    background: var(--triarch-surface-soft);
    font-size: 0.72rem;
    color: var(--triarch-text-soft);
}

@media (max-width: 767.98px) {
    .ta-global-search {
        width: min(100%, 60vw);
    }

    .ta-global-search__kbd {
        display: none;
    }

    /* The box sits mid-header on phones: pin the panel to the viewport (16px gutters) instead of the
       box's right edge; search-box.js sets its top just below the box. */
    .ta-global-search__panel {
        position: fixed;
        left: 16px;
        right: 16px;
        width: auto;
    }
}

@media (prefers-reduced-motion: reduce) {
    .ta-global-search__box {
        transition: none;
    }
}

/* ── Search help (#TaGlobalSearchHelp) ── the shared .ta-help-offcanvas / .ta-help-callout panel; only the
   clickable examples and step 3's per-type field rows are its own. */
.ta-search-help__examples,
.ta-search-help__type {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem;
    margin-top: 0.4rem;
}

.ta-search-help__type-name {
    margin-right: 0.2rem;
    font-weight: 600;
    color: var(--triarch-text);
}

.ta-search-help__example {
    padding: 0 0.4rem;
    border: 1px solid var(--triarch-border);
    border-radius: 6px;
    background: var(--triarch-surface);
    font-family: var(--triarch-font-mono);
    font-size: 11px;
    line-height: 1.6;
    color: var(--triarch-text);
    cursor: pointer;
}

.ta-search-help__example:hover,
.ta-search-help__example:focus-visible {
    border-color: var(--triarch-primary);
    color: var(--triarch-primary);
}

/* Phones: the per-row "↵ open" keyboard hint costs a third of the row, so titles get the room instead;
   touch devices also drop the keyboard footer (↑↓ move, → actions…), which they cannot use. */
@media (max-width: 575.98px) {
    .ta-global-search__end .ta-global-search__hint {
        display: none;
    }

    /* Titles may take two lines on phones (number + name rarely fit in one). */
    .ta-global-search__text > span {
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        white-space: normal;
    }
}

@media (hover: none) and (pointer: coarse) {
    .ta-global-search__foot {
        display: none;
    }
}

/* Search in flight (search-box.js adds .is-searching after 150 ms): the magnifier becomes a ring spinner.
   Typing never blocks the page; page transitions use the theme's taBusy overlay instead. */
.ta-global-search.is-searching .ta-global-search__icon::before {
    content: "";
    display: inline-block;
    width: 0.85em;
    height: 0.85em;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    vertical-align: -0.1em;
    animation: ta-global-search-spin 0.7s linear infinite;
}

.ta-global-search__empty.is-searching {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

@keyframes ta-global-search-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .ta-global-search.is-searching .ta-global-search__icon::before {
        animation: none;
        border-right-color: currentColor;
        opacity: 0.6;
    }
}

/* A warning pill in the dropdown (e.g. a material's trade-feed price is out of date). */
.ta-global-search__pill.is-warn {
    border-color: transparent;
    background: var(--status-in-review-bg);
    color: var(--status-in-review);
}

/* ── BuildRoom search results page (/BuildRoom/Search) ───────────────────────────────────
   Server-rendered by the search module; type tabs reuse .ta-detail-tabs, rows reuse .ta-pill. */
.ta-search-results__form {
    max-width: 720px;
    margin-bottom: var(--space-3, 12px);
}

.ta-search-results__chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    margin-bottom: var(--space-2, 8px);
}

.ta-search-results__chips-label {
    font-size: 0.75rem;
    color: var(--triarch-text-soft);
}

.ta-search-results__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.1rem 0.25rem 0.1rem 0.6rem;
    border: 1px solid var(--triarch-border);
    border-radius: 999px;
    background: var(--triarch-surface-soft);
    font-size: 0.75rem;
    color: var(--triarch-text);
}

.ta-search-results__chip.is-negated {
    border-style: dashed;
}

.ta-search-results__chip a {
    padding: 0 0.35rem;
    color: var(--triarch-text-soft);
    text-decoration: none;
}

.ta-search-results__chip a:hover {
    color: var(--triarch-text);
}

.ta-search-results__notice {
    margin-bottom: var(--space-2, 8px);
    font-size: 0.8rem;
    color: var(--triarch-text-soft);
}

.ta-search-results__tabs {
    margin-bottom: 0;
}

.ta-search-results__list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.ta-search-results__item {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.85rem 1rem;
    border-bottom: 1px solid var(--triarch-border);
}

.ta-search-results__item:last-child {
    border-bottom: 0;
}

.ta-search-results__main {
    min-width: 0;
}

.ta-search-results__title {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    font-weight: 600;
}

.ta-search-results__meta {
    margin-top: 0.15rem;
    font-size: 0.8rem;
    color: var(--triarch-text-soft);
}

.ta-search-results__scopes,
.ta-search-results__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 0.9rem;
    margin-top: 0.4rem;
    font-size: 0.8rem;
}

.ta-search-results__scopes {
    gap: 0.35rem;
}

.ta-search-results__actions a {
    color: var(--triarch-text-soft);
    text-decoration: none;
}

.ta-search-results__actions a:hover,
.ta-search-results__actions a:focus-visible {
    color: var(--triarch-primary);
}

.ta-search-results__end {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.3rem;
    flex-shrink: 0;
}

.ta-search-results__pager {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.75rem 1rem;
    border-top: 1px solid var(--triarch-border);
    font-size: 0.8rem;
    color: var(--triarch-text-soft);
}

@media (max-width: 575.98px) {
    .ta-search-results__item {
        flex-direction: column;
        gap: 0.4rem;
    }

    .ta-search-results__end {
        flex-direction: row;
        align-items: center;
    }
}

/* ============================================================================
   Tenant setup (/TenantSetup) — baseline packs, customer-data imports (choose
   file, validate, import), the demo set, and the progress / recent-runs rail.
   Tokens only, so light and dark follow the theme.
   ============================================================================ */
.ta-setup-layout {
    display: flex;
    gap: 20px;
    align-items: flex-start;
}

.ta-setup-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 28px;
}

.ta-setup-rail {
    flex: 0 0 320px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

@media (max-width: 1199.98px) {
    .ta-setup-layout {
        flex-direction: column;
    }

    .ta-setup-rail {
        flex-basis: auto;
        width: 100%;
    }
}

/* The theme swaps the native select for .custom-select-display right after it; size the visible control. */
.ta-setup-tenant,
.ta-setup-tenant + .custom-select-display {
    width: auto;
    min-width: 240px;
    max-width: 320px;
}

.ta-setup-section {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.ta-setup-section__head {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.ta-setup-eyebrow {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--triarch-text-soft);
}

.ta-setup-section__title {
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    color: var(--triarch-text);
}

.ta-setup-section__lead {
    margin: 0;
    font-size: 13px;
    color: var(--triarch-text-soft);
}

.ta-setup-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
}

.ta-setup-card {
    background: var(--triarch-surface);
    border: 1px solid var(--triarch-border);
    border-radius: 12px;
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.ta-setup-card--error {
    border-color: color-mix(in srgb, var(--triarch-danger) 35%, var(--triarch-border));
}

.ta-setup-card__row {
    display: flex;
    align-items: flex-start;
    gap: 16px;
}

/* The card's action ("Re-apply") keeps its width; the text column shrinks instead. */
.ta-setup-card__row > form {
    flex-shrink: 0;
}

.ta-setup-card__row .btn {
    white-space: nowrap;
}

.ta-setup-card__body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.ta-setup-card__title {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: 15px;
    font-weight: 600;
    color: var(--triarch-text);
}

.ta-setup-card__text,
.ta-setup-card__meta {
    margin: 0;
    font-size: 13px;
    color: var(--triarch-text-soft);
}

.ta-setup-card__meta {
    font-size: 12px;
}

.ta-setup-card__link {
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    color: var(--triarch-cta);
    text-decoration: none;
}

.ta-setup-card__link:hover {
    color: var(--triarch-cta-hover);
}

.ta-setup-icon {
    flex: 0 0 40px;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--triarch-cta-tint);
    color: var(--triarch-cta);
}

.ta-setup-icon--done {
    background: var(--triarch-success-bg);
    color: var(--triarch-success-fg);
}

.ta-setup-icon--muted {
    background: var(--triarch-surface-soft);
    color: var(--triarch-text-soft);
}

.ta-setup-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

/* Choose file, validate, import */
.ta-setup-steps {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
}

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

.ta-setup-step {
    border: 1px solid var(--triarch-border);
    border-radius: 10px;
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.ta-setup-step__label {
    font-size: 12px;
    font-weight: 600;
    color: var(--triarch-text-soft);
}

.ta-setup-step__value {
    font-size: 13px;
    font-weight: 600;
    color: var(--triarch-text);
    overflow-wrap: anywhere;
}

.ta-setup-step__meta {
    font-size: 12px;
    color: var(--triarch-text-soft);
}

.ta-setup-step--done {
    border-color: color-mix(in srgb, var(--triarch-success) 35%, var(--triarch-border));
    background: color-mix(in srgb, var(--triarch-success-bg) 45%, var(--triarch-surface));
}

.ta-setup-step--done .ta-setup-step__label {
    color: var(--triarch-success-fg);
}

.ta-setup-step--current {
    border-color: var(--triarch-cta-outline);
    background: color-mix(in srgb, var(--triarch-cta-tint) 45%, var(--triarch-surface));
}

.ta-setup-step--current .ta-setup-step__label {
    color: var(--triarch-cta);
}

.ta-setup-step--error {
    border-color: color-mix(in srgb, var(--triarch-danger) 35%, var(--triarch-border));
    background: color-mix(in srgb, var(--triarch-danger) 6%, var(--triarch-surface));
}

.ta-setup-step--error .ta-setup-step__label {
    color: var(--triarch-danger);
}

.ta-setup-step--pending {
    border-style: dashed;
}

/* Result: per-area counts and issues */
.ta-setup-result {
    display: flex;
    flex-direction: column;
    gap: 12px;
    border-top: 1px solid var(--triarch-border);
    padding-top: 16px;
}

.ta-setup-table {
    border: 1px solid var(--triarch-border);
    border-radius: 10px;
    overflow: hidden;
    font-size: 13px;
}

.ta-setup-table__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 80px 80px 100px;
    gap: 12px;
    padding: 9px 14px;
    border-top: 1px solid var(--triarch-border);
    color: var(--triarch-text);
}

.ta-setup-table__row:first-child {
    border-top: 0;
}

.ta-setup-table__row--head {
    background: var(--triarch-surface-soft);
    font-size: 12px;
    font-weight: 600;
    color: var(--triarch-text-soft);
}

.ta-setup-table--issues .ta-setup-table__row {
    grid-template-columns: 200px minmax(0, 1fr);
}

.ta-setup-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.ta-setup-issues {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.ta-setup-issues__head {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    font-weight: 600;
    color: var(--triarch-text);
}

.ta-setup-issue__where {
    font-weight: 600;
    color: var(--triarch-text-soft);
}

.ta-setup-details {
    border-top: 1px solid var(--triarch-border);
    padding-top: 12px;
    font-size: 13px;
}

.ta-setup-details > summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--triarch-text);
}

/* Rail: setup progress and recent runs */
.ta-setup-rail__title {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--triarch-text);
}

.ta-setup-progress,
.ta-setup-runs {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.ta-setup-progress__item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
}

.ta-setup-progress__item > div {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ta-setup-progress__dot {
    flex: 0 0 18px;
    width: 18px;
    height: 18px;
    margin-top: 1px;
    border-radius: 50%;
    border: 2px solid var(--triarch-outline);
    box-sizing: border-box;
}

.ta-setup-progress__item--done .ta-setup-progress__dot {
    border-color: var(--triarch-success);
    background: var(--triarch-success);
}

.ta-setup-progress__item--error .ta-setup-progress__dot {
    border-color: var(--triarch-danger);
}

.ta-setup-progress__item--optional .ta-setup-progress__dot {
    border-style: dashed;
}

.ta-setup-progress__name,
.ta-setup-runs__name {
    font-size: 13px;
    font-weight: 600;
    color: var(--triarch-text);
}

.ta-setup-progress__meta,
.ta-setup-runs__meta,
.ta-setup-runs__summary {
    font-size: 12px;
    color: var(--triarch-text-soft);
}

.ta-setup-progress__item--error .ta-setup-progress__meta {
    color: var(--triarch-danger);
}

.ta-setup-runs__item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--triarch-border);
}

.ta-setup-runs__item:last-child {
    padding-bottom: 0;
    border-bottom: 0;
}

/* A run summary can be a long refusal (e.g. every colliding name); three lines, full text on hover. */
.ta-setup-runs__summary {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.ta-setup-runs__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

/* ── Guided product tours (ta-tour.js → driver.js) ─────────────────────
   driver.css is loaded on demand and inserted BEFORE this sheet, so these
   rules win on equal specificity. Colours are theme tokens only, so the
   popover follows light / dark with no separate dark block. */
.driver-popover.ta-tour-popover {
    font-family: var(--triarch-font-body);
    color: var(--triarch-text);
    background: var(--triarch-surface);
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-md, 10px);
    box-shadow: 0 18px 48px -18px rgba(15, 23, 42, 0.45);
    min-width: 280px;
    max-width: 360px;
    padding: 18px 18px 14px;
}

.driver-popover.ta-tour-popover .driver-popover-arrow {
    border-color: var(--triarch-surface);
}

.driver-popover.ta-tour-popover .driver-popover-arrow-side-left {
    border-top-color: transparent;
    border-bottom-color: transparent;
    border-right-color: transparent;
}

.driver-popover.ta-tour-popover .driver-popover-arrow-side-right {
    border-top-color: transparent;
    border-bottom-color: transparent;
    border-left-color: transparent;
}

.driver-popover.ta-tour-popover .driver-popover-arrow-side-top {
    border-bottom-color: transparent;
    border-left-color: transparent;
    border-right-color: transparent;
}

.driver-popover.ta-tour-popover .driver-popover-arrow-side-bottom {
    border-top-color: transparent;
    border-left-color: transparent;
    border-right-color: transparent;
}

.driver-popover.ta-tour-popover .driver-popover-title {
    font-family: var(--triarch-font-display);
    font-size: 16px;
    font-weight: 600;
    line-height: 1.35;
    padding-right: 24px;
    color: var(--triarch-text);
}

.driver-popover.ta-tour-popover .driver-popover-description {
    font-size: 14px;
    line-height: 1.55;
    color: var(--triarch-text-soft);
}

.driver-popover.ta-tour-popover .driver-popover-close-btn {
    color: var(--triarch-text-soft);
}

.driver-popover.ta-tour-popover .driver-popover-close-btn:hover,
.driver-popover.ta-tour-popover .driver-popover-close-btn:focus-visible {
    color: var(--triarch-text);
}

.driver-popover.ta-tour-popover .driver-popover-footer {
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 16px;
}

.driver-popover.ta-tour-popover .driver-popover-progress-text {
    font-size: 12px;
    color: var(--triarch-text-soft);
}

.driver-popover.ta-tour-popover .driver-popover-footer-btn {
    font-family: var(--triarch-font-body);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.2;
    padding: 6px 12px;
    border-radius: var(--radius-sm, 6px);
    text-shadow: none;
    color: var(--triarch-text);
    background: var(--triarch-surface);
    border: 1px solid var(--triarch-border);
}

.driver-popover.ta-tour-popover .driver-popover-footer-btn:hover {
    background: var(--triarch-surface-soft);
}

.driver-popover.ta-tour-popover .driver-popover-next-btn {
    color: var(--triarch-text-on-cta);
    background: var(--triarch-primary);
    border-color: var(--triarch-primary);
}

.driver-popover.ta-tour-popover .driver-popover-next-btn:hover {
    background: var(--triarch-primary-strong);
    border-color: var(--triarch-primary-strong);
}

.driver-popover.ta-tour-popover .driver-popover-footer-btn:focus-visible,
.driver-popover.ta-tour-popover .ta-tour-dismiss:focus-visible {
    outline: 2px solid var(--triarch-focus);
    outline-offset: 2px;
}

/* Resumed tour: one line above the title, with a way back to the first step. */
.driver-popover.ta-tour-popover .ta-tour-resume {
    margin: 0 24px 8px 0;
    font-size: 12px;
    color: var(--triarch-text-soft);
}

.driver-popover.ta-tour-popover .ta-tour-start-over {
    all: unset;
    cursor: pointer;
    font-weight: 600;
    color: var(--triarch-primary);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.driver-popover.ta-tour-popover .ta-tour-start-over:focus-visible {
    outline: 2px solid var(--triarch-focus);
    outline-offset: 2px;
}

/* "Don't show tours again" — a quiet text link at the start of the footer. */
.driver-popover.ta-tour-popover .ta-tour-dismiss {
    all: unset;
    order: -1;
    flex-basis: 100%;
    text-align: left;
    cursor: pointer;
    font-size: 12px;
    color: var(--triarch-text-soft);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.driver-popover.ta-tour-popover .ta-tour-dismiss:hover {
    color: var(--triarch-text);
}

/* ════════════════════════════════════════════════════════════════════════
   UI Standard primitives (docs/ui-standard.md §6–§7)
   Opt-in classes: nothing here changes existing markup. Colours come only
   from the role tokens, so every rule works in light and dark without a
   theme override.
   ════════════════════════════════════════════════════════════════════════ */

/* Tag — an outlined source or flag on a line: Take-off, Manual, No catalog part, Expired.
   A pill labels a record; a tag says where a line came from or what is wrong with it. */
.ta-tag {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 1px 7px;
    border: 1px solid var(--triarch-outline);
    border-radius: var(--radius-xs);
    background: transparent;
    color: var(--triarch-text-soft);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    line-height: 1.5;
    text-transform: uppercase;
    white-space: nowrap;
}

/* Data tag — the tag holds a value (a brand, a vendor name, a date, a value from an import file), so it
   keeps that value's own case. Plain .ta-tag is for fixed labels and stays uppercase. */
.ta-tag--data {
    letter-spacing: 0.02em;
    text-transform: none;
}

/* Vendor tag — a price that follows a vendor: the vendor identity colour. */
.ta-tag--vendor {
    color: var(--triarch-cat-6-fg);
    border-color: color-mix(in srgb, var(--triarch-cat-6-fg) 45%, transparent);
    background: var(--triarch-cat-6-bg);
}

/* Highlighted add action — "Add component", "Add from catalog", "Add line". A brand-outline button that
   stands out beside neutral secondaries without competing with the one filled button of the surface. */
.btn.ta-btn-add {
    border: 1px solid var(--triarch-action-outline);
    background: transparent;
    color: var(--triarch-action);
    font-weight: 600;
}
.btn.ta-btn-add:hover,
.btn.ta-btn-add:focus-visible {
    border-color: var(--triarch-action);
    background: var(--triarch-action-tint);
    color: var(--triarch-action-hover);
}

/* Brand tag — something the system added or adjusted: a code-suggested line, an applied factor. */
.ta-tag--brand {
    color: var(--triarch-action-fg);
    border-color: var(--triarch-action-outline);
    background: var(--triarch-action-tint);
}
.ta-tag--warning {
    color: var(--triarch-warning-fg);
    border-color: color-mix(in srgb, var(--triarch-warning-fg) 45%, transparent);
    background: var(--triarch-warning-bg);
}
.ta-tag--danger {
    color: var(--triarch-danger-fg);
    border-color: color-mix(in srgb, var(--triarch-danger-fg) 45%, transparent);
    background: var(--triarch-danger-bg);
}
.ta-tag--success {
    color: var(--triarch-success-fg);
    border-color: color-mix(in srgb, var(--triarch-success-fg) 45%, transparent);
    background: var(--triarch-success-bg);
}
.ta-tag--info {
    color: var(--triarch-info-fg);
    border-color: color-mix(in srgb, var(--triarch-info-fg) 45%, transparent);
    background: var(--triarch-info-bg);
}

/* Segmented control — switches between views of the same content. The active option is a
   raised surface with a hairline ring (the ring is what shows on dark surfaces), so it does not
   read as a selected filter chip (.ta-chip uses the action tint).
   Mark the active option with .is-active or aria-pressed / aria-selected / aria-checked. */
.ta-segmented {
    display: inline-flex;
    gap: 2px;
    padding: 3px;
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-md);
    background: var(--triarch-surface-soft);
}
.ta-segmented--block {
    display: flex;
}
.ta-segmented--block .ta-segmented__option {
    flex: 1;
}
.ta-segmented__option {
    appearance: none;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    padding: 5px 12px;
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.4;
    color: var(--triarch-text-soft);
    white-space: nowrap;
    cursor: pointer;
    transition: var(--transition-color);
}
/* The word beside an option's icon; the compact toolbar above clips it off screen. */
.ta-segmented__label {
    margin-left: 6px;
}
.ta-segmented__option:hover {
    color: var(--triarch-text);
}
.ta-segmented__option.is-active,
.ta-segmented__option[aria-pressed="true"],
.ta-segmented__option[aria-selected="true"],
.ta-segmented__option[aria-checked="true"] {
    background: var(--triarch-surface);
    color: var(--triarch-text);
    box-shadow: var(--shadow-xs), 0 0 0 1px var(--triarch-border);
}
.ta-segmented__option:focus-visible {
    outline: 0;
    box-shadow: var(--focus-ring);
}
.ta-segmented__option:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

/* Menu — add .ta-menu to a Bootstrap .dropdown-menu (keyboard and focus come from Bootstrap).
   Open it from the standard kebab, .ta-icon-btn. A destructive item goes last, after a divider. */
.dropdown-menu.ta-menu {
    --bs-dropdown-bg: var(--triarch-surface);
    --bs-dropdown-border-color: var(--triarch-border);
    --bs-dropdown-link-color: var(--triarch-text);
    --bs-dropdown-link-hover-color: var(--triarch-text);
    --bs-dropdown-link-hover-bg: var(--triarch-surface-soft);
    min-width: 13rem;
    padding: var(--space-1);
    border: 1px solid var(--triarch-border);
    border-radius: var(--radius-md);
    background: var(--triarch-surface);
    box-shadow: var(--shadow-md);
}
.ta-menu .dropdown-item {
    border-radius: var(--radius-sm);
    padding: 7px 10px;
    font-size: 13px;
    color: var(--triarch-text);
    white-space: normal;
}
.ta-menu .dropdown-item:hover,
.ta-menu .dropdown-item:focus {
    background: var(--triarch-surface-soft);
    color: var(--triarch-text);
}
.ta-menu__desc {
    display: block;
    font-size: 12px;
    font-weight: 400;
    color: var(--triarch-text-soft);
}
.ta-menu .dropdown-item.ta-menu__danger {
    color: var(--triarch-danger-fg);
}
.ta-menu .dropdown-item.ta-menu__danger:hover,
.ta-menu .dropdown-item.ta-menu__danger:focus {
    background: var(--triarch-danger-bg);
    color: var(--triarch-danger-fg);
}
.ta-menu .dropdown-divider {
    margin: var(--space-1) 6px;
    border-top-color: var(--triarch-border);
    opacity: 1;
}

/* Skeleton — placeholder rows while a region loads. Put aria-busy="true" on the region and
   keep the rows out of the accessibility tree with aria-hidden="true". Whole-page waits use
   triArch.taBusy; a single button shows its spinner inside the button. */
.ta-skeleton {
    display: grid;
    gap: var(--space-2);
}
.ta-skeleton__row {
    height: 12px;
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--triarch-text-soft) 16%, transparent);
}
.ta-skeleton__row--short {
    width: 60%;
}
.ta-skeleton__row--medium {
    width: 78%;
}
@media (prefers-reduced-motion: no-preference) {
    .ta-skeleton__row {
        animation: ta-skeleton-pulse 1.4s var(--ease-standard) infinite;
    }
}
@keyframes ta-skeleton-pulse {
    50% { opacity: 0.45; }
}

/* Timeline — history and activity, newest first. Stages in a sequence use .ta-step. */
.ta-timeline {
    list-style: none;
    margin: 0;
    padding: 0 0 0 var(--space-4);
    border-left: 2px solid var(--triarch-border);
    display: grid;
    gap: var(--space-3);
}
.ta-timeline__item {
    position: relative;
    display: grid;
    gap: 1px;
}
.ta-timeline__item::before {
    content: "";
    position: absolute;
    left: calc(-1 * var(--space-4) - 6px);   /* centres the 10px dot on the 2px rail */
    top: 5px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--triarch-outline);
    box-shadow: 0 0 0 3px var(--triarch-surface);
}
.ta-timeline__item--current::before {
    background: var(--triarch-action);
}
.ta-timeline__title {
    font-size: 13px;
    font-weight: 600;
    color: var(--triarch-text);
}
.ta-timeline__meta {
    font-size: 12px;
    color: var(--triarch-text-soft);
}

/* Empty state, one-line size — inside a card or a list, where the full centred block is too much. */
.ta-empty-state--inline {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 0;
    text-align: left;
    font-size: 13px;
    color: var(--triarch-text-soft);
}

/* Save indicator — the quiet "Saved / Saving… / Offline" pill beside a work surface's toolbar.
   Script toggles .is-visible and one state class; the page only places it (width, margin). */
.ta-save-status {
    padding: 2px 8px;
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--triarch-text-soft);
    font-size: 11px;
    font-weight: 600;
    line-height: 1.3;
    letter-spacing: 0.02em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    opacity: 0;
    pointer-events: none;
    transition:
        opacity 0.3s ease-in-out,
        background-color 0.25s ease-in-out,
        border-color 0.25s ease-in-out,
        color 0.25s ease-in-out;
}
.ta-save-status.is-visible {
    opacity: 1;
    pointer-events: auto;
}
.ta-save-status.is-pending {
    background: var(--triarch-surface-dim);
    border-color: var(--triarch-border);
}
.ta-save-status.is-saving {
    color: var(--triarch-neutral-fg);
    background: var(--triarch-neutral-bg);
    border-color: color-mix(in srgb, var(--triarch-neutral-fg) 25%, transparent);
}
.ta-save-status.is-saved {
    color: var(--triarch-success-fg);
    background: var(--triarch-success-bg);
    border-color: color-mix(in srgb, var(--triarch-success-fg) 25%, transparent);
}
.ta-save-status.is-offline,
.ta-save-status.is-error {
    color: var(--triarch-warning-fg);
    background: var(--triarch-warning-bg);
    border-color: color-mix(in srgb, var(--triarch-warning-fg) 30%, transparent);
}
/* An error can be clicked to retry. */
.ta-save-status.is-error {
    cursor: pointer;
}
.ta-save-status.is-error:hover,
.ta-save-status.is-error:focus-visible {
    background: color-mix(in srgb, var(--triarch-warning-fg) 18%, transparent);
    border-color: color-mix(in srgb, var(--triarch-warning-fg) 45%, transparent);
}
.ta-save-status.is-error:focus-visible {
    outline: 2px solid var(--triarch-focus);
    outline-offset: 2px;
}
