/* ============================================================================
 * ARGUS OPS — operations console
 *
 * Pure black & white, monospace, dense data. 1px borders. Two-color status:
 * white-on-black for OK, black-on-white inverted block for errors.
 *
 * MOTION: tasteful and intentful — fast page transitions (180ms), scan-line
 * text reveal on page entry, drawer slide from right, micro-press on
 * buttons, pulsing live dots. Polled re-renders DO NOT re-animate; only
 * real navigations (init + hashchange) trigger entry motion. All motion
 * respects prefers-reduced-motion. See the MOTION section near the bottom.
 * ============================================================================ */

/* ============================================================================
 * THEME TOKENS — light / dark.
 *
 * Dark is the default (the original pure-B&W console look, preserved). Light is
 * an Anthropic-style warm off-white with a SPARING deep-maroon accent.
 *
 * Tokens live on :root so they resolve for both #argus-ops-root AND the modals
 * that append to <body> (confirm / operator-key / idle overlays). Defining
 * --ao-* on :root is inert for the embedded portal — its CSS never reads them.
 *
 * The light palette is applied by adding `ao-theme-light` to <body>, and only in
 * standalone mode (argus-ops.js gates on body.ao-standalone), so the
 * portal-embedded console keeps the original dark look.
 * See .ayan/argus-ops-light-mode.md for the full spec.
 * ============================================================================ */
:root {
    /* ========================================================================
     * ARGUS Ops — GRAPHITE dark theme (dark-only, 2026-08-12).
     * A deliberate light-grey/graphite base, NOT near-black: softer on the eyes
     * and less harsh than the old #1d1d1d + pure-white inversion. Everything is
     * token-driven, so changing these values re-skins the whole console with no
     * component or logic change. The light theme below is neutralised to these
     * same values so the console is dark-only.
     * ==================================================================== */
    /* surfaces — graphite, stepped for elevation */
    --ao-bg: #2b2b30;
    --ao-surface: #323238;
    --ao-surface-2: #3a3a41;
    --ao-hover: #3d3d45;
    --ao-overlay: rgba(18, 18, 21, 0.72);
    /* ── TYPE SCALE (2026-08-15) ──────────────────────────────────────────
     * Before this, the console carried **683 raw px font-sizes across 13
     * distinct values** (9,10,11,12,13,14,15,16,18,20,22,26,30,40) — four of
     * them inside a 3px band. That is accretion, not a scale, and it is the
     * single biggest reason the console read as unconsidered no matter how the
     * colours were tuned.
     *
     * Nine steps. Every call site now references a token, so retuning the
     * console's density is a change HERE and nowhere else. The one-off sizes
     * (9, 14, 16, 20, 26) collapsed into their nearest step; nothing moved more
     * than 4px, and **nothing is below 10px any more** — 9px was used for
     * uppercase micro-labels, which is precisely where it was least readable. */
    --ao-fs-label: 10px; /* uppercase micro-labels, column heads, meta */
    --ao-fs-meta: 11px; /* secondary text, table cells, captions */
    --ao-fs-body: 12px; /* the default */
    --ao-fs-strong: 13px; /* emphasis, lead lines */
    --ao-fs-title: 15px; /* card and section titles */
    --ao-fs-h2: 18px;
    --ao-fs-h1: 22px;
    --ao-fs-num: 30px; /* a metric meant to be read across the room */
    --ao-fs-hero: 40px; /* the single Lighthouse headline score */

    /* ── RADIUS (2026-08-15) ──────────────────────────────────────────────
     * TEN radii were in use (1,2,3,4,5,6,7,8,10,12) while ARGUS_OPS_DESIGN.md
     * claimed a single "8px radius" vocabulary — the doc described an intent
     * the CSS had long drifted from. Four steps, and the doc now matches. */
    --ao-r-sm: 4px; /* chips, small controls */
    --ao-r-md: 8px; /* buttons, inputs — the workhorse */
    --ao-r-lg: 10px; /* cards, panels */
    /* ⛔ Circles only: status dots, avatars, spinners, a switch's track, a
     * numbered badge on a square. Never a button, chip, tag or bar. */
    --ao-r-pill: 999px;
    /* Design system v2 (2026-09-23 rehaul): the Team page's card radius,
     * promoted so every tab can use it. */
    --ao-r-xl: 16px; /* KPI cards, section cards */
    /* NO PILLS (owner, 2026-09-24: "hate this bubble shit, wipe it from
     * everywhere"). The portal's two shapes (--kit-r-ctl / --kit-r-tag, PR
     * #3201), so Ops and the portal match: one decision, two radii.
     *   --ao-r-ctl  buttons, filters, tabs, segmented bars, search, inputs
     *   --ao-r-tag  status tags, deltas, ranks, key caps
     * pill-buttons.contract.test.js pins both values. Two more, 2026-09-25:
     *   --ao-r-table  a table's frame: the portal's ArgusTable (12px)
     *   --ao-r-bar    data bars, meters and tracks (a 5-12px bar at 6px drew
     *                 as a capsule: square ends, never a pill) */
    --ao-r-ctl: 8px;
    --ao-r-tag: 6px;
    --ao-r-table: 12px;
    --ao-r-bar: 2px;

    /* text — soft white, never pure #fff */
    --ao-fg: #f1f1f4;
    --ao-fg-dim: #c4c4cc;
    --ao-fg-mute: #8e8e99;
    /* lines — grey, not the old harsh white */
    --ao-border: #4b4b54;
    --ao-border-soft: #3b3b43;
    --ao-border-faint: #35353c;
    /* accent — a soft light-grey inversion for buttons; brand maroon-rose for
     * links / emphasis (the leaderboard carries the vivid colour) */
    --ao-accent: #e8e8ee;
    --ao-accent-fg: #1e1e22;
    --ao-accent-hover: #f6f6fa;
    --ao-accent-line: #cf8f8f;
    /* neutral inversion — headers / value cells. A raised grey bar, NOT a white
     * block (the single biggest de-harshing win across every table + card). */
    --ao-ink: #43434c;
    --ao-ink-fg: #f1f1f4;
    /* selected nav row. Deliberately LIGHTER than --ao-hover (#3d3d45): the two
     * must not collide, or "which page am I on" becomes unreadable. 1.58:1
     * against hover and 2.07:1 against the rail ground — de-harshed from the old
     * near-white slab (11.5:1) without erasing the state. */
    --ao-rail-active: #5a5a66;
    /* focus ring — soft maroon-rose */
    --ao-focus: rgba(207, 143, 143, 0.55);
    --ao-focus-glow: rgba(207, 143, 143, 0.14);
    /* primary CTA — Amazon cart-gold, the console's single loud "do this" fill.
     * Used ONLY on .ao-btn.is-primary (confirm-modal primary, SAVE, PROMOTE, ARM)
     * so the boldness lands in one place amid the graphite. Retune here only. */
    --ao-cta: #ffd814;
    --ao-cta-hover: #f7ca00;
    --ao-cta-active: #f0c200;
    --ao-cta-border: #f7ca00;
    --ao-cta-fg: #0f1111;
    --ao-cta-focus: rgba(255, 216, 20, 0.4);
    /* status */
    --ao-ok: #4ade80;
    --ao-ok-text: #9fdf9f;
    --ao-ok-soft: #16201a;
    --ao-ok-border: rgba(134, 239, 172, 0.4);
    --ao-warn: #fbbf24;
    --ao-warn-text: #ff9f66;
    --ao-warn-strong: #ff8800;
    --ao-warn-border: rgba(252, 211, 77, 0.4);
    --ao-err: #fca5a5;
    --ao-err-strong: #ff6666;
    --ao-err-soft: rgba(239, 68, 68, 0.08);
    --ao-err-border: rgba(239, 68, 68, 0.25);
    --ao-err-border-strong: rgba(239, 68, 68, 0.45);
    --ao-info: #93c5fd;
    --ao-info-soft: rgba(96, 165, 250, 0.15);
    --ao-info-border: rgba(96, 165, 250, 0.4);
    /* tints + shadow */
    --ao-tint: rgba(255, 255, 255, 0.025);
    --ao-tint-2: rgba(255, 255, 255, 0.05);
    --ao-tint-line: rgba(255, 255, 255, 0.08);
    --ao-tint-strong: rgba(255, 255, 255, 0.16);
    --ao-shadow: rgba(0, 0, 0, 0.6);

    /* ── TYPEFACE (2026-08-22) ────────────────────────────────────────────
     * The console used to set `#argus-ops-root *` in a monospace stack — every
     * nav item, button, page title and sentence in the browser's <pre> face, at
     * one size. That, more than any colour, is why it read as "basic plain text
     * or html": a document, not a product.
     *
     * Inter is the ARGUS brand sans (docs/ARGUS_BRAND.md); JetBrains Mono is the
     * brand mono. Mono is now opt-in via `.ao-mono` / code / kbd / numeric
     * cells, which is what mono is FOR — aligning digits and ids, not prose.
     *
     * ⛔ --ao-mono WAS REFERENCED THREE TIMES AND DEFINED ZERO TIMES
     * (argus-ops.css .ao-mono, argus-ops.js x2), so every one of those call
     * sites silently inherited whatever the cascade gave it. Defined here now. */
    --ao-font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --ao-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

    /* ── SPACE (4px base, 2026-08-22) ─────────────────────────────────────
     * There were ZERO spacing tokens, against 69 distinct inline padding values
     * and 51 margin values. Same ladder as --crm-s-* so an ops page and a
     * customer page sit on the same rhythm. */
    --ao-s-1: 4px;
    --ao-s-2: 8px;
    --ao-s-3: 12px;
    --ao-s-4: 16px;
    --ao-s-5: 20px;
    --ao-s-6: 24px;
    --ao-s-7: 32px;
    --ao-s-8: 40px;

    /* ── PAGE-LEVEL TYPE (2026-08-22) ─────────────────────────────────────
     * The 9-step scale added 2026-08-15 tops out at 22px and NOTHING used it for
     * a page title: `.ao-page-title` declared no font-size at all and inherited
     * 13px, so every page opened with a heading the size of body text. 93% of
     * type references sat in a 10-13px band. These two steps give a page a top. */
    --ao-fs-page: 28px; /* the page title, once per page */
    --ao-fs-h: 20px; /* section headings inside a page */

    /* ── ELEVATION (2026-08-22) ───────────────────────────────────────────
     * 27 hand-tuned box-shadows existed against a single shadow COLOUR token and
     * no ramp, and `.ao-card` carried no shadow at all — cards were flat
     * rectangles separated from the page by a 1.06:1 luminance step. Mirrors the
     * --crm-shadow-* ramp. */
    --ao-elev-1: 0 1px 2px rgba(0, 0, 0, 0.28);
    --ao-elev-2: 0 2px 6px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.24);
    --ao-elev-3: 0 8px 24px rgba(0, 0, 0, 0.36), 0 2px 6px rgba(0, 0, 0, 0.24);

    /* ── STATUS, MADE SYMMETRIC (2026-08-22) ──────────────────────────────
     * The four status families each had a DIFFERENT shape: ok had -text but no
     * -strong, warn had -strong but no -soft, err had -soft but no -text, info
     * had neither. No generic "tinted status" rule could be written against
     * them, which is exactly why fourteen separate badge builders exist in the
     * JS. Every family now has the same {fg,bg,bd} trio. The legacy names above
     * are kept so the ~200 existing references keep resolving. */
    --ao-ok-fg: #9fdf9f;
    --ao-ok-bg: rgba(74, 222, 128, 0.12);
    --ao-ok-bd: rgba(134, 239, 172, 0.4);
    --ao-warn-fg: #fbbf24;
    --ao-warn-bg: rgba(251, 191, 36, 0.12);
    --ao-warn-bd: rgba(252, 211, 77, 0.4);
    --ao-err-fg: #fca5a5;
    --ao-err-bg: rgba(239, 68, 68, 0.1);
    --ao-err-bd: rgba(239, 68, 68, 0.35);
    --ao-info-fg: #93c5fd;
    --ao-info-bg: rgba(96, 165, 250, 0.12);
    --ao-info-bd: rgba(96, 165, 250, 0.4);

    /* ── LAYERING (2026-08-22) ────────────────────────────────────────────
     * 13 raw z-index literals ranging 1 to 99999, so "what sits above what" was
     * decided by whoever typed the biggest number last. */
    --ao-z-base: 1;
    --ao-z-sticky: 10;
    --ao-z-overlay: 100;
    --ao-z-modal: 1000;
    --ao-z-toast: 2000;

    /* ── TEAM PAGE (#/team, 2026-09-22) ───────────────────────────────────
     * Declared here, with every other colour, rather than in the Team block
     * at the bottom: the component rules down there stay hex-free, and so
     * does every per-module block the contract tests sweep to end-of-file. */
    --ao-tm-r: 16px;
    /* Medals as tokens. The Overview leaderboard's .aolb-rank.g/.s/.b carry
     * raw hexes in the rule; these are the tokenised version, not a copy. */
    --ao-tm-gold: #e3c16f;
    --ao-tm-silver: #c8cdd6;
    --ao-tm-bronze: #d39468;
    /* One muted accent per team KPI: icon tile + sparkline only. */
    --ao-tm-k-commits: #6fdcc6;
    --ao-tm-k-prs: #aea2f7;
    --ao-tm-k-lines: #f5b37a;
    --ao-tm-k-value: #f2cf63;
    --ao-tm-k-schema: #8ec0f7;
    --ao-tm-k-ops: #ee9fd0;
    /* The generic KPI palette for every other tab (design system v2). SAME
     * values as the six --ao-tm-k-* above, in the same order, so a Team card
     * and a Fleet card with the same accent are the same colour. Literals on
     * purpose: nothing below the INVENTORY banner may carry a hex, so this is
     * the only place a page's accent can be declared. Icon tile + sparkline
     * only — text never wears one. */
    --ao-k-1: #6fdcc6;
    --ao-k-2: #aea2f7;
    --ao-k-3: #f5b37a;
    --ao-k-4: #f2cf63;
    --ao-k-5: #8ec0f7;
    --ao-k-6: #ee9fd0;
    /* Entrance timing for the generic .ao-in rise (see MOTION): the Team
     * page's 560ms / 40ms stagger, named so every tab moves the same way. */
    --ao-enter: 560ms;
    --ao-stagger: 40ms;
    /* The streak flame. Deliberately NOT --ao-warn-*: a ten-day streak is
     * not a warning, and status colours stay reserved for status. */
    --ao-tm-flame: #f6a560;
    /* Print (the Compute report prints black on white whatever the theme). */
    --ao-print-paper: #fff;
    --ao-print-ink: #111;
    --ao-print-mute: #444;
    --ao-print-rule: #bbb;
    --ao-print-rule-soft: #ddd;
    --ao-print-callout: #f4f4f4;
}

/* ⛔ PIN THE CRM TOKENS DARK INSIDE THE CONSOLE.
 * css/argus-crm.css flips its whole token set on `body.light-mode`, which the
 * portal sets from the customer theme toggle (main.js). The ops console is
 * dark-only by decision (#1624, 2026-08-12), so without this the EMBEDDED
 * console would render crm-* components in light surfaces on light text inside
 * a graphite shell the moment an operator put the portal in light mode. The
 * standalone build never sets the class, so this is inert there.
 *
 * Re-stating the dark values (rather than `color-scheme` or a filter) is the
 * only approach that survives a token being added to the light block later:
 * anything we do not re-state simply keeps its :root dark value. */
body.light-mode #argus-ops-root,
body.light-mode .ao-arm-modal-overlay,
body.light-mode .ao-modal-overlay,
body.light-mode .ao-confirm-overlay {
    --crm-surface: #232323;
    --crm-surface-raised: #2b2b30;
    --crm-surface-sunken: #1f1f22;
    --crm-border: rgba(255, 255, 255, 0.1);
    --crm-border-strong: rgba(255, 255, 255, 0.18);
    --crm-fg: #f1f1f4;
    --crm-fg-muted: rgba(241, 241, 244, 0.62);
    --crm-fg-dim: rgba(241, 241, 244, 0.45);
    --crm-shadow-1: var(--ao-elev-1);
    --crm-shadow-2: var(--ao-elev-2);
    --crm-shadow-3: var(--ao-elev-3);
}

/* ARGUS Ops is DARK-ONLY (graphite) as of 2026-08-12. The old light palette is
 * neutralised: the `ao-theme-light` class is left in place (so no JS that adds/
 * removes it breaks) but overrides nothing, so a persisted "light" preference
 * simply resolves to the :root graphite theme. The theme toggles are hidden
 * below. To restore a light theme, re-populate these tokens. */
body.ao-theme-light {
    /* intentionally empty — inherits the graphite :root theme */
}

/* ── Brand icon (the Argus aperture mark) + theme toggle in the top bar ──── */
.ao-top-brand {
    display: flex;
    align-items: center;
    gap: 8px;
}
.ao-top-icon {
    height: 20px;
    width: 20px;
    object-fit: contain;
    display: block;
    flex-shrink: 0;
}
.ao-theme-toggle {
    color: var(--ao-fg);
    background: transparent;
    border: 1px solid var(--ao-border);
    padding: 2px 8px;
    cursor: pointer;
    font-family: inherit;
    font-size: inherit;
    letter-spacing: 0.04em;
}
.ao-theme-toggle:hover {
    background: var(--ao-ink);
    color: var(--ao-ink-fg);
}

/* Segmented light/dark control inside the Settings panel. */
.ao-theme-seg {
    display: inline-flex;
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-sm);
    overflow: hidden;
}
.ao-theme-seg-btn {
    background: transparent;
    color: var(--ao-fg);
    border: none;
    border-right: 1px solid var(--ao-border);
    padding: 5px 16px;
    cursor: pointer;
    font-family: inherit;
    font-size: var(--ao-fs-meta);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-theme-seg-btn:last-child {
    border-right: none;
}
.ao-theme-seg-btn:hover:not(.is-active) {
    background: var(--ao-hover);
}
.ao-theme-seg-btn.is-active {
    background: var(--ao-accent);
    color: var(--ao-accent-fg);
}

#argus-ops-root,
#argus-ops-root * {
    box-sizing: border-box;
}

/* ⛔ DO NOT PUT font-family BACK ON THE `*` SELECTOR.
 * It used to force a monospace stack onto every descendant — nav items,
 * buttons, page titles, prose, all of it. Combined with 93% of type sitting in
 * a 10-13px band, that is the measured reason the console read as "basic plain
 * text or html" rather than as a product. Inter inherits from the root; mono is
 * opt-in below, on the things mono is actually for. */
#argus-ops-root {
    background: var(--ao-bg);
    color: var(--ao-fg);
    min-height: 100vh;
    font-family: var(--ao-font-sans);
    font-size: var(--ao-fs-strong);
    line-height: 1.45;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Form controls do not inherit the document font on their own. */
#argus-ops-root input,
#argus-ops-root select,
#argus-ops-root textarea,
#argus-ops-root button {
    font-family: inherit;
}

/* ⛔ UNDO THE PORTAL'S 44px BUTTON BOX, ONCE, FOR THE WHOLE CONSOLE.
 * css/main.css gives every `button`, `[role='button']` and `a[tabindex='0']` a
 * 44×44 minimum (its WCAG touch-target rule). Only the EMBEDDED console loads
 * main.css, so every Ops control that is not .ao-btn — segmented tabs, chips,
 * the "?" purpose toggle (height:15px, silently beaten by min-height) — rendered
 * as a tall rectangle inside the portal and as designed in the standalone build.
 *
 * :where() keeps these at the SAME specificity as main.css's rules — (0,0,1),
 * (0,1,0) and (0,1,1) — so they win on load order (this sheet is lazy-loaded
 * for the module, after main.css) and lose to every class rule in this file.
 * ⛔ Keep this ABOVE `.ao-btn`: `[role='button']` ties with a single class, so
 * placed after .ao-btn it would erase the pill's 28px floor. Families that
 * want a floor (.ao-btn 28px, .ao-btn-sm 24px, the segment buttons) set it
 * themselves, as a literal px. */
:where(#argus-ops-root) button {
    min-height: auto;
    min-width: auto;
}
:where(#argus-ops-root) [role='button'] {
    min-height: auto;
    min-width: auto;
}
:where(#argus-ops-root) a[tabindex='0'] {
    min-height: auto;
    min-width: auto;
}

/* ── MONO, DELIBERATELY ──────────────────────────────────────────────────
 * Tabular data, identifiers, log output, keys. Anywhere digits must line up
 * column to column or an id must be copyable without ambiguity. `tabular-nums`
 * is the half of this that people forget: proportional digits make a column of
 * numbers ragged even in a monospace face when the face is not actually fixed. */
#argus-ops-root .ao-mono,
#argus-ops-root code,
#argus-ops-root pre,
#argus-ops-root kbd,
#argus-ops-root samp,
#argus-ops-root [data-mono],
#argus-ops-root .ao-num,
#argus-ops-root .ao-table td.ao-num,
#argus-ops-root .ao-stat-num {
    font-family: var(--ao-mono);
    font-variant-numeric: tabular-nums;
}
/* A number column's HEADER is a label like its neighbours, not a number:
 * aoTable tags a right-aligned th .ao-num, which the rule above would set in
 * mono. One header row, one face. */
#argus-ops-root .ao-table th.ao-num {
    font-family: inherit;
}

/* No universal color rule — let foreground inherit naturally so class-level
 * overrides (active rail item, error box, white-bg table headers) win on
 * specificity. The previous `* { color: ... }` rule beat them. */

/* Global keyboard focus ring (a11y). Before this rule the console had NO
 * :focus-visible style anywhere and `.ao-onb-input:focus { outline:none }`
 * actively removed the only ring — keyboard users got no focus indicator on
 * any tab/control. A crisp white ring (high contrast on the B&W surface) is
 * applied only on keyboard focus (:focus-visible), so mouse clicks don't show
 * a ring. */
#argus-ops-root :focus-visible {
    outline: 2px solid var(--ao-accent-line);
    outline-offset: 2px;
}

/* SCROLL LOCK (standalone host only).
 * ops.useargus.co renders the whole console inside a single 100vh shell whose
 * panes scroll internally — the document itself must NEVER scroll. Two things
 * made the page feel loose ("scroll up past the top bar", elastic bounce /
 * jitter): (1) the document had no overflow lock, so the trackpad overscroll
 * gesture rubber-banded the whole viewport even though nothing was scrollable,
 * and (2) inner panes chained their overscroll up to the document. We lock BOTH
 * <html> and <body> (overscroll-behavior on the viewport is read from the root
 * element, so <html> must carry it) and forbid document overflow. Result: a
 * solid, planted scroll like LYRA / the LP — inner panes still scroll, the page
 * never bounces. Scoped to .ao-standalone via :has() so the portal-embedded
 * module (PROXY_MODE, no .ao-standalone body) is completely untouched. */
html:has(body.ao-standalone) {
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
}
body.ao-standalone {
    margin: 0;
    background: var(--ao-bg);
    /* Toasts, confirms, pickers and drawers append to <body>, outside
     * #argus-ops-root: without this they drew in the browser's serif. */
    font-family: var(--ao-font-sans);
    -webkit-font-smoothing: antialiased;
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
}
/* The standalone root is exactly the viewport — fixed (not min-) height so it
 * can never grow a hair past 100vh and reintroduce a document scrollbar. */
body.ao-standalone #argus-ops-root {
    height: 100vh;
    min-height: 100vh;
    overflow: hidden;
}

/* ── Layout ─────────────────────────────────────────────────────────── */
.ao-shell {
    display: grid;
    grid-template-columns: 220px 1fr;
    grid-template-rows: 40px 1fr;
    grid-template-areas:
        'top top'
        'rail main';
    height: 100vh;
}

/* Every internal scroll region contains its own overscroll so a gesture that
 * reaches a pane's top/bottom does NOT chain up to (and bounce) the document.
 * Combined with the standalone document lock above this removes the rubber-band
 * jitter at every boundary. Unscoped on purpose — in portal-embedded mode it
 * just stops the ops panes from scroll-chaining into the host page, which is
 * the desired behaviour there too. */
.ao-rail,
.ao-main,
.ao-modal-list,
.ao-tselect-menu,
.ao-settings,
.ao-records-left,
.ao-records-right > #ao-records-body,
.ao-drawer,
.ao-help,
.ao-breakdown {
    overscroll-behavior: contain;
}
.ao-top {
    grid-area: top;
    border-bottom: 1px solid var(--ao-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 12px;
}
.ao-top-title {
    font-weight: 700;
    letter-spacing: 0.08em;
}
.ao-top-actions {
    display: flex;
    gap: 8px;
    font-size: var(--ao-fs-meta);
    align-items: center;
}
.ao-top-tenant {
    display: flex;
    align-items: center;
    gap: 6px;
}
.ao-top-tenant-label {
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    opacity: 0.6;
}
.ao-top-tenant .ao-picker-trigger {
    border-radius: var(--ao-r-ctl);
    padding: 4px 12px;
}
/* ── Top-bar identity control ───────────────────────────────────────── */
.ao-top-identity {
    display: flex;
    align-items: center;
    gap: 6px;
}
.ao-top-identity-chip {
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    border: 1px solid var(--ao-border-soft) !important;
    color: var(--ao-fg-dim) !important;
}
/* Design system v2 (2026-09-23): the top bar's controls wear the .ao-btn
 * look — they were bare 20px boxes on every page including Team. The control
 * radius and a literal px floor (this is a family in
 * pill-buttons.contract.test.js); never a pill (2026-09-24). Hover lifts to
 * --ao-hover like .ao-btn; it used to flip to a dark ink fill that read as a
 * selection. */
.ao-top-actions a,
.ao-top-actions button {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    box-shadow: inset 0 1px 0 var(--ao-tint);
    color: var(--ao-fg);
    cursor: pointer;
    font-family: inherit;
    font-size: inherit;
    font-weight: 600;
    letter-spacing: 0.04em;
    min-height: 26px;
    min-width: auto;
    padding: 4px 11px;
    text-decoration: none;
}
.ao-top-actions a:focus-visible,
.ao-top-actions button:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-top-actions button:hover,
.ao-top-actions a:hover {
    background: var(--ao-hover);
    color: var(--ao-fg);
}

/* Live-indicator pill (Phase 3b) — black-and-white aesthetic, leading
   bullet glyph in a state-specific color. The text is always white on
   black to keep the rest of the UI cohesive; only the dot encodes state. */
.ao-stream-indicator {
    display: inline-flex;
    align-items: center;
    padding: 4px 12px;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    min-height: 26px;
    box-sizing: border-box;
    font-family: inherit;
    font-size: inherit;
    letter-spacing: 0.06em;
    user-select: none;
}
.ao-stream-indicator::before {
    content: '\2022'; /* • */
    margin-right: 6px;
    font-size: var(--ao-fs-title);
    line-height: 0;
}
.ao-stream-indicator.is-open::before {
    color: var(--ao-ok);
}
.ao-stream-indicator.is-connecting::before {
    color: var(--ao-warn);
}
.ao-stream-indicator.is-closed::before {
    color: var(--ao-fg-mute);
}

/* Idle warning overlay (Phase 4) — fixed dialog at viewport center.
   Black-and-white aesthetic to match the rest of argus-ops. */
.ao-idle-overlay {
    position: fixed;
    inset: 0;
    background: var(--ao-overlay);
    z-index: 10000;
    display: flex;
    align-items: center;
    justify-content: center;
}
.ao-idle-dialog {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border);
    padding: 24px 32px;
    min-width: 320px;
    max-width: 480px;
    text-align: center;
    font-family: inherit;
}
.ao-idle-title {
    font-weight: 700;
    letter-spacing: 0.08em;
    margin-bottom: 12px;
}
.ao-idle-msg {
    margin-bottom: 20px;
    color: var(--ao-fg-dim);
}
.ao-idle-count {
    font-weight: 700;
    color: var(--ao-warn);
}
.ao-idle-actions {
    display: flex;
    gap: 12px;
    justify-content: center;
}
/* A pill with a literal 32px floor (design system v2; pinned by
 * pill-buttons.contract.test.js). The idle modal is appended to <body>,
 * OUTSIDE #argus-ops-root, so the console-wide reset of main.css's 44px box
 * does not reach it — this floor is the only thing that does. */
.ao-idle-btn {
    background: var(--ao-accent);
    color: var(--ao-accent-fg);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-ctl);
    min-height: 32px;
    min-width: auto;
    padding: 6px 16px;
    cursor: pointer;
    font-family: inherit;
    font-size: var(--ao-fs-body);
    letter-spacing: 0.06em;
}
.ao-idle-btn:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-idle-btn:hover {
    background: var(--ao-accent-hover);
}
.ao-idle-btn-secondary {
    background: transparent;
    color: var(--ao-fg);
}
.ao-idle-btn-secondary:hover {
    background: var(--ao-ink);
    color: var(--ao-ink-fg);
}

.ao-rail {
    grid-area: rail;
    border-right: 1px solid var(--ao-border);
    overflow-y: auto;
}
/* ── Rail modules ────────────────────────────────────────────────────────
 * The rail groups its 39 destinations into nine collapsible modules. Collapsed
 * is the resting state, which is the entire point: every hint used to be on
 * screen at once, so the nav was a wall of body text before an operator read a
 * single page. */
.ao-rail-group {
    border-bottom: 1px solid var(--ao-border-soft);
}
.ao-rail-modhead {
    align-items: center;
    cursor: pointer;
    display: flex;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    gap: var(--ao-s-2);
    letter-spacing: 0.06em;
    list-style: none;
    padding: 10px var(--ao-s-3);
    text-transform: uppercase;
    user-select: none;
}
/* Safari/Chrome draw their own triangle through a shadow pseudo-element that
 * `list-style: none` alone does not reach. */
.ao-rail-modhead::-webkit-details-marker {
    display: none;
}
.ao-rail-modhead:hover {
    background: var(--ao-hover);
}
.ao-rail-modhead:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: -2px;
}
/* The disclosure chevron, drawn rather than typed: a text arrow inherits the
 * font and jumps between glyph widths when the module opens. */
.ao-rail-modhead::before {
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    content: '';
    flex: none;
    height: 5px;
    opacity: 0.55;
    transform: rotate(-45deg);
    transition: transform var(--ao-base) var(--ao-ease);
    width: 5px;
}
.ao-rail-group[open] > .ao-rail-modhead::before {
    transform: rotate(45deg);
}
.ao-rail-modlabel {
    flex: 1 1 auto;
    min-width: 0;
}
/* How much is behind a closed module. Without it a collapsed rail implies the
 * console is smaller than it is. */
.ao-rail-modcount {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-tag);
    flex: none;
    font-size: var(--ao-fs-label);
    font-weight: 500;
    letter-spacing: 0;
    opacity: 0.7;
    padding: 1px 7px;
}
.ao-rail-modbody {
    padding-bottom: var(--ao-s-1);
}

.ao-rail-item {
    display: block;
    padding: 8px 12px 8px var(--ao-s-5);
    color: var(--ao-fg);
    text-decoration: none;
    cursor: pointer;
}
.ao-rail-item:hover {
    background: var(--ao-hover);
}
/* Active nav item — a raised graphite row, NOT the near-white inversion it used
 * to be. A full-width slab of --ao-accent was the last piece of the old harsh
 * light-on-dark chrome (the same problem --ao-ink solved for table headers), and
 * at rail scale it shouted louder than anything else on the page.
 * ⛔ De-harshing must not erase the state. --ao-ink sits 1.10:1 from --ao-hover,
 * i.e. an active row would have been indistinguishable from any hovered one, so
 * the selected page needs its OWN token. Three signals separate them now:
 * marker width (4px vs 2px), weight, and background (1.58:1). The marker COLOUR
 * also differs but does not count — brand rose against neutral mute is 1.23:1,
 * so it vanishes in greyscale or for a red-deficient viewer; width is what
 * actually carries it. */
.ao-rail-item.is-active {
    background: var(--ao-rail-active);
    color: var(--ao-fg);
    font-weight: 600;
    padding-left: 24px;
}
.ao-rail-item .ao-rail-label {
    display: block;
}
.ao-rail-item .ao-rail-hint {
    display: block;
    font-size: var(--ao-fs-label);
    opacity: 0.6;
    margin-top: 2px;
}

.ao-main {
    grid-area: main;
    /* min-width 0: a grid item's automatic minimum is its content, so one
     * wide table used to widen the 1fr track and push the whole page past
     * the viewport. The table's own wrap scrolls instead (aoScrollWrap). */
    min-width: 0;
    overflow-y: auto;
    padding: 0;
}
/* The rail's menu button (renderShell) — hidden until the phone layout.
 * Two classes: .ao-btn (later in the file) sets display too. */
.ao-top .ao-top-menu {
    display: none;
}

/* ── Phone layout (design system v2, 2026-09-23) ─────────────────────────
 * ⛔ The 220px rail never collapsed: at 390px it left the page 170px, and
 * SIGN OUT / HELP / SETTINGS sat off-screen where nothing could reach them.
 * Under 760px the rail is an off-canvas drawer under the top bar, opened by
 * the menu button (.ao-shell.is-rail-open, toggled in renderShell and closed
 * on every navigation by highlightRail). The top bar's controls scroll
 * sideways rather than wrap, and the two labels that only restate what the
 * control says (TENANT, the signed-in email) give their width back. The
 * drawer's slide is transform-only; reduced motion drops it in the
 * primitives' reduced-motion block. */
@media (max-width: 760px) {
    .ao-shell {
        grid-template-areas:
            'top'
            'main';
        grid-template-columns: 1fr;
    }
    .ao-top {
        gap: var(--ao-s-2);
        min-width: 0;
        padding: 0 8px;
    }
    .ao-top-brand {
        flex: none;
    }
    /* The mark stays; the wordmark gives its width to the controls. */
    .ao-top-title {
        display: none;
    }
    /* !important only to beat the picker's inline 180px floor (renderShell
     * passes minWidth for the desktop bar). */
    .ao-top-tenant .ao-picker-trigger {
        max-width: 132px;
        min-width: 0 !important;
    }
    .ao-top .ao-top-menu {
        display: inline-flex;
        flex: none;
    }
    .ao-rail {
        background: var(--ao-bg);
        bottom: 0;
        box-shadow: var(--ao-elev-3);
        grid-area: auto;
        left: 0;
        position: fixed;
        top: 40px;
        transform: translateX(-100%);
        transition: transform var(--ao-base) var(--ao-ease);
        width: min(84vw, 300px);
        z-index: 50;
    }
    .ao-shell.is-rail-open .ao-rail {
        transform: none;
    }
    /* The scrim behind the open drawer. It is the shell's own box, so a tap
     * on it lands on the shell and renderShell closes the drawer. */
    .ao-shell.is-rail-open::after {
        background: var(--ao-overlay);
        content: '';
        inset: 40px 0 0;
        position: fixed;
        z-index: 49;
    }
    .ao-top-actions {
        min-width: 0;
        overflow-x: auto;
        scrollbar-width: none;
    }
    .ao-top-actions::-webkit-scrollbar {
        display: none;
    }
    .ao-top-actions > * {
        flex: none;
    }
    .ao-top-tenant-label,
    .ao-top-identity-chip {
        display: none;
    }
    .ao-page-head,
    #ao-page-body {
        padding-left: var(--ao-s-4);
        padding-right: var(--ao-s-4);
    }
}

/* ── PAGE BODY ───────────────────────────────────────────────────────────
 * `#ao-page-body` is created 48 times in argus-ops.js and had NOT ONE CSS rule,
 * so every page invented its own gutter with an inline `padding:12px 16px` (or
 * forgot to, or faked it with `width:calc(100% - 32px)`). One rule here is the
 * page rhythm; the per-page strings can then go.
 *
 * max-width so a 32-inch monitor does not stretch a table to 3000px of
 * unreadable line length. It is a max, not a width: narrow screens are
 * unaffected. */
#ao-page-body {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    padding: var(--ao-s-4) var(--ao-s-5) var(--ao-s-8);
    max-width: 1440px;
}

/* ── Page header ────────────────────────────────────────────────────── */
/* isolation: the dot grid below sits at z-index -1 INSIDE the head, never
 * behind the page (design system v2). */
.ao-page-head {
    align-items: center;
    border-bottom: 1px solid var(--ao-border);
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--ao-s-3);
    isolation: isolate;
    padding: var(--ao-s-4) var(--ao-s-5);
}
/* The Team page's faint dot grid behind the title, on every page (design
 * system v2) — texture, not noise. head() is unchanged; this is CSS only, so
 * all 52 pages get it at once. The mask fades it out before the meta line. */
.ao-page-head::before {
    background-image: radial-gradient(circle, var(--ao-tint-strong) 1px, transparent 1.5px);
    background-size: 18px 18px;
    content: '';
    inset: 0;
    -webkit-mask-image: radial-gradient(ellipse 60% 160% at 0% 0%, black 0%, transparent 72%);
    mask-image: radial-gradient(ellipse 60% 160% at 0% 0%, black 0%, transparent 72%);
    pointer-events: none;
    position: absolute;
    z-index: -1;
}
.ao-page-titlerow {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3);
}
/* ⛔ THIS DECLARED NO font-size AND INHERITED 13px. An all-caps 13px string with
 * 0.08em tracking is a LABEL; it was doing the job of a page title on 44 pages.
 * A page needs a top to its hierarchy, and nothing else in the console competes
 * at this size, so one line here changes the whole console's read. Sentence
 * case, because 28px uppercase is shouting and tracking hurts at this size. */
.ao-page-title {
    font-size: var(--ao-fs-page);
    font-weight: 650;
    letter-spacing: -0.01em;
    line-height: 1.15;
    margin: 0;
    text-transform: none;
}
/* On a phone the title scales down and may break inside a long id, instead
 * of wrapping a tenant id onto four lines. */
@media (max-width: 760px) {
    .ao-page-title {
        font-size: clamp(20px, 6vw, 28px);
        overflow-wrap: anywhere;
    }
}
/* Section headings inside a page are aoSection (design system v2): one step
 * down from the title, one step up from card titles, so a page reads as
 * title > section > card. Its rules live with the v2 block and the Team
 * .ao-tm-h it shares; the old h3.ao-section-title had four users, all now
 * aoSection. */
.ao-page-meta {
    font-size: var(--ao-fs-meta);
    opacity: 0.7;
}
/* "What is this page for?" — the 37-word paragraph every page used to open
 * with, now one click away and remembered per page. Deliberately quiet: it is
 * an affordance, not a call to action. */
.ao-page-why {
    align-self: center;
    background: none;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: inherit;
    cursor: pointer;
    flex: none;
    font-size: var(--ao-fs-meta);
    height: 20px;
    line-height: 1;
    opacity: 0.6;
    padding: 0;
    width: 20px;
}
.ao-page-why:hover,
.ao-page-why:focus-visible {
    border-color: var(--ao-fg-mute);
    opacity: 1;
}
.ao-page-why[aria-expanded='true'] {
    background: var(--ao-tint-2);
    opacity: 0.85;
}
/* Full-width third line, so opening it pushes nothing sideways. */
.ao-page-purpose {
    flex-basis: 100%;
    font-size: var(--ao-fs-strong);
    line-height: 1.4;
    margin-top: 6px;
    max-width: 720px;
    opacity: 0.7;
}

/* ── Status dot ─────────────────────────────────────────────────────── */
/* Design system v2 (2026-09-23): a round dot in its status colour. It was
 * a white or hollow SQUARE from the black-and-white era — on Overview and
 * beside the signed-in email it read as a checkbox, and ok vs err was a fill
 * vs an outline at 8px. The class names are unchanged (tests read them). */
.ao-dot {
    border: 0;
    border-radius: 50%;
    box-sizing: border-box;
    display: inline-block;
    flex: none;
    height: 8px;
    margin-right: 6px;
    vertical-align: middle;
    width: 8px;
}
.ao-dot.ok {
    background: var(--ao-ok);
}
.ao-dot.warn {
    background: var(--ao-warn);
    animation: ao-pulse 1.4s linear infinite;
}
/* A halo, so down still reads for a red-deficient eye. */
.ao-dot.err {
    background: var(--ao-err-strong);
    box-shadow: 0 0 0 3px var(--ao-err-bg);
}
.ao-dot.idle {
    background: transparent;
    box-shadow: inset 0 0 0 1.5px var(--ao-fg-mute);
}
/* ⛔ UNMEASURED IS NOT IDLE AND IS NOT DOWN. `idle` says "deliberately off" and
   `err` says "we know it is broken"; this says "we could not tell", which is a
   third answer prompting a third action (go find out). It has to be visually
   distinct from both, or the distinction the code buys is thrown away at the
   last step — a dashed edge reads as provisional at dot scale. */
.ao-dot.unknown {
    background: transparent;
    border: 1px dashed var(--ao-fg-mute);
}
@keyframes ao-pulse {
    0%,
    100% {
        opacity: 1;
    }
    50% {
        opacity: 0.25;
    }
}

/* ── Tables (design system v2, 2026-09-23) ─────────────────────────────
 * The Team page's table voice for EVERY .ao-table at once — 33 tables, 8 of
 * them through aoTable — which is why this is CSS and not a JS migration: a
 * quiet header, roomier rows, faint row rules, and an accent tick on the
 * hovered row. Pages built to fit without a scroll opt into .is-dense, which
 * keeps the old 6px/10px rhythm (decision D4; the list is in
 * ARGUS_OPS_DESIGN.md "Design system v2"). border-collapse stays collapse:
 * `separate` brings back the UA's 2px cell spacing and breaks every row rule
 * into dashes. */
.ao-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--ao-fs-body);
}
/* Row lines are --ao-border-soft (2026-09-24): the old --ao-border-faint rule
 * sat within a shade of the page and the rows ran together ("it doesn't even
 * look like we have a table below"). */
.ao-table th,
.ao-table td {
    border-bottom: 1px solid var(--ao-border-soft);
    padding: 9px 12px;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 320px;
}
/* ⛔ OPAQUE, not transparent. The header is sticky, and inside a scrollMax
 * wrap a transparent header lets the rows scroll visibly through its labels.
 * On a table that sits straight on --ao-bg this shows as a light band — the
 * header, lighter than the ink bar it replaced, and read as one. */
.ao-table th {
    background: var(--ao-surface-2);
    border-bottom-color: var(--ao-border);
    /* --ao-fg-dim, not -mute: mute on the header's surface is about 3.5:1,
     * under the floor for 10px capitals. */
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    position: sticky;
    text-transform: uppercase;
    top: 0;
    z-index: 1;
}
.ao-table.is-dense th,
.ao-table.is-dense td {
    padding: 6px 10px;
}
/* ⛔ Inside a card the faint row rule (--ao-border-faint) is within a shade
 * of the card's own gradient, so the rows ran together — Overview's Service
 * health lost the dividers it had on the flat page. A light tint line reads
 * on any card surface. The header drops to the page ground so it sits IN the
 * card as a band rather than matching it. */
.ao-card .ao-table td,
.ao-table-wrap.is-card .ao-table td {
    border-bottom-color: var(--ao-border-soft);
}
.ao-card .ao-table th {
    background: var(--ao-bg);
}
/* Row hover highlights for SCANNING (legitimate on any dense table) — but the
 * cursor must not promise a click that does not exist. 21 tables are built here
 * and only 12 sites call makeRowClickable, so a blanket `cursor:pointer` told
 * operators that most rows open something. makeRowClickable already sets an
 * inline pointer on the <tr>, and `cursor` inherits, so genuinely clickable rows
 * still show it — with no rule here to fake it for the rest. */
.ao-table tr:hover td {
    background: var(--ao-hover);
}
/* The hovered (or keyboard-focused) row's accent tick. An inset shadow, not a
 * border, so the row never shifts 2px under the pointer. Group headers and
 * detail rows are not data rows and do not get one. */
.ao-table tbody tr:not(.ao-table-group):not(.ao-table-detail):hover > td:first-child,
.ao-table tbody tr[role='button']:focus-visible > td:first-child {
    box-shadow: inset 2px 0 0 var(--ao-accent-line);
}
.ao-table .ao-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* ── Cards (pipeline page) ─────────────────────────────────────────── */
.ao-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--ao-s-3);
}
/* An empty state inside a card shelf spans the shelf. As one grid cell it sat
 * 260px wide in the corner, reading as a card that failed to load. */
.ao-grid > .ao-empty,
.ao-card-grid > .ao-empty {
    grid-column: 1 / -1;
}
/* Cards are raised graphite panels now (part of the 2026-08-12 refresh): a full
 * soft border + radius + a one-step-lighter surface, instead of the old
 * seamless right/bottom-only grid seams. Purely cosmetic. */
/* A card carried NO shadow, so it was separated from the page by a 1.06:1
 * luminance step and a 1px line — which is to say, by almost nothing. Elevation
 * is what makes a surface read as a distinct object rather than as a boxed
 * paragraph. Padding moves 12/14 to the 4px ladder. */
/* Design system v2 (2026-09-23): the Team card — 16px radius, a top-lit
 * gradient, a hairline inset highlight over elev-1. */
.ao-card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    padding: var(--ao-s-4);
    transition:
        transform var(--ao-base) var(--ao-ease),
        box-shadow var(--ao-base) var(--ao-ease);
}
/* A card inside a card (a tab panel's card inside a page card) is a panel of
 * its parent, not a second object floating over it: stacked shadows read as
 * clutter, not depth. */
.ao-card .ao-card {
    box-shadow: none;
}
/* ⛔ The lift is for cards that ARE controls. A static card that moves under
 * the pointer promises a click it does not have. The border never changes on
 * hover — the lift and the shadow are the whole signal (the Team rule). */
a.ao-card {
    color: inherit;
    display: block;
    text-decoration: none;
}
a.ao-card:hover,
a.ao-card:focus-visible,
.ao-card.is-interactive:hover,
.ao-card.is-interactive:focus-visible {
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-2);
    transform: translateY(-2px);
}
.ao-card.is-interactive {
    cursor: pointer;
}
/* 11px / 600 in --ao-fg-dim: a label-sized card title, one step under a
 * section title (aoSection). Uppercase stays (decision D2). */
.ao-card-h {
    align-items: center;
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    gap: var(--ao-s-2);
    justify-content: space-between;
    letter-spacing: 0.08em;
    margin-bottom: var(--ao-s-2);
    text-transform: uppercase;
}
.ao-card-kv {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 4px 12px;
    font-size: var(--ao-fs-body);
}
.ao-card-kv dt {
    opacity: 0.6;
}
.ao-card-kv dd {
    margin: 0;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* ── Detail page ────────────────────────────────────────────────────── */
.ao-detail {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0;
}
.ao-detail-pane {
    padding: 12px;
    border-right: 1px solid var(--ao-border-soft);
    border-bottom: 1px solid var(--ao-border-soft);
}
.ao-detail-pane:last-child {
    border-right: none;
}
.ao-detail-h {
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: var(--ao-fs-meta);
    margin: 0 0 8px 0;
    border-bottom: 1px solid var(--ao-border);
    padding-bottom: 4px;
}
/* The way back off a drill-down. Reads as a control, at text contrast. */
.ao-backlink {
    align-items: center;
    align-self: flex-start;
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: var(--ao-s-1);
    text-decoration: none;
}
.ao-backlink::before {
    content: '\2039';
    font-size: 1.3em;
    line-height: 1;
}
.ao-backlink:hover {
    color: var(--ao-fg);
    text-decoration: underline;
}
.ao-backlink:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}

/* A responsive card shelf. Every page that shows a set of cards was rolling its
 * own inline flex-wrap; auto-fill means the same rule works for a 2-camera store
 * and a 15-camera one without a breakpoint. */
.ao-card-grid {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

/* A caveat that travels with the number it qualifies. The throughput profile
 * returns its own `note` explaining that an effect smaller than the noise floor
 * cannot be claimed — printing the figures without it is how three fps claims on
 * this platform got quoted against an unstated floor and two were retracted. */
.ao-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    margin: var(--ao-s-3) 0 0;
    max-width: 68ch;
}

.ao-kv {
    display: grid;
    grid-template-columns: 140px 1fr;
    gap: 4px 16px;
    font-size: var(--ao-fs-body);
}
.ao-kv dt {
    opacity: 0.6;
}
.ao-kv dd {
    margin: 0;
    /* A long id or URL still breaks anywhere; a sentence breaks between words
     * (break-all split them mid-word: "th e portal"). */
    overflow-wrap: anywhere;
}

.ao-tag {
    display: inline-block;
    border: 1px solid var(--ao-border);
    padding: 1px 6px;
    margin: 2px 4px 2px 0;
    font-size: var(--ao-fs-meta);
}
.ao-tag.is-reviewer {
    background: var(--ao-ink);
    color: var(--ao-ink-fg);
}

/* ── Rating pill ────────────────────────────────────────────────────── */
.ao-rating {
    display: inline-block;
    border: 1px solid var(--ao-border);
    padding: 0 6px;
    font-weight: 700;
    font-size: var(--ao-fs-meta);
    min-width: 32px;
    text-align: center;
    letter-spacing: 0.04em;
}
.ao-rating.t-AAA,
.ao-rating.t-AA,
.ao-rating.t-A {
    background: var(--ao-ink);
    color: var(--ao-ink-fg);
}
.ao-rating.t-D {
    background: var(--ao-surface);
    color: var(--ao-fg);
    border-color: var(--ao-border);
    text-decoration: line-through;
}

/* ── Buttons / forms ────────────────────────────────────────────────── */
/* Buttons — Amazon-inspired geometry (8px radius, a touch larger + heavier, a
 * subtly raised feel) on the graphite surface. Keeps the console's uppercase
 * micro-label identity so the ~100 buttons in dense toolbars don't reflow. */
/* 2026-09-22 (owner: "we much prefer the types of buttons we have in
 * documents tab, instead of the large rectangular ones"): the Documents pill
 * GEOMETRY only. Colours, the uppercase micro-label and the cart-gold primary
 * are the console's own and stay. The explicit floor + `min-width: auto`
 * undo css/main.css's blanket 44px button box, which was what made these
 * rectangles tall in dense toolbars. */
/* 2026-09-23 (design system v2, "redo all the buttons … so every tab is
 * consistent"): the Team page's sync pill is now THE button. Surface fill, the
 * soft border, a hairline inset highlight over elev-1, and hover that lifts to
 * --ao-hover + the full border instead of the old ink inversion (which made a
 * row of quiet buttons flash like a selection). The min-height is a literal
 * px floor — pill-buttons.contract.test.js reads it off THIS rule, and a
 * var() floor does not pass. Labels stay uppercase (decision D2: ~136 test
 * assertions read them).
 * 2026-09-24 (owner: "hate this bubble shit, wipe it from everywhere"): NOT a
 * pill any more. The radius is the control radius (--ao-r-ctl, 8px, the
 * portal's --kit-r-ctl), and the icon-only variant, which inherits it, is an
 * 8px square rather than a circle. */
.ao-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 28px;
    min-width: auto;
    line-height: 1.2;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    color: var(--ao-fg);
    padding: 6px 13px;
    font-family: inherit;
    font-size: var(--ao-fs-body);
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    box-shadow:
        inset 0 1px 0 var(--ao-tint),
        var(--ao-elev-1);
}
/* :not(:disabled) — a disabled button must not answer the pointer. */
.ao-btn:hover:not(:disabled) {
    background: var(--ao-hover);
    border-color: var(--ao-border);
    color: var(--ao-fg);
}
/* The console's global ring is a box-shadow on some controls; a pill carries
 * its own box-shadow, so the keyboard ring is an OUTLINE here and can never be
 * painted over by the elevation. */
.ao-btn:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    box-shadow: none;
}
/* Icons inside a button are 14px and sit on the label's optical centre; the
 * gap above spaces them. aoIcon sets width/height attributes, CSS wins. */
.ao-btn .ao-ico {
    flex: none;
    height: 14px;
    width: 14px;
}

/* Destructive. The err family, NEVER the gold CTA and never the ink bar: a
 * destructive action must not read as "recommended" (the rule confirmModal
 * used to enforce with an inline red). Quiet at rest, tinted on hover. */
.ao-btn.is-danger {
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-btn.is-danger:hover:not(:disabled) {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-fg);
}
/* aoBtn iconEnd: the icon after the label (NEXT / forward). Visual order
 * only; the label stays first for a screen reader. */
.ao-btn.is-icon-end {
    flex-direction: row-reverse;
}
/* Ghost — tertiary actions in dense rows (Cancel, Clear, a row's "more"). No
 * fill, no border, no elevation until the pointer is on it. */
.ao-btn.is-ghost {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    color: var(--ao-fg-dim);
}
.ao-btn.is-ghost:hover:not(:disabled) {
    background: var(--ao-tint-2);
    border-color: transparent;
    color: var(--ao-fg);
}
/* Icon-only — a 28px circle (24px with .ao-btn-sm). It has no text, so the
 * caller MUST give it an aria-label (aoBtn does, from label/ariaLabel). */
.ao-btn.is-icon {
    padding: 0;
    width: 28px;
}
.ao-btn.is-icon.ao-btn-sm {
    width: 26px;
}

/* Primary CTA — Amazon cart-gold (both sizing and colour copied): the console's
 * one loud "do this" action, on the otherwise-graphite chrome. Applied only to
 * genuine primaries (the confirm-modal primary, SAVE, PROMOTE, ARM). Danger
 * confirms keep their inline red and never carry .is-primary. */
.ao-btn.is-primary {
    background: var(--ao-cta);
    border-color: var(--ao-cta-border);
    color: var(--ao-cta-fg);
    font-weight: 700;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}
.ao-btn.is-primary:hover {
    background: var(--ao-cta-hover);
    border-color: var(--ao-cta-hover);
    color: var(--ao-cta-fg);
}
.ao-btn.is-primary:active {
    background: var(--ao-cta-active);
}
.ao-btn.is-primary:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--ao-cta-focus);
}
.ao-btn.is-primary:disabled {
    background: var(--ao-surface);
    border-color: var(--ao-border);
    color: var(--ao-fg-mute);
    box-shadow: none;
}

.ao-input,
.ao-select,
.ao-textarea {
    background: var(--ao-surface);
    color: var(--ao-fg);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    padding: 5px 9px;
    font-family: inherit;
    font-size: var(--ao-fs-body);
    width: 100%;
    transition:
        border-color var(--ao-fast) var(--ao-ease),
        box-shadow var(--ao-fast) var(--ao-ease);
}
.ao-input:focus,
.ao-select:focus,
.ao-textarea:focus {
    outline: none;
    border-color: var(--ao-accent-line);
    box-shadow: 0 0 0 3px var(--ao-focus-glow);
}
.ao-textarea {
    min-height: 60px;
    resize: vertical;
}

.ao-toolbar {
    border-bottom: 1px solid var(--ao-border-soft);
    padding: 8px 12px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    font-size: var(--ao-fs-meta);
}
.ao-toolbar label {
    display: flex;
    flex-direction: column;
    gap: 2px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.ao-toolbar label .ao-input,
.ao-toolbar label .ao-select {
    min-width: 140px;
}

/* ── Tenant combobox (auto-populated picker) ────────────────────────── */
/* ── Picker trigger (.ao-picker) — the button that opens the searchable picker
 * modal (tenant / GPU SKU). Replaces the former free-text .ao-combo: a button
 * at rest gives Chrome/Apple password managers nothing to autofill. Styled to
 * match .ao-tselect for visual consistency across the toolbars. ──────────── */
.ao-picker {
    position: relative;
    display: inline-block;
}
.ao-picker-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    background: var(--ao-surface);
    color: var(--ao-fg);
    border: 1px solid var(--ao-border);
    padding: 4px 8px;
    font-family: inherit;
    font-size: var(--ao-fs-body);
    min-width: 140px;
    text-align: left;
    cursor: pointer;
}
.ao-picker-trigger:hover {
    background: var(--ao-surface-2);
}
.ao-picker-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-picker-label.is-placeholder {
    opacity: 0.55;
}
.ao-picker-caret {
    flex: none;
    opacity: 0.6;
    font-size: var(--ao-fs-label);
}

/* ── Searchable picker modal (.ao-modal) — body-appended overlay shared by the
 * tenant + GPU SKU pickers (searchableModal() in argus-ops.js). Mirrors the
 * confirm / idle / operator-key modals: var(--ao-overlay) scrim over a
 * surface-2 card. The search box is ephemeral (created on open, removed on
 * close, never in a <form>) so password managers can't attach. ──────────── */
.ao-modal-overlay {
    position: fixed;
    inset: 0;
    background: var(--ao-overlay);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    /* Appended to <body>, outside the root: the console's face, in the
     * portal-embedded mode too. */
    font-family: var(--ao-font-sans);
    -webkit-font-smoothing: antialiased;
    z-index: 99998;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 10vh 24px 24px;
}
.ao-modal-card {
    display: flex;
    flex-direction: column;
    max-height: 70vh;
    width: 100%;
    max-width: 520px;
    background: var(--ao-surface-2);
    color: var(--ao-fg-dim);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow: 0 12px 40px var(--ao-shadow);
    overflow: hidden;
}

/* ── Confirm / arm / action modals (.ao-arm-modal-*, built inline in
 * argus-ops.js). The JS sets most of the card via style.cssText; these rules
 * supply only what those inline styles OMIT — an elevation shadow and a soft
 * backdrop blur — so every operator confirm modal gets the same modern, focused
 * chrome as the flagship support-view card. The support-view modal sets its own
 * box-shadow + backdrop-filter inline, so those win there and this never
 * double-applies. ──────────────────────────────────────────────────────── */
.ao-arm-modal-overlay {
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}
/* These modals attach to <body>, outside #argus-ops-root, and the standalone
 * body sets no font: every confirm rendered in the browser's default serif.
 * A field's label sits 5px over its input, fields 12px apart, and an input
 * stays inside the card's padding. */
.ao-arm-modal-overlay,
.ao-confirm-overlay {
    font-family: var(--ao-font-sans);
}
.ao-arm-modal-card > .ao-field {
    margin-top: 12px;
}
.ao-arm-modal-card > .ao-field > .ao-field-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    letter-spacing: 0.02em;
    margin-bottom: 5px;
}
.ao-arm-modal-card .ao-input {
    box-sizing: border-box;
}
.ao-arm-modal-card {
    box-shadow: 0 20px 50px -12px var(--ao-shadow);
}
.ao-modal-head {
    padding: 16px 18px 10px;
}
.ao-modal-title {
    margin: 0;
    font-size: var(--ao-fs-title);
    letter-spacing: 0.04em;
    color: var(--ao-fg);
}
.ao-modal-sub {
    margin-top: 4px;
    font-size: var(--ao-fs-meta);
    opacity: 0.6;
    line-height: 1.4;
}
.ao-modal-sub:empty {
    display: none;
}
.ao-modal-search {
    margin: 0 18px 10px;
    background: var(--ao-surface);
    color: var(--ao-fg);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    padding: 7px 10px;
    font-family: inherit;
    font-size: var(--ao-fs-strong);
    transition:
        border-color var(--ao-fast) var(--ao-ease),
        box-shadow var(--ao-fast) var(--ao-ease);
}
.ao-modal-search:focus {
    outline: none;
    border-color: var(--ao-accent-line);
    box-shadow: 0 0 0 3px var(--ao-focus-glow);
}
.ao-modal-list {
    overflow-y: auto;
    border-top: 1px solid var(--ao-border-soft);
}
.ao-modal-row {
    padding: 9px 18px;
    cursor: pointer;
    border-bottom: 1px solid var(--ao-border-faint);
}
.ao-modal-row.is-active,
.ao-modal-row:hover {
    background: var(--ao-surface);
}
.ao-modal-row-lead {
    color: var(--ao-fg-mute);
    font-style: italic;
}
.ao-modal-row-clear {
    border-bottom: 1px solid var(--ao-border-soft);
}
.ao-modal-row-main {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.ao-modal-row-title {
    display: flex;
    align-items: center;
    gap: 8px;
}
.ao-modal-row-name {
    font-weight: 600;
    color: var(--ao-fg);
}
.ao-modal-row-meta {
    font-size: var(--ao-fs-meta);
    opacity: 0.6;
}
.ao-modal-badge {
    font-size: var(--ao-fs-label);
    letter-spacing: 0.04em;
    padding: 0 4px;
}
.ao-modal-badge.is-armed {
    color: var(--ao-ok-text);
}
.ao-modal-badge.is-unarmed {
    color: var(--ao-fg-mute);
}
.ao-modal-empty,
.ao-modal-freehint {
    padding: 12px 18px;
    font-size: var(--ao-fs-body);
    opacity: 0.6;
}
.ao-modal-freehint {
    color: var(--ao-ok-text);
    opacity: 0.85;
    border-top: 1px solid var(--ao-border-faint);
}

/* ── Themed select (.ao-tselect) — no-native-controls replacement for the
 * former native <select> in the incidents + records toolbars. The trigger is a
 * focusable button styled like the old .ao-select; the menu mirrors the combo
 * styling. Keyboard accessible (see selectInput() in argus-ops.js). ───────── */
.ao-tselect {
    position: relative;
    display: inline-block;
}
.ao-toolbar label .ao-tselect {
    min-width: 140px;
}
.ao-tselect-trigger {
    background: var(--ao-surface);
    color: var(--ao-fg);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-ctl);
    padding: 4px 8px;
    font-family: inherit;
    font-size: var(--ao-fs-body);
    width: 100%;
    min-width: 140px;
    text-align: left;
    cursor: pointer;
}
.ao-tselect-trigger::after {
    content: '▾';
    float: right;
    opacity: 0.6;
    margin-left: 8px;
}
.ao-tselect-menu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 100%;
    max-height: 260px;
    overflow-y: auto;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border);
    border-top: none;
    z-index: 9999;
    box-shadow: 0 8px 24px var(--ao-shadow);
}
.ao-tselect-menu.is-hidden {
    display: none;
}
.ao-tselect-opt {
    padding: 4px 10px;
    font-size: var(--ao-fs-body);
    cursor: pointer;
    white-space: nowrap;
}
.ao-tselect-opt:hover,
.ao-tselect-opt.is-active {
    background: var(--ao-surface-2);
    color: var(--ao-ok-text);
}
.ao-tselect-opt.is-disabled {
    opacity: 0.5;
    cursor: default;
    font-style: italic;
}
.ao-tselect-opt.is-disabled:hover {
    background: none;
    color: inherit;
}

/* ── Warning pill (.ao-warn-pill) — no-emoji replacement for the former `⚠`
 * glyph (req #8). A compact inverted badge that reads as a warning without a
 * pictograph. ──────────────────────────────────────────────────────────── */
.ao-warn-pill {
    display: inline-block;
    background: var(--ao-warn-strong);
    color: var(--ao-accent-fg);
    font-size: var(--ao-fs-label);
    font-weight: 700;
    letter-spacing: 0.1em;
    padding: 0 5px;
    border-radius: var(--ao-r-sm);
    vertical-align: middle;
}

/* ── Settings panel ─────────────────────────────────────────────────── */
.ao-settings {
    position: fixed;
    top: 0;
    right: 0;
    width: 360px;
    height: 100vh;
    background: var(--ao-surface);
    border-left: 1px solid var(--ao-border);
    padding: 16px;
    z-index: 10;
    overflow-y: auto;
}
.ao-settings.is-hidden {
    display: none;
}
.ao-settings h2 {
    font-size: var(--ao-fs-body);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    border-bottom: 1px solid var(--ao-border);
    padding-bottom: 4px;
    margin: 0 0 12px 0;
}
/* ── Settings sections / profile / token status ─────────────────────── */
.ao-settings-section {
    margin: 0 0 18px 0;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--ao-border-soft);
}
.ao-settings-h {
    font-size: var(--ao-fs-label);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    opacity: 0.55;
    margin: 0 0 8px 0;
}
.ao-settings-hint {
    font-size: var(--ao-fs-meta);
    opacity: 0.6;
    line-height: 1.4;
    margin: 8px 0;
}
.ao-settings-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: center;
    margin-top: 8px;
}

/* ── Profile page (#/profile) — identity + role, reusing buildProfileInto's
 * .ao-kv / .ao-settings-h / .ao-settings-actions. Since the 2026-09-23 rehaul
 * every section is also a Team card (.ao-card) and the page body's own rule
 * (#ao-page-body) sets the gutter; the page's layout rules live in the
 * GROWTH + ACCOUNT PAGES block after the Profile help rules. ─────────────── */
.ao-profile-section {
    min-width: 0;
}
.ao-profile-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    margin: 0 0 var(--ao-s-3);
}
.ao-role-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 14px 5px 10px;
    background: linear-gradient(180deg, var(--ao-rail-active), var(--ao-ink));
    border: 1px solid var(--ao-accent-line);
    border-radius: var(--ao-r-tag);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-strong),
        var(--ao-elev-1);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    color: var(--ao-fg);
    margin-bottom: var(--ao-s-3);
}
.ao-role-badge-dot {
    color: var(--ao-accent-line);
    display: inline-grid;
    place-items: center;
}
.ao-role-ref {
    margin-top: 14px;
    border-top: 1px solid var(--ao-border-faint);
    padding-top: 12px;
}
.ao-role-ref-h {
    font-size: var(--ao-fs-label);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    opacity: 0.5;
    margin-bottom: 8px;
}
.ao-role-ref-row {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 8px 12px;
    border-radius: var(--ao-r-md);
    border: 1px solid transparent;
}
.ao-role-ref-row.is-current {
    border-color: var(--ao-accent-line);
    background: var(--ao-tint-2);
    box-shadow: inset 2px 0 0 var(--ao-accent-line);
}
.ao-role-ref-name {
    font-size: var(--ao-fs-body);
    font-weight: 600;
    color: var(--ao-fg);
}
.ao-role-ref-row.is-current .ao-role-ref-name::after {
    content: ' · you';
    font-weight: 400;
    opacity: 0.6;
}
.ao-role-ref-desc {
    font-size: var(--ao-fs-meta);
    opacity: 0.65;
}
.ao-field-err {
    color: var(--ao-err);
    font-size: var(--ao-fs-meta);
    min-height: 0;
    margin: -4px 0 8px 0;
}
.ao-field-err:empty {
    display: none;
}
.ao-token-status {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--ao-fs-meta);
    opacity: 0.8;
    margin: 4px 0 8px 0;
}
/* The small pill (decision D3, raised to 26px 2026-09-23) for row actions
 * and error-box CTAs. A literal px floor for the same reason as .ao-btn's:
 * main.css's 44px box. ⛔ ONE small-button voice: .ao-actbtn and .ao-al-btn
 * carry the same size, weight, case and tracking, because a row that mixed
 * them read as two products (Alerting's Ack / Resolve next to PROMOTE TO
 * TICKET; Compute's TURN OFF next to RESTART). */
.ao-btn-sm {
    min-height: 26px;
    padding: 4px 11px;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.ao-btn-sm .ao-ico {
    height: 12px;
    width: 12px;
}
/* ── Operator-key modal ─────────────────────────────────────────────── */
.ao-key-overlay {
    position: fixed;
    inset: 0;
    background: var(--ao-overlay);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 12000;
}
.ao-key-card {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border);
    padding: 20px;
    width: 520px;
    max-width: calc(100vw - 32px);
    box-shadow: 0 12px 40px var(--ao-shadow);
}
.ao-key-h {
    margin: 0 0 8px 0;
    font-size: var(--ao-fs-strong);
    letter-spacing: 0.06em;
}
.ao-key-warn {
    font-size: var(--ao-fs-body);
    opacity: 0.75;
    line-height: 1.5;
    margin: 0 0 12px 0;
}
.ao-key-tokwrap {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 12px;
}
.ao-key-token {
    flex: 1;
    font-family: ui-monospace, Menlo, monospace;
    color: var(--ao-ok-text);
}
.ao-settings .ao-field {
    margin-bottom: 10px;
}
.ao-settings .ao-field-label {
    font-size: var(--ao-fs-meta);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 4px;
    opacity: 0.7;
}

/* ── Empty + error states (design system v2, 2026-09-23) ────────────────
 * Two panels at the card radius, deliberately unlike each other:
 *   .ao-empty  "we looked and there is nothing" — centred, muted, a soft
 *              dashed edge on a faint tint. Calm on purpose.
 *   .ao-error  "we could not look" — the err family, left-aligned with a
 *              3px err stripe, because it carries a headline, an explanation
 *              and actions (errorBox: .ao-error-title / -sub / -acts).
 * (.ao-table-unread, "could not be read", keeps its dashed warn edge — see
 * the aoTable block.) The 16px margin is unchanged: pages were laid out
 * around it. */
.ao-empty,
.ao-error {
    border-radius: var(--ao-r-xl);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
    margin: 16px;
    padding: var(--ao-s-6) var(--ao-s-5);
}
.ao-empty {
    background: var(--ao-tint);
    border: 1px dashed var(--ao-border);
    color: var(--ao-fg-mute);
    text-align: center;
}
.ao-error {
    background: var(--ao-err-bg);
    border: 1px solid var(--ao-err-bd);
    box-shadow: inset 3px 0 0 var(--ao-err-fg);
    color: var(--ao-fg);
    padding: var(--ao-s-4) var(--ao-s-5);
    text-align: left;
}
.ao-error-title {
    color: var(--ao-err-fg);
    font-weight: 600;
}
.ao-error-sub {
    color: var(--ao-fg-dim);
    line-height: 1.45;
    margin: 6px 0 10px;
    max-width: 620px;
}
.ao-error-acts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
}

/* ── Loading ────────────────────────────────────────────────────────── */
.ao-loading {
    padding: 12px;
    font-size: var(--ao-fs-meta);
    opacity: 0.6;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    position: relative;
    animation: ao-loading-pulse 1.4s ease-in-out infinite;
}
.ao-loading::after {
    content: '';
    display: inline-block;
    width: 0.6em;
    margin-left: 0.4em;
    text-align: left;
    animation: ao-loading-dots 1s steps(4, end) infinite;
}
@keyframes ao-loading-dots {
    0% {
        content: '';
    }
    25% {
        content: '·';
    }
    50% {
        content: '··';
    }
    75% {
        content: '···';
    }
    100% {
        content: '';
    }
}
@keyframes ao-loading-pulse {
    0%,
    100% {
        opacity: 0.45;
    }
    50% {
        opacity: 0.85;
    }
}

/* ── Manifest list ──────────────────────────────────────────────────── */
.ao-manifest {
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-manifest li {
    border-bottom: 1px solid var(--ao-border-soft);
    padding: 4px 0;
    display: flex;
    justify-content: space-between;
    font-size: var(--ao-fs-body);
}
.ao-manifest a {
    color: var(--ao-fg);
}

/* ── Records page (D3 — dataset browser + drawer) ───────────────────── */
/* Design system v2 (2026-09-23 rehaul): #ao-page-body is the page's flex
 * column (KPI strip, then this split), so the split is its own grid — it
 * used to carry the page-body id, whose `display:flex` beat this rule and
 * stacked the tree on top of the table at every width. Two cards; the tree
 * card scrolls itself and stays in view while the table scrolls the page. */
.ao-records-split {
    align-items: start;
    display: grid;
    gap: var(--ao-s-4);
    grid-template-columns: minmax(240px, 300px) minmax(0, 1fr);
}
.ao-records-left {
    max-height: calc(100vh - 150px);
    overflow-y: auto;
    position: sticky;
    top: 0;
}
.ao-records-left.ao-card {
    padding: var(--ao-s-3) 0 var(--ao-s-2);
}
.ao-records-right {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-records-right > #ao-records-body {
    min-width: 0;
}
.ao-records-right.ao-card > .ao-rec-head {
    margin-bottom: 0;
}

.ao-records-left.ao-card > .ao-tree-head {
    border-bottom: 1px solid var(--ao-tint-line);
    margin: 0;
    padding: var(--ao-s-1) var(--ao-s-4) var(--ao-s-3);
}
.ao-tree {
    padding: var(--ao-s-1) var(--ao-s-2) 0;
}
.ao-tree-tenant {
    padding: var(--ao-s-3) var(--ao-s-2) 2px;
}
.ao-tree-label {
    align-items: center;
    color: var(--ao-fg);
    display: flex;
    font-size: var(--ao-fs-body);
    font-weight: 600;
    gap: 6px;
    min-width: 0;
}
.ao-tree-label .ao-ico {
    color: var(--ao-fg-mute);
    flex: none;
}
.ao-tree-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tree-id {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    gap: 6px;
    min-width: 0;
    padding-left: 19px;
}
/* "CLI-… · cs-01": the tenant id gives way (ellipsis) before the site. */
.ao-tree-id-t {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tree-id-sep {
    flex: none;
    opacity: 0.7;
}
.ao-tree-id-s {
    align-items: center;
    display: inline-flex;
    flex: none;
    gap: 3px;
    letter-spacing: 0.02em;
}
.ao-tree-store {
    padding: 6px var(--ao-s-2) 2px 27px;
}
.ao-tree-store-label {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    gap: 4px;
    letter-spacing: 0.02em;
}
/* A month: name + count · size on one line, its size meter under both. */
.ao-tree-item {
    align-items: center;
    border: 1px solid transparent;
    border-radius: 10px;
    color: var(--ao-fg);
    cursor: pointer;
    display: grid;
    font-size: var(--ao-fs-body);
    gap: 5px var(--ao-s-2);
    grid-template-columns: minmax(0, 1fr) auto;
    margin: 2px 0 2px 19px;
    padding: 7px 10px;
    text-decoration: none;
}
.ao-tree-item:hover {
    background: var(--ao-hover);
}
.ao-tree-item:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 1px;
}
/* The picked month: a 2px accent edge on a lifted tint, as the rail's active
 * item. (It was the keyboard-focus glow plus a rose border, which read as an
 * error on the one row that was simply chosen.) */
.ao-tree-item.is-active {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-ctl);
    box-shadow: inset 2px 0 0 var(--ao-accent);
    color: var(--ao-fg);
}
.ao-tree-month {
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    letter-spacing: 0.06em;
}
.ao-tree-stat {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-variant-numeric: tabular-nums;
}
.ao-tree-item.is-active .ao-tree-stat {
    color: var(--ao-fg-dim);
}
.ao-tree-meter {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    grid-column: 1 / -1;
    height: 3px;
    overflow: hidden;
    position: relative;
}
.ao-tree-meter-fill {
    /* Size is --ao-k-5 on this page (the records SIZE and manifest bars too);
     * the brand rose read as an alert on every month. */
    background: var(--ao-k-5);
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
/* The MOTION block's hover slide (padding-left 30px) was built for the old
 * flush rows; on a pill it pushes the text off its meter. A nudge instead. */
.ao-tree .ao-tree-item:hover:not(.is-active) {
    padding-left: 13px;
}

/* The control bar over the artifacts table and the keyset pager under it. */
.ao-rec-bar.ao-toolbar {
    border-bottom: 0;
    gap: var(--ao-s-3);
    padding: 0;
}
.ao-rec-refresh {
    margin-left: auto;
}
/* SORT and the order toggle repeat the column headers' sort; a phone hides
 * the header row, so only a phone shows them. */
@media (min-width: 760.02px) {
    #argus-ops-root .ao-rec-bar .ao-rec-sortctl {
        display: none;
    }
}
.ao-rec-conf.ao-input {
    border-radius: var(--ao-r-ctl);
    min-height: 28px;
    padding: 4px 12px;
    width: 92px;
}
.ao-rec-pager {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: var(--ao-s-2);
    padding-top: var(--ao-s-3);
}
.ao-rec-pager-info {
    color: var(--ao-fg-mute);
    margin-left: var(--ao-s-1);
}
.ao-rec-pager-page {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-weight: 600;
}

/* Drawer — slides in from the right over the records page */
.ao-drawer-overlay {
    position: fixed;
    inset: 0;
    background: var(--ao-overlay);
    z-index: 100;
}
.ao-drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 50vw;
    max-width: 720px;
    min-width: 480px;
    background: var(--ao-surface);
    color: var(--ao-fg);
    border-left: 1px solid var(--ao-border);
    overflow-y: auto;
    z-index: 101;
    padding: 0 0 16px;
    /* ⛔ NO font-family HERE. This was the last survivor of the global monospace
     * rule removed from `#argus-ops-root *`, and it made the pod/record drawer
     * the one surface still set entirely in the browser's <pre> face — including
     * its title, its buttons and its prose ("Live on RunPod with NO worker row —
     * it is billing now"). Mono is for aligning digits and ids, and the drawer's
     * ids and numbers already get it from the `.ao-mono` / `code` / `.ao-num`
     * opt-ins, which reach in here like anywhere else. */
    font-size: var(--ao-fs-strong);
}
.ao-drawer-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid var(--ao-border);
    padding: 8px 12px;
    position: sticky;
    top: 0;
    background: var(--ao-surface);
    z-index: 1;
}
.ao-drawer-title {
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-size: var(--ao-fs-body);
    word-break: break-all;
    margin-right: 12px;
}
.ao-drawer .ao-kv {
    margin: 12px;
}
.ao-drawer-section-head {
    font-size: var(--ao-fs-meta);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 8px 12px 4px;
    border-top: 1px solid var(--ao-border-soft);
    margin-top: 8px;
}
.ao-drawer-btnrow {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 4px 12px 8px;
}
.ao-drawer-btnrow .ao-btn {
    font-size: var(--ao-fs-meta);
    padding: 4px 8px;
}
/* The inset is on the framed wrap, not the table: a margin on the table
 * would open a gutter inside the frame. */
.ao-drawer .ao-table-wrap {
    margin: 0 12px 12px;
}
.ao-drawer .ao-table {
    width: 100%;
}

/* ── DETECTIONS — Incidents, incident detail, the record drawer ─────────
 * Design system v2 (2026-09-23 rehaul, batch b08). The pages are built from
 * the shared pieces (aoStat.row, aoTable card, aoSection, aoSeg chips,
 * aoBtn); these rules only lay them out and restyle the few page-owned bits
 * (the dropdown fields, cell stacks, the hero, tags). Tokens only. */

/* A neutral state pill (unreviewed, "none", a consent flag): aoState has no
 * neutral rank — its `unknown` is the dashed "we could not read" look, which
 * a known-but-quiet value must not borrow. Scoped to these pages. */
:is(.ao-inc-page, .ao-incd-page, .ao-rec-page, .ao-rec-drawer, .ao-rv-page, .ao-breakdown) .ao-state-pill.is-neutral,
.ao-rv-badge.is-neutral {
    background: var(--ao-tint-2);
    border-color: var(--ao-border-soft);
    color: var(--ao-fg-dim);
}
.ao-rv-badge.is-info {
    background: var(--ao-info-bg);
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}

/* The control row: chips lead, the dropdown fields wrap beside them. */
.ao-inc-bar.ao-toolbar {
    border-bottom: 0;
    gap: var(--ao-s-3);
    padding: 0;
}
.ao-inc-selects {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2) var(--ao-s-4);
}
/* A dropdown with its caption beside it (as a seg field), not stacked
 * over it the way the old .ao-toolbar label column did. */
.ao-toolbar .ao-inc-field {
    align-items: center;
    color: var(--ao-fg-mute);
    flex-direction: row;
    font-size: var(--ao-fs-label);
    gap: var(--ao-s-2);
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ao-toolbar .ao-inc-field .ao-tselect {
    letter-spacing: normal;
    min-width: 0;
    text-transform: none;
}
/* The trigger as a pill (the Team page's one dropdown is one), at the 28px
 * control height, so it sits level with the chips and buttons beside it.
 * The text inputs in the same rows (.ao-rec-conf, .ao-rv-notes, the tag
 * input) take the same pill corners. */
.ao-inc-field .ao-tselect-trigger,
.ao-rv-labelcell .ao-tselect-trigger {
    align-items: center;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint),
        var(--ao-elev-1);
    color: var(--ao-fg);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    gap: var(--ao-s-2);
    justify-content: space-between;
    min-height: 28px;
    min-width: 92px;
    padding: 4px 12px 4px 14px;
}
.ao-inc-field .ao-tselect-trigger:hover,
.ao-rv-labelcell .ao-tselect-trigger:hover {
    background: var(--ao-hover);
    border-color: var(--ao-border);
}
.ao-inc-field .ao-tselect-trigger:focus-visible,
.ao-rv-labelcell .ao-tselect-trigger:focus-visible {
    border-color: var(--ao-accent-line);
    box-shadow: 0 0 0 3px var(--ao-focus-glow);
    outline: none;
}
.ao-inc-field .ao-tselect-menu,
.ao-rv-labelcell .ao-tselect-menu {
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-lg);
    margin-top: 4px;
    padding: 4px;
}
.ao-inc-field .ao-tselect-opt,
.ao-rv-labelcell .ao-tselect-opt {
    border-radius: 6px;
    padding: 5px 10px;
}

/* The painted panel: the KPI strip, then the table card. */
.ao-inc-panel {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
}
/* A KPI card's 0..1 meter (aoStat pct): the full card width at its foot,
 * in the card's own hue unless a real state colours it (risk level). The
 * empty label aoState leaves beside the bar is dropped. */
:is(.ao-inc-kpis, .ao-incd-kpis, .ao-rec-kpis-row, .ao-rec-drawer-kpis, .ao-pd-kpis, .ao-rv-kpis-row)
    .ao-stat
    > .ao-state-bar {
    border-radius: var(--ao-r-bar);
    display: block;
    height: 5px;
    margin-top: auto;
    min-width: 0;
    width: 100%;
}
:is(.ao-inc-kpis, .ao-incd-kpis, .ao-rec-kpis-row, .ao-rec-drawer-kpis, .ao-pd-kpis, .ao-rv-kpis-row)
    .ao-stat
    > .ao-state-bar.is-unknown {
    background: var(--ao-tint-2);
}
:is(.ao-inc-kpis, .ao-incd-kpis, .ao-rec-kpis-row, .ao-rec-drawer-kpis, .ao-pd-kpis, .ao-rv-kpis-row)
    .ao-stat
    > .ao-state-bar.is-unknown
    .ao-state-bar-fill {
    background: var(--ao-stat-accent, var(--ao-k-5));
}
:is(.ao-inc-kpis, .ao-incd-kpis, .ao-rec-kpis-row, .ao-rec-drawer-kpis, .ao-pd-kpis, .ao-rv-kpis-row)
    .ao-stat
    > .ao-state-bar
    .ao-state-bar-fill {
    border-radius: inherit;
}
:is(.ao-inc-kpis, .ao-incd-kpis, .ao-rec-kpis-row, .ao-rec-drawer-kpis, .ao-pd-kpis, .ao-rv-kpis-row)
    .ao-state-bar-label:empty {
    display: none;
}
/* With a meter AND a sparkline, the meter sits right over the spark. */
:is(.ao-inc-kpis, .ao-pd-kpis, .ao-rv-kpis-row, .ao-rec-kpis-row) .ao-stat > .ao-state-bar + .ao-stat-spark {
    margin-top: 0;
}

/* The header ⓘ definitions (RISK, RATING, CONFIRMATION, STORE): the v2 cell
 * clips its overflow, which cut the popover to the header's own height, and
 * the header's capitals leaked into the definition. The last column's opens
 * leftward so it stays inside the card. */
.ao-incidents th {
    overflow: visible;
}
.ao-incidents th .ao-info-pop {
    font-weight: 400;
    letter-spacing: normal;
    text-transform: none;
    white-space: normal;
    width: 280px;
}
.ao-incidents th:last-child .ao-info-pop {
    left: auto;
    right: 0;
}

/* Two-line cells: the value, then a quiet sub-line (age, camera id). */
.ao-inc-when,
.ao-inc-cam {
    display: flex;
    flex-direction: column;
    gap: 2px;
    line-height: 1.3;
}
.ao-inc-ts {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
}
.ao-inc-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}
.ao-inc-cam-name {
    color: var(--ao-fg);
}
/* Risk's magnitude track takes the row's risk level — the incidents list's
 * risk_level, the review queue's bucket (span.: the design-system test reads
 * the FIRST rule ending in " .ao-table-bar-fill" as the shared one). */
:is(.ao-incidents, .ao-rv-queue) tr.is-risk-high span.ao-table-bar-fill {
    background: linear-gradient(90deg, var(--ao-err-border-strong), var(--ao-err));
}
:is(.ao-incidents, .ao-rv-queue) tr.is-risk-medium span.ao-table-bar-fill {
    background: linear-gradient(90deg, var(--ao-warn-border), var(--ao-warn));
}
:is(.ao-incidents, .ao-rv-queue) tr.is-risk-low span.ao-table-bar-fill {
    background: linear-gradient(90deg, var(--ao-ok-border), var(--ao-ok));
}
/* Magnitudes that are not a verdict take a KPI hue, not the brand rose (which
 * read as an alert on every row): confidence --ao-k-1, bytes --ao-k-5 — the
 * records table, both manifests and the dataset tree agree. */
.ao-records td:nth-child(4) span.ao-table-bar-fill {
    background: var(--ao-k-1);
}
:is(.ao-records td:nth-child(5), .ao-rec-manifest td:nth-child(2), .ao-incd-manifest td:nth-child(2))
    span.ao-table-bar-fill {
    background: var(--ao-k-5);
}
/* Grade chips on these pages: a rounded mono chip, not a square stamp, toned
 * by band — A ok, B neutral, C warn, D error. (The shared .ao-rating keeps
 * the old ink / struck-through D for HELP and Grade; here the D's
 * line-through read as "Ð".) */
:is(.ao-incidents, .ao-records, .ao-incd, .ao-rec-drawer, .ao-breakdown) .ao-rating {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: 6px;
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    line-height: 1.6;
    text-decoration: none;
}
:is(.ao-incidents, .ao-records, .ao-incd, .ao-rec-drawer, .ao-breakdown)
    :is(.ao-rating.t-AAA, .ao-rating.t-AA, .ao-rating.t-A) {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
:is(.ao-incidents, .ao-records, .ao-incd, .ao-rec-drawer, .ao-breakdown)
    :is(.ao-rating.t-CCC, .ao-rating.t-CC, .ao-rating.t-C) {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
:is(.ao-incidents, .ao-records, .ao-incd, .ao-rec-drawer, .ao-breakdown) .ao-rating.t-D {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}

/* B / BB / BBB and a neutral state pill (class NONE, unreviewed): the soft
 * border vanished on the grey fill, so these read as the only unoutlined
 * chips on the page. The full border token, like every toned chip. */
:is(.ao-incidents, .ao-records, .ao-incd, .ao-rec-drawer, .ao-breakdown)
    :is(.ao-rating.t-BBB, .ao-rating.t-BB, .ao-rating.t-B) {
    border-color: var(--ao-border);
}
:is(.ao-inc-page, .ao-incd-page, .ao-rec-page, .ao-rec-drawer, .ao-rv-page, .ao-breakdown) .ao-state-pill.is-neutral,
.ao-rv-badge.is-neutral {
    border-color: var(--ao-border);
}

/* The head's "auto-refresh" as the Team sync chip (its .ao-tm-sync look):
 * a live dot, the poll interval and when the last answer landed. It is a
 * readout, not a control — no pointer, no hover change. The meta line's
 * 0.7 dim would grey the chip, so the words beside it carry the dim. */
.ao-page-meta.has-det-live {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px var(--ao-s-3);
    margin-top: 2px;
    opacity: 1;
}
.ao-det-live-lead {
    color: var(--ao-fg-mute);
}
.ao-tm-sync.ao-det-live {
    cursor: default;
    font-size: var(--ao-fs-label);
    gap: 7px;
    padding: 4px 11px 4px 10px;
}
.ao-tm-sync.ao-det-live:hover {
    border-color: var(--ao-border-soft);
    color: var(--ao-fg-dim);
}
.ao-det-live-text {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-det-live-at {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-variant-numeric: tabular-nums;
}
.ao-det-live-at::before {
    content: '·';
    margin-right: 7px;
}
.ao-tm-sync.ao-det-live.is-err .ao-det-live-at {
    color: var(--ao-err-strong);
}

/* Incidents: the phone sort chips (the header row is the sort control on a
 * wide screen; a phone hides it) and the pager under a long list. */
.ao-inc-sortrow {
    display: none;
}
.ao-inc-pager {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2) var(--ao-s-3);
    padding: var(--ao-s-3) var(--ao-s-1) 0;
}
.ao-inc-pager-info {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-inc-pager-range {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}
.ao-inc-pager-size {
    margin-left: auto;
}
/* Disabled PREV / NEXT keep their pill (outline and all) at a dim 0.55, so
 * a one-page list still shows where paging lives. */
:is(.ao-inc-pager, .ao-rec-pager) .ao-btn:disabled {
    border-color: var(--ao-border);
    opacity: 0.55;
}

/* ── Incident detail ─────────────────────────────────────────────────── */
.ao-incd {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
}
.ao-incd-back {
    align-self: flex-start;
}
.ao-incd-page > .ao-incd-back {
    margin-bottom: calc(var(--ao-s-2) * -1);
}
.ao-incd-hero {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-4) var(--ao-s-6);
    isolation: isolate;
    overflow: hidden;
    padding: var(--ao-s-5) var(--ao-s-6);
    position: relative;
}
/* The Team hero's corner glow: texture behind the grade, never over text. */
.ao-incd-hero::before {
    background: radial-gradient(ellipse 50% 120% at 0% 0%, var(--ao-tint-strong), transparent 70%);
    content: '';
    inset: 0;
    opacity: 0.5;
    pointer-events: none;
    position: absolute;
    z-index: -1;
}
.ao-incd-grade {
    align-items: center;
    display: flex;
    flex: none;
    flex-direction: column;
    gap: 6px;
}
.ao-incd-grade .ao-rating {
    border-radius: 14px;
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-2);
    font-size: 26px;
    letter-spacing: -0.01em;
    line-height: 1;
    min-width: 84px;
    padding: 14px 16px;
}
.ao-incd-grade-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.12em;
    text-transform: uppercase;
}
.ao-incd-hero-main {
    display: flex;
    flex: 1 1 320px;
    flex-direction: column;
    gap: var(--ao-s-2);
    min-width: 0;
}
.ao-incd-hero-title {
    align-items: center;
    display: flex;
    font-size: var(--ao-fs-h);
    font-weight: 650;
    gap: var(--ao-s-2);
    letter-spacing: -0.01em;
    overflow-wrap: anywhere;
}
.ao-incd-hero-title .ao-ico {
    color: var(--ao-fg-mute);
    flex: none;
}
.ao-incd-hero-meta {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2) var(--ao-s-5);
}
.ao-incd-hero-when {
    align-items: center;
    color: var(--ao-fg-dim);
    display: inline-flex;
    gap: 6px;
}
.ao-incd-hero-when .ao-ico {
    color: var(--ao-fg-mute);
}
.ao-incd-pills {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
/* How the grade was reached, across the hero's right side: confidence ×
 * weight + data quality × weight = composite, as three factor tiles in the
 * page's hues (confidence --ao-k-1, quality --ao-k-2, as the cards below;
 * the composite blends the two). Meters are transforms, never widths. */
.ao-incd-formula {
    align-items: stretch;
    display: flex;
    flex: 0 1 auto;
    gap: var(--ao-s-2);
    margin-left: auto;
    min-width: 0;
}
.ao-incd-factor {
    --ao-incd-f: var(--ao-k-1);
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    box-shadow: inset 0 1px 0 var(--ao-tint-line);
    display: grid;
    gap: 4px 8px;
    grid-template-areas:
        'k k'
        'v w'
        'bar bar'
        'note note';
    grid-template-columns: minmax(0, 1fr) auto;
    min-width: 142px;
    padding: 12px 14px 13px;
}
.ao-incd-factor.is-dq {
    --ao-incd-f: var(--ao-k-2);
}
.ao-incd-factor.is-comp {
    background: var(--ao-tint-2);
    border-color: var(--ao-border);
}
.ao-incd-factor-k {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    grid-area: k;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    white-space: nowrap;
}
.ao-incd-factor-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: 24px;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    grid-area: v;
    letter-spacing: -0.02em;
    line-height: 1.1;
}
.ao-incd-factor-w {
    align-self: end;
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    grid-area: w;
    padding-bottom: 2px;
}
.ao-incd-factor-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: block;
    grid-area: bar;
    height: 4px;
    margin-top: 2px;
    overflow: hidden;
    position: relative;
}
.ao-incd-factor-bar.is-unmeasured {
    background: repeating-linear-gradient(45deg, var(--ao-tint-2) 0 3px, transparent 3px 6px);
}
.ao-incd-factor-fill {
    background: var(--ao-incd-f);
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
.ao-incd-factor.is-comp .ao-incd-factor-w {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-incd-factor.is-comp .ao-incd-factor-fill {
    background: linear-gradient(90deg, var(--ao-k-1), var(--ao-k-2));
}
.ao-incd-factor-note {
    color: var(--ao-err-fg);
    font-size: var(--ao-fs-label);
    grid-area: note;
    white-space: nowrap;
}
.ao-incd-op {
    align-self: center;
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: 18px;
    font-weight: 600;
    line-height: 1;
}
.ao-incd-grid.ao-detail {
    align-items: start;
    gap: var(--ao-s-4);
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.ao-incd-col {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
.ao-incd-grid .ao-detail-pane {
    border: 1px solid var(--ao-border-soft);
    min-width: 0;
    padding: var(--ao-s-4) var(--ao-s-5) var(--ao-s-5);
}
.ao-incd-kv.ao-kv {
    gap: 7px var(--ao-s-4);
    grid-template-columns: 116px minmax(0, 1fr);
}
.ao-incd-kv dt {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    opacity: 1;
}
.ao-incd-kv dd {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-incd-kv + .ao-incd-kv {
    margin-top: 7px;
}
.ao-incd-review {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
}
.ao-incd-review .ao-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.ao-incd-review .ao-field-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ao-incd-review-acts {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3);
}
.ao-incd-review-now {
    align-items: center;
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
}
.ao-incd-tags {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
}
.ao-tag.ao-incd-tag {
    align-items: center;
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    margin: 0;
    padding: 1px 2px 1px 11px;
}
.ao-tag.ao-incd-tag.is-reviewer {
    background: var(--ao-info-bg);
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-incd-tag-src {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}
.ao-tag.ao-incd-tag.is-reviewer .ao-incd-tag-src {
    color: var(--ao-info-fg);
    opacity: 0.7;
}
/* The remove control is a real button, drawn as a small round glyph that
 * sits inside the tag pill (it is still focusable and keyboard-operable). */
.ao-incd-tag .ao-btn.ao-incd-tag-x {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    color: inherit;
    min-height: 24px;
    min-width: 24px;
    opacity: 0.7;
    width: 24px;
}
.ao-incd-tag .ao-btn.ao-incd-tag-x:hover:not(:disabled) {
    background: var(--ao-tint-2);
    border-color: transparent;
    opacity: 1;
}
.ao-incd-tag .ao-incd-tag-x .ao-ico {
    height: 12px;
    width: 12px;
}
.ao-incd-addtag {
    display: flex;
    gap: var(--ao-s-2);
    margin-top: var(--ao-s-4);
}
.ao-incd-addtag .ao-input {
    border-radius: var(--ao-r-ctl);
    flex: 1 1 auto;
    min-height: 28px;
    min-width: 0;
    padding: 4px 14px;
}
/* Consent as two pills in the Facts list (it was YES / no text). */
.ao-incd-kv dd .ao-incd-consent {
    font-family: var(--ao-font-sans);
}
.ao-incd-consent .ao-state-pill {
    align-items: center;
    display: inline-flex;
    gap: 4px;
}
.ao-incd-file {
    align-items: center;
    display: inline-flex;
    gap: var(--ao-s-2);
    min-width: 0;
}
.ao-incd-file .ao-ico {
    color: var(--ao-fg-mute);
    flex: none;
}
.ao-incd-file a {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    text-decoration: none;
}
.ao-incd-file a:hover {
    text-decoration: underline;
}

/* ── The record drawer (the pod drawer shares .ao-drawer; these are its
 * own .ao-rec-drawer restyles, so Compute's drawer is untouched) ───────── */
.ao-rec-drawer {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-left: 1px solid var(--ao-border-soft);
    box-shadow: var(--ao-elev-3);
    /* Body-appended, so outside #argus-ops-root and its type: without these
     * the drawer fell back to the browser's serif face. */
    font-family: var(--ao-font-sans);
    -webkit-font-smoothing: antialiased;
    line-height: 1.45;
}
.ao-rec-drawer .ao-stat-num,
.ao-rec-drawer .ao-mono,
.ao-rec-drawer .ao-num {
    font-family: var(--ao-mono);
    font-variant-numeric: tabular-nums;
}
.ao-rec-drawer .ao-drawer-head {
    align-items: flex-start;
    background: var(--ao-surface-2);
    border-bottom: 1px solid var(--ao-tint-line);
    gap: var(--ao-s-3);
    padding: var(--ao-s-4);
}
.ao-rec-drawer-titlewrap {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    min-width: 0;
}
.ao-rec-drawer .ao-drawer-title {
    font-family: var(--ao-mono);
    letter-spacing: 0.02em;
    margin: 0;
    text-transform: none;
}
.ao-rec-drawer-kpis {
    margin: var(--ao-s-4) var(--ao-s-4) var(--ao-s-1);
}
.ao-rec-drawer .ao-kv {
    margin: 0 var(--ao-s-4) var(--ao-s-2);
}
.ao-rec-drawer-kv.ao-kv {
    gap: 7px var(--ao-s-4);
    grid-template-columns: 96px minmax(0, 1fr);
}
.ao-rec-drawer .ao-kv dt {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    opacity: 1;
}
/* Ids and times in mono; a store name (aoIdentity) keeps the sans face. */
.ao-rec-drawer .ao-kv dd {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-rec-drawer .ao-kv dd .ao-identity-name {
    font-family: var(--ao-font-sans);
    font-size: var(--ao-fs-body);
}
/* Details / Artifacts / Manifest: aoSection heads, each opening a band. */
.ao-rec-drawer .ao-sec-head.ao-rec-drawer-sec {
    border-top: 1px solid var(--ao-tint-line);
    margin: var(--ao-s-3) 0 0;
    padding: var(--ao-s-4) var(--ao-s-4) var(--ao-s-3);
}
.ao-rec-drawer-sec > .ao-sec-h {
    font-size: var(--ao-fs-title);
}
.ao-rec-drawer .ao-drawer-btnrow {
    display: grid;
    gap: var(--ao-s-2);
    grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
    padding: var(--ao-s-1) var(--ao-s-4) var(--ao-s-2);
}
.ao-rec-drawer .ao-drawer-btnrow .ao-btn {
    justify-content: flex-start;
    padding: 4px 12px;
    white-space: nowrap;
}
.ao-rec-drawer .ao-table-wrap {
    margin: 0 var(--ao-s-4) var(--ao-s-4);
}
.ao-rec-drawer .ao-table {
    margin: 0;
    width: 100%;
}

@media (max-width: 760px) {
    .ao-records-split {
        grid-template-columns: minmax(0, 1fr);
    }
    /* The head stays put and the months scroll under it: all ten stores ran
     * about 1300px above the table. (px cap too: a vh one alone grows with a
     * tall window.) */
    .ao-records-left {
        max-height: none;
        position: static;
    }
    .ao-records-left .ao-tree {
        max-height: min(40vh, 340px);
        overflow-y: auto;
        padding-bottom: var(--ao-s-2);
    }
    .ao-incd-grid.ao-detail {
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-incd-hero {
        padding: var(--ao-s-4);
    }
    /* The formula takes its own row, three tiles sharing it. */
    .ao-incd-formula {
        flex: 1 1 100%;
        gap: 6px;
        margin-left: 0;
    }
    /* A third of a phone: the weight drops under the value and a long
     * factor name may take two lines, so nothing overlaps or truncates. */
    .ao-incd-factor {
        flex: 1 1 0;
        grid-template-areas:
            'k'
            'v'
            'w'
            'bar'
            'note';
        grid-template-columns: minmax(0, 1fr);
        /* The name takes the slack, so a two-line name never lifts its
         * value above the other tiles'. */
        grid-template-rows: minmax(0, 1fr) repeat(4, auto);
        min-width: 0;
        padding: 9px 10px 10px;
    }
    .ao-incd-factor-k {
        letter-spacing: 0.06em;
        white-space: normal;
    }
    .ao-incd-factor-v {
        font-size: 18px;
    }
    .ao-incd-factor-w {
        align-self: start;
        padding-bottom: 0;
    }
    .ao-incd-factor-note {
        white-space: normal;
    }
    .ao-incd-op {
        font-size: 14px;
    }
    /* Facts: a narrow key column, so the ids get the width. */
    .ao-incd-kv.ao-kv {
        grid-template-columns: 88px minmax(0, 1fr);
    }
    .ao-incd-kv dd {
        min-width: 0;
        overflow-wrap: anywhere;
    }
    .ao-rec-drawer {
        max-width: none;
        min-width: 0;
        width: 100vw;
    }
    .ao-toolbar .ao-inc-field .ao-tselect-trigger {
        min-width: 0;
    }
    /* The sort the hidden header row gave, as chips over the cards. */
    .ao-inc-sortrow {
        display: flex;
        margin-bottom: var(--ao-s-3);
    }
    .ao-inc-pager {
        justify-content: space-between;
    }
    .ao-inc-pager-info {
        flex: 1 1 100%;
        order: -1;
    }
    .ao-inc-pager-size {
        margin-left: auto;
    }

    /* Phone tables: each row becomes a small card of its own cells (the Team
     * leaderboard stacks the same way) instead of a table that scrolls
     * sideways inside its card and hides RISK / CONFIRMATION off the edge.
     * The header goes (every cell says what it is by its shape), the hover
     * tick moves from the first cell to the row. */
    :is(.ao-incidents, .ao-records),
    :is(.ao-incidents, .ao-records) > tbody {
        display: block;
    }
    :is(.ao-incidents, .ao-records) > thead {
        display: none;
    }
    :is(.ao-incidents, .ao-records) > tbody > tr {
        border-bottom: 1px solid var(--ao-border-soft);
        display: grid;
        gap: 6px 12px;
        padding: 12px 14px;
    }
    :is(.ao-incidents, .ao-records) > tbody > tr:last-child {
        border-bottom: 0;
    }
    #argus-ops-root :is(.ao-incidents, .ao-records) > tbody > tr > td {
        background: transparent;
        border: 0;
        box-shadow: none;
        max-width: none;
        padding: 0;
    }
    :is(.ao-incidents, .ao-records) > tbody > tr:hover {
        background: var(--ao-hover);
        box-shadow: inset 2px 0 0 var(--ao-accent-line);
    }
    /* Incidents: when + grade / store + review state / camera + risk. */
    .ao-incidents > tbody > tr {
        grid-template-areas:
            'when rating'
            'store conf'
            'cam risk';
        grid-template-columns: minmax(0, 1fr) auto;
    }
    .ao-incidents > tbody > tr > td:nth-child(1) {
        grid-area: when;
    }
    .ao-incidents > tbody > tr > td:nth-child(2) {
        grid-area: store;
    }
    .ao-incidents > tbody > tr > td:nth-child(3) {
        grid-area: cam;
    }
    .ao-incidents > tbody > tr > td:nth-child(4) {
        align-self: end;
        grid-area: risk;
    }
    .ao-incidents > tbody > tr > td:nth-child(5) {
        grid-area: rating;
        justify-self: end;
    }
    .ao-incidents > tbody > tr > td:nth-child(6) {
        align-self: center;
        grid-area: conf;
        justify-self: end;
    }
    /* Records: when + grade / class, confidence, size / camera + incident.
     * The class pill has a fixed column, so CONF starts at the same x on
     * every card; confidence and size split the rest with a 12px gutter
     * between their two bars, each captioned. */
    .ao-records > tbody > tr {
        column-gap: 12px;
        grid-template-areas:
            'when when rating'
            'class conf size'
            'cam inc inc';
        grid-template-columns: 96px minmax(0, 1fr) minmax(0, 1fr);
    }
    #argus-ops-root .ao-records > tbody > tr > td.has-bar {
        min-width: 0;
    }
    .ao-records > tbody > tr > td:nth-child(1) {
        grid-area: when;
    }
    .ao-records > tbody > tr > td:nth-child(2) {
        align-self: center;
        grid-area: class;
    }
    .ao-records > tbody > tr > td:nth-child(3) {
        grid-area: rating;
        justify-self: end;
    }
    .ao-records > tbody > tr > td:nth-child(4) {
        grid-area: conf;
    }
    .ao-records > tbody > tr > td:nth-child(5) {
        grid-area: size;
    }
    .ao-records > tbody > tr > td:nth-child(6) {
        color: var(--ao-fg-mute);
        grid-area: inc;
        text-align: right;
    }
    .ao-records > tbody > tr > td:nth-child(7) {
        color: var(--ao-fg-mute);
        grid-area: cam;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .ao-records > tbody > tr > td:nth-child(4)::before,
    .ao-records > tbody > tr > td:nth-child(5)::before {
        color: var(--ao-fg-mute);
        content: 'conf ';
        float: left;
        font-family: var(--ao-font-sans);
        font-size: var(--ao-fs-label);
        letter-spacing: 0.08em;
        line-height: 1.8;
        text-transform: uppercase;
    }
    .ao-records > tbody > tr > td:nth-child(5)::before {
        content: 'size ';
    }
    .ao-records > tbody > tr > td:nth-child(6)::before {
        content: 'incident ';
        font-size: var(--ao-fs-label);
        letter-spacing: 0.08em;
        text-transform: uppercase;
    }
}
/* A phone's record drawer: the download pills one to a line, so no label
 * wraps onto two. */
@media (max-width: 480px) {
    .ao-rec-drawer .ao-drawer-btnrow {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ─────────────────────────────────────────────────────────────────────
 * MOTION
 *
 * Premium feel inside a B&W terminal aesthetic. Fast, intentful, uniform.
 * Three timing tokens (--ao-fast / --ao-base / --ao-slow), one easing
 * (--ao-ease) so the system feels of-a-piece.
 * ───────────────────────────────────────────────────────────────────── */
:root {
    --ao-fast: 90ms;
    --ao-base: 180ms;
    --ao-slow: 360ms;
    --ao-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* ⛔ OPACITY FLOOR 0.55 ON EVERY FADE BELOW (2026-09-23). A browser pauses CSS
 * animations in a hidden tab, and a keyframe that starts at opacity:0 with a
 * `both` fill pins its element at frame zero until it runs — a deep link opened
 * in a background tab painted a blank console (the whole page body sits under
 * .ao-anim-enter). ao-page-in, ao-rail-in, ao-row-in, ao-card-in, ao-fade-in
 * and ao-kv-in all start at 0.55 now; the rise still reads, a paused one is
 * merely dim. portal-invisible-animation.contract.test.js ratchets the count. */

/* Page entry — gated to actual nav, NOT polled re-renders. JS adds the
 * .ao-anim-enter class only on init + hashchange. */
.ao-anim-enter {
    animation: ao-page-in var(--ao-base) var(--ao-ease) both;
}
@keyframes ao-page-in {
    from {
        opacity: 0.55;
        transform: translateY(4px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Page header scan-line text reveal — gated. */
.ao-anim-enter .ao-page-title,
.ao-anim-enter .ao-page-meta {
    animation: ao-text-reveal var(--ao-slow) var(--ao-ease) both;
}
.ao-anim-enter .ao-page-meta {
    animation-delay: 80ms;
}
@keyframes ao-text-reveal {
    from {
        clip-path: inset(0 100% 0 0);
        opacity: 0.4;
    }
    to {
        clip-path: inset(0 0 0 0);
        opacity: 1;
    }
}

/* Scan-bar underline that swipes left→right under the page header. */
.ao-page-head {
    position: relative;
    overflow: hidden;
}
.ao-anim-enter.ao-page-head::after,
.ao-anim-enter .ao-page-head::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: -1px;
    height: 1px;
    width: 0;
    background: var(--ao-fg);
    animation: ao-scan-bar var(--ao-slow) var(--ao-ease) forwards;
}
@keyframes ao-scan-bar {
    0% {
        width: 0;
        opacity: 1;
    }
    70% {
        width: 100%;
        opacity: 1;
    }
    100% {
        width: 100%;
        opacity: 0;
    }
}

/* Rail items — staggered fade-in on first mount, slide-in indicator on hover. */
.ao-rail .ao-rail-item {
    animation: ao-rail-in 220ms var(--ao-ease) both;
}
.ao-rail .ao-rail-item:nth-child(1) {
    animation-delay: 30ms;
}
.ao-rail .ao-rail-item:nth-child(2) {
    animation-delay: 60ms;
}
.ao-rail .ao-rail-item:nth-child(3) {
    animation-delay: 90ms;
}
.ao-rail .ao-rail-item:nth-child(4) {
    animation-delay: 120ms;
}
.ao-rail .ao-rail-item:nth-child(5) {
    animation-delay: 150ms;
}
.ao-rail .ao-rail-item:nth-child(6) {
    animation-delay: 180ms;
}
.ao-rail .ao-rail-item:nth-child(7) {
    animation-delay: 210ms;
}
@keyframes ao-rail-in {
    from {
        opacity: 0.55;
        transform: translateX(-8px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

.ao-rail-item {
    position: relative;
    transition:
        background var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease),
        padding-left var(--ao-fast) var(--ao-ease);
}
.ao-rail-item::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 0;
    background: var(--ao-accent-line);
    transition: width var(--ao-fast) var(--ao-ease);
}
.ao-rail-item:hover {
    padding-left: 16px;
}
/* Hover's marker is deliberately the WEAKER one — thinner and neutral — so a
 * merely-hovered row can never out-signal the genuinely selected one. */
.ao-rail-item:hover::before {
    width: 2px;
    background: var(--ao-fg-mute);
}
.ao-rail-item.is-active {
    transition: none;
}
/* The marker persists while the item is active — previously it existed only on
 * hover, so the selected page had no standing indicator once the pointer left.
 * Declared after the :hover rules so an active row keeps the strong brand marker
 * under the pointer instead of twitching to the neutral hover one. */
.ao-rail-item.is-active::before,
.ao-rail-item.is-active:hover::before {
    width: 4px;
    background: var(--ao-accent-line);
}
/* The active row still needs to feel clickable. Its background rule wins over
 * :hover and its marker is pinned, so without this the selected row is the one
 * place in the console where the pointer produces no response at all. A tint
 * layer lifts it without introducing another background token. */
.ao-rail-item.is-active:hover {
    background-image: linear-gradient(var(--ao-tint-2), var(--ao-tint-2));
}

/* Buttons — press feedback */
.ao-btn,
.ao-top-actions button,
.ao-top-actions a {
    transition:
        background var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease),
        transform var(--ao-fast) var(--ao-ease);
}
.ao-btn:active,
.ao-top-actions button:active {
    transform: translateY(1px);
}

/* Table rows — gentle fade on every render (signals data refresh)
 * plus a staggered cascade on real page entry. */
.ao-table tbody tr {
    transition: background var(--ao-fast) var(--ao-ease);
    animation: ao-row-in var(--ao-fast) var(--ao-ease) both;
}
.ao-anim-enter .ao-table tbody tr {
    animation-duration: 280ms;
}
.ao-anim-enter .ao-table tbody tr:nth-child(1) {
    animation-delay: 0ms;
}
.ao-anim-enter .ao-table tbody tr:nth-child(2) {
    animation-delay: 18ms;
}
.ao-anim-enter .ao-table tbody tr:nth-child(3) {
    animation-delay: 36ms;
}
.ao-anim-enter .ao-table tbody tr:nth-child(4) {
    animation-delay: 54ms;
}
.ao-anim-enter .ao-table tbody tr:nth-child(5) {
    animation-delay: 72ms;
}
.ao-anim-enter .ao-table tbody tr:nth-child(6) {
    animation-delay: 90ms;
}
.ao-anim-enter .ao-table tbody tr:nth-child(7) {
    animation-delay: 108ms;
}
.ao-anim-enter .ao-table tbody tr:nth-child(8) {
    animation-delay: 126ms;
}
.ao-anim-enter .ao-table tbody tr:nth-child(9) {
    animation-delay: 144ms;
}
.ao-anim-enter .ao-table tbody tr:nth-child(10) {
    animation-delay: 162ms;
}
.ao-anim-enter .ao-table tbody tr:nth-child(n + 11) {
    animation-delay: 180ms;
}
@keyframes ao-row-in {
    from {
        opacity: 0.55;
        transform: translateY(2px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Pipeline cards — staggered cascade on entry */
.ao-anim-enter .ao-grid > .ao-card {
    animation: ao-card-in 320ms var(--ao-ease) both;
}
.ao-anim-enter .ao-grid > .ao-card:nth-child(1) {
    animation-delay: 0ms;
}
.ao-anim-enter .ao-grid > .ao-card:nth-child(2) {
    animation-delay: 30ms;
}
.ao-anim-enter .ao-grid > .ao-card:nth-child(3) {
    animation-delay: 60ms;
}
.ao-anim-enter .ao-grid > .ao-card:nth-child(4) {
    animation-delay: 90ms;
}
.ao-anim-enter .ao-grid > .ao-card:nth-child(5) {
    animation-delay: 120ms;
}
.ao-anim-enter .ao-grid > .ao-card:nth-child(6) {
    animation-delay: 150ms;
}
.ao-anim-enter .ao-grid > .ao-card:nth-child(7) {
    animation-delay: 180ms;
}
.ao-anim-enter .ao-grid > .ao-card:nth-child(8) {
    animation-delay: 210ms;
}
.ao-anim-enter .ao-grid > .ao-card:nth-child(n + 9) {
    animation-delay: 240ms;
}
@keyframes ao-card-in {
    from {
        opacity: 0.55;
        transform: translateY(6px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Polled re-render data-refresh tell — a 1-frame underline pulse on
 * page-meta so operators see when data ticked. JS toggles
 * .ao-data-refreshed in head() during polling. */
.ao-page-meta {
    position: relative;
}
.ao-page-meta::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: -2px;
    height: 1px;
    background: var(--ao-fg);
    transform: scaleX(0);
    transform-origin: left;
    opacity: 0;
}
.ao-page-meta.ao-data-refreshed::after {
    animation: ao-refresh-tick 600ms var(--ao-ease);
}
/* Standalone value-cell pulse. The ::after underline above is scoped to
 * .ao-page-meta; this rule makes .ao-data-refreshed on ANY element (table
 * cells, badges, card facts) flash a brief, subtle background so operators see
 * exactly which value changed on a tick. Black/white aesthetic, ~600ms. The
 * :not(.ao-page-meta) guard keeps the two cues from doubling up on the meta. */
.ao-data-refreshed:not(.ao-page-meta) {
    animation: ao-cell-pulse 600ms var(--ao-ease);
}
@keyframes ao-cell-pulse {
    0% {
        background-color: var(--ao-tint-strong);
    }
    60% {
        background-color: var(--ao-tint);
    }
    100% {
        background-color: transparent;
    }
}
@keyframes ao-refresh-tick {
    0% {
        transform: scaleX(0);
        opacity: 1;
    }
    50% {
        transform: scaleX(1);
        opacity: 1;
    }
    100% {
        transform: scaleX(1);
        opacity: 0;
    }
}

/* Drawer — slide in from right + backdrop fade */
.ao-drawer {
    animation: ao-drawer-in var(--ao-base) var(--ao-ease) both;
}
.ao-drawer-overlay {
    animation: ao-fade-in var(--ao-base) var(--ao-ease) both;
}
@keyframes ao-drawer-in {
    from {
        transform: translateX(100%);
    }
    to {
        transform: translateX(0);
    }
}
@keyframes ao-fade-in {
    from {
        opacity: 0.55;
    }
    to {
        opacity: 1;
    }
}

/* Drawer KV staggered reveal */
.ao-drawer .ao-kv dt,
.ao-drawer .ao-kv dd {
    animation: ao-kv-in var(--ao-base) var(--ao-ease) both;
}
@keyframes ao-kv-in {
    from {
        opacity: 0.55;
        transform: translateX(6px);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

/* Dataset tree items — entry + hover slide */
.ao-tree-item {
    transition:
        background var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease),
        padding-left var(--ao-fast) var(--ao-ease);
    animation: ao-row-in var(--ao-base) var(--ao-ease) both;
}
.ao-tree-item:hover:not(.is-active) {
    padding-left: 30px;
}

/* Live status dot pulse */
.ao-dot.live,
.ao-dot.leader {
    animation: ao-dot-pulse 1.6s ease-in-out infinite;
    /* The v2 dot has no border, so a state with no fill would vanish. */
    background: var(--ao-ok);
}
@keyframes ao-dot-pulse {
    0%,
    100% {
        opacity: 1;
    }
    50% {
        opacity: 0.45;
    }
}

/* Reduced motion — accessibility */
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])),
    :where(html:not([data-motion='full'])) *,
    :where(html:not([data-motion='full'])) *::before,
    :where(html:not([data-motion='full'])) *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
    :where(html:not([data-motion='full'])) .ao-page-head::after {
        display: none;
    }
}

/* ── Help panel (rubric reference) ─────────────────────────────────── */
.ao-help {
    position: fixed;
    top: 0;
    right: 0;
    width: 520px;
    max-width: 100vw;
    height: 100vh;
    background: var(--ao-surface);
    border-left: 1px solid var(--ao-border);
    padding: 18px 22px 24px;
    z-index: 1100;
    overflow-y: auto;
    color: var(--ao-fg);
    box-shadow:
        -2px 0 0 var(--ao-bg),
        -3px 0 0 var(--ao-border);
}
.ao-help.is-hidden {
    display: none;
}
.ao-help-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 6px;
}
.ao-help-head h2 {
    font-size: var(--ao-fs-strong);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin: 0;
}
.ao-help-close,
.ao-breakdown-close {
    background: transparent;
    color: var(--ao-fg);
    border: 1px solid var(--ao-border);
    padding: 2px 8px;
    font: inherit;
    font-size: var(--ao-fs-body);
    cursor: pointer;
}
.ao-help-close:hover,
.ao-breakdown-close:hover {
    background: var(--ao-ink);
    color: var(--ao-ink-fg);
}
.ao-help-sub {
    font-size: var(--ao-fs-meta);
    opacity: 0.7;
    border-bottom: 1px solid var(--ao-border);
    padding-bottom: 10px;
    margin: 0 0 14px 0;
}
.ao-help-section {
    margin-bottom: 18px;
}
.ao-help-section h3 {
    font-size: var(--ao-fs-meta);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin: 0 0 8px 0;
    opacity: 0.85;
}
.ao-help-code {
    background: var(--ao-surface);
    color: var(--ao-fg);
    border: 1px solid var(--ao-border);
    padding: 8px 10px;
    font-size: var(--ao-fs-body);
    margin: 0;
    overflow-x: auto;
}
.ao-help-note {
    font-size: var(--ao-fs-meta);
    opacity: 0.7;
    margin: 8px 0 0 0;
    line-height: 1.45;
}
/* Framed (2026-09-24): a reference table in the help text still reads as a
 * table, with a ruled frame and a header band. */
.ao-help-table {
    width: 100%;
    border: 1px solid var(--ao-border);
    border-collapse: collapse;
    font-size: var(--ao-fs-meta);
}
.ao-help-table th,
.ao-help-table td {
    border-bottom: 1px solid var(--ao-border-soft);
    padding: 6px 8px;
    text-align: left;
    vertical-align: top;
}
.ao-help-table th {
    background: var(--ao-surface-2);
    border-bottom: 1px solid var(--ao-border);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    opacity: 0.7;
    font-weight: 500;
}
.ao-help-factor-name {
    font-weight: 600;
    white-space: nowrap;
}
.ao-help-factor-weight {
    font-variant-numeric: tabular-nums;
    text-align: right;
    white-space: nowrap;
    width: 60px;
}
/* The TABS table's middle column is a word (the tab's group), not a weight. */
.ao-help-factor-group {
    color: var(--ao-fg-mute);
    white-space: nowrap;
}

/* ── Per-row rating clickability + breakdown popover ─────────────── */
.ao-rating.is-clickable {
    cursor: pointer;
    outline-offset: 2px;
}
.ao-rating.is-clickable:hover {
    outline: 1px solid var(--ao-border);
}
/* The grade breakdown (design system v2, 2026-09-23 rehaul b08): a Team
 * card over the scrim. ⛔ It is appended to <body>, outside #argus-ops-root,
 * so it sets the console's type itself — without this it fell back to the
 * browser's serif face — and its buttons/ids get their faces from here. */
.ao-breakdown-overlay {
    align-items: center;
    background: var(--ao-overlay);
    color: var(--ao-fg);
    display: flex;
    font-family: var(--ao-font-sans);
    font-size: var(--ao-fs-strong);
    inset: 0;
    justify-content: center;
    line-height: 1.45;
    padding: 24px 16px;
    position: fixed;
    z-index: 1200;
    -webkit-font-smoothing: antialiased;
}
.ao-breakdown {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-3);
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    max-height: 86vh;
    max-width: 560px;
    overflow-y: auto;
    padding: var(--ao-s-5);
    width: 100%;
}
.ao-breakdown .ao-sec-head.ao-breakdown-head {
    margin-bottom: 0;
}
.ao-breakdown-head > .ao-sec-h {
    font-size: var(--ao-fs-title);
}
.ao-breakdown-sum {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-4) var(--ao-s-5);
    padding: var(--ao-s-4);
}
.ao-breakdown-grade .ao-rating {
    border-radius: 14px;
    font-size: 24px;
    line-height: 1;
    min-width: 76px;
    padding: 14px 14px;
}
.ao-breakdown-meta.ao-kv {
    flex: 1 1 240px;
    font-size: var(--ao-fs-meta);
    gap: 6px var(--ao-s-4);
    grid-template-columns: 80px minmax(0, 1fr);
    margin: 0;
    min-width: 0;
}
.ao-breakdown-meta dt {
    color: var(--ao-fg-mute);
    opacity: 1;
}
.ao-breakdown-meta dd {
    align-items: center;
    display: flex;
    font-family: var(--ao-mono);
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-breakdown-meta dd .ao-state-pill,
.ao-breakdown td.ao-mono .ao-state-pill {
    font-family: var(--ao-font-sans);
}
.ao-breakdown .ao-mono,
.ao-breakdown .ao-inc-ts {
    font-family: var(--ao-mono);
    font-variant-numeric: tabular-nums;
}
.ao-breakdown-table td {
    white-space: normal;
}
.ao-breakdown-table td:first-child {
    color: var(--ao-fg);
    font-weight: 600;
    white-space: nowrap;
}
.ao-breakdown-table td:last-child {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
.ao-breakdown-table tr.is-composite > td {
    background: var(--ao-tint);
}
.ao-breakdown-hint {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    line-height: 1.45;
    margin: 0;
}
.ao-breakdown-hint .ao-ico {
    flex: none;
}
@media (max-width: 480px) {
    .ao-breakdown {
        padding: var(--ao-s-4);
    }
    .ao-breakdown-table th,
    .ao-breakdown-table td {
        padding-left: 8px;
        padding-right: 8px;
    }
}

/* ── Onboarding admin (per-tenant skip/seed/reset) ────────────────────── */
/* Design system v2 (2026-09-23, batch b02): the picker is a card, the four
 * actions are Team-style cards with an icon tile and the account they will
 * hit, and the live state is a KPI strip over a stepper. */

.ao-onb-page {
    max-width: 1080px;
}

.ao-onb-picker {
    align-items: center;
    display: grid;
    gap: 10px var(--ao-s-3);
    grid-template-columns: auto minmax(0, 1fr) auto;
}

.ao-onb-picker-label {
    align-items: center;
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    gap: 6px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.ao-onb-pick {
    min-width: 0;
}
/* The trigger fills its slot (it was 370px of an 880px slot, so the right
 * half of what looked like the control did nothing) at the 32px floor. */
.ao-onb-pick .ao-picker-trigger {
    background: var(--ao-tint);
    border-color: var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    min-height: 32px;
    min-width: 0;
    padding: 6px 10px 6px 12px;
    width: 100%;
}
.ao-onb-pick .ao-picker-trigger:hover {
    background: var(--ao-tint-2);
    border-color: var(--ao-border);
}
.ao-onb-pick .ao-picker-caret {
    display: inline-grid;
    opacity: 0.75;
    place-items: center;
}

.ao-onb-input {
    background: var(--ao-surface);
    border: 1px solid var(--ao-tint-line);
    color: var(--ao-fg);
    padding: 8px 10px;
    border-radius: var(--ao-r-md);
    font-family: inherit;
    font-size: var(--ao-fs-body);
}

.ao-onb-input:focus {
    /* No `outline:none` here — that would defeat the global :focus-visible ring
     * for keyboard users. The border/box-shadow are an additional affordance. */
    border-color: var(--ao-focus);
    box-shadow: 0 0 0 3px var(--ao-focus-glow);
}

.ao-onb-hint {
    font-size: var(--ao-fs-meta);
    color: var(--ao-fg-mute);
    grid-column: 1 / -1;
    line-height: 1.5;
    margin: 0;
}

.ao-onb-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: var(--ao-s-3);
}

/* The Team card as a button: gradient, 16px radius, inset highlight; it
 * lifts because it IS a control. Danger cards carry the err ring. */
.ao-onb-card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    color: inherit;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    font-family: inherit;
    gap: 6px;
    padding: 16px;
    text-align: left;
    transition:
        transform var(--ao-base) var(--ao-ease),
        box-shadow var(--ao-base) var(--ao-ease),
        border-color var(--ao-base) var(--ao-ease);
}

.ao-onb-card:hover,
.ao-onb-card:focus-visible {
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-2);
    transform: translateY(-2px);
}

.ao-onb-card:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}

.ao-onb-card:active {
    transform: translateY(0);
}

.ao-onb-card-top {
    align-items: center;
    display: flex;
    justify-content: space-between;
    margin-bottom: 4px;
}

.ao-onb-card-ico {
    background: color-mix(in srgb, var(--ao-k-5) 14%, transparent);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ao-k-5) 24%, transparent);
    color: var(--ao-k-5);
    display: grid;
    height: 32px;
    place-items: center;
    width: 32px;
}

.ao-onb-card-title {
    font-size: var(--ao-fs-title);
    font-weight: 600;
    color: var(--ao-fg);
}

.ao-onb-card-desc {
    font-size: var(--ao-fs-body);
    color: var(--ao-fg-mute);
    flex: 1 1 auto;
    line-height: 1.45;
}

.ao-onb-card-target {
    align-items: center;
    border-top: 1px solid var(--ao-tint-line);
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    margin-top: 6px;
    min-width: 0;
    padding-top: 10px;
}

.ao-onb-card-who {
    color: var(--ao-fg-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ao-onb-card.is-danger {
    border-color: var(--ao-err-border);
}

.ao-onb-card.is-danger .ao-onb-card-ico {
    background: var(--ao-err-bg);
    box-shadow: inset 0 0 0 1px var(--ao-err-bd);
    color: var(--ao-err-fg);
}

.ao-onb-card.is-danger:hover,
.ao-onb-card.is-danger:focus-visible {
    border-color: var(--ao-err-border-strong);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        0 0 0 1px var(--ao-err-border),
        var(--ao-elev-2);
}

/* Which account a press hits: plain text (blue read as a link), and the err
 * colour on the two destructive cards. */
.ao-onb-card.is-danger .ao-onb-card-target {
    color: var(--ao-err-fg);
}
.ao-onb-card.is-danger .ao-onb-card-who {
    color: var(--ao-err-fg);
}

/* Busy: the pressed card spins, the rest stand down until it settles. */
.ao-onb-card-spin {
    border: 2px solid var(--ao-tint-strong);
    border-radius: 50%;
    border-top-color: var(--ao-fg);
    display: none;
    height: 16px;
    width: 16px;
}

.ao-onb-card.is-busy .ao-onb-card-spin {
    animation: ao-onb-spin 0.8s linear infinite;
    display: block;
}

@keyframes ao-onb-spin {
    to {
        transform: rotate(360deg);
    }
}

.ao-onb-grid.is-busy .ao-onb-card:not(.is-busy) {
    cursor: progress;
    opacity: 0.55;
}

.ao-onb-status {
    align-items: center;
    align-self: flex-start;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-body);
    gap: 6px;
    padding: 5px 12px;
}

.ao-onb-status:empty {
    display: none;
}

.ao-onb-status.is-busy {
    color: var(--ao-fg-dim);
}

.ao-onb-status.is-ok {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}

.ao-onb-status.is-err {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}

/* Static module display — replaces the former native <select> (single option
   'argus'). Read-only label/value chip, no dropdown. */
.ao-onb-module-static {
    display: flex;
    align-items: baseline;
    border-radius: var(--ao-r-ctl);
    gap: 8px;
    cursor: default;
    padding: 6px 12px;
}

.ao-onb-module-label {
    font-size: var(--ao-fs-label);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ao-fg-dim);
}

.ao-onb-module-value {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-body);
    font-weight: 600;
    color: var(--ao-fg);
}

/* ── Onboarding live state panel (U12) ───────────────────────────────────── */
.ao-onb-state {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
}

.ao-onb-state > .ao-sec-head {
    margin-bottom: 0;
}

/* Nothing picked yet / no steps: the shared centred .ao-empty panel, flush
 * in this column. */
.ao-onb-state > .ao-empty {
    margin: 0;
}
.ao-onb-state-empty {
    align-items: center;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.ao-onb-state-empty-ico {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-lg);
    color: var(--ao-fg-dim);
    display: grid;
    height: 38px;
    place-items: center;
    width: 38px;
}
.ao-onb-state-who {
    align-items: baseline;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 2px 8px;
    min-width: 0;
}
.ao-onb-state-name {
    color: var(--ao-fg-dim);
}
.ao-onb-state-id {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}

.ao-onb-state-overall {
    font-size: var(--ao-fs-label);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 2px 10px;
    border-radius: var(--ao-r-tag);
    border: 1px dashed var(--ao-border);
    color: var(--ao-fg-mute);
}

.ao-onb-state-overall.is-complete {
    background: var(--ao-ok-bg);
    border-style: solid;
    color: var(--ao-ok-text);
    border-color: var(--ao-ok-border);
}

.ao-onb-state-overall.is-in_progress {
    background: var(--ao-warn-bg);
    border-style: solid;
    color: var(--ao-warn);
    border-color: var(--ao-warn-border);
}

/* The stepper: a numbered / iconned marker per step on a connecting rail. */
.ao-onb-steps {
    display: flex;
    flex-direction: column;
    list-style: none;
    margin: 0;
    padding: 6px 16px;
}

.ao-onb-step {
    align-items: flex-start;
    border-bottom: 1px solid var(--ao-tint-line);
    display: flex;
    gap: var(--ao-s-3);
    padding: 12px 0;
    position: relative;
}

.ao-onb-step:last-child {
    border-bottom: 0;
}

.ao-onb-step-mark {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border);
    border-radius: 50%;
    color: var(--ao-fg-mute);
    display: grid;
    flex: none;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    height: 26px;
    place-items: center;
    position: relative;
    width: 26px;
    z-index: 1;
}

/* The rail between markers. */
.ao-onb-step:not(:last-child)::before {
    background: var(--ao-border-soft);
    bottom: -13px;
    content: '';
    left: 12px;
    position: absolute;
    top: 38px;
    width: 2px;
}

.ao-onb-step.is-verified:not(:last-child)::before {
    background: var(--ao-ok-bd);
}

.ao-onb-step.is-verified .ao-onb-step-mark {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}

.ao-onb-step.is-claimed .ao-onb-step-mark {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}

.ao-onb-step.is-failed .ao-onb-step-mark {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}

.ao-onb-step.is-next .ao-onb-step-mark {
    box-shadow: 0 0 0 3px var(--ao-info-soft);
    border-color: var(--ao-info-border);
    color: var(--ao-info-fg);
}

.ao-onb-step-main {
    flex: 1 1 auto;
    min-width: 0;
}

.ao-onb-step-label {
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    color: var(--ao-fg);
}

.ao-onb-step-desc {
    font-size: var(--ao-fs-meta);
    color: var(--ao-fg-mute);
    line-height: 1.4;
    margin-top: 2px;
}

.ao-onb-step-when {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    margin-top: 4px;
}

.ao-onb-step.is-failed .ao-onb-step-when {
    color: var(--ao-err-fg);
}

.ao-onb-step-next {
    align-self: center;
    background: var(--ao-info-bg);
    border: 1px solid var(--ao-info-bd);
    border-radius: var(--ao-r-tag);
    color: var(--ao-info-fg);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.05em;
    padding: 1px 8px;
    text-transform: uppercase;
}

.ao-onb-step-status {
    align-self: center;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 1px 8px;
    border-radius: var(--ao-r-tag);
    white-space: nowrap;
    color: var(--ao-fg-mute);
    border: 1px dashed var(--ao-border);
}

.ao-onb-step-status.is-verified {
    background: var(--ao-ok-bg);
    border-style: solid;
    color: var(--ao-ok-text);
    border-color: var(--ao-ok-border);
}

.ao-onb-step-status.is-claimed {
    background: var(--ao-warn-bg);
    border-style: solid;
    color: var(--ao-warn);
    border-color: var(--ao-warn-border);
}

.ao-onb-step-status.is-failed {
    background: var(--ao-err-bg);
    border-style: solid;
    color: var(--ao-err);
    border-color: var(--ao-err-border);
}

@media (max-width: 760px) {
    .ao-onb-picker {
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-onb-pick .ao-picker-trigger {
        min-width: 0;
        width: 100%;
    }
    .ao-onb-module-static {
        justify-self: start;
    }
    .ao-onb-step {
        flex-wrap: wrap;
    }
    .ao-onb-step-main {
        flex-basis: calc(100% - 40px);
    }
    .ao-onb-step-next,
    .ao-onb-step-status {
        margin-left: 38px;
    }
    .ao-onb-step-next + .ao-onb-step-status {
        margin-left: 0;
    }
}

/* ══ TENANT TABS REHAUL (batch b02, design system v2, 2026-09-23) ══════════
 * Notify, Onboarding (admin + live), the tenant detail sub-tabs (users,
 * cameras, agent, metrics, activity) and #/timeline, on the Team page's
 * pieces: aoStat KPI strips, aoTable / .ao-table-wrap.is-card tables,
 * aoSection heads, .ao-card panels and .ao-btn variants. Tokens only (no
 * hex, comments included); every entrance is transform-only or rides the
 * shared .ao-in (0.55 floor). Reduced-motion entries live in this section's
 * own block below, never at the end of the file. */

/* Shared by the b02 pages: a form control's look (the tselect trigger is a
 * square system box everywhere else), and [hidden] restated because every
 * slot here sets its own display. */
.ao-ntf-page [hidden],
.ao-ttab-panel [hidden],
.ao-onb-page [hidden] {
    display: none !important;
}
.ao-ntf-page .ao-input,
.ao-ttab-panel .ao-input,
.ao-onb-page .ao-input {
    border-radius: var(--ao-r-md);
    padding: 8px 11px;
}
/* .ao-tusr-overlay: the user modals (Change role's NEW ROLE picker) are
 * appended to the body, outside .ao-ttab-panel. */
.ao-ntf-page .ao-tselect,
.ao-ttab-panel .ao-tselect,
.ao-tusr-overlay .ao-tselect {
    display: block;
}
.ao-ntf-page .ao-tselect-trigger,
.ao-ttab-panel .ao-tselect-trigger,
.ao-tusr-overlay .ao-tselect-trigger {
    border-color: var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    min-height: 34px;
    padding: 8px 11px;
}
.ao-ntf-page .ao-tselect-trigger:hover,
.ao-ttab-panel .ao-tselect-trigger:hover,
.ao-tusr-overlay .ao-tselect-trigger:hover {
    border-color: var(--ao-border);
}
.ao-ntf-page .ao-tselect-menu,
.ao-ttab-panel .ao-tselect-menu,
.ao-tusr-overlay .ao-tselect-menu {
    border-radius: 0 0 var(--ao-r-md) var(--ao-r-md);
}
/* The arrow is drawn, as Onboarding admin's picker draws it: a chevron mask
 * over currentColor (a typed ▾ sat on the text baseline, a size too big). */
.ao-ntf-page .ao-tselect-trigger::after,
.ao-ttab-panel .ao-tselect-trigger::after,
.ao-tusr-overlay .ao-tselect-trigger::after {
    background: currentColor;
    content: '';
    float: right;
    height: 14px;
    margin: 1px 0 0 8px;
    opacity: 0.7;
    width: 14px;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E")
        center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E")
        center / contain no-repeat;
}

/* ── Notify (#/notify) ───────────────────────────────────────────────────── */
.ao-ntf-page {
    container-type: inline-size;
}
.ao-ntf-grid {
    align-items: start;
    display: grid;
    gap: var(--ao-s-4);
    grid-template-columns: minmax(0, 1fr) minmax(300px, 380px);
}
@container (max-width: 860px) {
    .ao-ntf-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}
.ao-ntf-compose {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
.ao-ntf-side {
    min-width: 0;
    position: sticky;
    top: var(--ao-s-4);
}
.ao-ntf-step,
.ao-ntf-review {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
}
.ao-ntf-step.ao-card > .ao-sec-head,
.ao-ntf-review.ao-card > .ao-sec-head {
    margin-bottom: 0;
}
.ao-ntf-num {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-body);
    font-weight: 600;
    transition:
        background var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease);
}
/* A step whose checklist facts hold: its number tile turns to an ok check.
 * svg.*: the icon set's own .ao-ico {display:block} comes later. */
.ao-ntf-num svg.ao-ntf-num-ok {
    display: none;
}
.ao-ntf-step.is-done .ao-ntf-num {
    background: var(--ao-ok-bg);
    box-shadow: inset 0 0 0 1px var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-ntf-step.is-done .ao-ntf-num-n {
    display: none;
}
.ao-ntf-step.is-done .ao-ntf-num svg.ao-ntf-num-ok {
    display: block;
}
.ao-ntf-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-ntf-hint {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
    margin: 0;
}
.ao-ntf-aud {
    align-self: flex-start;
}
.ao-ntf-tenant {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-width: 440px;
}
.ao-ntf-channels {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.ao-ntf-ch {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    cursor: pointer;
    display: flex;
    gap: var(--ao-s-3);
    min-width: 0;
    padding: 12px 12px 12px 14px;
    transition:
        background var(--ao-fast) var(--ao-ease),
        border-color var(--ao-fast) var(--ao-ease);
}
.ao-ntf-ch:hover {
    background: var(--ao-tint-2);
    border-color: var(--ao-border);
}
.ao-ntf-ch.is-on {
    background: var(--ao-tint-2);
    border-color: var(--ao-border);
}
.ao-ntf-ch-ico {
    background: var(--ao-tint-2);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-mute);
    display: grid;
    flex: none;
    height: 32px;
    place-items: center;
    transition: color var(--ao-fast) var(--ao-ease);
    width: 32px;
}
.ao-ntf-ch.is-on .ao-ntf-ch-ico {
    background: color-mix(in srgb, var(--ao-k-5) 14%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ao-k-5) 28%, transparent);
    color: var(--ao-k-5);
}
/* An on channel's switch wears its tile's blue, not the neutral accent. */
.ao-ntf-ch.is-on .ao-switch[aria-checked='true'] .ao-switch-track,
.ao-ntf-ch.is-on .ao-switch[aria-checked='true']:hover:not(:disabled) .ao-switch-track {
    background: var(--ao-k-5);
    border-color: var(--ao-k-5);
}
.ao-ntf-ch-text {
    flex: 1 1 auto;
    min-width: 0;
}
.ao-ntf-ch-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
}
.ao-ntf-ch-sub {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    line-height: 1.4;
    margin-top: 2px;
}
.ao-ntf-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.ao-ntf-field-top {
    align-items: baseline;
    display: flex;
    gap: var(--ao-s-2);
    justify-content: space-between;
}
.ao-ntf-count {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}
.ao-ntf-count.is-near {
    color: var(--ao-warn-text);
}
.ao-ntf-page .ao-ntf-subject {
    font-size: var(--ao-fs-strong);
}
.ao-ntf-page .ao-ntf-body {
    font-family: inherit;
    line-height: 1.55;
    min-height: 150px;
}
.ao-ntf-checks {
    display: grid;
    gap: 6px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-ntf-check {
    align-items: center;
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: var(--ao-s-2);
}
/* A still-open item: a solid ring (a dashed one all but vanished on the
 * card), empty until the fact is true. */
.ao-ntf-check-ico {
    border: 1.5px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: transparent;
    display: grid;
    flex: none;
    height: 18px;
    place-items: center;
    width: 18px;
}
.ao-ntf-check.is-done {
    color: var(--ao-fg);
}
.ao-ntf-check.is-done .ao-ntf-check-ico {
    background: var(--ao-ok-bg);
    border: 1px solid var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-ntf-idle {
    align-items: center;
    background: var(--ao-tint);
    border: 1px dashed var(--ao-border);
    border-radius: var(--ao-r-lg);
    display: flex;
    gap: var(--ao-s-3);
    padding: 14px;
}
.ao-ntf-idle-ico {
    background: var(--ao-tint-2);
    border-radius: 10px;
    color: var(--ao-fg-mute);
    display: grid;
    flex: none;
    height: 36px;
    place-items: center;
    width: 36px;
}
.ao-ntf-idle-text {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
}
.ao-ntf-result {
    display: flex;
    flex-direction: column;
    gap: 10px;
    transition: opacity var(--ao-base) var(--ao-ease);
}
.ao-ntf-result.is-fresh {
    animation: ao-ntf-pop 420ms var(--ao-ease);
}
@keyframes ao-ntf-pop {
    from {
        transform: translateY(6px) scale(0.985);
    }
    to {
        transform: none;
    }
}
.ao-ntf-result.is-stale > :not(.ao-ntf-stale) {
    opacity: 0.55;
}
.ao-ntf-stale {
    display: none;
}
.ao-ntf-result.is-stale .ao-ntf-stale {
    color: var(--ao-warn-text);
    display: block;
    font-size: var(--ao-fs-meta);
}
.ao-ntf-result-head {
    align-items: flex-start;
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: var(--ao-s-2);
    line-height: 1.45;
}
.ao-ntf-result-ico {
    background: var(--ao-info-bg);
    border: 1px solid var(--ao-info-bd);
    border-radius: 50%;
    color: var(--ao-info-fg);
    display: grid;
    flex: none;
    height: 20px;
    place-items: center;
    width: 20px;
}
.ao-ntf-result.is-sent .ao-ntf-result-ico {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-ntf-result .ao-ntf-kpis.ao-stat-row {
    grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
}
.ao-ntf-sms {
    align-items: center;
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
}
.ao-ntf-sample {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.ao-ntf-from {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}
.ao-ntf-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ao-ntf-chip {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    max-width: 100%;
    overflow: hidden;
    padding: 2px 8px;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-ntf-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
}
.ao-ntf-actions .ao-btn {
    flex: 1 1 auto;
    justify-content: center;
}
/* A ready broadcast SEND is the one final action: filled, not a faint
 * outline weaker than the PREVIEW it follows. */
.ao-ntf-review .ao-btn.is-danger:not(:disabled) {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-border-strong);
}
.ao-ntf-gate {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.45;
    margin: 0;
}
.ao-ntf-gate.is-ready {
    color: var(--ao-fg-dim);
}

/* ── Onboarding live (#/onboarding-live) ─────────────────────────────────── */
.ao-olv-board {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
}
.ao-olv-head .ao-sec-head {
    margin-bottom: 0;
}
/* The head's subtitle: the tenant count, then the live-dot legend as a
 * drawn dot (the prose that used to sit under the head is the page's ? help). */
.ao-olv-sub {
    align-items: center;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 4px 12px;
}
.ao-olv-legend {
    align-items: center;
    display: inline-flex;
    gap: 6px;
}
.ao-olv-legend-dot {
    background: var(--ao-ok);
    border-radius: 50%;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--ao-ok) 22%, transparent);
    display: inline-block;
    height: 7px;
    width: 7px;
}
.ao-olv-tbl td {
    vertical-align: middle;
}
.ao-olv-tenant {
    max-width: 260px;
}
.ao-olv-name {
    color: var(--ao-fg);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-olv-id {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    margin-top: 1px;
}
.ao-olv-muted {
    color: var(--ao-fg-dim);
}
.ao-olv-step {
    color: var(--ao-fg-dim);
}
.ao-olv-page.is-live {
    color: var(--ao-ok-text);
    font-weight: 500;
}
/* The live ● is a character (tests read it) drawn as a pulsing dot:
 * transform-only, so a paused animation leaves it fully visible. */
.ao-olv-dot {
    color: var(--ao-ok);
    display: inline-block;
    font-size: 9px;
    transform-origin: center;
    vertical-align: 1px;
}
.ao-olv-page.is-live .ao-olv-dot {
    animation: ao-olv-beat 1.6s var(--ao-ease) infinite;
}
@keyframes ao-olv-beat {
    0%,
    100% {
        transform: scale(1);
    }
    50% {
        transform: scale(1.45);
    }
}
.ao-olv-prog {
    min-width: 96px;
}
.ao-olv-prog-val {
    color: var(--ao-fg-dim);
    display: inline-block;
    font-size: var(--ao-fs-meta);
    min-width: 28px;
}
.ao-olv-track {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: inline-block;
    height: 5px;
    margin-left: 8px;
    overflow: hidden;
    vertical-align: middle;
    width: 56px;
}
.ao-olv-fill {
    background: linear-gradient(90deg, var(--ao-k-5), var(--ao-k-1));
    border-radius: inherit;
    display: block;
    height: 100%;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform var(--ao-slow) var(--ao-ease);
}
.ao-olv-row.is-done .ao-olv-fill {
    background: var(--ao-ok);
}
/* In progress is the healthy state: the funnel's own blue, solid. Only a
 * sign-up quiet for over a day keeps the warning orange (is-warn). */
.ao-olv-tbl .ao-state-pill.ao-olv-st-live {
    background: color-mix(in srgb, var(--ao-k-5) 12%, transparent);
    border-color: color-mix(in srgb, var(--ao-k-5) 40%, transparent);
    border-style: solid;
    color: var(--ao-k-5);
}
/* '-' and a finished row's on-page time are "nothing here", not readings. */
.ao-olv-tbl td.is-nil {
    color: var(--ao-fg-mute);
}
.ao-olv-funnel {
    display: flex;
    flex-direction: column;
}
.ao-olv-steps {
    display: grid;
    gap: 8px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-olv-fstep {
    align-items: center;
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: 22px minmax(120px, 200px) minmax(0, 1fr) 44px;
}
.ao-olv-fnum {
    background: var(--ao-tint-2);
    border-radius: 6px;
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    line-height: 20px;
    text-align: center;
}
.ao-olv-flabel {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-olv-fstep .ao-olv-track {
    height: 8px;
    margin: 0;
    width: 100%;
}
.ao-olv-fval {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    text-align: right;
}
@media (max-width: 760px) {
    .ao-olv-fstep {
        grid-template-columns: 22px minmax(0, 1fr) 40px;
    }
    .ao-olv-fstep .ao-olv-track {
        grid-column: 2 / 4;
        grid-row: 2;
    }
    /* A phone drops FIELD, ON-PAGE and STARTED (columns 3, 7, 9) so STATUS
     * and PROGRESS are on screen; the cells stay in the row. */
    .ao-olv-tbl th:nth-child(3),
    .ao-olv-tbl td:nth-child(3),
    .ao-olv-tbl th:nth-child(7),
    .ao-olv-tbl td:nth-child(7),
    .ao-olv-tbl th:nth-child(9),
    .ao-olv-tbl td:nth-child(9) {
        display: none;
    }
    /* CURRENT STEP (column 4) too: the progress bar already says it. */
    .ao-olv-tbl th:nth-child(4),
    .ao-olv-tbl td:nth-child(4) {
        display: none;
    }
    .ao-olv-tenant {
        max-width: 150px;
    }
    /* The pinned tenant cell carries the row's status as an edge, so it
     * shows before any sideways scroll: blue in progress, green done,
     * orange when quiet for over a day. */
    .ao-olv-tbl td.ao-olv-tenant {
        box-shadow: inset 3px 0 var(--ao-k-5);
    }
    .ao-olv-tbl .ao-olv-row.is-done td.ao-olv-tenant {
        box-shadow: inset 3px 0 var(--ao-ok);
    }
    .ao-olv-tbl .ao-olv-row.is-quiet td.ao-olv-tenant {
        box-shadow: inset 3px 0 var(--ao-warn);
    }
}

/* ── Tenant detail sub-tabs (users / cameras / agent / metrics / activity) ── */
/* Each sub-panel is a flex column, so its head, KPI strip and table card
 * space themselves (the tab panel already pads the top). */
.ao-ttab-panel {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
.ao-ttab-panel > .ao-sec-head {
    margin-bottom: 0;
}
/* A tab's two panels (users + invites) read as one column. */
.ao-ttab-panel + .ao-ttab-panel {
    margin-top: var(--ao-s-6);
}
.ao-ttab-panel > .ao-card-grid {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
/* A phone fits two KPI cards a row; an odd last card takes the whole row
 * instead of leaving a hole beside it. */
@media (max-width: 560px) {
    .ao-ttab-panel .ao-stat-row > .ao-stat:last-child:nth-child(odd),
    .ao-olv-kpis .ao-stat-row > .ao-stat:last-child:nth-child(odd),
    .ao-onb-state .ao-stat-row > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
}
/* A KPI card whose value is words (a relative time, a step name): the sans
 * face at a heading size, wrapping instead of running out of the card. */
/* span.ao-stat-num, not a bare .ao-stat-num: the design-system test reads
 * the first rule ending in ` .ao-stat-num {` as the primitive's own. The id
 * outranks the MONO rule at the top of the file. */
#argus-ops-root .ao-ttab-textstat span.ao-stat-num {
    font-family: var(--ao-font-sans);
    font-size: var(--ao-fs-h);
    letter-spacing: -0.01em;
    line-height: 1.2;
    white-space: normal;
}
/* Row actions: one right-aligned row of small pills. */
.ao-ttab-acts {
    align-items: center;
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
    justify-content: flex-end;
}
.ao-ttab-callout {
    align-items: flex-start;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: var(--ao-s-2);
    line-height: 1.45;
    padding: 10px 12px;
}
.ao-ttab-callout.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    box-shadow: inset 3px 0 0 var(--ao-warn);
    color: var(--ao-warn-text);
}
.ao-ttab-callout .ao-ico {
    flex: none;
    margin-top: 1px;
}
.ao-note.ao-ttab-note {
    align-items: flex-start;
    background: var(--ao-info-bg);
    border: 1px solid var(--ao-info-bd);
    border-radius: var(--ao-r-lg);
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: var(--ao-s-2);
    line-height: 1.5;
    margin: 0;
    max-width: none;
    padding: 10px 12px;
}
.ao-note.ao-ttab-note .ao-ico {
    color: var(--ao-info-fg);
    flex: none;
    margin-top: 2px;
}

/* An identity's id line (the agents table's pinned column) at a readable
 * contrast: mute was 3.5:1 on the pinned phone column's surface. */
.ao-ttab-panel .ao-identity-id {
    color: var(--ao-fg-dim);
}

/* The shared agents table keeps its wrapping action cell; in this tab it
 * gets room for two buttons a line instead of one (a phone stacked all four
 * and each row grew to 140px). */
.ao-ttab-panel .ao-agents td:has(> .ao-actrow) {
    min-width: 290px;
}

/* Two heads keep an uppercase literal their tests read ('USERS (n)',
 * 'TIMELINE'); drawn in sentence case like every other head on the page. */
.ao-ttab-sentence .ao-sec-h {
    text-transform: lowercase;
}
.ao-ttab-sentence .ao-sec-h::first-letter {
    text-transform: uppercase;
}

/* A KPI card's ratio bar (aoStat `pct`: active of members, online of
 * enrolled, steps verified, days sampled): a full-width track at the card's
 * foot in the card's own hue. A card with a state (cameras ONLINE) keeps the
 * state's ok / warn / err fill. span.*: the primitive tests read the first
 * rule ending in the bare class. */
.ao-ttab-panel .ao-stat > span.ao-state-bar,
.ao-onb-state .ao-stat > span.ao-state-bar,
.ao-olv-kpis .ao-stat > span.ao-state-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: block;
    height: 5px;
    margin-top: auto;
    min-width: 0;
    width: 100%;
}
.ao-ttab-panel .ao-stat > span.ao-state-bar span.ao-state-bar-fill,
.ao-onb-state .ao-stat > span.ao-state-bar span.ao-state-bar-fill,
.ao-olv-kpis .ao-stat > span.ao-state-bar span.ao-state-bar-fill {
    border-radius: inherit;
}
.ao-ttab-panel .ao-stat > span.ao-state-bar.is-unknown span.ao-state-bar-fill,
.ao-onb-state .ao-stat > span.ao-state-bar.is-unknown span.ao-state-bar-fill,
.ao-olv-kpis .ao-stat > span.ao-state-bar.is-unknown span.ao-state-bar-fill {
    background: linear-gradient(
        90deg,
        color-mix(in srgb, var(--ao-stat-accent, var(--ao-k-1)) 55%, transparent),
        var(--ao-stat-accent, var(--ao-k-1))
    );
}
.ao-ttab-panel .ao-stat > span.ao-state-bar span.ao-state-bar-label,
.ao-onb-state .ao-stat > span.ao-state-bar span.ao-state-bar-label,
.ao-olv-kpis .ao-stat > span.ao-state-bar span.ao-state-bar-label {
    display: none;
}

/* A bar column's number sits on the row's line; the track rides the cell's
 * foot instead of pushing the number up (the cell is padded 9px / 12px). */
.ao-tcam-table td.has-bar,
.ao-tmet-table td.has-bar {
    position: relative;
}
.ao-tcam-table td.has-bar span.ao-table-bar,
.ao-tmet-table td.has-bar span.ao-table-bar {
    bottom: 7px;
    left: 12px;
    margin: 0;
    position: absolute;
    right: 12px;
}
/* The shared fill is the brand rose, which reads as an error. More frames
 * is good (green); alerts are a warning. Cameras: FPS is column 3 and
 * ALERTS 24H column 7 (_tcamTable's order). span.*, not a bare class: the
 * design-system test reads the first rule ending in the primitive's class. */
.ao-tcam-table td:nth-child(3) span.ao-table-bar-fill,
.ao-tmet-table span.ao-table-bar-fill {
    background: linear-gradient(90deg, color-mix(in srgb, var(--ao-k-1) 45%, transparent), var(--ao-k-1));
}
.ao-tcam-table td:nth-child(7) span.ao-table-bar-fill {
    background: linear-gradient(90deg, color-mix(in srgb, var(--ao-warn) 45%, transparent), var(--ao-warn));
}

/* Phone: every table here scrolls sideways inside its card; its first
 * column (who / which) stays pinned so the scrolled-to status and actions
 * still say whose they are. */
@media (max-width: 760px) {
    .ao-ttab-panel .ao-table th:first-child,
    .ao-ttab-panel .ao-table td:first-child,
    .ao-olv-tbl th:first-child,
    .ao-olv-tbl td:first-child {
        background: var(--ao-surface-2);
        left: 0;
        position: sticky;
        z-index: 1;
    }
    .ao-ttab-panel .ao-table th:first-child,
    .ao-olv-tbl th:first-child {
        z-index: 2;
    }
    .ao-ttab-panel .ao-table tr:hover td:first-child,
    .ao-olv-tbl tr:hover td:first-child {
        background: linear-gradient(var(--ao-hover), var(--ao-hover)), var(--ao-surface-2);
    }
    /* The agent's full uuid made the pinned column 245px of a 350px card;
     * the identity already ellipsizes, so just give it less room. */
    .ao-ttab-panel .ao-agents td:first-child .ao-identity {
        max-width: 140px;
    }
    /* Cameras: LAST STATUS POST, AGENT and DEVICE (columns 4-6) drop out so the
     * liveness, FPS and alerts sit beside the pinned name; the cells stay in
     * the row. */
    .ao-tcam-table th:nth-child(4),
    .ao-tcam-table td:nth-child(4),
    .ao-tcam-table th:nth-child(5),
    .ao-tcam-table td:nth-child(5),
    .ao-tcam-table th:nth-child(6),
    .ao-tcam-table td:nth-child(6) {
        display: none;
    }
    /* VIEW LIVE and DEREGISTER go icon-only, as the users row does: the
     * same 28px ringed circle, the label still the button's text. */
    .ao-tcam-table .ao-ttab-acts .ao-btn {
        background: var(--ao-surface);
        border: 1px solid var(--ao-border-soft);
        height: 28px;
        min-height: 28px;
        min-width: 28px;
        padding: 0;
        width: 28px;
    }
    .ao-tcam-table .ao-ttab-acts .ao-btn .ao-btn-label {
        clip-path: inset(50%);
        height: 1px;
        overflow: hidden;
        position: absolute;
        white-space: nowrap;
        width: 1px;
    }
}

/* ── Users + invites ── */
.ao-tusr-table td,
.ao-tusr-inv td {
    vertical-align: middle;
}
.ao-tusr-who {
    align-items: center;
    display: flex;
    gap: 10px;
    max-width: 320px;
    min-width: 0;
}
.ao-tusr-av {
    flex: none;
}
.ao-tusr-email-txt {
    color: var(--ao-fg);
    font-weight: 500;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-tusr-name {
    color: var(--ao-fg-dim);
}
.ao-tusr-muted,
.ao-tusr-table .ao-tusr-muted {
    color: var(--ao-fg-dim);
}
.ao-tusr-role {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-block;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.04em;
    padding: 1px 8px;
    text-transform: uppercase;
}
.ao-tusr-role.is-owner,
.ao-tusr-role.is-admin {
    background: color-mix(in srgb, var(--ao-k-2) 14%, transparent);
    border-color: color-mix(in srgb, var(--ao-k-2) 34%, transparent);
    color: var(--ao-fg);
}
.ao-tusr-inv-st {
    background: var(--ao-info-bg);
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-tusr-acts {
    text-align: right;
    width: 1%;
}
.ao-tusr-table th.ao-tusr-acts {
    text-align: right;
}
.ao-tusr-table td.ao-tusr-acts,
.ao-tusr-inv td.ao-tusr-acts {
    max-width: none;
    overflow: visible;
}
.ao-tusr-ghost .ao-ico {
    color: var(--ao-k-1);
}
/* Wide: IMPERSONATE is the row's one labelled pill; VIEW, ROLE, SUSPEND /
 * ACTIVATE and REMOVE are 28px ringed icon circles (the label leaves the
 * layout but stays the button's text: its accessible name, and what the
 * tests read; the title names it on hover). REMOVE rests quiet and turns red
 * only on its own row, so five red pills no longer shout down the table. */
@media (min-width: 761px) {
    .ao-tusr-table .ao-tusr-acts .ao-btn:not(.ao-tusr-ghost) {
        background: var(--ao-surface);
        border-color: var(--ao-border-soft);
        box-shadow:
            inset 0 1px 0 var(--ao-tint),
            var(--ao-elev-1);
        color: var(--ao-fg-dim);
        height: 28px;
        min-height: 28px;
        min-width: 28px;
        padding: 0;
        width: 28px;
    }
    .ao-tusr-table .ao-tusr-acts .ao-btn:not(.ao-tusr-ghost):hover:not(:disabled) {
        background: var(--ao-hover);
        border-color: var(--ao-border);
        color: var(--ao-fg);
    }
    .ao-tusr-table .ao-tusr-acts .ao-btn:not(.ao-tusr-ghost) .ao-ico {
        height: 14px;
        width: 14px;
    }
    .ao-tusr-table .ao-tusr-acts .ao-btn:not(.ao-tusr-ghost) .ao-btn-label {
        clip-path: inset(50%);
        height: 1px;
        overflow: hidden;
        position: absolute;
        white-space: nowrap;
        width: 1px;
    }
    .ao-tusr-table .ao-tusr-acts .ao-btn[data-role='act-remove'] {
        background: transparent;
        border-color: transparent;
        box-shadow: none;
        color: var(--ao-fg-mute);
    }
    .ao-tusr-table tr:hover .ao-tusr-acts .ao-btn[data-role='act-remove'],
    .ao-tusr-table tr:focus-within .ao-tusr-acts .ao-btn[data-role='act-remove'],
    .ao-tusr-table .ao-tusr-acts .ao-btn[data-role='act-remove']:focus-visible {
        border-color: var(--ao-err-bd);
        color: var(--ao-err-fg);
    }
    .ao-tusr-table .ao-tusr-acts .ao-btn[data-role='act-remove']:hover:not(:disabled) {
        background: var(--ao-err-bg);
        border-color: var(--ao-err-border-strong);
        color: var(--ao-err-fg);
    }
}
.ao-tusr-empty {
    color: var(--ao-fg-mute);
    padding: 18px 16px;
    text-align: center;
}
.ao-tusr-invite {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
}
.ao-tusr-invite.ao-card > .ao-sec-head {
    margin-bottom: 0;
}
.ao-tusr-form {
    align-items: center;
    display: grid;
    gap: var(--ao-s-2);
    grid-template-columns: minmax(0, 1fr) minmax(130px, 170px) auto;
}
.ao-tusr-email {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    position: relative;
}
.ao-tusr-email .ao-ico {
    left: 11px;
    pointer-events: none;
    position: absolute;
}
.ao-ttab-panel .ao-tusr-email .ao-input {
    padding-left: 32px;
}
.ao-tusr-inv-ico {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-ctl);
    color: var(--ao-fg-mute);
    display: grid;
    flex: none;
    height: 28px;
    place-items: center;
    width: 28px;
}
@media (max-width: 760px) {
    .ao-tusr-form {
        grid-template-columns: minmax(0, 1fr) auto;
    }
    .ao-tusr-email {
        grid-column: 1 / -1;
    }
    /* The pinned who-column stays narrow enough that role and status sit
     * beside it; NAME (column 2) drops out — the avatar's initials and VIEW
     * carry it — and the cell stays in the row. */
    .ao-tusr-who {
        max-width: 150px;
    }
    .ao-tusr-table th:nth-child(2),
    .ao-tusr-table td:nth-child(2) {
        display: none;
    }
    /* ORG ROLE and LAST SIGN-IN (columns 3, 5) and the avatar drop out too,
     * so the row actions start on the first screen; the invites table drops
     * SENT (column 4). The cells stay in the row. */
    .ao-tusr-table th:nth-child(3),
    .ao-tusr-table td:nth-child(3),
    .ao-tusr-table th:nth-child(5),
    .ao-tusr-table td:nth-child(5),
    .ao-tusr-inv th:nth-child(4),
    .ao-tusr-inv td:nth-child(4),
    .ao-tusr-table .ao-tusr-av {
        display: none;
    }
    /* Row actions go icon-only: the label leaves the layout but stays the
     * button's text (its accessible name, and what the tests read). Every
     * one is the same 28px ringed circle, ghost variants included. */
    .ao-tusr-acts .ao-btn {
        background: var(--ao-surface);
        border: 1px solid var(--ao-border-soft);
        box-shadow:
            inset 0 1px 0 var(--ao-tint),
            var(--ao-elev-1);
        height: 28px;
        justify-content: center;
        min-height: 28px;
        min-width: 28px;
        padding: 0;
        width: 28px;
    }
    .ao-tusr-acts .ao-btn .ao-btn-label {
        clip-path: inset(50%);
        height: 1px;
        overflow: hidden;
        position: absolute;
        white-space: nowrap;
        width: 1px;
    }
}

/* ── User modals (body-appended: outside #argus-ops-root, so nothing here
 * may lean on the root's cascade) ── */
.ao-tusr-overlay {
    align-items: center;
    background: var(--ao-overlay);
    display: flex;
    inset: 0;
    justify-content: center;
    padding: 24px;
    position: fixed;
    z-index: 99998;
}
.ao-tusr-modal {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    color: var(--ao-fg-dim);
    display: flex;
    flex-direction: column;
    font-family: var(--ao-font-sans);
    font-size: var(--ao-fs-strong);
    gap: var(--ao-s-3);
    max-height: 86vh;
    max-width: 520px;
    overflow: auto;
    padding: 22px;
    width: 100%;
}
.ao-tusr-modal.is-detail {
    max-width: 560px;
}
/* Outside the root, nothing sets border-box: a 100%-wide padded input ran
 * past the card's edge on a phone. */
.ao-tusr-modal,
.ao-tusr-modal *,
.ao-ghost-card,
.ao-ghost-card * {
    box-sizing: border-box;
}
.ao-tusr-detail {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
}
.ao-tusr-modal-head {
    align-items: center;
    display: flex;
    gap: var(--ao-s-3);
}
.ao-tusr-modal-ico {
    background: color-mix(in srgb, var(--ao-k-5) 14%, transparent);
    border-radius: 10px;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ao-k-5) 26%, transparent);
    color: var(--ao-k-5);
    display: grid;
    flex: none;
    height: 34px;
    place-items: center;
    width: 34px;
}
.ao-tusr-modal.is-danger .ao-tusr-modal-ico {
    background: var(--ao-err-bg);
    box-shadow: inset 0 0 0 1px var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-tusr-modal-titles {
    min-width: 0;
}
.ao-tusr-modal-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    font-weight: 600;
    margin: 0;
    overflow-wrap: anywhere;
}
.ao-tusr-modal-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-top: 2px;
}
.ao-tusr-modal-warn {
    align-items: flex-start;
    background: var(--ao-warn-bg);
    border: 1px solid var(--ao-warn-bd);
    border-radius: var(--ao-r-lg);
    color: var(--ao-warn-text);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: var(--ao-s-2);
    line-height: 1.45;
    padding: 10px 12px;
}
.ao-tusr-modal-warn .ao-ico {
    flex: none;
    margin-top: 1px;
}
.ao-tusr-modal .ao-field-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    margin-bottom: 5px;
    text-transform: uppercase;
}
.ao-tusr-modal .ao-input {
    border-radius: var(--ao-r-md);
    padding: 8px 11px;
}
.ao-tusr-modal-err {
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-body);
    min-height: 16px;
}
.ao-tusr-modal-err:empty {
    min-height: 0;
}
.ao-tusr-modal-acts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
    margin-top: 4px;
}
.ao-tusr-kv {
    display: flex;
    flex-direction: column;
}
.ao-tusr-kv-h {
    border-top: 1px solid var(--ao-tint-line);
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    margin-top: 12px;
    padding-top: 10px;
    text-transform: uppercase;
}
.ao-tusr-kv-h:first-child {
    border-top: 0;
    margin-top: 0;
    padding-top: 0;
}
.ao-tusr-kv-row {
    display: grid;
    font-size: var(--ao-fs-body);
    gap: var(--ao-s-3);
    grid-template-columns: 130px minmax(0, 1fr);
    padding: 3px 0;
}
.ao-tusr-kv-k {
    color: var(--ao-fg-mute);
}
.ao-tusr-kv-v {
    color: var(--ao-fg);
    overflow-wrap: anywhere;
}
.ao-tusr-kv-v.is-warn {
    color: var(--ao-warn-text);
}
/* The " : " between key and value, and the check's "verified": text for a
 * reader and a copy, off the screen (the grid column is the separator). */
.ao-tusr-kv-sep,
.ao-tusr-sr {
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}
.ao-tusr-kv-row {
    position: relative;
}
.ao-tusr-kv-contact {
    align-items: center;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 4px 8px;
    max-width: 100%;
}
.ao-tusr-kv-addr {
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-tusr-kv-ok {
    background: var(--ao-ok-bg);
    border: 1px solid var(--ao-ok-bd);
    border-radius: 50%;
    color: var(--ao-ok-fg);
    display: inline-grid;
    flex: none;
    height: 18px;
    place-items: center;
    width: 18px;
}
.ao-tusr-kv-pill {
    flex: none;
}
/* Phone: the label sits over its value, so an address gets the whole card
 * width instead of breaking mid-word in a narrow column. */
@media (max-width: 760px) {
    .ao-tusr-kv-row {
        gap: 1px;
        grid-template-columns: minmax(0, 1fr);
        padding: 5px 0;
    }
    .ao-tusr-kv-k {
        font-size: var(--ao-fs-meta);
    }
}

/* ── Ghost-in (SHADOW / IMPERSONATE) — the palette is tokens now ── */
.ao-ghost-overlay {
    backdrop-filter: blur(1.5px);
    -webkit-backdrop-filter: blur(1.5px);
}
.ao-ghost-card {
    --ao-ghost-pop: var(--ao-info-fg);
    --ao-ghost-soft: var(--ao-info-bg);
    --ao-ghost-line: var(--ao-info-bd);
    background: var(--ao-surface-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow: 0 24px 60px -12px var(--ao-shadow);
    color: var(--ao-fg-dim);
    font-family: var(--ao-font-sans);
    font-size: var(--ao-fs-strong);
    max-width: 520px;
    overflow: hidden;
    padding: 24px;
    position: relative;
    width: 100%;
}
.ao-ghost-card.is-person {
    --ao-ghost-pop: var(--ao-warn-text);
    --ao-ghost-soft: var(--ao-warn-bg);
    --ao-ghost-line: var(--ao-warn-bd);
}
.ao-ghost-rail {
    background: linear-gradient(90deg, var(--ao-info), var(--ao-k-2) 55%, var(--ao-cta));
    height: 4px;
    left: 0;
    position: absolute;
    right: 0;
    top: 0;
}
.ao-ghost-badge {
    align-items: center;
    background: var(--ao-ghost-soft);
    border: 1px solid var(--ao-ghost-line);
    border-radius: var(--ao-r-tag);
    color: var(--ao-ghost-pop);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 700;
    gap: 6px;
    letter-spacing: 0.08em;
    margin-bottom: 12px;
    padding: 3px 10px;
}
.ao-ghost-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-h2);
    margin: 0 0 3px;
    overflow-wrap: anywhere;
}
.ao-ghost-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    margin: 0 0 14px;
}
.ao-ghost-warn {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
    margin-bottom: 12px;
}
.ao-ghost-lock {
    align-items: center;
    background: var(--ao-warn-bg);
    border: 1px solid var(--ao-warn-bd);
    border-radius: var(--ao-r-lg);
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 8px;
    margin-bottom: 16px;
    padding: 9px 12px;
}
.ao-ghost-lock .ao-ico {
    color: var(--ao-cta);
    flex: none;
}
.ao-ghost-field {
    position: relative;
}
.ao-ghost-card .ao-ghost-input {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-ctl);
    box-sizing: border-box;
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    outline: none;
    padding: 20px 14px 8px;
    transition:
        border-color 0.15s,
        box-shadow 0.15s;
    width: 100%;
}
.ao-ghost-float {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    left: 15px;
    pointer-events: none;
    position: absolute;
    top: 15px;
    transform-origin: left top;
    transition:
        transform 0.15s,
        color 0.15s;
}
.ao-ghost-field.is-lifted .ao-ghost-float {
    transform: translateY(-9px) scale(0.82);
}
.ao-ghost-field.is-focused .ao-ghost-float {
    color: var(--ao-ghost-pop);
}
.ao-ghost-field.is-focused .ao-ghost-input {
    border-color: var(--ao-ghost-pop);
    box-shadow: 0 0 0 3px var(--ao-ghost-soft);
}
.ao-ghost-card .ao-tusr-modal-err {
    margin-top: 8px;
}
.ao-ghost-card .ao-tusr-modal-acts {
    margin-top: 16px;
}

/* ── Cameras ── */
.ao-tcam-cam {
    align-items: center;
    display: flex;
    gap: 10px;
    min-width: 0;
}
.ao-tcam-cam .ao-dot {
    flex: none;
}
.ao-tcam-text {
    min-width: 0;
}
.ao-tcam-name {
    color: var(--ao-fg);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-tcam-sub {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
}
.ao-tcam-table td {
    vertical-align: middle;
}
.ao-tcam-table td:last-child {
    max-width: none;
    overflow: visible;
    width: 1%;
}
.ao-tcam-when {
    color: var(--ao-fg-dim);
}

/* ── Agent: support readiness checklist ── */
.ao-tagt-ready {
    display: flex;
    flex-direction: column;
}
.ao-tagt-checks {
    display: grid;
    gap: 2px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-tagt-check {
    align-items: flex-start;
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    gap: 10px;
    padding: 10px 0;
}
.ao-tagt-check:first-child {
    border-top: 0;
    padding-top: 2px;
}
.ao-tagt-ico {
    border-radius: var(--ao-r-tag);
    display: grid;
    flex: none;
    height: 20px;
    place-items: center;
    width: 20px;
}
.ao-tagt-check.is-ok .ao-tagt-ico {
    background: var(--ao-ok-bg);
    border: 1px solid var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-tagt-check.is-fail .ao-tagt-ico {
    background: var(--ao-err-bg);
    border: 1px solid var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-tagt-label {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
}
.ao-tagt-check.is-ok .ao-tagt-label {
    color: var(--ao-fg-dim);
}
.ao-tagt-hint {
    color: var(--ao-err-fg);
    font-size: var(--ao-fs-meta);
    margin-top: 2px;
}

/* ── Metrics ── */
.ao-tmet-band {
    align-items: baseline;
    display: flex;
    gap: 8px;
}
.ao-tmet-band-name {
    color: var(--ao-fg);
    font-weight: 600;
}

/* ── Timeline (tenant Activity tab + #/timeline) ── */
.ao-tline-bar {
    align-items: center;
}
.ao-tline-who {
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-tline-who:empty {
    display: none;
}
.ao-tline-who-name {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    font-weight: 600;
}
.ao-tline-who-id {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-tline-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
    margin-left: auto;
}
.ao-tline-full .ao-ico {
    order: 2;
}
.ao-tline-card {
    padding: 6px 16px 10px;
}
.ao-tline-days,
.ao-tline-events {
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-tline-dayhead {
    align-items: center;
    display: flex;
    gap: 8px;
    padding: 12px 0 8px;
}
.ao-tline-daylabel {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-tline-daycount {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    padding: 0 7px;
}
/* One event: a kind marker on the rail, the label + kind chip, the time. */
.ao-tline-ev {
    --ao-tline-c: var(--ao-fg-mute);
    align-items: flex-start;
    display: flex;
    gap: var(--ao-s-3);
    padding: 7px 0;
    position: relative;
}
.ao-tline-ev:not(:last-child)::before {
    background: var(--ao-border-soft);
    bottom: -7px;
    content: '';
    left: 12px;
    position: absolute;
    top: 33px;
    width: 2px;
}
.ao-tline-ev.is-signup {
    --ao-tline-c: var(--ao-k-4);
}
.ao-tline-ev.is-onboarding {
    --ao-tline-c: var(--ao-k-3);
}
.ao-tline-ev.is-agent {
    --ao-tline-c: var(--ao-k-1);
}
.ao-tline-ev.is-camera {
    --ao-tline-c: var(--ao-k-2);
}
.ao-tline-ev.is-nudge {
    --ao-tline-c: var(--ao-k-5);
}
.ao-tline-ev.is-billing {
    --ao-tline-c: var(--ao-k-6);
}
.ao-tline-mark {
    background: color-mix(in srgb, var(--ao-tline-c) 14%, var(--ao-surface));
    border-radius: 50%;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ao-tline-c) 32%, transparent);
    color: var(--ao-tline-c);
    display: grid;
    flex: none;
    height: 26px;
    place-items: center;
    position: relative;
    width: 26px;
    z-index: 1;
}
.ao-tline-main {
    flex: 1 1 auto;
    min-width: 0;
    padding-top: 3px;
}
.ao-tline-top {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: 4px 8px;
}
.ao-tline-label {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    font-weight: 500;
}
.ao-tline-kind {
    background: color-mix(in srgb, var(--ao-tline-c) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--ao-tline-c) 28%, transparent);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.04em;
    padding: 0 7px;
    text-transform: uppercase;
}
.ao-tline-detail {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    margin-top: 2px;
    overflow-wrap: anywhere;
}
/* Wide: one line per event — label, kind, time, then the detail after a
 * drawn middle dot ("Agent paired AGENT 10:42 · juniper-pc-01"). It wraps
 * only when the detail does not fit. */
@media (min-width: 761px) {
    .ao-tline-main {
        align-items: baseline;
        display: flex;
        flex-wrap: wrap;
        gap: 4px 8px;
    }
    .ao-tline-detail {
        color: var(--ao-fg-dim);
        margin: 0;
        min-width: 0;
    }
    .ao-tline-detail::before {
        color: var(--ao-fg-mute);
        content: '·';
        margin-right: 8px;
    }
    /* One line an event, so a tighter rhythm: 4px a side, the rail joining
     * marker to marker across the smaller gap. */
    .ao-tline-ev {
        padding: 4px 0;
    }
    .ao-tline-ev:not(:last-child)::before {
        bottom: -4px;
        top: 30px;
    }
    .ao-tline-dayhead {
        padding: 10px 0 4px;
    }
}
/* On the event's own line, after the kind chip: 14:05 inside a past day,
 * "3m ago" today. */
.ao-tline-when {
    color: var(--ao-fg-dim);
    flex: none;
    font-size: var(--ao-fs-meta);
    white-space: nowrap;
}
.ao-tline-foot {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    text-align: center;
}

/* Reduced motion for this section's own animations (the pulsing live dot,
 * the notify result pop, the busy spinner stays: it is the only busy cue,
 * and it is transform-only). */
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-olv-page.is-live .ao-olv-dot,
    :where(html:not([data-motion='full'])) .ao-ntf-result.is-fresh {
        animation: none;
    }
    :where(html:not([data-motion='full'])) .ao-olv-fill,
    :where(html:not([data-motion='full'])) .ao-onb-card,
    :where(html:not([data-motion='full'])) .ao-ntf-ch {
        transition: none;
    }
    :where(html:not([data-motion='full'])) .ao-onb-card:hover,
    :where(html:not([data-motion='full'])) .ao-onb-card:focus-visible {
        transform: none;
    }
}

/* ── Toasts (U9) ─────────────────────────────────────────────────────────
   Transient themed notifications. Fixed bottom-right stack, black/white
   console aesthetic with a tinted left border per kind. */
.ao-toasts {
    position: fixed;
    right: 18px;
    bottom: 18px;
    z-index: 99999;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
}

.ao-toast {
    pointer-events: auto;
    cursor: pointer;
    min-width: 220px;
    max-width: 360px;
    padding: 10px 14px;
    background: var(--ao-surface-2);
    color: var(--ao-fg-dim);
    border: 1px solid var(--ao-border-soft);
    border-left: 3px solid var(--ao-fg-mute);
    border-radius: var(--ao-r-md);
    /* #ao-toasts hangs off the page body, outside the Ops root, so it does
       not inherit the console face (it rendered in the browser's serif). */
    font-family: var(--ao-font-sans);
    font-size: var(--ao-fs-body);
    letter-spacing: 0.02em;
    box-shadow: 0 6px 22px var(--ao-shadow);
    opacity: 0;
    transform: translateY(8px);
    transition:
        opacity 0.28s ease,
        transform 0.28s ease;
}

.ao-toast.is-shown {
    opacity: 1;
    transform: translateY(0);
}

.ao-toast.is-leaving {
    opacity: 0;
    transform: translateY(8px);
}

.ao-toast.is-ok {
    border-left-color: var(--ao-ok-text);
}

.ao-toast.is-err {
    border-left-color: var(--ao-err);
}

.ao-toast.is-info {
    border-left-color: var(--ao-info);
}

/* ── Stream Setup (interactive wiring map) ──────────────────────────────── */
/* Design system v2 (2026-09-23): the NEXT STEP banner is a hero card whose
 * CTA is the page's one filled pill, the stages are Team cards with an icon
 * tile, and a connector carries a moving pulse once both of its ends are
 * live. Tokens only. */
.ao-wiring-next {
    --ao-wiring-tone: var(--ao-fg-mute);
    align-items: center;
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        inset 3px 0 0 var(--ao-wiring-tone),
        var(--ao-elev-1);
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3) var(--ao-s-4);
    padding: var(--ao-s-4) var(--ao-s-5);
}
.ao-wiring-next.is-live {
    --ao-wiring-tone: var(--ao-ok);
}
.ao-wiring-next.is-waiting {
    --ao-wiring-tone: var(--ao-warn);
}
.ao-wiring-next-ico {
    background: var(--ao-tint-2);
    border-radius: 10px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-wiring-tone);
    display: grid;
    flex: none;
    height: 38px;
    place-items: center;
    width: 38px;
}
.ao-wiring-next-body {
    display: flex;
    flex: 1 1 280px;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}
.ao-wiring-next-label {
    color: var(--ao-wiring-tone);
    font-size: var(--ao-fs-label);
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}
.ao-wiring-next-text {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    line-height: 1.45;
}
.ao-wiring-next-action:empty {
    display: none;
}

.ao-wiring-flow {
    align-items: stretch;
    display: flex;
    gap: 0;
}
.ao-wiring-stage {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    color: var(--ao-fg);
    cursor: pointer;
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    font: inherit;
    gap: 3px;
    min-width: 0;
    padding: 14px;
    text-align: left;
    transition:
        transform var(--ao-base) var(--ao-ease),
        box-shadow var(--ao-base) var(--ao-ease);
}
.ao-wiring-stage:hover,
.ao-wiring-stage:focus-visible {
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-2);
    transform: translateY(-2px);
}
.ao-wiring-stage:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
/* The stage open below: a neutral light ring, not a new border colour (the
 * salmon accent — and the focus token, the same salmon — read as an error
 * beside the state pills). */
.ao-wiring-stage.is-selected {
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        0 0 0 2px var(--ao-fg-dim),
        var(--ao-elev-2);
}
.ao-wiring-stage-top {
    align-items: center;
    display: flex;
    gap: var(--ao-s-2);
    margin-bottom: 10px;
}
.ao-wiring-ico {
    background: var(--ao-tint-2);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    display: grid;
    flex: none;
    height: 34px;
    place-items: center;
    width: 34px;
}
.ao-wiring-stage[data-status='live'] .ao-wiring-ico {
    color: var(--ao-ok-text);
}
.ao-wiring-stage[data-status='waiting'] .ao-wiring-ico {
    color: var(--ao-warn-text);
}
.ao-wiring-num {
    align-items: center;
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-pill);
    color: var(--ao-fg-dim);
    display: inline-flex;
    flex: 0 0 auto;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    height: 20px;
    justify-content: center;
    line-height: 1;
    width: 20px;
}
.ao-wiring-stage-title {
    font-size: var(--ao-fs-strong);
    font-weight: 600;
}
.ao-wiring-stage-where {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.3;
}
.ao-wiring-pill {
    align-items: center;
    border: 1px solid currentColor;
    border-radius: var(--ao-r-tag);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 700;
    gap: 5px;
    letter-spacing: 0.1em;
    margin-left: auto;
    padding: 2px 8px;
}
.ao-wiring-pill::before {
    background: currentColor;
    border-radius: 50%;
    content: '';
    height: 6px;
    width: 6px;
}
.ao-wiring-pill.is-live {
    background: var(--ao-ok-soft);
    color: var(--ao-ok-text);
}
.ao-wiring-pill.is-live::before {
    animation: ao-cam-breathe 2.4s var(--ao-ease) infinite;
}
.ao-wiring-pill.is-waiting {
    background: var(--ao-warn-bg);
    color: var(--ao-warn-text);
}
.ao-wiring-pill.is-unknown {
    border-style: dashed;
    color: var(--ao-fg-mute);
}
.ao-wiring-pill.is-unknown::before {
    background: transparent;
    box-shadow: inset 0 0 0 1.5px currentColor;
}

/* A connector: a rail with a travelling pulse (transform only), the hop's
 * payload named under it. */
.ao-wiring-conn {
    align-items: center;
    display: flex;
    flex: 0 0 104px;
    flex-direction: column;
    gap: 6px;
    justify-content: center;
    padding: 0 6px;
    position: relative;
}
/* The rail and its chevron: the arrow is placed against this track, never
 * against the whole connector (whose label height varies). */
.ao-wiring-track {
    display: block;
    position: relative;
    width: 100%;
}
.ao-wiring-line {
    background: var(--ao-border);
    border-radius: var(--ao-r-tag);
    display: block;
    height: 2px;
    overflow: hidden;
    position: relative;
    width: 100%;
}
.ao-wiring-pulse {
    background: linear-gradient(90deg, transparent, var(--ao-ok), transparent);
    display: none;
    height: 100%;
    left: 0;
    position: absolute;
    top: 0;
    width: 40%;
}
.ao-wiring-conn.is-live .ao-wiring-line {
    background: var(--ao-ok-border);
}
.ao-wiring-conn.is-live .ao-wiring-pulse {
    animation: ao-wiring-flow 1.8s linear infinite;
    display: block;
}
@keyframes ao-wiring-flow {
    from {
        transform: translateX(-100%);
    }
    to {
        transform: translateX(250%);
    }
}
.ao-wiring-arrow {
    color: var(--ao-fg-mute);
    display: grid;
    place-items: center;
    position: absolute;
    right: -2px;
    top: 50%;
    transform: translateY(-50%);
}
.ao-wiring-conn.is-live .ao-wiring-arrow {
    color: var(--ao-ok-text);
}
.ao-wiring-conn-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    line-height: 1.25;
    max-width: 92px;
    /* Always two lines tall, so every rail sits at the same height. */
    min-height: 2.5em;
    text-align: center;
}

.ao-wiring-detail {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    padding: var(--ao-s-5);
}
/* The panel runs the stage row's full width; only the prose keeps a
 * readable measure. */
.ao-wiring-what,
.ao-wiring-steps {
    max-width: 72ch;
}
/* The route in the section sub-line: the words joined by arrow icons. */
.ao-wiring-route {
    align-items: center;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 2px 5px;
}
.ao-wiring-route .ao-ico {
    color: var(--ao-fg-mute);
    flex: none;
}
.ao-wiring-route-tail {
    margin-left: 2px;
}
.ao-wiring-detail-head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 12px;
}
.ao-wiring-detail-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    font-weight: 600;
}
.ao-wiring-detail-where {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-wiring-what {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-strong);
    line-height: 1.55;
    margin-bottom: 16px;
}
.ao-wiring-steps-h {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.12em;
    margin-bottom: 10px;
    text-transform: uppercase;
}
/* Numbered steps as a checklist of small tiles. */
.ao-wiring-steps {
    counter-reset: ao-wiring-step;
    display: flex;
    flex-direction: column;
    gap: 8px;
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
}
.ao-wiring-steps li {
    color: var(--ao-fg-dim);
    counter-increment: ao-wiring-step;
    display: grid;
    font-size: var(--ao-fs-strong);
    gap: 10px;
    grid-template-columns: 22px minmax(0, 1fr);
    line-height: 1.5;
}
.ao-wiring-steps li::before {
    align-items: center;
    background: var(--ao-tint-2);
    border-radius: 6px;
    color: var(--ao-fg);
    content: counter(ao-wiring-step);
    display: flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    height: 22px;
    justify-content: center;
}
/* A pill with a literal floor (pinned by pill-buttons.contract.test.js). The
 * look is .ao-btn's — the CTA carries .ao-btn (and .is-primary on the NEXT
 * STEP banner); this rule only keeps the family's geometry and ring. */
.ao-wiring-cta {
    border-radius: var(--ao-r-ctl);
    min-height: 28px;
}
.ao-wiring-cta:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
@media (max-width: 900px) {
    /* The path turns vertical: stages stack, connectors run downwards. */
    .ao-wiring-flow {
        flex-direction: column;
    }
    .ao-wiring-conn {
        flex: 0 0 auto;
        flex-direction: row;
        justify-content: flex-start;
        min-height: 34px;
        padding: 0 0 0 28px;
    }
    .ao-wiring-line {
        height: 30px;
        width: 2px;
    }
    .ao-wiring-pulse {
        height: 40%;
        width: 100%;
    }
    .ao-wiring-conn.is-live .ao-wiring-pulse {
        animation-name: ao-wiring-flow-down;
    }
    .ao-wiring-track {
        width: auto;
    }
    .ao-wiring-arrow {
        display: none;
    }
    .ao-wiring-conn-label {
        max-width: none;
        min-height: 0;
        text-align: left;
    }
}
@keyframes ao-wiring-flow-down {
    from {
        transform: translateY(-100%);
    }
    to {
        transform: translateY(250%);
    }
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-wiring-stage,
    :where(html:not([data-motion='full'])) .ao-wiring-pill.is-live::before,
    :where(html:not([data-motion='full'])) .ao-wiring-conn.is-live .ao-wiring-pulse {
        animation: none;
        transition: none;
    }
    :where(html:not([data-motion='full'])) .ao-wiring-stage:hover,
    :where(html:not([data-motion='full'])) .ao-wiring-stage:focus-visible {
        transform: none;
    }
}
/* ── Camera pages (pipeline, cameras, recognition, TV wall, live modal) ────
 * Design system v2 (2026-09-23). The camera family's own pieces: the store
 * scope bar, the liveness chip, the registry card with its state stripe, the
 * recognition cards, the TV wall's tile chrome and the live-preview modal.
 * The card, KPI and table looks come from the primitives; tokens only. */
.ao-cam-stack {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
/* In a flex-gap stack the gap spaces a heading from its content; the extra
 * room goes above it instead (the #ao-page-body rule, one level down). */
.ao-cam-stack > .ao-sec-head {
    margin: var(--ao-s-2) 0 0;
}

/* The store this page reads. */
.ao-cam-scope {
    align-items: center;
    align-self: flex-start;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    display: inline-flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-body);
    gap: var(--ao-s-2) var(--ao-s-3);
    max-width: 100%;
    min-width: 0;
    padding: 6px 14px 6px 6px;
}
.ao-cam-scope:empty {
    display: none;
}
.ao-cam-scope-ico {
    background: var(--ao-tint-2);
    border-radius: 7px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    display: grid;
    flex: none;
    height: 26px;
    place-items: center;
    width: 26px;
}
.ao-cam-scope-k {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
/* No store picked on a fleet-wide page: the scope is every store. */
.ao-cam-scope-all {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-cam-scope-meta,
.ao-cam-scope-hint {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
.ao-cam-scope-meta {
    border-left: 1px solid var(--ao-border-soft);
    padding-left: var(--ao-s-3);
}

/* The liveness / activity chip: a dot and a word in the .ao-dot vocabulary. */
.ao-cam-chip {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    flex: none;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 6px;
    letter-spacing: 0.04em;
    line-height: 1.6;
    max-width: 100%;
    padding: 1px 9px 1px 7px;
    text-transform: uppercase;
    white-space: nowrap;
}
.ao-cam-chip-dot {
    background: currentColor;
    border-radius: 50%;
    flex: none;
    height: 7px;
    width: 7px;
}
.ao-cam-chip-text {
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-cam-chip.is-ok {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
/* A live dot breathes (transform only), so "streaming now" reads as a signal
 * and not a sticker. */
.ao-cam-chip.is-ok .ao-cam-chip-dot {
    animation: ao-cam-breathe 2.4s var(--ao-ease) infinite;
}
.ao-cam-chip.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-cam-chip.is-err {
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-strong);
}
.ao-cam-chip.is-idle {
    color: var(--ao-fg-mute);
}
/* ⛔ Unmeasured is dashed and hollow: never the ok palette, never the err one. */
.ao-cam-chip.is-unknown {
    background: transparent;
    border-color: var(--ao-border);
    border-style: dashed;
    color: var(--ao-fg-mute);
}
.ao-cam-chip.is-idle .ao-cam-chip-dot,
.ao-cam-chip.is-unknown .ao-cam-chip-dot {
    background: transparent;
    box-shadow: inset 0 0 0 1.5px currentColor;
}
@keyframes ao-cam-breathe {
    0%,
    100% {
        transform: scale(1);
    }
    50% {
        transform: scale(0.62);
    }
}

/* A time on screen in the operator's clock; the exact stamp is on hover. */
.ao-cam-when {
    white-space: nowrap;
}
/* ── PIPELINE ── */
.ao-pl-when {
    color: var(--ao-fg-dim);
}
/* A phone keeps CAMERA, LAST ALERT and 24H: the state word (it restates the
 * last alert), the last hour and tracks drop out, so the number that matters
 * sits beside the camera instead of off the card's right edge. */
@media (max-width: 759px) {
    .ao-pl-activity th:nth-child(2),
    .ao-pl-activity td:nth-child(2),
    .ao-pl-activity th:nth-child(4),
    .ao-pl-activity td:nth-child(4),
    .ao-pl-activity th:nth-child(6),
    .ao-pl-activity td:nth-child(6) {
        display: none;
    }
    .ao-pl-activity .ao-cam-cell-id {
        max-width: 120px;
    }
}

/* ── CAMERAS: the registry card — a state stripe on top, the name and its
 * liveness chip, the inventory facts, the two actions pinned to the foot. */
.ao-cam-grid {
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 290px), 1fr));
}
.ao-cam-card {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
    overflow: hidden;
    position: relative;
}
.ao-cam-card::before {
    background: var(--ao-cam-state, var(--ao-border));
    content: '';
    height: 3px;
    inset: 0 0 auto;
    position: absolute;
}
.ao-cam-card.is-ok {
    --ao-cam-state: var(--ao-ok);
}
.ao-cam-card.is-warn {
    --ao-cam-state: var(--ao-warn);
}
.ao-cam-card.is-err {
    --ao-cam-state: var(--ao-err-strong);
}
.ao-cam-card.is-idle {
    --ao-cam-state: var(--ao-fg-mute);
}
.ao-cam-card.is-unknown::before {
    background: repeating-linear-gradient(90deg, var(--ao-fg-mute) 0 6px, transparent 6px 11px);
}
.ao-cam-card .ao-card-h {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    letter-spacing: 0;
    margin: 0;
    min-width: 0;
    text-transform: none;
}
.ao-cam-card-name {
    font-weight: 600;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The agent on a card: its name, then the on-demand ID chip on the same
 * line (the id is one click away, never a line of its own). */
.ao-cam-card .ao-identity-agent {
    align-items: center;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 2px 6px;
    justify-content: flex-end;
}
.ao-cam-card .ao-identity-agent .ao-identity-idchip {
    align-self: center;
}
/* The inventory facts: a label column that never wraps, values right. */
.ao-cam-kv,
.ao-rec-kv {
    font-size: var(--ao-fs-meta);
    gap: 6px var(--ao-s-3);
    grid-template-columns: max-content minmax(0, 1fr);
}
.ao-cam-kv dt,
.ao-rec-kv dt {
    color: var(--ao-fg-mute);
    opacity: 1;
    white-space: nowrap;
}
.ao-cam-kv dd,
.ao-rec-kv dd {
    color: var(--ao-fg-dim);
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-cam-actions {
    align-items: center;
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
    margin-top: auto;
    padding-top: var(--ao-s-3);
}
/* DEREGISTER is the quieter of the pair but still a button: a red line and a
 * faint red tint at rest (the pill VIEW LIVE is, in the err family), the full
 * err tint on hover. In the table it is the same 26px circle as play. */
.ao-cam-actions .ao-btn.is-danger {
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border);
    box-shadow: none;
    margin-left: auto;
}
.ao-table .ao-cam-actions {
    border-top: 0;
    flex-wrap: nowrap;
    justify-content: flex-end;
    margin: 0;
    padding: 0;
}
.ao-table .ao-cam-actions .ao-btn.is-danger {
    margin-left: 0;
}
.ao-cam-cell {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}
.ao-cam-cell-name {
    color: var(--ao-fg);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-cam-cell-id {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    max-width: 190px;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* A phone always gets the cards (camerasInto), so the switch has no job.
 * (Scoped past .ao-tm-seg's own display rule, which comes later.) */
@media (max-width: 759px) {
    .ao-cam-stack .ao-seg.ao-cam-layout {
        display: none;
    }
}

/* ── RECOGNITION ── */
.ao-rec-grid {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}
.ao-rec-card {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-rec-card.is-wide {
    grid-column: 1 / -1;
}
.ao-rec-head {
    justify-content: flex-start;
    margin: 0;
}
.ao-rec-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    letter-spacing: 0;
    text-transform: none;
}
.ao-rec-tag {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    margin-left: auto;
    padding: 1px 8px;
    white-space: nowrap;
}
/* A caveat that travels with its numbers: quiet until it is the finding. */
.ao-rec-note {
    background: var(--ao-tint);
    border-left: 2px solid var(--ao-border);
    border-radius: 0 var(--ao-r-sm) var(--ao-r-sm) 0;
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.45;
    padding: var(--ao-s-2) var(--ao-s-3);
}
.ao-rec-note.is-warn {
    background: var(--ao-warn-bg);
    border-left-color: var(--ao-warn-strong);
    color: var(--ao-warn-text);
}
/* The activity mix: one bar per activity, scaled to the busiest. One grid
 * for the whole list (each row a subgrid), so the name, bar, count and flag
 * columns line up down the card; the flag is its own column after the count,
 * so it never squeezes a name into an ellipsis. */
.ao-rec-mix {
    border-top: 1px solid var(--ao-tint-line);
    column-gap: var(--ao-s-2);
    display: grid;
    grid-template-columns: minmax(0, max-content) minmax(56px, 1fr) auto auto;
    padding-top: var(--ao-s-3);
    row-gap: 7px;
}
.ao-rec-mix-row {
    align-items: center;
    display: grid;
    font-size: var(--ao-fs-meta);
    gap: var(--ao-s-2);
    grid-column: 1 / -1;
    grid-template-columns: minmax(0, max-content) minmax(56px, 1fr) auto auto;
}
@supports (grid-template-columns: subgrid) {
    .ao-rec-mix-row {
        grid-template-columns: subgrid;
    }
}
.ao-rec-mix-label {
    align-items: center;
    color: var(--ao-fg-dim);
    display: flex;
    gap: 6px;
    min-width: 0;
}
.ao-rec-mix-text {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-rec-mix-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    height: 6px;
    overflow: hidden;
    position: relative;
}
.ao-rec-mix-fill {
    background: linear-gradient(90deg, var(--ao-k-1), var(--ao-k-5));
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
.ao-rec-mix-row.is-flagged .ao-rec-mix-fill {
    background: var(--ao-err-strong);
}
.ao-rec-mix-n {
    color: var(--ao-fg);
    min-width: 2.5em;
    text-align: right;
}
.ao-rec-flag {
    color: var(--ao-err-strong);
    flex: none;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
}
/* On a phone each escalation is a stacked row (the Team page's phone rows),
 * not a table scrolling sideways: the activity on top, the employee and WHEN
 * beside each other under it, the camera last. Nothing is hidden. */
@media (max-width: 759px) {
    .ao-rec-esc thead {
        display: none;
    }
    .ao-rec-esc,
    .ao-rec-esc tbody {
        display: block;
        width: 100%;
    }
    .ao-rec-esc tbody tr {
        align-items: center;
        border-bottom: 1px solid var(--ao-border-soft);
        display: grid;
        gap: 6px 12px;
        grid-template-columns: minmax(0, 1fr) auto;
        padding: 10px 2px;
    }
    .ao-rec-esc tbody tr:last-child {
        border-bottom: 0;
    }
    .ao-rec-esc tbody td {
        border: 0;
        max-width: none;
        padding: 0;
    }
    .ao-rec-esc tbody td:nth-child(1) {
        grid-column: 1 / -1;
        grid-row: 1;
    }
    .ao-rec-esc tbody td:nth-child(2) {
        grid-column: 1;
        grid-row: 2;
    }
    .ao-rec-esc tbody td:nth-child(4) {
        color: var(--ao-fg-dim);
        grid-column: 2;
        grid-row: 2;
        text-align: right;
    }
    .ao-rec-esc tbody td:nth-child(3) {
        grid-column: 1 / -1;
        grid-row: 3;
    }
}

/* ── TV WALL: tile chrome by state class (.is-pending / .is-live /
 * .is-degraded / .is-lost), never an inline colour a callback forgets to
 * reset. */
.ao-tv-controls .ao-seg-field {
    flex-wrap: wrap;
}
.ao-tv-pos {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-tv-pos:empty {
    display: none;
}
/* The wall's live counts ride in the control row as four chips, so a 3x3
 * wall still fits on one 1440x900 screen. */
.ao-tv-counts {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
    margin-left: auto;
}
.ao-tv-counts:empty {
    display: none;
}
.ao-tv-count {
    align-items: center;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    line-height: 1.2;
    padding: 5px 11px 5px 9px;
    transition:
        border-color var(--ao-base) var(--ao-ease),
        background-color var(--ao-base) var(--ao-ease);
    white-space: nowrap;
}
.ao-tv-count-dot {
    background: var(--ao-fg-mute);
    border-radius: 50%;
    flex: none;
    height: 7px;
    width: 7px;
}
.ao-tv-count-num {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-strong);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}
.ao-tv-count.is-ok .ao-tv-count-dot {
    background: var(--ao-ok);
}
.ao-tv-count.is-warn .ao-tv-count-dot {
    background: var(--ao-warn);
}
.ao-tv-count.is-err .ao-tv-count-dot {
    background: var(--ao-err-strong);
}
.ao-tv-count.is-ok:not(.is-zero) {
    border-color: var(--ao-ok-border);
}
.ao-tv-count.is-warn:not(.is-zero) {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
}
.ao-tv-count.is-zero .ao-tv-count-dot {
    opacity: 0.4;
}
.ao-tv-count.ao-tv-alarm {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-border-strong);
}
.ao-tv-count.ao-tv-alarm .ao-tv-count-num {
    color: var(--ao-err-strong);
}
/* ⛔ The gutter is a 2px SEAM, not an 8px frame: the tile border separates
 * cameras, the gap only keeps the borders from touching. */
.ao-tv-grid {
    display: grid;
    gap: 2px;
    grid-template-columns: repeat(var(--ao-tv-cols, 3), minmax(0, 1fr));
}
/* The focused tile runs the width of the control row above it (flush on
 * both sides). The cap only binds on a very wide, short screen, where a full
 * width 16:9 tile would run off the bottom. */
.ao-tv-grid.is-focus {
    margin: 0 auto;
    max-width: min(100%, calc(88vh * 16 / 9));
    width: 100%;
}
.ao-tv-grid.is-focus .ao-tv-bar {
    font-size: var(--ao-fs-strong);
    padding: 28px 16px 12px;
}
.ao-tv-tile {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-md);
    overflow: hidden;
    position: relative;
    transition:
        border-color var(--ao-base) var(--ao-ease),
        box-shadow var(--ao-base) var(--ao-ease);
}
.ao-tv-tile:hover,
.ao-tv-tile:focus-visible {
    border-color: var(--ao-fg-mute);
    box-shadow: var(--ao-elev-2);
    outline: none;
}
.ao-tv-tile:focus-visible {
    box-shadow: 0 0 0 2px var(--ao-focus);
}
/* ⛔ One colour for one problem: a lost tile is red all through — fill,
 * border, dot, pill and heading — matching the Video loss KPI. Amber stays
 * for a degraded (snapshot) tile. */
.ao-tv-tile.is-lost {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
}
.ao-tv-stage {
    align-items: center;
    aspect-ratio: 16 / 9;
    display: flex;
    justify-content: center;
    width: 100%;
}
/* The caption rides on the video: a scrim, a state dot, the name, the rung. */
.ao-tv-bar {
    align-items: center;
    background: linear-gradient(180deg, transparent, var(--ao-overlay));
    bottom: 0;
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: var(--ao-s-2);
    left: 0;
    padding: 18px 10px 7px;
    position: absolute;
    right: 0;
}
.ao-tv-dot {
    background: var(--ao-fg-mute);
    border-radius: 50%;
    flex: none;
    height: 8px;
    width: 8px;
}
.ao-tv-tile.is-live .ao-tv-dot {
    animation: ao-cam-breathe 2.4s var(--ao-ease) infinite;
    background: var(--ao-ok);
}
.ao-tv-tile.is-degraded .ao-tv-dot {
    background: var(--ao-warn);
}
.ao-tv-tile.is-lost .ao-tv-dot {
    background: var(--ao-err-strong);
}
.ao-tv-name {
    color: var(--ao-fg);
    font-weight: 600;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tv-pill {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    flex: none;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    margin-left: auto;
    padding: 0 7px;
}
.ao-tv-tile.is-live .ao-tv-pill {
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-tv-tile.is-degraded .ao-tv-pill {
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
/* A lost tile already says VIDEO LOSS at tile scale; the pill would say it
 * twice. */
.ao-tv-tile.is-lost .ao-tv-pill {
    display: none;
}
/* ⛔ VIDEO LOSS reads from across the room: tile-scale words over an err
 * fill, the detail quiet but present. */
.ao-tv-error {
    align-items: center;
    display: flex;
    flex-direction: column;
    gap: 6px;
    height: 100%;
    justify-content: center;
    padding: 8px;
    text-align: center;
    width: 100%;
}
.ao-tv-error-ico {
    color: var(--ao-err-strong);
    display: grid;
    place-items: center;
}
.ao-tv-error-head {
    color: var(--ao-err-strong);
    font-size: var(--ao-fs-h);
    font-weight: 600;
    letter-spacing: 0.08em;
}
.ao-tv-error-why {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    max-width: 90%;
}
@media (max-width: 760px) {
    /* A phone wall is two across at most; 3x3 / 4x4 would be postage stamps. */
    .ao-tv-grid:not(.is-single) {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .ao-tv-error-head {
        font-size: var(--ao-fs-body);
    }
    .ao-tv-error-why {
        display: none;
    }
    /* Two tiles across leave no room for the transport pill: the name keeps
     * the width, the status dot keeps the state. */
    .ao-tv-grid:not(.is-focus) .ao-tv-pill {
        display: none;
    }
    /* Four chips two by two, even, rather than three and an orphan. */
    .ao-tv-counts {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        margin-left: 0;
        width: 100%;
    }
}

/* ── Live media (TV tiles + the live-preview modal) ── */
.ao-live-media {
    background: var(--ao-bg);
    display: block;
    height: 100%;
    object-fit: contain;
    width: 100%;
}
.ao-live-offline {
    padding: 12px;
    text-align: center;
}
.ao-live-offline-badge {
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-block;
    font-size: var(--ao-fs-meta);
    letter-spacing: 0.1em;
    padding: 3px 10px;
}
.ao-live-offline-msg {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    margin-top: 8px;
}
.ao-live-msg {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-strong);
    padding: 20px;
    text-align: center;
}
/* The VIEW LIVE modal (body-appended, so its geometry is literal here). */
.ao-camlive-overlay {
    align-items: center;
    background: var(--ao-overlay);
    display: flex;
    inset: 0;
    justify-content: center;
    padding: 24px;
    position: fixed;
    z-index: 99998;
}
/* Body-appended, so outside the console root: it names its own face. */
.ao-camlive-card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    font-family: var(--ao-font-sans);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-strong);
    max-height: 90vh;
    max-width: 760px;
    overflow: auto;
    padding: 20px;
    width: 100%;
}
.ao-camlive-head {
    align-items: center;
    display: flex;
    gap: var(--ao-s-3);
    margin-bottom: var(--ao-s-3);
}
.ao-camlive-ico {
    background: var(--ao-tint-2);
    border-radius: 8px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg);
    display: grid;
    flex: none;
    height: 32px;
    place-items: center;
    width: 32px;
}
.ao-camlive-titles {
    min-width: 0;
}
.ao-camlive-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    margin: 0;
}
.ao-camlive-sub {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    margin-top: 2px;
    overflow-wrap: anywhere;
}
.ao-camlive-stage {
    align-items: center;
    aspect-ratio: 16 / 9;
    background: var(--ao-bg);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    display: flex;
    justify-content: center;
    overflow: hidden;
    position: relative;
    width: 100%;
}
.ao-camlive-card .ao-live-transport {
    color: var(--ao-fg-dim);
}
.ao-camlive-card .ao-live-transport.is-ok {
    color: var(--ao-ok-text);
}
.ao-camlive-card .ao-live-transport.is-warn {
    color: var(--ao-warn-text);
}
.ao-camlive-err {
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-body);
    margin-top: 8px;
    min-height: 16px;
}
.ao-camlive-actions {
    display: flex;
    gap: var(--ao-s-2);
    justify-content: flex-end;
    margin-top: var(--ao-s-3);
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-cam-chip.is-ok .ao-cam-chip-dot,
    :where(html:not([data-motion='full'])) .ao-tv-tile.is-live .ao-tv-dot,
    :where(html:not([data-motion='full'])) .ao-rec-mix-fill {
        animation: none;
        transition: none;
    }
}

/* ── Wide-width reference rail (compute pricing, agents readiness) ───────── */
/* CSS-only layout wrapper. At >=1100px the secondary block sits in a 320px
 * right rail; below that it collapses to a single column. Does NOT change any
 * section ids or the refresh/patch logic — purely presentational. */
.ao-2col {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 340px;
    gap: 14px;
    align-items: start;
    padding: 14px 16px;
}
.ao-2col-rail {
    min-width: 0;
}
.ao-2col-main {
    min-width: 0;
    /* Wide data tables (e.g. the compute WORKERS table) must scroll WITHIN this
     * column, never paint over the reference rail to the right. */
    overflow-x: auto;
}
@media (max-width: 1100px) {
    .ao-2col {
        grid-template-columns: 1fr;
    }
    /* When stacked, a priority rail (agents readiness) floats above the main
     * column so green/red is seen first; a normal rail (compute pricing) stays
     * below as secondary reference. */
    .ao-2col-rail.is-priority {
        order: -1;
    }
}

/* ── Agents-page panel cards ────────────────────────────────────────────
 * Each section (activity / telemetry / readiness / actions / agents) is a
 * distinct raised card with its own header + timestamp, so blocks no longer
 * blend into one flat hairline-divided wall (the operator complaint). */
.ao-panel {
    background: var(--ao-surface-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    margin: 0 0 14px;
    overflow: hidden;
}
.ao-panel:last-child {
    margin-bottom: 0;
}
.ao-panel-h {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--ao-border-faint);
    background: var(--ao-surface);
}
.ao-panel-title {
    font-size: var(--ao-fs-meta);
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    opacity: 0.85;
}
.ao-panel-meta {
    font-size: var(--ao-fs-label);
    opacity: 0.6;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.ao-panel-body {
    padding: 12px 14px;
}
.ao-panel-body.is-flush {
    padding: 0;
}
/* Absolute timestamp shown next to a relative one — dimmer, monospace. */
.ao-ts-abs {
    opacity: 0.5;
    font-size: 0.9em;
    font-variant-numeric: tabular-nums;
}
/* Action buttons (replace the copy-paste CLI hints). */
/* Design system v2 (2026-09-23): exactly the small .ao-btn pill (26px
 * literal floor, surface fill, soft border, inset tint over elev-1, 11px/600
 * uppercase), keeping this family's outline-semantic variants below. Pinned
 * by pill-buttons.contract.test.js. */
.ao-actbtn {
    align-items: center;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    box-shadow:
        inset 0 1px 0 var(--ao-tint),
        var(--ao-elev-1);
    color: var(--ao-fg);
    display: inline-flex;
    gap: 6px;
    min-height: 26px;
    min-width: auto;
    padding: 4px 11px;
    font-family: inherit;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    cursor: pointer;
    border-radius: var(--ao-r-ctl);
    white-space: nowrap;
}
.ao-actbtn:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
/* Hover is the .ao-btn hover. It was a green border + text, which on a
 * TURN OFF read as "this is the healthy choice". */
.ao-actbtn:hover {
    background: var(--ao-hover);
    border-color: var(--ao-border);
}
.ao-actbtn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.ao-actbtn.is-primary {
    color: var(--ao-ok-text);
    border-color: var(--ao-ok-strong);
}
.ao-actbtn.is-danger:hover {
    border-color: var(--ao-err-strong);
    color: var(--ao-err-strong);
}
.ao-actbtn.is-info:hover {
    border-color: var(--ao-info);
    color: var(--ao-info);
}
.ao-actrow {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    align-items: center;
}
/* An action cell is the one place a table row is allowed to wrap: four buttons
 * on one nowrap line push the row wider than the viewport and every other
 * column ellipsises to pay for it. Scoped to the cell that HOLDS the row, so
 * nothing else in the table loses its single-line scanning. */
.ao-table td:has(> .ao-actrow) {
    white-space: normal;
    max-width: none;
}
.ao-actrow-hint {
    font-size: var(--ao-fs-meta);
    opacity: 0.4;
}

/* ── Tech Stack (live capacity & headroom) ──────────────────────────────
 * The watch list on top answers "what runs out of headroom first"; the
 * collapsible library below is the per-service reference. Reuses --ao-* tokens,
 * uppercase headers, tabular-nums for every value, monospace bars.
 * Design system v2 (2026-09-23): a KPI strip on top, the watch list as
 * severity cards with a real meter, the library in one Team card with a
 * turning chevron. TOKENS borrows all of it (.ao-ts-*), and _tsBar is Pipeline
 * Data's bar too, so the bar keeps its classes and its inline width. */
.ao-ts-stack {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-5);
    min-width: 0;
}
/* The block heads are aoSection (the 20px heading every page uses); the
 * block's count is a badge beside the title — the one way a count shows. */
.ao-ts-count {
    align-self: center;
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    line-height: 1.6;
    padding: 0 8px;
}
.ao-ts-lib {
    min-width: 0;
}
/* Utilization bar (a rounded track with a severity-tinted fill). */
.ao-ts-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: inline-block;
    height: 6px;
    overflow: hidden;
    vertical-align: middle;
    width: 120px;
}
.ao-ts-bar-fill {
    background: var(--ao-fg-mute);
    border-radius: inherit;
    display: block;
    height: 100%;
    transition: width 620ms var(--ao-ease);
}
.ao-ts-bar-fill.ok {
    background: var(--ao-ok-text);
}
.ao-ts-bar-fill.warn {
    background: var(--ao-warn-strong);
}
.ao-ts-bar-fill.err {
    background: var(--ao-err-strong);
}
.ao-ts-bar-fill.idle {
    background: var(--ao-fg-mute);
}
/* Severity colour utility classes (text), mapped to status tokens. */
.ao-ts-ok {
    color: var(--ao-ok-text);
}
.ao-ts-warn {
    color: var(--ao-warn-strong);
}
.ao-ts-critical {
    color: var(--ao-err-strong);
}
.ao-ts-mute {
    color: var(--ao-fg-mute);
}
/* NEEDS ATTENTION: one severity card per constraint, the ETA the headline. */
.ao-ts-watch-grid {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
}
.ao-ts-watch {
    --ao-ts-tone: var(--ao-border);
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        inset 3px 0 0 var(--ao-ts-tone),
        var(--ao-elev-1);
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
    padding: var(--ao-s-4);
}
.ao-ts-watch.is-err {
    --ao-ts-tone: var(--ao-err-strong);
}
.ao-ts-watch.is-warn {
    --ao-ts-tone: var(--ao-warn-strong);
}
.ao-ts-watch.is-ok {
    --ao-ts-tone: var(--ao-ok);
}
.ao-ts-watch-top {
    align-items: center;
    display: flex;
    gap: var(--ao-s-3);
}
.ao-ts-watch-ico {
    background: var(--ao-tint-2);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-ts-tone);
    display: grid;
    flex: none;
    height: 34px;
    place-items: center;
    width: 34px;
}
.ao-ts-watch-names {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.ao-ts-watch-name {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
}
.ao-ts-watch-metric {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-ts-eta {
    flex: none;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-h2);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.02em;
    white-space: nowrap;
}
/* "~ 4 days": the approximation mark qualifies the number, it is not one. */
.ao-ts-tilde {
    color: var(--ao-fg-mute);
    font-size: 0.6em;
    font-weight: 500;
    vertical-align: 0.15em;
    white-space: pre;
}
.ao-ts-watch-bottom {
    align-items: center;
    display: flex;
    gap: 12px;
}
.ao-ts-watch-bottom .ao-ts-bar {
    flex: 1;
    height: 8px;
    min-width: 60px;
}
.ao-ts-watch-val {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.ao-ts-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.4;
    max-width: 760px;
}
/* The library: one card, one collapsible row per service (or token source). */
.ao-ts-list {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    overflow: hidden;
}
.ao-ts-svc + .ao-ts-svc {
    border-top: 1px solid var(--ao-tint-line);
}
.ao-ts-svc-head {
    align-items: center;
    column-gap: 12px;
    display: grid;
    /* One grid for every row, so the names, the category pills and the
     * meters each start on one line down the list. */
    grid-template-areas: 'dot name cat worst caret';
    grid-template-columns: 10px minmax(150px, 200px) 84px minmax(0, 1fr) 20px;
    padding: 11px 14px;
    row-gap: 6px;
    transition: background var(--ao-fast) var(--ao-ease);
}
.ao-ts-svc-head > .ao-dot {
    grid-area: dot;
}
.ao-ts-svc-head:hover,
.ao-ts-svc-head:focus-visible {
    background: var(--ao-hover);
    outline: none;
}
.ao-ts-svc-head:focus-visible {
    box-shadow: inset 2px 0 0 var(--ao-accent-line);
}
.ao-ts-svc-name {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    font-weight: 600;
    grid-area: name;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-ts-svc-cat {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    grid-area: cat;
    justify-self: start;
    letter-spacing: 0.06em;
    max-width: 100%;
    overflow: hidden;
    padding: 0 7px;
    text-overflow: ellipsis;
    text-transform: uppercase;
    white-space: nowrap;
}
/* The collapsed row's reading: the metric's name in muted sans, a mini
 * meter, the value in the severity colour in mono — three fixed columns, so
 * the meters line up down the list. */
.ao-ts-svc-worst {
    align-items: center;
    column-gap: 10px;
    display: grid;
    font-size: var(--ao-fs-meta);
    grid-area: worst;
    grid-template-columns: minmax(0, 190px) 56px auto;
    justify-content: start;
    min-width: 0;
}
.ao-ts-svc-worst-k {
    color: var(--ao-fg-mute);
    grid-column: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-ts-svc-worst-v {
    font-family: var(--ao-mono);
    font-variant-numeric: tabular-nums;
    grid-column: 3;
    white-space: nowrap;
}
/* Without a meter (not instrumented; a token's expiry chip) the reading
 * starts where the meter would. */
.ao-ts-svc-worst > .ao-ts-muted,
.ao-ts-svc-worst > .ao-tok-days {
    grid-column: 2 / -1;
    justify-self: start;
}
.ao-ts-bar.is-mini {
    height: 5px;
    width: 56px;
}
.ao-ts-caret {
    color: var(--ao-fg-mute);
    display: grid;
    grid-area: caret;
    justify-self: end;
    place-items: center;
    transition: transform var(--ao-base) var(--ao-ease);
}
.ao-ts-svc-head[aria-expanded='true'] .ao-ts-caret {
    transform: rotate(180deg);
}
.ao-ts-svc-detail {
    background: var(--ao-tint);
    border-top: 1px dashed var(--ao-border-soft);
    padding: 12px 14px 14px;
}
.ao-ts-why {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.4;
    margin-bottom: 8px;
}
.ao-ts-plan {
    align-items: center;
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 10px;
    margin-bottom: 4px;
}
.ao-ts-plan-k {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.1em;
    min-width: 44px;
    text-transform: uppercase;
}
.ao-ts-plan-v {
    font-variant-numeric: tabular-nums;
}
.ao-ts-static {
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.1em;
    padding: 0 6px;
    text-transform: uppercase;
}
.ao-ts-metric {
    align-items: center;
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-body);
    gap: 6px 12px;
    padding: 7px 0;
}
.ao-ts-metric-label {
    color: var(--ao-fg-dim);
    min-width: 200px;
}
.ao-ts-metric-val {
    font-family: var(--ao-mono);
    font-variant-numeric: tabular-nums;
}
.ao-ts-metric-meta {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    margin-left: auto;
}
/* Honest posture: an un-instrumented metric is muted text, never a number. */
.ao-ts-muted {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    font-style: italic;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.ao-ts-footer {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
}
/* TOKENS: a days-left chip and scope chips. */
.ao-tok-name {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-tok-days {
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    padding: 1px 8px;
    white-space: nowrap;
}
.ao-tok-days.is-err {
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-strong);
}
.ao-tok-days.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-tok-days.is-ok {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
/* "no expiry" is not health: muted and dashed, never the ok colour. */
.ao-tok-days.is-idle {
    border-style: dashed;
}
.ao-tok-scopes {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 4px;
}
.ao-tok-scope {
    background: var(--ao-tint);
    border-radius: var(--ao-r-sm);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    padding: 0 5px;
}
@media (max-width: 760px) {
    /* A phone row: the dot, the name and the chevron on the first line; the
     * category and the reading under the name; the chevron centred. */
    .ao-ts-svc-head {
        grid-template-areas:
            'dot name name caret'
            '. cat worst caret';
        /* A fixed category column, so every reading starts on one line. */
        grid-template-columns: 10px 76px minmax(0, 1fr) 20px;
    }
    .ao-ts-caret {
        align-self: center;
    }
    .ao-ts-svc-worst {
        display: flex;
        flex-wrap: wrap;
        gap: 4px 8px;
    }
    .ao-ts-metric-label {
        min-width: 0;
        width: 100%;
    }
    .ao-ts-metric-meta {
        margin-left: 0;
    }
}
@media (max-width: 759px) {
    /* An odd last KPI card (Tokens' five) takes the row, not half of it. */
    .ao-ts-stack .ao-stat-row > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
    /* EXPIRING SOON keeps the token and its expiry side by side; the source,
     * scopes and creator drop out (they are in the library below). */
    .ao-tok-table th:nth-child(2),
    .ao-tok-table td:nth-child(2),
    .ao-tok-table th:nth-child(4),
    .ao-tok-table td:nth-child(4),
    .ao-tok-table th:nth-child(5),
    .ao-tok-table td:nth-child(5) {
        display: none;
    }
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-ts-bar-fill,
    :where(html:not([data-motion='full'])) .ao-ts-caret,
    :where(html:not([data-motion='full'])) .ao-ts-svc-head {
        transition: none;
    }
}
/* ── Uptime (#/uptime) ─────────────────────────────────────────────────────
 * Our own watcher's reading. One headline, then the Tokens page's library
 * card (.ao-ts-list) with a wider row: name, state, last checked, response
 * time, a 90-day strip and its percent. The strip is flat: one square tick
 * per day in the status colour, no frame, no gradient. Tokens only. */
.ao-up-stack {
    gap: var(--ao-s-6);
}
/* The page's own gutter, not a second one inside it. */
.ao-up-stack > .ao-table-unread,
.ao-up-stack > .ao-empty {
    margin: 0;
}
/* Degraded is a steady state here, not work in progress: no pulse. */
.ao-up-stack .ao-dot.warn {
    animation: none;
}
.ao-up-headline {
    align-items: center;
    column-gap: 14px;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    row-gap: 6px;
}
.ao-up-headline > .ao-dot {
    height: 14px;
    margin: 0;
    width: 14px;
}
.ao-up-headline-text {
    color: var(--ao-fg);
    font-size: var(--ao-fs-num);
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.1;
}
/* Red is for down (and for a watcher that has gone quiet), nothing else. A
 * copy that is merely old in this browser ("Checking now", "Cannot reach
 * Ops") keeps the plain ink and the grey dot. */
.ao-up-headline.is-err .ao-up-headline-text {
    color: var(--ao-err-strong);
}
.ao-up-headline-sub {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-strong);
    grid-column: 2;
    line-height: 1.45;
    max-width: 760px;
}
/* "Could not refresh": the same dashed warn edge as .ao-table-unread. */
.ao-up-note {
    border: 1px dashed var(--ao-warn-border);
    border-radius: var(--ao-r-md);
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-body);
    padding: 10px 12px;
}
/* One grid for the column labels and every row, so they line up. */
.ao-up-cols,
.ao-ts-svc-head.ao-up-head {
    grid-template-areas: 'dot name state checked ms days pct caret';
    grid-template-columns:
        10px minmax(190px, 1.1fr) minmax(128px, 0.9fr) 68px 64px minmax(160px, 2.2fr)
        58px 20px;
}
.ao-up-cols {
    border-bottom: 1px solid var(--ao-tint-line);
    color: var(--ao-fg-mute);
    column-gap: 12px;
    display: grid;
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    padding: 9px 14px;
    text-transform: uppercase;
}
.ao-up-cols > span {
    font-size: inherit;
    min-width: 0;
}
.ao-up-meta {
    display: contents;
}
.ao-up-name {
    align-items: center;
    display: flex;
    gap: 8px;
    grid-area: name;
    min-width: 0;
}
.ao-up-name-text {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    font-weight: 600;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-up-following {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-up-state {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-body);
    gap: 0 6px;
    grid-area: state;
    min-width: 0;
}
.ao-up-head .ao-up-state.is-ok .ao-up-state-word {
    color: var(--ao-ok-text);
}
.ao-up-head .ao-up-state.is-warn .ao-up-state-word {
    color: var(--ao-warn-text);
}
.ao-up-head .ao-up-state.is-err .ao-up-state-word {
    color: var(--ao-err-strong);
    font-weight: 600;
}
.ao-up-head .ao-up-state.is-unknown .ao-up-state-word {
    color: var(--ao-fg-mute);
}
.ao-up-for {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.ao-up-checked {
    grid-area: checked;
}
.ao-up-ms {
    grid-area: ms;
    text-align: right;
}
.ao-up-pct {
    grid-area: pct;
    text-align: right;
}
.ao-up-head .ao-up-checked,
.ao-up-head .ao-up-ms,
.ao-up-head .ao-up-pct {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.ao-up-head .ao-up-pct {
    color: var(--ao-fg);
}
.ao-up-days-cell {
    grid-area: days;
    min-width: 0;
}
.ao-up-days {
    align-items: stretch;
    display: flex;
    gap: 1px;
    height: 18px;
    min-width: 0;
}
.ao-up-day {
    background: var(--ao-tint-2);
    flex: 1 1 0;
    min-width: 1px;
}
.ao-up-day.is-up {
    background: var(--ao-ok);
    opacity: 0.62;
}
.ao-up-day.is-degraded {
    background: var(--ao-warn);
}
.ao-up-day.is-down {
    background: var(--ao-err-strong);
}
.ao-up-day:hover {
    opacity: 1;
    outline: 1px solid var(--ao-fg);
}
.ao-up-quiet {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-up-err {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    overflow-wrap: anywhere;
}
.ao-up-check.is-down .ao-up-err {
    color: var(--ao-err-strong);
}
.ao-up-check.is-degraded .ao-up-err {
    color: var(--ao-warn-text);
}
.ao-up-detail .ao-ts-plan {
    align-items: baseline;
}
.ao-up-detail .ao-ts-plan-k {
    flex: none;
    min-width: 108px;
}
.ao-up-detail .ao-ts-plan:last-child {
    margin-bottom: 0;
}
.ao-up-cause {
    color: var(--ao-fg-dim);
    display: inline-block;
    min-width: 150px;
    overflow-wrap: break-word;
    white-space: normal;
}
.ao-up-inc-sub {
    display: none;
}
/* An old reading: the strips and the numbers step back; the words say why. */
.ao-up-stack.is-old .ao-up-days,
.ao-up-stack.is-old .ao-up-meta {
    opacity: 0.45;
}
.ao-up-watch {
    align-items: baseline;
    color: var(--ao-fg-mute);
    display: flex;
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    line-height: 1.5;
}
.ao-up-watch > .ao-dot {
    align-self: center;
}
.ao-up-watch.is-err .ao-up-watch-text {
    color: var(--ao-err-strong);
}
@media (max-width: 1240px) {
    /* A narrow page (the rail takes 220px of a laptop's width, so this is
     * most laptops too): name and state on the first line, the strip on its
     * own line at full width, then one line of numbers. No column labels. */
    .ao-up-cols {
        display: none;
    }
    .ao-ts-svc-head.ao-up-head {
        grid-template-areas:
            'dot name state caret'
            '. days days days'
            '. meta meta meta';
        grid-template-columns: 10px minmax(0, 1fr) auto 20px;
    }
    .ao-up-head .ao-up-state {
        justify-content: flex-end;
    }
    /* The group is already titled "Internal"; the tag would cost the name
     * its room. The opened row still says where the check is shown. */
    .ao-up-head .ao-ts-static {
        display: none;
    }
    .ao-up-meta {
        color: var(--ao-fg-mute);
        display: flex;
        flex-wrap: wrap;
        font-size: var(--ao-fs-meta);
        gap: 2px 14px;
        grid-area: meta;
    }
    .ao-up-head .ao-up-checked::before {
        content: 'checked ';
    }
    .ao-up-head .ao-up-pct::after {
        content: ' over 90 days';
    }
    .ao-up-head .ao-up-ms,
    .ao-up-head .ao-up-pct {
        text-align: left;
    }
    /* No response time (a check that is down, a heartbeat): leave it out of
     * the line instead of a dash between two numbers. */
    .ao-up-head .ao-up-ms.is-none {
        display: none;
    }
}
@media (max-width: 759px) {
    .ao-up-headline-text {
        font-size: var(--ao-fs-h1);
    }
    /* The incident tables keep what, state and how long. The start time and
     * the reason move under the name ("Oct 1, 11:59 PM · HTTP 502"), so a
     * phone can still tell yesterday's outage from one three weeks ago. */
    .ao-up-inc-table th:nth-child(3),
    .ao-up-inc-table td:nth-child(3),
    .ao-up-inc-table th:nth-child(5),
    .ao-up-inc-table td:nth-child(5) {
        display: none;
    }
    .ao-up-inc-sub {
        color: var(--ao-fg-mute);
        display: block;
        font-size: var(--ao-fs-meta);
        line-height: 1.4;
        margin-top: 2px;
        overflow-wrap: anywhere;
        white-space: normal;
    }
}
@media (max-width: 360px) {
    /* The smallest phones: the name keeps its room; "for 3d 4h" is in the
     * opened row. */
    .ao-up-head .ao-up-for {
        display: none;
    }
}
/* ── Site health (#/sitehealth) — design system v2 (2026-09-23) ────────────
 * The published web report: a score ring beside the headline facts, KPI
 * cards with the report's own week / month deltas, one table component for
 * all eleven report tables (share bars in the cells), and two-column blocks
 * that drop to one column on a phone. Tokens only. */
.ao-sh-stack,
.ao-sh-stack-sm {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
.ao-sh-stack-sm {
    gap: var(--ao-s-2);
}
.ao-sh-stack > .ao-sec-head {
    margin: var(--ao-s-4) 0 0;
}
.ao-sh-stamp {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
/* The grade: a conic ring filled to the Lighthouse average, in its tier. */
.ao-sh-hero-row {
    align-items: stretch;
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
}
.ao-sh-hero {
    align-items: center;
    display: flex;
    gap: var(--ao-s-5);
}
.ao-sh-ring {
    --ao-sh-tone: var(--ao-fg-mute);
    background: conic-gradient(var(--ao-sh-tone) calc(var(--ao-sh-p, 0) * 1%), var(--ao-tint-2) 0);
    border-radius: 50%;
    display: grid;
    flex: none;
    height: 104px;
    padding: 8px;
    place-items: center;
    width: 104px;
}
.ao-sh-ring.is-ok {
    --ao-sh-tone: var(--ao-ok);
}
.ao-sh-ring.is-warn {
    --ao-sh-tone: var(--ao-warn);
}
.ao-sh-ring.is-err {
    --ao-sh-tone: var(--ao-err-strong);
}
.ao-sh-ring-in {
    background: var(--ao-surface);
    border-radius: 50%;
    box-shadow: inset 0 1px 0 var(--ao-tint-line);
    display: grid;
    height: 100%;
    place-items: center;
    width: 100%;
}
.ao-sh-grade {
    color: var(--ao-sh-tone);
    font-family: var(--ao-mono);
    font-size: 34px;
    font-weight: 600;
    letter-spacing: -0.04em;
    line-height: 1;
}
.ao-sh-hero-meta {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.ao-sh-hero-k {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
.ao-sh-hero-score {
    align-items: baseline;
    display: flex;
    gap: 6px;
}
.ao-sh-hero-num {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: 34px;
    font-weight: 600;
    letter-spacing: -0.04em;
    line-height: 1.05;
}
.ao-sh-hero-of,
.ao-sh-hero-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
/* The report's own deltas, labelled 7d / 28d, under a KPI number. */
.ao-sh-deltas {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 10px;
}
.ao-sh-delta {
    align-items: center;
    display: inline-flex;
    gap: 4px;
}
.ao-sh-delta-k {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}
/* Report tables side by side, one column on a narrow page. */
.ao-sh-2col {
    align-items: start;
    display: grid;
    gap: var(--ao-s-4) var(--ao-s-3);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr));
}
/* Two cards that stand as a pair (Security & SEO) share one height. */
.ao-sh-2col.is-stretch {
    align-items: stretch;
}
.ao-sh-sub {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    min-width: 0;
}
.ao-sh-sub-h {
    margin: 0;
}
.ao-sh-table {
    min-width: 0;
}
.ao-sh-note {
    align-items: flex-start;
    background: var(--ao-tint);
    border-radius: var(--ao-r-md);
    box-shadow: inset 2px 0 0 var(--ao-border);
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: var(--ao-s-2);
    line-height: 1.5;
    padding: var(--ao-s-2) var(--ao-s-3);
}
.ao-sh-note.is-info {
    box-shadow: inset 2px 0 0 var(--ao-info);
}
.ao-sh-note .ao-ico {
    color: var(--ao-fg-mute);
    flex: none;
    margin-top: 3px;
}
.ao-sh-muted {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
}
/* A Lighthouse score: a pill in its tier. */
.ao-sh-score {
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-block;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    min-width: 34px;
    padding: 1px 7px;
    text-align: center;
}
.ao-sh-score.is-ok {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-sh-score.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-sh-score.is-err {
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-strong);
}
.ao-sh-lh-page {
    color: var(--ao-fg);
    font-weight: 600;
}
/* The phone's one score cell: four keyed pills, two by two. Wide screens
 * have a column per score, so the cluster column stays hidden there. */
.ao-sh-lh th:nth-child(7),
.ao-sh-lh td:nth-child(7) {
    display: none;
}
.ao-sh-scores {
    display: inline-grid;
    gap: 4px;
    grid-template-columns: repeat(2, 1fr);
}
.ao-sh-scores > .ao-sh-score {
    display: block;
}
.ao-sh-score-k {
    font-weight: 500;
    margin-right: 4px;
    opacity: 0.75;
}
.ao-sh-lh-dev {
    color: var(--ao-fg-mute);
}
/* A status word as a pill (report service states, sitemap / index states). */
.ao-sh-pill {
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-block;
    flex: none;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.06em;
    padding: 1px 8px;
    text-transform: uppercase;
    white-space: nowrap;
}
.ao-sh-pill.is-ok {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-sh-pill.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-sh-pill.is-err {
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-strong);
}
.ao-sh-pill.is-info {
    background: var(--ao-info-bg);
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-sh-card {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-sh-card > .ao-card-h {
    margin: 0;
}
.ao-sh-sec-head {
    align-items: center;
    display: flex;
    gap: var(--ao-s-4);
}
.ao-sh-sec-grade {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: 40px;
    font-weight: 600;
    letter-spacing: -0.04em;
    line-height: 1;
}
.ao-sh-sec-grade.is-ok,
.ao-sh-tone.is-ok {
    color: var(--ao-ok-text);
}
.ao-sh-sec-grade.is-warn,
.ao-sh-tone.is-warn {
    color: var(--ao-warn-text);
}
.ao-sh-sec-grade.is-err,
.ao-sh-tone.is-err {
    color: var(--ao-err-strong);
}
.ao-sh-tone {
    font-weight: 700;
}
.ao-sh-sec-meta {
    color: var(--ao-fg-dim);
    display: flex;
    flex: 1;
    flex-direction: column;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    min-width: 0;
}
.ao-sh-meter {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: block;
    height: 6px;
    overflow: hidden;
    position: relative;
}
.ao-sh-meter-fill {
    background: var(--ao-fg-mute);
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
.ao-sh-meter.is-ok .ao-sh-meter-fill {
    background: var(--ao-ok);
}
.ao-sh-meter.is-warn .ao-sh-meter-fill {
    background: var(--ao-warn);
}
.ao-sh-meter.is-err .ao-sh-meter-fill {
    background: var(--ao-err-strong);
}
/* Security headers as a checklist of chips. */
.ao-sh-checks {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ao-sh-check {
    align-items: center;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    display: inline-flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    gap: 5px;
    max-width: 100%;
    padding: 2px 9px 2px 6px;
}
.ao-sh-check.is-ok {
    color: var(--ao-fg-dim);
}
.ao-sh-check.is-ok .ao-ico {
    color: var(--ao-ok-text);
}
.ao-sh-check.is-err {
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-strong);
}
.ao-sh-kv {
    font-size: var(--ao-fs-meta);
}
.ao-sh-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.ao-sh-list-row {
    align-items: center;
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: var(--ao-s-2);
    min-width: 0;
}
/* One pill width down a list, so the URLs beside them start on one line. */
.ao-sh-list-row > .ao-sh-pill {
    min-width: 92px;
    text-align: center;
}
.ao-sh-more {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    padding-left: calc(92px + var(--ao-s-2));
}
.ao-sh-url {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-sh-svc {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-sh-what {
    color: var(--ao-fg-dim);
}
.ao-sh-svc-cell {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
/* "What it feeds" under the name: a phone's line, hidden where the table
 * has the column for it. */
.ao-sh-svc-feeds {
    color: var(--ao-fg-dim);
    display: none;
    font-size: var(--ao-fs-meta);
    line-height: 1.4;
}
/* The services table's "what it feeds" is a sentence: let it wrap. */
.ao-table.ao-sh-wrap td {
    max-width: none;
    white-space: normal;
}
@media (max-width: 900px) {
    .ao-sh-hero-row {
        grid-template-columns: minmax(0, 1fr);
    }
}
@media (max-width: 759px) {
    /* An odd last KPI card (Core Web Vitals' three, Engagement's seven) takes
     * the row, not half of it. */
    .ao-sh-stack .ao-stat-row > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
    /* Phone tables fit the card: fixed columns (the name cuts with an
     * ellipsis, whole on hover in the cell's title where it has one) and the
     * low-value columns dropped — queries / pages keep clicks + impressions,
     * most-viewed pages keep views + time, Lighthouse keeps its four scores
     * as one pill cluster + LCP, services fold "what it feeds" under the
     * name. */
    .ao-sh-gsc,
    .ao-sh-views,
    .ao-sh-lh {
        table-layout: fixed;
    }
    .ao-sh-gsc th:nth-child(4),
    .ao-sh-gsc td:nth-child(4),
    .ao-sh-gsc th:nth-child(5),
    .ao-sh-gsc td:nth-child(5),
    .ao-sh-views th:nth-child(3),
    .ao-sh-views td:nth-child(3),
    .ao-sh-lh th:nth-child(3),
    .ao-sh-lh td:nth-child(3),
    .ao-sh-lh th:nth-child(4),
    .ao-sh-lh td:nth-child(4),
    .ao-sh-lh th:nth-child(5),
    .ao-sh-lh td:nth-child(5),
    .ao-sh-lh th:nth-child(6),
    .ao-sh-lh td:nth-child(6),
    .ao-sh-lh th:nth-child(n + 9),
    .ao-sh-lh td:nth-child(n + 9),
    .ao-sh-services th:nth-child(3),
    .ao-sh-services td:nth-child(3) {
        display: none;
    }
    .ao-sh-lh th:nth-child(7),
    .ao-sh-lh td:nth-child(7) {
        display: table-cell;
    }
    .ao-sh-svc-feeds {
        display: block;
    }
    .ao-sh-gsc th:nth-child(2),
    .ao-sh-gsc th:nth-child(3),
    .ao-sh-views th:nth-child(2),
    .ao-sh-views th:nth-child(4) {
        width: 84px;
    }
    .ao-sh-lh th:nth-child(2) {
        width: 80px;
    }
    .ao-sh-lh th:nth-child(8) {
        width: 64px;
    }
    .ao-sh-lh th:nth-child(7) {
        width: 104px;
    }
}
@media (max-width: 760px) {
    .ao-sh-hero {
        gap: var(--ao-s-4);
    }
    .ao-sh-ring {
        height: 84px;
        width: 84px;
    }
    .ao-sh-grade,
    .ao-sh-hero-num {
        font-size: 28px;
    }
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-sh-meter-fill {
        transition: none;
    }
}

/* ── Performance (#/performance) — design system v2 (2026-09-23) ───────────
 * KPI strips for throughput and the database, severity cards for "what to
 * fix first" (the edge, icon and value carry the severity — never an inline
 * colour), the frame-rate chain as four cards in a row with a meter against
 * the target rate, and the latency / table-size tables with bars. The card
 * sub-line (.ao-card-sub, used across these panels) gets its first rule. */
.ao-perf-panel {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-perf-panel .ao-card-sub,
.ao-perf-panel.ao-card-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.45;
}
.ao-perf-note {
    align-items: flex-start;
    display: flex;
    gap: 6px;
}
.ao-perf-note .ao-ico {
    flex: none;
    margin-top: 2px;
}
/* WHAT TO FIX FIRST */
.ao-perf-issues {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
}
.ao-perf-issue {
    --ao-perf-tone: var(--ao-fg-mute);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        inset 3px 0 0 var(--ao-perf-tone),
        var(--ao-elev-1);
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    min-width: 0;
}
.ao-perf-issue.is-err {
    --ao-perf-tone: var(--ao-err-strong);
}
.ao-perf-issue.is-warn {
    --ao-perf-tone: var(--ao-warn-strong);
}
.ao-perf-issue.is-ok {
    --ao-perf-tone: var(--ao-ok);
}
.ao-perf-issue-head {
    align-items: center;
    display: flex;
    gap: var(--ao-s-2);
}
.ao-perf-issue-head .ao-card-h {
    color: var(--ao-fg);
    flex: 1;
    font-size: var(--ao-fs-body);
    letter-spacing: 0;
    margin: 0;
    min-width: 0;
    text-transform: none;
}
.ao-perf-issue-ico {
    background: var(--ao-tint-2);
    border-radius: 8px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-perf-tone);
    display: grid;
    flex: none;
    height: 30px;
    place-items: center;
    width: 30px;
}
/* The severity pill wears the state-pill fills (.ao-state-pill.is-*), so
 * the page has one severity style, not three. */
.ao-perf-sev {
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    flex: none;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.03em;
    line-height: 1.6;
    padding: 1px 8px;
    text-transform: uppercase;
    white-space: nowrap;
}
.ao-perf-sev.is-ok {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-perf-sev.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-perf-sev.is-err {
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-strong);
}
.ao-perf-sev.is-idle {
    border-style: dashed;
}
.ao-perf-issue-val {
    color: var(--ao-perf-tone);
    font-size: 26px;
    font-weight: 600;
    letter-spacing: -0.03em;
    line-height: 1.1;
}
.ao-perf-issue.is-ok .ao-perf-issue-val,
.ao-perf-issue.is-idle .ao-perf-issue-val {
    color: var(--ao-fg);
}
.ao-perf-issue-unit {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-left: 4px;
}
.ao-perf-rec {
    align-items: flex-start;
    color: var(--ao-fg);
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    line-height: 1.45;
    margin-top: auto;
}
.ao-perf-rec .ao-ico {
    color: var(--ao-perf-tone);
    flex: none;
    margin-top: 2px;
}
/* FRAME-RATE CHAIN: four stages left to right, a chevron between them. */
.ao-perf-chain {
    display: grid;
    gap: var(--ao-s-5);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
}
.ao-perf-stage {
    --ao-perf-tone: var(--ao-fg-mute);
    border-top: 3px solid var(--ao-perf-tone);
    min-width: 0;
    position: relative;
}
.ao-perf-stage.is-ok {
    --ao-perf-tone: var(--ao-ok);
}
.ao-perf-stage.is-warn {
    --ao-perf-tone: var(--ao-warn);
}
.ao-perf-stage.is-err {
    --ao-perf-tone: var(--ao-err-strong);
}
.ao-perf-stage:not(:last-child)::after {
    border-right: 2px solid var(--ao-border);
    border-top: 2px solid var(--ao-border);
    content: '';
    height: 9px;
    position: absolute;
    right: calc(var(--ao-s-5) / -2 - 5px);
    top: 50%;
    transform: translateY(-50%) rotate(45deg);
    width: 9px;
}
.ao-perf-stage-body {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}
.ao-perf-stage-head {
    align-items: center;
    display: flex;
    gap: var(--ao-s-2);
    margin-bottom: 2px;
    min-width: 0;
}
.ao-perf-stage .ao-card-h {
    flex: 1;
    margin: 0;
    min-width: 0;
}
.ao-perf-stage-val {
    align-items: baseline;
    display: flex;
}
.ao-perf-fps {
    color: var(--ao-fg);
    font-size: 30px;
    font-weight: 600;
    letter-spacing: -0.04em;
    line-height: 1.05;
}
.ao-perf-fps-unit {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-left: 4px;
    white-space: pre;
}
.ao-perf-meter {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: block;
    height: 6px;
    overflow: hidden;
    position: relative;
}
.ao-perf-meter.is-unmeasured {
    background: repeating-linear-gradient(45deg, var(--ao-tint-2) 0 3px, transparent 3px 6px);
}
.ao-perf-meter-fill {
    background: var(--ao-perf-tone);
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
/* A failed source's own words inside its stage card: the red note, so the
 * reason reads as the finding it is (not as plain white text). */
.ao-perf-panel .ao-perf-detail {
    background: var(--ao-err-soft);
    border-left: 2px solid var(--ao-err-strong);
    border-radius: 0 var(--ao-r-sm) var(--ao-r-sm) 0;
    color: var(--ao-err);
    padding: 6px 10px;
}
/* API LATENCY: the band legend, then the table. */
.ao-perf-legend {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 6px 10px;
}
.ao-perf-band {
    align-items: center;
    display: inline-flex;
    gap: 5px;
}
.ao-perf-band-dot {
    border-radius: 50%;
    height: 8px;
    width: 8px;
}
.ao-perf-band.is-ok .ao-perf-band-dot {
    background: var(--ao-ok);
}
.ao-perf-band.is-warn .ao-perf-band-dot {
    background: var(--ao-warn);
}
.ao-perf-band.is-critical .ao-perf-band-dot {
    background: var(--ao-err-strong);
}
.ao-perf-route {
    color: var(--ao-fg);
}
.ao-perf-method {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    padding: 0 5px;
}
.ao-perf-lat.is-ok {
    color: var(--ao-ok-text);
}
.ao-perf-lat.is-warn,
.ao-perf-share.is-warn,
.ao-perf-warn-note {
    color: var(--ao-warn-strong);
}
.ao-perf-lat.is-critical,
.ao-perf-errs.is-err,
.ao-perf-share.is-err {
    color: var(--ao-err-strong);
    font-weight: 600;
}
@media (max-width: 760px) {
    .ao-perf-stage:not(:last-child)::after {
        display: none;
    }
    .ao-perf-chain {
        gap: var(--ao-s-3);
    }
}
@media (max-width: 759px) {
    /* An odd last KPI card (Database's five, Throughput's three) takes the
     * row, not half of it. */
    .ao-perf-panel .ao-stat-row > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
    /* API LATENCY keeps ROUTE, p95 and 5xx: method, count, p50, p99 and 4xx
     * drop out so the p95 sits beside the route. */
    .ao-perf-lat-table th:nth-child(2),
    .ao-perf-lat-table td:nth-child(2),
    .ao-perf-lat-table th:nth-child(3),
    .ao-perf-lat-table td:nth-child(3),
    .ao-perf-lat-table th:nth-child(4),
    .ao-perf-lat-table td:nth-child(4),
    .ao-perf-lat-table th:nth-child(6),
    .ao-perf-lat-table td:nth-child(6),
    .ao-perf-lat-table th:nth-child(8),
    .ao-perf-lat-table td:nth-child(8) {
        display: none;
    }
    .ao-perf-lat-table .ao-perf-route {
        display: inline-block;
        max-width: 170px;
        overflow: hidden;
        text-overflow: ellipsis;
        vertical-align: bottom;
    }
    /* DB settings: fixed columns, the NOTE column folds under the setting's
     * name so the value stays on screen. */
    .ao-perf-settings,
    .ao-perf-big {
        table-layout: fixed;
    }
    .ao-perf-settings th:nth-child(3),
    .ao-perf-settings td:nth-child(3) {
        display: none;
    }
    .ao-perf-settings th:nth-child(2) {
        width: 88px;
    }
    .ao-perf-settings td:first-child {
        white-space: normal;
    }
    .ao-perf-setting-note {
        display: block;
        font-family: var(--ao-font-sans);
        font-size: var(--ao-fs-meta);
        margin-top: 2px;
    }
    /* BIGGEST TABLES: the name cuts, size and share keep their width. */
    .ao-perf-big th:nth-child(2) {
        width: 84px;
    }
    .ao-perf-big th:nth-child(3) {
        width: 100px;
    }
}
/* The folded note is for a phone only; a wide screen has the NOTE column. */
@media (min-width: 760px) {
    .ao-perf-setting-note {
        display: none;
    }
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-perf-meter-fill {
        transition: none;
    }
}

/* Live-camera modal transport chip (HLS / MJPEG / OFFLINE), matching the border
 * vocabulary the other chips use. It sits on the modal card (--ao-surface-2), so
 * --ao-border-soft would be invisible there (1.02:1) — it takes --ao-border over
 * a darker fill instead.
 * 🪤 :empty uses VISIBILITY, not display. buildCameraLiveModal creates the chip
 * empty and start() calls setTransport('', null) before the player resolves;
 * `display:none` would collapse the row and drop everything below it, then jump
 * back when the transport arrives. visibility alone is NOT enough either: an
 * empty inline-block has zero content height, so the line box still changes.
 * The nbsp in :empty::before gives it the filled state's exact font metrics —
 * and a pseudo-element is not a child node, so it does not break the :empty
 * match. Together: reserved box, nothing visible, no shift.
 * ⛔ No `opacity` here. It composites the border, fill AND text onto the card,
 * which dropped the border back to ~1.25:1 and undid the reason this rule sets
 * --ao-border at all. The chip is a status indicator, not chrome — the ok/warn
 * colour setTransport writes should read at full strength.
 * No `color` here either: setTransport writes an inline colour on EVERY path
 * (including its null reset), so any colour declared here would be dead. */
.ao-live-transport {
    display: inline-block;
    margin-top: 8px;
    padding: 2px 7px;
    background: var(--ao-bg);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-sm);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
}
.ao-live-transport:empty {
    visibility: hidden;
}
.ao-live-transport:empty::before {
    content: '\00a0';
}

/* ── AGENT DETAIL (#/agent/<uid>/<tenant>) — rehaul 2026-09-23 ───────────────
 * A KPI strip over the Team range tray (the aoTabs classes on this page's own
 * bar), then each tab body as an aoSection over a card or an aoTable card. The
 * builders set no looks inline any more; everything below is tokens only. */
.ao-ad-back {
    align-self: flex-start;
}
.ao-ad-panel {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
.ao-ad-tabs {
    margin: 0;
    min-width: 0;
}
.ao-ad-tab-body {
    padding-top: var(--ao-s-4);
}
/* On a phone the tab tray scrolls sideways: the edge with more tabs past it
 * fades out (_adTabEdges sets .is-overflow / .is-scrolled / .is-end), so a
 * cut-off "CAMERAS" reads as "more this way". */
.ao-ad-tabs > .ao-tabs-bar.is-overflow:not(.is-end):not(.is-scrolled) {
    -webkit-mask-image: linear-gradient(90deg, black calc(100% - 28px), transparent);
    mask-image: linear-gradient(90deg, black calc(100% - 28px), transparent);
}
.ao-ad-tabs > .ao-tabs-bar.is-overflow.is-scrolled:not(.is-end) {
    -webkit-mask-image: linear-gradient(90deg, transparent, black 28px, black calc(100% - 28px), transparent);
    mask-image: linear-gradient(90deg, transparent, black 28px, black calc(100% - 28px), transparent);
}
.ao-ad-tabs > .ao-tabs-bar.is-overflow.is-scrolled.is-end {
    -webkit-mask-image: linear-gradient(90deg, transparent, black 28px);
    mask-image: linear-gradient(90deg, transparent, black 28px);
}
.ao-ad-live {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-6);
}
/* A tab's body (.ao-ad-pane, not "-tab": the scroll-keep contract treats any
 * *-tab class as a clickable tab). */
.ao-ad-region,
.ao-ad-pane {
    min-width: 0;
}
.ao-ad-pane + .ao-ad-pane,
.ao-ad-tail-card + .ao-ad-pane {
    margin-top: var(--ao-s-5);
}

/* Batch helpers (agent detail, incubator, releases, rollouts): headings the
 * tests read in capitals are drawn in sentence case, like Team's; on a phone
 * the low-value columns (.ao-agr-hide-sm on th + td) step aside and a
 * timestamp is its age alone (the stamp stays on hover), so each table's
 * state and action columns are on screen without a sideways scroll. */
.ao-agr-sc > .ao-sec-h {
    text-transform: lowercase;
}
.ao-agr-sc > .ao-sec-h::first-letter {
    text-transform: uppercase;
}
/* A cell's value with a muted second line under it (_agrTwoLine). The line
 * marked .ao-agr-sm-only shows on a phone alone, where it carries the value
 * of a column that steps aside there. */
.ao-agr-2l {
    display: inline-flex;
    flex-direction: column;
    gap: 2px;
    max-width: 100%;
    min-width: 0;
    vertical-align: middle;
}
.ao-agr-2l-sub {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-family: var(--ao-font-sans);
    font-size: var(--ao-fs-label);
    font-weight: 400;
    gap: 2px 6px;
    letter-spacing: 0;
    white-space: normal;
}
.ao-agr-2l-sub.ao-agr-sm-only,
.ao-agr-sm-only {
    display: none;
}
/* A long state word ("operator IP not allowed") stays one line, clipped with
 * an ellipsis; the code and the detail are on hover. */
.ao-state-pill.ao-agr-clip {
    box-sizing: border-box;
    display: inline-block;
    max-width: 30ch;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
    white-space: nowrap;
}
.ao-state-pill.ao-agr-clip > .ao-ico {
    display: inline-block;
    margin-right: 5px;
    vertical-align: -1px;
}
@media (max-width: 760px) {
    .ao-table th.ao-agr-hide-sm,
    .ao-table td.ao-agr-hide-sm {
        display: none;
    }
    .ao-agr-when .ao-agr-when-abs {
        display: none;
    }
    .ao-agr-2l-sub.ao-agr-sm-only {
        display: flex;
    }
    .ao-state-pill.ao-agr-clip {
        max-width: 18ch;
    }
    .ao-rel-card .ao-state-pill.ao-agr-clip {
        max-width: 15ch;
    }
    span.ao-agr-sm-only:not(.ao-agr-2l-sub) {
        display: inline-flex;
    }
    /* A version cell is the version number on a phone ("v2.18.1"). */
    .ao-agr-ver-pre {
        display: none;
    }
    .ao-agr-table .ao-table th,
    .ao-agr-table .ao-table td,
    .ao-rel-table th,
    .ao-rel-table td {
        padding-left: 8px;
        padding-right: 8px;
    }
}

/* The meta line once the payload names the agent: store · short id chip. */
.ao-ad-meta {
    align-items: center;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 4px 10px;
}
.ao-ad-meta-store {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-ad-meta-id {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    padding: 0 8px;
}

/* LIVE tab — camera tiles: a card grid, each tile a Team card with an icon
 * tile, the name, the liveness line and one action. A camera that is down or
 * degraded wears a 2px stripe in its state colour along the top edge. */
/* Even rows: liveCamerasInto sets --ao-stat-cols (aoStat.cols), so six
 * cameras are one row of six on a wide screen, never 5 + 1; two across on a
 * phone. */
.ao-ad-camgrid {
    --ao-stat-cols: 6;
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(
        auto-fit,
        minmax(max(172px, calc((100% - (var(--ao-stat-cols) - 1) * var(--ao-s-3)) / var(--ao-stat-cols) - 1px)), 1fr)
    );
}
@media (max-width: 760px) {
    .ao-ad-camgrid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}
/* A word as the KPI value (Online, v2.18.1, Active) never spills its card. */
.ao-ad-kpis .ao-stat-num {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Words are set in the sans face (a number keeps the mono), and a state word
 * wears its state colour, as Incubator's PASS / FAIL do. */
#argus-ops-root .ao-ad-kpis .ao-stat.is-word .ao-stat-num {
    font-family: var(--ao-font-sans);
    letter-spacing: -0.02em;
}
.ao-ad-kpis .ao-stat.is-tone-ok .ao-stat-num {
    color: var(--ao-ok-text);
}
.ao-ad-kpis .ao-stat.is-tone-warn .ao-stat-num {
    color: var(--ao-warn-text);
}
.ao-ad-kpis .ao-stat.is-tone-err .ao-stat-num {
    color: var(--ao-err-strong);
}
/* CPU / memory: a load meter under the number, teal / amber / red. */
.ao-ad-load .ao-ro-meter-track {
    max-width: none;
}
.ao-ad-load.is-ok .ao-ro-meter-fill {
    background: var(--ao-k-1);
}
.ao-ad-load.is-warn .ao-ro-meter-fill {
    background: var(--ao-warn);
}
.ao-ad-load.is-err .ao-ro-meter-fill {
    background: var(--ao-err-strong);
}
.ao-live-tile {
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    font-variant-numeric: tabular-nums;
    gap: 10px;
    min-width: 0;
    overflow: hidden;
    padding: 14px;
    position: relative;
}
.ao-live-tile::before {
    background: transparent;
    content: '';
    height: 2px;
    inset: 0 0 auto;
    position: absolute;
}
.ao-live-tile[data-state='ok']::before {
    background: var(--ao-ok-border);
}
.ao-live-tile[data-state='warn']::before {
    background: var(--ao-warn-border);
}
.ao-live-tile[data-state='err']::before {
    background: var(--ao-err-border-strong);
}
.ao-ad-cam-head {
    align-items: flex-start;
    display: flex;
    gap: 10px;
    min-width: 0;
}
.ao-ad-cam-ico,
.ao-ad-action-ico,
.ao-console-ico {
    background: color-mix(in srgb, var(--ao-k-2) 14%, transparent);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ao-k-2) 24%, transparent);
    color: var(--ao-k-2);
    display: grid;
    flex: none;
    height: 30px;
    place-items: center;
    width: 30px;
}
.ao-ad-cam-names {
    flex: 1 1 auto;
    min-width: 0;
}
/* The name wraps rather than truncating ("Front Entr…" on a phone); the
 * status dot sits on the icon tile's corner, so the name has the row. */
.ao-ad-cam-name {
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    line-height: 1.3;
    overflow-wrap: anywhere;
}
.ao-ad-cam-ico {
    position: relative;
}
.ao-ad-cam-ico > .ao-dot {
    height: 9px;
    outline: 2px solid var(--ao-surface-2);
    position: absolute;
    right: -3px;
    top: -3px;
    width: 9px;
}
.ao-ad-cam-where {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-top: 1px;
}
.ao-ad-cam-live {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
.ao-ad-cam-act {
    display: flex;
    margin-top: auto;
}
.ao-ad-cam-why {
    align-items: center;
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
}

/* LIVE tab — the data-flow strip: four KPI cards (aoStat) in pipeline order,
 * a chevron between each stage on a wide screen. The health dot and the
 * deep-link ride the card's head row, right-aligned. */
.ao-dataflow-strip {
    --ao-stat-cols: 4;
    box-sizing: border-box;
    min-width: 0;
}
.ao-dataflow-card {
    box-sizing: border-box;
    min-width: 0;
    font-variant-numeric: tabular-nums;
}
.ao-dataflow-card .ao-stat-head > .ao-dot {
    margin-left: auto;
}
/* The health dot rides the icon tile's corner, as on the camera tiles. */
.ao-dataflow-card .ao-stat-ico.ao-df-ico {
    position: relative;
}
.ao-df-ico > .ao-dot {
    height: 9px;
    outline: 2px solid var(--ao-surface-2);
    position: absolute;
    right: -3px;
    top: -3px;
    width: 9px;
}
.ao-dataflow-card .ao-stat-unit {
    white-space: nowrap;
}
/* The storage label breaks only after a "." or "," (a <wbr> there), and a
 * bracketed aside ("(best-effort)") stays whole. */
.ao-dataflow-card .ao-stat-cap {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    overflow-wrap: normal;
    word-break: normal;
}
.ao-df-nowrap {
    white-space: nowrap;
}
.ao-dataflow-card[data-health='warn'] {
    box-shadow:
        inset 0 2px 0 var(--ao-warn-border),
        var(--ao-elev-1);
}
.ao-dataflow-card[data-health='err'] {
    box-shadow:
        inset 0 2px 0 var(--ao-err-border-strong),
        var(--ao-elev-1);
}
.ao-df-link {
    align-items: center;
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    display: inline-flex;
    height: 24px;
    justify-content: center;
    text-decoration: none;
    width: 24px;
}
.ao-df-link:hover {
    background: var(--ao-hover);
    color: var(--ao-fg);
}
.ao-df-link:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 1px;
}
/* On a phone the deep link rides the card's top-right corner, so the head
 * row is the icon and the stage name alone ("Store-Notify" on one line). */
@media (max-width: 760px) {
    .ao-dataflow-card .ao-df-link {
        height: 22px;
        position: absolute;
        right: 8px;
        top: 8px;
        width: 22px;
    }
    .ao-dataflow-card .ao-stat-label {
        white-space: nowrap;
    }
}
@media (min-width: 900px) {
    .ao-dataflow-card:not(:last-child)::after {
        border-right: 1.5px solid var(--ao-border);
        border-top: 1.5px solid var(--ao-border);
        content: '';
        height: 7px;
        position: absolute;
        right: -9px;
        top: 50%;
        transform: translateY(-50%) rotate(45deg);
        width: 7px;
    }
}
.ao-df-unavail {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    grid-column: 1 / -1;
    padding: 6px 0;
}

/* LIVE tab — the command console: a card whose head is the toggle (icon
 * tile, title, the allowlisted verbs, a chevron that turns when open). */
.ao-console {
    box-sizing: border-box;
    padding: 0;
    overflow: hidden;
}
.ao-console-toggle {
    align-items: center;
    background: transparent;
    border: 0;
    color: var(--ao-fg);
    cursor: pointer;
    display: flex;
    font-family: inherit;
    gap: 12px;
    padding: 12px 16px;
    text-align: left;
    width: 100%;
}
.ao-console-toggle:hover {
    background: var(--ao-tint);
}
.ao-console-toggle:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: -2px;
}
.ao-console-ico {
    background: color-mix(in srgb, var(--ao-k-3) 14%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ao-k-3) 24%, transparent);
    color: var(--ao-k-3);
}
.ao-console-title {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.ao-console-name {
    font-size: var(--ao-fs-strong);
    font-weight: 600;
}
.ao-console-verbs {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    overflow-wrap: anywhere;
}
.ao-console-chev {
    color: var(--ao-fg-mute);
    display: grid;
    transition: transform var(--ao-fast) var(--ao-ease);
}
.ao-console-toggle[aria-expanded='true'] .ao-console-chev {
    transform: rotate(180deg);
}
.ao-console-body {
    border-top: 1px solid var(--ao-tint-line);
    padding: 14px 16px 16px;
}
.ao-console-quick {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 12px;
}
.ao-console-inrow {
    align-items: center;
    display: flex;
    gap: 8px;
}
.ao-console-prompt {
    color: var(--ao-accent-line);
    display: grid;
}
.ao-console-input {
    flex: 1 1 auto;
    font-family: var(--ao-mono);
    min-width: 0;
}
/* Console output: monospace + scroll; long lines wrap inside the scroll
   region rather than forcing horizontal overflow. */
.ao-console-out {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    box-shadow: inset 0 1px 2px var(--ao-shadow);
    box-sizing: border-box;
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    margin-top: 10px;
    max-height: 280px;
    overflow: auto;
    padding: 10px 12px;
    white-space: pre-wrap;
    word-break: break-word;
}
.ao-console-out:empty {
    display: none;
}
.ao-console-block + .ao-console-block {
    margin-top: 10px;
}
.ao-console-echo {
    color: var(--ao-fg-mute);
    white-space: pre-wrap;
    word-break: break-word;
}
.ao-console-echo.is-err {
    color: var(--ao-err);
}
.ao-console-pre {
    color: var(--ao-fg);
    font-family: inherit;
    font-size: var(--ao-fs-meta);
    margin: 4px 0 0;
    white-space: pre-wrap;
    word-break: break-word;
}
.ao-console-hint {
    color: var(--ao-warn-text);
    margin: 6px 0;
}

/* OVERVIEW tab — one identity card: enrollment (left) beside activity and
 * the last telemetry report (right), stacked on a phone. The version, CPU
 * and memory the KPI strip shows are not repeated here. */
.ao-ad-ov {
    align-items: start;
    display: grid;
    gap: var(--ao-s-2) var(--ao-s-6);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr));
}
.ao-ad-ov-card {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-ad-ov-card > .ao-sec-head {
    margin-bottom: 0;
}
.ao-ad-kvgroup {
    min-width: 0;
}
.ao-ad-kvgroup-h {
    align-items: center;
    border-bottom: 1px solid var(--ao-tint-line);
    color: var(--ao-fg-mute);
    display: flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 6px;
    letter-spacing: 0.08em;
    padding-bottom: 6px;
    text-transform: uppercase;
}
.ao-ad-kvs {
    display: flex;
    flex-direction: column;
}
.ao-ad-kv {
    align-items: center;
    border-top: 1px solid var(--ao-tint-line);
    display: grid;
    font-size: var(--ao-fs-body);
    gap: 4px 12px;
    grid-template-columns: minmax(110px, 38%) minmax(0, 1fr);
    padding: 8px 0;
}
.ao-ad-kv:first-child {
    border-top: 0;
}
.ao-ad-kv-k {
    color: var(--ao-fg-mute);
}
.ao-ad-kv-v {
    color: var(--ao-fg);
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-ad-kv-v.is-mono {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-ad-kv-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    grid-column: 2;
    height: 4px;
    overflow: hidden;
}
.ao-ad-kv-fill {
    background: var(--ao-k-1);
    border-radius: inherit;
    display: block;
    height: 100%;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
}

/* Tables — a cell with a muted second line; the shared timestamp cell. */
.ao-ad-cell-name {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.ao-ad-cell-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
@media (max-width: 760px) {
    .ao-ad-cell-hw {
        display: none;
    }
}
.ao-agr-when {
    align-items: baseline;
    display: inline-flex;
    gap: 8px;
    white-space: nowrap;
}
.ao-agr-when-abs {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}

/* ACTIONS tab — two action cards; the revoke one in the err family. */
.ao-ad-actions {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}
.ao-ad-action {
    align-items: flex-start;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.ao-ad-action-h {
    align-items: center;
    display: flex;
    gap: 10px;
    width: 100%;
}
.ao-ad-action-h .ao-state {
    margin-left: auto;
}
.ao-ad-action-t {
    font-size: var(--ao-fs-strong);
    font-weight: 600;
}
.ao-ad-action-txt {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
    max-width: 62ch;
}
.ao-ad-action.is-danger .ao-ad-action-ico {
    background: var(--ao-err-bg);
    box-shadow: inset 0 0 0 1px var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-ad-tunnel .ao-ico {
    order: 2;
}

/* LOGS tab — the live tail: a sunken terminal pane in a card. */
.ao-ad-note {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    margin-bottom: 10px;
    max-width: 70ch;
}
.ao-ad-tail {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    box-shadow: inset 0 1px 2px var(--ao-shadow);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    line-height: 1.55;
    margin: 0;
    max-height: 240px;
    min-height: 64px;
    overflow: auto;
    padding: 10px 12px;
    white-space: pre-wrap;
    word-break: break-word;
}
.ao-ad-tail:empty::before {
    color: var(--ao-fg-mute);
    content: 'No live frames yet. Attach the tail to stream them here.';
}
.ao-ad-tail-line {
    display: flex;
    gap: 10px;
}
.ao-ad-tail-seq {
    color: var(--ao-fg-mute);
    flex: 0 0 52px;
    text-align: right;
}
.ao-ad-tail-text {
    min-width: 0;
}
.ao-ad-dl .ao-ico {
    flex: none;
}
/* The archive's object key is a long path: the cell is its file name
 * (c6.jsonl.gz), the full key on hover. */
.ao-table td.ao-ad-chunk {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
.ao-ad-chunk-name {
    cursor: default;
}

/* ── ALERTING tab ──────────────────────────────────────────────────────── */
/* Design system v2 (2026-09-23): every colour below is a status token (these
   base rules were hex). The rows, chips, banner and trends take the Team
   card look in the OPS DESK v2 block right after this section, scoped to
   the Alerting / Tickets pages — the Incubator reuses .ao-al-* and keeps
   these base rules. */
/* Planned-maintenance banner: sits above the summary counts. Neutral/blue, not
   an alert colour — it explains quiet, it is not itself a problem. */
.ao-al-maint {
    margin-bottom: 14px;
    padding: 10px 12px;
    border: 1px solid var(--ao-info-bd);
    border-left-width: 3px;
    border-radius: var(--ao-r-md);
    background: var(--ao-info-bg);
}
.ao-al-maint-h {
    font-size: var(--ao-fs-meta);
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--ao-info-fg);
    margin-bottom: 6px;
}
/* Banner header: the count on the left, SILENCE FLEET on the right. */
.ao-al-maint-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}
/* Bare strip carrying SILENCE FLEET when NO window is active. Deliberately
   quiet: it is a door, not a status. */
.ao-al-fleetsilence {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 10px;
}
.ao-al-maint-row {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    font-size: var(--ao-fs-body);
    padding: 2px 0;
}
.ao-al-maint-kind {
    font-size: var(--ao-fs-label);
    font-weight: 700;
    letter-spacing: 0.05em;
    padding: 2px 7px;
    border: 1px solid var(--ao-info-bd);
    border-radius: var(--ao-r-tag);
    color: var(--ao-info-fg);
}
.ao-al-maint-scope {
    font-size: var(--ao-fs-meta);
    opacity: 0.7;
    font-variant-numeric: tabular-nums;
}
.ao-al-maint-reason {
    flex: 1 1 240px;
    opacity: 0.9;
}
.ao-al-maint-meta {
    font-size: var(--ao-fs-meta);
    opacity: 0.55;
    font-variant-numeric: tabular-nums;
}
.ao-al-maint-note {
    margin-top: 6px;
    font-size: var(--ao-fs-meta);
    opacity: 0.6;
}
/* END NOW on a banner row: pushed to the far right of the row. Ending a window
   must be as cheap as opening one, so it sits on every row rather than behind a
   detail view. */
.ao-al-maint-end {
    margin-left: auto;
}
/* SILENCE / Un-silence / SILENCE FLEET. Design system v2 (2026-09-23): a
   plain pill with a bell icon, not the maintenance blue — an info-blue label
   and border beside the neutral pills read as a link or a status, not a
   control. The bell says "planned-work system" now. */
.ao-al-btn-silence,
.ao-btn.ao-al-btn-silence {
    align-items: center;
    border-color: var(--ao-border-soft);
    color: inherit;
    display: inline-flex;
    gap: 6px;
}
.ao-al-btn-silence:hover:not(:disabled) {
    border-color: var(--ao-border);
}
/* The bell is painted by CSS, not an aoIcon node: every silence path writes
 * btn.textContent ('Silencing…', then the label back), which would strip a
 * child icon after the first click. A currentColor mask of the icon set's
 * bell glyph survives any text write. */
.ao-al-btn-silence::before {
    background: currentColor;
    content: '';
    flex: none;
    height: 13px;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9'/%3E%3Cpath d='M10.3 21a1.94 1.94 0 0 0 3.4 0'/%3E%3C/svg%3E")
        center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9'/%3E%3Cpath d='M10.3 21a1.94 1.94 0 0 0 3.4 0'/%3E%3C/svg%3E")
        center / contain no-repeat;
    width: 13px;
}
/* Ack and Resolve get a glyph the same way (a check, a check in a circle),
 * so every pill on a row carries an icon. CSS, not a node: _ackAlert writes
 * the button's text and the tests read the label as the whole text. */
.ao-al-btn-ack,
.ao-al-btn-resolve {
    align-items: center;
    display: inline-flex;
    gap: 6px;
}
.ao-al-btn-ack::before,
.ao-al-btn-resolve::before {
    background: currentColor;
    content: '';
    flex: none;
    height: 13px;
    width: 13px;
}
.ao-al-btn-ack::before {
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
        center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
        center / contain no-repeat;
}
.ao-al-btn-resolve::before {
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E")
        center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E")
        center / contain no-repeat;
}
/* Row chip on an alert an ACTIVE window covers. Distinct from .ao-al-planned:
   PLANNED is the producer's stamp on a stored row, this is the live window the
   console can still cancel. */
.ao-al-silenced {
    font-size: var(--ao-fs-label);
    font-weight: 700;
    letter-spacing: 0.05em;
    padding: 2px 7px;
    border: 1px solid var(--ao-info-bd);
    border-radius: var(--ao-r-lg);
    color: var(--ao-info-fg);
    cursor: help;
    font-variant-numeric: tabular-nums;
}
/* Row chip on an alert the producer capped to info. */
.ao-al-planned {
    font-size: var(--ao-fs-label);
    font-weight: 700;
    letter-spacing: 0.05em;
    padding: 2px 7px;
    border: 1px solid var(--ao-info-bd);
    border-radius: var(--ao-r-lg);
    color: var(--ao-info-fg);
    cursor: help;
}
/* Row chip on an alert the producer capped to info because the same dedup_key
   keeps reopening. Amber like INTENT UNKNOWN rather than blue like PLANNED:
   nobody declared this, the platform inferred it from repetition, and the
   underlying condition may well still be real. */
.ao-al-flap {
    font-size: var(--ao-fs-label);
    font-weight: 700;
    letter-spacing: 0.05em;
    padding: 2px 7px;
    border: 1px solid var(--ao-warn-bd);
    border-radius: var(--ao-r-lg);
    color: var(--ao-warn);
    cursor: help;
    font-variant-numeric: tabular-nums;
}
/* Three-valued intent chip. INTENT UNKNOWN is the default and it PAGES, so it
   is styled as a live question (amber), not as a neutral absence. */
.ao-al-intent {
    font-size: var(--ao-fs-label);
    font-weight: 700;
    letter-spacing: 0.05em;
    padding: 2px 7px;
    border-radius: var(--ao-r-lg);
    border: 1px solid transparent;
    cursor: help;
}
.ao-al-intent-expected {
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-al-intent-unexpected {
    border-color: var(--ao-err-bd);
    color: var(--ao-err-strong);
}
.ao-al-intent-unknown {
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn);
}
.ao-al-summary {
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
    margin-bottom: 14px;
    font-size: var(--ao-fs-body);
    font-variant-numeric: tabular-nums;
}
.ao-al-count {
    opacity: 0.75;
}
.ao-al-c-critical {
    color: var(--ao-err-strong);
    opacity: 1;
}
.ao-al-c-warn {
    color: var(--ao-warn);
    opacity: 1;
}
.ao-al-h {
    margin: 14px 0 8px;
    font-size: var(--ao-fs-meta);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.7;
}
.ao-al-row {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 10px 12px;
    margin-bottom: 8px;
    border: 1px solid var(--ao-tint-line);
    border-left-width: 3px;
    border-radius: var(--ao-r-md);
    background: var(--ao-tint);
}
.ao-al-row.ao-al-critical {
    border-left-color: var(--ao-err-strong);
}
.ao-al-row.ao-al-warn {
    border-left-color: var(--ao-warn);
}
.ao-al-row.ao-al-info {
    border-left-color: var(--ao-fg-mute);
}
/* A FIXED ticket is good news waiting on its guard, not an emergency: the
 * badge and the bar take the ok colour whatever the origin severity was (a
 * fixed critical wore the red it was opened with). Keyed on data-status, so
 * the severity classes tests read stay as they are. */
.ao-al-row[data-status='fixed'] {
    border-left-color: var(--ao-ok);
}
.ao-al-row[data-status='fixed'] .ao-al-badge {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-al-top {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.ao-al-badge {
    font-size: var(--ao-fs-label);
    font-weight: 700;
    letter-spacing: 0.05em;
    padding: 2px 7px;
    border: 1px solid;
    border-radius: var(--ao-r-tag);
}
.ao-al-badge-critical {
    color: var(--ao-err-strong);
    border-color: var(--ao-err-bd);
}
.ao-al-badge-warn {
    color: var(--ao-warn);
    border-color: var(--ao-warn-bd);
}
.ao-al-badge-info {
    color: var(--ao-fg-mute);
    border-color: var(--ao-border);
}
.ao-al-src {
    font-size: var(--ao-fs-label);
    letter-spacing: 0.05em;
    opacity: 0.6;
}
.ao-al-acked {
    font-size: var(--ao-fs-label);
    letter-spacing: 0.05em;
    opacity: 0.55;
}
.ao-al-age {
    margin-left: auto;
    font-size: var(--ao-fs-label);
    opacity: 0.45;
    font-variant-numeric: tabular-nums;
}
.ao-al-title {
    font-size: var(--ao-fs-strong);
}
.ao-al-body {
    font-size: var(--ao-fs-body);
    opacity: 0.7;
    /* The body is now a multi-line dashed report — keep its newlines (and still
       wrap long lines) instead of collapsing everything onto one line. */
    white-space: pre-wrap;
}
/* Remediation on an alert row. Deliberately NOT collapsed, unlike the log tail
   below: the log tail is evidence an operator opens while working an alert, but
   the remedy is the action itself. 1,722 alerts with zero acknowledgements is
   what "one more click" costs, so this one is always on screen. */
.ao-al-fix {
    margin-top: 4px;
    padding-left: 8px;
    border-left: 2px solid var(--ao-tint-strong);
}
.ao-al-why {
    font-size: var(--ao-fs-meta);
    opacity: 0.6;
    margin-bottom: 2px;
}
.ao-al-steps {
    margin: 0;
    padding-left: 16px;
    font-size: var(--ao-fs-meta);
    opacity: 0.85;
}
.ao-al-steps li {
    margin: 1px 0;
    /* Remedies carry commands and paths; keep them readable without letting a
       long one blow out the row width. */
    overflow-wrap: anywhere;
}

/* Agent log tail on an alert row — collapsed by default so the inbox stays
   scannable; only the operator working an alert expands it. */
.ao-al-logs {
    margin-top: 2px;
}
.ao-al-logs-sum {
    font-size: var(--ao-fs-meta);
    opacity: 0.6;
    cursor: pointer;
    user-select: none;
    letter-spacing: 0.04em;
}
.ao-al-logs-sum:hover {
    opacity: 0.85;
}
.ao-al-logs-meta {
    font-size: var(--ao-fs-meta);
    opacity: 0.7;
    margin-top: 6px;
}
.ao-al-logs-tail {
    font-family: var(--ao-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    opacity: 0.85;
    margin: 6px 0 0;
    padding: 8px 10px;
    max-height: 320px;
    overflow: auto;
    /* Preserve the log's own line breaks, but wrap long lines rather than
       forcing the whole row to scroll sideways. */
    white-space: pre-wrap;
    word-break: break-word;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    background: var(--ao-bg);
}
.ao-al-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
}
/* Open / DETAIL / SOURCE ALERT. Design system v2 (2026-09-23): a ghost small
 * pill with an arrow (the JS adds .ao-btn.ao-btn-sm.is-ghost after this
 * class), not a bare info-blue link beside the pill buttons. The rule below
 * only covers a bare .ao-al-link nothing has upgraded. */
.ao-al-link {
    font-size: var(--ao-fs-meta);
    color: var(--ao-fg-dim);
    text-decoration: none;
}
.ao-al-link:not(.ao-btn):hover {
    text-decoration: underline;
}
/* Design system v2 (2026-09-23): the small .ao-btn pill — 26px literal
 * floor, surface fill, soft border, inset tint over elev-1, 11px/600
 * uppercase — so Ack / Resolve match PROMOTE TO TICKET beside them. The
 * source labels stay 'Ack' / 'Resolve' (tests read them); the case is CSS. */
.ao-al-btn {
    font-family: inherit;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    min-height: 26px;
    min-width: auto;
    padding: 4px 11px;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    background: var(--ao-surface);
    box-shadow:
        inset 0 1px 0 var(--ao-tint),
        var(--ao-elev-1);
    color: var(--ao-fg);
    cursor: pointer;
}
.ao-al-btn:hover {
    background: var(--ao-hover);
    border-color: var(--ao-border);
}
.ao-al-btn:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-al-btn:disabled {
    opacity: 0.5;
    cursor: default;
}
.ao-al-footer {
    margin-top: 18px;
    font-size: var(--ao-fs-meta);
    opacity: 0.5;
    font-variant-numeric: tabular-nums;
}

/* ── OPS DESK v2 — Alerting + Tickets (design system v2, 2026-09-23) ──────
   The Team page's family for the two .ao-al-* pages. Scoped to the page
   wrappers (.ao-al-page, .ao-tk-page) so the Incubator, which reuses the
   .ao-al-* classes, keeps its own look. ⛔ These overrides sit AFTER the base
   rules above on purpose: two CSS contract tests read the FIRST
   `.ao-al-body {` / `.ao-al-btn {` rule they find. Tokens only. */
.ao-al-panel,
.ao-trends-panel,
.ao-tk-panel {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}
.ao-al-page .ao-al-summary,
.ao-tk-page .ao-al-summary {
    display: block;
    margin: 0 0 4px;
}
/* A row is a Team card with a severity rail (::before), not a boxed line
   with a thick left border. Static: it lifts nothing on hover. */
.ao-al-page .ao-al-row,
.ao-tk-page .ao-al-row {
    --ao-al-sev: var(--ao-fg-mute);
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    gap: 8px;
    margin: 0;
    padding: 14px 16px 14px 20px;
    position: relative;
}
.ao-al-page .ao-al-row::before,
.ao-tk-page .ao-al-row::before {
    background: var(--ao-al-sev);
    border-radius: 0 3px 3px 0;
    bottom: 14px;
    box-shadow: 0 0 10px color-mix(in srgb, var(--ao-al-sev) 55%, transparent);
    content: '';
    left: 0;
    position: absolute;
    top: 14px;
    width: 3px;
}
.ao-al-page .ao-al-row.ao-al-critical,
.ao-tk-page .ao-al-row.ao-al-critical {
    --ao-al-sev: var(--ao-err-strong);
    background:
        radial-gradient(120% 90% at 0% 0%, color-mix(in srgb, var(--ao-err-strong) 9%, transparent), transparent 60%),
        linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
}
.ao-al-page .ao-al-row.ao-al-warn,
.ao-tk-page .ao-al-row.ao-al-warn {
    --ao-al-sev: var(--ao-warn);
}
.ao-al-page .ao-al-row.ao-al-info,
.ao-tk-page .ao-al-row.ao-al-info {
    --ao-al-sev: var(--ao-info);
}
.ao-tk-page .ao-al-row[data-status='fixed'] {
    --ao-al-sev: var(--ao-ok);
}
/* Closed / won't-fix / duplicate: receipts, one step quieter. */
.ao-tk-page .ao-al-row[data-status='closed'],
.ao-tk-page .ao-al-row[data-status='wont_fix'],
.ao-tk-page .ao-al-row[data-status='duplicate'] {
    --ao-al-sev: var(--ao-border);
    background: var(--ao-tint);
    box-shadow: none;
}
.ao-al-page .ao-al-top,
.ao-tk-page .ao-al-top {
    gap: 6px;
    row-gap: 6px;
}
/* One chip family for everything on a row's top line. */
.ao-al-page :is(.ao-al-badge, .ao-al-src, .ao-al-acked, .ao-al-planned, .ao-al-intent, .ao-al-flap, .ao-al-silenced),
.ao-tk-page :is(.ao-al-badge, .ao-al-src, .ao-al-flap) {
    align-items: center;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 5px;
    letter-spacing: 0.06em;
    line-height: 1.5;
    opacity: 1;
    padding: 1px 8px;
}
.ao-al-page .ao-al-src,
.ao-al-page .ao-al-acked,
.ao-tk-page .ao-al-src {
    background: var(--ao-tint-2);
    color: var(--ao-fg-dim);
    overflow-wrap: anywhere;
}
.ao-al-page .ao-al-badge-critical,
.ao-tk-page .ao-al-badge-critical {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-al-page .ao-al-badge-warn,
.ao-tk-page .ao-al-badge-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-al-page .ao-al-badge-info,
.ao-tk-page .ao-al-badge-info {
    background: var(--ao-info-bg);
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-al-page .ao-al-planned,
.ao-al-page .ao-al-silenced {
    background: var(--ao-info-bg);
}
/* On the chip line beside PLANNED, in the chips' voice (the literal reads
   "Silenced, lifts in 1h"; the case is CSS). */
.ao-al-page .ao-al-silenced {
    text-transform: uppercase;
}
.ao-al-page .ao-al-flap,
.ao-al-page .ao-al-intent-unknown,
.ao-tk-page .ao-al-flap {
    background: var(--ao-warn-bg);
}
.ao-al-page .ao-al-intent-expected {
    background: var(--ao-ok-bg);
}
.ao-al-page .ao-al-intent-unexpected {
    background: var(--ao-err-bg);
}
.ao-al-page .ao-al-age,
.ao-tk-page .ao-al-age {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    opacity: 1;
}
.ao-al-page .ao-al-title,
.ao-tk-page .ao-al-title {
    color: var(--ao-fg);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -0.005em;
    line-height: 1.35;
}
.ao-al-page .ao-al-body,
.ao-tk-page .ao-al-body {
    color: var(--ao-fg-dim);
    line-height: 1.5;
    opacity: 1;
}
/* The remedy: an inset panel with numbered steps (CSS counters, so the <li>
   text tests read stays exactly the step). */
.ao-al-page .ao-al-fix {
    background: var(--ao-tint);
    border: 1px solid var(--ao-tint-line);
    border-radius: 12px;
    margin-top: 2px;
    padding: 10px 12px;
}
.ao-al-page .ao-al-why {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-bottom: 6px;
    opacity: 1;
}
.ao-al-page .ao-al-steps {
    counter-reset: ao-al-step;
    display: flex;
    flex-direction: column;
    gap: 5px;
    list-style: none;
    opacity: 1;
    padding: 0;
}
.ao-al-page .ao-al-steps li {
    align-items: baseline;
    color: var(--ao-fg-dim);
    counter-increment: ao-al-step;
    display: flex;
    gap: 8px;
    margin: 0;
}
.ao-al-page .ao-al-steps li::before {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-pill);
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    content: counter(ao-al-step);
    flex: none;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    height: 17px;
    line-height: 17px;
    text-align: center;
    width: 17px;
}
/* LOGS: a pill toggle over a terminal block. */
.ao-al-page .ao-al-logs-sum {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    color: var(--ao-fg-dim);
    display: inline-flex;
    gap: 6px;
    list-style: none;
    opacity: 1;
    padding: 3px 11px;
}
.ao-al-page .ao-al-logs-sum::-webkit-details-marker {
    display: none;
}
.ao-al-page .ao-al-logs-sum::after {
    border-bottom: 1.5px solid currentColor;
    border-right: 1.5px solid currentColor;
    content: '';
    height: 5px;
    margin-left: 2px;
    transform: rotate(-45deg);
    transition: transform var(--ao-fast) var(--ao-ease);
    width: 5px;
}
.ao-al-page .ao-al-logs[open] > .ao-al-logs-sum::after {
    transform: rotate(45deg);
}
.ao-al-page .ao-al-logs-sum:hover {
    background: var(--ao-hover);
    color: var(--ao-fg);
}
.ao-al-page .ao-al-logs-tail {
    border-radius: 12px;
    color: var(--ao-fg-dim);
    opacity: 1;
    padding: 10px 12px;
}
/* The row's actions sit on a hairline, like a Team card's footer. */
.ao-al-page .ao-al-actions,
.ao-tk-page .ao-al-actions {
    border-top: 1px solid var(--ao-tint-line);
    margin-top: 4px;
    padding-top: 10px;
}
.ao-al-page .ao-btn.is-done {
    color: var(--ao-ok-fg);
}
/* Group headings: exact text ('CRITICAL (2)', 'STALE (1)'), a status dot and a
   hairline to the right edge — all CSS. */
.ao-al-page .ao-al-h,
.ao-tk-page .ao-al-h {
    --ao-al-h-dot: var(--ao-fg-mute);
    align-items: center;
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    gap: 10px;
    letter-spacing: 0.1em;
    margin: 12px 0 0;
    opacity: 1;
}
.ao-al-page .ao-al-h::before,
.ao-tk-page .ao-al-h::before {
    background: var(--ao-al-h-dot);
    border-radius: 50%;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--ao-al-h-dot) 22%, transparent);
    content: '';
    flex: none;
    height: 7px;
    width: 7px;
}
.ao-al-page .ao-al-h::after,
.ao-tk-page .ao-al-h::after {
    background: var(--ao-tint-line);
    content: '';
    flex: 1;
    height: 1px;
}
.ao-al-page .ao-al-h[data-sev='critical'],
.ao-tk-page .ao-al-h[data-section='STALE'] {
    --ao-al-h-dot: var(--ao-err-strong);
}
.ao-al-page .ao-al-h[data-sev='warn'],
.ao-tk-page .ao-al-h[data-section='UNOWNED BACKLOG'],
.ao-tk-page .ao-al-h[data-section='BLOCKED'] {
    --ao-al-h-dot: var(--ao-warn);
}
.ao-al-page .ao-al-h[data-sev='info'],
.ao-tk-page .ao-al-h[data-section^='OWNED BY'] {
    --ao-al-h-dot: var(--ao-info);
}
.ao-tk-page .ao-al-h[data-section='CLOSED'] {
    --ao-al-h-dot: var(--ao-ok);
}
/* The Active card's critical / warn / info split, coloured by severity
   (not by order, as the Team mix bar is). */
.ao-al-sevbar.ao-tm-stack {
    border-radius: var(--ao-r-bar);
    height: 8px;
    margin-top: auto;
}
.ao-al-sevbar .ao-tm-stack-seg[data-key='critical'] {
    background: var(--ao-err-strong);
}
.ao-al-sevbar .ao-tm-stack-seg[data-key='warn'] {
    background: var(--ao-warn);
}
.ao-al-sevbar .ao-tm-stack-seg[data-key='info'] {
    background: var(--ao-info);
}
/* The source filter leads the inbox (it was a row of chips under the last
   alert). The tray wraps rather than pushing a phone sideways. */
.ao-al-page .ao-al-srcbar {
    margin: 2px 0 0;
}
.ao-al-page .ao-al-srcbar .ao-seg-field {
    flex-wrap: wrap;
    max-width: 100%;
    min-width: 0;
}
.ao-al-page .ao-al-srcfilter {
    flex-wrap: wrap;
    max-width: 100%;
}
/* The maintenance banner: an info-tinted card over the KPI strip. */
.ao-al-page .ao-al-maint {
    background:
        radial-gradient(120% 120% at 0% 0%, var(--ao-info-bg), transparent 70%),
        linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-info-bd);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    margin: 0;
    padding: 14px 16px;
}
.ao-al-page .ao-al-maint-h {
    align-items: center;
    display: inline-flex;
    flex: none;
    gap: 8px;
    margin: 0;
}
/* The note rides the head line (title · note · SILENCE FLEET), so the banner
   is one line shorter above the KPI strip. */
.ao-al-page .ao-al-maint-head {
    justify-content: flex-start;
}
.ao-al-page .ao-al-maint-head > [data-role='silence-fleet'] {
    margin-left: auto;
}
.ao-al-page .ao-al-maint-row {
    align-items: center;
    border-top: 1px solid var(--ao-tint-line);
    margin-top: 10px;
    padding-top: 10px;
}
.ao-al-page .ao-al-maint-kind {
    background: var(--ao-info-bg);
    border-radius: var(--ao-r-tag);
}
.ao-al-page .ao-al-maint-scope {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    opacity: 1;
}
/* The reason gets the room; the meta (who, when it ends) is Inter and only
   as wide as its words, so "ends in 1h" never strands a word on a line. */
.ao-al-page .ao-al-maint-reason {
    flex: 1 1 320px;
    min-width: 0;
}
.ao-al-page .ao-al-maint-meta {
    color: var(--ao-fg-mute);
    flex: 0 1 auto;
    font-family: var(--ao-font-sans);
    opacity: 1;
}
.ao-al-page .ao-al-maint-note {
    color: var(--ao-fg-mute);
    flex: 1 1 260px;
    margin: 0;
    min-width: 0;
    opacity: 1;
}

/* ── Failure trends (the ALERTING tab's second panel) ── */
.ao-trends-panel {
    gap: 12px;
    margin-top: var(--ao-s-3);
}
.ao-trends-panel > .ao-sec-head {
    margin-bottom: 0;
}
/* The trends strip spans the row like every other strip (aoStat.row sets
   its columns from the card count): it used to hold each card to a sixth,
   leaving half the row blank beside three cards. */
.ao-tr-grid {
    display: grid;
    gap: 12px;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr));
}
.ao-tr-grid > .ao-empty,
.ao-tr-card-disp {
    grid-column: 1 / -1;
}
.ao-tr-card {
    min-width: 0;
}
.ao-tr-card .ao-table-wrap {
    margin: 0 -4px;
}
.ao-tr-orgtypes {
    align-items: center;
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 12px;
    padding-top: 12px;
}
.ao-tr-org-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-right: 2px;
}
.ao-tr-org {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    padding: 1px 9px;
}
/* One row per source: name over code | verdict bar + legend | rate pill. */
.ao-tr-dispositions {
    display: flex;
    flex-direction: column;
}
/* The rate column is a fixed width, so every row's bar is the same length
   (each row is its own grid; an auto column made them ragged). */
.ao-tr-disposition {
    align-items: center;
    border-top: 1px solid var(--ao-tint-line);
    display: grid;
    gap: 6px 18px;
    grid-template-columns: minmax(130px, 190px) minmax(0, 1fr) 150px;
    padding: 12px 2px;
}
.ao-tr-disposition > .ao-tr-disp-rate {
    justify-self: end;
}
.ao-tr-disposition:first-child {
    border-top: 0;
    padding-top: 2px;
}
.ao-tr-disp-src {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.ao-tr-disp-name {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    font-weight: 600;
}
.ao-tr-disp-code {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    overflow-wrap: anywhere;
}
.ao-tr-disp-mid {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}
.ao-tr-disp-bar.ao-tm-stack {
    height: 10px;
}
/* Coloured by verdict, not by order (aoStackBar's default): real is the
   one that matters, the three noise verdicts are the quiet hues. */
.ao-tr-disp-bar .ao-tm-stack-seg[data-key='real'],
.ao-tr-disp-bit.is-real::before {
    background: var(--ao-err-strong);
}
.ao-tr-disp-bar .ao-tm-stack-seg[data-key='self_healed'],
.ao-tr-disp-bit.is-self_healed::before {
    background: var(--ao-k-1);
}
.ao-tr-disp-bar .ao-tm-stack-seg[data-key='expected'],
.ao-tr-disp-bit.is-expected::before {
    background: var(--ao-k-5);
}
.ao-tr-disp-bar .ao-tm-stack-seg[data-key='flapping'],
.ao-tr-disp-bit.is-flapping::before {
    background: var(--ao-k-4);
}
.ao-tr-disp-bar .ao-tm-stack-seg[data-key='unknown'],
.ao-tr-disp-bit.is-unknown::before {
    background: var(--ao-fg-mute);
}
.ao-tr-disp-legend {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
}
.ao-tr-disp-bit {
    color: var(--ao-fg-dim);
    white-space: nowrap;
}
.ao-tr-disp-bit::before {
    border-radius: 2px;
    content: '';
    display: inline-block;
    height: 7px;
    margin-right: 5px;
    vertical-align: 1px;
    width: 7px;
}
.ao-tr-disp-rate {
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    padding: 2px 10px;
    white-space: nowrap;
}
.ao-tr-disp-rate.is-err {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-tr-disp-rate.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-tr-disp-rate.is-ok {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
@media (max-width: 760px) {
    /* TOP CAUSE is the first thing a phone loses (it was cut to "Agen"). */
    .ao-tr-tenants .ao-tr-table th:nth-child(3),
    .ao-tr-tenants .ao-tr-table td:nth-child(3) {
        display: none;
    }
    /* The long Disposition title wraps; the icon stays beside it and the
       sub-line goes under it (flex-wrap stacked the icon on top). */
    .ao-sec-head.ao-tr-disp-h {
        align-items: center;
        column-gap: 12px;
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
    }
    .ao-sec-head.ao-tr-disp-h > .ao-sec-sub {
        grid-column: 2;
    }
    .ao-tr-disposition {
        grid-template-columns: minmax(0, 1fr) auto;
    }
    .ao-tr-disposition > .ao-tr-disp-rate {
        justify-self: auto;
    }
    .ao-tr-disp-mid {
        grid-column: 1 / -1;
        grid-row: 2;
    }
    .ao-al-page .ao-al-row,
    .ao-tk-page .ao-al-row {
        padding: 12px 14px 12px 16px;
    }
    /* KPI strips on a phone: two even columns, and an odd last card takes
       the whole row instead of sitting half-width beside a hole. (div.: the
       design-system test reads the FIRST bare `.ao-stat-row {` rule.) */
    :is(.ao-al-page, .ao-tk-page, .ao-logs-page, .ao-dlq-page) div.ao-stat-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    :is(.ao-al-page, .ao-tk-page, .ao-logs-page, .ao-dlq-page) div.ao-stat-row > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
}

/* ── The desk modals (SILENCE, ASSIGN) ── body-appended, so unscoped. */
/* The console's type is set on #argus-ops-root, which a body-appended modal
   is outside of — so the modal names its own face (it rendered in the
   browser's serif default). */
.ao-al-modal {
    align-items: center;
    background: var(--ao-overlay);
    display: flex;
    font-family: var(--ao-font-sans);
    inset: 0;
    justify-content: center;
    padding: 24px;
    position: fixed;
    z-index: 99998;
}
.ao-al-modal-card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-3);
    color: var(--ao-fg-dim);
    box-sizing: border-box;
    font-size: var(--ao-fs-strong);
    max-width: 480px;
    padding: 22px;
    width: 100%;
}
.ao-al-modal-head {
    align-items: center;
    display: flex;
    gap: 10px;
    margin-bottom: 12px;
}
.ao-al-modal-ico {
    background: var(--ao-info-bg);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px var(--ao-info-bd);
    color: var(--ao-info-fg);
    display: grid;
    flex: none;
    height: 30px;
    place-items: center;
    width: 30px;
}
.ao-al-modal-card.is-fleet .ao-al-modal-ico {
    background: var(--ao-err-bg);
    box-shadow: inset 0 0 0 1px var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-al-modal-h {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    font-weight: 600;
    margin: 0;
}
.ao-al-modal-why {
    color: var(--ao-fg-mute);
    line-height: 1.5;
    margin-bottom: 14px;
}
.ao-al-modal-scope {
    background: var(--ao-tint);
    border: 1px solid var(--ao-tint-line);
    border-radius: var(--ao-r-ctl);
    font-size: var(--ao-fs-body);
    margin-bottom: 12px;
    padding: 8px 10px;
}
.ao-al-modal-scope-k {
    color: var(--ao-fg-mute);
}
.ao-al-modal-scope-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
}
.ao-al-modal-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    margin-top: 16px;
}
/* The pickers and inputs (label() / selectInput() / textInput()) as a
   stacked form: a small caps caption over a full-width control. */
.ao-al-modal-card .ao-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 12px;
}
.ao-al-modal-card .ao-field-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-al-modal-card .ao-tselect {
    display: block;
}
.ao-al-modal-card .ao-tselect-trigger,
.ao-al-modal-card .ao-input {
    border-radius: var(--ao-r-ctl);
    box-sizing: border-box;
    min-height: 32px;
    padding: 6px 10px;
    width: 100%;
}

/* ── TICKETS tab (#/tickets, #/tickets/<id>) — design system v2 ────────────
   Rides the .ao-al-* row (above) inside .ao-tk-page; this block is what is
   ticket-only: the owner disc, the guard line (it was inline hex), the
   GUARD DID NOT HOLD band, the ratio meter, and the detail page's evidence
   card and narrative timeline. Tokens only. */
/* A receipt's status badge is neutral: the origin severity's colour belongs
   to work still open. */
.ao-tk-page .ao-al-row[data-status='closed'] > .ao-al-top > .ao-al-badge,
.ao-tk-page .ao-al-row[data-status='wont_fix'] > .ao-al-top > .ao-al-badge,
.ao-tk-page .ao-al-row[data-status='duplicate'] > .ao-al-top > .ao-al-badge {
    background: var(--ao-tint-2);
    border-color: var(--ao-border);
    color: var(--ao-fg-dim);
}
/* The status pill by STATUS (the JS appends .ao-tk-st.is-<status> after the
   legacy severity classes); the row's rail keeps the origin severity. The
   hues match the KPI cards above: open blue, investigating violet, blocked
   amber, fixed green, closed neutral. */
.ao-tk-page .ao-al-badge.ao-tk-st.is-open {
    background: var(--ao-info-bg);
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-tk-page .ao-al-badge.ao-tk-st.is-investigating {
    background: color-mix(in srgb, var(--ao-k-2) 14%, transparent);
    border-color: color-mix(in srgb, var(--ao-k-2) 45%, transparent);
    color: var(--ao-k-2);
}
.ao-tk-page .ao-al-badge.ao-tk-st.is-blocked {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-tk-page .ao-al-badge.ao-tk-st.is-fixed {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-tk-page .ao-al-badge.ao-tk-st:is(.is-closed, .is-wont_fix, .is-duplicate) {
    background: var(--ao-tint-2);
    border-color: var(--ao-border);
    color: var(--ao-fg-dim);
}
/* "OWNED BY diego.alvarez@example.com (2)": the literal is already upper
   case where it should be; the address is not shouted. */
.ao-tk-page .ao-al-h[data-section^='OWNED BY'] {
    text-transform: none;
}
/* The source chip holds its label and the dedup key on ONE line, cutting
   the key with an ellipsis (the whole key is in the title). */
.ao-tk-page .ao-al-src[data-role='source'] {
    flex-wrap: nowrap;
    gap: 0;
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
}
.ao-tk-src-lab {
    flex: none;
}
.ao-tk-src-key {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: pre;
}
/* Under "OWNED BY x" the heading names the owner; the row does not repeat
   it (the node stays, hidden, for copy and the tests). */
.ao-tk-page .ao-al-row.is-owner-grouped .ao-tk-owner {
    display: none;
}
/* The queue's section head leads the page like Alerting's inbox head. */
.ao-tk-panel > .ao-tk-queue-h {
    margin-bottom: 2px;
}
.ao-tk-page .ao-tk-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-top: -4px;
}
.ao-tk-owner {
    align-items: center;
    display: inline-flex;
    gap: 6px;
}
.ao-tk-page .ao-tk-owner.is-unowned .ao-al-src {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-tk-page .ao-tk-pri.is-urgent {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-tk-page .ao-tk-pri.is-high {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-tk-page .ao-tk-callout {
    background: var(--ao-tint);
    border: 1px solid var(--ao-tint-line);
    border-radius: 10px;
    padding: 7px 10px;
}
.ao-tk-page .ao-tk-callout.is-blocked {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
}
.ao-tk-guard {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-tint-line);
    border-radius: 10px;
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 8px;
    margin-top: 2px;
    padding: 8px 10px;
}
.ao-tk-guard-badge.is-waived {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-tk-guard-badge.is-verified {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-tk-guard-badge.is-named {
    background: transparent;
    border-color: var(--ao-border);
    border-style: dashed;
    color: var(--ao-fg-dim);
}
/* VERBATIM: wraps anywhere, never truncates. */
.ao-tk-guard-ref {
    background: var(--ao-tint-2);
    border-radius: 6px;
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    padding: 1px 6px;
    word-break: break-all;
}
.ao-tk-guard-shape {
    color: var(--ao-fg-mute);
}
.ao-tk-guard-how {
    color: var(--ao-fg-dim);
}
.ao-tk-guard-waiver {
    color: var(--ao-fg-dim);
    flex-basis: 100%;
}
.ao-tk-page .ao-al-row.ao-tk-band {
    border-color: var(--ao-err-bd);
}
/* Inside GUARD DID NOT HOLD a green "verified" would contradict the band:
   the guard exists, and it failed. Amber there. */
.ao-tk-band .ao-tk-guard-badge.is-verified {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-tk-band > .ao-al-title {
    align-items: center;
    color: var(--ao-err-fg);
    display: flex;
    gap: 8px;
    letter-spacing: 0.04em;
}
.ao-tk-band-line {
    font-weight: 500;
}
/* The Verified-guards card's n / of meter; hatched when nothing is closed. */
.ao-tk-meter {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: block;
    height: 4px;
    margin-top: 4px;
    overflow: hidden;
    position: relative;
}
.ao-tk-meter-fill {
    background: var(--ao-stat-accent, var(--ao-ok));
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform var(--ao-slow) var(--ao-ease);
}
.ao-tk-meter.is-unmeasured {
    background: repeating-linear-gradient(135deg, var(--ao-tint-2) 0 4px, transparent 4px 8px);
}
/* ── ticket detail ── */
.ao-tk-back {
    align-self: flex-start;
}
.ao-tk-page .ao-al-row.ao-tk-hero {
    padding: 18px 20px 16px 24px;
}
.ao-tk-page .ao-tk-hero > .ao-al-title {
    font-size: var(--ao-fs-h2);
    letter-spacing: -0.01em;
}
.ao-tk-links {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px 12px;
}
.ao-tk-links .ao-al-actions {
    border: 0;
    margin: 0;
    padding: 0;
}
.ao-tk-fix {
    max-width: 100%;
    overflow-wrap: anywhere;
}
/* The source alert's live status: a chip on the hero's chip line that
   links to the inbox (warn while the alert is live, ok once resolved). */
.ao-tk-page a.ao-tk-linked {
    text-decoration: none;
    text-transform: uppercase;
    transition:
        border-color var(--ao-fast) var(--ao-ease),
        background-color var(--ao-fast) var(--ao-ease);
}
.ao-tk-page a.ao-tk-linked:hover {
    border-color: currentColor;
}
.ao-tk-page a.ao-tk-linked:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-tk-page .ao-tk-linked.is-resolved {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-tk-page .ao-tk-linked.is-open,
.ao-tk-page .ao-tk-linked.is-acked {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-tk-detail-grid {
    align-items: start;
    display: grid;
    gap: 12px;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
}
.ao-tk-card {
    min-width: 0;
}
/* Evidence as key / value rows; the ': ' separator is kept as text (a copy
   still reads "key: value") but not painted. */
.ao-tk-kv {
    display: flex;
    flex-direction: column;
}
.ao-tk-page .ao-tk-kv-row {
    border-top: 1px solid var(--ao-tint-line);
    display: grid;
    gap: 12px;
    grid-template-columns: minmax(110px, 38%) minmax(0, 1fr);
    padding: 8px 0;
}
.ao-tk-page .ao-tk-kv-row:first-child {
    border-top: 0;
}
.ao-tk-kv-k {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    overflow-wrap: anywhere;
}
.ao-tk-kv-sep {
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}
.ao-tk-kv-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    overflow-wrap: anywhere;
}
/* Support cases on tickets: the case chip, the state pill, the email thread
   and the composer. Tokens only. */
.ao-tk-case {
    font-family: var(--ao-mono);
    font-weight: 600;
}
/* An internal record's id (INT-): staff only, set apart from a customer
   case code by a dashed outline, not a new colour. */
.ao-tk-case.is-internal {
    border-style: dashed;
}
.ao-tk-kind {
    font-weight: 600;
    letter-spacing: 0.04em;
}
.ao-tk-kind-filter {
    margin: 8px 0 4px;
}
.ao-state-pill.ao-tk-case-state.is-closed {
    background: var(--ao-tint);
    border-color: var(--ao-border);
    color: var(--ao-fg-dim);
}
.ao-tk-convo {
    margin-top: 12px;
}
.ao-tk-msgs {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.ao-tk-msg {
    background: var(--ao-surface-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    padding: var(--ao-s-3);
}
.ao-tk-msg.is-out {
    background: var(--ao-surface);
    border-color: var(--ao-border);
    margin-left: 24px;
}
.ao-tk-msg.is-in {
    margin-right: 24px;
}
.ao-tk-msg.is-failed {
    border-color: var(--ao-err-border-strong);
}
.ao-tk-msg-head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.ao-tk-msg-from {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-tk-msg-head .ao-al-age {
    margin-left: auto;
}
.ao-tk-msg-subj {
    color: var(--ao-fg);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    margin-top: 6px;
    overflow-wrap: anywhere;
}
.ao-tk-msg-body {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    line-height: 1.55;
    margin-top: 6px;
    max-height: 420px;
    overflow: auto;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}
.ao-tk-compose {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 12px;
}
.ao-tk-compose-body {
    min-height: 110px;
    resize: vertical;
    width: 100%;
}
.ao-tk-compose-subj {
    width: 100%;
}
@media (max-width: 640px) {
    .ao-tk-msg.is-out {
        margin-left: 8px;
    }
    .ao-tk-msg.is-in {
        margin-right: 8px;
    }
}
.ao-tk-limits {
    background: var(--ao-warn-bg);
    border: 1px solid var(--ao-warn-bd);
    border-radius: 12px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 12px;
    padding: 10px 12px;
}
.ao-tk-page .ao-tk-limits > .ao-al-title {
    align-items: center;
    color: var(--ao-warn-fg);
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: 7px;
    letter-spacing: 0.08em;
}
/* The narrative: a vertical rail with a dot per event. */
.ao-tk-tl {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-left: 22px;
    position: relative;
}
.ao-tk-tl::before {
    background: var(--ao-tint-line);
    bottom: 12px;
    content: '';
    left: 7px;
    position: absolute;
    top: 12px;
    width: 1px;
}
.ao-tk-page .ao-al-row.ao-tk-event {
    --ao-al-sev: var(--ao-fg-mute);
    background: var(--ao-tint);
    border-color: var(--ao-tint-line);
    border-radius: 12px;
    box-shadow: none;
    overflow: visible;
    padding: 10px 12px;
}
.ao-tk-page .ao-al-row.ao-tk-event::before {
    border-radius: 50%;
    bottom: auto;
    box-shadow: 0 0 0 3px var(--ao-surface);
    height: 9px;
    left: -19px;
    top: 15px;
    width: 9px;
}
.ao-tk-page .ao-tk-event.is-created {
    --ao-al-sev: var(--ao-info);
}
.ao-tk-page .ao-tk-event.is-claimed {
    --ao-al-sev: var(--ao-k-2);
}
.ao-tk-page .ao-tk-event.is-fixed,
.ao-tk-page .ao-tk-event.is-closed {
    --ao-al-sev: var(--ao-ok);
}
.ao-tk-page .ao-tk-event.is-reopened,
.ao-tk-page .ao-tk-event.is-blocked {
    --ao-al-sev: var(--ao-err-strong);
}
@media (max-width: 760px) {
    /* A phone shows the source's name only; the key is in the title. */
    .ao-tk-page .ao-tk-src-key {
        display: none;
    }
    /* "updated 2d ago" stays on the chip line, after the last chip. */
    .ao-tk-page .ao-al-top > .ao-al-age {
        margin-left: 0;
    }
}
@media (max-width: 480px) {
    /* The key over its value, so "cpu_pct_before_drop" never breaks. */
    .ao-tk-page .ao-tk-kv-row {
        gap: 2px;
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ── LOGS (#/logs) — design system v2 ──────────────────────────────────────
   The remote-support audit: a KPI strip, the feed on aoTable (a card), and
   the external sources card. Tokens only. */
.ao-logs-panel,
.ao-dlq-panel {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
}
.ao-logs-panel > .ao-sec-head,
.ao-dlq-panel > .ao-sec-head {
    margin: 6px 0 0;
}
/* No tenant: the empty panel lines up with the heading and the card below
   (.ao-empty carries a 16px margin of its own). */
.ao-logs-panel > .ao-empty {
    margin: 0;
}
/* The v2 empty state: an icon tile, one line, and the way out. */
.ao-logs-pick {
    align-items: center;
    border-radius: var(--ao-r-xl);
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 32px 20px;
}
.ao-logs-pick-ico {
    align-items: center;
    background: color-mix(in srgb, var(--ao-k-5) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--ao-k-5) 40%, transparent);
    border-radius: 12px;
    color: var(--ao-k-5);
    display: inline-flex;
    height: 40px;
    justify-content: center;
    width: 40px;
}
.ao-logs-pick-text {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.55;
    margin: 0;
    max-width: 64ch;
}
a.ao-logs-pick-btn {
    text-decoration: none;
}
/* A fixed layout: the columns hold their place when the filter changes
   (EVENT moved 25px and AGENT 38px switching to FAILED). TIME, EVENT, AGENT
   and COMMAND are pinned; OPERATOR and RESULT share the rest. Below this
   floor the card scrolls sideways instead of crushing the prose. */
table.ao-logs-table {
    min-width: 920px;
    table-layout: fixed;
}
.ao-logs-table th:nth-child(1) {
    width: 158px;
}
.ao-logs-table th:nth-child(2) {
    width: 250px;
}
.ao-logs-table th:nth-child(4) {
    width: 150px;
}
.ao-logs-table th:nth-child(5) {
    width: 132px;
}
.ao-logs-table .ao-logs-op-email {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-logs-table .ao-logs-op {
    max-width: 100%;
}
.ao-logs-table .ao-logs-evcell {
    max-width: 100%;
}
.ao-logs-table .ao-logs-ev-raw {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* The result under the event is the phone's copy of RESULT (hidden here). */
.ao-logs-ev-result {
    display: none;
}
.ao-logs-when {
    display: flex;
    flex-direction: column;
    gap: 1px;
    white-space: nowrap;
}
.ao-logs-when-abs {
    color: var(--ao-fg);
}
.ao-logs-when-rel {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}
/* The event: a readable pill ("View camera · dispatched") over the raw
   event_type in small mono (the name a log search needs). */
.ao-logs-evcell {
    align-items: flex-start;
    display: inline-flex;
    flex-direction: column;
    gap: 3px;
}
.ao-state-pill.ao-logs-ev {
    font-size: var(--ao-fs-meta);
    letter-spacing: 0;
    text-transform: none;
}
.ao-logs-ev-raw {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    padding-left: 2px;
}
/* An agent with no name: its id, cut to about eight characters on screen.
   The text is the WHOLE id (select-to-copy and a search still get it all),
   and aoIdentity puts it in the title too. */
.ao-logs-table .ao-identity-agent .ao-identity-name.is-unresolved {
    display: block;
    max-width: 10ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-state-pill.ao-logs-ev.is-neutral {
    background: var(--ao-tint-2);
    border-color: var(--ao-border-soft);
    border-style: solid;
    color: var(--ao-fg-dim);
}
.ao-logs-op {
    align-items: center;
    display: inline-flex;
    gap: 8px;
    white-space: nowrap;
}
.ao-logs-result {
    color: var(--ao-fg-dim);
}
/* The result is prose ("probe_rtsp: 3 of 3 streams answered"): it wraps
   rather than pushing the table past its card. */
.ao-logs-table td:last-child {
    white-space: normal;
}
.ao-logs-result.is-err {
    color: var(--ao-err-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-logs-table tr.is-err > td:first-child,
.ao-dlq tr.is-abandoned > td:first-child {
    box-shadow: inset 2px 0 0 var(--ao-err-strong);
}
.ao-logs-table tr.is-warn > td:first-child,
.ao-dlq tr.is-pending > td:first-child {
    box-shadow: inset 2px 0 0 var(--ao-warn);
}
.ao-logs-ext-body {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 14px 24px;
    justify-content: space-between;
}
.ao-logs-ext-text {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.7;
    margin: 0;
    max-width: 72ch;
}
.ao-logs-code {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: 6px;
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    padding: 1px 6px;
}
.ao-logs-ext-links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
a.ao-logs-ext-link {
    text-decoration: none;
}
@media (max-width: 760px) {
    /* A phone keeps TIME and EVENT: OPERATOR, AGENT, COMMAND and RESULT go,
       the time drops its date (the relative line says the day), and the
       result rides under the event pill in place of the raw event name, so
       an ERR code is on screen without a sideways swipe. */
    table.ao-logs-table {
        min-width: 0;
    }
    .ao-logs-table th:nth-child(3),
    .ao-logs-table td:nth-child(3),
    .ao-logs-table th:nth-child(4),
    .ao-logs-table td:nth-child(4),
    .ao-logs-table th:nth-child(5),
    .ao-logs-table td:nth-child(5),
    .ao-logs-table th:last-child,
    .ao-logs-table td:last-child,
    .ao-logs-when-date,
    .ao-logs-ev-raw {
        display: none;
    }
    .ao-logs-table th:nth-child(1) {
        width: 92px;
    }
    .ao-logs-table th:nth-child(2) {
        width: auto;
    }
    .ao-logs-table td:nth-child(2) {
        white-space: normal;
    }
    .ao-logs-ev-result {
        display: block;
        font-size: var(--ao-fs-meta);
        line-height: 1.45;
        padding-left: 2px;
    }
}

/* ── WEBHOOK DLQ (#/dlq) — design system v2 ────────────────────────────────
   KPI strip, a status pill per row, host + path targets, status-code pills,
   RETRY as an icon pill that spins while busy. Tokens only. */
.ao-dlq-admin {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 5px;
    letter-spacing: 0.1em;
    padding: 3px 10px;
}
.ao-dlq-target {
    display: flex;
    flex-direction: column;
    gap: 1px;
    max-width: 210px;
    min-width: 0;
}
.ao-dlq-host {
    color: var(--ao-fg);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-dlq-path {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The phone's second TARGET line (status code · next retry · error). */
.ao-dlq-phone {
    display: none;
}
/* The host / path wrap points are for a phone only: Chrome honours a <wbr>
   even under nowrap, which split "example.com" on a wide screen. */
.ao-dlq-target wbr {
    display: none;
}
.ao-dlq-code {
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    padding: 1px 8px;
    white-space: nowrap;
}
.ao-dlq-code.is-err {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-dlq-code.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-dlq-code.is-ok {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-dlq-code.is-none {
    border-style: dashed;
    color: var(--ao-fg-mute);
}
.ao-dlq-next {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    white-space: nowrap;
}
.ao-dlq-muted {
    color: var(--ao-fg-mute);
}
/* Two lines at most (the whole message rides in the title), so the row's
   RETRY stays on screen at 1440 without a sideways scroll. */
.ao-dlq-err {
    -webkit-box-orient: vertical;
    color: var(--ao-fg-dim);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    max-width: 190px;
    min-width: 130px;
    overflow: hidden;
    white-space: normal;
}
.ao-dlq-key {
    color: var(--ao-fg-dim);
    white-space: nowrap;
}
/* The action column is pinned to the right edge, so RETRY stays on screen
   while a phone scrolls the table sideways. Opaque, or the rows would show
   through it. */
.ao-dlq th:last-child,
.ao-dlq td:last-child {
    background: var(--ao-surface-2);
    box-shadow: inset 1px 0 0 var(--ao-tint-line);
    position: sticky;
    right: 0;
}
.ao-dlq th:last-child {
    z-index: 2;
}
.ao-dlq-retry.is-busy .ao-ico {
    animation: ao-dlq-spin 900ms linear infinite;
}
@media (max-width: 760px) {
    /* A phone keeps STATUS, TARGET and the action, so the table fits the
       screen and the pinned RETRY covers nothing. ID and IDEM KEY go (opaque
       keys nobody reads on a phone); ATTEMPTS through ERROR move into the
       target's second line (status code, next retry or parked, the error). */
    .ao-dlq th:nth-child(2),
    .ao-dlq td:nth-child(2),
    .ao-dlq th:nth-child(3),
    .ao-dlq td:nth-child(3),
    .ao-dlq th:nth-child(n + 5):nth-child(-n + 9),
    .ao-dlq td:nth-child(n + 5):nth-child(-n + 9) {
        display: none;
    }
    .ao-dlq td:nth-child(4) {
        white-space: normal;
        width: 100%;
    }
    .ao-dlq-target {
        max-width: none;
    }
    .ao-dlq-target wbr {
        display: inline;
    }
    .ao-dlq-host,
    .ao-dlq-path {
        overflow-wrap: break-word;
        white-space: normal;
    }
    .ao-dlq-phone {
        align-items: center;
        display: flex;
        flex-wrap: wrap;
        gap: 4px 8px;
        margin-top: 4px;
    }
    .ao-dlq-phone-next {
        color: var(--ao-fg-dim);
        font-family: var(--ao-mono);
        font-size: var(--ao-fs-label);
        white-space: nowrap;
    }
    .ao-dlq-phone-err {
        color: var(--ao-fg-dim);
        flex-basis: 100%;
        font-size: var(--ao-fs-meta);
        line-height: 1.45;
        overflow-wrap: anywhere;
    }
}
/* Transform-only: nothing here can leave the button invisible. */
@keyframes ao-dlq-spin {
    to {
        transform: rotate(360deg);
    }
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-dlq-retry.is-busy .ao-ico,
    :where(html:not([data-motion='full'])) .ao-al-page .ao-al-logs-sum::after {
        animation: none;
        transition: none;
    }
}

/* ── ROLLOUTS — active ring ladder + health gate (rehaul 2026-09-23) ──────────
 * The active rollout is a KPI strip (ring, cohort, bake, failure rate — each
 * against its gate) over a hero card: version + state + the legal controls,
 * then the ring ladder as a stepper (canary → fleet) and the ring-scoped
 * health gate. Nodes read done / active / pending off [data-state]
 * (rolloutInto in argus-ops.js). */
.ao-ro-sec {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-ro-hero {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
.ao-ro-hero.is-idle {
    align-items: flex-start;
}
.ao-rollout-empty {
    align-items: center;
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-strong);
    gap: 10px;
}
.ao-rollout-empty .ao-ico {
    color: var(--ao-fg-mute);
}
.ao-rollout-head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3);
    justify-content: space-between;
}
.ao-ro-id {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 12px;
    min-width: 0;
}
.ao-rollout-version {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-h2);
    font-weight: 600;
    letter-spacing: -0.02em;
}
/* The rollout state pill — the header badge and the RECENT table's STATE. */
.ao-rollout-state {
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-block;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.06em;
    line-height: 1.6;
    padding: 1px 9px;
    text-transform: uppercase;
    white-space: nowrap;
}
.ao-rollout-state[data-state='active'] {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-rollout-state[data-state='paused'] {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-rollout-state[data-state='halted'] {
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-strong);
}
.ao-rollout-state[data-state='completed'] {
    background: var(--ao-info-soft);
    border-color: var(--ao-info-border);
    color: var(--ao-info);
}
.ao-rollout-meta {
    color: var(--ao-fg-mute);
    flex-basis: 100%;
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
}
/* The ladder: numbered steps joined by rails; the rail up to the current ring
 * is filled, the current ring is the lit node. */
.ao-ladder {
    align-items: center;
    display: flex;
    gap: 0;
    overflow-x: auto;
    padding: 4px 2px 6px;
    scrollbar-width: thin;
}
.ao-ladder-node {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    display: inline-flex;
    flex: none;
    gap: 10px;
    padding: 8px 14px 8px 8px;
}
.ao-ladder-step {
    background: var(--ao-surface-2);
    border: 1px solid var(--ao-border);
    border-radius: 50%;
    color: var(--ao-fg-mute);
    display: grid;
    flex: none;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    height: 26px;
    place-items: center;
    width: 26px;
}
.ao-ladder-txt {
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.ao-ladder-node .ao-ladder-name {
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.ao-ladder-node .ao-ladder-pct {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-variant-numeric: tabular-nums;
}
.ao-ladder-node[data-state='done'] {
    color: var(--ao-ok-text);
}
.ao-ladder-node[data-state='done'] .ao-ladder-step {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
/* The current ring is the KPI teal, not the brand rose: rose beside the red
 * HALT read as an error. */
.ao-ladder-node[data-state='active'] {
    background: color-mix(in srgb, var(--ao-k-1) 12%, var(--ao-surface-2));
    border-color: color-mix(in srgb, var(--ao-k-1) 70%, transparent);
    box-shadow:
        0 0 0 3px color-mix(in srgb, var(--ao-k-1) 16%, transparent),
        var(--ao-elev-1);
    color: var(--ao-fg);
}
.ao-ladder-node[data-state='active'] .ao-ladder-step {
    background: var(--ao-k-1);
    border-color: var(--ao-k-1);
    color: var(--ao-bg);
}
.ao-ladder-node[data-state='active'] .ao-ladder-pct {
    color: var(--ao-fg-dim);
}
.ao-ladder-node[data-state='pending'] {
    color: var(--ao-fg-mute);
}
/* The rails share the card's width, so the stepper spans it end to end. */
.ao-ladder-conn {
    background: var(--ao-border);
    border-radius: var(--ao-r-tag);
    flex: 1 1 28px;
    height: 2px;
    min-width: 20px;
}
.ao-ladder-conn[data-state='done'] {
    background: linear-gradient(90deg, var(--ao-ok-border), var(--ao-k-1));
}
/* A phone stacks the steps, joined by a short vertical rail under each
 * step's number, so BROAD and FLEET never scroll out of view. */
@media (max-width: 760px) {
    .ao-ladder {
        align-items: stretch;
        flex-direction: column;
        overflow-x: visible;
    }
    .ao-ladder-node {
        align-self: flex-start;
        box-sizing: border-box;
        min-width: 168px;
    }
    .ao-ladder-conn {
        flex: none;
        height: 12px;
        margin-left: 20px;
        min-width: 0;
        width: 2px;
    }
    .ao-ladder-conn[data-state='done'] {
        background: linear-gradient(180deg, var(--ao-ok-border), var(--ao-k-1));
    }
}
.ao-ladder-unavailable {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
}
/* The ring's health gate: the verdict pill, then one check / cross row per
 * gate (the reading against its threshold); the reasons are on the pill's
 * hover. */
.ao-ring-health {
    align-items: flex-start;
    background: var(--ao-tint);
    border: 1px solid var(--ao-tint-line);
    border-radius: var(--ao-r-lg);
    color: var(--ao-fg-dim);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    gap: 10px 18px;
    padding: 12px 14px;
}
.ao-ring-checks {
    display: flex;
    flex: 1 1 260px;
    flex-direction: column;
    gap: 6px;
    list-style: none;
    margin: 0;
    min-width: 0;
    padding: 0;
}
.ao-ring-check {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 4px 10px;
}
.ao-ring-check-ico {
    border-radius: var(--ao-r-tag);
    display: grid;
    flex: none;
    height: 18px;
    place-items: center;
    width: 18px;
}
.ao-ring-check[data-state='ok'] .ao-ring-check-ico {
    background: var(--ao-ok-soft);
    box-shadow: inset 0 0 0 1px var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-ring-check[data-state='fail'] .ao-ring-check-ico {
    background: var(--ao-warn-bg);
    box-shadow: inset 0 0 0 1px var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-ring-check[data-state='unknown'] .ao-ring-check-ico {
    background: var(--ao-tint-2);
    color: var(--ao-fg-mute);
}
.ao-ring-check-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-body);
    min-width: 11ch;
}
.ao-ring-check-gate {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}
.ao-rollout-controls {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
/* A KPI card's progress toward its gate (cohort, bake). */
.ao-ro-meter {
    align-items: center;
    display: flex;
    gap: 8px;
}
.ao-ro-meter-track {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    flex: 1 1 auto;
    height: 4px;
    max-width: 120px;
    overflow: hidden;
}
.ao-ro-meter-fill {
    background: var(--ao-warn-border);
    border-radius: inherit;
    display: block;
    height: 100%;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
}
.ao-ro-meter.is-met .ao-ro-meter-fill {
    background: var(--ao-ok);
}
/* Failure rate fills toward HALT: green at or under the gate, amber past it,
 * red at halt (_roFailMeter). */
.ao-ro-meter.is-rev.is-ok .ao-ro-meter-fill {
    background: var(--ao-ok);
}
.ao-ro-meter.is-rev.is-warn .ao-ro-meter-fill {
    background: var(--ao-warn);
}
.ao-ro-meter.is-rev.is-err .ao-ro-meter-fill {
    background: var(--ao-err-strong);
}
.ao-ro-meter-t {
    flex: none;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}

/* VERSIONS catalog (read-only): a wrapping changelog cell so the free-text
   notes ("what's different / capabilities") stay readable rather than being
   ellipsis-truncated like the default nowrap .ao-table cells. */
.ao-vcat-section,
.ao-dist-section {
    margin-top: var(--ao-s-3);
    min-width: 0;
}
.ao-table.ao-vcat td.ao-vcat-changelog {
    color: var(--ao-fg-dim);
    max-width: 420px;
    min-width: 220px;
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
}
/* Every version cell on the tab (recent, versions, distribution) is the
 * same semibold mono. */
.ao-table td.ao-ro-ver {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-table td.ao-ro-ver .ao-agr-2l-sub {
    font-weight: 400;
}
@media (max-width: 760px) {
    /* Recent: STARTED / BY ride under the version, the operator's address
     * free to break so the RING column stays on screen. */
    .ao-table.ao-ro-recent td.ao-ro-ver {
        white-space: normal;
    }
    .ao-table.ao-ro-recent td.ao-ro-ver .ao-agr-2l-sub {
        overflow-wrap: anywhere;
    }
    /* Versions: the rename action is its pencil alone. */
    .ao-table.ao-vcat .ao-vcat-setname .ao-btn-label {
        display: none;
    }
    .ao-table.ao-vcat th,
    .ao-table.ao-vcat td {
        padding-left: 6px;
        padding-right: 6px;
    }
    /* The changelog under the version: up to three lines, the rest on hover. */
    .ao-table.ao-vcat td.ao-vcat-version {
        min-width: 104px;
        white-space: normal;
    }
    .ao-table.ao-vcat td.ao-vcat-version .ao-agr-2l-sub {
        -webkit-box-orient: vertical;
        display: -webkit-box;
        -webkit-line-clamp: 3;
        line-clamp: 3;
        overflow: hidden;
    }
    .ao-table.ao-dist td.ao-dist-share {
        min-width: 96px;
    }
}

/* VERSIONS catalog — inline "name this version" action beside the codename:
 * a ghost pill that comes up to full strength on row hover or focus. */
.ao-table.ao-vcat td.ao-vcat-codename {
    white-space: nowrap;
}
.ao-vcat-cn {
    align-items: center;
    display: inline-flex;
    gap: 6px;
}
.ao-vcat-setname {
    opacity: 0.55;
}
.ao-table.ao-vcat tr:hover .ao-vcat-setname,
.ao-vcat-setname:focus-visible {
    opacity: 1;
}
.ao-rel-sha {
    color: var(--ao-fg-dim);
}

/* FLEET DISTRIBUTION — the SHARE column is an aoTable magnitude bar; a
 * version shedding agents in 24h wears the err colour. */
.ao-table.ao-dist td.ao-dist-share {
    min-width: 160px;
}
.ao-dist-failed.is-err {
    color: var(--ao-err-strong);
    font-weight: 600;
}
.ao-dist-sharebox {
    align-items: baseline;
    display: inline-flex;
    gap: 8px;
}
.ao-dist-sharebox > .ao-dist-failed {
    font-family: var(--ao-font-sans);
    font-size: var(--ao-fs-label);
}
/* Each version keeps the hue Releases' "Fleet versions" bar gives it
 * (_agrVerHues): a swatch before the version, and its share bar. */
.ao-table.ao-dist td.ao-dist-ver::before {
    background: var(--ao-dist-hue, var(--ao-k-5));
    border-radius: 3px;
    content: '';
    display: inline-block;
    height: 9px;
    margin-right: 9px;
    width: 9px;
}
/* span. prefix: the design-system test reads the first rule whose selector
 * ends in " .ao-table-bar-fill" as the primitive's own rule. */
.ao-table.ao-dist tr[data-hue] span.ao-table-bar-fill {
    background: var(--ao-dist-hue, var(--ao-k-5));
}
.ao-table.ao-dist tr[data-hue='k1'] {
    --ao-dist-hue: var(--ao-k-1);
}
.ao-table.ao-dist tr[data-hue='k2'] {
    --ao-dist-hue: var(--ao-k-2);
}
.ao-table.ao-dist tr[data-hue='k3'] {
    --ao-dist-hue: var(--ao-k-3);
}
.ao-table.ao-dist tr[data-hue='k4'] {
    --ao-dist-hue: var(--ao-k-4);
}
.ao-table.ao-dist tr[data-hue='k5'] {
    --ao-dist-hue: var(--ao-k-5);
}
.ao-table.ao-dist tr[data-hue='k6'] {
    --ao-dist-hue: var(--ao-k-6);
}

/* The step-up dialogs (rollout actions, codename, release promote /
 * rollback, revoke) built by _agrModal: the chrome that was 12 inline
 * cssText writes per builder. They attach to <body>, outside
 * #argus-ops-root, so nothing here is scoped under it. */
.ao-agr-modal-overlay {
    align-items: center;
    background: var(--ao-overlay);
    display: flex;
    inset: 0;
    justify-content: center;
    padding: 24px;
    position: fixed;
    z-index: 99998;
}
.ao-arm-modal-card.ao-agr-modal {
    background: var(--ao-surface-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-sizing: border-box;
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-strong);
    max-height: calc(100vh - 48px);
    max-width: 520px;
    overflow-y: auto;
    padding: 22px;
    width: 100%;
}
.ao-arm-modal-card.ao-agr-modal.is-narrow {
    max-width: 480px;
}
.ao-agr-modal-h {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    margin: 0 0 10px;
}
.ao-agr-modal-desc {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.45;
    margin-bottom: 10px;
}
.ao-agr-modal-desc.is-warn {
    color: var(--ao-warn-text);
}
.ao-agr-modal-desc:empty {
    display: none;
}
.ao-agr-modal-err {
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-body);
    margin-top: 6px;
    min-height: 16px;
}
/* The DOM keeps [SUBMIT][CANCEL]; the row reads [CANCEL][SUBMIT] at the
 * right edge, as the incubator REMOVE confirm does. */
.ao-agr-modal-acts {
    display: flex;
    flex-direction: row-reverse;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: flex-start;
    margin-top: 12px;
}

/* The rollout modal's FORCE / ROLLBACK checkboxes, themed in the console
 * gold (the field spacing is the shared .ao-arm-modal-card rule). */
.ao-agr-modal > .ao-field.ao-agr-check {
    align-items: center;
    color: var(--ao-fg-dim);
    cursor: pointer;
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 9px;
}
.ao-agr-check input[type='checkbox'] {
    accent-color: var(--ao-cta);
    cursor: pointer;
    flex: none;
    height: 16px;
    margin: 0;
    width: 16px;
}
.ao-agr-check input[type='checkbox']:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}

/* ── RELEASES (#/releases) — rehaul 2026-09-23 ───────────────────────────────
 * OTA HEALTH as a KPI strip + two cards (fleet versions as one split bar,
 * recent hotfixes as a table), then the keyed releases table in a card. */
.ao-rel-sec,
.ao-rel-ota {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-rel-ota > .ao-sec-head,
.ao-rel-sec > .ao-sec-head {
    margin-bottom: 0;
}
.ao-rel-sec + .ao-rel-sec {
    margin-top: var(--ao-s-3);
}
.ao-rel-notes {
    background: var(--ao-warn-bg);
    border: 1px solid var(--ao-warn-bd);
    border-radius: var(--ao-r-lg);
    box-shadow: inset 3px 0 0 var(--ao-warn-border);
    color: var(--ao-warn-text);
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 10px 14px;
}
.ao-rel-note {
    align-items: center;
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 8px;
}
.ao-rel-note .ao-ico {
    flex: none;
}
/* A card pair (.is-pair) stretches both cards to the taller one's height,
 * so Fleet versions and Recent hotfixes end on one line. */
.ao-rel-grid {
    align-items: start;
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
}
.ao-rel-grid.is-pair {
    align-items: stretch;
}
.ao-rel-card {
    min-width: 0;
}
/* Recent hotfixes: WHEN is the age alone (the stamp stays on hover); the
 * result pill never wraps. */
.ao-rel-card .ao-agr-when-abs {
    display: none;
}
.ao-rel-card .ao-state-pill {
    white-space: nowrap;
}
.ao-rel-dist {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: flex;
    gap: 2px;
    height: 12px;
    overflow: hidden;
}
.ao-rel-seg {
    flex-basis: 0;
    min-width: 4px;
}
.ao-rel-seg.is-k1,
.ao-rel-sw.is-k1 {
    background: var(--ao-k-1);
}
.ao-rel-seg.is-k2,
.ao-rel-sw.is-k2 {
    background: var(--ao-k-2);
}
.ao-rel-seg.is-k3,
.ao-rel-sw.is-k3 {
    background: var(--ao-k-3);
}
.ao-rel-seg.is-k4,
.ao-rel-sw.is-k4 {
    background: var(--ao-k-4);
}
.ao-rel-seg.is-k5,
.ao-rel-sw.is-k5 {
    background: var(--ao-k-5);
}
.ao-rel-seg.is-k6,
.ao-rel-sw.is-k6 {
    background: var(--ao-k-6);
}
.ao-rel-dist-legend {
    display: flex;
    flex-direction: column;
    margin-top: 12px;
}
.ao-rel-leg {
    align-items: center;
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 10px;
    padding: 7px 0;
}
.ao-rel-leg:first-child {
    border-top: 0;
}
.ao-rel-sw {
    border-radius: 3px;
    flex: none;
    height: 10px;
    width: 10px;
}
.ao-rel-leg-v {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-rel-leg-n {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    margin-left: auto;
    white-space: nowrap;
}
.ao-rel-legend {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    margin: 0;
    max-width: 92ch;
}
.ao-rel-table td.ao-rel-ver {
    font-weight: 600;
}
/* ROLLOUT: the channel pill, the phone's bake pill, then PROMOTE beside the
 * CANARY it promotes (no separate ACTION column). */
.ao-rel-table td.ao-rel-rollout {
    white-space: nowrap;
}
.ao-rel-chanbox,
.ao-rel-bake-sm {
    display: inline-flex;
    vertical-align: middle;
}
.ao-rel-bake-sm.ao-agr-sm-only {
    display: none;
}
span.ao-rel-bake-sm.ao-agr-sm-only:empty {
    display: none;
}
.ao-rel-rollout > .ao-rel-bake-sm,
.ao-rel-rollout > .ao-btn {
    margin-left: 8px;
}
.ao-rel-rollout > .ao-btn {
    vertical-align: middle;
    white-space: nowrap;
}
/* PROMOTE over a failing bake gate: a neutral pill with an amber alert icon
 * (.is-override), never the gold primary the gate says to wait on. */
.ao-btn.is-override .ao-ico {
    color: var(--ao-warn-text);
}
/* STAGED is a real channel, not an absent reading: dim text, solid rim. */
.ao-state-pill.ao-rel-chan[data-chan='staged'] {
    border-color: var(--ao-border);
    border-style: solid;
    color: var(--ao-fg-dim);
}
@media (max-width: 760px) {
    .ao-rel-table .ao-rel-ver-pre {
        display: none;
    }
    .ao-rel-bake-sm.ao-agr-sm-only:not(:empty) {
        display: inline-flex;
    }
    .ao-rel-rollout > .ao-rel-bake-sm {
        margin-left: 6px;
    }
    /* PROMOTE takes a second line under the pills rather than widening the
     * row past the phone (a hidden one keeps its inline display: none). */
    .ao-rel-table td.ao-rel-rollout {
        white-space: normal;
    }
    .ao-rel-rollout > .ao-btn {
        display: flex;
        margin: 6px 0 0;
        width: fit-content;
    }
}
.ao-rel-empty {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    padding: 18px 16px;
    text-align: center;
}
.ao-rel-override {
    align-items: flex-start;
    background: var(--ao-warn-bg);
    border: 1px solid var(--ao-warn-bd);
    border-radius: var(--ao-r-md);
    color: var(--ao-warn-text);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 8px;
    line-height: 1.4;
    margin-bottom: 10px;
    padding: 8px 10px;
}
.ao-rel-override .ao-ico {
    flex: none;
    margin-top: 1px;
}

/* ── Incubator: gym scannability layer ──────────────────────────────────────
   The run is 43 stacks and climbing. As a flat row list it was a wall you had
   to read to learn the one thing you came for: is it green, and if not, what
   broke. Verdict + gaps + a colour grid answer that above the fold; the rows
   move behind a disclosure. */

.ao-gym-headline {
    align-items: center;
}

.ao-gym-verdict {
    font-weight: 700;
    letter-spacing: 0.08em;
    font-size: var(--ao-fs-meta);
    padding: 3px 10px;
    border-radius: var(--ao-r-sm);
    border: 1px solid transparent;
}

.ao-gym-pass {
    color: var(--ao-ok-text);
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
}

.ao-gym-fail {
    color: var(--ao-err-strong);
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
}

/* The grid. Cells are named, not anonymous squares: a red cell you cannot
   identify without hovering is a puzzle, not a status. */
.ao-gym-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin: 10px 0 4px;
}

.ao-gym-cell {
    font-size: var(--ao-fs-label);
    line-height: 1.5;
    padding: 2px 7px;
    border-radius: var(--ao-r-sm);
    border: 1px solid var(--ao-border-soft);
    color: var(--ao-fg-dim);
    background: var(--ao-tint);
    white-space: nowrap;
    cursor: default;
}

.ao-gym-solved {
    color: var(--ao-ok-text);
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
}

.ao-gym-failed {
    color: var(--ao-err-strong);
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
    font-weight: 600;
}

/* Deferred is a decision, not a failure. It must not read as either green or
   red, or the score stops meaning anything. */
.ao-gym-deferred {
    color: var(--ao-fg-mute);
    background: transparent;
    border-style: dashed;
}

.ao-gym-unknown {
    color: var(--ao-fg-mute);
}

/* Gaps, promoted from the bottom of the pane to just under the verdict. */
.ao-gym-gap {
    display: flex;
    gap: 10px;
    align-items: baseline;
    padding: 5px 9px;
    margin: 4px 0;
    font-size: var(--ao-fs-body);
    border-left: 2px solid var(--ao-err-border-strong);
    background: var(--ao-err-soft);
    border-radius: 0 3px 3px 0;
}

.ao-gym-gap-id {
    color: var(--ao-err-strong);
    font-weight: 600;
    flex: 0 0 auto;
}

.ao-gym-gap-why {
    color: var(--ao-fg-dim);
    overflow-wrap: anywhere;
}

.ao-gym-detail {
    margin: 10px 0 4px;
    border-top: 1px solid var(--ao-border-soft);
    padding-top: 8px;
}

.ao-gym-detail > summary {
    cursor: pointer;
    font-size: var(--ao-fs-meta);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ao-fg-mute);
    list-style: revert;
}

.ao-gym-detail > summary:hover {
    color: var(--ao-fg-dim);
}

.ao-gym-detail[open] > summary {
    margin-bottom: 6px;
}

/* Advisory: a NON_GATING obstacle that failed. Amber, not red — run_gym excludes
   it from the exit code, so CI is green and the tab must agree. */
.ao-gym-advisory {
    color: var(--ao-warn-text);
    background: rgba(251, 191, 36, 0.08);
    border-color: var(--ao-warn-border);
}

.ao-gym-gap-advisory {
    border-left-color: var(--ao-warn-border);
    background: rgba(251, 191, 36, 0.06);
}

/* ── Pipeline Data (#/pipelinedata, track-ops slice 4 Task 3) ──────────
   Tracks/day named-cell strip. Deliberately its OWN class namespace (not
   .ao-gym-*): same "named, not anonymous squares" shape as the training-gym
   heatmap above, but a different state vocabulary (idle/ok/warn, tied to
   classifier-bucket semantics, not solved/failed/deferred), so the two
   blocks never share — and can never accidentally cross-affect — CSS. */
/* Design system v2 (2026-09-23 rehaul): the page is a KPI strip, the
 * tracks/day chart card and a two-card row (labels, storage). The day strip
 * is now a stacked column chart on the Team pulse classes; each column is
 * still the named .ao-pd-cell with its idle/ok/warn grade — the grade now
 * shows as the column's hover tint and, for an idle day, a dashed floor. */
.ao-pd-panel {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
}
.ao-pd-block.ao-card {
    min-width: 0;
    padding: var(--ao-s-4) var(--ao-s-5) var(--ao-s-5);
}
.ao-pd-cols {
    align-items: start;
    display: grid;
    gap: var(--ao-s-4);
    grid-template-columns: minmax(0, 1fr);
}
/* Labels holds two tables side by side, so it takes two thirds. */
@media (min-width: 1280px) {
    .ao-pd-cols {
        grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    }
}
.ao-pd-chart {
    grid-template-rows: 200px 24px;
}
.ao-pd-chart .ao-tm-pulse-tick.is-top,
.ao-pd-chart .ao-tm-pulse-grid.is-top {
    bottom: 100%;
}
.ao-pd-chart .ao-tm-pulse-tick.is-mid,
.ao-pd-chart .ao-tm-pulse-grid.is-mid {
    bottom: 50%;
}
.ao-pd-chart .ao-tm-pulse-tick.is-zero {
    bottom: 0;
}
/* Fourteen days, not Team's thirty: the columns may be twice as wide (at
 * the Team cap they left more gap than bar). */
.ao-pd-chart .ao-tm-pulse-stack {
    max-width: 48px;
}
.ao-pd-cell {
    cursor: default;
    outline: none;
}
.ao-pd-cell.is-hot,
.ao-pd-cell:focus-visible {
    background: var(--ao-tint-2);
}
.ao-pd-cell:focus-visible {
    box-shadow: inset 0 0 0 1px var(--ao-accent-line);
}
.ao-pd-cell.warn.is-hot {
    background: var(--ao-warn-bg);
}
/* No tracks that day: a dashed floor, neither green nor red — a closed
 * store is not a pipeline failure. */
.ao-pd-cell.idle::after {
    background: repeating-linear-gradient(90deg, var(--ao-fg-mute) 0 3px, transparent 3px 6px);
    border-radius: 2px;
    bottom: 0;
    content: '';
    height: 2px;
    left: 22%;
    position: absolute;
    right: 22%;
}
.ao-pd-seg.is-high {
    background: var(--ao-err);
}
.ao-pd-seg.is-medium {
    background: var(--ao-warn);
}
.ao-pd-seg.is-low {
    background: var(--ao-k-1);
}
/* The day and its total, as text for a screen reader (and the tests). */
.ao-pd-sr {
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}
.ao-pd-foot {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3) var(--ao-s-4);
    justify-content: space-between;
    margin-top: var(--ao-s-3);
}
.ao-pd-readout {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    min-height: 1.4em;
}
.ao-pd-labels {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
}
.ao-pd-facts {
    display: grid;
    gap: var(--ao-s-2);
    grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
}
.ao-pd-fact {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    padding: 10px 12px;
}
.ao-pd-fact-v {
    font-family: var(--ao-mono);
    font-size: 18px;
    font-weight: 600;
    letter-spacing: -0.02em;
    overflow-wrap: anywhere;
}
.ao-pd-fact-k {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
/* A ledger code in words, its code under it (quiet, mono). */
.ao-pd-key {
    display: flex;
    flex-direction: column;
    gap: 1px;
    line-height: 1.3;
    min-width: 0;
}
.ao-pd-key-name {
    color: var(--ao-fg);
}
.ao-pd-key-code {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}
/* Label bars: sources one KPI hue; verdicts by what they mean. */
.ao-pd-label-table.is-source span.ao-table-bar-fill {
    background: var(--ao-k-5);
}
.ao-pd-label-table tr.is-tone-err span.ao-table-bar-fill {
    background: var(--ao-err);
}
.ao-pd-label-table tr.is-tone-warn span.ao-table-bar-fill {
    background: var(--ao-warn);
}
.ao-pd-label-table tr.is-tone-ok span.ao-table-bar-fill {
    background: var(--ao-ok);
}
.ao-pd-label-table tr.is-tone-neutral span.ao-table-bar-fill {
    background: var(--ao-fg-mute);
}
.ao-pd-retention {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    margin-top: var(--ao-s-4);
}
.ao-pd-retention-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
/* Retention per kind on one day scale: name, bar, days. */
.ao-pd-ret-list {
    display: flex;
    flex-direction: column;
    gap: 9px;
}
.ao-pd-ret {
    --ao-pd-ret-c: var(--ao-k-5);
    align-items: center;
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: minmax(84px, 112px) minmax(0, 1fr) 44px;
}
.ao-pd-ret.is-flagged {
    --ao-pd-ret-c: var(--ao-k-4);
}
.ao-pd-ret.is-vectors {
    --ao-pd-ret-c: var(--ao-k-2);
}
.ao-pd-ret-k {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    white-space: nowrap;
}
.ao-pd-ret-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: block;
    height: 6px;
    overflow: hidden;
    position: relative;
}
.ao-pd-ret-bar.is-unmeasured {
    background: repeating-linear-gradient(45deg, var(--ao-tint-2) 0 3px, transparent 3px 6px);
}
.ao-pd-ret-fill {
    background: var(--ao-pd-ret-c);
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
.ao-pd-ret-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    text-align: right;
}
/* Open reports: open / matched / no footage as one split bar with a key,
 * under the card's number (the foot the card used to leave empty). */
.ao-pd-split {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: auto;
    padding-top: var(--ao-s-2);
}
.ao-pd-split-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: flex;
    gap: 2px;
    height: 5px;
    overflow: hidden;
}
.ao-pd-split-seg {
    flex: 1 1 0;
    min-width: 3px;
}
.ao-pd-split-seg.is-open,
.ao-pd-split-sw.is-open {
    background: var(--ao-warn);
}
.ao-pd-split-seg.is-matched,
.ao-pd-split-sw.is-matched {
    background: var(--ao-info);
}
.ao-pd-split-seg.is-nofoot,
.ao-pd-split-sw.is-nofoot {
    background: var(--ao-fg-mute);
}
.ao-pd-split-key {
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-label);
    gap: 2px 10px;
}
.ao-pd-split-k {
    align-items: center;
    display: inline-flex;
    gap: 4px;
}
.ao-pd-split-sw {
    border-radius: 50%;
    display: inline-block;
    height: 6px;
    width: 6px;
}
@media (max-width: 760px) {
    .ao-pd-chart {
        grid-template-rows: 150px 24px;
    }
}

/* ── Review (#/review) — design system v2 (2026-09-23 rehaul) ─────────────
 * A KPI strip, then the queue and the reports as cards. The queue keeps its
 * hand-built keyed table (patchRows reconciles it, and its media row spans
 * every column), so these rules style the cells it builds; the reports are
 * card rows with a status edge. */
.ao-rv-panel.ao-card {
    min-width: 0;
    padding: var(--ao-s-4) var(--ao-s-5) var(--ao-s-5);
}
.ao-rv-keys {
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 6px 14px;
    margin: 0 0 var(--ao-s-3);
}
.ao-rv-key {
    align-items: center;
    display: inline-flex;
    gap: 4px;
}
.ao-rv-key kbd {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border);
    border-bottom-width: 2px;
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    line-height: 1;
    min-width: 18px;
    padding: 3px 5px;
    text-align: center;
}
.ao-rv-queue td {
    vertical-align: middle;
}
/* Sans capitals on every header (the old .ao-num on two made them mono and
 * a pixel high). PRIORITY starts where its dot does — the cell reads left,
 * dot then number — and PEAK RISK sits right over its right-aligned value. */
.ao-rv-queue th.ao-rv-th-num {
    text-align: right;
}
#argus-ops-root .ao-rv-queue td.ao-rv-prio {
    text-align: left;
}
/* Priority tier dot, drawn by CSS so the cell's text stays the number. */
.ao-rv-prio[data-p]::before {
    background: var(--ao-fg-mute);
    border-radius: 50%;
    content: '';
    display: inline-block;
    height: 7px;
    margin-right: 8px;
    vertical-align: middle;
    width: 7px;
}
.ao-rv-prio[data-p='1']::before {
    background: var(--ao-err);
    box-shadow: 0 0 0 3px var(--ao-err-bg);
}
.ao-rv-prio[data-p='2']::before {
    background: var(--ao-warn);
}
.ao-rv-prio[data-p='']::before {
    display: none;
}
.ao-rv-queue td[data-role='q-peakrisk'] {
    min-width: 88px;
}
.ao-rv-age {
    color: var(--ao-fg-dim);
}
.ao-rv-labelcell > * {
    vertical-align: middle;
}
/* The label cell holds controls, not text: the v2 cell's 320px cap and
 * overflow clip cut off LABEL and clipped the verdict dropdown to one row. */
.ao-rv-queue td.ao-rv-labelcell {
    max-width: none;
    overflow: visible;
}
/* Wide enough for the whole queue: let the dropdown hang out of the table
 * instead of scrolling inside the wrap. Narrower screens keep the scroll. */
@media (min-width: 1400px) {
    .ao-rv-queue-wrap.ao-table-wrap {
        overflow: visible;
    }
}
.ao-rv-labelcell .ao-tselect {
    margin-right: 6px;
}
.ao-rv-labelcell .ao-tselect-trigger {
    min-height: 26px;
    min-width: 136px;
    padding: 3px 10px;
}
.ao-rv-notes.ao-input {
    border-radius: var(--ao-r-ctl);
    font-size: var(--ao-fs-meta);
    margin-right: 6px;
    min-height: 26px;
    padding: 3px 12px;
    width: 132px;
}
.ao-rv-notes.ao-input.is-wide {
    width: 240px;
}
/* VIEW / HIDE: a bordered pill with an eye. The eye is a currentColor mask
 * (the icon set's eye glyph), not an aoIcon node — the patch path rewrites
 * the label with textContent, which would strip a child icon. */
.ao-rv-media-btn::before {
    background: currentColor;
    content: '';
    flex: none;
    height: 13px;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E")
        center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E")
        center / contain no-repeat;
    width: 13px;
}
.ao-rv-media-btn {
    min-width: 72px;
}
.ao-rv-media-btn.is-open {
    background: var(--ao-tint-2);
    border-color: var(--ao-accent-line);
    color: var(--ao-fg);
}
/* j/k focus: the console's focus ring on the row, plus the accent tick. */
.ao-rv-queue tr.is-kbd-focus {
    outline: 2px solid var(--ao-focus);
    outline-offset: -2px;
}
.ao-rv-queue tr.is-kbd-focus > td {
    background: var(--ao-hover);
}
.ao-rv-queue tr.is-kbd-focus > td:first-child {
    box-shadow: inset 2px 0 0 var(--ao-accent-line);
}
/* The media row is a well under its track, not another data row. */
.ao-rv-media-cell,
.ao-table tr.ao-rv-media-row:hover > td {
    background: var(--ao-bg);
}
.ao-rv-media-cell {
    padding: var(--ao-s-3) var(--ao-s-4);
    white-space: normal;
}
.ao-rv-clip {
    background: var(--ao-bg);
    border-radius: var(--ao-r-lg);
    display: block;
    max-height: 360px;
    width: 100%;
}
.ao-rv-film-big {
    background: var(--ao-bg);
    border-radius: var(--ao-r-lg);
    cursor: pointer;
    margin-bottom: var(--ao-s-2);
    max-height: 360px;
    object-fit: contain;
    width: 100%;
}
.ao-rv-film-strip {
    display: flex;
    gap: var(--ao-s-2);
    overflow-x: auto;
    padding-bottom: 2px;
}
.ao-rv-film-thumb {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    cursor: pointer;
    flex: 0 0 auto;
    height: 64px;
    width: auto;
}
.ao-rv-film-thumb:hover {
    border-color: var(--ao-accent-line);
}
.ao-rv-media-note {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    margin-left: var(--ao-s-2);
}
.ao-rv-media-note.is-empty {
    font-style: italic;
    margin-left: 0;
}
.ao-rv-empty {
    color: var(--ao-fg-mute);
    padding: var(--ao-s-5) var(--ao-s-4);
    text-align: center;
    white-space: normal;
}
.ao-rv-reports {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.ao-rv-report {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    box-shadow: inset 3px 0 0 var(--ao-border);
    padding: var(--ao-s-3) var(--ao-s-4);
}
.ao-rv-report[data-status='open'],
.ao-rv-report[data-status='no_footage'] {
    box-shadow: inset 3px 0 0 var(--ao-warn-border);
}
.ao-rv-report[data-status='matched'] {
    box-shadow: inset 3px 0 0 var(--ao-info-bd);
}
.ao-rv-report[data-status='resolved'] {
    box-shadow: inset 3px 0 0 var(--ao-ok-border);
}
.ao-rv-report-top {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 6px var(--ao-s-3);
}
.ao-rv-report-store {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-rv-report-store:empty {
    display: none;
}
.ao-rv-report-window {
    align-items: center;
    color: var(--ao-fg-mute);
    display: inline-flex;
    flex-wrap: wrap;
    font-family: var(--ao-mono);
    gap: 2px 6px;
}
.ao-rv-report-window .ao-ico {
    flex: none;
}
.ao-rv-report-matched {
    background: var(--ao-info-bg);
    border: 1px solid var(--ao-info-bd);
    border-radius: var(--ao-r-tag);
    color: var(--ao-info-fg);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    padding: 1px 8px;
}
.ao-rv-report-desc {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-strong);
    line-height: 1.5;
    margin: var(--ao-s-2) 0 var(--ao-s-3);
    overflow-wrap: anywhere;
}
.ao-rv-report-acts {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
}
.ao-rv-report-acts .ao-rv-notes.ao-input {
    margin-right: 0;
}
.ao-rv-resolution {
    align-items: center;
    color: var(--ao-ok-text);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
}
@media (max-width: 760px) {
    .ao-rv-panel.ao-card {
        padding: var(--ao-s-3);
    }
    .ao-rv-notes.ao-input.is-wide {
        flex: 1 1 160px;
        width: auto;
    }
    /* No keyboard on a phone: the j/k legend is noise there. */
    .ao-rv-keys {
        display: none;
    }
    /* The queue as stacked row cards (as Incidents and Records): priority
     * dot down the left, store + bucket, camera + risk, age + VIEW, then the
     * LABEL controls on their own full-width line. The media row and the
     * empty row stay one full-width cell. */
    .ao-rv-queue,
    .ao-rv-queue > tbody {
        display: block;
    }
    .ao-rv-queue > thead {
        display: none;
    }
    .ao-rv-queue > tbody > tr {
        border-bottom: 1px solid var(--ao-border-soft);
        display: grid;
        gap: 6px 10px;
        grid-template-areas:
            'prio tenant tenant bucket'
            'prio cam cam peak'
            'prio age hn media'
            'label label label label';
        grid-template-columns: auto minmax(0, 1fr) auto auto;
        padding: 12px 12px 12px 10px;
    }
    .ao-rv-queue > tbody > tr:last-child {
        border-bottom: 0;
    }
    .ao-rv-queue > tbody > tr.ao-rv-media-row,
    .ao-rv-queue > tbody > tr.ao-rv-empty-row {
        display: block;
        padding: 0;
    }
    #argus-ops-root .ao-rv-queue > tbody > tr > td {
        background: transparent;
        border: 0;
        box-shadow: none;
        max-width: none;
        padding: 0;
    }
    #argus-ops-root .ao-rv-queue > tbody > tr.ao-rv-media-row > td {
        background: var(--ao-bg);
        display: block;
        padding: var(--ao-s-3);
    }
    .ao-rv-queue > tbody > tr:not(.ao-rv-media-row):not(.ao-rv-empty-row):hover {
        background: var(--ao-hover);
    }
    .ao-rv-queue > tbody > tr.is-kbd-focus {
        outline-offset: -2px;
    }
    .ao-rv-queue > tbody > tr > td:nth-child(1) {
        grid-area: prio;
    }
    .ao-rv-queue > tbody > tr > td:nth-child(2) {
        align-self: center;
        font-weight: 600;
        grid-area: tenant;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .ao-rv-queue > tbody > tr > td:nth-child(3) {
        color: var(--ao-fg-dim);
        grid-area: cam;
    }
    .ao-rv-queue > tbody > tr > td:nth-child(4) {
        grid-area: peak;
    }
    .ao-rv-queue > tbody > tr > td:nth-child(5) {
        grid-area: bucket;
        justify-self: end;
    }
    .ao-rv-queue > tbody > tr > td:nth-child(6) {
        align-self: center;
        grid-area: hn;
        justify-self: end;
    }
    .ao-rv-queue > tbody > tr > td:nth-child(7) {
        align-self: center;
        grid-area: age;
    }
    .ao-rv-queue > tbody > tr > td:nth-child(8) {
        grid-area: media;
        justify-self: end;
    }
    /* Verdict, notes, LABEL on one line: the notes box gives way. */
    .ao-rv-queue > tbody > tr > td.ao-rv-labelcell {
        align-items: center;
        display: flex;
        gap: 6px;
        grid-area: label;
        padding-top: 2px;
    }
    .ao-rv-queue td.ao-rv-labelcell > * {
        flex: none;
        margin-right: 0;
    }
    .ao-rv-queue td.ao-rv-labelcell .ao-tselect-trigger {
        min-width: 112px;
    }
    .ao-rv-queue td.ao-rv-labelcell .ao-rv-notes.ao-input {
        flex: 1 1 60px;
        min-width: 0;
        width: auto;
    }
}

.ao-gym-gap-advisory .ao-gym-gap-id {
    color: var(--ao-warn-text);
}

.ao-gym-gap-tag {
    font-size: var(--ao-fs-label);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ao-fg-mute);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    padding: 0 5px;
    flex: 0 0 auto;
}

/* ── INCUBATOR (#/incubator) — rehaul 2026-09-23 ─────────────────────────────
 * A KPI strip, then one Team card per pane: the training run (verdict band,
 * run bar, gaps, the named-cell grid), the live fleet table, the operator
 * queue, recent adaptations beside harness coverage, the generations card
 * (chip picker, per-generation KPIs, delta, fix-list, trend dots) and the
 * composer. The .ao-al-* classes the builders still carry are Alerting's, so
 * every override here is scoped to an .ao-inc-* class. */
.ao-inc-sec {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
.ao-inc-card {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-inc-card > .ao-sec-head {
    margin-bottom: 0;
}
/* Two columns. A card pair (.is-pair: recent adaptations beside harness
 * coverage) stretches both cards to the taller one's height; the in-card
 * delta / fix-list pair keeps its own heights (align start). */
.ao-inc-grid2 {
    align-items: start;
    display: grid;
    gap: var(--ao-s-4);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
    min-width: 0;
}
.ao-inc-grid2.is-pair {
    align-items: stretch;
}
.ao-inc-col {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    min-width: 0;
}
.ao-inc-kpis .ao-stat.is-pass .ao-stat-num {
    color: var(--ao-ok-text);
}
.ao-inc-kpis .ao-stat.is-fail .ao-stat-num {
    color: var(--ao-err-strong);
}
.ao-inc-subh {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    gap: 7px;
    margin-top: var(--ao-s-2);
}
.ao-inc-subh-t {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    letter-spacing: 0.08em;
    margin: 0;
    text-transform: uppercase;
}

/* Status chips: the verdict band, the run context, the generation picker's
 * neighbours. One pill look over the Alerting chip classes they keep. */
.ao-inc-headline.ao-al-summary,
.ao-inc-meta.ao-al-summary,
.ao-inc-genstrip.ao-al-summary {
    align-items: center;
    gap: 8px;
    margin: 0;
}
.ao-al-count.ao-inc-chip {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    line-height: 1.5;
    opacity: 1;
    padding: 2px 10px;
}
.ao-al-count.ao-inc-chip.is-mono {
    font-family: var(--ao-mono);
}
.ao-al-count.ao-inc-chip.ao-al-c-warn,
.ao-al-count.ao-inc-chip.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-text);
}
.ao-al-count.ao-inc-chip.is-ok {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-al-count.ao-inc-chip.ao-al-badge {
    background: var(--ao-info-soft);
    border-color: var(--ao-info-border);
    color: var(--ao-info);
    font-weight: 600;
    letter-spacing: 0;
}
.ao-inc-headline .ao-gym-verdict {
    border-radius: var(--ao-r-tag);
    font-size: var(--ao-fs-strong);
    letter-spacing: 0.12em;
    padding: 4px 16px;
}
/* Beside the verdict, the count and the agent build are plain muted words
 * (no border, no fill), so nothing competes with FAIL / PASS. */
.ao-inc-headline.ao-al-summary {
    gap: 6px 14px;
}
.ao-inc-headline .ao-al-count.ao-inc-chip,
.ao-inc-headline .ao-al-count.ao-inc-chip.is-warn {
    background: none;
    border: 0;
    border-radius: 0;
    color: var(--ao-fg-dim);
    padding: 0;
}
.ao-inc-headline .ao-al-count.ao-inc-chip.is-mono {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}
/* The run context: when it ran and what is next are plain words (.is-text);
 * only a status (running, the promotion bar, the streak) stays a pill. */
.ao-inc-meta.ao-al-summary {
    gap: 6px 16px;
}
.ao-al-count.ao-inc-chip.is-text {
    background: none;
    border: 0;
    border-radius: 0;
    color: var(--ao-fg-mute);
    padding: 0;
}
.ao-al-count.ao-inc-chip.is-text .ao-ico {
    flex: none;
}
/* The field signal: an icon and muted words, the seeded ids as mono chips. */
.ao-al-count.ao-inc-fsig {
    align-items: center;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 4px 6px;
    letter-spacing: 0;
    opacity: 1;
}
.ao-inc-fsig.is-live > .ao-ico {
    color: var(--ao-info);
}
.ao-inc-fsig .ao-inc-id {
    background: var(--ao-tint-2);
    color: var(--ao-fg-dim);
}

/* The run bar: one track split by state, the legend under it. */
.ao-inc-runbar {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.ao-inc-runbar-track {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: flex;
    gap: 2px;
    height: 10px;
    overflow: hidden;
}
.ao-inc-seg {
    flex-basis: 0;
    min-width: 4px;
}
.ao-inc-seg.is-solved,
.ao-inc-legend-i.is-solved .ao-inc-sw {
    background: var(--ao-ok);
}
.ao-inc-seg.is-advisory,
.ao-inc-legend-i.is-advisory .ao-inc-sw {
    background: var(--ao-warn);
}
.ao-inc-seg.is-failed,
.ao-inc-legend-i.is-failed .ao-inc-sw {
    background: var(--ao-err);
}
.ao-inc-seg.is-deferred,
.ao-inc-legend-i.is-deferred .ao-inc-sw {
    background: var(--ao-border);
}
.ao-inc-legend {
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 4px 16px;
}
.ao-inc-legend-i {
    align-items: center;
    display: inline-flex;
    gap: 6px;
}
.ao-inc-legend-n {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-weight: 600;
}
.ao-inc-sw {
    border-radius: 3px;
    display: inline-block;
    flex: none;
    height: 10px;
    width: 10px;
}
.ao-inc-sw.is-k1,
.ao-inc-distseg.is-k1 {
    background: var(--ao-k-1);
}
.ao-inc-sw.is-k2,
.ao-inc-distseg.is-k2 {
    background: var(--ao-k-2);
}
.ao-inc-sw.is-k3,
.ao-inc-distseg.is-k3 {
    background: var(--ao-k-3);
}
.ao-inc-sw.is-k4,
.ao-inc-distseg.is-k4 {
    background: var(--ao-k-4);
}
.ao-inc-sw.is-k5,
.ao-inc-distseg.is-k5 {
    background: var(--ao-k-5);
}
.ao-inc-sw.is-k6,
.ao-inc-distseg.is-k6 {
    background: var(--ao-k-6);
}
.ao-inc-gaps {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.ao-inc-gaps .ao-gym-gap {
    border-radius: 0 var(--ao-r-md) var(--ao-r-md) 0;
    margin: 0;
}
.ao-inc-run .ao-gym-grid {
    margin: 0;
}
.ao-inc-run .ao-gym-cell {
    border-radius: var(--ao-r-tag);
    padding: 2px 9px;
}
.ao-inc-run .ao-gym-detail {
    border-top-color: var(--ao-tint-line);
    margin: 0;
}
/* Per-stack detail: the summary is a row with a chevron that turns when open
 * (no browser triangle), over one dense card table. */
.ao-inc-run .ao-gym-detail > summary.ao-inc-stacksum {
    align-items: center;
    border-radius: var(--ao-r-md);
    color: var(--ao-fg-dim);
    display: flex;
    font-weight: 600;
    gap: 8px;
    letter-spacing: 0.08em;
    list-style: none;
    padding: 4px 6px 4px 2px;
    width: fit-content;
}
.ao-inc-stacksum::-webkit-details-marker {
    display: none;
}
.ao-inc-run .ao-gym-detail > summary.ao-inc-stacksum:hover {
    background: var(--ao-hover);
    color: var(--ao-fg);
}
.ao-inc-stacksum:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-inc-chev {
    display: grid;
    transition: transform var(--ao-fast) var(--ao-ease);
}
.ao-gym-detail[open] > .ao-inc-stacksum .ao-inc-chev {
    transform: rotate(90deg);
}
.ao-inc-stacks td.ao-inc-stack-id {
    color: var(--ao-fg);
    font-weight: 600;
}
/* A stack name never breaks mid-word ("captive_port / al"). */
.ao-table.ao-inc-stacks td:first-child {
    white-space: nowrap;
}
.ao-inc-stack-sub {
    align-items: center;
    display: inline-flex;
    flex-wrap: wrap;
    font-family: var(--ao-font-sans);
    font-weight: 400;
    gap: 3px 6px;
    max-width: 240px;
}
.ao-inc-stacks td.ao-inc-stack-moves {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
.ao-inc-stacks td.ao-inc-stack-note {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    max-width: 420px;
    min-width: 200px;
    white-space: normal;
}
.ao-inc-stacks tr.ao-inc-stack[data-state='failed'] td:first-child {
    box-shadow: inset 2px 0 0 var(--ao-err-border-strong);
}
.ao-inc-stacks tr.ao-inc-stack[data-state='advisory'] td:first-child {
    box-shadow: inset 2px 0 0 var(--ao-warn-border);
}
.ao-inc-stacks tr.ao-table-group.is-sub .ao-table-group-label {
    color: var(--ao-fg-mute);
    padding-left: 12px;
}
/* On a phone the per-stack table is STACK + VERDICT (ENV / CAUSE, MOVES and
 * NOTE step aside, .ao-agr-hide-sm) with the env chip and the note on a
 * second line; the fix-list drops GAP the same way (the gap rides under the
 * scenario id, which breaks only after a "~" or "="). */
@media (max-width: 760px) {
    .ao-table.ao-inc-stacks td:first-child {
        white-space: normal;
    }
    .ao-inc-stack-name {
        overflow-wrap: normal;
        word-break: normal;
    }
    .ao-table.ao-inc-fixlist th:nth-child(3),
    .ao-table.ao-inc-fixlist tr:not(.ao-table-group) > td:nth-child(3) {
        display: none;
    }
    .ao-table.ao-inc-fixlist td:first-child {
        min-width: 150px;
        white-space: normal;
    }
    .ao-inc-sid {
        overflow-wrap: normal;
        word-break: normal;
    }
}

/* LIVE — the environment split as one bar + a chip per environment. */
.ao-inc-dist {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.ao-inc-distbar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: flex;
    gap: 2px;
    height: 8px;
    overflow: hidden;
}
.ao-inc-distseg {
    flex-basis: 0;
    min-width: 4px;
}
.ao-inc-distchips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
}
.ao-inc-envchip {
    align-items: center;
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    gap: 6px;
}
/* A problem environment whose oldest agent entered it a while ago wears a
 * small "oldest 3h" pill on its legend item. */
.ao-state-pill.ao-inc-oldest {
    font-family: var(--ao-font-sans);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.02em;
    line-height: 1.45;
    padding: 0 7px;
    text-transform: none;
}
/* ONE chip for every environment / cause code on the page (fleet, recent
 * adaptations, operator actions, per-stack detail). Some builders keep the
 * code in capitals in the text (the tests read them); every chip draws it
 * the same lowercase way. */
.ao-inc-env {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-block;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    line-height: 1.6;
    padding: 0 8px;
    text-transform: lowercase;
    white-space: nowrap;
}
.ao-table td.ao-inc-strong {
    color: var(--ao-fg);
    font-weight: 600;
}
/* Real content (the raw verdict, the params): --ao-fg-dim, not mute. */
.ao-table td.ao-inc-verdict {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    min-width: 200px;
    white-space: normal;
}

/* OPERATOR ACTIONS — one warn-edged row per action, the runbook under it. */
.ao-inc-action {
    background: var(--ao-tint);
    border: 1px solid var(--ao-tint-line);
    border-radius: var(--ao-r-lg);
    box-shadow: inset 3px 0 0 var(--ao-warn-border);
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px 14px 12px 16px;
}
.ao-inc-action-top {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px 10px;
}
.ao-inc-action-ico {
    color: var(--ao-warn-text);
    display: grid;
}
.ao-inc-action-agent {
    font-size: var(--ao-fs-strong);
    font-weight: 600;
}
.ao-inc-move {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-inc-pending {
    align-items: center;
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 5px;
}
.ao-inc-needs {
    margin-left: auto;
}
.ao-inc-action-desc {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
}
.ao-al-body.ao-inc-runbook {
    background: var(--ao-bg);
    border: 1px solid var(--ao-tint-line);
    border-radius: var(--ao-r-md);
    display: flex;
    flex-direction: column;
    gap: 6px;
    opacity: 1;
    padding: 10px 12px;
    white-space: normal;
}
.ao-al-src.ao-inc-runbook-h {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    gap: 6px;
    letter-spacing: 0.08em;
    opacity: 1;
}
.ao-inc-rb-line {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.ao-al-count.ao-inc-rb-tag {
    color: var(--ao-warn-text);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    opacity: 1;
}
.ao-inc-rb-body {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    white-space: pre-wrap;
}

/* HARNESS COVERAGE — a chip per environment, green where a playbook exists. */
.ao-inc-cov {
    display: grid;
    gap: 6px;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
}
.ao-inc-cov-item {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-tint-line);
    border-radius: var(--ao-r-md);
    color: var(--ao-fg-dim);
    display: flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    gap: 8px;
    min-width: 0;
    overflow-wrap: anywhere;
    padding: 6px 10px;
}
.ao-inc-cov-item.is-pb {
    color: var(--ao-fg);
}
.ao-inc-foot {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
}
/* In a stretched pair the footnote sits on the card's bottom edge. */
.ao-inc-grid2.is-pair > .ao-inc-card > .ao-inc-foot:last-child {
    margin-top: auto;
}

/* GENERATIONS — the picker (one segmented bar) takes the strip's whole
 * width and scrolls sideways once it overflows; RUN NOW sits on its own line
 * under it. (Side by side, RUN NOW covered the last generation mid-word.) */
.ao-inc-genstrip.ao-al-summary {
    flex-wrap: wrap;
}
.ao-inc-genrail {
    flex: 1 1 100%;
    min-width: 0;
    position: relative;
}
/* (The fade at its right edge, while there is more, is every chip bar's:
 * .ao-tm-chips[data-more].) */
.ao-inc-genchips.ao-seg {
    min-width: 0;
    padding-bottom: 2px;
}
.ao-inc-genchips .ao-seg-btn.ao-al-count {
    flex: none;
    opacity: 1;
}
.ao-inc-genchip-age {
    color: var(--ao-fg-mute);
    font-weight: 500;
}
.ao-inc-genchips .ao-seg-btn[aria-pressed='true'] .ao-inc-genchip-age {
    color: inherit;
    opacity: 0.7;
}
.ao-inc-runnow {
    flex: none;
}
.ao-inc-meta.ao-al-summary {
    flex-wrap: wrap;
}
.ao-inc-gengrid {
    align-items: start;
}

/* GENERATION DELTA — one tile per bucket, ids as mono chips. */
.ao-inc-delta {
    display: grid;
    gap: 8px;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
}
.ao-inc-bucket {
    background: var(--ao-tint);
    border: 1px solid var(--ao-tint-line);
    border-radius: var(--ao-r-lg);
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px 12px;
}
.ao-inc-bucket-top {
    align-items: baseline;
    display: flex;
    justify-content: space-between;
}
.ao-inc-bucket-l {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    letter-spacing: 0.04em;
}
.ao-inc-bucket-n {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-h2);
    font-weight: 600;
}
.ao-inc-bucket.is-ok .ao-inc-bucket-n {
    color: var(--ao-ok-text);
}
.ao-inc-bucket.is-err {
    box-shadow: inset 3px 0 0 var(--ao-err-border-strong);
}
.ao-inc-bucket.is-err .ao-inc-bucket-n {
    color: var(--ao-err-strong);
}
.ao-inc-bucket.is-warn .ao-inc-bucket-n {
    color: var(--ao-warn-text);
}
.ao-inc-bucket.is-info .ao-inc-bucket-n {
    color: var(--ao-info);
}
.ao-inc-bucket-ids {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.ao-inc-id {
    background: var(--ao-bg);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    overflow-wrap: anywhere;
    padding: 1px 6px;
}

/* SCENARIO TRENDS — per-scenario dot rows (never an aggregate %). */
.ao-inc-legend.is-trend {
    margin-top: -2px;
}
.ao-inc-trends {
    column-gap: var(--ao-s-5);
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 460px), 1fr));
}
.ao-inc-trend {
    align-items: center;
    border-bottom: 1px solid var(--ao-tint-line);
    display: grid;
    gap: 12px;
    grid-template-columns: minmax(120px, 38%) minmax(0, 1fr);
    padding: 5px 0;
}
.ao-inc-trend-id {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Each result is a drawn dot (the typed glyph stays in the text, at size 0,
 * for the tests and a copy-paste): solved green, failed red, deferred an
 * amber ring, not-yet-in-the-suite a faint dot. The legend uses the same. */
.ao-inc-dots {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    min-width: 0;
}
.ao-inc-dot {
    border-radius: 50%;
    box-sizing: border-box;
    display: inline-block;
    flex: none;
    font-size: 0;
    height: 8px;
    line-height: 0;
    overflow: hidden;
    vertical-align: middle;
    width: 8px;
}
.ao-inc-dot.is-ok {
    background: var(--ao-ok);
}
.ao-inc-dot.is-fail {
    background: var(--ao-err-strong);
}
.ao-inc-dot.is-defer {
    background: transparent;
    box-shadow: inset 0 0 0 1.5px var(--ao-warn);
}
.ao-inc-dot.is-none {
    background: var(--ao-tint-2);
    box-shadow: inset 0 0 0 1px var(--ao-border);
}
/* The typed tick after "auto-fix" stays in the text (display: none adds no
 * flex gap); the pill leads with the check icon instead. */
.ao-inc-tick {
    display: none;
}
.ao-inc-params {
    color: var(--ao-fg-dim);
}
.ao-btn.ao-inc-rm:hover {
    color: var(--ao-err-strong);
}

.ao-table td.ao-inc-scen-cell {
    max-width: 360px;
    white-space: normal;
}

/* COMPOSE SCENARIO — a two-column form (label | control) in the card. */
.ao-inc-help {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    margin: 0;
    max-width: 90ch;
}
.ao-compose-form {
    background: var(--ao-tint);
    border: 1px solid var(--ao-tint-line);
    border-radius: var(--ao-r-lg);
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px 16px;
}
.ao-compose-knobs {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.ao-compose-row {
    align-items: center;
    display: grid;
    gap: 6px 14px;
    grid-template-columns: minmax(120px, 190px) minmax(0, 1fr);
}
.ao-compose-label {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
}
.ao-compose-ctl {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    min-width: 0;
}
.ao-compose-name {
    flex: 1 1 220px;
    max-width: 460px;
    min-width: 0;
}
.ao-compose-num {
    width: 120px;
}
.ao-compose-hint {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}
.ao-compose-actions {
    display: flex;
    justify-content: flex-end;
}
.ao-inc-scenlist {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    min-width: 0;
}
.ao-inc-scen-name {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-inc-scen-base {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-inc-tag {
    background: var(--ao-info-soft);
    border: 1px solid var(--ao-info-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-info);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.06em;
    padding: 1px 8px;
}
@media (max-width: 760px) {
    .ao-compose-row {
        grid-template-columns: minmax(0, 1fr);
    }
    /* In-card KPI rows keep two across on a phone (the card's padding
     * leaves less than two 168px tracks). */
    .ao-inc-genkpis.ao-stat-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    /* An odd count leaves no half-width orphan: the last card takes the row. */
    .ao-inc-genkpis.ao-stat-row > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
    .ao-inc-gaps .ao-gym-gap {
        flex-wrap: wrap;
    }
    .ao-inc-genstrip.ao-al-summary {
        flex-wrap: wrap;
    }
    .ao-inc-runnow {
        margin-left: 0;
    }
    .ao-inc-trend {
        grid-template-columns: minmax(0, 1fr);
        gap: 2px;
    }
    /* One line of dots per scenario, never one dot alone on a second line. */
    .ao-inc-dots {
        flex-wrap: nowrap;
        gap: 3px;
        overflow: hidden;
    }
}

/* ── Grading (#/grade) ──────────────────────────────────────────────────
   Ops adjudication queue for FIRED incidents. Its own .ao-grade-* namespace
   rather than sharing #/review's table styles: this is a card list an operator
   works down for hundreds of rows, not a dense scan table, and the two must
   never be able to cross-affect each other.

   Design system v2 (2026-09-23, the Team page's family): a KPI strip of
   aoStat cards (Ungraded / Graded / Shadowed / In this view), the agreement
   rate as one aoStat card per auto-labeller with a ring meter, the queue
   controls on aoSeg chips, Team-card incident cards, verdicts on .ao-btn
   variants and the clip-quality toggle on aoSwitch. Tokens only. */
.ao-grade-panel {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}

/* ── the KPI strip ──────────────────────────────────────────────────────── */
.ao-grade-kpis.is-skel {
    --ao-stat-cols: 4;
}
.ao-grade-kpi-skel {
    min-height: 118px;
    pointer-events: none;
}
.ao-grade-skel-tile {
    border-radius: 9px;
    height: 30px;
    width: 30px;
}
.ao-grade-skel-num {
    height: 28px;
    margin-top: 6px;
    width: 74px;
}
.ao-grade-skel-sub {
    height: 10px;
    width: 62%;
}
/* The Graded card's sub-line: "20% of 601" over a thin progress meter in
 * the card's own accent. A transform, never a width, so it never reflows. */
.ao-grade-kpi-meter {
    display: flex;
    flex-direction: column;
    gap: 7px;
}
.ao-grade-meter {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    height: 4px;
    overflow: hidden;
    position: relative;
}
.ao-grade-meter-fill {
    background: var(--ao-stat-accent, var(--ao-k-1));
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform var(--ao-slow) var(--ao-ease);
}
/* Not measured is hatched, never an empty track (an empty one reads 0%). */
.ao-grade-meter.is-unmeasured {
    background: repeating-linear-gradient(135deg, var(--ao-tint-2) 0 4px, transparent 4px 8px);
}

/* ── AGREEMENT WITH YOU: one aoStat card per auto-labeller ───────────────
   How often an auto-labeller matched the person who then graded it. It
   reads as an instrument rather than a score - the human grade is not
   proven truth, so the bands say "look at this", not "this is wrong". */
.ao-grade-agree {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
/* [hidden] is display:none at author strength only when restated: the rule
 * above would otherwise paint an empty strip for "nothing graded yet". */
.ao-grade-agree[hidden] {
    display: none;
}
.ao-grade-agreecell .ao-stat-head {
    align-items: flex-start;
}
.ao-grade-agreecell .ao-stat-label {
    align-items: flex-start;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}
/* The model's short name is the card's title; the kind (VLM / FUSION) and
 * the vendor sit under it in the label voice. */
.ao-grade-agreename {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    font-weight: 600;
    letter-spacing: 0.01em;
    overflow-wrap: anywhere;
}
.ao-grade-agreemodel {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.1em;
    overflow-wrap: anywhere;
}
/* The ring: the same percentage as the number, drawn — the track a faint
 * tint, the arc the card's band colour (ok / warn / err). */
.ao-grade-ring {
    display: grid;
    flex: none;
    margin-left: auto;
    place-items: center;
}
.ao-grade-ring-track {
    stroke: var(--ao-tint-2);
}
.ao-grade-ring-arc {
    stroke: var(--ao-stat-accent, var(--ao-fg-mute));
}
.ao-grade-agreesub {
    color: var(--ao-fg-mute);
}
.ao-grade-agreenum {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}
.ao-grade-agreecell.is-bad .ao-grade-agreenum {
    color: var(--ao-err-fg);
}
.ao-grade-agreecell.is-mid .ao-grade-agreenum {
    color: var(--ao-warn-fg);
}
.ao-grade-agreecell.is-ok .ao-grade-agreenum {
    color: var(--ao-ok-fg);
}
/* The direction of each disagreement (14 THEFT → FP), as small pills: a mono
 * count, then the two verdicts either side of a drawn arrow. */
.ao-grade-agreemiss {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 2px;
}
.ao-grade-agreepair {
    align-items: center;
    background: var(--ao-tint);
    border-radius: var(--ao-r-tag);
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 5px;
    letter-spacing: 0.06em;
    padding: 2px 9px 2px 3px;
    white-space: nowrap;
}
.ao-grade-agreepair-n {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0;
    padding: 0 6px;
}
.ao-grade-agreepair .ao-ico {
    color: var(--ao-fg-mute);
    flex: none;
}

/* A section heading belongs to what follows it: room above, and in this
 * flex-gap panel the gap (not a margin) spaces it from its content. */
.ao-grade-panel > .ao-sec-head {
    margin-bottom: 0;
    margin-top: var(--ao-s-3);
}
.ao-grade-agree > .ao-sec-head {
    margin-top: var(--ao-s-3);
}

/* ── the queue controls ─────────────────────────────────────────────────── */
.ao-grade-progress {
    font-variant-numeric: tabular-nums;
}
.ao-grade-controls {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-grade-bar {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3) var(--ao-s-6);
    min-width: 0;
}
/* SORT / MODEL / JUDGED BY: a two-column grid. Each row is display:contents,
 * so every caption shares the first column and every chip row starts on one
 * left edge, whatever the caption's length. */
.ao-grade-tools {
    align-items: center;
    border-top: 1px solid var(--ao-border-faint);
    display: grid;
    gap: var(--ao-s-3) var(--ao-s-4);
    grid-template-columns: auto minmax(0, 1fr);
    min-width: 0;
    padding-top: var(--ao-s-3);
}
.ao-grade-toolrow {
    display: contents;
}
/* No labeller to choose between: the JUDGED BY row steps aside. [hidden]
 * restated, as display:contents would otherwise keep it on screen. */
.ao-grade-toolrow[hidden] {
    display: none;
}
.ao-grade-toolcap {
    white-space: nowrap;
}

/* Every queue chip is the shared chip (aoSeg → .ao-tm-chip); these base
 * rules only pin the geometry the pill-buttons contract reads off each
 * family (the control radius + a literal px floor). The look is .ao-tm-chip's:
 * a segment of one bordered bar, the pressed one tinted and bold.
 * The queue FILTER is the exception: it is the page's main view switch, so it
 * is built as the segmented bar (aoSeg variant 'seg'), whose later
 * .ao-tm-seg-btn rule draws its segments; the radius here is its fallback. */
.ao-grade-filter,
.ao-grade-sortbtn,
.ao-grade-mvbtn,
.ao-grade-clsbtn {
    border-radius: var(--ao-r-ctl);
    min-height: 28px;
    min-width: auto;
}
.ao-grade-filter:focus-visible,
.ao-grade-sortbtn:focus-visible,
.ao-grade-mvbtn:focus-visible,
.ao-grade-clsbtn:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: -2px;
}

/* JUDGED BY: the work left per auto-labeller, as a plain number beside the
 * name (spec: counts in a filter are plain numbers, not a tag in a tag). */
.ao-grade-clscount {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-variant-numeric: tabular-nums;
    /* 14px tall, so a chip with a count is ALL's 28px, not 29. */
    line-height: 14px;
}
.ao-grade-clsbtn[aria-pressed='true'] .ao-grade-clscount {
    color: var(--ao-fg-dim);
}

/* Sort is fixed on the calibration queue - the group dims to say so. The
   buttons stay clickable (they re-arm once you leave calibration); only the
   look changes, matching how the server treats the value (ignored, not
   rejected). */
.ao-grade-sort.is-inert {
    opacity: 0.45;
}

/* Standing reminder of what a grade is and is not. Muted, never a warning
   colour: it states a boundary, it does not report a problem. */
.ao-grade-note {
    align-items: flex-start;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-lg);
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: 10px;
    line-height: 1.55;
    padding: 10px 14px;
}
.ao-grade-note-ico {
    color: var(--ao-info-fg);
    display: grid;
    flex: none;
    margin-top: 1px;
}
.ao-grade-note-text {
    min-width: 0;
}

/* ── the incident cards (the Team card) ─────────────────────────────────── */
.ao-grade-list {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
/* A failed fetch lines up with the note and the cards, not 16px inside them. */
.ao-grade-list > .ao-error {
    margin: 0;
}

.ao-grade-card {
    display: flex;
    flex-direction: column;
    min-width: 0;
    padding: 0;
    position: relative;
}

/* An already-graded card stays legible but stops competing for attention with
   the ungraded ones the operator is here for: dimmer, with an ok edge. */
.ao-grade-card.is-graded {
    box-shadow:
        inset 3px 0 0 var(--ao-ok-bd),
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    opacity: 0.8;
}
/* The edge is the verdict's tone: THEFT red, UNCERTAIN neutral. */
.ao-grade-card.is-graded.gv-confirmed_theft,
.ao-grade-card.is-graded.gv-missed_theft {
    box-shadow:
        inset 3px 0 0 var(--ao-err-bd),
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
}
.ao-grade-card.is-graded.gv-uncertain {
    box-shadow:
        inset 3px 0 0 var(--ao-border),
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
}

.ao-grade-head {
    align-items: center;
    background: var(--ao-tint);
    border-bottom: 1px solid var(--ao-tint-line);
    border-radius: var(--ao-r-xl) var(--ao-r-xl) 0 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px 14px;
    padding: 12px 16px;
}

/* The risk band and raw score, as a status pill with a dot. */
.ao-grade-risk {
    align-items: center;
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-tag);
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    gap: 7px;
    letter-spacing: 0.04em;
    padding: 3px 10px;
    white-space: nowrap;
}
.ao-grade-risk::before {
    background: var(--ao-fg-mute);
    border-radius: 50%;
    content: '';
    flex: none;
    height: 7px;
    width: 7px;
}
.ao-grade-risk.lvl-critical,
.ao-grade-risk.lvl-high {
    background: var(--ao-err-bg);
    box-shadow: inset 0 0 0 1px var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-grade-risk.lvl-critical::before,
.ao-grade-risk.lvl-high::before {
    background: var(--ao-err);
    box-shadow: 0 0 0 3px var(--ao-err-soft);
}
.ao-grade-risk.lvl-elevated,
.ao-grade-risk.lvl-medium {
    background: var(--ao-warn-bg);
    box-shadow: inset 0 0 0 1px var(--ao-warn-border);
    color: var(--ao-warn-fg);
}
.ao-grade-risk.lvl-elevated::before,
.ao-grade-risk.lvl-medium::before {
    background: var(--ao-warn);
}

.ao-grade-cam {
    align-items: center;
    color: var(--ao-fg);
    display: inline-flex;
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    gap: 6px;
    min-width: 0;
}
.ao-grade-cam .ao-ico,
.ao-grade-when .ao-ico {
    color: var(--ao-fg-mute);
    flex: none;
}

.ao-grade-when {
    align-items: center;
    color: var(--ao-fg-dim);
    display: inline-flex;
    flex: 1 1 auto;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 4px 6px;
    min-width: 0;
}
.ao-grade-ts {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    overflow-wrap: anywhere;
}

.ao-grade-chip {
    /* UNGRADED is quiet: an outline, never the risk pill's amber beside it. */
    background: transparent;
    border-radius: var(--ao-r-tag);
    box-shadow: inset 0 0 0 1px var(--ao-border);
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.1em;
    padding: 3px 10px;
    text-transform: uppercase;
    white-space: nowrap;
}

.ao-grade-chip.is-graded {
    background: var(--ao-ok-bg);
    box-shadow: inset 0 0 0 1px var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
/* A graded pill takes its verdict's tone, as the verdict buttons do: THEFT
 * red, FALSE POSITIVE (and NORMAL) green, UNCERTAIN neutral. */
.ao-grade-chip.is-graded.v-confirmed_theft,
.ao-grade-chip.is-graded.v-missed_theft {
    background: var(--ao-err-bg);
    box-shadow: inset 0 0 0 1px var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-grade-chip.is-graded.v-uncertain {
    background: var(--ao-tint-2);
    box-shadow: inset 0 0 0 1px var(--ao-border);
    color: var(--ao-fg-dim);
}

.ao-grade-body {
    display: grid;
    gap: 18px;
    grid-template-columns: minmax(220px, 300px) minmax(0, 1fr);
    padding: 16px;
}

.ao-grade-media {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}

/* The keyframe: a 16:9 frame with the whole picture visible (contain — a
 * crop could cut the very hand the grade is about). */
.ao-grade-thumb {
    aspect-ratio: 16 / 9;
    background: var(--ao-bg);
    border-radius: 12px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    display: grid;
    overflow: hidden;
    place-items: center;
}
.ao-grade-thumb img {
    display: block;
    height: 100%;
    object-fit: contain;
    width: 100%;
}
.ao-grade-thumb .ao-grade-nomedia {
    padding: 12px;
    text-align: center;
}

.ao-grade-video {
    background: var(--ao-bg);
    border-radius: 12px;
    display: block;
    max-height: 260px;
    width: 100%;
}

.ao-grade-clip {
    align-items: flex-start;
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}
.ao-grade-clip > .ao-grade-video {
    align-self: stretch;
}

/* Why there is no player: a warn pill over the sentence that explains it. */
.ao-grade-clipbadge {
    align-items: center;
    background: var(--ao-warn-bg);
    border-radius: var(--ao-r-tag);
    box-shadow: inset 0 0 0 1px var(--ao-warn-border);
    color: var(--ao-warn-fg);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 5px;
    letter-spacing: 0.08em;
    padding: 3px 10px 3px 8px;
    white-space: nowrap;
}

/* Absent media is stated in words, never left as an empty box that reads as a
   loading failure. */
.ao-grade-nomedia {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.45;
}

.ao-grade-detail {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
}

.ao-grade-narrative {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    line-height: 1.55;
    margin: 0;
}

/* The facts as a spec sheet: label over a mono value, one tile each. Each
 * tile starts at its own content's width and the row shares out the rest, so
 * a long value (exit_without_pay) is never cut mid-word to make room, and the
 * store (the one long value, a name over an id) takes twice the share so its
 * name is not cut either. A row that cannot hold them all wraps, no holes. */
.ao-grade-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ao-grade-fact.is-store {
    flex-grow: 2;
}

.ao-grade-fact {
    background: var(--ao-tint);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px var(--ao-border-faint);
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    padding: 7px 10px;
}

.ao-grade-fact-k {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.ao-grade-fact-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    min-width: 0;
    overflow-wrap: anywhere;
}
/* The store resolves to a NAME (aoIdentity) — a name reads in the sans. The
 * identity is held to the tile's width, so the name and the id under it take
 * the shared ellipsis instead of running out of the tile (or breaking the id
 * mid-hash); the tile's title carries the whole id. */
.ao-grade-fact-v .ao-identity {
    display: flex;
    max-width: 100%;
    min-width: 0;
}
.ao-grade-fact-v .ao-identity-name {
    font-family: var(--ao-font-sans);
    font-weight: 600;
}

.ao-grade-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.ao-grade-tag {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-tag);
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    padding: 2px 9px;
}

.ao-grade-vlm {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.ao-grade-vlm-chip {
    align-items: center;
    background: var(--ao-tint);
    border-radius: var(--ao-r-tag);
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 5px;
    letter-spacing: 0.08em;
    padding: 3px 10px 3px 8px;
    white-space: nowrap;
}

.ao-grade-vlm-chip.is-ok {
    background: var(--ao-ok-bg);
    box-shadow: inset 0 0 0 1px var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}

.ao-grade-vlm-chip.is-no {
    background: var(--ao-warn-bg);
    box-shadow: inset 0 0 0 1px var(--ao-warn-border);
    color: var(--ao-warn-fg);
}

/* "no verdict recorded" must not read as a negative verdict: dashed + neutral,
   the same "absence is not a value" treatment .ao-pd-cell.idle uses. */
.ao-grade-vlm-chip.is-unknown {
    background: transparent;
    border: 1px dashed var(--ao-border);
    box-shadow: none;
}

.ao-grade-vlm-reason {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    line-height: 1.45;
}

/* The VLM teacher verdict strip — which model / platform graded this clip,
 * each a mono pill with a dot in the verdict's colour. */
.ao-grade-models {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ao-grade-models-label {
    align-items: center;
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    gap: 5px;
    letter-spacing: 0.1em;
    margin-right: 2px;
}
/* No model verdict: the dashed, neutral pill NO VLM VERDICT RECORDED wears. */
.ao-grade-models-empty {
    align-items: center;
    border: 1px dashed var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 5px;
    letter-spacing: 0.08em;
    padding: 3px 10px 3px 8px;
    white-space: nowrap;
}
.ao-grade-model {
    align-items: center;
    background: var(--ao-surface-2);
    border-radius: var(--ao-r-tag);
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    gap: 6px;
    padding: 3px 9px;
    white-space: nowrap;
}
.ao-grade-model-id {
    display: inline-flex;
    min-width: 0;
}
/* The vendor muted, the model bright: named as the agreement cards name it. */
.ao-grade-model-vendor {
    color: var(--ao-fg-mute);
}
.ao-grade-model-name {
    color: var(--ao-fg);
}
.ao-grade-model::before {
    background: var(--ao-fg-mute);
    border-radius: 50%;
    content: '';
    flex: none;
    height: 6px;
    width: 6px;
}
.ao-grade-model.v-confirmed_theft::before {
    background: var(--ao-err);
}
.ao-grade-model.v-false_positive::before {
    background: var(--ao-ok);
}
.ao-grade-model.v-uncertain::before {
    background: var(--ao-warn);
}

.ao-grade-current {
    background: var(--ao-tint);
    border-radius: 10px;
    box-shadow: inset 0 0 0 1px var(--ao-border-faint);
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 9px 12px;
}
.ao-grade-card.is-graded .ao-grade-current {
    background: var(--ao-ok-bg);
    box-shadow:
        inset 3px 0 0 var(--ao-ok-bd),
        inset 0 0 0 1px var(--ao-border-faint);
}

.ao-grade-current-none {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}

.ao-grade-current-verdict {
    color: var(--ao-ok-text);
    font-size: var(--ao-fs-body);
    font-weight: 700;
    letter-spacing: 0.06em;
}
/* The grade box in its verdict's tone, like the header pill. */
.ao-grade-card.is-graded .ao-grade-current.v-confirmed_theft,
.ao-grade-card.is-graded .ao-grade-current.v-missed_theft {
    background: var(--ao-err-bg);
    box-shadow:
        inset 3px 0 0 var(--ao-err-bd),
        inset 0 0 0 1px var(--ao-border-faint);
}
.ao-grade-card.is-graded .ao-grade-current.v-uncertain {
    background: var(--ao-tint-2);
    box-shadow:
        inset 3px 0 0 var(--ao-border),
        inset 0 0 0 1px var(--ao-border-faint);
}
.ao-grade-current.v-confirmed_theft .ao-grade-current-verdict,
.ao-grade-current.v-missed_theft .ao-grade-current-verdict {
    color: var(--ao-err-fg);
}
.ao-grade-current.v-uncertain .ao-grade-current-verdict {
    color: var(--ao-fg-dim);
}

.ao-grade-current-meta,
.ao-grade-current-reason,
.ao-grade-current-subject {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}

/* Append-only ledger: this line is why the buttons below say re-grade and not
   edit, so it stays visible rather than living in a tooltip. */
.ao-grade-current-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}

/* ── the card's controls: WHO / DOING / clip quality, then the submit row ── */
.ao-grade-actions {
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 14px 16px 16px;
}

.ao-grade-mods {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 10px 22px;
}

/* WHO, beside WHAT. Deliberately SUBORDINATE to .ao-grade-verdicts: the
   verdict buttons submit, these only modify what a submit will carry, and a
   grader must never mistake a chip for the thing that saves. Hence the
   smaller chip (11px on 26px, the small-button floor; the verdicts are 32px)
   and a pressed state in the INFO tone with a tick — plainly on, and unlike
   both the accent fill a page filter wears and the verdict buttons' tones. */
/* WHO and DOING captions share one width, so both chip rows start on one
 * left edge (the queue tools' rule, in a flex row). */
.ao-grade-mods .ao-tm-chips-label {
    min-width: 42px;
}
.ao-grade-mods .ao-seg-sm .ao-seg-btn.ao-tm-chip {
    font-size: var(--ao-fs-meta);
    gap: 5px;
    min-height: 26px;
    padding: 4px 11px;
}
/* A segment of the bar (no ring, no border change): the info tint laid over
 * the segment's own surface, so a translucent tone never shows the page. */
.ao-grade-mods .ao-tm-chip[aria-pressed='true'] {
    background: linear-gradient(var(--ao-info-bg), var(--ao-info-bg)) var(--ao-surface);
    color: var(--ao-info-fg);
}
/* The tick is drawn only while pressed: a second cue that is not colour. It
 * takes part of the chip's own padding, so a press barely moves the row. */
.ao-grade-mods .ao-tm-chip .ao-ico {
    display: none;
    height: 12px;
    width: 12px;
}
.ao-grade-mods .ao-seg-sm .ao-tm-chip[aria-pressed='true'] {
    gap: 4px;
    padding: 4px 8px 4px 6px;
}
.ao-grade-mods .ao-tm-chip[aria-pressed='true'] .ao-ico {
    display: block;
    opacity: 1;
}
.ao-grade-mods .ao-tm-chip:disabled {
    cursor: default;
    opacity: 0.4;
}
/* On = unusable: a warning, so the track wears warn, not the accent. */
.ao-grade-mods .ao-grade-quality[aria-checked='true'] .ao-switch-track {
    background: var(--ao-warn);
    border-color: var(--ao-warn);
}
.ao-grade-quality .ao-switch-text {
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
}

.ao-grade-submit {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.ao-grade-reason {
    flex: 1 1 260px;
    min-height: 32px;
    min-width: 0;
    width: auto;
}

.ao-grade-verdicts {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* The verdict buttons SUBMIT, so they are the biggest targets on the card:
 * .ao-btn pills (the class is on them) at a 32px floor, told apart by glyph
 * and tone — theft is .is-danger, false positive the ok tone, uncertain the
 * neutral pill. Pinned by pill-buttons.contract.test.js (literal radius and
 * floor on this base rule). */
.ao-grade-verdict {
    border-radius: var(--ao-r-ctl);
    min-height: 32px;
    min-width: auto;
    padding: 7px 15px;
}

.ao-grade-verdict:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}

.ao-grade-verdict.v-false_positive {
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}

.ao-grade-verdict.v-false_positive:hover:not(:disabled) {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}

.ao-grade-verdict.v-missed_theft {
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-fg);
}

.ao-grade-status {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}

.ao-grade-current-subject {
    font-size: var(--ao-fs-meta);
}

/* ── empty state + pager ────────────────────────────────────────────────── */
/* margin 0: the shared .ao-empty inset would pull it 16px in from the cards'
 * edges; the empty state takes the list's width like a card would. */
.ao-grade-empty {
    align-items: center;
    border-radius: var(--ao-r-xl);
    display: flex;
    flex-direction: column;
    font-size: var(--ao-fs-body);
    gap: 10px;
    margin: 0;
    padding: 36px 20px;
}
.ao-grade-empty-ico {
    background: var(--ao-tint-2);
    border-radius: 12px;
    color: var(--ao-fg-dim);
    display: grid;
    height: 40px;
    place-items: center;
    width: 40px;
}
.ao-grade-empty-ico.is-clear {
    background: var(--ao-ok-bg);
    color: var(--ao-ok-fg);
}

.ao-grade-pager {
    align-items: center;
    display: flex;
    gap: 12px;
    justify-content: center;
    padding: 4px 0 8px;
}
/* An empty first page hides the pager (restated: display:flex above). */
.ao-grade-pager[hidden] {
    display: none;
}

.ao-grade-range {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
}

/* A phone: the media stacks over the detail, the head wraps. */
@media (max-width: 760px) {
    .ao-grade-body {
        grid-template-columns: minmax(0, 1fr);
        padding: 14px;
    }
    .ao-grade-head,
    .ao-grade-actions {
        padding-left: 14px;
        padding-right: 14px;
    }
    /* One column: each caption sits over its own chip row. */
    .ao-grade-tools {
        gap: 6px;
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-grade-toolrow + .ao-grade-toolrow > .ao-grade-toolcap {
        margin-top: var(--ao-s-2);
    }
    /* The main switch as an even 3-wide grid rather than a ragged wrap
     * (five segments do not fit one phone row; three a row do). */
    .ao-grade-filters.ao-tm-seg {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
    .ao-grade-filters.ao-tm-seg .ao-grade-filter {
        justify-content: center;
    }
    /* The grid wraps the bar into rows: each row starts without a divider,
     * and every row after the first is ruled above. */
    .ao-grade-filters.ao-tm-seg .ao-grade-filter:nth-child(3n + 1) {
        border-left: 0;
    }
    .ao-grade-filters.ao-tm-seg .ao-grade-filter:nth-child(n + 4) {
        border-top: 1px solid var(--ao-border-soft);
    }
    /* The relative time stays; the absolute stamp is in the title. */
    .ao-grade-ts {
        display: none;
    }
    /* One agreement card a row: the ring and the model name need the width. */
    .ao-stat-row.ao-grade-agreegrid {
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-grade-verdicts {
        width: 100%;
    }
    .ao-grade-verdict {
        flex: 1 1 auto;
    }
}

/* ============================================================================
 * DARK-ONLY: hide the (now inert) theme switchers. The console is graphite-only
 * as of 2026-08-12; the toggle handlers stay wired (no JS removed) but there is
 * nothing to switch to.
 * ==================================================================== */
.ao-theme-toggle,
.ao-theme-seg {
    display: none !important;
}

/* ============================================================================
 * COMMIT LEADERBOARD (overview) — a proper leaderboard, not a spreadsheet.
 * Rank medals, avatar discs, a 7-day activity bar, TODAY+7D emphasised, a TEAM
 * totals footer. All token-driven so it rides the graphite theme.
 * ==================================================================== */
.aolb {
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-lg);
    overflow: hidden;
    background: var(--ao-bg);
}
.aolb-scroll {
    overflow-x: auto;
}
/* Design system v2 (2026-09-23): in the Overview card the board runs edge to
 * edge like the card's other tables, header on the page ground. */
.ao-ov-card > .aolb-scroll {
    border-bottom: 1px solid var(--ao-border);
    border-top: 1px solid var(--ao-border);
    margin: 0 calc(var(--ao-s-4) * -1);
}
.aolb-t {
    width: 100%;
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
}
.aolb-t thead th {
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ao-fg-dim);
    text-align: right;
    padding: 9px 10px;
    white-space: nowrap;
    background: var(--ao-bg);
    border-bottom: 1px solid var(--ao-border);
}
.aolb-t thead th.who {
    text-align: left;
    padding-left: 16px;
}
.aolb-t thead th.pri {
    color: var(--ao-fg-dim);
}
.aolb-t tbody td {
    padding: 9px 10px;
    border-bottom: 1px solid var(--ao-border-soft);
    text-align: right;
    white-space: nowrap;
}
.aolb-t tbody tr:last-child td {
    border-bottom: none;
}
.aolb-t tbody tr:hover td {
    background: var(--ao-hover);
}
/* The hovered row's accent tick, as every .ao-table row has. */
.aolb-t tbody tr.aolb-row:hover > td:first-child {
    box-shadow: inset 2px 0 0 var(--ao-accent-line);
}
.aolb-t tbody td.aolb-n,
.aolb-t tbody td.aolb-last {
    font-family: var(--ao-mono);
}
/* identity cell: rank medal + avatar + name/sub. The cell stays a real
 * table cell (a display:flex <td> drops out of the row, so its rule, hover
 * fill and accent tick stepped 1px off the rest); the flex row is the
 * .aolb-id-in div inside it. */
.aolb-t tbody td.aolb-id {
    text-align: left;
    padding-left: 16px !important;
}
.aolb-id-in {
    display: flex;
    align-items: center;
    gap: 11px;
}
.aolb-rank {
    flex: none;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: var(--ao-fs-meta);
    font-weight: 700;
    color: var(--ao-fg-mute);
}
.aolb-rank.medal {
    color: var(--ao-bg);
}
.aolb-rank.g {
    background: var(--ao-tm-gold);
}
.aolb-rank.s {
    background: var(--ao-tm-silver);
}
.aolb-rank.b {
    background: var(--ao-tm-bronze);
}
.aolb-av {
    flex: none;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: var(--ao-fs-body);
    font-weight: 700;
    color: #fff;
    letter-spacing: 0.02em;
}
.aolb-who {
    min-width: 0;
}
.aolb-name {
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    color: var(--ao-fg);
}
.aolb-name.lead {
    font-weight: 800;
}
.aolb-sub {
    font-size: var(--ao-fs-meta);
    color: var(--ao-fg-mute);
    margin-top: 1px;
}
.aolb-chip {
    font-size: var(--ao-fs-label);
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--ao-fg-mute);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-sm);
    padding: 1px 5px;
    margin-left: 7px;
    vertical-align: 1px;
}
.aolb-row.bot .aolb-name,
.aolb-row.bot .aolb-av {
    opacity: 0.5;
}
/* number cells */
.aolb-n {
    font-size: var(--ao-fs-strong);
    color: var(--ao-fg-mute);
}
.aolb-n.pri {
    color: var(--ao-fg);
    font-weight: 700;
    font-size: var(--ao-fs-strong);
}
.aolb-n.zero {
    opacity: 0.32;
}
/* 7-day activity bar */
.aolb-barcell {
    width: 128px;
    padding-right: 16px !important;
}
.aolb-bar {
    position: relative;
    height: 6px;
    border-radius: var(--ao-r-bar);
    background: var(--ao-tint-2);
    overflow: hidden;
}
.aolb-bar > i {
    position: absolute;
    inset: 0 auto 0 0;
    border-radius: inherit;
    background: linear-gradient(90deg, var(--ao-k-5), var(--ao-k-2));
    opacity: 0.8;
}
.aolb-bar.lead > i {
    background: linear-gradient(90deg, var(--ao-k-1), var(--ao-k-5));
    opacity: 1;
}
.aolb-last {
    font-size: var(--ao-fs-meta);
    color: var(--ao-fg-mute);
    width: 52px;
}
/* team totals footer row */
.aolb-team td {
    border-top: 2px solid var(--ao-border);
    background: var(--ao-tint);
    padding-top: 11px;
    padding-bottom: 11px;
}
.aolb-team .aolb-id {
    padding-left: 16px !important;
}
.aolb-tlabel {
    font-size: var(--ao-fs-meta);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ao-fg-mute);
}
.aolb-team .aolb-n {
    color: var(--ao-fg);
    font-weight: 700;
}
.aolb-foot {
    padding: 11px 0 0;
    font-size: var(--ao-fs-meta);
    line-height: 1.55;
    color: var(--ao-fg-mute);
    border-top: 1px solid var(--ao-tint-line);
}
.aolb-foot b {
    color: var(--ao-fg-dim);
    font-weight: 600;
}
/* warming / loading state */
.aolb-loading {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 22px 16px;
    font-size: var(--ao-fs-body);
    color: var(--ao-fg-mute);
}
.aolb-spin {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid var(--ao-border-soft);
    border-top-color: var(--ao-accent-line);
    animation: aolb-spin 0.8s linear infinite;
}
@keyframes aolb-spin {
    to {
        transform: rotate(360deg);
    }
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .aolb-spin {
        animation: none;
    }
}
/* Phone: the two emphasised windows (TODAY, 7D) and LAST, so the board fits
 * its card instead of scrolling sideways; #/team has every window. */
@media (max-width: 760px) {
    .aolb-t th:nth-child(3),
    .aolb-t td:nth-child(3),
    .aolb-t th:nth-child(5),
    .aolb-t td:nth-child(5),
    .aolb-t th:nth-child(6),
    .aolb-t td:nth-child(6),
    .aolb-t th:nth-child(7),
    .aolb-t td:nth-child(7),
    .aolb-t th:nth-child(8),
    .aolb-t td:nth-child(8) {
        display: none;
    }
    .aolb-t thead th,
    .aolb-t tbody td {
        padding-left: 6px;
        padding-right: 6px;
    }
    .aolb-t tbody td.aolb-id {
        white-space: normal;
    }
    .aolb-t tbody td:last-child,
    .aolb-t thead th:last-child {
        padding-right: 16px;
    }
    .aolb-id-in {
        gap: 8px;
    }
    .aolb-last {
        width: auto;
    }
    /* A long bot login and its BOT chip may part lines. */
    .aolb-name {
        align-items: center;
        display: flex;
        flex-wrap: wrap;
        gap: 2px 6px;
    }
    .aolb-name > .aolb-chip {
        margin-left: 0;
    }
    .aolb-t tbody td.aolb-id,
    .aolb-t thead th.who,
    .aolb-team .aolb-id {
        padding-left: 12px !important;
    }
}

/* ============================================================================
 * 2026-08-12 refresh — global motion polish (cosmetic, reduced-motion aware).
 * Interactive surfaces ease their hover/focus feedback instead of snapping, so
 * the console feels dynamic without changing any layout or behaviour.
 * ==================================================================== */
.ao-btn,
.ao-btn-sm,
.ao-tab,
.ao-chip,
.ao-pill,
.ao-theme-seg-btn,
.ao-table tbody tr td {
    /* transform + box-shadow listed too (2026-09-23): this rule comes after
     * the press-feedback one above and replaces its list, which silently
     * dropped the 1px press ease and snapped the v2 pill's elevation. */
    transition:
        background var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease),
        border-color var(--ao-fast) var(--ao-ease),
        box-shadow var(--ao-fast) var(--ao-ease),
        transform var(--ao-fast) var(--ao-ease),
        opacity var(--ao-fast) var(--ao-ease);
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-btn,
    :where(html:not([data-motion='full'])) .ao-btn-sm,
    :where(html:not([data-motion='full'])) .ao-tab,
    :where(html:not([data-motion='full'])) .ao-chip,
    :where(html:not([data-motion='full'])) .ao-pill,
    :where(html:not([data-motion='full'])) .ao-theme-seg-btn,
    :where(html:not([data-motion='full'])) .ao-table tbody tr td {
        transition: none;
    }
}

/* ============================================================================
 * 2026-08-13 refresh (4) — surface consistency. Brings the last flat / green-
 * focus stragglers into the graphite language established by refresh (1)-(3):
 * the shared 7-10px radius vocabulary and a VISIBLE active-tab state. The
 * agent-detail tab bar toggles .is-active in JS (paintTab, argus-ops.js) but
 * nothing ever styled it, so the selected tab looked identical to the rest.
 * Cosmetic only — no layout or behaviour change. The tab/chip base styles are
 * set inline in JS and set NO radius, so the radius rules here apply cleanly;
 * the !important on .ao-tab.is-active / :hover exists solely to win over that
 * inline base (background/border/color), which is higher specificity than a
 * class rule. ========================================================= */

/* Rounded-surface consistency for the last flat containers. */
.ao-key-card {
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
}
.ao-tag {
    border-radius: var(--ao-r-tag);
}
/* (.ao-empty / .ao-error took --ao-r-lg here; design system v2 moved both to
 * --ao-r-xl in their own rule, and a second radius here would override it.) */

/* Tabs + chips join the rounded vocabulary (inline base sets no radius). */
.ao-tab {
    border-radius: var(--ao-r-md);
}
.ao-chip {
    border-radius: var(--ao-r-ctl);
}

/* The selected tab finally reads as selected — same accent fill the active
 * chip already uses, so the two controls speak one visual language. */
.ao-tab.is-active {
    background: var(--ao-accent) !important;
    border-color: var(--ao-accent) !important;
    color: var(--ao-accent-fg) !important;
    font-weight: 600;
}
.ao-tab:not(.is-active):hover {
    border-color: var(--ao-accent-line) !important;
}

/* ============================ SUPPORT (#/support) ============================
   Inbound requests from people, not conditions the platform noticed about
   itself. The wait time leads every row because the failure mode here is a slow
   reply, not a wrong one. See the SUPPORT tab block in argus-ops.js.

   Design system v2 (2026-09-23, the Team page's family): the headline is a
   KPI strip whose first (hero) card carries the old .ao-sup-summary-big number;
   each group is an aoSection with a count pill; each request is a Team card
   with a wait-time tile and a status rail; the buttons are .ao-btn pills with
   icons. Tokens only. */

.ao-sup-panel {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-5);
    min-width: 0;
}
/* The hero card spans two tracks on a wide screen (the JS sets six columns for
   its five cards). Never on a phone: a span on a one-track grid would add an
   implicit column and push the page sideways. */
@media (min-width: 900px) {
    .ao-sup-summary .ao-stat.is-hero {
        grid-column: span 2;
    }
    /* The wide hero in two halves: the count and who has it on the left,
       new requests per day (a real series off first_seen) on the right. */
    .ao-sup-summary .ao-stat.is-hero {
        align-content: start;
        column-gap: 22px;
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        grid-template-rows: auto auto 1fr;
    }
    .ao-sup-summary .ao-stat.is-hero > .ao-stat-head {
        grid-column: 1;
        grid-row: 1;
    }
    .ao-sup-summary .ao-stat.is-hero > .ao-stat-value {
        grid-column: 1;
        grid-row: 2;
    }
    .ao-sup-summary .ao-stat.is-hero > .ao-stat-sub {
        grid-column: 1;
        grid-row: 3;
    }
    .ao-sup-summary .ao-stat.is-hero > .ao-stat-foot {
        grid-column: 2;
        grid-row: 1;
        justify-content: flex-end;
    }
    .ao-sup-summary div.ao-stat.is-hero > .ao-stat-spark {
        align-self: end;
        grid-column: 2;
        grid-row: 2 / span 2;
        height: 72px;
    }
}
/* Narrower: the hero takes its own row (1 / -1 spans every track at any
   count, so it cannot add one), and the four under it pair up. */
@media (max-width: 899px) {
    .ao-sup-summary div.ao-stat-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .ao-sup-summary .ao-stat.is-hero {
        grid-column: 1 / -1;
    }
}
/* Only coloured when someone is actually waiting: an all-clear must not use the
   same visual weight as work, or the page reads as busy when it is empty. */
.ao-sup-summary-big.is-live {
    color: var(--ao-err-fg);
}
.ao-sup-summary-big.is-live.is-counting::after {
    color: var(--ao-err-fg);
}
/* "All caught up" is words, not a number: a size that fits the card. */
.ao-sup-summary .ao-stat.is-hero .ao-stat-num.ao-sup-summary-big:not(.is-live) {
    color: var(--ao-ok-fg);
    font-size: clamp(20px, 10cqi, 28px);
    letter-spacing: -0.02em;
}
.ao-sup-summary-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    letter-spacing: 0.01em;
}
/* The hero's new-requests spark (its inline height is cleared in JS). */
.ao-sup-summary .ao-stat.is-hero > .ao-stat-spark {
    height: 40px;
}
/* Unclaimed (red: nobody has it) vs claimed, as one split meter. */
.ao-sup-split.ao-tm-stack {
    border-radius: var(--ao-r-bar);
    height: 8px;
    margin-top: 12px;
    max-width: 320px;
}
.ao-sup-split .ao-tm-stack-seg[data-key='unclaimed'] {
    background: var(--ao-err-strong);
}
.ao-sup-split .ao-tm-stack-seg[data-key='claimed'] {
    background: var(--ao-k-2);
}

.ao-sup-group {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}
.ao-sup-group > .ao-sup-group-head {
    margin-bottom: 2px;
}
/* The titles are written NEEDS A REPLY / CLAIMED / REPLIED in the source;
   at section-title size they read as sentence case, like every aoSection. */
.ao-sup-group-title {
    text-transform: lowercase;
}
.ao-sup-group-title::first-letter {
    text-transform: uppercase;
}
.ao-sup-group-count {
    align-self: center;
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    line-height: 1.5;
    min-width: 24px;
    padding: 0 8px;
    text-align: center;
}
.ao-sup-group.is-waiting .ao-sup-group-count {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-sup-empty {
    background: var(--ao-tint);
    border: 1px dashed var(--ao-border-soft);
    border-radius: 12px;
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    padding: 12px 14px;
}

/* Owner sub-grouping inside CLAIMED. Reads as a quiet header, not a second
   section heading — the group heading above it already did that job. */
.ao-sup-owner {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.ao-sup-owner + .ao-sup-owner {
    margin-top: 6px;
}
.ao-sup-owner-head {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.1em;
    padding: 2px 2px 0;
}

/* Who owns this. Once rows belong to people this is the most important field on
   the row, so unlike .ao-sup-who it is not muted into the background. */
.ao-sup-ownerline {
    align-items: center;
    display: flex;
    gap: 8px;
    margin-top: 10px;
}
.ao-sup-assigned {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    font-weight: 500;
}
.ao-sup-who {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}

/* The server capped the read and drops the OLDEST first. This has to out-shout
   the summary above it, because the summary is the part that is now wrong. */
.ao-sup-truncated {
    align-items: flex-start;
    background: var(--ao-warn-bg);
    border: 1px solid var(--ao-warn-bd);
    border-radius: 12px;
    color: var(--ao-warn-fg);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 10px;
    line-height: 1.5;
    padding: 12px 14px;
}
.ao-sup-truncated .ao-ico {
    flex: none;
    margin-top: 2px;
}

/* A request: a Team card with a status rail, a wait-time tile and the person;
   its actions are the desk footer (a hairline and a left-aligned row of
   pills), the same as an Alerting or Tickets row. */
.ao-sup-row {
    --ao-sup-rail: var(--ao-border);
    align-items: start;
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    display: grid;
    gap: 18px;
    grid-template-columns: 96px minmax(0, 1fr) minmax(220px, 260px);
    padding: 16px 18px 14px 20px;
    position: relative;
}
/* The right-hand meta column: when it arrived, which form sent it, and
   whether anyone has it — label over value, a hairline to its left. */
.ao-sup-meta {
    border-left: 1px solid var(--ao-tint-line);
    display: flex;
    flex-direction: column;
    gap: 7px;
    margin: 0;
    min-width: 0;
    padding: 3px 0 3px 16px;
}
.ao-sup-meta-item {
    align-items: baseline;
    display: grid;
    gap: 10px;
    grid-template-columns: 68px minmax(0, 1fr);
    min-width: 0;
}
.ao-sup-meta-k {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-sup-meta-v {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    margin: 0;
    overflow-wrap: anywhere;
}
/* A narrow desk: the meta column moves under the request (a wrapped line),
   so the message keeps its width. */
@media (max-width: 1100px) {
    .ao-sup-row {
        grid-template-columns: 96px minmax(0, 1fr);
    }
    .ao-sup-meta {
        border-left: 0;
        border-top: 1px solid var(--ao-tint-line);
        flex-direction: row;
        flex-wrap: wrap;
        gap: 8px 22px;
        grid-column: 2;
        padding: 10px 0 0;
    }
    .ao-sup-meta-item {
        display: flex;
        gap: 8px;
    }
}
.ao-sup-row::before {
    background: var(--ao-sup-rail);
    border-radius: 0 3px 3px 0;
    bottom: 16px;
    box-shadow: 0 0 10px color-mix(in srgb, var(--ao-sup-rail) 50%, transparent);
    content: '';
    left: 0;
    position: absolute;
    top: 16px;
    width: 3px;
}
.ao-sup-row.is-waiting {
    --ao-sup-rail: var(--ao-k-5);
}
.ao-sup-row.is-claimed {
    --ao-sup-rail: var(--ao-k-2);
}
/* Waited longer than a day with nobody answering. */
.ao-sup-row.is-stale {
    --ao-sup-rail: var(--ao-err-strong);
    background:
        radial-gradient(120% 110% at 0% 0%, var(--ao-err-soft), transparent 65%),
        linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-color: var(--ao-err-border);
}
/* A receipt: one step quieter than work still open. */
.ao-sup-row.is-done {
    --ao-sup-rail: var(--ao-ok);
    background: var(--ao-tint);
    box-shadow: none;
}

.ao-sup-when {
    background: var(--ao-tint);
    border-radius: 12px;
    box-shadow: inset 0 0 0 1px var(--ao-tint-line);
    padding: 10px 6px 8px;
    text-align: center;
}
.ao-sup-waited {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-title);
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.2;
    white-space: nowrap;
}
.ao-sup-row.is-stale .ao-sup-when {
    background: var(--ao-err-bg);
    box-shadow: inset 0 0 0 1px var(--ao-err-bd);
}
.ao-sup-row.is-stale .ao-sup-waited {
    color: var(--ao-err-fg);
}
.ao-sup-waited-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    margin-top: 2px;
    text-transform: uppercase;
}

.ao-sup-body {
    min-width: 0;
}
.ao-sup-top {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 4px;
}
.ao-sup-chip {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    line-height: 1.5;
    padding: 1px 8px;
}
.ao-sup-demo {
    background: color-mix(in srgb, var(--ao-k-4) 14%, transparent);
    border-color: color-mix(in srgb, var(--ao-k-4) 45%, transparent);
    color: var(--ao-k-4);
}
.ao-sup-help {
    background: color-mix(in srgb, var(--ao-k-5) 14%, transparent);
    border-color: color-mix(in srgb, var(--ao-k-5) 45%, transparent);
    color: var(--ao-k-5);
}
.ao-sup-name {
    color: var(--ao-fg);
    font-size: 14px;
    font-weight: 600;
}
.ao-sup-co {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
}
.ao-sup-mail {
    align-items: center;
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-body);
    gap: 6px;
    max-width: 100%;
    overflow-wrap: anywhere;
    text-decoration: none;
}
.ao-sup-mail:hover {
    color: var(--ao-fg);
    text-decoration: underline;
    text-decoration-color: var(--ao-accent-line);
    text-underline-offset: 3px;
}
/* A dead end should look like one rather than inviting a hunt for a reply path
   that does not exist. */
.ao-sup-noemail {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    font-style: italic;
}
.ao-sup-snippet {
    background: var(--ao-tint);
    border-left: 2px solid var(--ao-tint-strong);
    border-radius: 0 10px 10px 0;
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.55;
    margin-top: 10px;
    padding: 8px 12px;
}

.ao-sup-actions {
    align-items: center;
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    grid-column: 1 / -1;
    margin-top: -6px;
    padding-top: 10px;
}
.ao-sup-actions .ao-btn {
    white-space: nowrap;
}

/* REPLIED: the receipts as a compact table (nothing to press). */
.ao-sup-dt-who {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}
.ao-sup-done-table .ao-sup-name {
    font-size: var(--ao-fs-body);
}
.ao-sup-dt-mail {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    overflow: hidden;
    text-decoration: none;
    text-overflow: ellipsis;
}
.ao-sup-dt-mail:hover {
    color: var(--ao-fg);
    text-decoration: underline;
    text-decoration-color: var(--ao-accent-line);
    text-underline-offset: 3px;
}
.ao-sup-dt-by {
    align-items: center;
    color: var(--ao-fg-dim);
    display: inline-flex;
    gap: 8px;
}
.ao-sup-done-table tbody tr > td:first-child {
    box-shadow: inset 2px 0 0 var(--ao-ok);
}

@media (max-width: 760px) {
    .ao-sup-row {
        gap: 12px;
        grid-template-columns: 1fr;
        padding: 14px 14px 14px 18px;
    }
    .ao-sup-when {
        align-items: baseline;
        display: flex;
        gap: 8px;
        justify-self: start;
        padding: 6px 10px;
        text-align: left;
    }
    .ao-sup-waited-sub {
        margin-top: 0;
    }
    /* The meta line spans the one-column card. */
    .ao-sup-meta {
        grid-column: 1;
    }
    .ao-sup-actions {
        margin-top: 0;
    }
    /* A phone keeps who, what kind and how long the reply took. */
    .ao-sup-dt-mail,
    .ao-sup-done-table th:nth-child(2),
    .ao-sup-done-table td:nth-child(2),
    .ao-sup-done-table th:nth-child(5),
    .ao-sup-done-table td:nth-child(5),
    .ao-sup-done-table th:nth-child(6),
    .ao-sup-done-table td:nth-child(6) {
        display: none;
    }
}
/* ═══════════════════════════════════════════════════════════════════════════
 * OPS PRIMITIVES — Phase 1 of docs/plans/ops-console-restructure.md
 *
 * The shared identity / state / definition vocabulary. Nothing on any page
 * uses these classes yet; the pages adopt them in Phase 2 onward. Every colour
 * comes from a --ao-* token — never a raw hex in a component rule.
 * ══════════════════════════════════════════════════════════════════════════ */

/* ── aoIdentity ─────────────────────────────────────────────────────────────
 * Human name reads as the subject; the machine id is demoted to a dim,
 * monospace, smaller subline — present and copyable, never the headline. */
.ao-identity {
    display: inline-flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
    vertical-align: top;
}
.ao-identity-name {
    color: var(--ao-fg);
    font-weight: 600;
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The name we could NOT resolve — it is the raw id standing in. Dimmer and
 * un-bolded so a directory that never loaded is visible as such rather than
 * silently passing itself off as a store name. */
.ao-identity-name.is-unresolved {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-weight: 400;
    font-size: var(--ao-fs-body);
}
.ao-identity-link {
    color: inherit;
    text-decoration: none;
}
.ao-identity-link:hover .ao-identity-name {
    color: var(--ao-accent-line);
    text-decoration: underline;
}
.ao-identity-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.2;
}
.ao-identity-id {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.01em;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-identity-idchip {
    align-self: flex-start;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    cursor: pointer;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.04em;
    padding: 1px 4px;
}
.ao-identity-idchip:hover {
    border-color: var(--ao-border);
    color: var(--ao-fg-dim);
}
.ao-identity-idchip.is-revealed {
    letter-spacing: 0.01em;
}
.ao-identity.is-clickable {
    cursor: pointer;
}

/* ── aoState ────────────────────────────────────────────────────────────────
 * ⛔ `is-unknown` NEVER borrows the OK palette. It is deliberately the neutral
 * grey with a dashed edge: legible as "we have no reading", distinguishable at
 * a glance from both healthy and failing, and impossible to mistake for either.
 * A failed read rendering as health is this platform's most expensive shape. */
.ao-state {
    align-items: center;
    display: inline-flex;
    gap: 5px;
    vertical-align: middle;
}
.ao-state-pill {
    border: 1px solid transparent;
    border-radius: var(--ao-r-tag);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.03em;
    line-height: 1.6;
    padding: 1px 8px;
    text-transform: uppercase;
    white-space: nowrap;
}
.ao-state-pill.is-ok {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-state-pill.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-state-pill.is-err {
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-strong);
}
.ao-state-pill.is-unknown {
    background: transparent;
    border-color: var(--ao-border);
    border-style: dashed;
    color: var(--ao-fg-mute);
}

.ao-state-dot {
    border-radius: 50%;
    height: 8px;
    width: 8px;
}
.ao-state-dot.is-ok {
    background: var(--ao-ok);
}
.ao-state-dot.is-warn {
    background: var(--ao-warn);
}
.ao-state-dot.is-err {
    background: var(--ao-err-strong);
}
/* Hollow, not filled — an unknown state must not read as a lit indicator. */
.ao-state-dot.is-unknown {
    background: transparent;
    box-shadow: inset 0 0 0 1.5px var(--ao-fg-mute);
}

.ao-state-stripe {
    border-radius: var(--ao-r-sm);
    height: 100%;
    min-height: 16px;
    width: 3px;
}
.ao-state-stripe.is-ok {
    background: var(--ao-ok);
}
.ao-state-stripe.is-warn {
    background: var(--ao-warn);
}
.ao-state-stripe.is-err {
    background: var(--ao-err-strong);
}
.ao-state-stripe.is-unknown {
    background: repeating-linear-gradient(135deg, var(--ao-fg-mute) 0 2px, transparent 2px 4px);
}

.ao-state-bar {
    background: var(--ao-tint);
    border-radius: var(--ao-r-bar);
    display: inline-block;
    height: 6px;
    min-width: 64px;
    overflow: hidden;
    position: relative;
}
.ao-state-bar-fill {
    display: block;
    height: 100%;
    transition: width 180ms ease;
}
.ao-state-bar.is-ok .ao-state-bar-fill {
    background: var(--ao-ok);
}
.ao-state-bar.is-warn .ao-state-bar-fill {
    background: var(--ao-warn);
}
.ao-state-bar.is-err .ao-state-bar-fill {
    background: var(--ao-err-strong);
}
/* No fill at all when the percentage was never measured — an empty track and
 * a 0% track must not look the same. The hatch says "not measured". */
.ao-state-bar.is-unmeasured {
    background: repeating-linear-gradient(135deg, var(--ao-border-faint) 0 3px, transparent 3px 6px);
}
.ao-state-bar-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    margin-left: 6px;
}
/* A KPI card's meter (aoStat `pct`) is the card's foot: a full-width track
 * pinned to the bottom, filled in the card's own hue unless a real state
 * (ok / warn / err) colours it. Pages may still tune height or fill. */
.ao-stat > .ao-state-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: block;
    height: 5px;
    margin-top: auto;
    min-width: 0;
    width: 100%;
}
.ao-stat > .ao-state-bar .ao-state-bar-fill {
    border-radius: inherit;
}
.ao-stat > .ao-state-bar.is-unknown .ao-state-bar-fill {
    background: var(--ao-stat-accent, var(--ao-fg-dim));
}
.ao-stat > .ao-state-bar .ao-state-bar-label:empty {
    display: none;
}

/* ── aoInfo ─────────────────────────────────────────────────────────────────
 * A quiet dot that only gets loud on hover/focus. It must not compete with the
 * number it explains. */
.ao-info {
    background: none;
    border: 0;
    color: var(--ao-fg-mute);
    cursor: help;
    font-size: var(--ao-fs-meta);
    line-height: 1;
    opacity: 0.55;
    padding: 0 2px;
    transition:
        opacity 120ms ease,
        color 120ms ease;
}
.ao-info:hover,
.ao-info:focus-visible {
    color: var(--ao-accent-line);
    opacity: 1;
}
.ao-info:focus-visible {
    border-radius: var(--ao-r-sm);
    outline: 2px solid var(--ao-focus);
    outline-offset: 1px;
}
.ao-info.is-inline {
    margin-left: 3px;
}
.ao-info-pop {
    background: var(--ao-surface-2);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-md);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    left: 0;
    line-height: 1.45;
    max-width: 320px;
    padding: 9px 11px;
    position: absolute;
    top: 100%;
    z-index: 60;
}
.ao-info-pop.is-right {
    left: auto;
    right: 0;
}
.ao-info-term {
    color: var(--ao-fg);
    font-weight: 700;
    margin-bottom: 3px;
}
.ao-info-good {
    color: var(--ao-ok-text);
    margin-top: 5px;
}
/* The abstain line is the one an operator most needs and least expects, so it
 * is given the warn colour rather than being buried in body grey. */
.ao-info-abstain {
    color: var(--ao-warn-text);
    margin-top: 5px;
}
.ao-info-source {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    margin-top: 6px;
    word-break: break-word;
}

/* ── aoStat — the KPI card (design system v2, 2026-09-23) ───────────────────
 * The Team KPI card (.ao-tm-kpi) for every tab: 16px radius, a top-lit
 * gradient, a hairline inset highlight over elev-1, an accent icon tile, a big
 * mono number, and on hover a 2px lift + the rotating conic ring. The BORDER
 * never changes on hover — the lift and the ring are the whole signal (the
 * Team rule; the v1 card swapped its border colour instead).
 *
 * --ao-stat-accent is set inline by aoStat from a TOKEN name (never a raw
 * colour) and tints the icon tile, the sparkline and the ring — never text. */
/* ⛔ NO HOLES. auto-fill with a bare 168px minimum split outreach's eleven
 * into 8 + 3 (five empty slots) and left a slot open after the mailbox
 * panel's seven. aoStat.row sets --ao-stat-cols to the column count that
 * spreads its cards over the fewest, most even rows (11 → 6 + 5, 7 → 7);
 * the track minimum is that share of the row, never below 168px, so a
 * narrow screen still wraps, and auto-fit stretches what is left over.
 * The -1px keeps sub-pixel rounding from dropping the last column. */
.ao-stat-row {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(
        auto-fit,
        minmax(
            max(168px, calc((100% - (var(--ao-stat-cols, 6) - 1) * var(--ao-s-3)) / var(--ao-stat-cols, 6) - 1px)),
            1fr
        )
    );
}
/* A long strip (outreach's eleven) in small cards, so it does not push the
 * page's real content a screen down. */
.ao-stat-row.is-sm {
    gap: var(--ao-s-2);
    grid-template-columns: repeat(
        auto-fit,
        minmax(
            max(132px, calc((100% - (var(--ao-stat-cols, 8) - 1) * var(--ao-s-2)) / var(--ao-stat-cols, 8) - 1px)),
            1fr
        )
    );
}
/* The fallback hue is a KPI blue, never the brand rose: a card with no
 * accent used to be a grey slab with a pink ring on hover. aoStat.row gives
 * every card an accent anyway; this covers a lone card. */
.ao-stat {
    --ao-stat-ring: var(--ao-stat-accent, var(--ao-k-5));
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    color: var(--ao-fg);
    display: flex;
    flex: 1 1 150px;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
    padding: 14px 16px 12px;
    position: relative;
    transition:
        transform var(--ao-base) var(--ao-ease),
        box-shadow var(--ao-base) var(--ao-ease);
}
/* Inside a row the card's width comes from the grid track, never from its
 * content — so it can be a size container and the number can scale with its
 * own card (cqi) instead of overflowing a narrow one. ⛔ Only here: a size
 * container whose width depends on its content (a lone card in a flex row)
 * collapses to zero. */
.ao-stat-row > .ao-stat {
    container-type: inline-size;
}
/* 84px: a small card is still a card (the Team one, shorter), not a chip. */
.ao-stat.is-sm {
    gap: 6px;
    min-height: 84px;
    padding: 12px 14px;
}
.ao-stat.is-hero {
    padding: 18px 20px 16px;
}
/* A card inside a card (the mailbox panel's stat cards) is a panel of its
 * parent: one radius step down and no second shadow, so a rounded tile does
 * not float over a rounded box. */
.ao-card .ao-stat {
    border-radius: var(--ao-r-lg);
    box-shadow: none;
}
/* The 1px conic ring: a gradient box masked down to its own padding ring, as
 * on .ao-tm-card.has-ring (the angle is the Team page's @property; unsupported
 * browsers simply hold the ring still). */
.ao-stat::before {
    background: conic-gradient(
        from var(--ao-tm-angle),
        transparent 0deg,
        var(--ao-stat-ring) 70deg,
        transparent 150deg,
        transparent 190deg,
        var(--ao-stat-ring) 260deg,
        transparent 340deg
    );
    border-radius: inherit;
    content: '';
    inset: -1px;
    -webkit-mask:
        linear-gradient(black 0 0) content-box,
        linear-gradient(black 0 0);
    -webkit-mask-composite: xor;
    mask:
        linear-gradient(black 0 0) content-box,
        linear-gradient(black 0 0);
    mask-composite: exclude;
    opacity: 0;
    padding: 1px;
    pointer-events: none;
    position: absolute;
    transition: opacity var(--ao-slow) var(--ao-ease);
}
/* z-index: a hovered card's ⓘ popover must sit above its neighbours. */
.ao-stat:hover,
.ao-stat:focus-visible {
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-2);
    transform: translateY(-2px);
    z-index: 2;
}
.ao-stat:focus-within {
    z-index: 2;
}
.ao-stat:hover::before,
.ao-stat:focus-visible::before {
    animation: ao-tm-spin 5s linear infinite;
    opacity: 1;
}
.ao-stat.is-clickable {
    cursor: pointer;
}
.ao-stat.is-clickable:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-stat.is-active {
    border-color: var(--ao-accent-line);
    box-shadow:
        0 0 0 1px var(--ao-accent-line),
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
}
.ao-stat-head {
    align-items: center;
    display: flex;
    gap: 10px;
    min-width: 0;
}
/* The icon tile: the accent at 14% with a 24% hairline, as .ao-tm-ico-tile. */
.ao-stat-ico {
    background: color-mix(in srgb, var(--ao-stat-accent, var(--ao-fg-mute)) 14%, transparent);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ao-stat-accent, var(--ao-fg-mute)) 24%, transparent);
    color: var(--ao-stat-accent, var(--ao-fg-dim));
    display: grid;
    flex: none;
    height: 30px;
    place-items: center;
    width: 30px;
}
.ao-stat.is-sm .ao-stat-ico {
    border-radius: 7px;
    height: 24px;
    width: 24px;
}
/* Sentence case in --ao-fg-dim, like the Team card label. Labels written in
 * capitals in the source stay capitals (decision D2 — CSS cannot lower them
 * without breaking the tests that read them). */
.ao-stat-label {
    align-items: center;
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-meta);
    font-weight: 500;
    gap: 2px;
    letter-spacing: 0.02em;
    min-width: 0;
    overflow-wrap: break-word;
    position: relative;
}
.ao-stat.is-sm .ao-stat-label {
    font-size: var(--ao-fs-label);
}
.ao-stat-value {
    align-items: baseline;
    color: var(--ao-fg);
    display: flex;
    flex-wrap: wrap;
    font-variant-numeric: tabular-nums;
    gap: 0 6px;
    line-height: 1.05;
    margin-top: 4px;
    min-width: 0;
}
.ao-stat.is-sm .ao-stat-value {
    margin-top: 2px;
}
/* Mono comes from the MONO rule at the top (#argus-ops-root .ao-stat-num).
 * The fixed sizes are for a card outside a row; inside one (a size
 * container) the number scales with its card. */
.ao-stat-num {
    font-size: 28px;
    font-weight: 600;
    letter-spacing: -0.04em;
    position: relative;
    white-space: nowrap;
}
/* The Team KPI number's own formula (.ao-tm-kpi-num). The small size stays
 * a headline number too — at 15-20px it read as a chip's label. */
.ao-stat-row > .ao-stat .ao-stat-num {
    font-size: clamp(22px, 21cqi, 34px);
}
.ao-stat.is-sm .ao-stat-num,
.ao-stat-row > .ao-stat.is-sm .ao-stat-num {
    font-size: clamp(20px, 18cqi, 26px);
}
.ao-stat.is-hero .ao-stat-num,
.ao-stat-row > .ao-stat.is-hero .ao-stat-num {
    font-size: clamp(24px, 24cqi, 40px);
}
/* ⛔ THE COUNT-UP IS PAINT, NOT TEXT. aoCountUp (visual mode) writes the
 * FINAL number as the node's text before anything else and never touches it
 * again; while .is-counting is set the text goes transparent and the rolling
 * frame is drawn from [data-count] on top of it. Tests, screen readers and a
 * copy all read the real value at every instant, and the box is already the
 * final number's width, so nothing reflows as it climbs. */
.ao-stat-num.is-counting {
    color: transparent;
}
.ao-stat-num.is-counting::after {
    color: var(--ao-fg);
    content: attr(data-count);
    left: 0;
    position: absolute;
    top: 0;
}
.ao-stat-unit {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
/* A value that is a word (Done, Ready, Online, Armed, FAIL): aoStat tags it
 * .is-word and every page sets it in the sans face, so it does not read as a
 * code. The id-scoped selector outranks the MONO rule at the top. */
#argus-ops-root .ao-stat-num.is-word {
    font-family: var(--ao-font-sans);
    letter-spacing: -0.02em;
}
/* An em dash for an unmeasured metric, dimmed so it never reads as a value. */
.ao-stat-value.is-unmeasured .ao-stat-num {
    color: var(--ao-fg-mute);
    font-weight: 400;
}
.ao-stat-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    min-width: 0;
    overflow-wrap: break-word;
}
.ao-stat-foot {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 8px;
}
.ao-stat-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}
.ao-stat-delta {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
}
.ao-stat > .ao-state-pill {
    align-self: flex-start;
}
.ao-stat-spark {
    color: var(--ao-stat-accent, var(--ao-fg-dim));
    margin-top: auto;
    padding-top: 6px;
}
/* A delta on a metric where DOWN is good (errors, bounces, open alerts —
 * aoStat's `better:'down'`): the arrow still says which way it moved, the
 * colour says whether that was good. A rising failure count is never green. */
.ao-tm-delta.is-up.is-inverse {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-tm-delta.is-down.is-inverse {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}

/* Reduced motion: the card holds still (no lift, no spinning ring — the ring
 * shows, static, so hover still reads) and aoCountUp already skips the climb.
 * Entries for the v2 primitives live in EXISTING blocks like this one, never
 * in a new block at the end of the file (the Team profile test reads the
 * last). */
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-state-bar-fill {
        transition: none;
    }
    /* The phone layout's drawer appears in place instead of sliding. */
    :where(html:not([data-motion='full'])) .ao-rail {
        transition: none;
    }
    :where(html:not([data-motion='full'])) .ao-stat,
    :where(html:not([data-motion='full'])) .ao-stat::before {
        transition: none;
    }
    :where(html:not([data-motion='full'])) .ao-stat:hover,
    :where(html:not([data-motion='full'])) .ao-stat:focus-visible {
        transform: none;
    }
    :where(html:not([data-motion='full'])) .ao-stat:hover::before,
    :where(html:not([data-motion='full'])) .ao-stat:focus-visible::before {
        animation: none;
    }
}

/* ── aoTable / aoDisclosure — Phase 3 engine ─────────────────────────────── */
.ao-table-wrap {
    overflow-x: auto;
}
/* ⛔ A TABLE IS FRAMED (2026-09-24). Owner, on a floating list of rows: "it
 * doesn't even look like we have a table below". Every wrap that holds a
 * table (aoTable, and aoScrollWrap for the hand-built ones) is one bordered
 * block at the card radius: the header row is a tinted band ruled below
 * (.ao-table th), the rows are ruled between (--ao-border-soft), and the last
 * row gives its rule to the frame. The same frame as the portal's shared
 * table (css/kit-table.css, PR #3201), at its 12px (--ao-r-table). An empty /
 * unread wrap is not framed: those states draw their own box. The wrap clips
 * (overflow-x), so the header's corners follow the radius; the corner cells
 * round too, for the one wrap that lets its content overflow (the review
 * queue). Their radius is --ao-tbl-head-r, set by the wrap: a wrap whose top
 * corners are square (a table bled to a card's edges) sets it to 0, or the
 * header band keeps a rounded corner inside a square frame (a notch). */
.ao-table-wrap:has(> .ao-table) {
    --ao-tbl-head-r: calc(var(--ao-r-table) - 1px);
    background: var(--ao-surface);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-table);
}
.ao-table-wrap > .ao-table > thead > tr > th:first-child {
    border-top-left-radius: var(--ao-tbl-head-r, 0);
}
.ao-table-wrap > .ao-table > thead > tr > th:last-child {
    border-top-right-radius: var(--ao-tbl-head-r, 0);
}
.ao-table-wrap > .ao-table > tbody > tr:last-child > td {
    border-bottom: 0;
}
/* aoTable {card:true} (design system v2): the table sits in the Team card,
 * which is its frame. */
.ao-table-wrap.is-card {
    --ao-tbl-head-r: calc(var(--ao-r-xl) - 1px);
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
}
.ao-table-wrap.is-card .ao-table tbody tr:last-child > td {
    border-bottom: 0;
}
/* An empty / unread state inside the card is the card's content, not a
 * second panel drawn inside it. */
.ao-table-wrap.is-card > .ao-empty {
    background: transparent;
    border: 0;
    margin: 0;
}
/* aoTable {scrollMax}: the wrap scrolls vertically too, so the sticky header
 * finally has a scroll container that scrolls (the max-height is inline). */
.ao-table-wrap.is-scroll {
    overflow-y: auto;
}
/* col.mono: ids, hashes, timestamps. The MONO rule at the top of the file
 * gives .ao-mono its face; this only keeps the digits aligned. */
.ao-table td.ao-mono {
    font-variant-numeric: tabular-nums;
}
/* col.bar: a magnitude track under the value, as the Team leaderboard's
 * .ao-tm-r-track. The fill is a transform (--ao-fill 0..1), never a width, so
 * a repaint with new data eases instead of jumping. */
.ao-table td.has-bar {
    min-width: 96px;
}
.ao-table-barval {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-table-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: block;
    height: 4px;
    margin-top: 5px;
    overflow: hidden;
    position: relative;
}
.ao-table.is-dense .ao-table-bar {
    margin-top: 3px;
}
/* Unmeasured is hatched, never an empty track: "we could not read this" and
 * "zero" must not look the same. */
.ao-table-bar.is-unmeasured {
    background: repeating-linear-gradient(45deg, var(--ao-tint-2) 0 3px, transparent 3px 6px);
}
.ao-table-bar-fill {
    background: linear-gradient(90deg, var(--ao-accent-line), var(--ao-accent));
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
/* ⛔ "could not read" must not look like "nothing here". The dashed warn edge
 * is the same vocabulary aoState uses for is-unknown, deliberately. */
.ao-table-unread {
    border: 1px dashed var(--ao-warn-border);
    border-radius: var(--ao-r-md);
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-body);
    margin: 10px 16px;
    padding: 10px 12px;
}
.ao-table-group > td {
    background: var(--ao-ink);
    color: var(--ao-ink-fg);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.06em;
    padding: 5px 16px !important;
    position: sticky;
    text-transform: uppercase;
    top: 0;
    z-index: 2;
}
.ao-table-group-meta {
    color: var(--ao-fg-dim);
    margin-left: 8px;
    text-transform: none;
}
.ao-table-group-count {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-tag);
    float: right;
    font-variant-numeric: tabular-nums;
    padding: 0 7px;
}
/* Per-row detail. The cell opts out of the table's nowrap/ellipsis scanning
 * rules because its whole job is to hold prose, lists and log output. */
.ao-table-detail > td {
    max-width: none;
    overflow: visible;
    padding: 0;
    white-space: normal;
}
.ao-table-detail .ao-disc {
    border-left: 0;
    border-radius: 0;
    border-right: 0;
    margin: 0;
}
.ao-table-detail .ao-disc-sum {
    background: transparent;
    padding-left: 16px;
}
/* A detail row is not a data row — the table's hover highlight would suggest it
 * is clickable in the same way. */
.ao-table tr.ao-table-detail:hover td {
    background: transparent;
}
/* ⚠️ Dimmed, not hidden, and never below legibility: a stale row is still the
 * only reading we have. Whatever the row also SAYS in words stays full strength. */
.ao-table tbody tr.is-stale > td {
    opacity: 0.55;
}
.ao-table tbody tr.is-stale > td .ao-state {
    opacity: 1;
}
.ao-disc {
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    margin: 10px 16px;
    overflow: hidden;
}
.ao-disc-sum {
    align-items: center;
    background: var(--ao-surface);
    cursor: pointer;
    display: flex;
    gap: 10px;
    list-style: none;
    padding: 9px 12px;
}
.ao-disc-sum::-webkit-details-marker {
    display: none;
}
.ao-disc-sum::before {
    color: var(--ao-fg-mute);
    content: '▸';
    font-size: var(--ao-fs-label);
    transition: transform 140ms ease;
}
.ao-disc[open] > .ao-disc-sum::before {
    transform: rotate(90deg);
}
.ao-disc-sum:hover {
    background: var(--ao-hover);
}
.ao-disc-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    font-weight: 600;
}
.ao-disc-meta {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-disc-body {
    border-top: 1px solid var(--ao-border-faint);
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-disc-sum::before {
        transition: none;
    }
    :where(html:not([data-motion='full'])) .ao-table-bar-fill {
        transition: none;
    }
}

/* ── aoAttention (Phase 4) ──────────────────────────────────────────────
   The block that leads #/overview. Its whole job is to be read before
   anything else on the page, so it carries a left state stripe at full
   height and sits above the tile strip in the source order too — a
   screen-reader user meets it first for the same reason a sighted one does. */
.ao-attn {
    border: 1px solid var(--ao-border-soft);
    border-left: 3px solid var(--ao-border-soft);
    background: var(--ao-surface);
    margin: 0 0 12px;
}
.ao-attn.is-err {
    border-left-color: var(--ao-err-strong);
}
.ao-attn.is-warn {
    border-left-color: var(--ao-warn-strong);
}
.ao-attn.is-clear {
    border-left-color: var(--ao-ok);
}
/* ⛔ UNREAD and PARTIAL deliberately do NOT get the ok colour. They are the
   two states this console has historically painted green by accident. */
.ao-attn.is-unread,
.ao-attn.is-partial {
    border-left-color: var(--ao-fg-mute);
    border-left-style: dashed;
}
.ao-attn-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
}
.ao-attn-verdict {
    flex: 1 1 auto;
    min-width: 0;
}
.ao-attn-verdict-text {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    line-height: 1.4;
}
.ao-attn-count {
    color: var(--ao-fg);
    font-size: var(--ao-fs-h2);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    flex: 0 0 auto;
}
.ao-attn-unobserved {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 0 14px 10px;
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
}
.ao-attn-list {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--ao-border-faint);
}
.ao-attn-group {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 14px;
    background: var(--ao-surface-2);
    border-bottom: 1px solid var(--ao-border-faint);
}
.ao-attn-group-label {
    align-items: center;
    display: inline-flex;
    gap: 6px;
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-attn-group-count {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-variant-numeric: tabular-nums;
    margin-left: auto;
}
.ao-attn-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 14px;
    border-bottom: 1px solid var(--ao-border-faint);
}
.ao-attn-item:last-child {
    border-bottom: 0;
}
.ao-attn-item-main {
    flex: 1 1 auto;
    min-width: 0;
}
.ao-attn-item-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    line-height: 1.4;
    overflow-wrap: anywhere;
}
.ao-attn-item-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-top: 2px;
}
/* The CTA is a ghost pill (ao-btn ao-btn-sm is-ghost, design system v2):
 * this only places it. No underline — the pill's hover is its own. */
.ao-attn-cta {
    align-self: center;
    flex: 0 0 auto;
    text-decoration: none;
}
.ao-attn-cta:hover {
    text-decoration: none;
}

/* ── aoTabs + the overview status line (2026-08-14) ─────────────────────
   Owner's density rule: "unless the page requires a scroll, try to push into
   another tab or menu/button focused". Relocation, never deletion — the tab
   carries a badge/dot so a hidden number still announces itself. */
.ao-tabs {
    margin: 0 0 12px;
}
/* The tab bar is a square-cornered SEGMENTED BAR (2026-09-24, owner: "hate
 * this bubble shit, wipe it from everywhere"): one bordered box at the
 * control radius, the tabs split by 1px rules, the selected one tinted and
 * bold. It replaced the Team range tray (a sunken pill track with the
 * selected tab raised out of it), the same look the portal's Kit segmented
 * filter (.kit-segs, PR #3201) draws. ⛔ aoTabs sets no inline base, so
 * without these rules the tabs are the browser's own buttons. The bar
 * scrolls sideways on a phone rather than wrapping into a ragged second row;
 * its scrollbar is hidden. overflow clips, so the focus ring sits INSIDE. */
.ao-tabs-bar {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-ctl);
    display: inline-flex;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
}
.ao-tabs-bar::-webkit-scrollbar {
    display: none;
}
/* min-height: a literal 28px floor, like .ao-tm-seg-btn — the console-wide
 * reset removed main.css's 44px box, and this keeps the tab a real target. */
.ao-tabs-bar .ao-tab {
    align-items: center;
    appearance: none;
    background: transparent;
    border: 0;
    border-left: 1px solid var(--ao-border-soft);
    border-radius: 0;
    color: var(--ao-fg-mute);
    cursor: pointer;
    display: inline-flex;
    flex: none;
    font-family: inherit;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    gap: 6px;
    letter-spacing: 0.06em;
    line-height: 1;
    min-height: 28px;
    padding: 7px 12px;
    text-transform: uppercase;
    white-space: nowrap;
}
.ao-tabs-bar .ao-tab:first-child {
    border-left: 0;
}
/* !important only to outrank the legacy .ao-tab.is-active accent fill (the
 * 2026-08-13 refresh), which carries it to beat an inline base aoTabs never
 * sets. Tinted and bold is the selected state; the divider stays. */
.ao-tabs-bar .ao-tab.is-active {
    background: var(--ao-rail-active) !important;
    border-color: var(--ao-border-soft) !important;
    box-shadow: none;
    color: var(--ao-fg) !important;
    font-weight: 700;
}
.ao-tabs-bar .ao-tab:not(.is-active):hover {
    background: var(--ao-tint-2);
    border-color: var(--ao-border-soft) !important;
    color: var(--ao-fg);
}
.ao-tabs-bar .ao-tab:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: -2px;
}
.ao-tabs-bar .ao-tab.is-active .ao-tab-badge {
    color: var(--ao-fg-dim);
}
.ao-tab-badge {
    font-size: var(--ao-fs-label);
    font-variant-numeric: tabular-nums;
    color: var(--ao-fg-mute);
}
.ao-tabs-panel {
    padding-top: 12px;
}
/* The panel owns the spacing; cards inside a tab must not double it up. */
.ao-tabs-panel > .ao-card:last-child {
    margin-bottom: 0;
}

/* ══ OVERVIEW + TENANTS — design system v2 rehaul (b01, 2026-09-23) ══════════
 * Page-local rules for #/overview, #/tenants and the tenant page's shell,
 * Overview and Plan & access tabs, in the Team page's family: KPI strips from
 * aoStat.row, .ao-table v2 inside card wraps, pill buttons, fact tiles.
 * Tokens only. Entrances come from .ao-in (aoIn) on a navigation only; this
 * section adds no keyframes. */

/* ── Overview: three blocks, one rhythm ─────────────────────────────────── */
.ao-ov-panel {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-5);
    padding: var(--ao-s-2) 0 var(--ao-s-6);
}
/* The attention list as a Team card: same radius, gradient and highlight as
 * the KPI cards under it. Its left edge still carries the verdict colour. */
.ao-ov-panel > .ao-attn {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    margin: 0;
    overflow: hidden;
}
.ao-ov-panel > .ao-tabs .ao-tabs-panel {
    padding-top: var(--ao-s-3);
}
/* The numbers lead, as on Team: on a phone a 520px alert list put them below
 * the fold. Visual order only — the DOM (and the test that reads it) keeps
 * attention, status line, tabs. */
.ao-ov-panel > .ao-ov-kpis {
    order: -1;
}

/* The status line is the KPI strip now, with the as-of stamp and the
 * degraded count as quiet chips under it. */
.ao-statline {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    margin: 0;
}
.ao-statline-meta {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
    justify-content: flex-end;
}
.ao-statline-asof,
.ao-statline-degraded {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    gap: 6px;
    padding: 3px 10px;
}
.ao-statline-degraded {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
    cursor: help;
}
/* A card's meter (aoStat `pct`) is its foot, where Team's cards draw the
 * sparkline: a full-width rounded track pinned to the bottom, so a row of
 * cards stretched to its tallest one has no empty lower half. A meter with no
 * state colour of its own (a share, not a health) takes the card's hue. */
.ao-ov-kpis .ao-stat > .ao-state-bar,
.ao-tn-kpis .ao-stat > .ao-state-bar {
    border-radius: var(--ao-r-bar);
    height: 6px;
    margin-top: auto;
    min-width: 0;
    width: 100%;
}
/* Its floor above: the card's 6px gap plus this, as Team's spark sits. */
.ao-ov-kpis .ao-stat > :has(+ .ao-state-bar),
.ao-tn-kpis .ao-stat > :has(+ .ao-state-bar) {
    margin-bottom: 6px;
}
.ao-ov-kpis .ao-stat > .ao-state-bar .ao-state-bar-fill,
.ao-tn-kpis .ao-stat > .ao-state-bar .ao-state-bar-fill {
    border-radius: inherit;
}
.ao-ov-kpis .ao-stat > .ao-state-bar.is-unknown .ao-state-bar-fill,
.ao-tn-kpis .ao-stat > .ao-state-bar.is-unknown .ao-state-bar-fill {
    background: var(--ao-stat-accent, var(--ao-fg-dim));
}
.ao-ov-kpis .ao-stat > .ao-state-bar .ao-state-bar-label,
.ao-tn-kpis .ao-stat > .ao-state-bar .ao-state-bar-label {
    display: none;
}

/* ── Overview tab cards ─────────────────────────────────────────────────── */
/* The table bleeds to the card's sides, so the card is its frame there: the
 * wrap keeps only the rules above and below (a side border would sit against
 * the card's own and read as a 2px line). */
.ao-ov-card .ao-table-wrap {
    --ao-tbl-head-r: 0px;
    border-radius: 0;
    border-width: 1px 0;
    margin: 0 calc(var(--ao-s-4) * -1);
    width: calc(100% + var(--ao-s-4) * 2);
}
.ao-ov-card .ao-table th:first-child,
.ao-ov-card .ao-table td:first-child {
    padding-left: var(--ao-s-4);
}
.ao-ov-card .ao-table th:last-child,
.ao-ov-card .ao-table td:last-child {
    padding-right: var(--ao-s-4);
}
.ao-ov-svc {
    align-items: center;
    color: var(--ao-fg);
    display: inline-flex;
    font-weight: 600;
    gap: 9px;
}
.ao-ov-svc-detail {
    color: var(--ao-fg-dim);
}
/* The detail under the name: only on a phone, where DETAIL is hidden. */
.ao-ov-svc-sub {
    display: none;
}
/* A bar under a number must not lift the number off its row: the track is
 * pinned to the cell's foot, so the value centres like its neighbours
 * (the in-flow track put 1022 ms 4px above the 1026 beside it). */
.ao-ov-card .ao-table td.has-bar {
    position: relative;
}
.ao-ov-card .ao-table td.has-bar .ao-table-bar {
    bottom: 7px;
    left: 12px;
    margin: 0;
    position: absolute;
    right: 12px;
}
.ao-ov-card .ao-table td.has-bar:last-child .ao-table-bar {
    right: var(--ao-s-4);
}
/* LATENCY: the bar is time on a fixed 1s scale, coloured by the probe's own
 * state — a timed-out probe's full bar is a warning, never the best score. */
.ao-ov-svc-table tr.is-up .ao-table-bar-fill {
    background: var(--ao-ok-fg);
}
.ao-ov-svc-table tr.is-unknown .ao-table-bar-fill {
    background: var(--ao-warn-fg);
}
.ao-ov-svc-table tr.is-down .ao-table-bar-fill {
    background: var(--ao-err-fg);
}
.ao-ov-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.55;
    margin-top: var(--ao-s-3);
    max-width: 920px;
}
.ao-ov-acts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
    margin-top: var(--ao-s-3);
}
/* A link dressed as a ghost pill keeps the pill's colour on hover (the
 * console's a:hover would underline it in the brand rose). */
a.ao-ov-link,
a.ao-ov-link:hover {
    text-decoration: none;
}
.ao-ov-chips {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: var(--ao-s-3);
}
.ao-ov-chips-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    margin-right: 4px;
    text-transform: uppercase;
}
.ao-ov-chip {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    padding: 3px 10px 3px 8px;
}
.ao-ov-chip.is-bad {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-ov-callout {
    align-items: center;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-body);
    gap: var(--ao-s-2);
    margin-top: var(--ao-s-3);
    padding: 8px 8px 8px 12px;
}
.ao-ov-callout.is-err {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-ov-callout > .ao-ov-link {
    margin-left: auto;
}
/* DEPLOY: four fact tiles instead of an inline-styled key/value list. A
 * wrapping flex row, not a grid: the last row's tiles grow to fill it, so a
 * sixth fact never sits alone under five. */
.ao-ov-facts,
.ao-tn-facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
}
.ao-ov-facts > *,
.ao-tn-facts > * {
    flex: 1 1 200px;
}
/* The tenant page's tiles sit under a KPI row: the same 12px gap as the
 * cards, so the two rows share one rhythm. */
.ao-tn-facts {
    gap: var(--ao-s-3);
}
.ao-ov-fact,
.ao-tn-fact {
    align-items: flex-start;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-lg);
    display: flex;
    gap: 10px;
    min-width: 0;
    padding: 10px 12px;
}
.ao-ov-fact-ico,
.ao-tn-fact-ico {
    background: var(--ao-tint-2);
    border-radius: 7px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    display: grid;
    flex: none;
    height: 26px;
    place-items: center;
    width: 26px;
}
.ao-ov-fact-body,
.ao-tn-fact-body {
    min-width: 0;
}
.ao-ov-fact-l,
.ao-tn-fact-l {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-ov-fact-v,
.ao-tn-fact-v {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    margin-top: 3px;
    overflow-wrap: break-word;
}
/* A line that must not break at all (an email address): it ellipses, and
 * carries the whole value as its title. */
.ao-tn-ellip {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tn-fact-v.is-ok {
    color: var(--ao-ok-fg);
}
.ao-tn-fact-v.is-warn {
    color: var(--ao-warn-fg);
}
.ao-tn-fact-v.is-err {
    color: var(--ao-err-fg);
}
.ao-tn-fact-v.is-mute {
    color: var(--ao-fg-mute);
}
.ao-ov-card .ao-stat-row {
    margin-top: var(--ao-s-1);
}
/* PIPELINE's yes/no card: the answer is the pill, set where the number
 * would sit, a step larger than a card's footnote pill. */
.ao-ov-pillcard > .ao-state-pill {
    align-self: flex-start;
    font-size: var(--ao-fs-meta);
    margin-top: var(--ao-s-1);
    order: -1;
    padding: 3px 10px;
}
.ao-ov-pillcard > .ao-stat-head {
    order: -2;
}

/* ── Tenants directory ──────────────────────────────────────────────────── */
.ao-tn-page,
.ao-tn-detail {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    padding-bottom: var(--ao-s-6);
}
.ao-tn-panel,
.ao-tn-head {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-tn-panel {
    gap: var(--ao-s-4);
    padding-top: var(--ao-s-2);
}
.ao-tn-head > .ao-sec-head {
    margin: var(--ao-s-2) 0 0;
}
/* A count that keeps its test hook and its (upper-case) words, set as a
 * quiet mono pill beside the sentence-case title rather than spaced-out
 * capitals next to it. */
.ao-tn-count {
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-variant-numeric: tabular-nums;
    font-weight: 500;
    letter-spacing: 0;
    padding: 1px 8px;
    white-space: nowrap;
}
.ao-tn-legend,
.ao-tn-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    max-width: 760px;
}
.ao-tn-legend {
    margin-top: calc(var(--ao-s-2) * -1);
}
.ao-tn-filterline {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    color: var(--ao-fg-dim);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: var(--ao-s-2);
    padding: 3px 4px 3px 12px;
    width: fit-content;
    max-width: 100%;
}
.ao-tn-filterline[hidden] {
    display: none;
}
/* A KPI card that filters the table is a control: the pointer and the
 * active outline come from .ao-stat.is-clickable / .is-active. */
.ao-tn-kpis .ao-stat-sub {
    white-space: normal;
}
/* The directory table: the name cell may wrap, every other cell holds. Two
 * cells stack a quieter second line (the plan, the last heartbeat) so the
 * seven columns and four actions fit a desktop column without a scroll. */
.ao-tn-table th,
.ao-tn-table td {
    padding-left: 8px;
    padding-right: 8px;
    vertical-align: middle;
}
.ao-tn-table th {
    letter-spacing: 0.06em;
}
.ao-tn-table th:first-child,
.ao-tn-table td:first-child {
    padding-left: var(--ao-s-4);
}
.ao-tn-sep {
    display: none;
}
.ao-tn-l1,
.ao-tn-l2 {
    display: block;
}
.ao-tn-l2 {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-top: 1px;
}
.ao-tn-table td.ao-tn-idcell {
    max-width: 260px;
    min-width: 208px;
    white-space: normal;
}
/* The HQ pill follows the name's last word: a name that wraps carries it on
 * its second line, not at the cell's far right (a flex row pushed it there). */
.ao-tn-name {
    color: var(--ao-fg);
    display: block;
    font-weight: 600;
    line-height: 1.3;
}
.ao-tn-name.is-id {
    font-family: var(--ao-mono);
    font-weight: 500;
}
.ao-tn-id {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    margin-top: 2px;
}
.ao-tn-acct {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    margin-top: 2px;
}
.ao-tn-hq {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-block;
    font-size: var(--ao-fs-label);
    font-weight: 700;
    letter-spacing: 0.06em;
    line-height: 1.5;
    margin-left: 6px;
    padding: 0 7px;
    vertical-align: 1px;
    white-space: nowrap;
}
.ao-tn-nowrap {
    white-space: nowrap;
}
.ao-tn-table td.ao-tn-type.is-dim,
.ao-tn-table td.is-mute,
.ao-tn-dim {
    color: var(--ao-fg-mute);
}
.ao-tn-last {
    color: var(--ao-fg-dim);
}
/* "no activity" is an absence: quieter than the times beside it, in words
 * rather than the mono face a time gets (the id prefix outranks .ao-mono). */
#argus-ops-root .ao-tn-table td.ao-tn-last.is-none {
    color: var(--ao-fg-mute);
    font-family: var(--ao-font-sans);
    font-size: var(--ao-fs-meta);
}
.ao-tn-onb,
.ao-tn-rs {
    align-items: center;
    display: inline-flex;
    gap: 5px;
}
.ao-tn-onb.is-ok {
    color: var(--ao-ok-fg);
}
.ao-tn-onb.is-warn {
    color: var(--ao-warn-fg);
}
.ao-tn-onb.is-mute {
    color: var(--ao-fg-mute);
}
/* Remote support: a status dot in the pill's own colour, no typed ●/○. */
/* The state pill's type (10px / 600 / uppercase), as every status pill. */
.ao-tn-rs {
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.03em;
    line-height: 1.6;
    padding: 1px 8px 1px 7px;
    text-transform: uppercase;
    white-space: nowrap;
}
.ao-tn-rs::before {
    border: 1.5px solid currentColor;
    border-radius: 50%;
    content: '';
    height: 6px;
    width: 6px;
}
.ao-tn-rs.is-on {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-tn-rs.is-on::before {
    background: currentColor;
}
.ao-tn-acts {
    align-items: center;
    display: flex;
    gap: 2px;
}
.ao-tn-acts .ao-btn {
    padding-inline: 9px;
}
.ao-tn-acts .ao-btn.is-ghost {
    padding-inline: 8px;
}
/* ARM and DISARM differ by three letters; the floor (DISARM's own width)
 * keeps PIN / LINK AGENT in one column down the table whichever one a row
 * shows. */
.ao-tn-arm {
    justify-content: center;
    min-width: 86px;
}
/* ARM mirrors DISARM in the positive family: quiet tint at rest, a step up
 * on hover. It was a filled grey pill that read as MANAGE. */
.ao-btn.ao-tn-arm:not([data-armed='1']) {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-btn.ao-tn-arm:not([data-armed='1']):hover:not(:disabled) {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
/* Their icon is painted by CSS, not an aoIcon node: patchTenantRow rewrites
 * the button's text on every tick, which would strip a child icon. A
 * currentColor mask of the icon set's shield (ARM) / power (DISARM) glyph
 * survives any text write — the .ao-al-btn-silence bell's technique. */
.ao-tn-arm::before {
    background: currentColor;
    content: '';
    flex: none;
    height: 13px;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z'/%3E%3C/svg%3E")
        center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z'/%3E%3C/svg%3E")
        center / contain no-repeat;
    width: 13px;
}
.ao-tn-arm[data-armed='1']::before {
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2v10'/%3E%3Cpath d='M18.4 6.6a9 9 0 1 1-12.77.04'/%3E%3C/svg%3E")
        center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2v10'/%3E%3Cpath d='M18.4 6.6a9 9 0 1 1-12.77.04'/%3E%3C/svg%3E")
        center / contain no-repeat;
}
.ao-tn-table td.ao-tn-actcell,
.ao-tn-mod-table td.ao-tn-actcell {
    max-width: none;
    overflow: visible;
    padding-bottom: 6px;
    padding-top: 6px;
}
.ao-tn-table tr.is-group-start > td {
    border-top-color: var(--ao-border);
}
/* Grouped: a chain's stores sit indented under its HQ on the chain's rule,
 * so ON reads differently from OFF (the HQ row keeps the inline divider). */
.ao-tn-table tr.is-group-child > td.ao-tn-idcell {
    box-shadow: inset 2px 0 var(--ao-k-5);
    padding-left: calc(var(--ao-s-4) + 28px);
}
.ao-tn-empty > td {
    color: var(--ao-fg-mute);
    padding: var(--ao-s-5) var(--ao-s-4);
    text-align: center;
}
/* The Tenants ENTERPRISE toggle: a chip whose pressed state is its own. */
.ao-tn-group {
    letter-spacing: 0.04em;
    font-weight: 600;
}

/* ── Tenant page (shell + Overview + Plan & access) ─────────────────────── */
.ao-tn-detail-bar {
    align-items: center;
    padding-top: var(--ao-s-2);
}
/* The way back is a ghost pill (its chevron is an aoIcon): the legacy
 * .ao-backlink's typed ‹ and underline stay off. */
a.ao-backlink.ao-tn-back,
a.ao-backlink.ao-tn-back:hover {
    text-decoration: none;
}
a.ao-backlink.ao-tn-back::before {
    content: none;
}
.ao-tn-detail-acts {
    display: flex;
    gap: var(--ao-s-2);
}
.ao-tn-detail .ao-tabs-pane > section {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
}
.ao-tn-detail .ao-tabs-pane > section + section {
    margin-top: var(--ao-s-6);
}
.ao-tn-detail .ao-tabs-pane > section > .ao-sec-head {
    margin-bottom: 0;
}
/* The first header in a tab sits clear of the tab bar (Team's ~32px), not
 * 12px under it. */
.ao-tn-detail .ao-tabs-pane > section:first-child > .ao-sec-head:first-child {
    margin-top: var(--ao-s-5);
}
/* The store profile's facts: an even grid (the flex row made five tiles of
 * five widths); a value only breaks at its separators (.ao-tn-seg). */
.ao-tn-facts.is-profile {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.ao-tn-seg {
    white-space: nowrap;
}
.ao-tn-fact-v .ao-tn-l2 {
    color: inherit;
    font-size: inherit;
}
/* On the tenant page the facts are their own row of small cards (the
 * Overview DEPLOY tiles sit inside a card and stay flat). */
.ao-tn-facts > .ao-tn-fact {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-color: var(--ao-border-soft);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
}
.ao-tn-actions {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    padding: var(--ao-s-3) var(--ao-s-4);
}
.ao-tn-actrow {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
}
.ao-tn-actrow + .ao-tn-actrow {
    border-top: 1px solid var(--ao-tint-line);
    padding-top: var(--ao-s-3);
}
.ao-tn-actrow-l {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    min-width: 96px;
    text-transform: uppercase;
}
.ao-tn-actrow-hint {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
/* Plan & access: subscriptions and invoices side by side when there is room,
 * one height: a short Subscriptions card beside a tall Invoices one left a
 * hole under it. */
.ao-tn-billcols {
    align-items: stretch;
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
}
.ao-tn-billcard {
    display: flex;
    flex-direction: column;
    min-width: 0;
    padding: var(--ao-s-3) 0 var(--ao-s-1);
}
.ao-tn-billcard > .ao-sec-head {
    padding: 0 var(--ao-s-4);
}
/* The card has no side padding, so the table runs edge to edge and the card
 * is its frame at the sides: the wrap keeps the rules above and below. */
.ao-tn-billcard > .ao-table-wrap {
    --ao-tbl-head-r: 0px;
    border-radius: 0;
    border-width: 1px 0;
}
.ao-tn-billcard .ao-table th:first-child,
.ao-tn-billcard .ao-table td:first-child {
    padding-left: var(--ao-s-4);
}
.ao-tn-billcard > .ao-table-wrap > .ao-empty,
.ao-tn-billcard > .ao-table-wrap > .ao-table-unread {
    margin: 0 var(--ao-s-4) var(--ao-s-3);
}
.ao-tn-billcard tr.is-ending td {
    color: var(--ao-warn-fg);
}
.ao-tn-warntext,
.ao-tn-errtext {
    align-items: center;
    display: inline-flex;
    gap: 5px;
}
.ao-tn-warntext {
    color: var(--ao-warn-fg);
}
.ao-tn-errtext {
    color: var(--ao-err-fg);
    cursor: help;
}
a.ao-tn-receipt,
a.ao-tn-receipt:hover {
    text-decoration: none;
}
.ao-tn-chip {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    padding: 1px 6px;
}
.ao-tn-mod-name {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-tn-mod-table tr:not(.is-active) .ao-tn-mod-name {
    color: var(--ao-fg-dim);
    font-weight: 500;
}

/* ── Tenant step-up modals (ARM / PIN / LINK / GRANT / installer / skip) ── */
.ao-tn-modal {
    align-items: center;
    background: var(--ao-overlay);
    display: flex;
    /* Appended to <body>, outside #argus-ops-root: it carries the console's
     * face itself or it falls back to the host page's. */
    font-family: var(--ao-font-sans);
    inset: 0;
    justify-content: center;
    padding: var(--ao-s-6);
    position: fixed;
    z-index: 99998;
}
.ao-tn-modal-card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-3);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-strong);
    max-height: calc(100vh - 48px);
    max-width: 520px;
    overflow-y: auto;
    padding: var(--ao-s-5) var(--ao-s-5) var(--ao-s-4);
    width: 100%;
}
.ao-tn-modal-card.is-wide {
    max-width: 580px;
}
.ao-tn-modal-head {
    align-items: center;
    display: flex;
    gap: 10px;
    margin-bottom: var(--ao-s-3);
}
.ao-tn-modal-ico {
    background: var(--ao-tint-2);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    display: grid;
    flex: none;
    height: 32px;
    place-items: center;
    width: 32px;
}
.ao-tn-modal-ico.is-err {
    background: var(--ao-err-bg);
    box-shadow: inset 0 0 0 1px var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-tn-modal-ico.is-warn {
    background: var(--ao-warn-bg);
    box-shadow: inset 0 0 0 1px var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-tn-modal-titles {
    min-width: 0;
}
.ao-tn-modal-h {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    font-weight: 600;
    line-height: 1.3;
    margin: 0;
    overflow-wrap: anywhere;
}
.ao-tn-modal-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-top: 2px;
    overflow-wrap: anywhere;
}
/* Read to a screen reader (the confirm field's description), not painted. */
.ao-tn-sr {
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}
.ao-tn-modal-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    line-height: 1.45;
    margin-bottom: var(--ao-s-3);
}
.ao-tn-modal-note.is-warn {
    background: var(--ao-warn-bg);
    border: 1px solid var(--ao-warn-bd);
    border-radius: var(--ao-r-md);
    color: var(--ao-warn-fg);
    padding: 8px 10px;
}
.ao-tn-modal-note.is-after {
    margin: var(--ao-s-3) 0 0;
}
.ao-tn-modal-hint {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin: 2px 0 var(--ao-s-2);
}
.ao-tn-modal-url {
    margin-bottom: var(--ao-s-2);
    width: 100%;
}
.ao-tn-modal-err {
    color: var(--ao-warn-fg);
    font-size: var(--ao-fs-body);
    margin-top: 6px;
    min-height: 16px;
}
/* One layout for every tenant modal: CANCEL / CLOSE on the left, the action
 * on the right, the pair at the right edge. The DOM order is test-locked
 * (submit first in PIN / LINK / ARM / GRANT / installer, cancel first in
 * SKIP), so the row is reversed here rather than in the markup. */
.ao-tn-modal-acts {
    display: flex;
    flex-direction: row-reverse;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
    justify-content: flex-start;
    margin-top: var(--ao-s-3);
}
.ao-tn-modal-acts.is-end {
    flex-direction: row;
    justify-content: flex-end;
}
.ao-tn-affirm {
    margin-top: var(--ao-s-2);
}
/* The labelled fields: outside #argus-ops-root nothing else sizes them (the
 * root's border-box reset does not reach <body>). */
.ao-tn-modal *,
.ao-tn-modal *::before,
.ao-tn-modal *::after {
    box-sizing: border-box;
}
.ao-tn-modal .ao-field {
    margin-top: var(--ao-s-3);
}
.ao-tn-modal .ao-field-label {
    color: var(--ao-fg-mute);
    display: block;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    margin-bottom: 5px;
    text-transform: uppercase;
}
.ao-tn-modal .ao-input {
    min-height: 32px;
}
/* The version picker is a field like the inputs beside it, full width. */
.ao-tn-modal .ao-tselect {
    display: flex;
    min-height: 32px;
    width: 100%;
}
/* …and dressed like them: the same soft border, radius and padding. */
.ao-tn-modal .ao-tselect-trigger {
    border-color: var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    flex: 1 1 auto;
    min-height: 32px;
    padding: 5px 9px;
}
.ao-tn-affirm .ao-field-label {
    align-items: center;
    color: var(--ao-fg-dim);
    cursor: pointer;
    display: flex;
    font-size: var(--ao-fs-body);
    font-weight: 500;
    gap: 8px;
    letter-spacing: 0;
    text-transform: none;
}
/* The consent box in the console's own dress: a sunken 16px square that
 * fills with the CTA gold and a drawn tick when checked. Still the real
 * <input type=checkbox> (tests and the submit gate read .checked). */
.ao-tn-affirm input[type='checkbox'] {
    -webkit-appearance: none;
    appearance: none;
    background: var(--ao-bg);
    border: 1px solid var(--ao-border);
    border-radius: 5px;
    cursor: pointer;
    display: inline-grid;
    flex: none;
    height: 16px;
    margin: 0;
    place-content: center;
    transition:
        background-color var(--ao-base) var(--ao-ease),
        border-color var(--ao-base) var(--ao-ease);
    width: 16px;
}
.ao-tn-affirm input[type='checkbox']::before {
    background: var(--ao-cta-fg);
    content: '';
    height: 10px;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
        center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
        center / contain no-repeat;
    visibility: hidden;
    width: 10px;
}
.ao-tn-affirm input[type='checkbox']:hover:not(:checked) {
    border-color: var(--ao-fg-mute);
}
.ao-tn-affirm input[type='checkbox']:checked {
    background: var(--ao-cta);
    border-color: var(--ao-cta-border);
}
.ao-tn-affirm input[type='checkbox']:checked::before {
    visibility: visible;
}
.ao-tn-affirm input[type='checkbox']:focus-visible {
    outline: 2px solid var(--ao-cta-focus);
    outline-offset: 2px;
}

/* ── Phone (< 760px) ────────────────────────────────────────────────────── */
@media (max-width: 760px) {
    .ao-statline-meta {
        justify-content: flex-start;
    }
    .ao-ov-facts > * {
        flex-basis: 100%;
    }
    /* Plan & access: its short facts two-up, not four full-width slabs
     * (half the row less half the 12px gap). */
    .ao-tn-facts > * {
        flex-basis: calc(50% - var(--ao-s-3) / 2);
    }
    /* A card left alone on the last line takes the whole line. */
    .ao-ov-kpis .ao-stat-row > .ao-stat:last-child:nth-child(odd),
    .ao-tn-kpis > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
    .ao-tn-actrow-l {
        min-width: 0;
        width: 100%;
    }
    .ao-tn-modal {
        align-items: flex-end;
        padding: var(--ao-s-2);
    }

    /* Overview SERVICES: no DETAIL column; the detail rides under the name. */
    .ao-ov-svc-table th:nth-child(3),
    .ao-ov-svc-table td:nth-child(3) {
        display: none;
    }
    .ao-ov-svc-table td:first-child {
        white-space: normal;
    }
    .ao-ov-svc-sub {
        color: var(--ao-fg-mute);
        display: block;
        font-size: var(--ao-fs-meta);
        margin: 2px 0 0 17px;
    }

    /* ── The directory as stacked row cards. A 1179px table in a 348px card
     * put REMOTE SUPPORT, LAST ACTIVITY and every row action off-screen.
     * Each row is a two-column grid: name | type, onboarding | remote
     * support, agents | last activity, then the actions across. */
    .ao-tn-table thead {
        display: none;
    }
    .ao-tn-table,
    .ao-tn-table tbody {
        display: block;
        width: 100%;
    }
    .ao-tn-table tbody tr {
        border-bottom: 1px solid var(--ao-border-soft);
        display: grid;
        gap: 6px 12px;
        grid-template-columns: minmax(0, 1fr) auto;
        padding: 12px 16px;
    }
    .ao-tn-table tbody tr:last-child {
        border-bottom: 0;
    }
    .ao-tn-table td,
    .ao-tn-table td:first-child,
    .ao-tn-table td.ao-tn-idcell,
    .ao-tn-table td.ao-tn-actcell {
        border: 0;
        display: block;
        max-width: none;
        min-width: 0;
        padding: 0;
    }
    .ao-tn-table td.ao-tn-type,
    .ao-tn-table td[data-role='rs'],
    .ao-tn-table td[data-role='last'] {
        justify-self: end;
        text-align: right;
    }
    /* Cell order in the card (the DOM keeps the table's column order). */
    .ao-tn-table td.ao-tn-type {
        order: 1;
    }
    .ao-tn-table td[data-role='onb'] {
        order: 2;
    }
    .ao-tn-table td[data-role='rs'] {
        order: 3;
    }
    .ao-tn-table td[data-role='agents'] {
        order: 4;
    }
    .ao-tn-table td[data-role='last'] {
        order: 5;
    }
    .ao-tn-table td.ao-tn-actcell {
        order: 6;
    }
    .ao-tn-table td[data-role='last']:not(.is-none)::before {
        color: var(--ao-fg-mute);
        content: 'active ';
        font-family: var(--ao-font-sans);
        font-size: var(--ao-fs-meta);
    }
    .ao-tn-table td.ao-tn-actcell,
    .ao-tn-empty > td {
        grid-column: 1 / -1;
    }
    .ao-tn-table td.ao-tn-actcell {
        margin-top: 4px;
    }
    /* Four actions as an even 2 × 2, not three and a straggler. */
    .ao-tn-acts {
        display: grid;
        gap: 6px;
        grid-template-columns: 1fr 1fr;
    }
    .ao-tn-acts > .ao-btn {
        justify-content: center;
    }
    /* ARM / DISARM + MANAGE on the first line, PIN + LINK AGENT (the quiet
     * pair) on the second — not a filled/quiet checkerboard. Visual order
     * only; the DOM keeps the desktop order. */
    .ao-tn-acts > [data-role='manage'] {
        order: 1;
    }
    .ao-tn-acts > [data-role='pin'] {
        order: 2;
    }
    .ao-tn-acts > [data-role='link-agent'] {
        order: 3;
    }
    .ao-tn-table tbody tr:hover {
        background: var(--ao-hover);
    }
    .ao-tn-table tbody tr:hover > td {
        background: transparent;
        box-shadow: none;
    }
    .ao-tn-table tr.is-group-child {
        box-shadow: inset 2px 0 var(--ao-k-5);
        padding-left: 28px;
    }
    .ao-tn-table tr.is-group-child > td.ao-tn-idcell {
        box-shadow: none;
        padding-left: 0;
    }

    /* ── Plan & access MODULES as stacked rows: the name, its state and its
     * GRANT / REVOKE on the first line; the id and the facts it has under. */
    .ao-tn-mod-table thead {
        display: none;
    }
    .ao-tn-mod-table,
    .ao-tn-mod-table tbody {
        display: block;
        width: 100%;
    }
    .ao-tn-mod-table tbody tr {
        align-items: center;
        border-bottom: 1px solid var(--ao-border-soft);
        display: flex;
        flex-wrap: wrap;
        gap: 3px 8px;
        padding: 10px 16px;
    }
    .ao-tn-mod-table tbody tr:last-child {
        border-bottom: 0;
    }
    /* The line break between the two lines. */
    .ao-tn-mod-table tbody tr::after {
        content: '';
        flex-basis: 100%;
        height: 0;
        order: 3;
    }
    .ao-tn-mod-table td,
    .ao-tn-mod-table td:first-child,
    .ao-tn-mod-table td.ao-tn-actcell {
        border: 0;
        display: block;
        max-width: none;
        padding: 0;
    }
    .ao-tn-mod-table td.ao-tn-mod-name {
        flex: 1 1 0;
        min-width: 0;
        white-space: normal;
    }
    .ao-tn-mod-table td[data-role='state'] {
        order: 1;
    }
    .ao-tn-mod-table td.ao-tn-actcell {
        order: 2;
    }
    .ao-tn-mod-table td:nth-child(2) {
        order: 4;
    }
    .ao-tn-mod-table td:nth-child(4),
    .ao-tn-mod-table td:nth-child(5) {
        font-size: var(--ao-fs-meta);
        order: 5;
    }
    .ao-tn-mod-table td:nth-child(5) {
        order: 6;
    }
    .ao-tn-mod-table td:nth-child(4)::before,
    .ao-tn-mod-table td:nth-child(5)::before {
        content: '· ';
    }
    .ao-tn-mod-table td:nth-child(5)::before {
        content: '· granted ';
    }
    .ao-tn-mod-table tr.is-none td:nth-child(4),
    .ao-tn-mod-table tr:not(.is-active) td:nth-child(5) {
        display: none;
    }
    .ao-tn-mod-table tbody tr:hover {
        background: var(--ao-hover);
    }
    .ao-tn-mod-table tbody tr:hover > td {
        background: transparent;
        box-shadow: none;
    }

    /* ── Plan & access INVOICES as two-line rows: product | amount, then
     * date | status | receipt. */
    .ao-tn-inv-table thead {
        display: none;
    }
    .ao-tn-inv-table,
    .ao-tn-inv-table tbody {
        display: block;
        width: 100%;
    }
    .ao-tn-inv-table tbody tr {
        align-items: center;
        border-bottom: 1px solid var(--ao-border-soft);
        display: grid;
        gap: 4px 10px;
        grid-template-areas:
            'prod prod amt'
            'date stat rcpt';
        grid-template-columns: minmax(0, 1fr) auto auto;
        padding: 10px 16px;
    }
    .ao-tn-inv-table tbody tr:last-child {
        border-bottom: 0;
    }
    .ao-tn-billcard .ao-tn-inv-table td,
    .ao-tn-billcard .ao-tn-inv-table td:first-child {
        border: 0;
        display: block;
        max-width: none;
        padding: 0;
    }
    .ao-tn-inv-table td:nth-child(1) {
        color: var(--ao-fg-mute);
        font-size: var(--ao-fs-meta);
        grid-area: date;
    }
    .ao-tn-inv-table td:nth-child(2) {
        grid-area: prod;
        white-space: normal;
    }
    .ao-tn-inv-table td:nth-child(3) {
        grid-area: amt;
    }
    .ao-tn-inv-table td:nth-child(4) {
        grid-area: stat;
    }
    .ao-tn-inv-table td:nth-child(5) {
        grid-area: rcpt;
        justify-self: end;
    }
    .ao-tn-inv-table tbody tr:hover {
        background: var(--ao-hover);
    }
    .ao-tn-inv-table tbody tr:hover > td {
        background: transparent;
        box-shadow: none;
    }
}

/* Fleet agent card identity (2026-08-15) — the Phase 2 sweep swept a function
   with zero call sites; these are the classes the REAL card renderer needed. */
.ao-fleet-card-title .ao-identity-name {
    font-size: var(--ao-fs-title);
    font-weight: 600;
    line-height: 1.2;
}
.ao-fleet-card-attached {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 0 5px;
    margin-top: 4px;
}
.ao-fleet-card-attached .ao-identity-name {
    color: var(--ao-fg-dim);
}

/* ── Agent telemetry detail (inside an aoTable detail disclosure) ─────────── */
.ao-tel-line {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-top: 2px;
}
.ao-tel-line:first-child {
    margin-top: 0;
}
.ao-tel-line.is-err {
    color: var(--ao-err-strong);
}
.ao-tel-label {
    opacity: 0.6;
}
.ao-tel-log {
    background: var(--ao-surface);
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin: 6px 0 0;
    max-height: 140px;
    overflow: auto;
    padding: 6px;
    white-space: pre-wrap;
}

/* ══ FLEET (#/fleet) + AGENTS (#/agents) — design system v2 (rehaul b04) ════
 * The two agent tabs in the Team page's family. The shared look comes from
 * .ao-card / .ao-stat / .ao-table / .ao-btn / aoSection; these rules are the
 * page layout and the few page-only pieces (the agent card, the readiness
 * card, the RUN COMMAND console, the live-check wall, the modals). Tokens
 * only. JS: fleetInto … applyFleetFilter, metricsInto … agentsTable,
 * buildViewCameraModal. */

/* Sentence case for literal UPPERCASE titles and KPI labels, for the EYE
 * only: the DOM text stays exactly as written ("STREAMING AGENTS — 16 LIVE",
 * "OUTAGES", "DOWNLOADED") because tests and screen readers read it. */
.ao-agf-sc > .ao-sec-h,
.ao-agf-sc .ao-stat-label-text {
    text-transform: lowercase;
}
.ao-agf-sc > .ao-sec-h::first-letter,
.ao-agf-sc .ao-stat-label-text::first-letter {
    text-transform: uppercase;
}
/* Kept for a screen reader (and textContent), not drawn: the long form of a
 * short chip, the ✓ / ✗ behind a check icon. */
.ao-agf-sr {
    border: 0;
    clip-path: inset(50%);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}

/* ── Fleet page ──────────────────────────────────────────────────────────── */
/* One flex column: a heading gets room above it and the gap below, as in
 * #ao-page-body. */
.ao-fl {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
.ao-fl > .ao-sec-head {
    margin: var(--ao-s-4) 0 0;
}
.ao-fl > .ao-sec-head:first-child {
    margin-top: 0;
}
/* Empty / error panels line up with the tables and cards around them (the
 * shared rule's 16px margin is for pages that do not pad their body). */
.ao-fl > .ao-empty,
.ao-fl > .ao-error,
.ao-ag-panel > .ao-empty,
.ao-ag-panel > .ao-error,
.ao-ag-block > .ao-empty,
.ao-ag-main > .ao-error {
    margin: 0;
}
/* A plain-language strip: an icon and a sentence, tinted by tone. */
.ao-fl-note {
    align-items: flex-start;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: 8px;
    line-height: 1.45;
    padding: 8px 12px;
}
.ao-fl-note > .ao-ico {
    flex: none;
    margin-top: 1px;
}
.ao-fl-note.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-fl-note.is-err {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-fl-note-text {
    min-width: 0;
    overflow-wrap: anywhere;
}
/* The OUTAGES card's sub-line: a calm all-clear, or the band mix in err. */
.ao-fl-clear {
    color: var(--ao-ok-text);
    font-weight: 600;
    letter-spacing: 0.06em;
}
.ao-fl-outage-mix {
    color: var(--ao-err-fg);
}
/* Above zero the OUTAGES card is an alarm: the err border and number. */
.ao-stat[data-outages-badge].is-alert {
    border-color: var(--ao-err-bd);
}
.ao-stat[data-outages-badge].is-alert .ao-stat-num,
.ao-stat[data-outages-badge].is-alert .ao-stat-num.is-counting::after {
    color: var(--ao-err-fg);
}
.ao-stat[data-outages-badge].is-alert .ao-stat-num.is-counting {
    color: transparent;
}
/* Funnel: the three stages that filter the cards wear a funnel mark in the
 * corner, and the picked one is filled with its own hue; the two count-only
 * stages (aria-disabled) sit still — no lift, no ring. */
.ao-fl-filter-mark {
    color: var(--ao-fg-mute);
    display: inline-flex;
    opacity: 0.7;
    pointer-events: none;
    position: absolute;
    right: 12px;
    top: 12px;
}
.ao-fl-funnel > .ao-stat:hover .ao-fl-filter-mark,
.ao-fl-funnel > .ao-stat[aria-pressed='true'] .ao-fl-filter-mark {
    color: var(--ao-stat-accent);
    opacity: 1;
}
.ao-fl-funnel > .ao-stat[aria-pressed='true'] {
    background: color-mix(in srgb, var(--ao-stat-accent) 10%, var(--ao-surface));
    border-color: color-mix(in srgb, var(--ao-stat-accent) 45%, transparent);
    box-shadow:
        0 0 0 1px color-mix(in srgb, var(--ao-stat-accent) 45%, transparent),
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
}
.ao-fl-funnel > .ao-stat[aria-disabled='true'],
.ao-fl-funnel > .ao-stat[aria-disabled='true']:hover {
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    transform: none;
}
.ao-fl-funnel > .ao-stat[aria-disabled='true']::before {
    animation: none;
    opacity: 0;
}

/* Heartbeat table cells. */
.ao-fl-hb-status {
    align-items: center;
    display: inline-flex;
    gap: 8px;
}
.ao-fl-ago {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
}
.ao-fl-plat {
    align-items: center;
    display: inline-flex;
    gap: 4px;
}
.ao-fl-plat-os {
    text-transform: capitalize;
}
.ao-fl-ver {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    padding: 0 6px;
}

/* The agent cards. */
.ao-fl-grid {
    /* A card that opens its Technical details grows alone; its row-mates
     * keep their own height instead of stretching to match. */
    align-items: start;
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(min(360px, 100%), 1fr));
}
.ao-fl-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
    position: relative;
}
/* The heartbeat colour as a light along the card's top edge, edge to edge
 * and fading out at both ends: the fleet reads green / amber / red at a
 * glance, before a word is read. */
.ao-fl-card::before {
    background: linear-gradient(
        90deg,
        transparent,
        var(--ao-fl-tone, transparent) 15%,
        var(--ao-fl-tone, transparent) 85%,
        transparent
    );
    border-radius: var(--ao-r-xl) var(--ao-r-xl) 0 0;
    content: '';
    height: 3px;
    left: 0;
    opacity: 0.9;
    pointer-events: none;
    position: absolute;
    right: 0;
    top: 0;
}
.ao-fl-card.is-ok {
    --ao-fl-tone: var(--ao-ok);
}
.ao-fl-card.is-warn,
.ao-fl-card.is-paused {
    --ao-fl-tone: var(--ao-warn);
}
.ao-fl-card.is-err {
    --ao-fl-tone: var(--ao-err-strong);
}
.ao-fl-card.is-unknown {
    --ao-fl-tone: var(--ao-fg-mute);
}
.ao-fl-card-head {
    align-items: flex-start;
    display: flex;
    gap: 10px;
    justify-content: space-between;
}
.ao-fl-card-id {
    min-width: 0;
}
.ao-fl-card-pills {
    align-items: center;
    display: flex;
    flex: none;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: flex-end;
}
.ao-fl-hb-pill {
    flex: none;
}
.ao-fl-kv {
    background: var(--ao-tint);
    border: 1px solid var(--ao-tint-line);
    border-radius: var(--ao-r-md);
    display: grid;
    gap: 10px 14px;
    grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
    padding: 10px 12px;
}
.ao-fl-kv-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.ao-fl-kv-k {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.ao-fl-kv-v {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    font-weight: 500;
    overflow-wrap: anywhere;
}
.ao-fl-kv-v.is-ok {
    color: var(--ao-ok-text);
}
.ao-fl-kv-v.is-warn {
    color: var(--ao-warn-text);
}
.ao-fl-kv-v.is-err {
    color: var(--ao-err-strong);
}
.ao-fl-kv-v.is-mute {
    color: var(--ao-fg-mute);
}
.ao-fl-ver-cell {
    align-items: center;
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
}
.ao-fl-chip {
    align-items: center;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    display: inline-flex;
    flex: none;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 3px;
    line-height: 1.6;
    padding: 0 7px;
    position: relative;
    white-space: nowrap;
}
.ao-fl-chip.is-ok {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-fl-chip.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-fl-cams {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.ao-fl-cams-h {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    font-size: var(--ao-fs-label);
    gap: 6px;
    letter-spacing: 0.08em;
    margin-bottom: 4px;
    text-transform: uppercase;
}
.ao-fl-cams-src {
    letter-spacing: 0;
    margin-left: auto;
    text-transform: none;
}
.ao-fl-count {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    letter-spacing: 0;
    padding: 0 7px;
}
.ao-fl-cam {
    align-items: center;
    border-radius: var(--ao-r-md);
    display: flex;
    gap: 8px;
    justify-content: space-between;
    min-height: 32px;
    padding: 3px 4px 3px 8px;
    transition: background var(--ao-fast) var(--ao-ease);
}
.ao-fl-cam:hover {
    background: var(--ao-hover);
}
.ao-fl-cam-id {
    align-items: center;
    display: flex;
    gap: 8px;
    min-width: 0;
}
.ao-fl-cam-name {
    font-size: var(--ao-fs-body);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-fl-cam-live {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-fl-cam-off,
.ao-fl-cam-none {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    white-space: nowrap;
}
.ao-fl-cam-none {
    font-size: var(--ao-fs-meta);
    padding: 2px 8px;
}
/* A dark agent's cameras: one line in the pill's words, not a row each. */
.ao-fl-cam-dark {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: 8px;
    min-height: 32px;
    padding: 3px 8px;
}
.ao-fl-cam-dark.is-err {
    color: var(--ao-err-fg);
}
.ao-fl-cam-dark.is-warn {
    color: var(--ao-warn-text);
}
.ao-fl-cam-btn {
    flex: none;
}
.ao-fl-card-acts {
    gap: 8px;
    margin-top: auto;
}
/* Pausing streams is a neutral pill at rest — twenty-two amber pills made
 * amber mean nothing — and shows its amber on hover / focus, as the warning
 * it is (reversible, so never the danger variant). */
.ao-btn.ao-fl-pause:hover,
.ao-btn.ao-fl-pause:focus-visible {
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-text);
}
/* RESUME is the one call to action on a paused card: the green-outlined
 * pill it always was, not a twin of PAUSE. */
.ao-btn.ao-fl-resume {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-btn.ao-fl-resume:hover,
.ao-btn.ao-fl-resume:focus-visible {
    background: color-mix(in srgb, var(--ao-ok) 22%, var(--ao-surface));
    border-color: var(--ao-ok-text);
}
/* Danger in a row of many is quiet until it is aimed at: a RESTART on every
 * heartbeat row (and a Revoke in every card) painted the page red, so red no
 * longer meant a problem. The .is-danger colours return on hover / focus. */
.ao-fl-hb-table .ao-btn.is-danger:not(:hover):not(:focus-visible),
.ao-fl-tech-acts .ao-btn.is-danger:not(:hover):not(:focus-visible),
.ao-agents .ao-btn.is-danger:not(:hover):not(:focus-visible) {
    background: var(--ao-surface);
    border-color: var(--ao-border-soft);
    color: var(--ao-fg-dim);
}
.ao-fl-tech {
    border-top: 1px solid var(--ao-tint-line);
    padding-top: 10px;
}
.ao-fl-tech-sum {
    align-items: center;
    color: var(--ao-fg-mute);
    cursor: pointer;
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    list-style: none;
    user-select: none;
}
.ao-fl-tech-sum::-webkit-details-marker {
    display: none;
}
.ao-fl-tech-sum:hover {
    color: var(--ao-fg-dim);
}
.ao-fl-tech-sum .ao-ico {
    transition: transform var(--ao-fast) var(--ao-ease);
}
.ao-fl-tech[open] > .ao-fl-tech-sum .ao-ico {
    transform: rotate(90deg);
}
.ao-fl-tech-body {
    display: grid;
    font-size: var(--ao-fs-meta);
    gap: 4px 12px;
    grid-template-columns: auto minmax(0, 1fr);
    margin-top: 8px;
}
.ao-fl-tech-k {
    color: var(--ao-fg-mute);
}
.ao-fl-tech-v {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    word-break: break-all;
}
.ao-fl-tech-acts {
    gap: 8px;
    margin-top: 10px;
}
/* Sits under the Enrollment history heading, tighter than the column gap. */
.ao-fl-hist-why {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.45;
    margin-top: calc(-1 * var(--ao-s-2));
    max-width: 760px;
}

/* ── Agents page ─────────────────────────────────────────────────────────── */
.ao-ag-bar-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.1em;
}
.ao-ag-bar .ao-picker-trigger {
    max-width: 100%;
    min-width: 240px;
}
/* The TENANT picker and the two RUN COMMAND pickers are pills beside the
 * 28px pill buttons (the top bar's picker already is one), with a chevron
 * (_agCaret) in place of the typed ▾. */
.ao-ag-bar .ao-picker-trigger,
.ao-ag-console .ao-tselect-trigger {
    background: var(--ao-surface);
    border-color: var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    min-height: 28px;
    padding: 0 32px 0 12px;
    transition:
        background var(--ao-fast) var(--ao-ease),
        border-color var(--ao-fast) var(--ao-ease);
}
.ao-ag-bar .ao-picker-trigger:hover,
.ao-ag-console .ao-tselect-trigger:hover {
    background: var(--ao-surface-2);
    border-color: var(--ao-border);
}
.ao-ag-bar .ao-picker-trigger:focus-visible,
.ao-ag-console .ao-tselect-trigger:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-ag-bar .has-ag-caret .ao-picker-caret {
    display: none;
}
.ao-ag-console .has-ag-caret > .ao-tselect-trigger::after {
    content: none;
}
.has-ag-caret > .ao-ag-caret {
    color: var(--ao-fg-mute);
    display: inline-flex;
    pointer-events: none;
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
}
.ao-ag-console .ao-tselect-menu {
    border-radius: var(--ao-r-md);
    border-top: 1px solid var(--ao-border);
    margin-top: 4px;
    overflow: hidden auto;
    padding: 4px 0;
}
.ao-ag-panel {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-5);
    min-width: 0;
}
/* One column at every width: the readiness card (the priority rail) leads
 * as a full-width verdict banner, and the telemetry and agent tables get the
 * whole page — in an 818px main column beside a 340px rail the telemetry
 * table clipped LAST SEEN and the four row actions stacked into a tower.
 * The .ao-2col / -main / -rail.is-priority structure is unchanged. */
.ao-2col.ao-ag-2col {
    gap: var(--ao-s-5);
    grid-template-columns: minmax(0, 1fr);
    padding: 0;
}
.ao-2col-rail.ao-ag-rail {
    order: -1;
}
.ao-2col-main.ao-ag-main {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-5);
    overflow-x: visible;
}
.ao-ag-last {
    color: var(--ao-fg-mute);
}
.ao-ag-ts-empty {
    opacity: 0.5;
}
/* CPU / MEM bars take the load's colour: calm under 70%, amber from 70,
 * red from 90 (the band is a td class telemetryTable sets). */
.ao-telemetry td.has-bar .ao-table-bar-fill {
    background: var(--ao-ok);
    opacity: 0.8;
}
.ao-telemetry td.is-warm .ao-table-bar-fill {
    background: var(--ao-warn);
    opacity: 1;
}
.ao-telemetry td.is-hot .ao-table-bar-fill {
    background: var(--ao-err-strong);
    opacity: 1;
}
.ao-telemetry td.is-warm .ao-ag-load {
    color: var(--ao-warn-text);
}
.ao-telemetry td.is-hot .ao-ag-load {
    color: var(--ao-err-strong);
}
/* The per-agent DETAILS row is a quiet line under its agent, not half the
 * table: no rule between the two, a small uppercase control with a chevron,
 * and the body indented under it. */
.ao-telemetry tbody > tr:has(+ tr.ao-table-detail) > td {
    border-bottom-color: transparent;
}
.ao-table.ao-telemetry tr.ao-table-detail > td {
    padding: 2px 12px 6px;
}
.ao-telemetry .ao-table-detail .ao-disc {
    background: transparent;
    border: 0;
    margin: 0;
}
.ao-telemetry .ao-table-detail .ao-disc-sum {
    background: transparent;
    border-radius: var(--ao-r-sm);
    gap: 8px;
    padding: 3px 8px 3px 4px;
    width: fit-content;
}
.ao-telemetry .ao-table-detail .ao-disc-sum:hover {
    background: var(--ao-hover);
}
.ao-telemetry .ao-table-detail .ao-disc-sum::before {
    content: none;
}
.ao-telemetry .ao-disc-sum > .ao-ico {
    color: var(--ao-fg-mute);
    flex: none;
    transition: transform var(--ao-fast) var(--ao-ease);
}
.ao-telemetry .ao-disc[open] > .ao-disc-sum > .ao-ico {
    transform: rotate(90deg);
}
.ao-telemetry .ao-disc-title {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
}
.ao-telemetry .ao-table-detail .ao-disc-body {
    border-top: 0;
    padding: 4px 8px 4px 24px;
}
/* The absolute stamp beside the relative one, quieter and in the mono face.
 * The agents table spends that width on its four row actions instead; the
 * stamp stays in the cell's tooltip (tsSpan sets title). */
.ao-telemetry .ao-ts-abs {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}
.ao-agents .ao-ts-abs {
    display: none;
}
/* The actions cell ends in the row's drill-down chevron, as Team's rows.
 * The shared td:has(> .ao-actrow) rule no longer reaches the cell (the row
 * sits one level down), so the cell lifts the 320px cap itself. */
.ao-table.ao-agents td:has(> .ao-ag-row-end) {
    max-width: none;
    white-space: normal;
}
.ao-ag-row-end {
    align-items: center;
    display: flex;
    gap: 10px;
    justify-content: flex-end;
}
.ao-ag-row-end > .ao-ag-row-acts {
    flex: none;
}
.ao-ag-row-go {
    color: var(--ao-fg-mute);
    display: inline-flex;
    flex: none;
    margin-left: auto;
    transition:
        color var(--ao-fast) var(--ao-ease),
        transform var(--ao-fast) var(--ao-ease);
}
.ao-agents tr[data-key]:hover .ao-ag-row-go {
    color: var(--ao-fg);
    transform: translateX(2px);
}
/* Row actions stay one line of pills; a narrow table scrolls in its wrap. */
.ao-ag-row-acts {
    flex-wrap: nowrap;
    gap: 6px;
}
.ao-ag-row-acts .ao-btn,
.ao-fl-hb-table .ao-actrow .ao-btn {
    white-space: nowrap;
}
.ao-table.ao-fl-hb-table td:has(> .ao-actrow) {
    white-space: nowrap;
}
.ao-fl-hb-table .ao-actrow {
    flex-wrap: nowrap;
}
/* SHOW N ONLINE: a phone-only control (the online rows fold there). */
.ao-btn.ao-fl-hb-more {
    display: none;
}

/* Readiness card: a full-width banner — the verdict on the left, the
 * checklist beside it (two columns when there is room). The fleet counts it
 * used to carry lead the activity strip above as KPI cards. */
.ao-ag-ready {
    display: grid;
    gap: 14px 24px;
    grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
}
.ao-ag-ready > .ao-sec-head {
    grid-column: 1 / -1;
    margin-bottom: 0;
}
.ao-ag-ready > .ao-ag-verdict {
    grid-column: 1;
}
.ao-ag-ready > .ao-ag-checks {
    align-content: center;
    display: grid;
    grid-column: 2;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
/* In a card an aoSection drops to the card-title size; these two cards ARE
 * page sections (Activity, Telemetry and Agents are full headings beside
 * them), so they keep the page-heading size, as Team's in-card "Team pulse"
 * does. */
.ao-card.ao-ag-ready > .ao-sec-head > .ao-sec-h,
.ao-card.ao-ag-console > .ao-sec-head > .ao-sec-h {
    font-size: var(--ao-fs-h);
}
.ao-ag-verdict {
    align-items: center;
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    display: flex;
    gap: 12px;
    padding: 12px 14px;
}
.ao-ag-ready.is-ready .ao-ag-verdict {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
}
.ao-ag-ready.is-blocked .ao-ag-verdict {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
}
.ao-ag-verdict > .ao-dot {
    height: 10px;
    width: 10px;
}
.ao-ag-verdict-word {
    font-size: var(--ao-fs-h);
    font-weight: 700;
    letter-spacing: 0.04em;
    line-height: 1.2;
}
.ao-ag-ready.is-ready .ao-ag-verdict-word {
    color: var(--ao-ok-text);
}
.ao-ag-ready.is-blocked .ao-ag-verdict-word {
    color: var(--ao-warn-text);
}
.ao-ag-verdict-sub {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    margin-top: 2px;
}
.ao-ag-checks {
    display: flex;
    flex-direction: column;
    gap: 9px;
}
.ao-ag-check {
    align-items: flex-start;
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 10px;
}
.ao-ag-check-mark {
    border-radius: var(--ao-r-tag);
    display: grid;
    flex: none;
    height: 18px;
    margin-top: 1px;
    place-items: center;
    position: relative;
    width: 18px;
}
.ao-ag-check.is-ok .ao-ag-check-mark {
    background: var(--ao-ok-soft);
    color: var(--ao-ok-text);
}
.ao-ag-check.is-fail .ao-ag-check-mark {
    background: var(--ao-err-soft);
    color: var(--ao-err-strong);
}
.ao-ag-check-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.ao-ag-check.is-ok .ao-ag-check-label {
    color: var(--ao-fg-dim);
}
.ao-ag-check-hint {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
/* RUN COMMAND console. */
.ao-ag-field-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.1em;
    margin-bottom: 8px;
}
.ao-ag-run {
    gap: 8px;
}
.ao-ag-run-agent {
    max-width: 240px;
}
.ao-ag-spec {
    align-items: center;
    color: var(--ao-fg-dim);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 8px;
    margin-top: 10px;
    min-height: 20px;
}
.ao-ag-tier {
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    display: inline-block;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.06em;
    padding: 0 7px;
    text-transform: uppercase;
}
/* Colour tracks blast radius; an unknown tier stays neutral, never green. */
.ao-ag-tier.is-read {
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-ag-tier.is-operate,
.ao-ag-tier.is-mutate {
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-text);
}
.ao-ag-tier.is-privileged {
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-ag-tier.is-unknown {
    border-color: var(--ao-border-soft);
}
.ao-ag-spec-hazard {
    align-items: center;
    color: var(--ao-err-fg);
    display: inline-flex;
    gap: 5px;
}
.ao-ag-spec-last {
    color: var(--ao-fg-mute);
}
.ao-ag-out {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-md);
    box-shadow: inset 3px 0 0 var(--ao-ok);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    margin: 12px 0 0;
    max-height: 220px;
    overflow: auto;
    padding: 10px 12px;
    white-space: pre-wrap;
    word-break: break-word;
}
.ao-ag-out.is-fail {
    box-shadow: inset 3px 0 0 var(--ao-err-strong);
}
.ao-ag-hint {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.6;
}
.ao-ag-code {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-sm);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    padding: 1px 6px;
    word-break: break-all;
}

/* ── Fleet / agents modals (appended to <body>) ──────────────────────────── */
/* Appended to <body>, so nothing inherits from #argus-ops-root: the face is
 * set here or the modal paints in the browser's serif — and so is the
 * border-box sizing, or a width:100% input spills its padding and border
 * past the card's right edge. */
.ao-agf-modal,
.ao-agf-modal *,
.ao-agf-modal *::before,
.ao-agf-modal *::after {
    box-sizing: border-box;
}
.ao-agf-modal {
    align-items: center;
    background: var(--ao-overlay);
    display: flex;
    font-family: var(--ao-font-sans);
    inset: 0;
    justify-content: center;
    padding: 24px;
    position: fixed;
    z-index: 99998;
}
.ao-agf-modal-card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-3);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-strong);
    max-height: 92vh;
    overflow: auto;
    padding: 22px;
    width: 100%;
}
.ao-agf-modal-card.is-sm {
    max-width: 520px;
}
.ao-agf-modal-card.is-md {
    max-width: 680px;
}
.ao-agf-modal-card.is-wide {
    max-width: 1100px;
}
/* Outside #argus-ops-root the console's reset of main.css's 44px box does
 * not reach; the pills keep their own literal floor, and no stretched width. */
.ao-agf-modal .ao-btn {
    min-width: auto;
}
.ao-agf-modal-head {
    align-items: flex-start;
    display: flex;
    gap: 12px;
    margin-bottom: 14px;
}
.ao-agf-modal-ico {
    background: var(--ao-tint-2);
    border-radius: 10px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    display: grid;
    flex: none;
    height: 34px;
    place-items: center;
    width: 34px;
}
.ao-agf-modal-titles {
    min-width: 0;
}
.ao-agf-modal-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    font-weight: 600;
    margin: 0;
    overflow-wrap: anywhere;
}
.ao-agf-modal-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.45;
    margin-top: 3px;
}
.ao-agf-modal-id {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    margin-top: 2px;
    overflow-wrap: anywhere;
}
.ao-agf-modal-warn {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    line-height: 1.45;
    margin-bottom: 12px;
}
.ao-agf-modal-warn.is-warn {
    background: var(--ao-warn-bg);
    border: 1px solid var(--ao-warn-bd);
    border-radius: var(--ao-r-md);
    color: var(--ao-warn-fg);
    padding: 8px 12px;
}
.ao-agf-modal .ao-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 10px;
}
.ao-agf-modal .ao-field-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
/* The text boxes: 34px, a visible border and a focus ring (outside the
 * console root nothing styled them). */
.ao-agf-modal input.ao-input {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-ctl);
    color: var(--ao-fg);
    font-family: inherit;
    font-size: var(--ao-fs-body);
    min-height: 34px;
    padding: 0 12px;
    transition: border-color var(--ao-fast) var(--ao-ease);
    width: 100%;
}
.ao-agf-modal input.ao-input::placeholder {
    color: var(--ao-fg-mute);
}
.ao-agf-modal input.ao-input:hover {
    border-color: color-mix(in srgb, var(--ao-fg-mute) 45%, var(--ao-border));
}
.ao-agf-modal input.ao-input:focus-visible {
    border-color: var(--ao-focus);
    outline: 2px solid var(--ao-focus);
    outline-offset: 1px;
}
.ao-agf-modal-err {
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-body);
    margin-top: 6px;
    min-height: 16px;
}
.ao-agf-modal-err:empty {
    margin: 0;
    min-height: 0;
}
/* Right-aligned, as the RESTART confirm's buttons (their order in the page
 * is unchanged). */
.ao-agf-modal-acts {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: flex-end;
    margin: 12px 0;
}

/* LIVE CHECK wall. */
.ao-lc-status {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 8px;
    margin-bottom: 10px;
    min-height: 16px;
}
/* Before START the line has nothing to say: no empty band above REASON. */
.ao-lc-status:empty {
    display: none;
}
.ao-lc-status.is-live {
    color: var(--ao-ok-text);
}
.ao-lc-status.is-live::before {
    background: var(--ao-ok);
    border-radius: 50%;
    box-shadow: 0 0 0 3px var(--ao-ok-soft);
    content: '';
    flex: none;
    height: 8px;
    width: 8px;
}
.ao-lc-wall {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
}
.ao-lc-tile {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    box-shadow: var(--ao-elev-1);
    cursor: pointer;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transition:
        transform var(--ao-base) var(--ao-ease),
        box-shadow var(--ao-base) var(--ao-ease);
}
.ao-lc-tile:hover,
.ao-lc-tile:focus-visible {
    box-shadow: var(--ao-elev-2);
    transform: translateY(-2px);
}
.ao-lc-tile:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-lc-tile.is-err {
    border-color: var(--ao-warn-bd);
}
.ao-lc-frame {
    align-items: center;
    aspect-ratio: 16 / 9;
    background: var(--ao-bg);
    display: flex;
    justify-content: center;
    position: relative;
}
.ao-lc-img {
    height: 100%;
    object-fit: contain;
    transition: opacity var(--ao-base) var(--ao-ease);
    width: 100%;
}
.ao-lc-img.is-dim {
    opacity: 0.25;
}
.ao-lc-err {
    align-items: center;
    background: var(--ao-surface);
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-meta);
    inset: 0;
    justify-content: center;
    padding: 10px;
    position: absolute;
    text-align: center;
}
.ao-lc-cap {
    align-items: center;
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: 8px;
    justify-content: space-between;
    padding: 7px 10px;
}
.ao-lc-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-lc-age {
    color: var(--ao-fg-mute);
    flex: none;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    white-space: nowrap;
}
.ao-lc-enlarged {
    margin-bottom: 12px;
}
.ao-lc-enlarged-bar {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 12px;
    margin-bottom: 8px;
}
.ao-lc-enlarged-img {
    background: var(--ao-bg);
    border-radius: var(--ao-r-lg);
    cursor: zoom-out;
    max-height: 60vh;
    object-fit: contain;
    width: 100%;
}
.ao-lc-enlarged-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    min-width: 0;
}

/* View-camera modal: CAMERA, the telemetry's camera chips, and the box
 * for any other id. */
.ao-vc-field {
    gap: 8px;
}
.ao-vc-input {
    margin-bottom: 4px;
    width: 100%;
}
.ao-vc-status {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-bottom: 6px;
    min-height: 15px;
}
.ao-vc-status.is-err {
    color: var(--ao-err-strong);
}
.ao-vc-status.is-ok {
    color: var(--ao-ok-text);
}
.ao-vc-out {
    margin-top: 8px;
}
/* Where the frame will be, before there is one. */
.ao-vc-empty {
    align-items: center;
    aspect-ratio: 16 / 9;
    background: var(--ao-bg);
    border: 1px dashed var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    color: var(--ao-fg-mute);
    display: flex;
    flex-direction: column;
    font-size: var(--ao-fs-meta);
    gap: 8px;
    justify-content: center;
}
.ao-vc-err {
    color: var(--ao-err-strong);
    font-size: var(--ao-fs-body);
}
.ao-vc-img {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    display: block;
    max-width: 100%;
}
.ao-vc-cap {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    margin-top: 6px;
}

@media (max-width: 900px) {
    .ao-ag-ready {
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-ag-ready > .ao-ag-verdict,
    .ao-ag-ready > .ao-ag-checks {
        grid-column: 1;
    }
}
/* ── Phone ─────────────────────────────────────────────────────────────────
 * The three agent tables (paired devices, telemetry, agents) stack: each row
 * is one block — who and their state on top, the readings under it with
 * their column's label (td[data-label], set by _agfCellLabels), the row's
 * buttons wrapping at the bottom. Scrolled sideways, every status and button
 * sat off-screen inside a box that also scrolled down. */
@media (max-width: 760px) {
    .ao-fl-kv {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    /* No holes: two columns, and a lone last card takes the whole row. */
    .ao-stat-row.ao-fl-funnel,
    .ao-stat-row.ao-ag-kpis {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .ao-fl-funnel > .ao-stat:last-child:nth-child(odd),
    .ao-ag-kpis > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
    .ao-agf-modal {
        padding: 12px;
    }
    .ao-agf-modal-card {
        padding: 16px;
    }
    .ao-ag-bar .ao-picker-trigger {
        min-width: 0;
    }

    /* Camera rows: the frame count under the name, VIEW LIVE as its icon. */
    .ao-fl-cam-id {
        column-gap: 8px;
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
    }
    .ao-fl-cam-id > .ao-dot {
        grid-row: 1;
    }
    .ao-fl-cam-name,
    .ao-fl-cam-live {
        grid-column: 2;
    }
    /* The icon-only pill keeps an outline, or a lone ▷ reads as a glyph. */
    .ao-btn.ao-fl-cam-btn {
        justify-content: center;
        padding: 0;
        width: 26px;
    }
    .ao-btn.ao-fl-cam-btn:not(:hover):not(:focus-visible) {
        background: var(--ao-surface);
        border-color: var(--ao-border-soft);
    }
    .ao-fl-cam-btn .ao-btn-label {
        display: none;
    }

    /* Paired devices: the online rows fold behind SHOW N ONLINE, so the dark
     * and spotty ones lead and the agent cards are not two screens down;
     * the folded list needs no 440px inner scroll box (inline max-height). */
    .ao-fl-hb .ao-table-wrap.is-scroll {
        max-height: none !important;
        overflow-y: visible;
    }
    .ao-fl-hb.is-folded .ao-fl-hb-table > tbody > tr.ao-fl-hb-online,
    .ao-fl-hb.is-folded.is-all-online > .ao-table-wrap {
        display: none;
    }
    .ao-btn.ao-fl-hb-more {
        display: inline-flex;
        margin-top: 8px;
    }

    /* Stacked rows. */
    .ao-table.ao-fl-hb-table,
    .ao-table.ao-telemetry,
    .ao-table.ao-agents,
    .ao-table.ao-fl-hist-table,
    .ao-fl-hb-table > tbody,
    .ao-telemetry > tbody,
    .ao-agents > tbody,
    .ao-fl-hist-table > tbody {
        display: block;
    }
    .ao-fl-hb-table > thead,
    .ao-telemetry > thead,
    .ao-agents > thead,
    .ao-fl-hist-table > thead {
        display: none;
    }
    .ao-fl-hb-table > tbody > tr[data-key],
    .ao-telemetry > tbody > tr[data-key],
    .ao-agents > tbody > tr[data-key],
    .ao-fl-hist-table > tbody > tr[data-key] {
        align-items: center;
        border-bottom: 1px solid var(--ao-border-soft);
        display: flex;
        flex-wrap: wrap;
        gap: 10px 12px;
        padding: 12px 14px;
    }
    .ao-fl-hb-table > tbody > tr[data-key]:last-child,
    .ao-telemetry > tbody > tr:last-child,
    .ao-agents > tbody > tr[data-key]:last-child,
    .ao-fl-hist-table > tbody > tr[data-key]:last-child {
        border-bottom: 0;
    }
    .ao-table.ao-fl-hb-table > tbody > tr > td,
    .ao-table.ao-telemetry > tbody > tr > td,
    .ao-table.ao-agents > tbody > tr > td,
    .ao-table.ao-fl-hist-table > tbody > tr > td {
        border: 0;
        max-width: none;
        min-width: 0;
        padding: 0;
        text-align: left;
        white-space: normal;
    }
    /* The row, not its cells, takes the hover (the cells no longer tile it). */
    .ao-table.ao-fl-hb-table > tbody > tr[data-key]:hover,
    .ao-table.ao-telemetry > tbody > tr[data-key]:hover,
    .ao-table.ao-agents > tbody > tr[data-key]:hover,
    .ao-table.ao-fl-hist-table > tbody > tr[data-key]:hover {
        background: var(--ao-hover);
    }
    .ao-table.ao-fl-hb-table > tbody > tr[data-key]:hover > td,
    .ao-table.ao-telemetry > tbody > tr[data-key]:hover > td,
    .ao-table.ao-agents > tbody > tr[data-key]:hover > td,
    .ao-table.ao-fl-hist-table > tbody > tr[data-key]:hover > td {
        background: transparent;
    }
    .ao-table.ao-fl-hb-table > tbody > tr[data-key]:hover > td:first-child,
    .ao-table.ao-telemetry > tbody > tr[data-key]:hover > td:first-child,
    .ao-table.ao-agents > tbody > tr[data-key]:hover > td:first-child,
    .ao-table.ao-fl-hist-table > tbody > tr[data-key]:hover > td:first-child {
        box-shadow: none;
    }
    /* The id sublines: the name leads, and the row has no width to spare. */
    .ao-fl-hb-table .ao-identity-id,
    .ao-telemetry .ao-identity-id,
    .ao-agents .ao-identity-id {
        display: none;
    }
    .ao-telemetry .ao-ts-abs {
        display: none;
    }
    .ao-table.ao-telemetry > tbody > tr > td[data-label]::before,
    .ao-table.ao-agents > tbody > tr > td[data-label]::before {
        color: var(--ao-fg-mute);
        content: attr(data-label);
        display: block;
        font-family: var(--ao-font-sans);
        font-size: var(--ao-fs-label);
        font-weight: 600;
        letter-spacing: 0.08em;
        margin-bottom: 2px;
    }

    /* Paired devices: store · status / device / buttons. PLATFORM / VERSION
     * is the one column a phone leaves out. */
    .ao-fl-hb-table > tbody > tr > td:nth-child(1) {
        flex: 1 1 0;
        order: 1;
    }
    .ao-fl-hb-table > tbody > tr > td:nth-child(4) {
        flex: none;
        order: 2;
    }
    .ao-fl-hb-table > tbody > tr > td:nth-child(2) {
        color: var(--ao-fg-mute);
        flex: 1 1 100%;
        font-size: var(--ao-fs-meta);
        margin-top: -6px;
        order: 3;
        overflow-wrap: anywhere;
    }
    .ao-fl-hb-table > tbody > tr > td:nth-child(3) {
        display: none;
    }
    .ao-fl-hb-table > tbody > tr > td:nth-child(5) {
        flex: 1 1 100%;
        order: 4;
    }
    /* The three directives fit one line once their icons step aside. */
    .ao-table.ao-fl-hb-table .ao-actrow {
        flex-wrap: wrap;
        gap: 6px;
    }
    .ao-fl-hb-table .ao-actrow .ao-btn > .ao-ico {
        display: none;
    }

    /* Telemetry: agent · pipeline / CPU · MEM / version · uptime · cameras ·
     * last seen, each reading under its label. */
    /* Half the row at least, so the name and the pipeline pill fill the
     * first line and CPU / MEM start the second. */
    .ao-telemetry > tbody > tr > td:nth-child(1) {
        flex: 1 1 50%;
        order: 1;
    }
    .ao-table.ao-telemetry > tbody > tr > td:nth-child(1)::before,
    .ao-table.ao-telemetry > tbody > tr > td:nth-child(7)::before,
    .ao-table.ao-agents > tbody > tr > td:nth-child(1)::before,
    .ao-table.ao-agents > tbody > tr > td:nth-child(2)::before,
    .ao-table.ao-agents > tbody > tr > td:nth-child(3)::before {
        content: none;
    }
    .ao-telemetry > tbody > tr > td:nth-child(7) {
        flex: none;
        order: 2;
    }
    .ao-telemetry > tbody > tr > td:nth-child(5),
    .ao-telemetry > tbody > tr > td:nth-child(6) {
        flex: 1 1 calc(50% - 6px);
        order: 3;
    }
    .ao-telemetry > tbody > tr > td:nth-child(2),
    .ao-telemetry > tbody > tr > td:nth-child(3),
    .ao-telemetry > tbody > tr > td:nth-child(4),
    .ao-telemetry > tbody > tr > td:nth-child(8) {
        flex: 1 1 calc(25% - 9px);
        order: 4;
    }
    .ao-telemetry > tbody > tr[data-key]:has(+ tr.ao-table-detail) {
        border-bottom: 0;
        padding-bottom: 2px;
    }
    .ao-telemetry > tbody > tr.ao-table-detail {
        border-bottom: 1px solid var(--ao-border-soft);
        display: block;
        padding: 0 2px 4px;
    }
    .ao-table.ao-telemetry > tbody > tr.ao-table-detail > td {
        display: block;
    }

    /* Agents: agent · status · connection / last seen (in the id's place) /
     * buttons. */
    .ao-agents > tbody > tr > td:nth-child(1) {
        flex: 1 1 0;
        order: 1;
    }
    .ao-agents > tbody > tr > td:nth-child(2),
    .ao-agents > tbody > tr > td:nth-child(3) {
        flex: none;
        order: 2;
    }
    .ao-table.ao-agents > tbody > tr > td:nth-child(4) {
        color: var(--ao-fg-mute);
        flex: 1 1 100%;
        font-size: var(--ao-fs-meta);
        margin-top: -6px;
        order: 3;
    }
    .ao-table.ao-agents > tbody > tr > td:nth-child(4)::before {
        display: inline;
        margin-right: 6px;
    }
    .ao-agents > tbody > tr > td:nth-child(5) {
        display: none;
    }
    .ao-agents > tbody > tr > td:nth-child(6) {
        flex: 1 1 100%;
        order: 4;
    }
    .ao-actrow.ao-ag-row-acts {
        flex-wrap: wrap;
    }
    /* The chevron stays at the right end of the buttons' line. */
    .ao-ag-row-end {
        align-items: flex-end;
        justify-content: space-between;
    }
    .ao-ag-row-end > .ao-ag-row-acts {
        flex: 1 1 auto;
        min-width: 0;
    }

    /* Enrollment history: store · lifecycle / agent · last seen. The two
     * 55% bases cannot share a line, so the agent always starts line two. */
    .ao-fl-hist-table > tbody > tr > td:nth-child(2) {
        flex: 1 1 55%;
        font-weight: 500;
        order: 1;
    }
    .ao-fl-hist-table > tbody > tr > td:nth-child(1) {
        flex: none;
        order: 2;
    }
    .ao-table.ao-fl-hist-table > tbody > tr > td:nth-child(3) {
        color: var(--ao-fg-mute);
        flex: 1 1 55%;
        font-size: var(--ao-fs-meta);
        margin-top: -6px;
        order: 3;
        overflow-wrap: anywhere;
    }
    .ao-table.ao-fl-hist-table > tbody > tr > td:nth-child(4) {
        color: var(--ao-fg-mute);
        flex: none;
        font-size: var(--ao-fs-meta);
        margin-top: -6px;
        order: 4;
    }
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-lc-tile,
    :where(html:not([data-motion='full'])) .ao-lc-img,
    :where(html:not([data-motion='full'])) .ao-fl-cam,
    :where(html:not([data-motion='full'])) .ao-fl-tech-sum .ao-ico,
    :where(html:not([data-motion='full'])) .ao-telemetry .ao-disc-sum > .ao-ico,
    :where(html:not([data-motion='full'])) .ao-ag-row-go,
    :where(html:not([data-motion='full'])) .ao-ag-bar .ao-picker-trigger,
    :where(html:not([data-motion='full'])) .ao-ag-console .ao-tselect-trigger,
    :where(html:not([data-motion='full'])) .ao-agf-modal input.ao-input {
        transition: none;
    }
    :where(html:not([data-motion='full'])) .ao-lc-tile:hover,
    :where(html:not([data-motion='full'])) .ao-lc-tile:focus-visible,
    :where(html:not([data-motion='full'])) .ao-agents tr[data-key]:hover .ao-ag-row-go {
        transform: none;
    }
}

/* ── Planner decision detail (inside an aoTable detail disclosure) ────────── */
.ao-dec-detail {
    background: var(--ao-tint);
    border-radius: var(--ao-r-lg);
    padding: 12px 16px;
}
.ao-dec-grid {
    display: grid;
    font-size: var(--ao-fs-meta);
    gap: 24px;
    grid-template-columns: 1fr 1fr;
}
/* One column on a narrow viewport — the two-column grid was the reason this
 * panel needed a horizontal scroll on a laptop. */
@media (max-width: 720px) {
    .ao-dec-grid {
        grid-template-columns: 1fr;
    }
}
.ao-dec-colh {
    color: var(--ao-fg-mute);
    font-weight: 600;
    letter-spacing: 0.08em;
    margin-bottom: 6px;
}
.ao-dec-reason {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    margin-top: 12px;
    padding: 8px 12px;
}
/* A D / F reason is the err callout (was an inverted ink bar). */
.ao-dec-reason.is-bad {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    box-shadow: inset 3px 0 0 var(--ao-err-fg);
    color: var(--ao-fg);
}

/* ══ BATCH b06 — ARCHITECTURE · COMPUTE · PLANNER DECISIONS (rehaul 2026-09-23)
 * #/architecture, #/compute and #/decisions in the Team page's family: KPI
 * strips (aoStat.row), aoTable cards, aoSection heads, .ao-btn variants.
 * .ao-b6-* are the pieces the three pages share (page frame, callout, chip,
 * command chips, footer, the compute step-up modals); .ao-cmp-* is compute;
 * .ao-dec-* planner decisions. Tokens only. ═══════════════════════════════ */

/* ── page frame ─────────────────────────────────────────────────────────── */
.ao-b6-page {
    gap: var(--ao-s-5);
    /* No sideways page scroll at a phone width: a wide table scrolls in its
     * own wrap; anything else is clipped, not scrolled. */
    overflow-x: clip;
}
.ao-b6-panel,
.ao-b6-block {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.ao-b6-panel {
    gap: var(--ao-s-6);
}
.ao-b6-block {
    gap: var(--ao-s-3);
}
/* The block's flex gap spaces a heading from what follows it. */
.ao-b6-block > .ao-sec-head,
.ao-b6-lead > .ao-sec-head,
.ao-cmp-pricing > .ao-sec-head {
    margin-bottom: 0;
}
.ao-b6-page .ao-empty {
    margin: 0;
}
.ao-b6-lead {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.ao-b6-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    margin: 0;
    max-width: 760px;
}
.ao-b6-foot {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.04em;
}
/* The head's meta line and its freshness pill (the Team page's "Collected
 * 1d ago"): the time is one the payload carries; the dot says how old. */
.ao-b6-headmeta {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 10px;
}
.ao-b6-sync {
    align-items: center;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    gap: 7px;
    line-height: 1.5;
    max-width: 100%;
    padding: 2px 10px 2px 9px;
}
.ao-b6-sync-dot {
    background: currentColor;
    border-radius: 50%;
    color: var(--ao-fg-mute);
    flex: none;
    height: 7px;
    position: relative;
    width: 7px;
}
.ao-b6-sync.is-ok .ao-b6-sync-dot {
    color: var(--ao-ok);
}
.ao-b6-sync.is-warn .ao-b6-sync-dot {
    color: var(--ao-warn);
}
.ao-b6-sync.is-err {
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-b6-sync.is-err .ao-b6-sync-dot {
    color: var(--ao-err-strong);
}
/* A fresh reading breathes (the server card's ring, same keyframes). */
.ao-b6-sync.is-ok .ao-b6-sync-dot::after {
    animation: ao-b6-ping 2.4s var(--ao-ease) infinite;
    border: 1px solid currentColor;
    border-radius: 50%;
    box-sizing: border-box;
    content: '';
    inset: 0;
    position: absolute;
}
.ao-b6-strong {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-b6-muted {
    color: var(--ao-fg-mute);
}
/* A word the source keeps in capitals (tests read it as written), shown in
 * lower case so a notice does not shout. */
.ao-b6-lc {
    text-transform: lowercase;
}
/* A page's filter row: the .ao-bar layout, not the legacy bordered strip. */
.ao-toolbar.ao-cmp-toolbar,
.ao-toolbar.ao-dec-toolbar {
    border-bottom: 0;
    gap: var(--ao-s-3) var(--ao-s-4);
    padding: 0;
}

/* ── callout: a tinted notice with an icon tile ────────────────────────── */
.ao-b6-callout {
    align-items: flex-start;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    color: var(--ao-fg);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-body);
    gap: var(--ao-s-2) var(--ao-s-3);
    line-height: 1.45;
    padding: 10px 14px;
}
.ao-b6-callout-ico {
    background: var(--ao-tint-2);
    border-radius: 8px;
    display: grid;
    flex: none;
    height: 26px;
    place-items: center;
    width: 26px;
}
.ao-b6-callout-text {
    align-self: center;
    flex: 1 1 220px;
    min-width: 0;
    overflow-wrap: anywhere;
}
/* The notice's own action (the spend note's ORPHAN PODS jump), pinned right;
 * on a phone it wraps under the text. */
.ao-b6-callout-act {
    align-self: center;
    flex: none;
    margin-left: auto;
}
.ao-b6-callout.is-err {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    box-shadow: inset 3px 0 0 var(--ao-err-fg);
}
.ao-b6-callout.is-err .ao-b6-callout-ico {
    background: var(--ao-err-soft);
    color: var(--ao-err-fg);
}
.ao-b6-callout.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    box-shadow: inset 3px 0 0 var(--ao-warn-fg);
}
.ao-b6-callout.is-warn .ao-b6-callout-ico {
    color: var(--ao-warn-fg);
}
.ao-b6-callout.is-compact {
    font-size: var(--ao-fs-meta);
    gap: var(--ao-s-2);
    padding: 6px 10px;
}
.ao-b6-callout.is-compact .ao-b6-callout-ico {
    height: 22px;
    width: 22px;
}
.ao-b6-callout.is-drawer {
    margin: 12px;
}

/* ── chips, id cells, commands ─────────────────────────────────────────── */
.ao-b6-chip {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 4px;
    letter-spacing: 0.04em;
    line-height: 1.6;
    padding: 0 7px;
    white-space: nowrap;
}
.ao-b6-chip .ao-ico {
    flex: none;
    height: 11px;
    width: 11px;
}
.ao-b6-chip.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-b6-chip.is-gold {
    border-color: var(--ao-warn-border);
    color: var(--ao-tm-gold);
}
.ao-b6-chip.is-info {
    background: var(--ao-info-bg);
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-b6-chip.is-err {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-b6-idcell {
    align-items: center;
    display: inline-flex;
    gap: 6px;
    white-space: nowrap;
}
.ao-b6-stack {
    align-items: flex-start;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.ao-b6-subid {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}
/* Camera routing: the store under the camera is a phone's (the desktop has
 * a STORE column). */
.ao-b6-camstore {
    color: var(--ao-fg-mute);
    display: none;
    font-size: var(--ao-fs-meta);
}
.ao-b6-camstore .ao-identity-name {
    color: var(--ao-fg-dim);
    font-weight: 400;
    white-space: normal;
}
.ao-b6-acts {
    display: inline-flex;
    gap: 6px;
    white-space: nowrap;
}
.ao-b6-cmds {
    align-items: flex-start;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
/* A CLI one-liner is a copy chip: click or Enter copies it (a toast says
 * so). The copy glyph brightens with the hover / focus. */
.ao-b6-cmd {
    align-items: center;
    background: var(--ao-bg);
    border: 1px solid var(--ao-border-faint);
    border-radius: 6px;
    color: var(--ao-ok-text);
    cursor: copy;
    display: inline-flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    gap: 6px;
    line-height: 1.6;
    padding: 0 6px;
    transition:
        background var(--ao-fast) var(--ao-ease),
        border-color var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease);
    white-space: nowrap;
}
/* In the All workers table the commands are reference, not the row's
 * point: muted until the row is hovered or the chip focused. */
.ao-cmp-workers .ao-b6-cmd {
    color: var(--ao-fg-mute);
}
.ao-cmp-workers tr:hover .ao-b6-cmd,
.ao-cmp-workers .ao-b6-cmd:focus-visible {
    color: var(--ao-ok-text);
}
.ao-b6-cmd .ao-ico {
    color: var(--ao-fg-mute);
    flex: none;
    height: 11px;
    width: 11px;
}
.ao-b6-cmd:hover,
.ao-b6-cmd:focus-visible {
    background: var(--ao-hover);
    border-color: var(--ao-border);
}
.ao-b6-cmd:hover .ao-ico,
.ao-b6-cmd:focus-visible .ao-ico {
    color: var(--ao-fg);
}
.ao-b6-cmd:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 1px;
}
.ao-b6-cmdrow {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.ao-b6-cmdrow .ao-b6-cmd {
    overflow-wrap: anywhere;
    white-space: normal;
}
.ao-b6-cmdrow-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}

/* ── KPI meters: aoStat {pct} on these strips ───────────────────────────── */
/* aoStat draws the meter as an aoState bar with no state, which the shared
 * CSS leaves unfilled; here it is the card's own accent, full width, pinned
 * to the card foot so meters line up across a row. */
.ao-b6-kpis .ao-stat > .ao-state-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: block;
    height: 4px;
    margin-top: auto;
    min-width: 0;
    width: 100%;
}
.ao-b6-kpis .ao-stat > .ao-state-bar .ao-state-bar-fill {
    background: linear-gradient(
        90deg,
        color-mix(in srgb, var(--ao-stat-accent, var(--ao-k-5)) 45%, transparent),
        var(--ao-stat-accent, var(--ao-k-5))
    );
    border-radius: inherit;
    transform-origin: left center;
}
.ao-b6-kpis .ao-stat > .ao-state-bar .ao-state-bar-label {
    display: none;
}
/* The meter fills on a navigation's first paint only (.ao-in is added by
 * aoIn under the paint-enter flag, never on a poll). Transform-only, no fill
 * mode: a paused tab shows the full meter, not an empty one. */
.ao-b6-kpis .ao-stat.ao-in > .ao-state-bar .ao-state-bar-fill {
    animation: ao-b6-meter 900ms var(--ao-ease);
}
@keyframes ao-b6-meter {
    from {
        transform: scaleX(0);
    }
    to {
        transform: scaleX(1);
    }
}
/* Phone: two cards a row, so an odd last card takes the whole row instead of
 * leaving a hole beside it. */
@media (max-width: 480px) {
    .ao-b6-kpis > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
}
/* A count that should be zero and is not (D / F grades, failed applies,
 * emergencies, idle servers, idle spend): the number, a tinted tile and the
 * "needs a look" pill all say so — aoStat itself tints only the icon tile,
 * and the numbers read white. */
.ao-b6-kpis .ao-stat:has(> .ao-state-pill.is-err) {
    background:
        linear-gradient(180deg, var(--ao-err-bg), transparent 65%),
        linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-color: var(--ao-err-bd);
}
.ao-b6-kpis .ao-stat:has(> .ao-state-pill.is-warn) {
    background:
        linear-gradient(180deg, var(--ao-warn-bg), transparent 65%),
        linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-color: var(--ao-warn-bd);
}
.ao-b6-kpis .ao-stat:has(> .ao-state-pill.is-err) .ao-stat-num,
.ao-b6-kpis .ao-stat:has(> .ao-state-pill.is-err) .ao-stat-num.is-counting::after {
    color: var(--ao-err-strong);
}
.ao-b6-kpis .ao-stat:has(> .ao-state-pill.is-warn) .ao-stat-num,
.ao-b6-kpis .ao-stat:has(> .ao-state-pill.is-warn) .ao-stat-num.is-counting::after {
    color: var(--ao-warn);
}
/* While the number counts up its text stays transparent (the rolling frame
 * is the ::after above); the colour rule must not paint the final number
 * under it. */
.ao-b6-kpis .ao-stat:has(> .ao-state-pill.is-err) .ao-stat-num.is-counting,
.ao-b6-kpis .ao-stat:has(> .ao-state-pill.is-warn) .ao-stat-num.is-counting {
    color: transparent;
}

/* ── table bars: a hue per quantity, and the number on the row's line ──── */
/* The shared bar is the brand rose, which read as "danger" on load, $/hr and
 * GPU% alike. Load / cameras are a KPI hue, money is warn, GPU% a second
 * KPI hue. */
.ao-b6-providers td:nth-child(3) .ao-table-bar-fill,
.ao-b6-workers td:nth-child(6) .ao-table-bar-fill {
    background: linear-gradient(90deg, color-mix(in srgb, var(--ao-k-3) 40%, transparent), var(--ao-k-3));
}
.ao-b6-workers td:nth-child(9) .ao-table-bar-fill {
    background: linear-gradient(90deg, color-mix(in srgb, var(--ao-k-1) 40%, transparent), var(--ao-k-1));
}
.ao-b6-providers td:nth-child(5) .ao-table-bar-fill,
.ao-cmp-workers td:nth-child(3) .ao-table-bar-fill {
    background: linear-gradient(90deg, color-mix(in srgb, var(--ao-warn) 40%, transparent), var(--ao-warn));
}
/* Spend by customer / provider: the share bar fills half the card (it was
 * an empty middle), paying customers in gold, idle time in amber. */
.ao-cmp-break-table th:nth-child(2) {
    width: 50%;
}
.ao-cmp-break-table td:nth-child(2) .ao-table-bar-fill {
    background: linear-gradient(90deg, color-mix(in srgb, var(--ao-tm-gold) 40%, transparent), var(--ao-tm-gold));
}
.ao-cmp-break-table tr.is-idle td:nth-child(2) .ao-table-bar-fill {
    background: linear-gradient(90deg, color-mix(in srgb, var(--ao-warn-text) 40%, transparent), var(--ao-warn-text));
}
/* Providers: the worker count and its starting / unhealthy chips. */
.ao-b6-provw {
    white-space: nowrap;
}
/* The track sits under the number instead of below it in flow, so a bar
 * cell's number lines up with the rest of the row (it rode ~4px high). */
.ao-b6-page td.has-bar {
    position: relative;
}
.ao-b6-page td.has-bar .ao-table-bar {
    bottom: 5px;
    left: 12px;
    margin: 0;
    position: absolute;
    right: 12px;
}
.ao-b6-page .ao-table.is-dense td.has-bar .ao-table-bar {
    bottom: 2px;
    height: 3px;
    left: 10px;
    right: 10px;
}

/* ── compute: spend ────────────────────────────────────────────────────── */
/* Three providers or more: the provider table beside the (longer) customer
 * one, one third / two thirds, both cards as tall as the taller. Two or
 * fewer: the split is a share bar in "Spent this month" and customers take
 * the whole row (.is-single). */
.ao-cmp-split {
    align-items: stretch;
    display: grid;
    gap: var(--ao-s-4) var(--ao-s-3);
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
}
.ao-cmp-split.is-single {
    grid-template-columns: minmax(0, 1fr);
}
/* A new heading after a notice or a table gets a section's air, not a
 * row gap. */
.ao-cmp-split,
.ao-cmp-orphans {
    margin-top: var(--ao-s-3);
}
.ao-cmp-break > .ao-table-wrap {
    flex: 1 1 auto;
}
@media (max-width: 760px) {
    .ao-cmp-split {
        grid-template-columns: minmax(0, 1fr);
    }
}
/* ── compute: economics ────────────────────────────────────────────────── */
/* The provider filter sits under the heading, the two charts share the row
 * evenly (the spend split is 1/3 + 2/3), and the floor server is tinted. */
.ao-cmp-econ > .ao-seg-field {
    margin: 0 0 var(--ao-s-3);
}
.ao-cmp-econ-cap {
    margin-top: var(--ao-s-3);
}
.ao-cmp-econ-charts {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}
.ao-cmp-econ-curve .ao-b6-note,
.ao-cmp-econ-history .ao-b6-note {
    display: block;
    margin-top: 8px;
}
.ao-cmp-econ-table tr.is-floor td {
    background: color-mix(in srgb, var(--ao-ok) 10%, transparent);
}
.ao-cmp-econ-notes {
    margin: 0;
    padding-left: 18px;
}
.ao-cmp-econ-notes li + li {
    margin-top: 4px;
}
.ao-cmp-econ > .ao-b6-callout {
    margin-top: var(--ao-s-3);
}
@media (max-width: 760px) {
    .ao-cmp-econ-charts {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ── compute: the revamped page (2026-09-27, plan §A) ─────────────────── */
/* Eight sections, each a card-less block like the rest of b06, with the
 * figure primitive every number rides in: the value, its kind as a small
 * muted tag, and "Not known" (never a zero) with the reason when missing. */
.ao-cmp-sec {
    scroll-margin-top: var(--ao-s-6);
}
.ao-cmp-head-sub {
    align-items: baseline;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 4px 10px;
}
.ao-cmp-asof {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
    white-space: nowrap;
}
.ao-cmp-asof.is-unknown {
    font-style: italic;
}
.ao-cmp-fig {
    align-items: baseline;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 2px 6px;
    max-width: 100%;
    min-width: 0;
}
.ao-cmp-fig.is-block {
    display: flex;
}
.ao-cmp-fig-val {
    color: var(--ao-fg);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}
.ao-cmp-fig-val.is-neg {
    color: var(--ao-warn-fg);
}
.ao-cmp-fig.is-unknown .ao-cmp-fig-val {
    color: var(--ao-fg-dim);
    font-style: italic;
}
.ao-cmp-fig.is-over .ao-cmp-fig-val {
    color: var(--ao-warn-fg);
    font-weight: 600;
}
.ao-cmp-fig-why {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    line-height: 1.35;
    overflow-wrap: anywhere;
}
/* The kind: one small muted word, a hue per kind so a column of mixed
 * kinds reads at a glance. The words carry it; the hue only helps. */
.ao-cmp-kind {
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 500;
    letter-spacing: 0.02em;
    line-height: 1.5;
    padding: 0 5px;
    white-space: nowrap;
}
.ao-cmp-kind.is-measured {
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-cmp-kind.is-estimated {
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-cmp-kind.is-list_price {
    border-color: var(--ao-info-border);
    color: var(--ao-info-fg);
}
.ao-cmp-kind.is-entered_by_hand {
    border-style: dashed;
    color: var(--ao-fg-dim);
}
.ao-cmp-line {
    align-items: baseline;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 2px 4px;
}
.ao-cmp-line-label {
    color: var(--ao-fg-mute);
}
.ao-cmp-stack {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}
.ao-cmp-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.4;
    overflow-wrap: anywhere;
}
.ao-cmp-sub .ao-cmp-fig-val {
    color: var(--ao-fg-dim);
}

/* KPI tiles: the kind, the reason and the extra lines under the number. */
.ao-cmp-stat-sub {
    display: flex;
    flex-direction: column;
    gap: 3px;
    align-items: flex-start;
}
.ao-cmp-stat-extra {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.35;
}
.ao-cmp-kpis .ao-stat.is-unknown .ao-stat-num {
    color: var(--ao-fg-dim);
    font-style: italic;
}
.ao-cmp-totals {
    align-items: baseline;
    color: var(--ao-fg-dim);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 6px 18px;
}

/* Cards (credits, specs): two across on a wide screen, one on a phone. */
.ao-cmp-cards {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 420px), 1fr));
}
.ao-cmp-cards > .ao-card {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-cmp-card-head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 10px;
    justify-content: space-between;
}
.ao-cmp-card-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-cmp-chips {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 4px;
}
.ao-kv.ao-cmp-kv {
    gap: 6px 14px;
    grid-template-columns: minmax(96px, 150px) minmax(0, 1fr);
}
.ao-kv.ao-cmp-kv dt {
    color: var(--ao-fg-mute);
    opacity: 1;
}
.ao-cmp-how {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.45;
    margin: 0;
}
.ao-cmp-readings,
.ao-cmp-drift,
.ao-cmp-abstained,
.ao-cmp-model-notes,
.ao-cmp-notes-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 0;
    padding-left: 18px;
}
.ao-cmp-readings {
    list-style: none;
    padding-left: 0;
}
.ao-cmp-reading-head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ao-cmp-reading-vals {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 14px;
}
.ao-cmp-quota {
    border-top: 1px solid var(--ao-border-soft);
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding-top: var(--ao-s-3);
}
.ao-cmp-price-table tr.is-total td {
    font-weight: 600;
}

/* Forms (a credit reading, a new credit, a note). Buttons stay the plain
 * surface pill: never the bright red one on this page. */
.ao-cmp-form {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    padding: var(--ao-s-2) 0;
}
.ao-cmp-form-segs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2) var(--ao-s-4);
}
.ao-cmp-form-grid {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr));
}
.ao-cmp-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.ao-cmp-field-label {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
.ao-cmp-field-hint {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}
.ao-cmp-form-acts {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2) var(--ao-s-3);
    justify-content: flex-end;
}
.ao-cmp-form-acts > .ao-cmp-sub {
    flex: 1 1 220px;
}
.ao-cmp-form-err {
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-meta);
}
.ao-cmp-form-err:empty {
    display: none;
}
.ao-cmp-foot {
    margin-top: var(--ao-s-1);
}

/* ── Compute page: Summary, headroom, Switch panel, Report (2026-09-28) ─────
 * The Summary leads the page; each running server is a card with cameras
 * now, room for more, what limits it and what one camera uses. The Report is
 * a full-page layer whose toolbar never prints; @media print below prints the
 * report alone. Surface tones only: no bright red anywhere. */
.ao-cmp-rooms {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 420px), 1fr));
    margin-top: var(--ao-s-3);
}
.ao-cmp-room {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    min-width: 0;
}
.ao-cmp-room-top {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 10px;
    justify-content: space-between;
}
.ao-cmp-room-name {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-cmp-room-nums {
    display: grid;
    gap: var(--ao-s-2) var(--ao-s-4);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 120px), 1fr));
}
.ao-cmp-room-num {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.ao-cmp-room-num > .ao-cmp-fig .ao-cmp-fig-val {
    font-size: var(--ao-fs-h2);
    font-weight: 600;
}
.ao-cmp-room-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.02em;
}
.ao-cmp-room-limit {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.ao-cmp-percam-head {
    margin-top: var(--ao-s-1);
}
.ao-cmp-percam {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-1) var(--ao-s-4);
}
.ao-cmp-percam-item {
    align-items: baseline;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 2px 6px;
    min-width: 0;
}
.ao-cmp-percam-label {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
.ao-cmp-limits {
    display: flex;
    flex-direction: column;
    gap: 4px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-cmp-limit {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: 2px 8px;
}
.ao-cmp-limit-name {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    min-width: 110px;
}
.ao-cmp-limit.is-contradicted .ao-cmp-fig-val {
    text-decoration: line-through;
    color: var(--ao-fg-mute);
}
.ao-cmp-limit-note {
    color: var(--ao-fg-mute);
    flex-basis: 100%;
    font-size: var(--ao-fs-label);
}

/* Switch panel */
.ao-cmp-swap-card {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    margin: var(--ao-s-3) 0;
}
.ao-cmp-swap-what {
    margin: 0;
}
.ao-cmp-swap-steps {
    column-gap: var(--ao-s-5);
    column-width: 280px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-cmp-swap-steps > li {
    break-inside: avoid;
    margin-bottom: 4px;
}
.ao-cmp-report-limits-h {
    margin: var(--ao-s-2) 0 var(--ao-s-1);
}
.ao-cmp-swap-step-n {
    color: var(--ao-fg-mute);
    font-variant-numeric: tabular-nums;
    min-width: 18px;
}
.ao-cmp-swap-step {
    align-items: baseline;
    color: var(--ao-fg-dim);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 2px 8px;
}
.ao-cmp-swap-step-dot {
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-pill);
    display: inline-block;
    flex: 0 0 auto;
    height: 8px;
    width: 8px;
}
.ao-cmp-swap-step.is-done .ao-cmp-swap-step-dot {
    background: var(--ao-fg-dim);
    border-color: var(--ao-fg-dim);
}
.ao-cmp-swap-step.is-now .ao-cmp-swap-step-dot {
    border-color: var(--ao-fg);
    box-shadow: 0 0 0 2px var(--ao-border-soft);
}
.ao-cmp-swap-step.is-now .ao-cmp-swap-step-name {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-cmp-swap-step.is-failed .ao-cmp-swap-step-dot {
    background: var(--ao-warn);
    border-color: var(--ao-warn);
}
.ao-cmp-swap-confirm {
    border-top: 1px solid var(--ao-border-soft);
}
.ao-cmp-swap-log {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    list-style: none;
    margin: var(--ao-s-3) 0 0;
    padding: 0;
}
.ao-cmp-swap-log-item {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: var(--ao-s-2) var(--ao-s-3);
}
.ao-cmp-swap-log-top {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 10px;
}
.ao-cmp-swap-log-top > .ao-btn {
    margin-left: auto;
}
.ao-cmp-swap-log-what {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
}
.ao-cmp-swap-log-cost {
    display: flex;
    flex-wrap: wrap;
    gap: 2px var(--ao-s-4);
}
.ao-cmp-swap-log .ao-cmp-sub {
    overflow-wrap: anywhere;
}

/* Engine update panel (inside the switch section) */
.ao-cmp-upd {
    border-top: 1px solid var(--ao-border-soft);
    margin-top: var(--ao-s-4);
    padding-top: var(--ao-s-3);
}
.ao-cmp-upd-title {
    font-size: var(--ao-fs-title);
    margin: 0 0 var(--ao-s-1);
}
.ao-cmp-upd-audit {
    font-size: var(--ao-fs-meta);
    max-height: 420px;
    overflow: auto;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}

/* Report: a full-page layer over the console. */
.ao-cmp-report-overlay {
    background: var(--ao-bg);
    color: var(--ao-fg);
    inset: 0;
    overflow-y: auto;
    position: fixed;
    z-index: 900;
}
.ao-cmp-report-tools {
    align-items: center;
    background: var(--ao-surface);
    border-bottom: 1px solid var(--ao-border-soft);
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2) var(--ao-s-4);
    justify-content: space-between;
    padding: var(--ao-s-2) var(--ao-s-4);
    position: sticky;
    top: 0;
    z-index: 1;
}
.ao-cmp-report-days,
.ao-cmp-report-tools-acts {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-1) var(--ao-s-2);
}
.ao-btn.ao-cmp-report-day.is-active {
    border-color: var(--ao-fg-dim);
    color: var(--ao-fg);
}
.ao-cmp-report {
    box-sizing: border-box;
    margin: 0 auto;
    max-width: 980px;
    padding: var(--ao-s-5) var(--ao-s-4) var(--ao-s-8);
}
.ao-cmp-report-title {
    font-size: var(--ao-fs-h1);
    margin: 0 0 4px;
}
.ao-cmp-report-meta {
    margin: 0 0 var(--ao-s-3);
}
.ao-cmp-report-sec {
    border-top: 1px solid var(--ao-border-soft);
    padding: var(--ao-s-3) 0;
}
.ao-cmp-report-h {
    font-size: var(--ao-fs-title);
    margin: 0 0 var(--ao-s-2);
}
.ao-cmp-report-h4 {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-strong);
    margin: var(--ao-s-3) 0 var(--ao-s-1);
}
.ao-cmp-report-bottom {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0;
    padding-left: 20px;
}
.ao-cmp-report-bottom li {
    font-size: var(--ao-fs-strong);
    line-height: 1.45;
}
.ao-cmp-report-table {
    border-collapse: collapse;
    font-size: var(--ao-fs-body);
    width: 100%;
}
.ao-cmp-report-table th {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 500;
    padding: 4px 8px 4px 0;
    text-align: left;
}
.ao-cmp-report-table td {
    border-top: 1px solid var(--ao-border-faint);
    padding: 5px 8px 5px 0;
    vertical-align: top;
}
.ao-cmp-report-measure {
    color: var(--ao-fg-dim);
    width: 38%;
}
.ao-cmp-report-asof {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    white-space: nowrap;
    width: 150px;
}
.ao-cmp-report-issues {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: var(--ao-s-2) 0 0;
    padding-left: 18px;
}
@media (max-width: 640px) {
    .ao-cmp-report-asof {
        white-space: normal;
        width: auto;
    }
    .ao-cmp-report-measure {
        width: 42%;
    }
    .ao-cmp-report-tools {
        padding: var(--ao-s-2) var(--ao-s-3);
    }
}
@media print {
    body.ao-cmp-printing > *:not(.ao-cmp-report-overlay) {
        display: none !important;
    }
    body.ao-cmp-printing {
        background: var(--ao-print-paper) !important;
    }
    .ao-cmp-report-overlay {
        background: var(--ao-print-paper);
        color: var(--ao-print-ink);
        overflow: visible;
        position: static;
    }
    .ao-cmp-report-tools {
        display: none !important;
    }
    .ao-cmp-report {
        max-width: none;
        padding: 0;
    }
    .ao-cmp-report,
    .ao-cmp-report .ao-cmp-fig-val,
    .ao-cmp-report .ao-cmp-report-h,
    .ao-cmp-report .ao-cmp-report-title {
        color: var(--ao-print-ink) !important;
    }
    .ao-cmp-report .ao-cmp-kind,
    .ao-cmp-report .ao-cmp-fig-why,
    .ao-cmp-report .ao-cmp-sub,
    .ao-cmp-report-asof,
    .ao-cmp-report-measure {
        color: var(--ao-print-mute) !important;
    }
    .ao-cmp-report-sec {
        border-top-color: var(--ao-print-rule);
        break-inside: avoid;
    }
    .ao-cmp-report .ao-cmp-report-h4,
    .ao-cmp-report .ao-cmp-limit-name,
    .ao-cmp-report .ao-cmp-limit-note {
        color: var(--ao-print-ink) !important;
    }
    .ao-cmp-report .ao-b6-callout {
        background: var(--ao-print-callout) !important;
        border-color: var(--ao-print-rule) !important;
        color: var(--ao-print-ink) !important;
    }
    .ao-cmp-report .ao-b6-callout * {
        color: var(--ao-print-ink) !important;
    }
    .ao-cmp-report-table td {
        border-top-color: var(--ao-print-rule-soft);
    }
}

/* Issues: one row per issue, a severity edge, the fix in bold. */
.ao-cmp-issues-line {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    margin: 0;
}
.ao-cmp-issues,
.ao-cmp-notes {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-cmp-issue {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    box-shadow: inset 3px 0 0 var(--ao-border);
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 10px 14px;
}
.ao-cmp-issue.is-critical {
    box-shadow: inset 3px 0 0 var(--ao-err-fg);
}
.ao-cmp-issue.is-warn {
    box-shadow: inset 3px 0 0 var(--ao-warn-fg);
}
.ao-cmp-issue.is-info {
    box-shadow: inset 3px 0 0 var(--ao-info-fg);
}
.ao-cmp-issue-head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 10px;
}
.ao-cmp-issue-title {
    color: var(--ao-fg);
    font-weight: 600;
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-cmp-issue-detail,
.ao-cmp-issue-fix {
    font-size: var(--ao-fs-body);
    line-height: 1.45;
    margin: 0;
    overflow-wrap: anywhere;
}
.ao-cmp-issue-detail {
    color: var(--ao-fg-dim);
}
.ao-cmp-issue-meta {
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 2px 14px;
}
.ao-kv.ao-cmp-evidence {
    font-size: var(--ao-fs-meta);
    gap: 2px 12px;
    grid-template-columns: minmax(90px, 140px) minmax(0, 1fr);
}
/* Keys: one card per credential, an edge toned by its status, the settings
 * by name, the missing permissions as mono chips, the checks behind a
 * disclosure. "Not checked" is a muted edge, never the green one. */
.ao-cmp-keys {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-cmp-key {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    box-shadow: inset 3px 0 0 var(--ao-border);
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
    padding: 10px 14px;
}
.ao-cmp-key.is-ok {
    box-shadow: inset 3px 0 0 var(--ao-ok-fg);
}
.ao-cmp-key.is-warn {
    box-shadow: inset 3px 0 0 var(--ao-warn-fg);
}
.ao-cmp-key.is-err {
    box-shadow: inset 3px 0 0 var(--ao-err-fg);
}
.ao-cmp-key.is-info {
    box-shadow: inset 3px 0 0 var(--ao-info-fg);
}
.ao-cmp-key.is-muted {
    border-style: dashed;
}
.ao-b6-chip.is-ok {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-text);
}
.ao-b6-chip.is-muted {
    border-style: dashed;
    color: var(--ao-fg-mute);
}
.ao-cmp-key-head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 10px;
    min-width: 0;
}
.ao-cmp-key-title {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-cmp-key-who {
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-cmp-key-for,
.ao-cmp-key-fix,
.ao-cmp-key-note {
    font-size: var(--ao-fs-body);
    line-height: 1.45;
    margin: 0;
    overflow-wrap: anywhere;
}
.ao-cmp-key-for {
    color: var(--ao-fg-dim);
}
.ao-kv.ao-cmp-key-kv {
    font-size: var(--ao-fs-meta);
    gap: 4px 12px;
    grid-template-columns: minmax(80px, 110px) minmax(0, 1fr);
}
.ao-cmp-key-set {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.ao-cmp-key-set-line,
.ao-cmp-key-name {
    overflow-wrap: anywhere;
}
.ao-cmp-key-name.is-unset {
    color: var(--ao-warn-text);
}
.ao-cmp-key-missing {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 4px 6px;
}
.ao-cmp-key-perm-chip {
    background: var(--ao-warn-bg);
    border: 1px solid var(--ao-warn-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-warn-text);
    max-width: 100%;
    overflow-wrap: anywhere;
    padding: 0 6px;
}
.ao-cmp-key .ao-disc {
    margin: 4px 0 0;
}
.ao-cmp-key-checks {
    display: flex;
    flex-direction: column;
    gap: 8px;
    list-style: none;
    margin: 0;
    padding: 10px 12px;
}
.ao-cmp-key-impact {
    font-size: var(--ao-fs-meta);
}
.ao-cmp-key-impact.is-blocking {
    color: var(--ao-warn-text);
    font-weight: 600;
}
.ao-cmp-key-check {
    align-items: flex-start;
    display: flex;
    gap: 8px;
    min-width: 0;
}
.ao-cmp-key-check > .ao-b6-chip {
    flex: none;
    justify-content: center;
    min-width: 84px;
}
.ao-cmp-key-check-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.ao-cmp-key-check-head {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 8px;
}
.ao-cmp-key-check-label {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
}
.ao-cmp-key-perm,
.ao-cmp-key-check-detail {
    overflow-wrap: anywhere;
}
@media (max-width: 560px) {
    .ao-kv.ao-cmp-key-kv {
        gap: 0 0;
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-kv.ao-cmp-key-kv dd {
        margin-bottom: 6px;
    }
    .ao-cmp-key-check {
        flex-direction: column;
        gap: 4px;
    }
}
.ao-cmp-issues-empty.is-clear {
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-cmp-issues-empty.is-partial {
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
/* The head chip beside the freshness pill: a plain pill, toned by the
 * worst issue. */
.ao-cmp-issues-chip[data-tone='err'] {
    border-color: var(--ao-err-border);
    color: var(--ao-err-fg);
}
.ao-cmp-issues-chip[data-tone='warn'] {
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-cmp-issues-chip[data-tone='info'] {
    border-color: var(--ao-info-border);
    color: var(--ao-info-fg);
}
.ao-cmp-issues-chip[data-tone='ok'] {
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}

/* ── database & servers (#/database, 2026-09-29) ───────────────────────── */
/* Built from the compute page's figure, issue and table primitives; only the
 * chart grid, the budget sentence, the event list and the statement text are
 * its own. No raw colour: every rule rides the --ao-* tokens. */
.ao-dbm-findings-list .ao-cmp-issue.is-healthy {
    box-shadow: inset 3px 0 0 var(--ao-ok-text);
}
.ao-dbm-who {
    color: var(--ao-fg-dim);
    font-weight: 500;
}
.ao-dbm-who.is-owner {
    color: var(--ao-warn-text);
}
.ao-dbm-who.is-automatic {
    color: var(--ao-info-fg);
}
.ao-dbm-budget {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
    margin: var(--ao-s-2) 0;
}
.ao-dbm-budget .ao-cmp-fig {
    display: inline;
}
.ao-dbm-budget .ao-cmp-fig-why {
    margin-left: 4px;
}
.ao-dbm-blockers,
.ao-dbm-events {
    display: flex;
    flex-direction: column;
    gap: 6px;
    list-style: none;
    margin: var(--ao-s-2) 0 0;
    padding: 0;
}
.ao-dbm-blocker,
.ao-dbm-event {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-body);
    gap: 2px 8px;
    min-width: 0;
}
.ao-dbm-event-when {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.ao-dbm-charts {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    margin-top: var(--ao-s-2);
}
.ao-dbm-chart {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
    padding: 10px 12px;
}
.ao-dbm-chart-head {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: 2px 8px;
    justify-content: space-between;
}
.ao-dbm-chart-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    font-weight: 600;
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-dbm-chart-peak {
    align-items: baseline;
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 2px;
}
.ao-dbm-chart-empty {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    font-style: italic;
    margin: 0;
    min-height: 64px;
}
.ao-dbm-spark {
    color: var(--ao-accent);
}
.ao-dbm-sql {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    line-height: 1.45;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}
.ao-dbm-action-state {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 10px;
    margin-bottom: var(--ao-s-2);
}
@media (max-width: 760px) {
    .ao-dbm-charts {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Notes: the form, then the log newest first. A note is plain text with
 * its line breaks kept. */
.ao-cmp-note-form .ao-textarea {
    min-height: 72px;
}
.ao-cmp-note {
    border-bottom: 1px solid var(--ao-border-soft);
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 8px 0;
}
.ao-cmp-note-meta {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 4px 10px;
    font-size: var(--ao-fs-meta);
}
.ao-cmp-note-body {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
    margin: 0;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}

/* Milestones: the frame the provider choice dims while it loads. */
.ao-cmp-plan {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-refetching .ao-cmp-plan {
    opacity: 0.55;
    transition: opacity var(--ao-base) var(--ao-ease);
}
.ao-cmp-basis,
.ao-cmp-scale-cap {
    margin: 0;
}
.ao-cmp-swapnote {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.4;
    max-width: 34ch;
}
/* Tables on this page wrap their cells: a figure is a value, a kind tag
 * and sometimes a reason, and the console-wide nowrap + ellipsis would cut
 * the reason off. A table still scrolls inside its own wrap, never the page. */
.ao-cmp-sec .ao-table td {
    max-width: 420px;
    overflow: visible;
    overflow-wrap: break-word;
    text-overflow: clip;
    vertical-align: top;
    white-space: normal;
}
/* A comparison table: measures down, one column per server or provider. */
.ao-cmp-compare {
    table-layout: fixed;
    width: 100%;
}
.ao-cmp-compare th:first-child,
.ao-cmp-compare td:first-child {
    width: clamp(104px, 22%, 200px);
}
.ao-cmp-measure {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
/* A column named for a server keeps its name's case (g6.2xlarge, not G6). */
.ao-cmp-compare th[data-col] {
    letter-spacing: 0.01em;
    overflow-wrap: break-word;
    text-transform: none;
    white-space: normal;
}
@media (max-width: 560px) {
    .ao-cmp-sec .ao-table th,
    .ao-cmp-sec .ao-table td {
        padding: 8px 8px;
    }
    .ao-kv.ao-cmp-kv,
    .ao-kv.ao-cmp-evidence {
        grid-template-columns: minmax(0, 1fr);
        gap: 0 0;
    }
    .ao-kv.ao-cmp-kv dd,
    .ao-kv.ao-cmp-evidence dd {
        margin-bottom: 8px;
    }
}

/* The provider share inside "Spent this month": one bar, a hue per
 * provider, and a legend of name + share. */
.ao-cmp-spent-sub {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.ao-cmp-share {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.ao-cmp-share-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: flex;
    gap: 2px;
    height: 6px;
    overflow: hidden;
}
.ao-cmp-share-seg {
    --ao-cmp-k: var(--ao-k-1);
    background: var(--ao-cmp-k);
    flex-basis: 0;
    min-width: 4px;
}
.ao-cmp-share-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
}
.ao-cmp-share-key {
    --ao-cmp-k: var(--ao-k-1);
    align-items: center;
    display: inline-flex;
    gap: 5px;
}
.ao-cmp-share-dot {
    background: var(--ao-cmp-k);
    border-radius: 50%;
    flex: none;
    height: 7px;
    width: 7px;
}
.ao-cmp-share-name {
    color: var(--ao-fg-dim);
}
.ao-cmp-share-pct {
    color: var(--ao-fg);
    font-variant-numeric: tabular-nums;
}
.ao-cmp-share-seg.k-2,
.ao-cmp-share-key.k-2 {
    --ao-cmp-k: var(--ao-k-2);
}
.ao-cmp-share-seg.k-3,
.ao-cmp-share-key.k-3 {
    --ao-cmp-k: var(--ao-k-3);
}
.ao-cmp-share-seg.k-4,
.ao-cmp-share-key.k-4 {
    --ao-cmp-k: var(--ao-k-4);
}
.ao-cmp-share-seg.k-5,
.ao-cmp-share-key.k-5 {
    --ao-cmp-k: var(--ao-k-5);
}
.ao-cmp-share-seg.k-6,
.ao-cmp-share-key.k-6 {
    --ao-cmp-k: var(--ao-k-6);
}
.ao-cmp-idle {
    color: var(--ao-warn-text);
    font-style: italic;
}

/* ── compute: GPU server cards ─────────────────────────────────────────── */
.ao-cmp-fleet:empty {
    display: none;
}
.ao-running-pods-list {
    /* One row of cards is one height (the served list takes up the slack),
     * so a short card never leaves a hole under it. */
    align-items: stretch;
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 430px), 1fr));
}
.ao-running-pods-list > .ao-empty,
.ao-running-pods-list > .ao-error,
.ao-running-pods-list > .ao-loading {
    grid-column: 1 / -1;
}
.ao-cmp-pod {
    --ao-cmp-tone: var(--ao-border);
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
    overflow: hidden;
    padding: 14px 16px 16px 18px;
    position: relative;
}
/* The tone edge: green working, amber idle / changing, red problem, grey off. */
.ao-cmp-pod::before {
    background: var(--ao-cmp-tone);
    bottom: 0;
    content: '';
    left: 0;
    position: absolute;
    top: 0;
    width: 3px;
}
.ao-cmp-pod.is-ok {
    --ao-cmp-tone: var(--ao-ok);
}
.ao-cmp-pod.is-warn {
    --ao-cmp-tone: var(--ao-warn);
}
.ao-cmp-pod.is-err {
    --ao-cmp-tone: var(--ao-err);
}
/* Status left, buttons right, one line on every card (a long status pill
 * used to push the buttons onto a second line, and that card's GPU name sat
 * lower than its neighbours'). */
.ao-cmp-pod-head {
    align-items: center;
    display: grid;
    gap: 8px;
    grid-template-columns: minmax(0, 1fr) auto;
}
.ao-cmp-pod-head > .ao-cmp-status {
    justify-self: start;
    max-width: 100%;
}
.ao-cmp-pod-acts {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: flex-end;
    margin-left: auto;
}
.ao-cmp-status {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 700;
    gap: 7px;
    letter-spacing: 0.05em;
    line-height: 1.5;
    min-width: 0;
    padding: 2px 10px 2px 8px;
    position: relative;
    text-transform: uppercase;
}
.ao-cmp-status::before {
    background: currentColor;
    border-radius: 50%;
    content: '';
    flex: none;
    height: 7px;
    width: 7px;
}
/* A live ring on a server that is ON and working — the one moving thing on
 * the card, so "which ones are running" reads at a glance. Transform + a
 * fade that starts visible (0.7), infinite, no fill mode. */
.ao-cmp-status.is-ok::after {
    animation: ao-b6-ping 2.4s var(--ao-ease) infinite;
    border: 1px solid currentColor;
    border-radius: 50%;
    box-sizing: border-box;
    content: '';
    height: 7px;
    left: 8px;
    pointer-events: none;
    position: absolute;
    top: calc(50% - 3.5px);
    width: 7px;
}
@keyframes ao-b6-ping {
    from {
        opacity: 0.7;
        transform: scale(1);
    }
    to {
        opacity: 0;
        transform: scale(2.6);
    }
}
.ao-cmp-status.is-ok {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-cmp-status.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-cmp-status.is-err {
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-strong);
}
.ao-cmp-status.is-off {
    border-style: dashed;
    color: var(--ao-fg-mute);
}
.ao-cmp-pod-title {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: 4px 10px;
}
.ao-cmp-pod-gpu {
    color: var(--ao-fg);
    font-size: var(--ao-fs-h);
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.2;
}
.ao-cmp-pod.is-off .ao-cmp-pod-gpu {
    color: var(--ao-fg-dim);
}
.ao-cmp-pod-id {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-cmp-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ao-cmp-fact {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    gap: 6px;
    padding: 3px 10px 3px 8px;
    white-space: nowrap;
}
.ao-cmp-fact[hidden] {
    display: none;
}
.ao-cmp-fact .ao-ico {
    color: var(--ao-fg-mute);
    flex: none;
    height: 13px;
    width: 13px;
}
.ao-cmp-fact.is-ok,
.ao-cmp-fact.is-ok .ao-ico {
    color: var(--ao-ok-text);
}
.ao-cmp-fact.is-warn,
.ao-cmp-fact.is-warn .ao-ico {
    color: var(--ao-warn-text);
}
/* The cameras chip's meter (current / capacity) — a transform, so a poll
 * that moves it eases instead of jumping. */
.ao-cmp-meter {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: inline-block;
    height: 4px;
    overflow: hidden;
    width: 40px;
}
.ao-cmp-meter-fill {
    background: var(--ao-k-1);
    border-radius: inherit;
    display: block;
    height: 100%;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform var(--ao-base) var(--ao-ease);
}
.ao-cmp-served {
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-top: 10px;
}
.ao-cmp-served-group {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.ao-cmp-served-store {
    align-items: center;
    color: var(--ao-fg-dim);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 6px;
}
.ao-cmp-served-store .ao-ico {
    color: var(--ao-fg-mute);
    flex: none;
}
.ao-cmp-served-name {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-cmp-served-tn {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}
.ao-cmp-served-count {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    margin-left: auto;
    min-width: 20px;
    padding: 0 6px;
    text-align: center;
}
.ao-cmp-served-cams {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    padding-left: 19px;
}
.ao-cmp-cam {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: 7px;
    color: var(--ao-fg);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    padding: 1px 8px;
}
.ao-cmp-cam-tn {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}
.ao-cmp-served-none,
.ao-cmp-none {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-cmp-served-none {
    font-style: italic;
}
/* DELETE… — the destructive action in a quiet voice beside TURN OFF. */
.ao-btn.is-ghost.ao-cmp-del {
    color: var(--ao-err-fg);
}
.ao-btn.is-ghost.ao-cmp-del:hover:not(:disabled) {
    background: var(--ao-err-bg);
    color: var(--ao-err-fg);
}
/* RESTART as the fix for a PROBLEM server: the info tint (was .ao-actbtn.is-info). */
.ao-btn.ao-cmp-fix {
    background: var(--ao-info-bg);
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-btn.ao-cmp-fix:hover:not(:disabled) {
    border-color: var(--ao-info-border);
    color: var(--ao-info-fg);
}

/* ── compute: ADVANCED, workers, orphans, pricing ─────────────────────── */
.ao-cmp-adv {
    border-top: 1px solid var(--ao-border-faint);
    gap: var(--ao-s-4);
    padding-top: var(--ao-s-4);
}
/* ADVANCED: a full-width card row — a chevron that turns, the title with
 * what is inside, count chips on the right. A <button>, so the card's type
 * and colour are set here (a button does not inherit them). */
.ao-cmp-adv-toggle {
    align-items: center;
    color: var(--ao-fg);
    cursor: pointer;
    display: grid;
    font: inherit;
    gap: 4px var(--ao-s-3);
    grid-template-columns: auto minmax(0, 1fr) auto;
    padding: 12px 16px;
    text-align: left;
    white-space: nowrap;
    width: 100%;
}
.ao-cmp-adv-toggle:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-cmp-adv-chev {
    background: var(--ao-tint-2);
    border-radius: 9px;
    color: var(--ao-fg-dim);
    display: grid;
    height: 30px;
    place-items: center;
    width: 30px;
}
.ao-cmp-adv-chev .ao-ico {
    transition: transform var(--ao-base) var(--ao-ease);
}
.ao-cmp-adv-toggle.is-open .ao-cmp-adv-chev .ao-ico {
    transform: rotate(90deg);
}
.ao-cmp-adv-text {
    align-items: baseline;
    display: flex;
    gap: 10px;
    min-width: 0;
    overflow: hidden;
}
.ao-cmp-adv-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    font-weight: 600;
}
.ao-cmp-adv-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-cmp-adv-counts {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: flex-end;
}
.ao-cmp-adv-counts:empty {
    display: none;
}
.ao-cmp-adv-body {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-7);
}
.ao-cmp-adv-body[hidden] {
    display: none;
}
.ao-cmp-ttl {
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-label);
}
.ao-cmp-yes {
    color: var(--ao-ok-text);
    font-weight: 700;
}
/* Orphan pods: an aoSection over a card table, like the rest of the page.
 * The spend note's jump focuses the block; a mouse click must not ring it. */
.ao-cmp-orphans {
    scroll-margin-top: var(--ao-s-4);
}
.ao-cmp-orphans:focus:not(:focus-visible) {
    outline: none;
}
.ao-cmp-orphans:focus-visible {
    border-radius: var(--ao-r-lg);
    outline: 2px solid var(--ao-focus);
    outline-offset: 4px;
}
.ao-cmp-orphan-table tr.is-running > td:first-child {
    box-shadow: inset 2px 0 0 var(--ao-err-fg);
}
/* DETAILS is the row's cue, not a second control: a ghost pill (a <span>)
 * that lights with the row it sits in. */
.ao-btn.ao-cmp-details {
    color: var(--ao-fg-dim);
    gap: 2px;
    pointer-events: none;
    white-space: nowrap;
}
.ao-cmp-orphan-table tr:hover .ao-btn.ao-cmp-details,
.ao-cmp-orphan-table tr:focus-visible .ao-btn.ao-cmp-details {
    background: var(--ao-hover);
    border-color: var(--ao-border);
    color: var(--ao-fg);
}
.ao-cmp-pricing {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-cmp-feeds {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ao-cmp-feeds-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    margin-right: 4px;
}
.ao-cmp-feed {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    padding: 2px 10px 2px 8px;
    white-space: nowrap;
}
.ao-cmp-feed-dot {
    background: var(--ao-ok);
    border-radius: 50%;
    flex: none;
    height: 6px;
    width: 6px;
}
.ao-cmp-feed.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
}
.ao-cmp-feed.is-warn .ao-cmp-feed-dot {
    background: var(--ao-warn);
}
.ao-cmp-feed-name {
    color: var(--ao-fg);
    font-weight: 600;
    text-transform: uppercase;
}
.ao-cmp-feed-age {
    color: var(--ao-fg-mute);
}
.ao-cmp-feed-flag {
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* ── compute: the pod drawer ──────────────────────────────────────────── */
/* The drawer and the step-up modals append to <body>, outside
 * #argus-ops-root, so they take the console's face explicitly (standalone,
 * the body has none and they rendered in the browser's serif). */
.ao-cmp-drawer,
.ao-arm-modal-overlay.ao-b6-modal {
    -webkit-font-smoothing: antialiased;
    font-family: var(--ao-font-sans);
}
.ao-cmp-drawer-body {
    font-size: var(--ao-fs-body);
    line-height: 1.5;
    padding: 6px 12px;
}
.ao-cmp-drawer .ao-cmp-served {
    border-top: 0;
    padding-top: 6px;
}
.ao-cmp-drawer .ao-cmp-pod-acts {
    display: flex;
    /* Left at every width (it was right-aligned on a desktop only). */
    justify-content: flex-start;
    margin-left: 0;
}
/* A details list is a card on the drawer (it was bare text). */
.ao-cmp-drawer-card {
    margin: 10px 12px;
    padding: 12px 14px;
}
.ao-cmp-drawer .ao-cmp-drawer-card .ao-kv {
    grid-template-columns: 110px minmax(0, 1fr);
    margin: 0;
}
.ao-cmp-drawer-live .ao-cmp-drawer-card {
    margin-top: 6px;
}
.ao-cmp-drawer-live {
    min-height: 24px;
}
.ao-cmp-drawer-acts {
    padding-top: 8px;
}
.ao-cmp-drawer-link {
    margin-top: 8px;
}
/* Ids keep their case and their letters: the title is set in capitals and
 * the sans face's contextual alternates turned "9x1" into "9×1". */
.ao-cmp-id {
    /* The drawer is on <body>, outside the root's MONO rule. */
    font-family: var(--ao-mono);
    font-feature-settings: 'calt' 0;
    letter-spacing: 0;
    text-transform: none;
}

/* ── compute: the LAUNCH A GPU picker ──────────────────────────────────── */
/* The shared searchable modal, dressed as the step-up modals: the gradient
 * card, and each SKU as a name over a mono meta line. (The face and the
 * blurred scrim are the shared .ao-modal-overlay's now.) */
.ao-cmp-picker .ao-modal-card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-radius: var(--ao-r-xl);
    box-shadow: 0 20px 50px -12px var(--ao-shadow);
}
.ao-cmp-picker .ao-modal-title {
    font-size: var(--ao-fs-title);
    font-weight: 600;
    letter-spacing: 0.02em;
}
.ao-cmp-picker .ao-modal-sub {
    color: var(--ao-fg-mute);
    opacity: 1;
}
.ao-cmp-picker .ao-modal-search {
    background: var(--ao-bg);
    border-color: var(--ao-border);
    min-height: 34px;
}
.ao-cmp-picker .ao-modal-row {
    border-bottom-color: var(--ao-tint-line);
}
.ao-cmp-picker .ao-modal-row.is-active,
.ao-cmp-picker .ao-modal-row:hover {
    background: var(--ao-hover);
}
.ao-cmp-picker .ao-modal-row-main {
    gap: 3px;
}
.ao-cmp-picker .ao-modal-row-name {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
}
.ao-cmp-picker .ao-modal-row-meta {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-feature-settings: 'calt' 0;
    font-size: var(--ao-fs-meta);
    opacity: 1;
}
.ao-cmp-picker .ao-modal-badge {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-weight: 600;
    line-height: 1.6;
    padding: 0 7px;
}
.ao-cmp-picker .ao-modal-badge.is-unarmed {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}

/* ── compute: step-up modals (TURN ON / OFF / RESTART / DELETE, LAUNCH) ── */
.ao-arm-modal-overlay.ao-b6-modal {
    align-items: center;
    background: var(--ao-overlay);
    display: flex;
    inset: 0;
    justify-content: center;
    padding: 24px;
    position: fixed;
    z-index: 99998;
}
.ao-b6-modal-card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    color: var(--ao-fg-dim);
    display: flex;
    flex-direction: column;
    font-size: var(--ao-fs-strong);
    gap: 12px;
    max-height: 90vh;
    max-width: 520px;
    overflow: auto;
    padding: 20px 22px;
    width: 100%;
}
/* Standalone has no global border-box: a 100%-wide padded input would poke
 * out of the card. */
.ao-b6-modal-card,
.ao-b6-modal-card * {
    box-sizing: border-box;
}
.ao-b6-modal-card.is-wide {
    max-width: 560px;
}
.ao-b6-modal-head {
    align-items: center;
    display: flex;
    gap: 10px;
}
.ao-b6-modal-ico {
    background: var(--ao-tint-2);
    border-radius: 9px;
    color: var(--ao-fg-dim);
    display: grid;
    flex: none;
    height: 32px;
    place-items: center;
    width: 32px;
}
.ao-b6-modal-ico.is-ok {
    background: var(--ao-ok-soft);
    color: var(--ao-ok-text);
}
.ao-b6-modal-ico.is-err {
    background: var(--ao-err-soft);
    color: var(--ao-err-fg);
}
.ao-b6-modal-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    font-weight: 600;
    letter-spacing: 0.02em;
    margin: 0;
    overflow-wrap: anywhere;
}
.ao-b6-modal-card .ao-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.ao-b6-modal-card .ao-field-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    letter-spacing: 0.02em;
}
.ao-b6-modal-grid {
    display: grid;
    gap: 12px;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
}
/* The modals append to <body>, so the fields are styled here: a visible
 * border on the card's gradient, the console's focus ring. */
.ao-b6-modal-card .ao-input {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-md);
    color: var(--ao-fg);
    min-height: 34px;
    padding: 6px 10px;
}
.ao-b6-modal-card .ao-input::placeholder {
    color: var(--ao-fg-mute);
}
.ao-b6-modal-card .ao-input:hover {
    border-color: var(--ao-fg-mute);
}
.ao-b6-modal-card .ao-input:focus,
.ao-b6-modal-card .ao-input:focus-visible {
    border-color: var(--ao-accent-line);
    box-shadow: 0 0 0 3px var(--ao-focus-glow);
    outline: none;
}
.ao-b6-modal-check {
    align-items: center;
    cursor: pointer;
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 10px;
}
/* The high-cost acknowledgement: a console checkbox, not the browser's —
 * the gold CTA fill with a drawn tick when checked. */
.ao-b6-modal-check input[type='checkbox'] {
    appearance: none;
    background: var(--ao-bg);
    border: 1px solid var(--ao-border);
    border-radius: 4px;
    cursor: pointer;
    display: grid;
    flex: none;
    height: 16px;
    margin: 0;
    place-items: center;
    transition:
        background var(--ao-fast) var(--ao-ease),
        border-color var(--ao-fast) var(--ao-ease);
    width: 16px;
}
.ao-b6-modal-check input[type='checkbox']::after {
    border: solid var(--ao-cta-fg);
    border-width: 0 2px 2px 0;
    content: '';
    height: 8px;
    margin-top: -2px;
    opacity: 0;
    transform: rotate(45deg);
    width: 4px;
}
.ao-b6-modal-check input[type='checkbox']:hover {
    border-color: var(--ao-fg-mute);
}
.ao-b6-modal-check input[type='checkbox']:checked {
    background: var(--ao-cta);
    border-color: var(--ao-cta-border);
}
.ao-b6-modal-check input[type='checkbox']:checked::after {
    opacity: 1;
}
.ao-b6-modal-check input[type='checkbox']:focus-visible {
    box-shadow: 0 0 0 3px var(--ao-focus-glow);
    outline: 2px solid var(--ao-focus);
    outline-offset: 1px;
}
.ao-b6-modal-err {
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-body);
}
.ao-b6-modal-err:empty {
    display: none;
}
.ao-b6-modal-acts {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: flex-end;
    padding-top: 4px;
}

/* ── planner decisions ─────────────────────────────────────────────────── */
.ao-dec-health {
    align-self: center;
}
.ao-dec-summary {
    gap: var(--ao-s-3);
}
.ao-dec-mix {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px 16px;
}
.ao-dec-mix-head {
    align-items: baseline;
    display: flex;
    gap: 8px;
    justify-content: space-between;
}
.ao-dec-mix-title {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-dec-mix-total {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-dec-mix-bar {
    background: var(--ao-tint);
    border-radius: var(--ao-r-bar);
    display: flex;
    gap: 2px;
    height: 10px;
    overflow: hidden;
}
.ao-dec-mix-seg {
    flex-basis: 0;
    min-width: 4px;
}
.ao-dec-mix-seg.g-A {
    background: var(--ao-ok);
}
.ao-dec-mix-seg.g-B {
    background: var(--ao-k-1);
}
.ao-dec-mix-seg.g-C {
    background: var(--ao-info);
}
.ao-dec-mix-seg.g-D {
    background: var(--ao-warn);
}
.ao-dec-mix-seg.g-F {
    background: var(--ao-err);
}
.ao-dec-mix-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
}
.ao-dec-mix-key {
    align-items: center;
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
}
.ao-dec-mix-n {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-dec-mix-pct {
    color: var(--ao-fg-mute);
}
/* The A–F pill on this page carries the grade's colour (the help page's
 * ink / strike-through pill stays where it is). */
.ao-decisions .ao-rating,
.ao-dec-mix .ao-rating {
    background: var(--ao-tint);
    border-color: var(--ao-border-soft);
    border-radius: 6px;
    color: var(--ao-fg-dim);
    line-height: 1.5;
    min-width: 22px;
    padding: 0 5px;
    text-align: center;
    text-decoration: none;
}
.ao-decisions .ao-rating.t-A,
.ao-dec-mix .ao-rating.t-A {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-decisions .ao-rating.t-B,
.ao-dec-mix .ao-rating.t-B {
    background: color-mix(in srgb, var(--ao-k-1) 14%, transparent);
    border-color: color-mix(in srgb, var(--ao-k-1) 45%, transparent);
    color: var(--ao-k-1);
}
.ao-decisions .ao-rating.t-C,
.ao-dec-mix .ao-rating.t-C {
    background: var(--ao-info-bg);
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-decisions .ao-rating.t-D,
.ao-dec-mix .ao-rating.t-D {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}
.ao-decisions .ao-rating.t-F,
.ao-dec-mix .ao-rating.t-F {
    background: var(--ao-err-soft);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-strong);
}
/* A decision and its "why" disclosure read as one unit: the rule runs under
 * the pair, not between them (the card's row rule and the disclosure's own
 * top border both drew one), and the WHY line is a slim caption whose
 * chevron sits under the CHOSE column's first word (--ao-dec-why: that
 * column's measured left edge, less the disclosure's own inset). */
.ao-table-wrap.is-card .ao-table.ao-decisions tbody tr:not(.ao-table-detail):not(.ao-table-group) > td {
    border-bottom-color: transparent;
}
.ao-decisions .ao-table-detail .ao-disc {
    border-bottom: 0;
    border-top: 0;
}
.ao-decisions .ao-table-detail .ao-disc-sum {
    padding: 4px 12px 8px max(12px, calc(var(--ao-dec-why, 28px) - 16px));
}
/* A word of the choice never breaks inside itself ("us-east-" / "1b"). */
.ao-dec-tok {
    white-space: nowrap;
}
.ao-dec-sec {
    color: var(--ao-fg-mute);
}
/* The GRADE filter carries each grade's colour (the pills' own hues). */
.ao-dec-grades [data-grade] {
    --ao-dec-g: var(--ao-fg-mute);
}
.ao-dec-grades [data-grade='A'] {
    --ao-dec-g: var(--ao-ok-text);
}
.ao-dec-grades [data-grade='B'] {
    --ao-dec-g: var(--ao-k-1);
}
.ao-dec-grades [data-grade='C'] {
    --ao-dec-g: var(--ao-info-fg);
}
.ao-dec-grades [data-grade='D'] {
    --ao-dec-g: var(--ao-warn-text);
}
.ao-dec-grades [data-grade='F'] {
    --ao-dec-g: var(--ao-err-strong);
}
.ao-dec-gdot {
    background: var(--ao-dec-g);
    border-radius: 50%;
    flex: none;
    height: 7px;
    width: 7px;
}
/* The pressed grade keeps its hue as a rule under the segment (a segment of
 * one bar: no border change, no ring). */
.ao-dec-grades [data-grade][aria-pressed='true'] {
    box-shadow: inset 0 -2px 0 color-mix(in srgb, var(--ao-dec-g) 70%, transparent);
}
/* --ao-fg-dim: mute was ~3.9:1 at this size. The meta is the reason, whole. */
.ao-decisions .ao-table-detail .ao-disc-title {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-decisions .ao-table-detail .ao-disc-meta {
    color: var(--ao-fg-dim);
    white-space: normal;
}
/* A decision that failed to apply: full-strength text, an err edge on the
 * row (the pair — row and its WHY line — reads as one unit). */
.ao-decisions tr.is-failed > td:first-child {
    box-shadow: inset 2px 0 0 var(--ao-err-fg);
}
/* Day groups (Today / Yesterday / Sep 20): a quiet band on the card's own
 * ground, not the inverted ink bar. */
.ao-decisions .ao-table-group > td {
    background: var(--ao-bg);
    border-bottom: 1px solid var(--ao-tint-line);
    color: var(--ao-fg-dim);
    font-weight: 600;
    padding: 6px 12px !important;
    top: 0;
}
.ao-decisions .ao-table-group-meta {
    color: var(--ao-fg-mute);
    font-weight: 400;
}
.ao-decisions .ao-table-group-count {
    color: var(--ao-fg-dim);
}
.ao-dec-chose {
    align-items: center;
    display: inline-flex;
    gap: 6px;
    white-space: nowrap;
}
.ao-dec-delta.is-warn {
    color: var(--ao-warn-text);
}
.ao-dec-delta.is-err {
    color: var(--ao-err-strong);
}

/* Phone (≤560px): each table keeps the column its rows are for in view by
 * hiding the low-value ones (a table still scrolls in its own card if it
 * must). Header and cells hide together, by position. */
@media (max-width: 560px) {
    /* Architecture: a tighter gutter and shorter bar tracks, so each card's
     * kept columns fit a phone without scrolling inside the card. */
    .ao-b6-providers th,
    .ao-b6-providers td,
    .ao-b6-workers th,
    .ao-b6-workers td,
    .ao-b6-assign th,
    .ao-b6-assign td {
        padding-left: 7px;
        padding-right: 7px;
    }
    .ao-b6-page .ao-b6-providers td.has-bar,
    .ao-b6-page .ao-b6-workers td.has-bar {
        min-width: 56px;
    }
    .ao-b6-page .ao-b6-providers td.has-bar .ao-table-bar,
    .ao-b6-page .ao-b6-workers td.has-bar .ao-table-bar {
        left: 7px;
        right: 7px;
    }
    /* Providers: fps goes, the load keeps its counts and bar (not the
     * words), and a provider's starting / unhealthy chips drop under its
     * healthy count. */
    .ao-b6-providers th:nth-child(4),
    .ao-b6-providers td:nth-child(4),
    .ao-b6-loadpct {
        display: none;
    }
    .ao-b6-providers .ao-b6-idcell {
        align-items: flex-start;
        flex-direction: column;
        gap: 3px;
    }
    /* A long header ("CAMERAS / CAPACITY") wraps rather than set the
     * column's width. */
    .ao-b6-providers th,
    .ao-b6-workers th {
        white-space: normal;
    }
    /* Workers: the id a step smaller (it sets the first column's width). */
    .ao-b6-workers td:first-child {
        font-size: var(--ao-fs-meta);
    }
    /* Camera routing: camera (the store's name under it), reason and when.
     * The store, worker and previous-worker columns go. */
    .ao-b6-assign th:nth-child(2),
    .ao-b6-assign td:nth-child(2),
    .ao-b6-assign th:nth-child(3),
    .ao-b6-assign td:nth-child(3),
    .ao-b6-assign th:nth-child(5),
    .ao-b6-assign td:nth-child(5) {
        display: none;
    }
    .ao-b6-assign .ao-b6-camstore {
        display: block;
    }
    .ao-b6-assign td:first-child {
        max-width: 170px;
        white-space: normal;
    }
    /* Architecture workers: id, status, cams and GPU% stay (the KPI strip
     * and the providers card carry the rest). */
    .ao-b6-workers th:nth-child(3),
    .ao-b6-workers td:nth-child(3),
    .ao-b6-workers th:nth-child(4),
    .ao-b6-workers td:nth-child(4),
    .ao-b6-workers th:nth-child(5),
    .ao-b6-workers td:nth-child(5),
    .ao-b6-workers th:nth-child(7),
    .ao-b6-workers td:nth-child(7),
    .ao-b6-workers th:nth-child(8),
    .ao-b6-workers td:nth-child(8),
    .ao-b6-workers th:nth-child(10),
    .ao-b6-workers td:nth-child(10),
    .ao-b6-workers th:nth-child(11),
    .ao-b6-workers td:nth-child(11) {
        display: none;
    }
    /* The leader chip is its crown alone (the word stays for a screen
     * reader). */
    .ao-b6-chip.ao-b6-leader {
        gap: 0;
        padding: 0 4px;
    }
    .ao-b6-chip.ao-b6-leader > span {
        clip: rect(0 0 0 0);
        height: 1px;
        overflow: hidden;
        position: absolute;
        white-space: nowrap;
        width: 1px;
    }
    /* Compute all workers: $/hr and cameras (each server card above shows
     * both), pinned, drift, commands; the actions stack. */
    .ao-cmp-workers th:nth-child(3),
    .ao-cmp-workers td:nth-child(3),
    .ao-cmp-workers th:nth-child(4),
    .ao-cmp-workers td:nth-child(4),
    .ao-cmp-workers th:nth-child(5),
    .ao-cmp-workers td:nth-child(5),
    .ao-cmp-workers th:nth-child(6),
    .ao-cmp-workers td:nth-child(6),
    .ao-cmp-workers th:nth-child(7),
    .ao-cmp-workers td:nth-child(7) {
        display: none;
    }
    .ao-cmp-workers .ao-b6-acts {
        align-items: flex-end;
        flex-direction: column;
        gap: 4px;
    }
    /* Orphan pods: the GPU name; DETAILS keeps only its chevron, and the
     * cells take a tighter gutter. */
    .ao-cmp-orphan-table th:nth-child(3),
    .ao-cmp-orphan-table td:nth-child(3) {
        display: none;
    }
    .ao-cmp-orphan-table th,
    .ao-cmp-orphan-table td {
        padding-left: 8px;
        padding-right: 8px;
    }
    .ao-btn.ao-cmp-details {
        padding: 0 4px;
    }
    .ao-btn.ao-cmp-details .ao-btn-label {
        display: none;
    }
    /* GPU pricing: SKU, VRAM, region, AZ, cams, stale (a stale row is dimmed
     * anyway) — provider, GPU, kind and $/hr stay. */
    .ao-catalog th:nth-child(2),
    .ao-catalog td:nth-child(2),
    .ao-catalog th:nth-child(4),
    .ao-catalog td:nth-child(4),
    .ao-catalog th:nth-child(9),
    .ao-catalog td:nth-child(9),
    .ao-catalog th:nth-child(5),
    .ao-catalog td:nth-child(5),
    .ao-catalog th:nth-child(6),
    .ao-catalog td:nth-child(6),
    .ao-catalog th:nth-child(10),
    .ao-catalog td:nth-child(10) {
        display: none;
    }
    /* Planner decisions: pool, $/hr and Δ% (the WHY detail has all three);
     * the time is HH:MM. The choice keeps the width and may wrap. */
    .ao-decisions th:nth-child(2),
    .ao-decisions td:nth-child(2),
    .ao-decisions th:nth-child(5),
    .ao-decisions td:nth-child(5),
    .ao-decisions th:nth-child(6),
    .ao-decisions td:nth-child(6),
    .ao-dec-sec {
        display: none;
    }
    /* The WHY line starts at the card's edge, not under a column. */
    .ao-decisions .ao-table-detail .ao-disc-sum {
        padding-left: 8px;
    }
    /* The choice wraps; its provider chip goes (the SKU names the provider,
     * and the WHY detail spells it out) so a row is not four lines tall. */
    .ao-dec-chose {
        display: block;
        white-space: normal;
    }
    .ao-dec-chose > .ao-b6-chip {
        display: none;
    }
    .ao-decisions th,
    .ao-decisions tr:not(.ao-table-detail):not(.ao-table-group) > td {
        padding-left: 5px;
        padding-right: 5px;
    }
    /* GPU server cards: status, then the GPU and its facts, and the
     * buttons last, full width at the left (they sat between the status and
     * the GPU name). The head dissolves into the card's column. */
    .ao-cmp-pod-head {
        display: contents;
    }
    .ao-cmp-pod-head > .ao-cmp-status {
        align-self: flex-start;
    }
    .ao-cmp-pod .ao-cmp-pod-acts {
        justify-content: flex-start;
        margin-left: 0;
        order: 9;
        width: 100%;
    }
    /* ADVANCED: the count chips move under the title. */
    .ao-cmp-adv-toggle {
        grid-template-columns: auto minmax(0, 1fr);
    }
    .ao-cmp-adv-counts {
        grid-column: 2;
        justify-content: flex-start;
    }
    .ao-cmp-adv-text {
        flex-direction: column;
        gap: 0;
    }
}

/* Phone: the server cards' buttons wrap under the status; the modals get the
 * whole width. */
@media (max-width: 760px) {
    .ao-cmp-pod {
        padding: 12px 12px 14px 14px;
    }
    .ao-cmp-served-cams {
        padding-left: 0;
    }
    .ao-arm-modal-overlay.ao-b6-modal {
        padding: 12px;
    }
    /* The shared drawer's 480px floor is wider than a phone. */
    .ao-drawer.ao-cmp-drawer {
        max-width: 100vw;
        min-width: 0;
        width: 100vw;
    }
    .ao-b6-modal-card {
        padding: 16px;
    }
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-cmp-status.is-ok::after {
        animation: none;
        display: none;
    }
    :where(html:not([data-motion='full'])) .ao-cmp-meter-fill,
    :where(html:not([data-motion='full'])) .ao-cmp-adv-chev .ao-ico,
    :where(html:not([data-motion='full'])) .ao-b6-cmd,
    :where(html:not([data-motion='full'])) .ao-b6-modal-check input[type='checkbox'] {
        transition: none;
    }
    :where(html:not([data-motion='full'])) .ao-b6-kpis .ao-stat.ao-in > .ao-state-bar .ao-state-bar-fill {
        animation: none;
    }
    :where(html:not([data-motion='full'])) .ao-b6-sync.is-ok .ao-b6-sync-dot::after {
        animation: none;
        display: none;
    }
}

/* Sortable column headers (aoTable spec.sort). The indicator is a glyph AND an
 * aria-sort attribute, so the sort direction is not colour- or shape-only.
 *
 * Design system v2: an unsorted sortable column shows a faint ↕ so it reads
 * as sortable BEFORE anyone clicks it. ⛔ It is a pseudo-element, never a
 * text node — the aoTable tests read header text exactly ('STORE', 'FPS'),
 * and the sorted column's .ao-sort-ind (▲/▼) is the only glyph in the DOM.
 * Hover brightens the label instead of underlining it. */
.ao-table th.is-sortable {
    cursor: pointer;
    transition: color var(--ao-fast) var(--ao-ease);
    user-select: none;
}
.ao-table th.is-sortable::after {
    color: var(--ao-fg-mute);
    content: '\2195';
    margin-left: 4px;
    opacity: 0.55;
}
.ao-table th.is-sortable.is-sorted::after {
    content: none;
}
.ao-table th.is-sortable:hover,
.ao-table th.is-sortable:focus-visible {
    color: var(--ao-fg);
}
.ao-table th.is-sortable:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: -2px;
}
.ao-table th.is-sorted {
    color: var(--ao-fg-dim);
}
.ao-sort-ind {
    color: var(--ao-accent);
    margin-left: 4px;
}

/* Profile help disclosure (was two inline cssText blocks). */
.ao-profile-help {
    margin: 4px 0 8px;
}
.ao-profile-help-body {
    line-height: 1.55;
    margin-top: 6px;
}

/* ══ GROWTH + ACCOUNT PAGES — #/profile, #/recipients, #/outreach, #/sms,
 * #/testing, #/engagement (ops rehaul 2026-09-23, design system v2) ═════════
 * The six pages in the Team page's family: a KPI strip (aoStat), Team cards
 * titled by aoSection, .ao-table everywhere, .ao-btn pills. What is here is
 * only what those primitives do not already say — the page kit (_b3Card /
 * _b3Tag / _b3Ico in argus-ops.js) and each page's own pieces. Tokens only:
 * no hex, no SVG paint-server references. */

/* ── page kit ─────────────────────────────────────────────────────────── */
/* A panel painted by paintPanel that lays its sections out with the page
 * gap (the page body is a flex column; a panel inside it is one child). */
.ao-b3-stack {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
/* Two cards side by side, one on a phone. Side by side they end on one
 * line (the Team page's leader cards are one height). */
.ao-b3-grid {
    align-items: stretch;
    display: grid;
    gap: var(--ao-s-4);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
    min-width: 0;
}
.ao-b3-grid > * {
    min-width: 0;
}
.ao-b3-card {
    min-width: 0;
}
/* A table is the card's content, edge to edge: it bleeds through the card's
 * padding, and its first / last columns line up with the card's title. */
/* It bleeds to three edges, so the card is its frame there; the wrap draws
 * only the rule above its header. */
.ao-b3-card > .ao-table-wrap {
    --ao-tbl-head-r: 0px;
    border-radius: 0 0 var(--ao-r-xl) var(--ao-r-xl);
    border-width: 1px 0 0;
    margin: 0 calc(-1 * var(--ao-s-4)) calc(-1 * var(--ao-s-4));
}
.ao-b3-card > .ao-table-wrap .ao-table th:first-child,
.ao-b3-card > .ao-table-wrap .ao-table td:first-child {
    padding-left: var(--ao-s-4);
}
.ao-b3-card > .ao-table-wrap .ao-table th:last-child,
.ao-b3-card > .ao-table-wrap .ao-table td:last-child {
    padding-right: var(--ao-s-4);
}
.ao-b3-card > .ao-table-wrap .ao-table tbody tr:last-child > td {
    border-bottom: 0;
}
/* A card stretched by a taller neighbour in its grid row: the table it ends
 * with runs to the card's bottom edge, so its bottom corners meet the card's
 * instead of the table stopping mid-card with nothing under it. */
.ao-b3-card:has(> .ao-table-wrap:last-child) {
    display: flex;
    flex-direction: column;
}
.ao-b3-card > .ao-table-wrap:last-child {
    flex: 1 1 auto;
}
/* A scroll box that has more past its edge fades there (_b3Fade toggles
 * .has-more), so a row cut by the edge reads as "more below", not as a
 * broken half row; at the end the fade goes. */
.ao-b3-fade-y.has-more {
    -webkit-mask-image: linear-gradient(180deg, black calc(100% - 56px), transparent);
    mask-image: linear-gradient(180deg, black calc(100% - 56px), transparent);
}
.ao-b3-fade-x.has-more {
    -webkit-mask-image: linear-gradient(90deg, black 85%, transparent);
    mask-image: linear-gradient(90deg, black 85%, transparent);
}
/* An empty / unread state is the card's content, not a panel inside it. */
.ao-b3-card > .ao-empty {
    margin: 0;
}
.ao-b3-card > .ao-table-wrap > .ao-empty,
.ao-b3-card > .ao-table-wrap > .ao-table-unread {
    margin: 0 var(--ao-s-4) var(--ao-s-4);
}
/* Engagement's card titles are uppercase literals in the source ("TIME PER
 * PAGE (10)", pinned by its tests): they read in sentence case here, the
 * 15px card title every other card on these pages wears. */
.ao-eng-page .ao-card > .ao-sec-head > .ao-sec-h {
    text-transform: lowercase;
}
.ao-eng-page .ao-card > .ao-sec-head > .ao-sec-h::first-letter {
    text-transform: uppercase;
}
/* The soft tag pill. Tone is a tint + a border + the family's fg — never a
 * full-saturation block. is-muted is dashed: "none", "not set". The type is
 * the state pill's (.ao-state-pill: 10px / 600 / uppercase), so a "Delivered"
 * tag and an "ACTIVE" pill on the same row, or on the next page, are one
 * family. .is-raw keeps an identifier as written (a page key, a hostname). */
.ao-b3-tag {
    align-items: center;
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 5px;
    letter-spacing: 0.03em;
    line-height: 1.6;
    max-width: 100%;
    overflow: hidden;
    padding: 1px 8px;
    text-overflow: ellipsis;
    text-transform: uppercase;
    vertical-align: middle;
    white-space: nowrap;
}
.ao-b3-tag.is-raw {
    font-family: var(--ao-mono);
    letter-spacing: 0;
    text-transform: none;
}
.ao-b3-tag .ao-ico {
    flex: none;
    height: 12px;
    width: 12px;
}
.ao-b3-tag.is-ok {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-b3-tag.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-b3-tag.is-err {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-b3-tag.is-info {
    background: var(--ao-info-bg);
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-b3-tag.is-accent {
    background: var(--ao-tint-2);
    border-color: var(--ao-accent-line);
    color: var(--ao-fg);
}
.ao-b3-tag.is-slate {
    background: var(--ao-tint);
    border-color: var(--ao-border);
    color: var(--ao-fg-dim);
}
.ao-b3-tag.is-muted {
    background: transparent;
    border-color: var(--ao-border);
    border-style: dashed;
    color: var(--ao-fg-mute);
}
.ao-b3-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: var(--ao-s-3);
}
/* A 30px icon tile tinted by a KPI accent (the .ao-stat-ico look). */
.ao-b3-ico {
    background: color-mix(in srgb, var(--ao-b3-accent, var(--ao-fg-mute)) 14%, transparent);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ao-b3-accent, var(--ao-fg-mute)) 24%, transparent);
    color: var(--ao-b3-accent, var(--ao-fg-dim));
    display: inline-grid;
    flex: none;
    height: 30px;
    place-items: center;
    width: 30px;
}
/* A person / agent cell: avatar, name, a muted mono line under it. */
.ao-b3-who {
    align-items: center;
    display: flex;
    gap: 10px;
    min-width: 0;
}
.ao-b3-who-txt {
    display: flex;
    flex-direction: column;
    line-height: 1.3;
    min-width: 0;
}
.ao-b3-who-name {
    color: var(--ao-fg);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-b3-who-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    overflow: hidden;
    text-overflow: ellipsis;
}
/* A tenant cell: the store's name, its id in grey mono under it. */
.ao-b3-tenant {
    min-width: 0;
}
/* A rank. 1 / 2 / 3 are medal pills — the Team rank chip (a tint, a
 * border and the medal's fg; the winner glows and carries a trophy). The
 * silver token reads as plain white on graphite, so 2 is the dim fg. */
.ao-b3-rank {
    align-items: center;
    border: 1px solid transparent;
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    gap: 3px;
    justify-content: center;
    line-height: 1.5;
    min-width: 26px;
    padding: 1px 7px;
}
.ao-b3-rank .ao-ico {
    flex: none;
    height: 11px;
    width: 11px;
}
.ao-b3-rank.is-1 {
    background: color-mix(in srgb, var(--ao-tm-gold) 15%, transparent);
    border-color: color-mix(in srgb, var(--ao-tm-gold) 42%, transparent);
    box-shadow: 0 0 14px -5px var(--ao-tm-gold);
    color: var(--ao-tm-gold);
}
.ao-b3-rank.is-2 {
    background: color-mix(in srgb, var(--ao-fg-dim) 10%, transparent);
    border-color: color-mix(in srgb, var(--ao-fg-dim) 32%, transparent);
    color: var(--ao-fg-dim);
}
.ao-b3-rank.is-3 {
    background: color-mix(in srgb, var(--ao-tm-bronze) 13%, transparent);
    border-color: color-mix(in srgb, var(--ao-tm-bronze) 38%, transparent);
    color: var(--ao-tm-bronze);
}
/* The podium rows: a medal-coloured left edge (the Team row's marker), and
 * the winner's row lit from the left. */
.ao-b3-top.is-top1 {
    --ao-b3-medal: var(--ao-tm-gold);
    background: linear-gradient(90deg, color-mix(in srgb, var(--ao-tm-gold) 9%, transparent), transparent 45%);
}
.ao-b3-top.is-top2 {
    --ao-b3-medal: var(--ao-fg-dim);
}
.ao-b3-top.is-top3 {
    --ao-b3-medal: var(--ao-tm-bronze);
}
@media (min-width: 640.02px) {
    .ao-b3-card .ao-table tbody tr.ao-b3-top:not(.ao-table-group):not(.ao-table-detail) > td:first-child {
        box-shadow: inset 3px 0 0 var(--ao-b3-medal);
    }
}
/* Magnitude bars on these pages: the KPI hue with the Team track's glow,
 * not the rose-to-white default (which read as an error). --ao-b3-bar is
 * the column's hue: volumes --ao-k-1 (the default), rates --ao-ok, a p95
 * --ao-warn, a rep's sends the rep's own avatar hue. The track stops
 * clipping so the glow shows. */
.ao-b3-card .ao-table-bar {
    height: 5px;
    overflow: visible;
}
.ao-b3-card .ao-table-bar-fill {
    background: linear-gradient(
        90deg,
        color-mix(in srgb, var(--ao-b3-bar, var(--ao-k-1)) 45%, transparent),
        var(--ao-b3-bar, var(--ao-k-1))
    );
    box-shadow: 0 0 10px color-mix(in srgb, var(--ao-b3-bar, var(--ao-k-1)) 40%, transparent);
}
.ao-sms-camp td:nth-child(5) {
    --ao-b3-bar: var(--ao-ok);
}
.ao-eng-perf td:nth-child(4) {
    --ao-b3-bar: var(--ao-warn);
}
.ao-b3-card .ao-o-reptable .ao-table-bar-fill {
    background: linear-gradient(90deg, hsl(var(--ao-tm-h) 62% 42%), hsl(var(--ao-tm-h2) 82% 66%));
    box-shadow: 0 0 12px hsl(var(--ao-tm-h) 80% 60% / 0.45);
}
/* A stored key shown as words ("Incident alert"); the key is its title. */
.ao-b3-key {
    color: var(--ao-fg);
}
/* A caption beside a control that is not a segmented tray (the engagement
 * tenant picker): same voice as .ao-seg-cap. */
.ao-eng-page .ao-seg-field > .ao-tselect {
    min-width: 180px;
}
/* The tenant picker was the last square control on these pages: here it is
 * a pill beside the WINDOW tray, its typed ▾ a chevron painted by a mask. */
.ao-eng-page .ao-bar .ao-tselect-trigger {
    background: var(--ao-surface-2);
    border-color: var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint),
        var(--ao-elev-1);
    font-weight: 500;
    min-height: 28px;
    padding: 0 28px 0 12px;
    position: relative;
}
.ao-eng-page .ao-bar .ao-tselect-trigger:hover {
    background: var(--ao-hover);
    border-color: var(--ao-border);
}
.ao-eng-page .ao-bar .ao-tselect-trigger:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-eng-page .ao-bar .ao-tselect-trigger::after {
    background: currentColor;
    content: '';
    float: none;
    height: 14px;
    margin: -7px 0 0;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E")
        center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E")
        center / contain no-repeat;
    opacity: 0.7;
    position: absolute;
    right: 10px;
    top: 50%;
    transition: transform var(--ao-fast) var(--ao-ease);
    width: 14px;
}
.ao-eng-page .ao-bar .ao-tselect-trigger[aria-expanded='true']::after {
    transform: rotate(180deg);
}
.ao-eng-page .ao-bar .ao-tselect-menu {
    background: var(--ao-surface-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    margin-top: 4px;
    padding: 4px;
}
.ao-eng-page .ao-bar .ao-tselect-opt {
    border-radius: var(--ao-r-md);
    padding: 6px 10px;
}
.ao-eng-page .ao-bar .ao-tselect-opt:hover,
.ao-eng-page .ao-bar .ao-tselect-opt.is-active {
    background: var(--ao-hover);
    color: var(--ao-fg);
}

/* ── #/profile ────────────────────────────────────────────────────────── */
.ao-profile-hero {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-4);
    padding: var(--ao-s-5);
}
.ao-profile-hero-who {
    display: flex;
    flex: 1 1 240px;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.ao-profile-hero-name {
    color: var(--ao-fg);
    font-size: var(--ao-fs-h);
    font-weight: 600;
    letter-spacing: -0.01em;
    overflow-wrap: anywhere;
}
.ao-profile-hero-mail {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    overflow-wrap: anywhere;
}
.ao-profile-hero-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
}
/* The session down the hero's right: its facts as a compact list and the
 * way out under them. It drops under the name on a narrow card. */
.ao-profile-hero-side {
    border-left: 1px solid var(--ao-tint-line);
    display: flex;
    flex: 0 1 420px;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
    padding-left: var(--ao-s-5);
}
.ao-profile-hero .ao-profile-hero-kv {
    gap: 5px 14px;
    grid-template-columns: max-content minmax(0, 1fr);
    margin: 0;
}
.ao-profile-hero-kv dt {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    line-height: 1.7;
    opacity: 1;
    text-transform: uppercase;
}
.ao-profile-hero-kv dd {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    margin: 0;
    overflow-wrap: break-word;
    word-break: normal;
}
.ao-profile-hero-acts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
}
@media (max-width: 760px) {
    .ao-profile-hero-side {
        border-left: 0;
        border-top: 1px solid var(--ao-tint-line);
        flex-basis: 100%;
        padding-left: 0;
        padding-top: var(--ao-s-4);
    }
}
/* The tab panes stack their cards with the page gap (keepMounted hides the
 * inactive ones with an inline display:none, which still wins). */
.ao-profile-page .ao-tabs {
    margin: 0;
}
.ao-profile-page .ao-tabs-pane {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
}
.ao-profile-hero-chips > .ao-profile-role-chip {
    background: color-mix(in srgb, var(--ao-k-5) 12%, transparent);
    border-color: color-mix(in srgb, var(--ao-k-5) 40%, transparent);
    color: var(--ao-fg);
}
.ao-profile-hero-chips > .ao-profile-role-chip .ao-ico {
    color: var(--ao-k-5);
}
/* YOU: identity (with the display name) beside the role, one height;
 * quiet hours across the foot in one row. One column on a narrow screen. */
.ao-profile-grid {
    align-items: stretch;
    display: grid;
    gap: var(--ao-s-4);
    grid-template-areas:
        'id role'
        'qh qh';
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.ao-profile-card-id {
    grid-area: id;
}
.ao-profile-card-role {
    grid-area: role;
}
.ao-profile-card-qh {
    grid-area: qh;
}
/* The display name: a field of the identity card under a hairline. */
.ao-profile-name-panel {
    border-top: 1px solid var(--ao-tint-line);
    margin-top: var(--ao-s-4);
    padding-top: var(--ao-s-4);
}
.ao-profile-name-panel .ao-profile-note {
    margin: 2px 0 0;
}
@media (max-width: 980px) {
    .ao-profile-grid {
        grid-template-areas: 'id' 'role' 'qh';
        grid-template-columns: minmax(0, 1fr);
    }
}
/* The role wears the KPI blue, not the brand rose (a rose ring read as an
 * error beside the green / amber status tags). */
.ao-profile-page .ao-role-badge {
    border-color: color-mix(in srgb, var(--ao-k-5) 45%, transparent);
}
.ao-profile-page .ao-role-badge-dot {
    color: var(--ao-k-5);
}
.ao-profile-page .ao-role-ref-row.is-current {
    border-color: color-mix(in srgb, var(--ao-k-5) 40%, transparent);
    box-shadow: inset 2px 0 0 var(--ao-k-5);
}
/* Disclosures sit on the card's own gutter (the shared 16px side margin
 * knocked them out of line with the badge above), and the summary's typed
 * ▸ — label-size, near invisible — is a 14px chevron painted by a mask. */
.ao-profile-page .ao-disc {
    margin: 12px 0;
}
/* The title keeps one line; its note wraps under it on a narrow card. */
.ao-profile-page .ao-disc-sum {
    flex-wrap: wrap;
    row-gap: 2px;
}
.ao-profile-page .ao-disc-title {
    white-space: nowrap;
}
.ao-profile-page .ao-disc-sum::before {
    background: currentColor;
    content: '';
    flex: none;
    height: 14px;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E")
        center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E")
        center / contain no-repeat;
    width: 14px;
}
.ao-profile-section .ao-kv {
    gap: 8px 16px;
    grid-template-columns: minmax(96px, 150px) minmax(0, 1fr);
}
.ao-profile-section .ao-kv dt {
    color: var(--ao-fg-mute);
    opacity: 1;
}
.ao-profile-section .ao-kv dd {
    color: var(--ao-fg);
    word-break: normal;
    overflow-wrap: anywhere;
}
.ao-profile-section .ao-settings-actions {
    margin-top: var(--ao-s-4);
}
/* Quiet hours in one row: FROM · TO · TIMEZONE · MUTE, the save at its end
 * (it wraps under on a narrow card). */
.ao-profile-qh-row .ao-profile-fld.is-mute {
    flex: 0 0 auto;
}
.ao-profile-qh-row .ao-profile-fld.is-mute button.ao-switch {
    min-height: 30px;
}
/* Every save sits at the end of its row, wrapped or not (SAVE NAME,
 * SAVE QUIET HOURS, and Recipients' ADD). */
.ao-profile-row > .ao-profile-save {
    margin-left: auto;
}
/* Display name + quiet hours: two blocks side by side, stacked on a phone
 * (the Settings-style call without a separate name card). */
.ao-profile-ctl {
    display: grid;
    gap: var(--ao-s-5) var(--ao-s-6);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
}
.ao-profile-ctl-block {
    min-width: 0;
}
.ao-profile-ctl-block > .ao-sec-head {
    margin-bottom: 0;
}
.ao-profile-ctl-block > .ao-sec-head > .ao-sec-h {
    font-size: var(--ao-fs-title);
}
.ao-profile-row {
    align-items: flex-end;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2) var(--ao-s-3);
    margin-top: var(--ao-s-3);
}
.ao-profile-row > .ao-input {
    flex: 1 1 200px;
    width: auto;
}
.ao-profile-row.is-foot {
    justify-content: space-between;
}
.ao-profile-fld {
    display: flex;
    flex: 0 1 130px;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.ao-profile-fld.is-wide {
    flex: 1 1 200px;
    max-width: 260px;
}
.ao-profile-page .ao-field-label,
.ao-rcp-modal .ao-field-label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
/* One control height across the row, so FROM / TO / TIMEZONE line up. */
.ao-profile-page .ao-profile-row .ao-input {
    min-height: 30px;
}
/* Native time inputs, in the console's dark theme. */
.ao-profile-page input[type='time'].ao-input {
    color-scheme: dark;
    font-family: var(--ao-mono);
}
.ao-profile-page .ao-profile-help {
    margin: 0 0 var(--ao-s-3);
}
.ao-profile-panel {
    min-width: 0;
}
/* The matrix / channels / activity tables bleed to the card's edges. */
/* Bled to the card's sides (and, last, its bottom): the card is the frame
 * there, so the wrap draws only the rules the card does not. */
.ao-profile-section .ao-profile-panel > .ao-table-wrap {
    --ao-tbl-head-r: 0px;
    border-radius: 0;
    border-width: 1px 0;
    margin: 0 calc(-1 * var(--ao-s-4));
}
.ao-profile-section .ao-profile-panel:last-child > .ao-table-wrap:last-child {
    border-bottom-width: 0;
    border-radius: 0 0 var(--ao-r-xl) var(--ao-r-xl);
    margin-bottom: calc(-1 * var(--ao-s-4));
}
.ao-profile-section .ao-profile-panel .ao-table th:first-child,
.ao-profile-section .ao-profile-panel .ao-table td:first-child {
    padding-left: var(--ao-s-4);
}
.ao-profile-section .ao-profile-panel .ao-table th:last-child,
.ao-profile-section .ao-profile-panel .ao-table td:last-child {
    padding-right: var(--ao-s-4);
}
.ao-profile-section .ao-profile-panel > .ao-empty {
    margin: 0;
}
/* The alert matrix: a switched-off source dims everything after its switch
 * (its channels are kept, they just do not deliver). */
.ao-pref-table td {
    vertical-align: middle;
}
.ao-pref-src {
    color: var(--ao-fg);
    font-weight: 500;
}
.ao-pref-chh-in {
    align-items: center;
    display: inline-flex;
    gap: 5px;
    white-space: nowrap;
}
.ao-pref-chh-in .ao-ico {
    flex: none;
    height: 12px;
    width: 12px;
}
/* The severity tray sizes to its two segments, not the cell. */
.ao-pref-table .ao-seg.ao-tm-seg {
    display: inline-flex;
}
.ao-pref-row[data-enabled='false'] > td:nth-child(n + 3) {
    opacity: 0.45;
}
/* The channel switches carry no state word (the thumb says it). */
.ao-pref-table .ao-switch-text:empty {
    display: none;
}
.ao-pref-row[data-enabled='false'] .ao-pref-src {
    color: var(--ao-fg-mute);
}
/* Channels: the icon tile beside the channel's name. */
.ao-profile-ch {
    align-items: center;
    display: flex;
    gap: 10px;
}
.ao-profile-ch-name {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-profile-ch-addr {
    color: var(--ao-fg-dim);
}
.ao-channels-table td {
    vertical-align: middle;
}
.ao-channels-table td.ao-profile-ch-status {
    max-width: none;
    overflow: visible;
}
.ao-profile-ch-acts {
    align-items: center;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 8px;
}
.ao-profile-sms {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
/* ⛔ .ao-btn sets display:inline-flex, which beats the UA's [hidden]; the
 * two-step SMS row swaps steps with `hidden`, so restate it. */
.ao-profile-sms [hidden],
.ao-profile-ch-acts [hidden],
.ao-channel-err[hidden] {
    display: none !important;
}
.ao-profile-sms-phone {
    width: 150px;
}
.ao-profile-sms-code {
    font-family: var(--ao-mono);
    letter-spacing: 0.2em;
    width: 116px;
}
.ao-channel-err {
    color: var(--ao-err-fg);
    display: block;
    font-size: var(--ao-fs-meta);
    margin-top: 4px;
    white-space: normal;
}
.ao-channel-note {
    align-items: flex-start;
    color: var(--ao-fg-mute);
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: 8px;
    line-height: 1.5;
    margin: var(--ao-s-3) 0 0;
    padding: var(--ao-s-3) 0 0;
}
.ao-channel-note .ao-ico {
    flex: none;
    margin-top: 1px;
}
/* The activity log: the method as a mono chip. */
.ao-profile-method {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.04em;
}
.ao-profile-method.is-post,
.ao-profile-method.is-put,
.ao-profile-method.is-patch {
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-profile-method.is-delete {
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}

/* ── #/recipients ─────────────────────────────────────────────────────── */
/* The roster's numbers lead the page. The painted panel is display:contents,
 * so its KPI strip and channel pills are items of the page column and order
 * above the add bar (which is built first and so still shows while the
 * panel loads or errors); the table card follows the bar. */
.ao-recipients-page > .ao-rcp-panel {
    display: contents;
}
.ao-rcp-panel > .ao-stat-row,
.ao-rcp-panel > .ao-rcp-avail {
    order: -1;
}
/* Add a recipient: one bar — the title and its help left, the form right
 * (aoSection's actions; it wraps under the title on a narrow card). */
.ao-rcp-add {
    padding-bottom: var(--ao-s-3);
    padding-top: var(--ao-s-3);
}
.ao-rcp-add > .ao-sec-head {
    align-items: center;
    margin-bottom: 0;
}
.ao-rcp-add div.ao-sec-actions {
    flex: 1 1 480px;
    justify-content: flex-end;
}
.ao-rcp-form {
    align-items: center;
    display: flex;
    flex: 1 1 auto;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
    justify-content: flex-end;
}
.ao-rcp-form > .ao-input {
    flex: 0 1 240px;
    min-height: 30px;
    min-width: 0;
    width: auto;
}
.ao-rcp-form > .ao-input[type='text'] {
    flex-basis: 190px;
}
/* Which channels can deliver: a caption and three pills that say it. */
.ao-rcp-avail {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2) var(--ao-s-3);
}
.ao-rcp-avail-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ao-rcp-avail-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ao-rcp-acts {
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
}
/* MUTE and UNMUTE take the same width, so PHONE / REMOVE never shift. */
.ao-rcp-acts [data-action='toggle-recipient'] {
    justify-content: center;
    min-width: 96px;
}
/* REMOVE stays neutral until it is pointed at or focused: seven red
 * outlines down a column read as seven alarms. */
.ao-rcp-acts .ao-btn.is-danger:not(:hover):not(:focus-visible) {
    border-color: var(--ao-border-soft);
    color: var(--ao-fg-dim);
}
.ao-channels-table td:last-child {
    max-width: none;
    overflow: visible;
}
/* The phone modal: the shared overlay voice, classes instead of cssText. */
.ao-rcp-modal {
    align-items: center;
    background: var(--ao-overlay);
    display: flex;
    inset: 0;
    justify-content: center;
    padding: var(--ao-s-6);
    position: fixed;
    z-index: 99998;
}
.ao-rcp-modal-card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    color: var(--ao-fg-dim);
    display: flex;
    flex-direction: column;
    font-size: var(--ao-fs-strong);
    gap: var(--ao-s-3);
    max-width: 480px;
    padding: var(--ao-s-5);
    width: 100%;
}
.ao-rcp-modal-head {
    align-items: center;
    display: flex;
    gap: var(--ao-s-3);
}
.ao-rcp-modal-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    font-weight: 600;
    margin: 0;
    overflow-wrap: anywhere;
}
.ao-rcp-modal-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
}
.ao-rcp-modal .ao-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.ao-rcp-modal-err {
    color: var(--ao-warn-text);
    font-size: var(--ao-fs-body);
    min-height: 16px;
}
.ao-rcp-modal-acts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
    justify-content: flex-end;
}

/* ── #/outreach ───────────────────────────────────────────────────────── */
.ao-o-kpis {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
}
/* The sync status is a pill, not a control: the Team .ao-tm-sync look
 * without its pointer. */
.ao-o-sync {
    cursor: default;
}
.ao-o-empty {
    margin: 0;
}
/* Daily volume: the Team pulse chart, coloured by what happened to the
 * sends. Replies on the axis in the KPI teal, opens in the KPI blue, the
 * rest a quiet grey. */
.ao-o-daily .ao-tm-pulse-chart {
    margin-top: var(--ao-s-2);
}
.ao-o-daily .ao-tm-pulse-seg.is-replied,
.ao-o-key.is-replied {
    background: var(--ao-k-1);
}
.ao-o-daily .ao-tm-pulse-seg.is-opened,
.ao-o-key.is-opened {
    background: var(--ao-k-5);
}
.ao-o-daily .ao-tm-pulse-seg.is-unopened,
.ao-o-key.is-unopened {
    background: var(--ao-tint-strong);
}
.ao-o-legend {
    margin-top: var(--ao-s-3);
}
/* A narrow chart keeps the first, middle and last dates (seven collide). */
.ao-o-daily {
    container: ao-o-daily / inline-size;
}
@container ao-o-daily (max-width: 512px) {
    .ao-o-daily .ao-tm-pulse-xl:not(.is-first):not(.is-last):not(.is-mid) {
        display: none;
    }
}
/* The small KPI labels at the meta size (10px read as fine print). A label
 * that wraps ("Active sequences") keeps its number on the row's line. */
.ao-outreach-page .ao-stat.is-sm .ao-stat-label {
    font-size: var(--ao-fs-meta);
}
.ao-outreach-page .ao-stat-row.is-sm > .ao-stat .ao-stat-value {
    margin-top: auto;
}
/* A rate's tone is a dot beside the number — the text never wears it. */
.ao-o-rate {
    align-items: center;
    display: inline-flex;
    gap: 6px;
}
.ao-o-rate::before {
    background: transparent;
    border: 1px solid var(--ao-border);
    border-radius: 50%;
    content: '';
    height: 7px;
    width: 7px;
}
.ao-o-rate.is-ok::before {
    background: var(--ao-ok);
    border-color: transparent;
}
.ao-o-rate.is-warn::before {
    background: var(--ao-warn);
    border-color: transparent;
}
.ao-o-rate.is-err::before {
    background: var(--ao-err-strong);
    border-color: transparent;
}
.ao-o-seqname {
    align-items: center;
    display: flex;
    gap: 8px;
    min-width: 0;
}
.ao-o-seqname-t {
    color: var(--ao-fg);
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-o-feed-rep {
    color: var(--ao-fg);
    font-weight: 600;
}
/* Mailbox health is a card like every other Outreach section (its title
 * the 15px in-card title); each mailbox is a panel inside it. The group is
 * not an .ao-card itself — the mailbox panels are (their tests count them). */
.ao-o-mailboxes {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
    padding: var(--ao-s-4);
}
.ao-o-mailboxes > .ao-sec-head {
    margin-bottom: 0;
}
.ao-o-mailboxes > .ao-sec-head > .ao-sec-h {
    font-size: var(--ao-fs-title);
}
.ao-o-mailboxes > .ao-empty {
    margin: 0;
}
/* One mailbox a row, so its seven stats are one row of seven. */
.ao-o-mbgrid {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: minmax(0, 1fr);
}
.ao-o-mailboxes .ao-o-mb.ao-card {
    background: var(--ao-bg);
    border-radius: var(--ao-r-lg);
    box-shadow: inset 0 1px 0 var(--ao-tint);
}
.ao-o-mb {
    container: ao-o-mb / inline-size;
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    min-width: 0;
}
.ao-o-mb > .ao-stat-row.is-sm {
    grid-template-columns: repeat(7, minmax(0, 1fr));
}
/* A mailbox stat is the Team KPI card in small: the icon tile above its
 * label (a label beside the tile wrapped in a 100-130px card and dropped
 * its number below the row), one number size whatever the card's span, the
 * number on the card's foot so a row lines up. */
.ao-o-mb > .ao-stat-row > .ao-stat .ao-stat-head {
    align-items: flex-start;
    flex-direction: column;
    gap: 8px;
}
.ao-o-mb > .ao-stat-row > .ao-stat .ao-stat-label,
.ao-o-mb > .ao-stat-row > .ao-stat .ao-stat-label-text {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-o-mb > .ao-stat-row > .ao-stat .ao-stat-value {
    margin-top: auto;
}
.ao-o-mb > .ao-stat-row > .ao-stat.is-sm .ao-stat-num {
    font-size: 22px;
}
/* A mailbox narrower than seven cards (a phone, a narrow window): each
 * stat is a compact label / value row, two a row, no icon tile — 28 tiles
 * for four mailboxes was the page. */
@container ao-o-mb (max-width: 799.98px) {
    .ao-o-mb > .ao-stat-row.is-sm {
        gap: 0 var(--ao-s-5);
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .ao-o-mb > .ao-stat-row > .ao-stat.is-sm {
        align-items: baseline;
        background: none;
        border: 0;
        border-bottom: 1px solid var(--ao-tint-line);
        border-radius: 0;
        box-shadow: none;
        flex-direction: row;
        justify-content: space-between;
        min-height: 0;
        padding: 7px 0;
        transform: none;
    }
    .ao-o-mb > .ao-stat-row > .ao-stat.is-sm::before,
    .ao-o-mb > .ao-stat-row > .ao-stat.is-sm .ao-stat-ico {
        display: none;
    }
    .ao-o-mb > .ao-stat-row > .ao-stat.is-sm .ao-stat-head {
        flex-direction: row;
    }
    .ao-o-mb > .ao-stat-row > .ao-stat.is-sm .ao-stat-value {
        margin: 0;
    }
    .ao-o-mb > .ao-stat-row > .ao-stat.is-sm .ao-stat-num {
        font-size: var(--ao-fs-strong);
        letter-spacing: 0;
    }
}
@container ao-o-mb (max-width: 239.98px) {
    .ao-o-mb > .ao-stat-row.is-sm {
        grid-template-columns: minmax(0, 1fr);
    }
}
.ao-o-mb-head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3);
}
.ao-o-mb-who {
    flex: 1 1 200px;
    min-width: 0;
}
.ao-o-mb-mail {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    overflow-wrap: anywhere;
}
.ao-o-mb-alert {
    align-items: center;
    background: var(--ao-warn-bg);
    border: 1px solid var(--ao-warn-bd);
    border-radius: var(--ao-r-md);
    color: var(--ao-warn-fg);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 8px;
    padding: 8px 12px;
}
.ao-o-mb-alert .ao-ico {
    flex: none;
}
.ao-o-mb-warmline {
    align-items: baseline;
    display: flex;
    justify-content: space-between;
    gap: var(--ao-s-3);
}
.ao-o-mb-warmlab {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.ao-o-mb-warmval {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-title);
    font-weight: 600;
}
/* The warmup meter: a scaleX fill (the table bar's motion), toned by class. */
.ao-o-meter {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    height: 8px;
    margin-top: 6px;
    overflow: hidden;
    position: relative;
}
.ao-o-meter-fill {
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
.ao-o-meter-fill.is-ok {
    background: var(--ao-ok);
}
.ao-o-meter-fill.is-warn {
    background: var(--ao-warn);
}
.ao-o-meter-fill.is-off {
    background: var(--ao-border);
}
/* The warmup sparkline's box (_oSparkline draws inside it). The chart
 * insets its first / last sample 4% from each side (PAD 4 of a 100-wide
 * viewBox — pinned by the outreach tests), so the box overhangs the meter by
 * 4/92 each side: the line then runs exactly the meter's width. */
.ao-o-spark {
    /* the grid lines run the full box: trim them to the meter (+6px, room
     * for the endpoint dot and its ring) */
    clip-path: inset(-8px calc(4% - 6px) -8px calc(4% - 6px));
    height: 34px;
    margin: 10px calc(-100% * 4 / 92) 0;
    position: relative;
}

/* ── #/sms ────────────────────────────────────────────────────────────── */
.ao-sms-dir.is-in {
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-sms-status {
    align-items: center;
    display: inline-flex;
    gap: 6px;
    max-width: 100%;
}
.ao-sms-err {
    color: var(--ao-err-fg);
    font-size: var(--ao-fs-meta);
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-sms-preview {
    color: var(--ao-fg-mute);
}
.ao-sms-recent td:last-child {
    max-width: 360px;
}
.ao-sms-tpls {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr));
}
.ao-sms-tpl {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    box-shadow: inset 0 1px 0 var(--ao-tint);
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    min-width: 0;
    padding: var(--ao-s-3) var(--ao-s-4);
}
.ao-sms-tpl-head {
    align-items: center;
    display: flex;
    gap: var(--ao-s-2);
    justify-content: space-between;
}
.ao-sms-tpl-label {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-sms-tpl-body {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    line-height: 1.55;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}
.ao-sms-tpl-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}

/* ── #/testing ────────────────────────────────────────────────────────── */
.ao-tst-console > .ao-sec-head .ao-sec-sub {
    display: inline-flex;
}
.ao-tst-lock {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.04em;
}
.ao-tst-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
    margin: 0 0 var(--ao-s-4);
    max-width: 820px;
}
.ao-tst-groups {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3) var(--ao-s-6);
}
.ao-tst-group {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    min-width: 0;
}
.ao-tst-group-cap {
    align-items: center;
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 6px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ao-tst-btns {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
}
/* Correlator scenarios fire the theft path: the info tint marks them apart
 * from the POS ones (was an inline rgba). */
.ao-btn.ao-tst-inject.is-correlator {
    border-color: var(--ao-info-bd);
}
.ao-btn.ao-tst-inject.is-correlator .ao-ico {
    color: var(--ao-info-fg);
}
.ao-tst-foot {
    align-items: center;
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3);
    justify-content: space-between;
    margin-top: var(--ao-s-4);
    padding-top: var(--ao-s-3);
}
.ao-tst-notify {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
}
.ao-tst-notify-txt {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-tst-verdict {
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.03em;
}
/* Evidence: six tracks, so five cards leave no hole — the two long lists
 * (evaluations, events) take half each, the three short ones a third. With
 * no unmapped SKUs (four cards) the second pair takes half each too. Cards
 * in a row end on one line. */
.ao-tst-evidence {
    align-items: stretch;
    display: grid;
    gap: var(--ao-s-4);
    grid-template-columns: repeat(6, minmax(0, 1fr));
}
.ao-tst-evidence > * {
    grid-column: span 2;
}
.ao-tst-evidence > :nth-child(-n + 2),
.ao-tst-evidence > :nth-child(3):nth-last-child(2),
.ao-tst-evidence > :nth-child(4):last-child {
    grid-column: span 3;
}
@media (max-width: 1180px) {
    .ao-tst-evidence {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .ao-tst-evidence > *,
    .ao-tst-evidence > :nth-child(-n + 2),
    .ao-tst-evidence > :nth-child(3):nth-last-child(2),
    .ao-tst-evidence > :nth-child(4):last-child {
        grid-column: auto;
    }
    .ao-tst-evidence > :last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
}
@media (max-width: 700px) {
    .ao-tst-evidence {
        grid-template-columns: minmax(0, 1fr);
    }
}
.ao-tst-incidents td:last-child {
    max-width: none;
    overflow: visible;
}

/* ── #/engagement ─────────────────────────────────────────────────────── */
.ao-eng-sec {
    min-width: 0;
}
.ao-eng-sec > .ao-empty {
    margin: var(--ao-s-3) 0 0;
}
.ao-eng-dur {
    align-items: center;
    display: inline-flex;
    gap: 6px;
    justify-content: flex-end;
}

/* ── phones ───────────────────────────────────────────────────────────── */
/* A lone last KPI card (five cards two a row) takes the row, not half of it.
 * Below 560px a row holds at most two cards (three need 528px). */
@media (max-width: 559.98px) {
    .ao-profile-page .ao-stat-row > .ao-stat:last-child:nth-child(odd),
    .ao-recipients-page .ao-stat-row > .ao-stat:last-child:nth-child(odd),
    .ao-outreach-page .ao-stat-row > .ao-stat:last-child:nth-child(odd),
    .ao-sms-page .ao-stat-row > .ao-stat:last-child:nth-child(odd),
    .ao-testing-page .ao-stat-row > .ao-stat:last-child:nth-child(odd),
    .ao-eng-page .ao-stat-row > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
}
/* The identity list: the label above its value, so an address never breaks
 * mid-word in a 200px column. */
@media (max-width: 480px) {
    .ao-profile-section .ao-kv {
        grid-template-columns: minmax(0, 1fr);
        row-gap: 2px;
    }
    .ao-profile-section .ao-kv dd {
        margin-bottom: 8px;
    }
}
/* Tables on a phone: every row a card (the Team board stacks its rows the
 * same way). The header hides; each cell is captioned by its column
 * (data-label, from _b3Stack) and the cells run two a row (three for a
 * table of short numbers), a name across the top, long values across the
 * card. :nth-child(n) lifts the cell rule over the card-bleed paddings.
 * The alert matrix is a grid of switches, not a list: it keeps its columns
 * and pins the source name while it scrolls. */
@media (max-width: 640px) {
    .ao-table.ao-b3-stk,
    .ao-table.ao-b3-stk > tbody {
        display: block;
        width: 100%;
    }
    .ao-table.ao-b3-stk > thead {
        display: none;
    }
    .ao-table-wrap > .ao-table.ao-b3-stk > tbody > tr {
        border-bottom: 1px solid var(--ao-border-soft);
        display: grid;
        gap: 10px 14px;
        grid-auto-flow: row dense;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        padding: 12px 16px;
        position: relative;
    }
    .ao-table-wrap > .ao-table.ao-b3-stk.is-c3 > tbody > tr {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
    .ao-table-wrap > .ao-table.ao-b3-stk.is-c4 > tbody > tr {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
    .ao-table-wrap > .ao-table.ao-b3-stk.has-rank > tbody > tr {
        padding-left: 56px;
    }
    .ao-table-wrap > .ao-table.ao-b3-stk > tbody > tr:last-child {
        border-bottom: 0;
    }
    .ao-table-wrap > .ao-table.ao-b3-stk > tbody > tr:hover {
        background: var(--ao-hover);
    }
    .ao-table-wrap > .ao-table.ao-b3-stk > tbody > tr.ao-b3-top {
        box-shadow: inset 3px 0 0 var(--ao-b3-medal);
    }
    .ao-table-wrap > .ao-table.ao-b3-stk > tbody > tr > td:nth-child(n) {
        background: transparent;
        border: 0;
        box-shadow: none;
        max-width: none;
        min-width: 0;
        overflow: visible;
        overflow-wrap: anywhere;
        padding: 0;
        text-align: left;
        white-space: normal;
    }
    .ao-table.ao-b3-stk td[data-label]::before {
        color: var(--ao-fg-mute);
        content: attr(data-label);
        display: block;
        font-family: var(--ao-font-sans);
        font-size: var(--ao-fs-label);
        font-weight: 600;
        letter-spacing: 0.08em;
        line-height: 1.5;
        margin-bottom: 2px;
        text-transform: uppercase;
    }
    .ao-table.ao-b3-stk td.ao-b3-lead,
    .ao-table.ao-b3-stk td.ao-b3-full {
        grid-column: 1 / -1;
    }
    .ao-table-wrap > .ao-table.ao-b3-stk > tbody > tr > td.ao-b3-rankcell {
        left: 16px;
        position: absolute;
        top: 13px;
    }
    /* Short tables stay tables on a phone; their low-value columns give
     * way instead: the sessions' TENANT, the consent ledger's SOURCE, the
     * activity log's SCOPE and IP. */
    .ao-eng-recent th:nth-child(2),
    .ao-eng-recent td:nth-child(2),
    .ao-sms-consent th:nth-child(3),
    .ao-sms-consent td:nth-child(3),
    .ao-activity-table th:nth-child(n + 5),
    .ao-activity-table td:nth-child(n + 5) {
        display: none;
    }
    /* A disclosure's note on its own line, under the title (not under
     * the chevron). */
    .ao-profile-page .ao-disc-meta {
        flex-basis: 100%;
        padding-left: 24px;
    }
    /* Time per page: the page name takes what the rank, the time bar and
     * the share leave (ellipsed, its title has it) — SHARE ran off the card. */
    .ao-eng-pages th,
    .ao-eng-pages td {
        padding-left: 8px;
        padding-right: 8px;
    }
    .ao-eng-pages td:nth-child(2) {
        max-width: 0;
        width: 100%;
    }
    .ao-eng-pages td.has-bar {
        min-width: 80px;
    }
    /* WHEN / METHOD / STATUS shrink to their content and the route takes
     * the rest, wrapping at its slashes. */
    .ao-activity-table th,
    .ao-activity-table td {
        padding-left: 6px;
        padding-right: 6px;
    }
    .ao-activity-table th:not(:nth-child(3)),
    .ao-activity-table td:not(:nth-child(3)) {
        width: 1%;
    }
    .ao-activity-table td:nth-child(3) {
        max-width: none;
        overflow-wrap: break-word;
        white-space: normal;
    }
    /* Inject buttons two a row, one width (they wrapped 1 / 1 / 2). */
    .ao-tst-group {
        flex: 1 1 100%;
    }
    .ao-tst-btns {
        display: grid;
        grid-auto-rows: 1fr;
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .ao-tst-verb {
        clip-path: inset(50%);
        height: 1px;
        overflow: hidden;
        position: absolute;
        white-space: nowrap;
        width: 1px;
    }
    .ao-tst-btns > .ao-btn {
        justify-content: center;
        line-height: 1.25;
        padding-bottom: 6px;
        padding-top: 6px;
        text-align: center;
        white-space: normal;
    }
    .ao-pref-table th:first-child,
    .ao-pref-table td:first-child {
        background: var(--ao-surface);
        box-shadow: 1px 0 0 var(--ao-tint-line);
        left: 0;
        max-width: 140px;
        min-width: 116px;
        position: sticky;
        white-space: normal;
        z-index: 2;
    }
    .ao-card .ao-pref-table th:first-child {
        background: var(--ao-bg);
        z-index: 3;
    }
    .ao-pref-table tr:hover > td:first-child {
        background: var(--ao-hover);
    }
    /* ENABLED's On / Off word goes too on a phone (aria-checked still says
     * it): the width goes to the channel columns. */
    .ao-pref-table td:nth-child(2) .ao-switch-text {
        display: none;
    }
    /* The add bar's form fills the card under its title: the address on
     * its own line, the name beside ADD. */
    .ao-rcp-form > .ao-input[type='email'] {
        flex: 1 1 100%;
    }
    .ao-rcp-form > .ao-input[type='text'] {
        flex: 1 1 0;
    }
}

/* ── motion ───────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-o-meter-fill {
        transition: none;
    }
    :where(html:not([data-motion='full'])) .ao-eng-page .ao-bar .ao-tselect-trigger::after {
        transition: none;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   SKELETONS (2026-08-22)
   ══════════════════════════════════════════════════════════════════════════
   There were ZERO skeletons in 5,500 lines of CSS, against 24 ad-hoc
   "Loading..." strings in the JS — one of which reused `.ao-card-h`, so a
   loading state rendered as an uppercase card heading. A page therefore went
   from empty, to a line of grey prose, to a full table: three unrelated
   layouts in sequence. That flicker is a large part of what reads as "an
   unstyled document repainting" rather than as an application loading.

   A skeleton holds the SHAPE of the thing that is coming, so the layout does
   not jump when it arrives. Mirrors crm-skeleton so ops and the customer app
   load the same way.

   ⛔ A SKELETON IS NOT AN EMPTY STATE AND NOT AN ERROR. `.ao-empty` means
   "we looked and there is nothing"; `.ao-table-unread` means "we could not
   look". Never leave a skeleton on screen as the terminal state of a failed
   read — that is a spinner that lies. */
.ao-skeleton {
    background: linear-gradient(90deg, var(--ao-tint) 25%, var(--ao-tint-2) 37%, var(--ao-tint) 63%);
    background-size: 400% 100%;
    border-radius: var(--ao-r-sm);
    animation: ao-shimmer 1.4s ease-in-out infinite;
}
.ao-skeleton--text {
    height: 12px;
    margin-bottom: var(--ao-s-2);
}
.ao-skeleton--title {
    height: 28px;
    width: 42%;
    margin-bottom: var(--ao-s-3);
}
.ao-skeleton--metric {
    height: 30px;
    width: 64px;
    margin-bottom: var(--ao-s-2);
}
.ao-skeleton--line {
    height: 1px;
    margin: var(--ao-s-3) 0;
}
/* Widths vary so a stack of rows does not read as a barcode. */
.ao-skeleton--text:nth-child(3n) {
    width: 72%;
}
.ao-skeleton--text:nth-child(3n + 1) {
    width: 91%;
}
.ao-skeleton--text:nth-child(3n + 2) {
    width: 83%;
}

@keyframes ao-shimmer {
    0% {
        background-position: 100% 50%;
    }
    100% {
        background-position: 0 50%;
    }
}

/* ⛔ The shimmer is the ONLY signal that a skeleton is a loading state and not
 * an empty grey box, so reduced-motion gets a static tint rather than nothing
 * at all — removing the animation without replacing the affordance would turn
 * every loading state into what looks like broken layout. */
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-skeleton {
        animation: none;
        background: var(--ao-tint-2);
    }
    /* Design system v2 (the block below). !important because those rules
     * come later in the file and would otherwise win the tie. Entries live
     * HERE, in an existing block, never in a new block at the end of the
     * file: the Team profile test reads the LAST reduced-motion block. */
    :where(html:not([data-motion='full'])) .ao-in {
        animation: none !important;
    }
    :where(html:not([data-motion='full'])) .ao-switch-track,
    :where(html:not([data-motion='full'])) .ao-switch-thumb {
        transition: none !important;
    }
}

/* ══ DESIGN SYSTEM v2 — shared controls and the generic entrance ════════════
 * Spec: argus/docs/superpowers/specs/2026-09-23-ops-console-rehaul-design.md §2.
 * The Team page (#/team) is the reference; these are its pieces made generic
 * so every tab looks and moves the same way. JS: aoSeg / aoSwitch / aoIn next
 * to the other ao* primitives in argus-ops.js.
 *
 * aoSeg deliberately REUSES the Team classes (.ao-tm-seg / .ao-tm-seg-btn,
 * .ao-tm-chips / .ao-tm-chip) for its look — one definition of a segmented
 * control in the file, not two that drift. The .ao-seg* classes below only
 * add what the Team page never needed: a small size and a caption. */

/* A segmented tray never makes the page scroll sideways; the tray itself
 * scrolls (the Team rule hides its scrollbar). */
.ao-seg {
    max-width: 100%;
}
/* The small size (decision D3: 24px), for window pickers inside a toolbar. */
.ao-seg-sm.ao-tm-seg {
    border-radius: var(--ao-r-ctl);
}
.ao-seg-sm .ao-seg-btn {
    font-size: var(--ao-fs-label);
    min-height: 24px;
    padding: 4px 9px;
}
.ao-seg-sm .ao-seg-btn .ao-ico {
    height: 12px;
    width: 12px;
}
/* A captioned tray ("WINDOW  [7d|30d|90d]"): the caption sits beside the
 * tray, never inside it — inside, it reads as a fourth option. The chips
 * variant puts its caption inside the group instead, as Team's "Rank by". */
.ao-seg-field {
    align-items: center;
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
    max-width: 100%;
}
.ao-seg-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

/* ── aoSwitch — button[role=switch] with a track, a thumb and a state word ──
 * The Profile page's alert toggles used to be bare buttons whose label never
 * changed and that had no CSS at all: clicking one saved the preference and
 * changed NOTHING on screen. The thumb position is the state; the word next to
 * it says it in text; aria-checked says it to a screen reader. On = the accent
 * fill the pressed chip wears, never a status colour (on is not "healthy"). */
.ao-switch {
    align-items: center;
    appearance: none;
    background: transparent;
    border: 0;
    border-radius: var(--ao-r-ctl);
    color: var(--ao-fg-dim);
    cursor: pointer;
    display: inline-flex;
    font-family: inherit;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    gap: 8px;
    min-height: 24px;
    min-width: auto;
    padding: 2px 6px 2px 2px;
    white-space: nowrap;
}
.ao-switch-track {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-pill);
    box-shadow: inset 0 1px 2px var(--ao-shadow);
    flex: none;
    height: 18px;
    position: relative;
    transition:
        background var(--ao-fast) var(--ao-ease),
        border-color var(--ao-fast) var(--ao-ease);
    width: 32px;
}
.ao-switch-thumb {
    background: var(--ao-fg-mute);
    border-radius: 50%;
    box-shadow: var(--ao-elev-1);
    height: 12px;
    left: 2px;
    position: absolute;
    top: 2px;
    transition:
        transform var(--ao-base) var(--ao-ease),
        background var(--ao-fast) var(--ao-ease);
    width: 12px;
}
.ao-switch[aria-checked='true'] {
    color: var(--ao-fg);
}
.ao-switch[aria-checked='true'] .ao-switch-track {
    background: var(--ao-accent);
    border-color: var(--ao-accent);
}
.ao-switch[aria-checked='true'] .ao-switch-thumb {
    background: var(--ao-accent-fg);
    transform: translateX(14px);
}
.ao-switch:hover:not(:disabled) .ao-switch-track {
    border-color: var(--ao-fg-mute);
}
.ao-switch[aria-checked='true']:hover:not(:disabled) .ao-switch-track {
    border-color: var(--ao-accent-hover);
}
.ao-switch:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-switch:disabled {
    cursor: not-allowed;
    opacity: 0.45;
}

/* ── .ao-in — the generic entrance (the Team page's rise, for every tab) ────
 * Gated exactly like .ao-tm-in: the JS (aoIn) adds the class only on the
 * first paint of a real navigation, never on a poll, and strips it once it has
 * played so a node moved by a re-sort does not replay it. --ao-i staggers.
 * ⛔ Floor 0.55, never 0: a paused animation in a hidden tab must leave its
 * element readable (portal-invisible-animation.contract.test.js). */
@keyframes ao-rise {
    from {
        opacity: 0.55;
        transform: translateY(16px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}
.ao-in {
    animation: ao-rise var(--ao-enter) var(--ao-ease) backwards;
    animation-delay: calc(var(--ao-i, 0) * var(--ao-stagger));
}

/* ── aoSection — the section header on every tab ───────────────────────────
 * aoSection emits the Team classes too (.ao-tm-sec-head > h2.ao-tm-h +
 * .ao-tm-sec-sub), so the title's size, weight and the muted sub-line come
 * from the ONE Team definition. These rules add only what Team never needed:
 * an icon tile, a right-pinned actions slot, the in-card size and the inset
 * variant. */
.ao-sec-ico {
    align-self: center;
    background: var(--ao-tint-2);
    border-radius: 7px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    display: grid;
    flex: none;
    height: 26px;
    place-items: center;
    width: 26px;
}
/* A long title stays beside its tile and wraps inside itself: without a cap
 * its one-line width is wider than a phone, so the whole title dropped onto
 * a line under a lone icon (Fleet's "Paired agents — heartbeat channel").
 * 38px = the 26px tile + the head's 12px column gap. */
.ao-sec-ico + .ao-sec-h {
    max-width: calc(100% - 38px);
}
/* Actions ride the right edge; on a narrow page they wrap under the title
 * rather than squeezing it. */
.ao-sec-actions {
    align-items: center;
    align-self: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2);
    margin-left: auto;
}
/* ⛔ A heading belongs to what follows it: room under it, more room over it.
 * Outreach's headings had 0 above and 4px below, so each one sat on the
 * table it titled and read as that table's header row. In a flex-gap page
 * body the gap already spaces the head from its content, so there the extra
 * goes above instead. */
.ao-sec-head {
    margin-bottom: var(--ao-s-3);
}
#ao-page-body > .ao-sec-head {
    margin-bottom: 0;
    margin-top: var(--ao-s-3);
}
#ao-page-body > .ao-sec-head:first-child {
    margin-top: 0;
}
/* A section header that titles a card is one step down from a page section:
 * the card-title size, with room under it before the card's content. */
.ao-card > .ao-sec-head {
    margin-bottom: var(--ao-s-3);
}
.ao-card > .ao-sec-head > .ao-sec-h {
    font-size: var(--ao-fs-title);
}
/* .is-inset: for pages that pad their rows rather than their sections (the
 * outreach page) — the header takes the same 16px gutter as its rows. */
.ao-sec-head.is-inset {
    padding: var(--ao-s-7) 16px var(--ao-s-3);
}
/* An Overview tab card: the gap below each card (was an inline margin). */
.ao-ov-card {
    margin: 0 0 12px;
}

/* ── .ao-bar — a page's control row ─────────────────────────────────────────
 * The Team page's .ao-tm-bar made generic: controls (a range, filters) lead
 * on the left, status (a sync pill, a count) is pushed right, and the row
 * wraps instead of overflowing. Put the left group in .ao-bar-lead. */
.ao-bar {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3);
    justify-content: space-between;
}
.ao-bar-lead {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3);
    max-width: 100%;
    min-width: 0;
}

/* ══ FAST REVIEW (#/fastreview) ═══════════════════════════════════════════
 * The grading loop: one clip, big, with the staged verdict impossible to miss.
 *
 * Design system v2 (2026-09-23, the Team page's family): a KPI strip (staged,
 * theft staged, graded coverage, strata never graded) over one Team card —
 * the clip's keyframe and footage side by side, the facts as a spec sheet,
 * big toned verdict chips, a stacked tally of what is staged, and .ao-btn
 * buttons. The crm-* classes the tests pin stay on every node. The portal
 * loads argus-crm.css BEFORE this sheet (main.js ROUTE_STYLES 'argus-ops'),
 * and the standalone console does not load it at all; every rule below that
 * meets a crm-* rule on the same property carries the crm class in its own
 * selector as well (.ao-fr-card.crm-card.ao-card, .ao-fr-bar .crm-btn.ao-btn,
 * .ao-fr-chips.crm-chipgroup .ao-fr-chip), so it outranks argus-crm.css on
 * specificity and still wins if that sheet is ever loaded last.
 *
 * ⛔ Every colour here is a semantic token, never a raw hex (house rule). The
 * four verdict states borrow the existing severity ladder rather than inventing
 * a fifth palette: theft = err (the consequential one), employee = info,
 * nothing = ok, unclear = warn.
 *
 * ⛭ The `is-staged` ring on .ao-fr-body is load-bearing, not decoration. A
 * staged verdict has to be visible from across the room while the reviewer is
 * moving at six seconds a clip — that visibility is one of the four independent
 * events an accidental attestation has to clear (see argus-ops.js's header). */
.ao-fr-panel {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}

/* The Team card, restated at .crm-card's weight plus two: .crm-card paints
 * its own flat surface, border and shadow, and must not win on load order. */
.ao-fr-card.crm-card.ao-card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    display: flex;
    flex-direction: column;
    gap: 16px;
    min-width: 0;
    padding: 18px 20px 20px;
}

/* ── head: "Clip i of N", the keyboard map, a position meter ────────────── */
.ao-fr-head {
    align-items: center;
    display: grid;
    gap: 10px 16px;
    grid-template-columns: minmax(0, 1fr) auto;
}
.ao-fr-headlead {
    align-items: center;
    display: flex;
    gap: 10px;
    min-width: 0;
}
.ao-fr-headico {
    background: var(--ao-tint-2);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-dim);
    display: grid;
    flex: none;
    height: 30px;
    place-items: center;
    width: 30px;
}
.ao-fr-pos {
    color: var(--ao-fg);
    font-size: var(--ao-fs-h);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.01em;
}
.ao-fr-keys {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    justify-content: flex-end;
}
/* No clips loaded: no key map (restated, display:flex above). */
.ao-fr-keys[hidden] {
    display: none;
}
.ao-fr-keygroup {
    align-items: center;
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    gap: 3px;
    letter-spacing: 0.06em;
}
.ao-fr-keylabel {
    margin-left: 3px;
    text-transform: uppercase;
}
/* A key cap: the keyboard is the fast path, so the page draws its keys. */
.ao-fr-kbd {
    background: var(--ao-hover);
    border-radius: var(--ao-r-tag);
    box-shadow:
        inset 0 -2px 0 var(--ao-border),
        inset 0 0 0 1px var(--ao-border);
    color: var(--ao-fg);
    display: inline-grid;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    height: 18px;
    line-height: 1;
    min-width: 18px;
    padding: 0 5px;
    place-items: center;
    text-transform: none;
}
.ao-fr-posbar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    grid-column: 1 / -1;
    height: 3px;
    overflow: hidden;
    position: relative;
}
.ao-fr-posbar-fill {
    background: var(--ao-k-5);
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
}

/* ── the clip ───────────────────────────────────────────────────────────── */
/* The negative inline margin cancels the ring's 2px + 14px inset, so the
 * media, facts and chips line up with "Clip i of N", the tally and the
 * toolbar, and the staged ring is drawn outside that column. */
.ao-fr-body {
    border: 2px solid transparent;
    border-radius: 14px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin-inline: -16px;
    padding: 14px;
    transition:
        border-color var(--ao-fast) var(--ao-ease),
        background var(--ao-fast) var(--ao-ease);
}
.ao-fr-body.is-staged {
    background: var(--ao-tint);
}
.ao-fr-body.is-theft {
    border-color: var(--ao-err);
}
.ao-fr-body.is-employee {
    border-color: var(--ao-info);
}
.ao-fr-body.is-nothing {
    border-color: var(--ao-ok);
}
.ao-fr-body.is-unclear {
    border-color: var(--ao-warn);
}

/* The keyframe and the footage, side by side: the keyframe IS the reviewable
 * artifact at six seconds a clip, the clip is the proof. */
.ao-fr-media {
    display: grid;
    gap: 12px;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.ao-fr-pane {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0;
    min-width: 0;
}
.ao-fr-panecap {
    align-items: center;
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    gap: 5px;
    letter-spacing: 0.1em;
}
.ao-fr-thumb,
.ao-fr-clip {
    aspect-ratio: 16 / 9;
    background: var(--ao-bg);
    border-radius: 12px;
    box-shadow: inset 0 0 0 1px var(--ao-border-soft);
    display: block;
    object-fit: contain;
    width: 100%;
}
.ao-fr-noclip {
    align-items: center;
    aspect-ratio: 16 / 9;
    background: var(--ao-tint);
    border: 1px dashed var(--ao-border);
    border-radius: 12px;
    color: var(--ao-fg-mute);
    display: flex;
    flex-direction: column;
    gap: 10px;
    justify-content: center;
    padding: 16px 20px;
    text-align: center;
}
.ao-fr-noclip .ao-fr-clipnote {
    max-width: 52ch;
}
.ao-fr-clipnote,
.ao-fr-nomedia {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
}
.ao-fr-pane .ao-fr-nomedia {
    align-items: center;
    aspect-ratio: 16 / 9;
    background: var(--ao-tint);
    border: 1px dashed var(--ao-border);
    border-radius: 12px;
    justify-content: center;
    padding: 16px;
}
/* The clip failed in the browser although the server holds it: a warn note. */
.ao-fr-cliperr {
    background: var(--ao-warn-bg);
    border: 1px solid var(--ao-warn-border);
    border-radius: 10px;
    color: var(--ao-warn-fg);
    padding: 8px 12px;
}

/* The facts as a spec sheet: label over a mono value, one tile each. */
.ao-fr-facts {
    display: grid;
    gap: 6px;
    grid-template-columns: repeat(auto-fit, minmax(max(120px, calc((100% - 30px) / 6 - 1px)), 1fr));
}
.ao-fr-fact {
    background: var(--ao-tint);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px var(--ao-border-faint);
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    padding: 7px 10px;
}
.ao-fr-fact-k {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-fr-fact-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    overflow-wrap: anywhere;
}
/* WHEN's absolute stamp is its own muted line under the relative time, and
 * never breaks inside itself. */
.ao-fr-fact-abs {
    color: var(--ao-fg-mute);
    display: block;
    white-space: nowrap;
}
.ao-fr-narrative {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    grid-column: 1 / -1;
    line-height: 1.55;
    padding-top: 4px;
}

/* The staged verdict, stated on the card in its own tone. */
.ao-fr-verdict {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 12px;
}
.ao-fr-verdict-v {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-title);
    font-weight: 700;
    letter-spacing: 0.04em;
}
.ao-fr-verdict-v.is-theft {
    color: var(--ao-err-fg);
}
.ao-fr-verdict-v.is-employee {
    color: var(--ao-info-fg);
}
.ao-fr-verdict-v.is-nothing {
    color: var(--ao-ok-fg);
}
.ao-fr-verdict-v.is-unclear {
    color: var(--ao-warn-fg);
}
/* Nothing staged is an absence, not a heading: the quiet dashed pill every
 * "no value" wears in this console. */
.ao-fr-verdict-v.is-none {
    border: 1px dashed var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    padding: 3px 10px;
    text-transform: uppercase;
}
.ao-fr-verdict-undo {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}

/* ── the four verdict chips: the page's main controls, so the biggest ─────
 * Written at .crm-chipgroup weight (plus one) so they win over the crm chip
 * group in either load order; pressed = the verdict's own tone. */
/* Four equal columns across the card: the main action is as wide as the
 * media above it. */
/* One bordered bar of four segments, not four floating chips (2026-09-25):
 * the group is the frame and its ground shows through a 1px gap as the rule
 * between segments, so the rules stay right at four columns and at the
 * phone's two-by-two. */
.ao-fr-chips.crm-chipgroup.ao-seg {
    background: var(--ao-border-soft);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-ctl);
    display: grid;
    gap: 1px;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    overflow: hidden;
}
.ao-fr-chips.crm-chipgroup .ao-fr-chip {
    align-items: center;
    background: var(--ao-surface);
    border: 0;
    border-radius: 0;
    box-shadow: none;
    color: var(--ao-fg-dim);
    cursor: pointer;
    display: inline-flex;
    font-size: var(--ao-fs-body);
    font-weight: 600;
    gap: 8px;
    justify-content: center;
    letter-spacing: 0.06em;
    line-height: 1.2;
    min-height: 36px;
    padding: 7px 10px 7px 13px;
}
/* A mouse only: on touch the next clip would inherit the tapped chip's
 * hover fill under "not staged". */
@media (hover: hover) {
    .ao-fr-chips.crm-chipgroup .ao-fr-chip:hover {
        background: var(--ao-hover);
        color: var(--ao-fg);
    }
}
.ao-fr-chips.crm-chipgroup .ao-fr-chip:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: -2px;
}
.ao-fr-chip.is-theft .ao-ico {
    color: var(--ao-err-fg);
}
.ao-fr-chip.is-employee .ao-ico {
    color: var(--ao-info-fg);
}
.ao-fr-chip.is-nothing .ao-ico {
    color: var(--ao-ok-fg);
}
.ao-fr-chip.is-unclear .ao-ico {
    color: var(--ao-warn-fg);
}
/* The digit, shown ON the chip: the keyboard is the fast path and the mouse is
 * the fallback, so the chip has to teach its own shortcut. */
.ao-fr-chip-key {
    background: var(--ao-surface-2);
    border-radius: var(--ao-r-tag);
    box-shadow:
        inset 0 -1px 0 var(--ao-border),
        inset 0 0 0 1px var(--ao-border-soft);
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    line-height: 18px;
    min-width: 18px;
    padding: 0 5px;
    text-align: center;
}
/* Staged = the verdict's tone laid over the segment's surface (a tone is
 * translucent; the group's rule-coloured ground must not show through), a
 * 2px rule in the verdict's colour along the bottom, bold. No ring. */
.ao-fr-chips.crm-chipgroup .ao-fr-chip.is-on {
    color: var(--ao-fg);
    font-weight: 700;
}
.ao-fr-chips.crm-chipgroup .ao-fr-chip.is-theft.is-on {
    background: linear-gradient(var(--ao-err-bg), var(--ao-err-bg)) var(--ao-surface);
    box-shadow: inset 0 -2px 0 var(--ao-err);
    color: var(--ao-err-fg);
}
.ao-fr-chips.crm-chipgroup .ao-fr-chip.is-employee.is-on {
    background: linear-gradient(var(--ao-info-bg), var(--ao-info-bg)) var(--ao-surface);
    box-shadow: inset 0 -2px 0 var(--ao-info);
    color: var(--ao-info-fg);
}
.ao-fr-chips.crm-chipgroup .ao-fr-chip.is-nothing.is-on {
    background: linear-gradient(var(--ao-ok-bg), var(--ao-ok-bg)) var(--ao-surface);
    box-shadow: inset 0 -2px 0 var(--ao-ok);
    color: var(--ao-ok-fg);
}
.ao-fr-chips.crm-chipgroup .ao-fr-chip.is-unclear.is-on {
    background: linear-gradient(var(--ao-warn-bg), var(--ao-warn-bg)) var(--ao-surface);
    box-shadow: inset 0 -2px 0 var(--ao-warn);
    color: var(--ao-warn-fg);
}
.ao-fr-chip.is-on .ao-fr-chip-key {
    background: transparent;
    box-shadow: inset 0 0 0 1px currentColor;
    color: inherit;
}

/* ── the running tally: total, a stacked bar of the mix, a legend ──────── */
.ao-fr-counts {
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-top: 14px;
}
.ao-fr-count-head {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: 4px 14px;
}
/* "N staged": the number in mono, the word in the label voice (aoStat's
 * split). Held at .crm-stat's weight plus one: .crm-stat is a flex column. */
.ao-fr-counts .ao-fr-count-total {
    align-items: baseline;
    color: var(--ao-fg);
    display: inline-flex;
    flex-direction: row;
    gap: 7px;
}
.ao-fr-count-num {
    font-family: var(--ao-mono);
    font-size: 22px;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.03em;
    line-height: 1;
}
.ao-fr-count-word {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ao-fr-count-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-fr-stack {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: flex;
    gap: 2px;
    height: 8px;
    overflow: hidden;
}
.ao-fr-stack-seg {
    flex: 1 1 0;
    min-width: 4px;
}
.ao-fr-stack-seg.is-theft {
    background: var(--ao-err);
}
.ao-fr-stack-seg.is-employee {
    background: var(--ao-info);
}
.ao-fr-stack-seg.is-nothing {
    background: var(--ao-ok);
}
.ao-fr-stack-seg.is-unclear {
    background: var(--ao-warn);
}
.ao-fr-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 16px;
}
.ao-fr-count {
    align-items: center;
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    gap: 6px;
}
.ao-fr-count::before {
    background: var(--ao-fg-mute);
    border-radius: 3px;
    content: '';
    height: 8px;
    width: 8px;
}
.ao-fr-count.is-theft::before {
    background: var(--ao-err);
}
.ao-fr-count.is-employee::before {
    background: var(--ao-info);
}
.ao-fr-count.is-nothing::before {
    background: var(--ao-ok);
}
.ao-fr-count.is-unclear::before {
    background: var(--ao-warn);
}
.ao-fr-count.is-theft:not(.is-zero) {
    color: var(--ao-err-fg);
}
.ao-fr-count.is-zero {
    color: var(--ao-fg-mute);
}
/* Theft staged: the tile is always THEFT's red; the number joins it only
 * once there is theft staged. */
.ao-fr-kpis .ao-stat.is-hot .ao-stat-num:not(.is-counting),
.ao-fr-kpis .ao-stat.is-hot .ao-stat-num.is-counting::after {
    color: var(--ao-err-fg);
}

/* ── the toolbar: PREV / NEXT, the one primary (COMMIT), LOAD NEXT BATCH ──
 * Every button is the 28px .ao-btn. .crm-btn (32px, 13px, line-height 1,
 * a transparent border) and its --secondary / --primary hover are restated
 * here with the crm class in the selector, so the .ao-btn look holds in
 * either load order. */
.ao-fr-bar.crm-toolbar {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.ao-fr-bar .crm-btn.ao-btn {
    border-radius: var(--ao-r-ctl);
    border-style: solid;
    border-width: 1px;
    font-family: inherit;
    font-size: var(--ao-fs-body);
    font-weight: 600;
    gap: 6px;
    letter-spacing: 0.04em;
    line-height: 1.2;
    min-height: 28px;
    padding: 6px 13px;
    text-transform: uppercase;
}
.ao-fr-bar .crm-btn.ao-btn:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-fr-bar .crm-btn.ao-btn:disabled {
    opacity: 0.4;
}
/* LOAD NEXT BATCH: the plain .ao-btn surface, never crm's transparent one. */
.ao-fr-bar .crm-btn--secondary.ao-btn {
    background: var(--ao-surface);
    border-color: var(--ao-border-soft);
    color: var(--ao-fg);
}
.ao-fr-bar .crm-btn--secondary.ao-btn:hover:not(:disabled) {
    background: var(--ao-hover);
    border-color: var(--ao-border);
    color: var(--ao-fg);
}
.ao-fr-bar .crm-btn--primary.ao-btn.is-primary {
    font-weight: 700;
}
.ao-fr-bar .crm-btn--primary.ao-btn.is-primary:hover:not(:disabled) {
    background: var(--ao-cta-hover);
    border-color: var(--ao-cta-hover);
    color: var(--ao-cta-fg);
}
.ao-fr-commit {
    margin-left: auto;
}
/* Disabled COMMIT stays legible: 0.6, not 0.4 over already-muted text. */
.ao-fr-bar .ao-fr-commit.crm-btn.ao-btn:disabled {
    opacity: 0.6;
}
/* 14px caps: a taller cap would stretch PREV / NEXT past COMMIT's 28px. */
.ao-fr-bar .ao-fr-kbd {
    /* 14px tall: a 6px corner would round it into a capsule. */
    border-radius: var(--ao-r-sm);
    font-size: 9px;
    height: 14px;
    min-width: 14px;
    padding: 0 4px;
}

.ao-fr-lastcommit {
    align-items: flex-start;
    background: var(--ao-ok-bg);
    border: 1px solid var(--ao-ok-bd);
    border-radius: var(--ao-r-lg);
    display: flex;
    gap: 10px;
    padding: 10px 14px;
}
.ao-fr-lastcommit-ico {
    color: var(--ao-ok-fg);
    display: grid;
    flex: none;
    margin-top: 2px;
}
.ao-fr-lastcommit-text {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}
.ao-fr-lastcommit-n {
    color: var(--ao-ok-fg);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
}
.ao-fr-lastcommit-theft,
.ao-fr-lastcommit-note {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    overflow-wrap: anywhere;
}

/* Error, empty and loading inside the card (crm-empty / crm-skeleton kept
 * as hooks; the look is the console's). */
.ao-fr-card .ao-fr-error {
    align-items: center;
    background: var(--ao-err-bg);
    border: 1px solid var(--ao-err-bd);
    border-radius: var(--ao-r-lg);
    color: var(--ao-err-fg);
    flex-direction: row;
    gap: 8px;
    padding: 10px 14px;
}
.ao-fr-card .ao-fr-empty {
    align-items: center;
    border-radius: var(--ao-r-xl);
    color: var(--ao-fg-mute);
    gap: 10px;
    margin: 0;
    padding: 36px 20px;
}
.ao-fr-card .ao-fr-skel {
    background: var(--ao-tint);
    border-radius: 12px;
    color: var(--ao-fg-mute);
    display: grid;
    font-size: var(--ao-fs-meta);
    min-height: 220px;
    place-items: center;
}

/* The border ring is the only thing distinguishing a staged card from an
 * unstaged one for a reviewer who cannot perceive its colour. Give the staged
 * state a second, non-chromatic cue. */
.ao-fr-body.is-staged {
    box-shadow: inset 0 0 0 1px var(--ao-border);
}

/* A phone: the two media panes stack; the ring's inset (2px + 10px) is
 * cancelled the same way as on a desktop. */
@media (max-width: 760px) {
    .ao-fr-card.crm-card.ao-card {
        padding: 14px;
    }
    .ao-fr-head {
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-fr-body {
        margin-inline: -12px;
        padding: 10px;
    }
    .ao-fr-media {
        grid-template-columns: minmax(0, 1fr);
    }
    /* Two chips a row, even. */
    .ao-fr-chips.crm-chipgroup.ao-seg {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    /* The toolbar as a grid: COMMIT full width on top, PREV | NEXT as an
     * even pair, LOAD NEXT BATCH full width under them. */
    .ao-fr-bar.crm-toolbar {
        display: grid;
        grid-template-columns: 1fr 1fr;
    }
    .ao-fr-bar .crm-btn.ao-btn {
        justify-content: center;
    }
    .ao-fr-commit,
    .ao-fr-bar [data-role='fr-load'] {
        grid-column: 1 / -1;
    }
    .ao-fr-commit {
        margin-left: 0;
        order: -1;
    }
}
/* No keyboard to teach: a touch screen or a phone-width window drops the
 * key map, the digits on the verdict chips and the key caps in the toolbar. */
@media (hover: none), (max-width: 760px) {
    .ao-fr-keys,
    .ao-fr-chip .ao-fr-chip-key,
    .ao-fr-bar .ao-fr-kbd {
        display: none;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
 * INVENTORY — the Ops Console Inventory module
 * ══════════════════════════════════════════════════════════════════════════
 *
 * Built entirely from the existing token ladder (--ao-*). No new colours, no
 * hard-coded hex: a section that invents its own palette is the one that looks
 * wrong the day the theme changes, and this console already carries a light
 * theme that overrides every token above.
 */

/* The scope bar. Present on ALL six pages so the active tenant + store are
 * never a thing the operator has to remember or infer from the URL. Design
 * system v2 (2026-09-23): the Team card, with the pickers as themed pills. */
.ao-inv-scope {
    align-items: flex-end;
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    display: flex;
    flex-wrap: wrap;
    gap: 12px 16px;
    padding: 12px 16px;
}
.ao-inv-scope__field {
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
}
.ao-inv-scope__label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.1em;
}
.ao-inv-scope .ao-picker-trigger {
    background: var(--ao-surface);
    border-color: var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    min-height: 32px;
    min-width: 220px;
    padding: 5px 10px;
}
/* The store picker is the tenant picker's trigger (.ao-picker); the store's
 * id rides beside its name, dimmer and in mono, so a screenshot still says
 * exactly which store it shows. .ao-inv-scope__select is only a hook now. */
.ao-inv-scope__id {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    margin-left: 8px;
}

/* The page body already pads (the page-body rule); the content is a column
 * of sections spaced by one gap. */
.ao-inv-content,
.ao-inv-stack-sec {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
.ao-inv-stack-sec {
    gap: var(--ao-s-3);
}
.ao-inv-content > .ao-sec-head,
.ao-inv-stack-sec > .ao-sec-head {
    margin: var(--ao-s-2) 0 0;
}
.ao-inv-stack-sec:first-child > .ao-sec-head:first-child {
    margin-top: 0;
}

.ao-inv-actions {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 12px;
}
.ao-sec-actions > .ao-inv-actions {
    margin-top: 0;
}
/* Every Inventory action is an .ao-btn now; this is the family's literal
 * geometry only (pill-buttons.contract.test.js pins it), so the .ao-btn look
 * wins everywhere else. */
.ao-inv-action {
    border-radius: var(--ao-r-ctl);
    min-height: 28px;
    min-width: auto;
}
.ao-inv-action.ao-btn-sm {
    min-height: 26px;
}
/* A hero panel (Physical counts, New physical count): the head IS the card. */
.ao-inv-panel.is-hero {
    background:
        radial-gradient(120% 140% at 0% 0%, var(--ao-tint-2), transparent 60%),
        linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    padding: var(--ao-s-5);
}
.ao-inv-panel.is-hero > .ao-sec-head {
    align-items: center;
    margin-bottom: 0;
}
.ao-inv-countfor {
    align-items: baseline;
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
}
/* A control in a panel head (the count-status tray) scrolls sideways on a
 * phone rather than running out of its card. */
.ao-inv-panel > .ao-sec-head > .ao-sec-actions {
    max-width: 100%;
    min-width: 0;
}
.ao-inv-panel > .ao-sec-head > .ao-sec-actions > .ao-seg {
    max-width: 100%;
    overflow-x: auto;
}
.ao-inv-panel.is-hero > .ao-sec-head > .ao-sec-ico {
    height: 34px;
    width: 34px;
}

/* ── The physical-count screen (#/inventory-counts/new) ───────────────────
 * js/inventory/physical-count.js is shared with the Inventory app and
 * injects its own sheet (flat tiles, 9px-radius buttons). Inside the console
 * its numbers, buttons and inputs wear the console's look instead: KPI cards
 * with the label above a mono number, pill buttons, themed inputs. Scoped to
 * #argus-ops-root, so the Inventory app keeps its own. */
#argus-ops-root .inv-pc {
    gap: var(--ao-s-4);
    min-width: 0;
}
#argus-ops-root .inv-pc__totals {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
#argus-ops-root .inv-pc__stat {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    display: flex;
    flex-direction: column-reverse;
    gap: 4px;
    justify-content: flex-end;
    min-width: 0;
    padding: 14px 16px 12px;
}
#argus-ops-root .inv-pc__stat b {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: 28px;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.04em;
    line-height: 1.05;
}
#argus-ops-root .inv-pc__stat span {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    font-weight: 500;
    letter-spacing: 0.02em;
    text-transform: none;
}
#argus-ops-root .inv-pc__stat.is-warn b {
    color: var(--ao-warn-text);
}
#argus-ops-root .inv-pc__stage {
    border-color: var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
}
#argus-ops-root .inv-pc__btn {
    align-items: center;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint),
        var(--ao-elev-1);
    color: var(--ao-fg);
    display: inline-flex;
    font-family: inherit;
    font-size: var(--ao-fs-body);
    font-weight: 600;
    gap: 6px;
    letter-spacing: 0.04em;
    line-height: 1.2;
    min-height: 28px;
    min-width: auto;
    padding: 6px 13px;
    text-transform: uppercase;
}
#argus-ops-root .inv-pc__btn:hover:not(:disabled) {
    background: var(--ao-hover);
    border-color: var(--ao-border);
    color: var(--ao-fg);
}
#argus-ops-root .inv-pc__btn:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
#argus-ops-root .inv-pc__btn:disabled {
    box-shadow: none;
    opacity: 0.4;
}
/* A chosen mode (Type total, 1 piece): the pressed segment's look. */
#argus-ops-root .inv-pc__btn.is-active {
    background: linear-gradient(180deg, var(--ao-rail-active), var(--ao-ink));
    border-color: var(--ao-border);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-strong),
        var(--ao-elev-1);
    color: var(--ao-fg);
}
#argus-ops-root .inv-pc__btn.is-primary {
    background: var(--ao-cta);
    border-color: var(--ao-cta-border);
    color: var(--ao-cta-fg);
    font-weight: 700;
}
#argus-ops-root .inv-pc__btn.is-primary:hover:not(:disabled) {
    background: var(--ao-cta-hover);
    border-color: var(--ao-cta-hover);
    color: var(--ao-cta-fg);
}
#argus-ops-root .inv-pc__btn.is-danger {
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
#argus-ops-root .inv-pc__btn.is-danger:hover:not(:disabled) {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-border-strong);
    color: var(--ao-err-fg);
}
#argus-ops-root .inv-pc__input {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    min-height: 32px;
    padding: 5px 10px;
}
#argus-ops-root .inv-pc__input:focus {
    border-color: var(--ao-accent-line);
    box-shadow: 0 0 0 3px var(--ao-focus-glow);
    outline: none;
}
#argus-ops-root .inv-pc__field label {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
}
#argus-ops-root .inv-pc__sub,
#argus-ops-root .inv-pc__note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
#argus-ops-root .inv-pc__card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-color: var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
}
#argus-ops-root .inv-pc__card.is-unknown,
#argus-ops-root .inv-pc__line.is-unresolved {
    border-color: var(--ao-warn-border);
}
#argus-ops-root .inv-pc__line {
    background: var(--ao-tint);
    border-radius: var(--ao-r-md);
}
#argus-ops-root .inv-pc__qty {
    color: var(--ao-k-1);
    font-family: var(--ao-mono);
}
#argus-ops-root .inv-pc__warn {
    border-left-color: var(--ao-warn-border);
    color: var(--ao-warn-text);
}

.ao-inv-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.55;
    margin-top: 10px;
    max-width: 100ch;
}
.ao-inv-content > .ao-inv-note,
.ao-inv-stack-sec > .ao-inv-note,
.ao-inv-card > .ao-inv-note {
    margin-top: 0;
}
/* A caveat the operator must read BEFORE spending provider quota — a muted
   note is the wrong weight for "the number above is an upper bound". */
.ao-inv-warn {
    background: var(--ao-warn-bg);
    border-radius: var(--ao-r-md);
    box-shadow: inset 3px 0 0 var(--ao-warn-border);
    color: var(--ao-warn-fg);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    margin-top: 10px;
    padding: 8px 12px;
}
.ao-inv-stack-sec > .ao-inv-warn {
    margin-top: 0;
}
.ao-inv-ok,
.ao-inv-err {
    border-radius: var(--ao-r-md);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    margin-top: 8px;
    padding: 7px 12px;
}
.ao-inv-ok {
    background: var(--ao-ok-bg);
    box-shadow: inset 3px 0 0 var(--ao-ok-border);
    color: var(--ao-ok-fg);
}
.ao-inv-err {
    background: var(--ao-err-bg);
    box-shadow: inset 3px 0 0 var(--ao-err-border-strong);
    color: var(--ao-err-fg);
}

/* Filters (aoSeg chips; .ao-inv-filter is kept as the hook) + search */
.ao-inv-controls {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.ao-inv-filter-n {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    line-height: 1.6;
}
.ao-tm-chip[aria-pressed='true'] .ao-inv-filter-n {
    color: var(--ao-fg-dim);
}
.ao-inv-searchwrap {
    align-items: center;
    display: inline-flex;
    position: relative;
}
.ao-inv-searchwrap .ao-ico {
    color: var(--ao-fg-mute);
    left: 11px;
    pointer-events: none;
    position: absolute;
}
.ao-inv-search {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    box-shadow: inset 0 1px 0 var(--ao-tint);
    color: var(--ao-fg);
    font-family: inherit;
    font-size: var(--ao-fs-body);
    min-height: 32px;
    min-width: 260px;
    padding: 5px 14px 5px 32px;
}
.ao-inv-search:focus {
    border-color: var(--ao-accent-line);
    box-shadow: 0 0 0 3px var(--ao-focus-glow);
    outline: none;
}

/* Tables. Wide content scrolls INSIDE its own container -- the page body must
 * never scroll horizontally, which on a 13-column catalog it otherwise would.
 * (The Inventory tables are aoTable now, whose wrap scrolls; this legacy class
 * keeps the same rule for anything still hand-built.) */
.ao-inv-table {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
}
.ao-inv-tablehost {
    min-width: 0;
    position: relative;
}
/* A table wider than its card fades at the right edge while there is more
 * that way (invScrollFade); the fade goes once the last column is in view. */
.ao-inv-tablehost.is-overflow:not(.is-end)::after {
    background: linear-gradient(90deg, transparent, var(--ao-surface) 85%);
    border-radius: 0 var(--ao-r-xl) var(--ao-r-xl) 0;
    bottom: 1px;
    content: '';
    pointer-events: none;
    position: absolute;
    right: 1px;
    top: 1px;
    width: 40px;
    /* Above the sticky header cells. */
    z-index: 3;
}
.ao-inv-tablehost .ao-table td {
    white-space: nowrap;
}
.ao-inv-tablehost .ao-inv-chips {
    flex-wrap: nowrap;
}
.ao-inv-caption {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-inv-name {
    color: var(--ao-fg);
    font-weight: 600;
}
/* Products: the name cell carries the row's flags on a second line, and an
 * unresolved row shows Passport's words there — muted and mono, so it never
 * reads as the product's identity. The cell wraps; the rest stay on one line. */
.ao-inv-namecell {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.ao-inv-name.is-raw {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-weight: 400;
}
.ao-inv-flags {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.ao-inv-tablehost.ao-inv-products .ao-table td:first-child {
    min-width: 180px;
    white-space: normal;
}
.ao-inv-tablehost.ao-inv-products .ao-table th,
.ao-inv-tablehost.ao-inv-products .ao-table td {
    padding-left: 10px;
    padding-right: 10px;
}
/* The Products table fits its card: the free-text cells (brand, Passport's
 * words, the sources) may wrap, and MAPPING / LAST COUNT are two short lines
 * instead of one long one. Codes, prices and dates never break. */
.ao-inv-products .ao-inv-wrap,
.ao-inv-products .ao-inv-raw {
    white-space: normal;
}
.ao-inv-tablehost.ao-inv-products .ao-inv-chips {
    align-items: flex-start;
    flex-direction: column;
    gap: 3px;
}
.ao-inv-mapcell,
.ao-inv-stackcell {
    align-items: flex-start;
    display: inline-flex;
    flex-direction: column;
    gap: 3px;
}
.ao-inv-mapnote {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}
.ao-table td.ao-mono .ao-inv-status {
    font-family: var(--ao-font-sans);
}
.ao-inv-raw {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-inv-dash {
    color: var(--ao-fg-mute);
}
.ao-inv-dept {
    align-items: baseline;
    display: inline-flex;
    gap: 6px;
}
.ao-inv-dept-code {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-inv-price,
.ao-inv-chips,
.ao-inv-rowacts,
.ao-inv-who {
    align-items: center;
    display: inline-flex;
    gap: 5px;
}
.ao-inv-chips {
    flex-wrap: wrap;
}
.ao-inv-who {
    gap: 8px;
}
.ao-inv-src {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    padding: 1px 6px;
}
.ao-inv-bad {
    color: var(--ao-err-fg);
}
.ao-inv-warnnum {
    color: var(--ao-warn-fg);
}

/* Chips. Each state carries a TEXT label as well as a colour -- the colour is
 * a second cue, never the only one. The aoState pill's geometry. */
.ao-inv-chip,
.ao-inv-status {
    align-items: center;
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.03em;
    line-height: 1.6;
    padding: 1px 8px;
    text-transform: uppercase;
    white-space: nowrap;
}
.ao-inv-chip.is-high,
.ao-inv-chip.is-map-mapped,
.ao-inv-status.is-ok {
    background: var(--ao-ok-soft);
    border-color: var(--ao-ok-border);
    color: var(--ao-ok-text);
}
.ao-inv-chip.is-medium,
.ao-inv-chip.is-map-mapped_no_canonical,
.ao-inv-chip.is-map-canonical_unlinked,
.ao-inv-status.is-info {
    background: var(--ao-info-soft);
    border-color: var(--ao-info-border);
    color: var(--ao-info-fg);
}
.ao-inv-chip.is-low,
.ao-inv-chip.is-unresolved,
.ao-inv-chip.is-map-unmapped,
.ao-inv-status.is-warn {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-fg);
}
.ao-inv-status.is-unknown {
    border-style: dashed;
    color: var(--ao-fg-mute);
}
.ao-inv-flag {
    border: 1px dashed var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-mute);
    display: inline-block;
    font-size: var(--ao-fs-label);
    line-height: 1.6;
    padding: 0 7px;
    white-space: nowrap;
}
/* The in-table actions (Confirm, CSV, Audit) are .ao-btn-sm pills; the old
 * underlined text link had a 12px hit area. */
.ao-inv-linkbtn {
    white-space: nowrap;
}

/* A 100% bar of parts (lookup coverage, which stage answered) + its legend. */
.ao-inv-stack {
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.ao-inv-stack-bar {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: flex;
    gap: 2px;
    height: 12px;
    overflow: hidden;
}
.ao-inv-stack-seg {
    min-width: 3px;
    transition: flex-grow var(--ao-slow) var(--ao-ease);
}
.ao-inv-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 20px;
}
.ao-inv-legend-item {
    align-items: center;
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
}
.ao-inv-legend-dot {
    border-radius: 50%;
    height: 8px;
    width: 8px;
}
.ao-inv-legend-num {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-weight: 600;
}
.ao-inv-legend-pct {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}
.ao-inv-stack-seg.is-ok,
.ao-inv-legend-dot.is-ok {
    background: var(--ao-ok);
}
.ao-inv-stack-seg.is-ok2,
.ao-inv-legend-dot.is-ok2 {
    background: color-mix(in srgb, var(--ao-ok) 55%, transparent);
}
.ao-inv-stack-seg.is-info,
.ao-inv-legend-dot.is-info {
    background: var(--ao-info);
}
.ao-inv-stack-seg.is-accent,
.ao-inv-legend-dot.is-accent {
    background: var(--ao-accent);
}
.ao-inv-stack-seg.is-warn,
.ao-inv-legend-dot.is-warn {
    background: var(--ao-warn);
}
.ao-inv-stack-seg.is-err,
.ao-inv-legend-dot.is-err {
    background: var(--ao-err);
}
.ao-inv-stack-seg.is-mute,
.ao-inv-legend-dot.is-mute {
    background: var(--ao-fg-mute);
}
.ao-inv-stack-seg.is-faint,
.ao-inv-legend-dot.is-faint {
    background: var(--ao-tint-strong);
}
.ao-inv-stagecard {
    padding: 14px 16px;
}
/* Products' second KPI row sits on the headline row's six columns (auto-fill
 * keeps an empty track, so five cards still line up with the six above). */
.ao-stat-row.ao-inv-kpis-more {
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(max(168px, calc((100% - 5 * var(--ao-s-3)) / 6 - 1px)), 1fr));
}
/* The sessions status chips, between the panel head and the table. */
.ao-inv-controls.is-sessions {
    margin-bottom: var(--ao-s-3);
}

/* A 0..100 meter under a KPI number (count coverage), in the card's accent. */
.ao-inv-meterwrap {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.ao-inv-meter {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: block;
    height: 4px;
    overflow: hidden;
    position: relative;
}
.ao-inv-meter.is-unmeasured {
    background: repeating-linear-gradient(45deg, var(--ao-tint-2) 0 3px, transparent 3px 6px);
}
.ao-inv-meter-fill {
    background: var(--ao-stat-accent, var(--ao-accent));
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}

.ao-inv-creds {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.ao-inv-cred {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 8px;
    padding: 4px 6px 4px 12px;
}

/* Confirmation cards — the review queue. A grid of Team cards, each with a
 * confidence edge (ok / info / warn) so the queue can be scanned by risk. */
.ao-inv-confirm-kpis:empty {
    display: none;
}
.ao-inv-queue {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 500px), 1fr));
}
.ao-inv-card {
    --ao-inv-tone: var(--ao-border);
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 3px 0 0 var(--ao-inv-tone),
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
    padding: 14px 16px 14px 18px;
}
.ao-inv-card.is-high {
    --ao-inv-tone: var(--ao-ok);
}
.ao-inv-card.is-medium {
    --ao-inv-tone: var(--ao-info);
}
.ao-inv-card.is-low,
.ao-inv-card.is-unresolved {
    --ao-inv-tone: var(--ao-warn);
}
.ao-inv-card__head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ao-inv-card__upc {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-title);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.01em;
}
.ao-inv-copy {
    margin-right: 4px;
}
.ao-inv-copy.is-done {
    color: var(--ao-ok-fg);
}
.ao-inv-card__body {
    display: grid;
    gap: 12px 16px;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.ao-inv-card__facts {
    align-content: start;
    display: grid;
    gap: 10px 14px;
    grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
}
.ao-inv-fact:first-child {
    grid-column: 1 / -1;
}
.ao-inv-fact__k {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.06em;
}
.ao-inv-fact__v {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    font-variant-numeric: tabular-nums;
    margin-top: 2px;
    overflow-wrap: anywhere;
}
.ao-inv-card__proposal {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-lg);
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    padding: 10px 12px;
}
.ao-inv-card__proposal.is-proposed {
    background: linear-gradient(180deg, var(--ao-info-soft), var(--ao-tint));
    border-color: var(--ao-info-border);
}
.ao-inv-card__ptitle {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 6px;
    letter-spacing: 0.06em;
}
.ao-inv-card__pname {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    overflow-wrap: anywhere;
}
.ao-inv-card__pmeta,
.ao-inv-card__reason {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
}
.ao-inv-card__reason {
    border-top: 1px dashed var(--ao-tint-line);
    margin-top: 4px;
    padding-top: 6px;
}
.ao-inv-card__fig {
    margin: 8px 0 0 0;
}
.ao-inv-card__fig img {
    border-radius: var(--ao-r-sm);
    display: block;
    max-height: 120px;
    max-width: 120px;
}
.ao-inv-card__fig figcaption {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    margin-top: 3px;
}
.ao-inv-conflict {
    color: var(--ao-warn-fg);
    font-size: var(--ao-fs-meta);
    margin-top: 2px;
}
.ao-inv-card__actions {
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding-top: 12px;
}
/* Internal / Defer change nothing in the catalog: a quieter pair at the
 * right edge — the same bordered pills, in a dimmer ink. */
.ao-inv-card__quiet {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-left: auto;
}
.ao-inv-card__quiet .ao-btn.is-quiet {
    color: var(--ao-fg-dim);
}
.ao-inv-card__quiet .ao-btn.is-quiet:hover {
    color: var(--ao-fg);
}
.ao-inv-card__result:empty {
    display: none;
}
.ao-inv-card__result > .ao-inv-ok,
.ao-inv-card__result > .ao-inv-err,
.ao-inv-card__result > .ao-inv-note {
    margin-top: 0;
}
.ao-inv-editor {
    align-items: end;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-lg);
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    padding: 12px;
}
.ao-inv-editor__title {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    grid-column: 1 / -1;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.ao-inv-editor__field {
    color: var(--ao-fg-mute);
    display: flex;
    flex-direction: column;
    font-size: var(--ao-fs-label);
    gap: 4px;
}
.ao-inv-editor__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    grid-column: 1 / -1;
}

/* Mobile. The scope bar stacks and the pickers go full width so the active
 * tenant/store stay readable on a phone, which is where a shelf count happens.
 * Actions keep a real touch floor. */
@media (max-width: 760px) {
    .ao-inv-scope {
        flex-direction: column;
        align-items: stretch;
    }
    .ao-inv-scope .ao-picker-trigger,
    .ao-inv-searchwrap,
    .ao-inv-search {
        min-width: 0;
        width: 100%;
    }
    .ao-inv-action {
        min-height: 36px;
    }
    .ao-inv-action.ao-btn-sm {
        min-height: 32px;
    }
    .ao-inv-card {
        padding: 12px 12px 12px 15px;
    }
    /* Sessions on a phone: CSV / Audit are their icons (the name is the
     * aria-label). */
    .ao-inv-rowacts .ao-btn-label {
        display: none;
    }
    .ao-inv-sessions-host .ao-table th,
    .ao-inv-sessions-host .ao-table td {
        padding-left: 6px;
        padding-right: 6px;
    }
    .ao-inv-sessions-host .ao-table td.has-bar {
        min-width: 64px;
    }
    .ao-inv-sessions-host .ao-inv-stackcell > span:first-child {
        white-space: normal;
    }
    .ao-inv-card__quiet {
        margin-left: 0;
    }
    .ao-inv-legend {
        gap: 6px 14px;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
 * STORES — connector health + live POS events (Stores, Live POS events)
 * ══════════════════════════════════════════════════════════════════════════
 *
 * Every rule here replaced an inline style (the pages carried 37 of them,
 * with raw colours and translucent-white borders). Tokens only.
 */
.ao-st-stack {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
.ao-st-stack > .ao-sec-head {
    margin: var(--ao-s-2) 0 0;
}
/* The back button sits in the store header card's actions slot, beside
 * the verdict (New physical count keeps its own in the same place). */
.ao-st-back {
    flex: none;
}
.ao-st-panel {
    min-width: 0;
}
.ao-st-note {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    line-height: 1.55;
    margin: 0;
    max-width: 110ch;
}
.ao-st-panel > .ao-st-note {
    margin-top: 10px;
}
.ao-st-muted {
    color: var(--ao-fg-mute);
}
.ao-st-peak,
.ao-st-count {
    align-items: center;
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    gap: 6px;
    white-space: nowrap;
}
/* The key to the one bar drawn in the peak colour. */
.ao-st-peak-dot {
    background: var(--ao-k-3);
    border-radius: 50%;
    display: inline-block;
    flex: none;
    height: 8px;
    width: 8px;
}
/* A freshness pill keeps its label's case: uppercase turned "1m ago" (a
 * minute) into "1M AGO" (a month). */
.ao-state-pill.ao-st-fresh {
    letter-spacing: 0;
    text-transform: none;
}
/* A KPI card that is a warning says so at its edge, not only in its icon
 * tile (storesStatRow's `warn: true`). */
.ao-stat.ao-st-warn {
    border-color: var(--ao-warn-border);
    box-shadow:
        inset 0 2px 0 var(--ao-warn),
        var(--ao-elev-1);
}
.ao-stat.ao-st-warn:hover,
.ao-stat.ao-st-warn:focus-visible {
    box-shadow:
        inset 0 2px 0 var(--ao-warn),
        var(--ao-elev-2);
}
/* Table columns a phone drops (storesTagCols), and the bits only a phone
 * shows in their place. */
@media (max-width: 760px) {
    .ao-st-phone-hide {
        display: none;
    }
}
@media (min-width: 761px) {
    .ao-st-phone-only {
        display: none;
    }
}
/* A KPI row of two columns on a phone: an odd last card takes the whole
 * last line instead of sitting beside a hole (Stores' five, Products' row
 * of five). Only where the row is two wide: a regular row up to 540px, a
 * small one up to 430px. */
@media (max-width: 540px) {
    .ao-st-stack > .ao-stat-row:not(.is-sm) > .ao-stat:last-child:nth-child(odd),
    .ao-inv-content .ao-stat-row:not(.is-sm) > .ao-stat:last-child:nth-child(odd),
    .ao-inv-content .ao-stat-row.ao-inv-kpis-more > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
}
@media (max-width: 430px) {
    .ao-inv-content .ao-stat-row.is-sm > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
}
.ao-st-index .ao-table td {
    white-space: nowrap;
}
.ao-st-store {
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.ao-st-store-name {
    color: var(--ao-fg);
    font-weight: 600;
}
.ao-st-store-sub {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
}
.ao-st-tenant-id {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}

/* The detail hero: which store, and the verdict — the tone edge and glow come
 * from the state (ok / warn / err / unknown), never a raw colour. */
.ao-st-hero {
    --ao-st-tone: var(--ao-fg-mute);
    align-items: center;
    display: grid;
    gap: 12px 16px;
    grid-template-columns: auto minmax(0, 1fr) auto;
    overflow: hidden;
    padding: 18px 20px 18px 22px;
    position: relative;
}
.ao-st-hero.is-ok {
    --ao-st-tone: var(--ao-ok);
}
.ao-st-hero.is-warn {
    --ao-st-tone: var(--ao-warn);
}
.ao-st-hero.is-err {
    --ao-st-tone: var(--ao-err);
}
.ao-st-hero::before {
    background: var(--ao-st-tone);
    content: '';
    inset: 0 auto 0 0;
    position: absolute;
    width: 3px;
}
.ao-st-hero::after {
    background: radial-gradient(
        90% 160% at 0% 0%,
        color-mix(in srgb, var(--ao-st-tone) 16%, transparent),
        transparent 60%
    );
    content: '';
    inset: 0;
    pointer-events: none;
    position: absolute;
}
.ao-st-hero > * {
    position: relative;
    z-index: 1;
}
.ao-st-hero-badge {
    background: color-mix(in srgb, var(--ao-st-tone) 14%, var(--ao-surface));
    border-radius: 12px;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ao-st-tone) 32%, transparent);
    color: var(--ao-st-tone);
    display: grid;
    height: 46px;
    place-items: center;
    width: 46px;
}
.ao-st-hero-name {
    color: var(--ao-fg);
    font-size: var(--ao-fs-h);
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.25;
    overflow-wrap: anywhere;
}
.ao-st-hero-meta {
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 2px 10px;
    margin-top: 3px;
}
/* The separator trails each item, so a wrapped line never starts with one. */
.ao-st-hero-meta > span:not(:last-child)::after {
    content: '·';
    margin-left: 10px;
    opacity: 0.6;
}
.ao-st-hero-state {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px 10px;
    justify-content: flex-end;
}
.ao-st-hero-state .ao-state-pill {
    font-size: var(--ao-fs-meta);
    padding: 3px 12px;
}
.ao-st-reasons {
    background: var(--ao-tint);
    border-radius: var(--ao-r-lg);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    grid-column: 1 / -1;
    line-height: 1.6;
    margin: 0;
    padding: 10px 14px 10px 30px;
}

/* A panel's label / value lines. */
.ao-st-kv {
    align-items: baseline;
    border-top: 1px solid var(--ao-tint-line);
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 12px;
    padding: 7px 0;
}
.ao-sec-head + .ao-st-kv {
    border-top: 0;
}
.ao-st-kv-k {
    color: var(--ao-fg-mute);
    flex: 0 0 min(42%, 210px);
}
.ao-st-kv-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    min-width: 0;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
}
.ao-st-kv.is-warn .ao-st-kv-v {
    color: var(--ao-warn-fg);
}
.ao-st-kv.is-err .ao-st-kv-v {
    color: var(--ao-err-fg);
}
.ao-st-grid {
    align-items: stretch;
    display: grid;
    gap: var(--ao-s-4);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
}
/* Live and Agent stack in one column beside Delivery; the boot snapshot
 * spans the grid under them, its lines in as many columns as fit. */
.ao-st-col {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
/* The two sides end level: whichever is shorter, its last card grows. */
.ao-st-col > .ao-st-panel:last-child {
    flex: 1 1 auto;
}
.ao-st-panel.is-wide {
    grid-column: 1 / -1;
}
.ao-st-kvgrid {
    column-gap: var(--ao-s-6);
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr));
}
.ao-st-callout {
    border-radius: var(--ao-r-md);
    font-size: var(--ao-fs-meta);
    line-height: 1.5;
    margin-top: 10px;
    padding: 8px 12px;
}
.ao-st-callout.is-warn {
    background: var(--ao-warn-bg);
    box-shadow: inset 3px 0 0 var(--ao-warn-border);
    color: var(--ao-warn-fg);
}

/* Captures per hour: bars are a scaleY of --ao-fill, so the only inline
 * writes are the data. A zero hour keeps a 2px stub. */
/* A y axis (peak, half, 0) left of the plot, the hour axis under it. The
 * two gridlines sit where the peak and half labels do; 0 is the baseline. */
.ao-st-hist {
    --ao-st-hist-h: 128px;
    --ao-st-hist-gap: 3px;
    column-gap: 10px;
    display: grid;
    grid-template-areas:
        'y plot'
        '. axis';
    grid-template-columns: auto minmax(0, 1fr);
    row-gap: 6px;
}
.ao-st-hist-y {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    grid-area: y;
    height: var(--ao-st-hist-h);
    min-width: 2ch;
    position: relative;
    text-align: right;
}
.ao-st-hist-y > span {
    line-height: 1;
    position: absolute;
    right: 0;
    transform: translateY(-50%);
}
.ao-st-hist-y > .is-top {
    top: 4px;
}
.ao-st-hist-y > .is-mid {
    top: calc(50% + 2px);
}
.ao-st-hist-y > .is-bot {
    top: 100%;
}
.ao-st-hist-plot {
    align-items: stretch;
    background:
        linear-gradient(var(--ao-tint-line), var(--ao-tint-line)) 0 4px / 100% 1px no-repeat,
        linear-gradient(var(--ao-tint-line), var(--ao-tint-line)) 0 calc(50% + 2px) / 100% 1px no-repeat;
    border-bottom: 1px solid var(--ao-border-soft);
    box-sizing: border-box;
    display: flex;
    gap: var(--ao-st-hist-gap);
    grid-area: plot;
    height: var(--ao-st-hist-h);
    padding-top: 4px;
}
.ao-st-hist-col {
    align-items: flex-end;
    display: flex;
    flex: 1;
    min-width: 4px;
    position: relative;
}
.ao-st-hist-bar {
    background: linear-gradient(180deg, var(--ao-k-1), color-mix(in srgb, var(--ao-k-1) 35%, transparent));
    border-radius: 4px 4px 1px 1px;
    display: block;
    height: 100%;
    transform: scaleY(var(--ao-fill, 0));
    transform-origin: bottom center;
    transition:
        transform 620ms var(--ao-ease),
        filter var(--ao-fast) var(--ao-ease);
    width: 100%;
}
.ao-st-hist-col:hover .ao-st-hist-bar {
    filter: brightness(1.3);
}
.ao-st-hist-col.is-peak .ao-st-hist-bar {
    background: linear-gradient(180deg, var(--ao-k-3), color-mix(in srgb, var(--ao-k-3) 35%, transparent));
}
.ao-st-hist-col.is-zero::after {
    background: var(--ao-tint-strong);
    border-radius: 1px;
    bottom: 0;
    content: '';
    height: 2px;
    left: 0;
    position: absolute;
    right: 0;
}
/* One slot per hour, spaced like the bars, so a label sits under its hour. */
.ao-st-hist-axis {
    color: var(--ao-fg-mute);
    display: flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    gap: var(--ao-st-hist-gap);
    grid-area: axis;
}
.ao-st-hist-axis > span {
    flex: 1 1 0;
    min-width: 0;
    white-space: nowrap;
}

/* The live events table and its receipt-style detail row. */
.ao-st-evrow.is-open > td {
    background: var(--ao-hover);
}
/* The row's chevron: it opens the receipt, and turns down while open. */
.ao-st-evgo {
    color: var(--ao-fg-mute);
    display: grid;
    place-items: center;
    transition:
        transform var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease);
}
.ao-st-evrow:hover .ao-st-evgo {
    color: var(--ao-fg);
}
.ao-st-evrow.is-open .ao-st-evgo {
    color: var(--ao-fg);
    transform: rotate(90deg);
}
/* Fifty rows in a 520px box: the foot fades while there is more below. */
.ao-st-evwrap::after {
    background: linear-gradient(180deg, transparent, var(--ao-surface));
    bottom: 0;
    content: '';
    display: block;
    height: 36px;
    margin-top: -36px;
    pointer-events: none;
    position: sticky;
    transition: opacity var(--ao-fast) var(--ao-ease);
}
.ao-st-evwrap.is-end::after {
    opacity: 0;
}
.ao-table td.ao-st-evdetail-cell {
    background: var(--ao-tint);
    padding: 12px 16px 14px;
    white-space: normal;
}
.ao-st-evtype {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-block;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    line-height: 1.6;
    padding: 0 9px;
    white-space: nowrap;
}
.ao-st-evtype.is-refund {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-border);
    color: var(--ao-warn-fg);
}
.ao-st-evtype.is-nosale {
    background: transparent;
    border-style: dashed;
    color: var(--ao-fg-mute);
}
.ao-st-money.is-neg,
.ao-st-lat.is-slow {
    color: var(--ao-warn-fg);
}
.ao-st-receipt {
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: 760px;
}
.ao-st-receipt-totals {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ao-st-receipt-chip {
    align-items: baseline;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    padding: 3px 10px;
}
.ao-st-receipt-k {
    color: var(--ao-fg-mute);
}
.ao-st-receipt-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-weight: 600;
}
.ao-st-receipt-lines {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-md);
    display: flex;
    flex-direction: column;
}
.ao-st-receipt-line {
    border-top: 1px dashed var(--ao-tint-line);
    display: grid;
    font-size: var(--ao-fs-meta);
    gap: 12px;
    grid-template-columns: 96px minmax(0, 1fr) 48px 84px;
    padding: 6px 12px;
}
.ao-st-receipt-line:first-child {
    border-top: 0;
}
.ao-st-receipt-kind {
    align-self: center;
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.ao-st-receipt-desc {
    color: var(--ao-fg);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-st-receipt-qty,
.ao-st-receipt-amt {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    text-align: right;
}
.ao-st-receipt-amt {
    color: var(--ao-fg);
}
.ao-st-receipt-tender {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
.ao-st-receipt-lineage {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    overflow-wrap: anywhere;
}

@media (max-width: 760px) {
    .ao-st-hero {
        grid-template-columns: auto minmax(0, 1fr);
        padding: 14px 16px 14px 18px;
    }
    .ao-st-hero-state {
        grid-column: 1 / -1;
        justify-content: space-between;
    }
    .ao-st-kv {
        flex-direction: column;
        gap: 2px;
    }
    .ao-st-kv-k {
        flex-basis: auto;
    }
    .ao-st-hist {
        --ao-st-hist-h: 96px;
        --ao-st-hist-gap: 2px;
        column-gap: 6px;
    }
    .ao-st-hist-axis > .is-minor {
        visibility: hidden;
    }
    /* The events table keeps four columns on a phone; tighter cells fit
     * them without a sideways scroll. */
    .ao-st-events .ao-table th,
    .ao-st-events .ao-table td {
        padding-left: 6px;
        padding-right: 6px;
    }
    .ao-st-index .ao-table td:first-child {
        white-space: normal;
    }
    /* The stores index keeps three columns on a phone: tighter cells and a
     * header that may break ("LAST POS / EVENT") fit them in the card. */
    .ao-st-index .ao-table th,
    .ao-st-index .ao-table td {
        padding-left: 8px;
        padding-right: 8px;
    }
    .ao-st-index .ao-table th {
        white-space: normal;
    }
    .ao-st-receipt-line {
        grid-template-columns: minmax(0, 1fr) 40px 72px;
    }
    .ao-st-receipt-kind {
        display: none;
    }
}
/* The Stores and Inventory bars and meters ease their transforms; reduced
 * motion jumps them to the value. (A page section's own block — the last
 * reduced-motion block in the file stays the Team profile's.) */
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-st-hist-bar,
    :where(html:not([data-motion='full'])) .ao-st-evgo,
    :where(html:not([data-motion='full'])) .ao-st-evwrap::after,
    :where(html:not([data-motion='full'])) .ao-inv-meter-fill,
    :where(html:not([data-motion='full'])) .ao-inv-stack-seg {
        transition: none;
    }
}

/* ── OCCUPANCY ───────────────────────────────────────────────────────────
 *
 * The per-camera heat map (#/occupancy). Every rule here exists to keep one
 * fact legible: the bottom row of the grid is where people whose FEET LEFT
 * THE FRAME get clamped, so on 11 of 28 fleet cameras it holds >= 15% of all
 * person-frames (worst: 87.2%). That is framing, not floor. The clipped-row
 * badge is styled to be read before the picture is, and the clipping row of
 * the grid itself is hatched so it can never pass for ordinary heat.
 *
 * Design system v2 (2026-09-23): the list is a sortable table in the Team
 * card, the fleet numbers are KPI cards, the heat is a token (--ao-occ-heat)
 * with only its strength (--v) set per cell, and the scale has a legend.
 */
/* The fleet strip fills in after the list loads; nothing holds its place. */
.ao-occ-kpis:empty {
    display: none;
}
.ao-occ-kpi-store {
    color: var(--ao-fg-dim);
}
/* The clipped-row opt-in rides the grid's disclosure line, right-aligned:
 * its name and the caveat (a muted sub), then the switch. */
.ao-occ-toggle {
    align-items: center;
    display: flex;
    gap: var(--ao-s-3);
    margin-left: auto;
    min-width: 0;
}
.ao-occ-toggle-text {
    display: flex;
    flex-direction: column;
    gap: 1px;
    line-height: 1.35;
    min-width: 0;
    text-align: right;
}
.ao-occ-toggle-k {
    color: var(--ao-fg);
    font-size: var(--ao-fs-body);
    font-weight: 600;
}
.ao-occ-toggle-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    max-width: 66ch;
}
.ao-occ-list {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
}
.ao-occ-table .ao-occ-row {
    cursor: pointer;
}
/* The camera whose grid is open below keeps the accent tick. */
.ao-occ-table tbody tr.is-selected > td {
    background: var(--ao-hover);
}
.ao-occ-table tbody tr.is-selected > td:first-child {
    box-shadow: inset 3px 0 0 var(--ao-accent-line);
}
.ao-occ-row-id {
    color: var(--ao-fg);
    max-width: 260px;
}
/* The camera cell's sub-line: the cut id, then (for a named camera) its
 * store. */
.ao-occ-cam-sub {
    align-items: baseline;
    display: flex;
    gap: 6px;
    min-width: 0;
}
.ao-occ-cam-sub .ao-cam-cell-id {
    flex: none;
}
.ao-occ-cam-store {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-occ-cam-store::before {
    content: '· ';
}
.ao-occ-row-clip {
    min-width: 96px;
}
/* The column header already says CLIPPED ROW: the table's badge is the share
 * alone ("6.2%"); the grid panel keeps the words. */
.ao-occ-table .ao-occ-clip-word {
    display: none;
}
/* The clipped-row meter: the share as a fill, the loud threshold as a tick. */
.ao-occ-meter {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: block;
    height: 4px;
    margin-top: 6px;
    overflow: hidden;
    position: relative;
}
/* The tick sits at OCC_CLIPPED_LOUD (0.15), the endpoint's loud threshold. */
.ao-occ-meter::after {
    background: var(--ao-fg-mute);
    bottom: 0;
    content: '';
    left: 15%;
    position: absolute;
    top: 0;
    width: 1px;
}
.ao-occ-meter-fill {
    background: var(--ao-fg-mute);
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
.ao-occ-row-clip:has(.ao-occ-clip-loud) .ao-occ-meter-fill {
    background: var(--ao-warn-strong);
}
/* The badge is a QUIET surface tone until the share crosses the endpoint's own
 * loud threshold — a permanently bright chip is a warning nobody reads. */
.ao-occ-clip {
    background: var(--ao-surface-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-tag);
    /* ⛔ The share must always be read: even quiet, it is dim, not mute. */
    color: var(--ao-fg-dim);
    display: inline-block;
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    padding: 1px 8px;
    white-space: nowrap;
}
.ao-occ-clip-loud {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-strong);
    color: var(--ao-warn-text);
    font-weight: 600;
}
.ao-occ-detail.is-loading > .ao-occ-panel {
    opacity: 0.55;
    transition: opacity var(--ao-base) var(--ao-ease);
}
.ao-occ-panel {
    --ao-occ-heat: var(--ao-warn-strong);
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-xl);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    padding: var(--ao-s-4);
}
.ao-occ-panel-head {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2) var(--ao-s-3);
    justify-content: space-between;
}
.ao-occ-panel-names {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-2) var(--ao-s-3);
    min-width: 0;
}
.ao-occ-panel-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-title);
    font-weight: 600;
    overflow-wrap: anywhere;
}
.ao-occ-panel-unit {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
}
.ao-occ-clipline {
    align-items: center;
    background: var(--ao-tint);
    border-radius: var(--ao-r-md);
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    padding: 8px 10px;
}
.ao-occ-clipline.is-loud {
    background: var(--ao-warn-bg);
    box-shadow: inset 3px 0 0 var(--ao-warn-strong);
}
/* Under the line nothing needs the sunken bar: the pill and the switch sit
 * on the panel itself. */
.ao-occ-clipline:not(.is-loud) {
    background: none;
    padding: 0;
}
.ao-occ-clipnote {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-occ-clipnote-loud {
    color: var(--ao-warn-text);
}
/* The picture beside its numbers; they stack on a narrow page. */
.ao-occ-body {
    align-items: start;
    display: grid;
    gap: var(--ao-s-4);
    grid-template-columns: minmax(0, 560px) minmax(220px, 320px);
}
.ao-occ-figure {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-2);
    min-width: 0;
}
.ao-occ-grid {
    aspect-ratio: 1 / 1;
    background: var(--ao-border-faint);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-md);
    display: grid;
    gap: 1px;
    grid-template-columns: repeat(var(--ao-occ-n, 16), 1fr);
    max-width: 560px;
    overflow: hidden;
    padding: 1px;
}
/* Linear heat: the token at the cell's own strength (--v, 0..1). */
.ao-occ-cell {
    background-color: color-mix(in srgb, var(--ao-occ-heat) calc(var(--v, 0) * 100%), var(--ao-bg));
    min-height: 0;
}
/* ⛔ THE CLIPPING ROW IS HATCHED, ALWAYS. Colour alone would make a bar of
 * clamped feet look exactly like a bar of people standing there — which is
 * the misreading this whole surface was built to prevent. The hatch survives
 * a screenshot, a colourblind viewer, and a printout. */
.ao-occ-cell-clipped {
    background-image: repeating-linear-gradient(
        45deg,
        var(--ao-tint-strong) 0,
        var(--ao-tint-strong) 2px,
        transparent 2px,
        transparent 5px
    );
}
.ao-occ-legend {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-label);
    gap: 6px;
}
.ao-occ-legend-ramp {
    background: linear-gradient(90deg, var(--ao-bg), var(--ao-occ-heat));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-bar);
    height: 8px;
    width: 96px;
}
.ao-occ-legend-hatch {
    background: repeating-linear-gradient(45deg, var(--ao-tint-strong) 0 2px, transparent 2px 5px);
    border: 1px solid var(--ao-border-soft);
    border-radius: 3px;
    height: 12px;
    width: 18px;
}
.ao-occ-legend-k {
    color: var(--ao-fg-dim);
}
.ao-occ-legend-item {
    align-items: center;
    display: inline-flex;
    gap: 6px;
    margin-left: var(--ao-s-2);
    white-space: nowrap;
}
/* Beside the picture the five numbers are one column, as tall as the grid
 * (two across left ~200px of empty panel beside it). */
.ao-occ-body > .ao-occ-stats {
    align-content: start;
    grid-template-columns: minmax(0, 1fr);
}
.ao-occ-notes {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.ao-occ-note {
    align-items: flex-start;
    color: var(--ao-fg-mute);
    display: flex;
    font-size: var(--ao-fs-meta);
    gap: 6px;
    line-height: 1.5;
}
.ao-occ-note .ao-ico {
    flex: none;
    margin-top: 2px;
}
@media (max-width: 900px) {
    .ao-occ-body {
        grid-template-columns: minmax(0, 1fr);
    }
}
@media (max-width: 900px) {
    /* Under the picture, the five numbers go back to a grid. */
    .ao-occ-body > .ao-occ-stats {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .ao-occ-body > .ao-occ-stats > .ao-stat:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
}
@media (max-width: 760px) {
    .ao-occ-row-id {
        max-width: 120px;
    }
    .ao-occ-toggle {
        justify-content: space-between;
        margin-left: 0;
        width: 100%;
    }
    .ao-occ-toggle-text {
        text-align: left;
    }
}
/* A phone keeps CAMERA, CLIPPED ROW and PERSON-FRAMES: tracks and cells
 * drop out. */
@media (max-width: 759px) {
    .ao-occ-table th:nth-child(4),
    .ao-occ-table td:nth-child(4),
    .ao-occ-table th:nth-child(5),
    .ao-occ-table td:nth-child(5) {
        display: none;
    }
    .ao-occ-table th,
    .ao-occ-table td {
        padding-left: 8px;
        padding-right: 8px;
    }
    .ao-occ-table td.has-bar,
    .ao-occ-row-clip {
        min-width: 64px;
    }
    .ao-occ-row-id .ao-cam-cell {
        max-width: 118px;
    }
    /* The store stays on the grid panel's title below; the row keeps the
     * name and the cut id, so the three columns fit the card. */
    .ao-occ-row-id .ao-occ-cam-store {
        display: none;
    }
    .ao-occ-row-id .ao-cam-cell-name {
        white-space: nowrap;
    }
}
@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-occ-meter-fill,
    :where(html:not([data-motion='full'])) .ao-occ-detail.is-loading > .ao-occ-panel {
        transition: none;
    }
}

/* ── SHIP tab (#/ship) ────────────────────────────────────────────────────
   Five stacked sections, same heading/subtitle pair the VERSIONS catalog uses
   (.ao-vcat-head / .ao-vcat-sub) so the page reads as part of the console
   rather than a second opinion about what a section header looks like.

   ⛔ Every new class here exists because the tab shipped a node that had no
   rule: an unstyled paint is one of the six defects that reached the owner on
   2026-09-22, and none of them was visible to any test. If you add a node,
   add its rule in the same edit. */
.ao-ship-section {
    margin-top: 18px;
}
.ao-ship-what-line {
    padding: 2px 0;
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
}
.ao-ship-what-lead {
    margin-top: 8px;
    font-size: var(--ao-fs-meta);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ao-fg-mute);
}
.ao-ship-what-list {
    margin: 4px 0 0;
    padding-left: 18px;
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
}
.ao-ship-what-list li {
    margin: 2px 0;
}
.ao-ship-live-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 0 16px 4px;
}
.ao-ship-live-shas {
    /* A short sha is read character by character — monospace so 0/O and 1/l
       cannot be confused while comparing two of them side by side. */
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: var(--ao-fs-body);
    color: var(--ao-fg-dim);
}
.ao-ship-inflight-line {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    padding: 3px 16px;
    font-size: var(--ao-fs-body);
}
.ao-ship-inflight-label {
    min-width: 88px;
    color: var(--ao-fg-mute);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-size: var(--ao-fs-meta);
}
.ao-ship-inflight-state {
    color: var(--ao-fg-dim);
    font-weight: 600;
}
.ao-ship-inflight-link {
    color: var(--ao-accent);
    text-decoration: none;
    border-bottom: 1px solid var(--ao-border-soft);
}
.ao-ship-inflight-link:hover {
    border-bottom-color: var(--ao-accent);
}
/* MERGE / PROMOTE drawn as UNAVAILABLE to this token (no ship:write, or no
   write credential on the ops-api). Muted, never the error palette: nothing
   failed, this key simply cannot ship. */
.ao-ship-unavailable {
    padding: 4px 16px;
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
}
span.ao-ship-unavailable {
    padding: 0;
    font-size: var(--ao-fs-meta);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
}
/* ============================================================================
 * TEAM (#/team) — contributor leaderboard + the shared Team primitives
 * (aoAvatar, aoRange, aoSpark, aoDeltaPill, KPI / podium / leader cards).
 *
 * "Mission control, inside the graphite palette" (spec §6.2). The console
 * stays graphite; the only vivid colour on the page is each teammate's OWN
 * hue (hsl(var(--ao-tm-h) …), sent by the API in the never-red 35..325 band)
 * plus one muted accent per team KPI. Text never wears a data colour. The
 * --ao-tm-* colour tokens live in the :root block at the top of this file.
 *
 * ⛔ No SVG url(#…) gradients anywhere below — the embedded portal's
 * <base href="/"> makes them resolve against the wrong document and paint
 * nothing. Every gradient here is a CSS background.
 * ⛔ Every entrance is transform-only or keeps an opacity floor of 0.55
 * (portal-invisible-animation.contract.test.js), lives under .ao-tm-in (a
 * class the JS adds only on a real navigation or a user's range change, never
 * on a poll), and is switched off in the reduced-motion block at the end.
 * ========================================================================== */

/* The rotating conic ring needs an animatable angle. Without @property
 * support the ring simply holds still — nothing breaks. */
@property --ao-tm-angle {
    syntax: '<angle>';
    inherits: false;
    initial-value: 0deg;
}

/* ── page frame ─────────────────────────────────────────────────────────── */
/* A container, so every breakpoint below answers "how wide is the page
 * BODY" — the rail already takes 220px, and a viewport query would put the
 * leaderboard's collapse points 220px in the wrong place. */
.ao-tm-page {
    container-type: inline-size;
    container-name: aotm;
    gap: var(--ao-s-5);
    /* Belt and braces for "no horizontal page scroll": whatever a future
     * label does at a silly width, it is clipped here rather than giving the
     * whole console a sideways scrollbar. clip, not hidden: no scroll
     * container, so nothing sticky or vertical changes. */
    overflow-x: clip;
}
/* The UA's [hidden] is display:none at author-overridable strength; every
 * slot below sets its own display, so restate it. */
.ao-tm-page [hidden] {
    display: none !important;
}
/* Faint dot grid behind the page title — texture, not noise. */
.ao-tm-head {
    isolation: isolate;
}
.ao-tm-head::before {
    background-image: radial-gradient(circle, var(--ao-tint-strong) 1px, transparent 1.5px);
    background-size: 18px 18px;
    content: '';
    inset: 0;
    -webkit-mask-image: radial-gradient(ellipse 60% 160% at 0% 0%, black 0%, transparent 72%);
    mask-image: radial-gradient(ellipse 60% 160% at 0% 0%, black 0%, transparent 72%);
    pointer-events: none;
    position: absolute;
    z-index: -1;
}

/* ── control bar: range + sync status ───────────────────────────────────── */
.ao-tm-bar {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3);
    justify-content: space-between;
}
.ao-tm-range {
    max-width: 100%;
    position: relative;
}
/* A SEGMENTED BAR, not a tray of pills (2026-09-24, owner: "hate this bubble
 * shit"): one bordered box at the control radius, the segments split by 1px
 * rules, the pressed one tinted and bold. The same shape as the tab bar and
 * the portal's Kit segmented filter (.kit-segs). overflow clips the corners
 * (and scrolls a long bar sideways), so focus rings sit inside. */
.ao-tm-seg {
    background: var(--ao-surface);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-ctl);
    display: flex;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
}
.ao-tm-seg::-webkit-scrollbar {
    display: none;
}
/* min-height: an explicit literal floor (design system v2). Inside the portal
 * css/main.css gave every button 44px, which is what stretched this tray; the
 * console-wide reset near the top of this file removes that, and the floor
 * here keeps the segment a 28px target on its own terms. */
.ao-tm-seg-btn {
    align-items: center;
    appearance: none;
    background: transparent;
    border: 0;
    border-left: 1px solid var(--ao-border-soft);
    border-radius: 0;
    color: var(--ao-fg-mute);
    cursor: pointer;
    display: inline-flex;
    flex: none;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    gap: 6px;
    letter-spacing: 0.06em;
    min-height: 28px;
    padding: 7px 12px;
    transition:
        background var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease),
        box-shadow var(--ao-fast) var(--ao-ease);
    white-space: nowrap;
}
.ao-tm-seg-btn:first-child {
    border-left: 0;
}
.ao-tm-seg-btn:hover {
    background: var(--ao-tint-2);
    color: var(--ao-fg);
}
.ao-tm-seg-btn[aria-pressed='true'] {
    background: var(--ao-rail-active);
    color: var(--ao-fg);
    font-weight: 700;
}
.ao-tm-seg-btn:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: -2px;
}
.ao-tm-seg-btn.is-custom {
    font-family: var(--ao-font-sans);
    font-weight: 500;
    letter-spacing: 0;
}
/* One case per tray: outreach's picker read "7d 30d 90d ALL". The source
 * labels stay as written (tests read them); Custom keeps its sentence case,
 * as it is a different kind of button (it opens a popover). */
.ao-tm-seg-btn:not(.is-custom) {
    text-transform: uppercase;
}
.ao-tm-range-pop {
    background: var(--ao-surface-2);
    border: 1px solid var(--ao-border);
    border-radius: 14px;
    box-shadow: var(--ao-elev-3);
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    left: 0;
    padding: var(--ao-s-4);
    position: absolute;
    top: calc(100% + 8px);
    width: min(340px, 100cqw);
    z-index: var(--ao-z-overlay);
}
.ao-tm-range-fields {
    display: grid;
    gap: var(--ao-s-2);
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.ao-tm-range-field {
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
}
.ao-tm-range-flabel {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-tm-date {
    background: var(--ao-bg);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-md);
    color: var(--ao-fg);
    color-scheme: dark;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-body);
    min-width: 0;
    padding: 7px 8px;
    width: 100%;
}
.ao-tm-date:focus {
    border-color: var(--ao-accent-line);
    outline: 2px solid var(--ao-focus);
    outline-offset: 1px;
}
.ao-tm-range-err {
    color: var(--ao-err-fg);
    font-size: var(--ao-fs-meta);
}
.ao-tm-range-err:empty {
    display: none;
}
.ao-tm-range-acts {
    display: flex;
    gap: var(--ao-s-2);
    justify-content: flex-end;
}

.ao-tm-sync {
    align-items: center;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    color: var(--ao-fg-dim);
    cursor: pointer;
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 8px;
    max-width: 100%;
    padding: 7px 12px 7px 11px;
    transition:
        border-color var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease);
}
.ao-tm-sync:hover {
    border-color: var(--ao-border);
    color: var(--ao-fg);
}
.ao-tm-sync:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-tm-sync .ao-ico {
    opacity: 0.7;
    transition: transform var(--ao-base) var(--ao-ease);
}
.ao-tm-sync[aria-expanded='true'] .ao-ico {
    transform: rotate(180deg);
}
.ao-tm-sync-dot {
    background: currentColor;
    border-radius: 50%;
    color: var(--ao-fg-mute);
    flex: none;
    height: 8px;
    position: relative;
    width: 8px;
}
.ao-tm-sync.is-ok .ao-tm-sync-dot {
    color: var(--ao-ok);
}
.ao-tm-sync.is-warn .ao-tm-sync-dot {
    color: var(--ao-warn);
}
.ao-tm-sync.is-err .ao-tm-sync-dot {
    color: var(--ao-err-strong);
}
/* The live pulse: a ring that breathes out of the dot. Scale + fade on a
 * pseudo-element — it never hides the dot itself. */
.ao-tm-sync-dot::after {
    animation: ao-tm-ping 2.4s var(--ao-ease) infinite;
    background: currentColor;
    border-radius: 50%;
    content: '';
    inset: 0;
    position: absolute;
}
.ao-tm-sync.is-unknown .ao-tm-sync-dot::after {
    display: none;
}
@keyframes ao-tm-ping {
    from {
        opacity: 0.55;
        transform: scale(1);
    }
    to {
        opacity: 0;
        transform: scale(2.8);
    }
}

.ao-tm-sources {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-3);
    padding: var(--ao-s-4);
}
.ao-tm-srclist {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-tm-src {
    align-items: flex-start;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: 12px;
    display: flex;
    gap: 10px;
    padding: 10px 12px;
}
.ao-tm-src-txt {
    min-width: 0;
}
.ao-tm-src-name {
    font-size: var(--ao-fs-body);
    font-weight: 600;
}
.ao-tm-src-meta {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-tm-src-note {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    line-height: 1.45;
    margin-top: 3px;
    overflow-wrap: anywhere;
}
.ao-tm-notcov-h {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    margin-bottom: 4px;
    text-transform: uppercase;
}
.ao-tm-notcov ul {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    line-height: 1.55;
    margin: 0;
    padding-left: 18px;
}

/* ── panel + board ──────────────────────────────────────────────────────── */
.ao-tm-panel {
    min-width: 0;
    position: relative;
}
/* paintPanel({inPlace}) keeps the previous frame on screen while the next
 * range loads — dimmed, never swapped for LOADING (no layout jump). */
.ao-refetching {
    opacity: 0.55;
    transition: opacity var(--ao-base) var(--ao-ease);
}
.ao-tm-board,
.ao-tm-skel {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-7);
}
/* First load: the board's silhouette (see _tmSkeletonFrame). It is already a
 * "loading" signal, so it is not dimmed a second time by .ao-refetching. */
.ao-refetching:has(> .ao-tm-skel) {
    opacity: 1;
}
.ao-tm-kpi.is-skel {
    min-height: 190px;
}
.ao-tm-skel-tile {
    border-radius: 9px;
    height: 30px;
    width: 30px;
}
.ao-tm-skel-spark {
    height: 34px;
    margin-top: auto;
}
.ao-tm-pod.is-skel,
.ao-tm-pod.is-skel.is-p1 {
    /* No member, so no hue: the #1 card's hue border and glow would compute
     * to currentColor (white) without one. */
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-color: var(--ao-border-soft);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    gap: 12px;
    justify-content: center;
    min-height: 360px;
}
.ao-tm-pod.is-skel.is-p1 {
    min-height: 410px;
}
.ao-tm-skel-av {
    border-radius: 50%;
    height: 64px;
    width: 64px;
}
.ao-tm-skel-name {
    height: 14px;
    width: 46%;
}
.ao-tm-skel-num {
    height: 40px;
    width: 34%;
}
.ao-tm-skel-row {
    border-radius: 10px;
    height: 44px;
    margin: 10px 12px;
}
.ao-tm-rank,
.ao-tm-leaders {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
}
.ao-tm-sec-head {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
}
.ao-tm-h {
    font-size: var(--ao-fs-h);
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.25;
    margin: 0;
    overflow-wrap: anywhere;
}
.ao-tm-sec-sub {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-tm-empty {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-body);
    list-style: none;
    padding: var(--ao-s-5);
    text-align: center;
}
/* Nothing could be READ — not "nobody did anything". */
.ao-tm-empty.is-err {
    color: var(--ao-err);
}

/* ── the card ───────────────────────────────────────────────────────────── */
.ao-tm-card {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-tm-r);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    color: var(--ao-fg);
    min-width: 0;
    position: relative;
}
a.ao-tm-card {
    color: inherit;
    text-decoration: none;
}
a.ao-tm-card:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-tm-card.has-ring {
    --ao-tm-ring: var(--ao-tm-accent, var(--ao-accent-line));
    --ao-tm-ring2: var(--ao-tm-ring);
    transition:
        transform var(--ao-base) var(--ao-ease),
        box-shadow var(--ao-base) var(--ao-ease);
}
/* Member cards ring in the member's own hue. */
.ao-tm-pod.has-ring,
.ao-tm-leader.has-ring {
    --ao-tm-ring: hsl(var(--ao-tm-h) 80% 68%);
    --ao-tm-ring2: hsl(var(--ao-tm-h2) 75% 60%);
}
/* The 1px conic ring: a gradient box masked down to its own padding ring
 * (content-box XOR border-box), so only a hairline of it shows. */
.ao-tm-card.has-ring::before {
    background: conic-gradient(
        from var(--ao-tm-angle),
        transparent 0deg,
        var(--ao-tm-ring) 70deg,
        transparent 150deg,
        transparent 190deg,
        var(--ao-tm-ring2) 260deg,
        transparent 340deg
    );
    border-radius: inherit;
    content: '';
    inset: -1px;
    -webkit-mask:
        linear-gradient(black 0 0) content-box,
        linear-gradient(black 0 0);
    -webkit-mask-composite: xor;
    mask:
        linear-gradient(black 0 0) content-box,
        linear-gradient(black 0 0);
    mask-composite: exclude;
    opacity: 0;
    padding: 1px;
    pointer-events: none;
    position: absolute;
    transition: opacity var(--ao-slow) var(--ao-ease);
}
.ao-tm-card.has-ring:hover,
.ao-tm-card.has-ring:focus-visible {
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-2);
    transform: translateY(-2px);
}
.ao-tm-card.has-ring:hover::before,
.ao-tm-card.has-ring:focus-visible::before {
    animation: ao-tm-spin 5s linear infinite;
    opacity: 1;
}
@keyframes ao-tm-spin {
    to {
        --ao-tm-angle: 360deg;
    }
}

/* ── icon tile, chips, pills ────────────────────────────────────────────── */
.ao-ico {
    display: block;
    flex: none;
}
.ao-tm-ico-tile {
    background: color-mix(in srgb, var(--ao-tm-accent, var(--ao-fg-mute)) 14%, transparent);
    border-radius: 9px;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ao-tm-accent, var(--ao-fg-mute)) 24%, transparent);
    color: var(--ao-tm-accent, var(--ao-fg-dim));
    display: grid;
    flex: none;
    height: 30px;
    place-items: center;
    width: 30px;
}
.ao-tm-ico-tile.is-hue {
    background: hsl(var(--ao-tm-h) 60% 50% / 0.14);
    box-shadow: inset 0 0 0 1px hsl(var(--ao-tm-h) 60% 62% / 0.26);
    color: hsl(var(--ao-tm-h) 78% 72%);
}
.ao-tm-delta {
    align-items: center;
    border: 1px solid transparent;
    border-radius: var(--ao-r-tag);
    display: inline-flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 3px;
    letter-spacing: 0.02em;
    padding: 2px 7px;
    white-space: nowrap;
}
.ao-tm-delta.is-up {
    background: var(--ao-ok-bg);
    border-color: var(--ao-ok-bd);
    color: var(--ao-ok-fg);
}
.ao-tm-delta.is-down {
    background: var(--ao-err-bg);
    border-color: var(--ao-err-bd);
    color: var(--ao-err-fg);
}
.ao-tm-delta.is-flat,
.ao-tm-delta.is-new,
.ao-tm-delta.is-none {
    background: var(--ao-tint-2);
    border-color: var(--ao-border-soft);
    color: var(--ao-fg-dim);
}
.ao-tm-kind {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.04em;
    max-width: 100%;
    overflow: hidden;
    padding: 1px 7px;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tm-kind.is-ops {
    background: var(--ao-info-bg);
    border-color: var(--ao-info-bd);
    color: var(--ao-info-fg);
}
.ao-tm-kind.is-unlinked {
    border-style: dashed;
    color: var(--ao-fg-mute);
}
.ao-tm-login {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-tm-streak {
    align-items: center;
    background: color-mix(in srgb, var(--ao-tm-flame) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--ao-tm-flame) 32%, transparent);
    border-radius: var(--ao-r-tag);
    color: var(--ao-tm-flame);
    display: inline-flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 4px;
    padding: 2px 8px 2px 6px;
    white-space: nowrap;
}
.ao-tm-area {
    align-items: center;
    background: hsl(var(--ao-tm-h) 50% 50% / 0.12);
    border: 1px solid hsl(var(--ao-tm-h) 50% 62% / 0.26);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    gap: 6px;
    padding: 3px 9px;
}
.ao-tm-area-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
}
.ao-tm-move {
    color: var(--ao-fg-mute);
    display: inline-block;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    white-space: nowrap;
}
.ao-tm-move.is-up {
    color: var(--ao-ok-fg);
}
.ao-tm-move.is-down {
    color: var(--ao-err-fg);
}
.ao-tm-move.is-new {
    color: var(--ao-info-fg);
}
.ao-tm-move.is-bump.is-up {
    animation: ao-tm-bump-up 720ms var(--ao-ease) 520ms;
}
.ao-tm-move.is-bump.is-down {
    animation: ao-tm-bump-down 720ms var(--ao-ease) 520ms;
}
@keyframes ao-tm-bump-up {
    0%,
    100% {
        transform: translateY(0);
    }
    35% {
        transform: translateY(-5px);
    }
    65% {
        transform: translateY(1px);
    }
}
@keyframes ao-tm-bump-down {
    0%,
    100% {
        transform: translateY(0);
    }
    35% {
        transform: translateY(5px);
    }
    65% {
        transform: translateY(-1px);
    }
}

/* ── avatar ─────────────────────────────────────────────────────────────── */
.ao-tm-av {
    border-radius: 50%;
    display: inline-grid;
    flex: none;
    place-items: center;
    position: relative;
}
.ao-tm-av-disc {
    border-radius: 50%;
    box-shadow: inset 0 1px 0 var(--ao-tint-strong);
    color: var(--ao-fg);
    display: grid;
    font-weight: 600;
    height: 100%;
    letter-spacing: 0.02em;
    place-items: center;
    width: 100%;
}
.ao-tm-av-img {
    border-radius: 50%;
    height: 100%;
    inset: 0;
    object-fit: cover;
    position: absolute;
    width: 100%;
}
.ao-tm-av.has-ring::before {
    background: conic-gradient(
        from var(--ao-tm-angle),
        hsl(var(--ao-tm-h) 82% 68%),
        hsl(var(--ao-tm-h2) 76% 60%) 40%,
        transparent 58%,
        hsl(var(--ao-tm-h) 82% 68%)
    );
    border-radius: 50%;
    content: '';
    inset: -5px;
    -webkit-mask:
        linear-gradient(black 0 0) content-box,
        linear-gradient(black 0 0);
    -webkit-mask-composite: xor;
    mask:
        linear-gradient(black 0 0) content-box,
        linear-gradient(black 0 0);
    mask-composite: exclude;
    padding: 2px;
    pointer-events: none;
    position: absolute;
}
.ao-tm-av.is-spin::before {
    animation: ao-tm-spin 6s linear infinite;
}

/* ── sparkline ──────────────────────────────────────────────────────────── */
.ao-tm-spark {
    position: relative;
    width: 100%;
}
.ao-tm-spark-svg {
    display: block;
    height: 100%;
    overflow: visible;
    width: 100%;
}
.ao-tm-spark-line {
    fill: none;
    stroke: currentColor;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-width: 1.5;
    vector-effect: non-scaling-stroke;
}
.ao-tm-spark-area {
    fill: currentColor;
    opacity: 0.14;
    stroke: none;
}
.ao-tm-spark-dot {
    background: currentColor;
    border-radius: 50%;
    box-shadow:
        0 0 0 2px var(--ao-surface),
        0 0 10px currentColor;
    height: 7px;
    margin: -3.5px 0 0 -3.5px;
    pointer-events: none;
    position: absolute;
    width: 7px;
}
.ao-tm-spark-hair {
    background: var(--ao-tint-strong);
    bottom: 0;
    pointer-events: none;
    position: absolute;
    top: 0;
    width: 1px;
}
.ao-tm-spark-tip {
    background: var(--ao-ink);
    border-radius: 6px;
    bottom: calc(100% + 4px);
    box-shadow: var(--ao-elev-2);
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    padding: 2px 7px;
    pointer-events: none;
    position: absolute;
    white-space: nowrap;
    z-index: 3;
}
.ao-tm-spark-tip.is-right {
    transform: translateX(-100%);
}

/* ── KPI strip ──────────────────────────────────────────────────────────── */
/* 6 across, 3×2, 2×3 or 1 column — never 5 + an orphan, which is what
 * auto-fit produced at every width between the two. */
.ao-tm-kpis {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
@container aotm (min-width: 560px) {
    .ao-tm-kpis {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}
@container aotm (min-width: 1060px) {
    .ao-tm-kpis {
        grid-template-columns: repeat(6, minmax(0, 1fr));
    }
}
@container aotm (max-width: 299.98px) {
    .ao-tm-kpis {
        grid-template-columns: minmax(0, 1fr);
    }
}
.ao-tm-kpi {
    /* A size container so the big number can scale with its own card (cqi)
     * rather than overflow it when six cards share a narrow page. */
    container-type: inline-size;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 14px 16px 12px;
}
/* A hovered card's ⓘ popover must sit above its neighbours. */
.ao-tm-kpi:hover,
.ao-tm-kpi:focus-within {
    z-index: 2;
}
.ao-tm-kpi-head {
    align-items: center;
    display: flex;
    gap: 10px;
    min-width: 0;
}
.ao-tm-kpi-label {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-meta);
    font-weight: 500;
    letter-spacing: 0.02em;
    min-width: 0;
    overflow-wrap: break-word;
}
/* A very narrow card (the console shell leaves ~155px for a page on a phone)
 * stacks the icon over the label rather than breaking "Commits" mid-word. */
@container (max-width: 160px) {
    .ao-tm-kpi-head {
        align-items: flex-start;
        flex-direction: column;
        gap: 6px;
    }
}
/* The ⓘ definition opens across its own card, anchored to the card rather
 * than the label: a 320px popover hung off the label of the right-most of six
 * cards ran ~150px past the page edge. */
.ao-tm-kpi .ao-info-pop {
    left: 10px;
    max-width: none;
    right: 10px;
    top: 50px;
}
.ao-tm-kpi-valrow {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: 0 6px;
    margin-top: 6px;
    min-width: 0;
}
.ao-tm-kpi-num {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: clamp(18px, 21cqi, 34px);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.04em;
    line-height: 1.05;
    white-space: nowrap;
}
.ao-tm-kpi-num.is-unmeasured,
.ao-tm-pod-num.is-unmeasured {
    color: var(--ao-fg-mute);
    font-weight: 400;
}
.ao-tm-kpi-unit {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-tm-kpi-sub {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-tm-kpi-sub.is-dim {
    font-family: var(--ao-font-sans);
}
.ao-tm-plus {
    color: var(--ao-ok-fg);
}
.ao-tm-minus {
    color: var(--ao-err-fg);
}
.ao-tm-kpi-foot {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 8px;
    min-height: 20px;
}
.ao-tm-kpi-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
}
.ao-tm-kpi-spark {
    color: var(--ao-tm-accent, var(--ao-fg-dim));
    margin-top: auto;
    padding-top: 6px;
}

/* ── ranking: chips, podium, rows ───────────────────────────────────────── */
.ao-tm-sortbar {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
/* ⛔ ONE SEGMENTED BAR, NOT A TRAY OF CHIPS (2026-09-25). The chips variant
 * (aoSeg {variant:'chips'}, Team's "Rank by", Grade's WHO / DOING) drew each
 * option as its own rounded box with a gap and a glowing accent fill on the
 * pressed one: the "bubble" row the owner asked to wipe. It now draws as the
 * segmented bar (.ao-tm-seg): the options touch, split by 1px rules, the ends
 * round at the control radius, the pressed one tinted and bold. The caption
 * stays INSIDE the group (aoSeg's DOM, which tests pin) but outside the box:
 * the box is drawn by the buttons' own borders, the first and last button
 * closing the ends. A long bar scrolls sideways instead of wrapping into a
 * second, broken row. */
.ao-tm-chips {
    align-items: center;
    display: flex;
    flex-wrap: nowrap;
    gap: 0;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: thin;
}
/* More past the right edge (aoSeg / _aoMoreHint set data-more): the edge
 * fades, so a cut-off option reads as "more this way". */
.ao-tm-chips[data-more] {
    -webkit-mask-image: linear-gradient(90deg, black calc(100% - 56px), transparent);
    mask-image: linear-gradient(90deg, black calc(100% - 56px), transparent);
}
.ao-tm-chips-label {
    color: var(--ao-fg-mute);
    flex: none;
    font-size: var(--ao-fs-label);
    letter-spacing: 0.1em;
    margin-right: 10px;
    text-transform: uppercase;
}
.ao-tm-chip {
    align-items: center;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border);
    border-left-color: var(--ao-border-soft);
    border-radius: 0;
    border-right-width: 0;
    box-shadow: none;
    color: var(--ao-fg-dim);
    cursor: pointer;
    display: inline-flex;
    flex: none;
    font-family: inherit;
    font-size: var(--ao-fs-meta);
    font-weight: 500;
    gap: 6px;
    margin: 0;
    min-height: 28px;
    padding: 6px 12px;
    transition:
        background var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease);
    white-space: nowrap;
}
.ao-tm-chip:first-of-type {
    border-bottom-left-radius: var(--ao-r-ctl);
    border-left-color: var(--ao-border);
    border-top-left-radius: var(--ao-r-ctl);
}
.ao-tm-chip:last-of-type {
    border-bottom-right-radius: var(--ao-r-ctl);
    border-right-width: 1px;
    border-top-right-radius: var(--ao-r-ctl);
}
.ao-tm-chip .ao-ico {
    opacity: 0.75;
}
.ao-tm-chip:hover {
    background: var(--ao-hover);
    color: var(--ao-fg);
}
.ao-tm-chip:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: -2px;
}
.ao-tm-chip[aria-pressed='true'] {
    background: var(--ao-rail-active);
    color: var(--ao-fg);
    font-weight: 700;
}
.ao-tm-chip[aria-pressed='true'] .ao-ico {
    opacity: 1;
}

.ao-tm-podium {
    align-items: end;
    display: grid;
    gap: var(--ao-s-4);
    grid-template-areas: 'p2 p1 p3';
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.14fr) minmax(0, 1fr);
    margin-top: var(--ao-s-2);
}
.ao-tm-pod {
    align-items: center;
    container-type: inline-size;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 16px 18px 16px;
    text-align: center;
}
.ao-tm-pod.is-p1 {
    background:
        radial-gradient(120% 70% at 50% 0%, hsl(var(--ao-tm-h) 60% 45% / 0.2), transparent 62%),
        linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-color: hsl(var(--ao-tm-h) 40% 55% / 0.35);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-2),
        0 22px 48px -26px hsl(var(--ao-tm-h) 70% 50% / 0.6);
    grid-area: p1;
    padding-bottom: 20px;
    padding-top: 22px;
}
.ao-tm-pod.is-p2 {
    grid-area: p2;
}
.ao-tm-pod.is-p3 {
    grid-area: p3;
}
/* #1 wears its ring permanently, turning slowly. */
.ao-tm-pod.is-p1::before {
    animation: ao-tm-spin 9s linear infinite;
    opacity: 1;
}
/* Glow and the giant watermark numeral live in their own clipped layer, so
 * the card itself needs no overflow:hidden (which would clip the ring). */
.ao-tm-pod-fx {
    border-radius: inherit;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    position: absolute;
}
.ao-tm-pod > :not(.ao-tm-pod-fx) {
    position: relative;
    z-index: 1;
}
.ao-tm-pod-numeral {
    bottom: -40px;
    color: var(--ao-tint-2);
    font-family: var(--ao-mono);
    font-size: 150px;
    font-weight: 600;
    letter-spacing: -0.06em;
    line-height: 1;
    position: absolute;
    right: -6px;
    user-select: none;
}
.ao-tm-pod.is-p1 .ao-tm-pod-numeral {
    color: hsl(var(--ao-tm-h) 60% 62% / 0.1);
    font-size: 180px;
}
.ao-tm-pod-top {
    align-items: center;
    align-self: stretch;
    display: flex;
    flex-wrap: wrap;
    gap: 4px 8px;
    justify-content: space-between;
    margin-bottom: 6px;
    min-height: 22px;
}
.ao-tm-medal {
    align-items: center;
    border-radius: var(--ao-r-tag);
    color: var(--ao-accent-fg);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    font-weight: 700;
    gap: 5px;
    letter-spacing: 0.08em;
    padding: 3px 9px 3px 7px;
    text-transform: uppercase;
}
.ao-tm-medal.is-m1 {
    background: var(--ao-tm-gold);
    box-shadow: 0 0 18px -4px var(--ao-tm-gold);
}
.ao-tm-medal.is-m2 {
    background: var(--ao-tm-silver);
}
.ao-tm-medal.is-m3 {
    background: var(--ao-tm-bronze);
}
.ao-tm-pod .ao-tm-av {
    margin: 4px 0 6px;
}
.ao-tm-pod-name {
    font-size: var(--ao-fs-title);
    font-weight: 600;
    letter-spacing: -0.01em;
    overflow-wrap: anywhere;
}
.ao-tm-pod-sub {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: center;
    min-height: 18px;
}
.ao-tm-pod-val {
    align-items: center;
    display: flex;
    flex-direction: column;
    margin: 10px 0 2px;
}
.ao-tm-pod-num {
    font-family: var(--ao-mono);
    font-size: clamp(24px, 20cqi, 48px);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.05em;
    line-height: 1;
}
.ao-tm-pod.is-p1 .ao-tm-pod-num {
    text-shadow: 0 0 28px hsl(var(--ao-tm-h) 80% 60% / 0.4);
}
.ao-tm-pod-unit {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.1em;
    margin-top: 7px;
    text-transform: uppercase;
}
.ao-tm-pod-meta {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: center;
    min-height: 20px;
}
.ao-tm-pod-spark {
    align-self: stretch;
    color: hsl(var(--ao-tm-h) 78% 68%);
    margin-top: 6px;
}
.ao-tm-pod .ao-tm-area {
    margin-top: 4px;
}

/* The list: one card, hairline-separated rows. */
.ao-tm-list {
    padding: 4px;
}
.ao-tm-rows {
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-tm-rowwrap {
    position: relative;
}
.ao-tm-rowwrap + .ao-tm-rowwrap::before {
    border-top: 1px solid var(--ao-border-faint);
    content: '';
    left: 14px;
    position: absolute;
    right: 14px;
    top: 0;
}
.ao-tm-row {
    align-items: center;
    border-radius: 12px;
    color: var(--ao-fg);
    column-gap: var(--ao-s-4);
    display: grid;
    grid-template-columns: 40px minmax(150px, 1.25fr) minmax(140px, 1.3fr) minmax(0, 2.6fr) 104px 52px 16px;
    padding: 12px 14px;
    position: relative;
    text-decoration: none;
    transition: background var(--ao-fast) var(--ao-ease);
}
.ao-tm-row:hover {
    background: var(--ao-hover);
}
.ao-tm-row:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: -2px;
}
/* A hue marker on the left edge: always on the podium three, on hover for
 * everyone else. */
.ao-tm-row::before {
    background: hsl(var(--ao-tm-h) 72% 64%);
    border-radius: 3px;
    bottom: 12px;
    content: '';
    left: 0;
    opacity: 0;
    position: absolute;
    top: 12px;
    transition: opacity var(--ao-fast) var(--ao-ease);
    width: 3px;
}
.ao-tm-row:hover::before,
.ao-tm-rowwrap.is-top .ao-tm-row::before {
    opacity: 1;
}
.ao-tm-rowwrap.is-top1 .ao-tm-row {
    background: linear-gradient(90deg, hsl(var(--ao-tm-h) 60% 50% / 0.12), transparent 42%);
}
.ao-tm-rowwrap.is-top1 .ao-tm-row:hover {
    background: linear-gradient(90deg, hsl(var(--ao-tm-h) 60% 50% / 0.18), var(--ao-hover) 42%);
}
.ao-tm-r-rank {
    align-items: center;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.ao-tm-r-num {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: 22px;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    line-height: 1;
}
.is-top1 .ao-tm-r-num {
    color: var(--ao-tm-gold);
}
.is-top2 .ao-tm-r-num {
    color: var(--ao-tm-silver);
}
.is-top3 .ao-tm-r-num {
    color: var(--ao-tm-bronze);
}
.ao-tm-r-who {
    align-items: center;
    display: flex;
    gap: 12px;
    min-width: 0;
}
.ao-tm-r-av {
    display: inline-flex;
    flex: none;
}
.ao-tm-r-id {
    min-width: 0;
}
.ao-tm-r-name {
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tm-r-sub {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 3px;
    min-width: 0;
}
.ao-tm-r-sub .ao-tm-login {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tm-r-pri {
    display: flex;
    flex-direction: column;
    gap: 7px;
    min-width: 0;
}
.ao-tm-r-val {
    align-items: baseline;
    display: flex;
    gap: 6px;
    min-width: 0;
}
.ao-tm-r-valnum {
    font-family: var(--ao-mono);
    font-size: 18px;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.02em;
    white-space: nowrap;
}
.ao-tm-r-valnum.is-unmeasured {
    color: var(--ao-fg-mute);
    font-weight: 400;
}
.ao-tm-r-valunit {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    overflow: hidden;
    text-overflow: ellipsis;
    text-transform: uppercase;
    white-space: nowrap;
}
.ao-tm-r-track {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    height: 6px;
    position: relative;
}
/* Unmeasured is hatched, never an empty bar: an empty track and a "we could
 * not read this" track must not look the same. */
.ao-tm-r-track.is-unmeasured {
    background: repeating-linear-gradient(45deg, var(--ao-tint-2) 0 3px, transparent 3px 6px);
}
.ao-tm-r-fill {
    background: linear-gradient(90deg, hsl(var(--ao-tm-h) 62% 42%), hsl(var(--ao-tm-h2) 82% 66%));
    border-radius: inherit;
    box-shadow: 0 0 12px hsl(var(--ao-tm-h) 80% 60% / 0.45);
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-tm-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
.ao-tm-r-sec {
    display: grid;
    gap: 8px;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    min-width: 0;
}
.ao-tm-r-m {
    align-items: center;
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    font-variant-numeric: tabular-nums;
    gap: 5px;
    min-width: 0;
    white-space: nowrap;
}
.ao-tm-r-m > span {
    overflow: hidden;
    text-overflow: ellipsis;
}
.ao-tm-r-m .ao-ico {
    color: var(--ao-fg-mute);
}
.ao-tm-r-m.is-zero,
.ao-tm-r-m.is-unmeasured {
    color: var(--ao-fg-mute);
}
.ao-tm-r-m.is-zero .ao-ico,
.ao-tm-r-m.is-unmeasured .ao-ico {
    opacity: 0.55;
}
.ao-tm-r-spark {
    color: hsl(var(--ao-tm-h) 78% 68%);
    min-width: 0;
}
.ao-tm-r-streak {
    display: flex;
    justify-content: flex-end;
}
.ao-tm-r-go {
    color: var(--ao-fg-mute);
    display: grid;
    place-items: center;
    transition:
        transform var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease);
}
.ao-tm-row:hover .ao-tm-r-go {
    color: var(--ao-fg);
    transform: translateX(2px);
}

/* ── category leaders ───────────────────────────────────────────────────── */
.ao-tm-leader-grid {
    display: grid;
    gap: var(--ao-s-3);
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
@container aotm (min-width: 600px) {
    .ao-tm-leader-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}
@container aotm (min-width: 1060px) {
    .ao-tm-leader-grid {
        grid-template-columns: repeat(6, minmax(0, 1fr));
    }
}
.ao-tm-leader {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 14px;
}
.ao-tm-leader-top {
    align-items: center;
    display: flex;
    gap: 10px;
    min-width: 0;
}
.ao-tm-leader-title {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.1em;
    min-width: 0;
    text-transform: uppercase;
}
.ao-tm-leader-who {
    align-items: center;
    display: flex;
    gap: 8px;
    min-width: 0;
}
.ao-tm-leader-name {
    font-size: var(--ao-fs-body);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tm-leader-val {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: 2px 6px;
    margin-top: auto;
}
.ao-tm-leader-num {
    font-family: var(--ao-mono);
    font-size: 24px;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.03em;
    line-height: 1.1;
}
.ao-tm-leader-unit {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}

/* ── team pulse ─────────────────────────────────────────────────────────── */
.ao-tm-pulse {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 16px 18px 16px;
}
.ao-tm-pulse-chart {
    display: grid;
    grid-template-columns: 36px minmax(0, 1fr);
    grid-template-rows: 190px 24px;
    position: relative;
}
.ao-tm-pulse-y {
    grid-column: 1;
    grid-row: 1;
    position: relative;
}
.ao-tm-pulse-tick {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    position: absolute;
    right: 8px;
    transform: translateY(50%);
}
.ao-tm-pulse-plot {
    align-items: flex-end;
    border-bottom: 1px solid var(--ao-border);
    display: flex;
    grid-column: 2;
    grid-row: 1;
    position: relative;
}
.ao-tm-pulse-grid {
    border-top: 1px solid var(--ao-border-faint);
    height: 0;
    left: 0;
    pointer-events: none;
    position: absolute;
    right: 0;
}
/* The whole column is the hit target, not the painted bar. */
.ao-tm-pulse-slot {
    align-items: flex-end;
    border-radius: 6px 6px 0 0;
    display: flex;
    flex: 1 1 0;
    height: 100%;
    justify-content: center;
    min-width: 0;
    position: relative;
}
.ao-tm-pulse-slot.is-hot {
    background: var(--ao-tint);
}
.ao-tm-pulse-stack {
    display: flex;
    flex-direction: column;
    gap: 2px;
    justify-content: flex-end;
    max-width: 24px;
    min-width: 2px;
    transform-origin: bottom center;
    width: 68%;
}
.ao-tm-pulse-seg {
    background: hsl(var(--ao-tm-h) 62% 58%);
    flex: 1 1 0;
    min-height: 2px;
    transition:
        opacity var(--ao-fast) var(--ao-ease),
        filter var(--ao-fast) var(--ao-ease);
}
.ao-tm-pulse-seg:first-child {
    border-radius: 4px 4px 0 0;
}
.ao-tm-pulse-slot.is-hot .ao-tm-pulse-seg {
    filter: brightness(1.18);
}
.ao-tm-pulse-chart.is-focus .ao-tm-pulse-seg:not(.is-hot) {
    opacity: 0.18;
}
.ao-tm-pulse-x {
    grid-column: 2;
    grid-row: 2;
    position: relative;
}
.ao-tm-pulse-xl {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    position: absolute;
    top: 7px;
    transform: translateX(-50%);
    white-space: nowrap;
}
.ao-tm-pulse-xl.is-first {
    left: 0 !important;
    transform: none;
}
.ao-tm-pulse-xl.is-last {
    left: auto !important;
    right: 0;
    transform: none;
}
.ao-tm-tip {
    background: var(--ao-surface-2);
    border: 1px solid var(--ao-border);
    border-radius: 12px;
    box-shadow: var(--ao-elev-3);
    max-width: 240px;
    min-width: 150px;
    padding: 10px 12px;
    pointer-events: none;
    position: absolute;
    top: 4px;
    transform: translateX(14px);
    z-index: 5;
}
.ao-tm-tip.is-left {
    transform: translateX(calc(-100% - 14px));
}
.ao-tm-tip-h {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-tm-tip-total {
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-title);
    font-weight: 600;
    margin: 2px 0 6px;
}
.ao-tm-tip-row {
    align-items: center;
    display: grid;
    font-size: var(--ao-fs-meta);
    gap: 8px;
    grid-template-columns: 12px minmax(2ch, auto) minmax(0, 1fr);
    line-height: 1.7;
}
/* Line keys, not boxes: at tooltip density a filled square is data ink
 * doing a label's job. */
.ao-tm-tip-key {
    background: hsl(var(--ao-tm-h) 62% 58%);
    border-radius: 2px;
    height: 2px;
    width: 12px;
}
.ao-tm-tip-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-weight: 600;
    text-align: right;
}
.ao-tm-tip-n {
    color: var(--ao-fg-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tm-tip-more {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    margin-top: 2px;
}
.ao-tm-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 8px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-tm-legend-item {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 7px;
    max-width: 100%;
    padding: 4px 10px 4px 8px;
    transition:
        border-color var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease);
}
.ao-tm-legend-item:hover,
.ao-tm-legend-item:focus-visible {
    border-color: var(--ao-border);
    color: var(--ao-fg);
    outline: none;
}
.ao-tm-legend-item:focus-visible {
    box-shadow: 0 0 0 2px var(--ao-focus);
}
.ao-tm-legend-sw {
    background: hsl(var(--ao-tm-h) 62% 58%);
    border-radius: 3px;
    flex: none;
    height: 10px;
    width: 10px;
}
.ao-tm-legend-n {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tm-legend-v {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
}

/* ── warming hero ───────────────────────────────────────────────────────── */
.ao-tm-warm {
    align-items: center;
    background:
        radial-gradient(80% 160% at 0% 0%, var(--ao-info-bg), transparent 62%),
        linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-color: var(--ao-info-bd);
    display: grid;
    gap: 16px;
    grid-template-columns: auto minmax(0, 1fr) auto;
    padding: 18px 20px;
}
.ao-tm-warm-ico {
    background: var(--ao-info-bg);
    border-radius: 12px;
    color: var(--ao-info-fg);
    display: grid;
    height: 44px;
    place-items: center;
    position: relative;
    width: 44px;
}
.ao-tm-warm-ico::after {
    animation: ao-tm-ping 2.4s var(--ao-ease) infinite;
    border: 1px solid currentColor;
    border-radius: inherit;
    content: '';
    inset: 0;
    position: absolute;
}
.ao-tm-warm-h {
    font-size: var(--ao-fs-title);
    font-weight: 600;
}
.ao-tm-warm-p {
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.55;
    margin: 4px 0 0;
    max-width: 80ch;
}
.ao-tm-warm-note {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    margin-top: 6px;
    overflow-wrap: anywhere;
}

/* ── PROFILE (#/team/member/<key>) — spec §6.4 ───────────────────────────
 * One teammate, every metric. Same card, type and motion language as the
 * board above; the teammate's hue (--ao-tm-h, set on .ao-tm-profile) is the
 * page's one vivid colour, and the KPI-family accents tint the metric cards.
 *
 * Every hue ramp below mixes toward --ao-bg IN OKLAB, never by stepping HSL
 * lightness: HSL L is not perceptual, so an HSL ramp that reads fine for a
 * teal teammate collapses into the surface for a violet one. The work-mix
 * steps (base hsl(h 88% 78%) at 100 / 80 / 63 / 48%) were run through the
 * dataviz ordinal validator across the whole 35..325 hue band on
 * --ao-surface: monotone, every adjacent ΔL >= 0.06, the dimmest step
 * >= 2:1 against the surface. */

/* ── control bar: back link + range ─────────────────────────────────────── */
.ao-tm-bar-lead {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--ao-s-3);
    max-width: 100%;
    min-width: 0;
}
.ao-tm-back {
    align-items: center;
    background: var(--ao-surface);
    border: 1px solid var(--ao-border-soft);
    border-radius: var(--ao-r-ctl);
    color: var(--ao-fg-dim);
    display: inline-flex;
    flex: none;
    font-size: var(--ao-fs-meta);
    font-weight: 500;
    gap: 6px;
    padding: 7px 14px 7px 11px;
    text-decoration: none;
    transition:
        background var(--ao-fast) var(--ao-ease),
        border-color var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease);
}
.ao-tm-back:hover {
    background: var(--ao-hover);
    border-color: var(--ao-border);
    color: var(--ao-fg);
}
.ao-tm-back:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-tm-back-arrow {
    display: inline-block;
    transition: transform var(--ao-fast) var(--ao-ease);
}
.ao-tm-back:hover .ao-tm-back-arrow {
    transform: translateX(-2px);
}

/* ── frame + skeleton ───────────────────────────────────────────────────── */
.ao-tm-profile,
.ao-tm-skel.is-profile {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-6);
}
.ao-tm-hero.is-skel {
    background: linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-color: var(--ao-border-soft);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-1);
    min-height: 180px;
}
.ao-tm-hero.is-skel .ao-tm-hero-id {
    align-self: stretch;
    flex: 1;
}
.ao-tm-skel-av.is-hero {
    height: 96px;
    width: 96px;
}
.ao-tm-skel-name.is-hero {
    height: 26px;
    width: 70%;
}
.ao-tm-skel-name.is-short {
    width: 30%;
}
.ao-tm-skel-num.is-hero {
    border-radius: 14px;
    height: 118px;
    width: 100%;
}
.ao-tm-skel-block {
    min-height: 300px;
}
.ao-tm-psec {
    display: flex;
    flex-direction: column;
    gap: var(--ao-s-4);
    min-width: 0;
}
.ao-tm-mono {
    font-family: var(--ao-mono);
}

/* ── hero ───────────────────────────────────────────────────────────────── */
.ao-tm-hero {
    align-items: center;
    background:
        radial-gradient(80% 150% at 0% 0%, hsl(var(--ao-tm-h) 62% 46% / 0.26), transparent 58%),
        radial-gradient(60% 120% at 100% 110%, hsl(var(--ao-tm-h2) 60% 44% / 0.14), transparent 62%),
        linear-gradient(180deg, var(--ao-surface-2), var(--ao-surface));
    border-color: hsl(var(--ao-tm-h) 40% 55% / 0.32);
    box-shadow:
        inset 0 1px 0 var(--ao-tint-line),
        var(--ao-elev-2),
        0 34px 70px -40px hsl(var(--ao-tm-h) 70% 50% / 0.6);
    display: grid;
    gap: var(--ao-s-6);
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
    padding: 28px;
}
/* Texture and the hue hairline live in their own clipped layer, so the card
 * itself needs no overflow:hidden (the avatar glow may spill past it). */
.ao-tm-hero-fx {
    border-radius: inherit;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    position: absolute;
}
.ao-tm-hero-fx::before {
    background-image: radial-gradient(circle, var(--ao-tint-strong) 1px, transparent 1.5px);
    background-size: 18px 18px;
    content: '';
    inset: 0;
    -webkit-mask-image: linear-gradient(100deg, transparent 35%, black 100%);
    mask-image: linear-gradient(100deg, transparent 35%, black 100%);
    opacity: 0.7;
    position: absolute;
}
.ao-tm-hero-fx::after {
    background: linear-gradient(
        90deg,
        transparent,
        hsl(var(--ao-tm-h) 85% 70% / 0.95) 28%,
        hsl(var(--ao-tm-h2) 80% 66% / 0.55) 72%,
        transparent
    );
    content: '';
    height: 1px;
    left: 0;
    position: absolute;
    right: 0;
    top: 0;
}
.ao-tm-hero > :not(.ao-tm-hero-fx) {
    position: relative;
    z-index: 1;
}
.ao-tm-hero-who {
    align-items: center;
    display: flex;
    gap: 24px;
    min-width: 0;
}
.ao-tm-hero-av {
    display: grid;
    flex: none;
    height: 124px;
    place-items: center;
    position: relative;
    width: 124px;
}
.ao-tm-hero-av .ao-tm-av {
    box-shadow: 0 0 44px -8px hsl(var(--ao-tm-h) 80% 55% / 0.6);
}
/* A dashed orbit with one satellite, turning the other way from the ring. */
.ao-tm-hero-orbit {
    animation: ao-tm-orbit 26s linear infinite;
    border: 1px dashed hsl(var(--ao-tm-h) 70% 66% / 0.42);
    border-radius: 50%;
    inset: 0;
    position: absolute;
}
.ao-tm-hero-orbit::before {
    background: hsl(var(--ao-tm-h) 88% 74%);
    border-radius: 50%;
    box-shadow: 0 0 10px hsl(var(--ao-tm-h) 85% 65%);
    content: '';
    height: 6px;
    left: 50%;
    margin-left: -3px;
    position: absolute;
    top: -3px;
    width: 6px;
}
@keyframes ao-tm-orbit {
    to {
        transform: rotate(-360deg);
    }
}
.ao-tm-hero-id {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}
.ao-tm-hero-name {
    font-size: 30px;
    font-weight: 600;
    letter-spacing: -0.025em;
    line-height: 1.1;
    margin: 0;
    overflow-wrap: anywhere;
}
.ao-tm-hero-handle,
.ao-tm-badges {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 8px;
    min-width: 0;
}
.ao-tm-gh {
    align-items: center;
    border: 1px solid var(--ao-border);
    border-radius: var(--ao-r-ctl);
    color: var(--ao-fg-dim);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    gap: 5px;
    padding: 2px 9px;
    text-decoration: none;
    transition:
        background var(--ao-fast) var(--ao-ease),
        color var(--ao-fast) var(--ao-ease);
}
.ao-tm-gh:hover {
    background: var(--ao-hover);
    color: var(--ao-fg);
}
.ao-tm-gh:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-tm-rankchip {
    align-items: center;
    border: 1px solid transparent;
    border-radius: var(--ao-r-tag);
    display: inline-flex;
    font-size: var(--ao-fs-meta);
    font-weight: 600;
    gap: 5px;
    padding: 3px 10px 3px 8px;
    white-space: nowrap;
}
.ao-tm-rankchip.is-m1 {
    background: color-mix(in srgb, var(--ao-tm-gold) 15%, transparent);
    border-color: color-mix(in srgb, var(--ao-tm-gold) 42%, transparent);
    box-shadow: 0 0 16px -6px var(--ao-tm-gold);
    color: var(--ao-tm-gold);
}
.ao-tm-rankchip.is-m2 {
    background: color-mix(in srgb, var(--ao-tm-silver) 12%, transparent);
    border-color: color-mix(in srgb, var(--ao-tm-silver) 36%, transparent);
    color: var(--ao-tm-silver);
}
.ao-tm-rankchip.is-m3 {
    background: color-mix(in srgb, var(--ao-tm-bronze) 13%, transparent);
    border-color: color-mix(in srgb, var(--ao-tm-bronze) 38%, transparent);
    color: var(--ao-tm-bronze);
}
.ao-tm-hero-streak {
    font-size: var(--ao-fs-meta);
    padding: 3px 10px 3px 8px;
}
.ao-tm-hero-streak.is-hot {
    box-shadow: 0 0 16px -5px var(--ao-tm-flame);
}
.ao-tm-hero-meta {
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 6px 16px;
}
.ao-tm-hero-fact {
    align-items: center;
    display: inline-flex;
    gap: 6px;
    min-width: 0;
}
.ao-tm-hero-fact.is-key {
    cursor: help;
}
.ao-tm-hero-stats {
    display: grid;
    gap: 12px;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    min-width: 0;
}
.ao-tm-hstat {
    background: color-mix(in srgb, var(--ao-bg) 60%, transparent);
    border: 1px solid var(--ao-border-soft);
    border-radius: 8px;
    box-shadow: inset 0 1px 0 var(--ao-tint);
    container-type: inline-size;
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    overflow: hidden;
    padding: 16px 16px 14px;
    position: relative;
}
/* The KPI family's accent as a short top rule — colour on the mark, never
 * on the number. */
.ao-tm-hstat::before {
    background: var(--ao-tm-accent, var(--ao-fg-mute));
    border-radius: 0 0 2px 2px;
    box-shadow: 0 0 12px var(--ao-tm-accent, transparent);
    content: '';
    height: 2px;
    left: 16px;
    position: absolute;
    top: 0;
    width: 36px;
}
.ao-tm-hstat-label {
    align-items: center;
    color: var(--ao-fg-dim);
    display: flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 6px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ao-tm-hstat-label .ao-ico {
    color: var(--ao-tm-accent, var(--ao-fg-dim));
}
.ao-tm-hstat-valrow {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: 0 6px;
    min-width: 0;
}
/* Spec: hero numbers clamp(44px, 5vw, 64px). Sized by the stat's own width
 * (cqi) instead, with the same 64px ceiling: three 5vw numbers side by side
 * overflow their tiles at every width between phone and 1440. */
.ao-tm-hstat-num {
    font-family: var(--ao-mono);
    font-size: clamp(28px, 22cqi, 64px);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.05em;
    line-height: 1;
    white-space: nowrap;
}
.ao-tm-hstat-num.is-unmeasured {
    color: var(--ao-fg-mute);
    font-weight: 400;
}
.ao-tm-hstat-unit {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ao-tm-hstat-foot {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 8px;
    min-height: 20px;
}
.ao-tm-hstat-rank {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    margin-left: auto;
}

/* ── KPI grid: 4 across, 2, or 1 (16 cards: no orphan at any step) ─────── */
.ao-tm-kpis.is-profile {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
@container aotm (min-width: 760px) {
    .ao-tm-kpis.is-profile {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}
@container aotm (max-width: 299.98px) {
    .ao-tm-kpis.is-profile {
        grid-template-columns: minmax(0, 1fr);
    }
}
/* The team-share meter sits at the card's foot, aligned across a row
 * whether or not the card above it has a sparkline. */
.ao-tm-share {
    display: flex;
    flex-direction: column;
    gap: 5px;
    margin-top: auto;
    padding-top: 10px;
}
.ao-tm-kpi-spark + .ao-tm-share {
    margin-top: 0;
}
.ao-tm-share-row {
    align-items: baseline;
    color: var(--ao-fg-mute);
    display: flex;
    font-size: var(--ao-fs-label);
    gap: 8px;
    justify-content: space-between;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.ao-tm-share-v {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-weight: 600;
    letter-spacing: 0;
}
.ao-tm-share-track {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    height: 4px;
    overflow: hidden;
    position: relative;
}
.ao-tm-share-track.is-unmeasured,
.ao-tm-radar-rt.is-unmeasured {
    background: repeating-linear-gradient(45deg, var(--ao-tint-2) 0 3px, transparent 3px 6px);
}
.ao-tm-share-fill {
    background: var(--ao-tm-accent, var(--ao-fg-dim));
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-tm-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
.ao-tm-share-cap {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    overflow-wrap: anywhere;
}

/* ── two-column rows + section cards ────────────────────────────────────── */
.ao-tm-prow {
    display: grid;
    gap: var(--ao-s-4);
    grid-template-columns: minmax(0, 1fr);
}
@container aotm (min-width: 980px) {
    .ao-tm-prow {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .ao-tm-prow.is-wide {
        grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
    }
}
.ao-tm-pcard {
    display: flex;
    flex-direction: column;
    gap: 14px;
    min-width: 0;
    padding: 18px 20px 20px;
}
.ao-tm-pcard .ao-tm-h {
    font-size: 16px;
}
.ao-tm-pcard-head {
    align-items: flex-start;
    display: flex;
    flex-wrap: wrap;
    gap: 10px 16px;
    justify-content: space-between;
}
.ao-tm-pcard-head > .ao-tm-sec-head {
    min-width: 0;
}
.ao-tm-note {
    background: var(--ao-tint);
    border: 1px dashed var(--ao-border);
    border-radius: 12px;
    color: var(--ao-fg-dim);
    font-size: var(--ao-fs-body);
    line-height: 1.5;
    overflow-wrap: anywhere;
    padding: 14px 16px;
}
.ao-tm-note.is-inline {
    font-size: var(--ao-fs-meta);
    padding: 8px 12px;
}
.ao-tm-subhead {
    align-items: center;
    border-top: 1px solid var(--ao-border-faint);
    color: var(--ao-fg-mute);
    display: flex;
    font-size: var(--ao-fs-label);
    font-weight: 600;
    gap: 7px;
    letter-spacing: 0.1em;
    margin-top: 4px;
    padding-top: 14px;
    text-transform: uppercase;
}

/* ── contribution heatmap ───────────────────────────────────────────────── */
.ao-tm-mini-seg {
    flex: none;
}
.ao-tm-mini-seg .ao-tm-seg-btn {
    font-family: var(--ao-font-sans);
    letter-spacing: 0.02em;
    min-height: 24px;
    padding: 5px 12px;
}
.ao-tm-hm-stats {
    align-items: baseline;
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 6px 18px;
    min-height: 18px;
}
.ao-tm-hm-stat b {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
    margin-right: 5px;
}
.ao-tm-hm-stat.is-warn {
    border: 1px dashed var(--ao-border);
    border-radius: var(--ao-r-tag);
    padding: 1px 8px;
}
/* Cell size follows the card: 53 (or 54) columns share the width, between
 * 8px and 15px a side. Below 8px the grid scrolls sideways INSIDE the card
 * (opened on today, see _tmHeatInto) — the page itself never scrolls. */
.ao-tm-hm {
    column-gap: 8px;
    container-type: inline-size;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
}
.ao-tm-hm-days,
.ao-tm-hm-scroll {
    --ao-tm-cell: clamp(
        8px,
        calc((100cqi - 38px - (var(--ao-tm-hm-cols, 53) - 1) * 3px) / var(--ao-tm-hm-cols, 53)),
        15px
    );
}
.ao-tm-hm-days {
    color: var(--ao-fg-mute);
    display: grid;
    font-family: var(--ao-mono);
    font-size: 9.5px;
    grid-template-rows: repeat(7, var(--ao-tm-cell));
    line-height: 1;
    padding-top: 20px;
    row-gap: 3px;
}
.ao-tm-hm-days > span {
    align-self: center;
}
.ao-tm-hm-scroll {
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 4px;
    scrollbar-width: thin;
}
.ao-tm-hm-months {
    color: var(--ao-fg-mute);
    column-gap: 3px;
    display: grid;
    font-family: var(--ao-mono);
    font-size: 9.5px;
    grid-template-columns: repeat(var(--ao-tm-hm-cols, 53), var(--ao-tm-cell));
    height: 16px;
    margin-bottom: 4px;
    width: max-content;
}
.ao-tm-hm-mon {
    white-space: nowrap;
}
.ao-tm-hm-grid {
    display: grid;
    gap: 3px;
    grid-auto-columns: var(--ao-tm-cell);
    grid-auto-flow: column;
    grid-template-rows: repeat(7, var(--ao-tm-cell));
    width: max-content;
}
.ao-tm-hm-c {
    background: var(--ao-tint-2);
    border-radius: 3px;
    display: block;
    height: var(--ao-tm-cell);
    width: var(--ao-tm-cell);
}
.ao-tm-hm-c.is-l0 {
    background: var(--ao-tint-2);
    box-shadow: inset 0 0 0 1px var(--ao-tint);
}
.ao-tm-hm-c.is-l1 {
    background: color-mix(in oklab, hsl(var(--ao-tm-h) 80% 70%) 34%, var(--ao-bg));
}
.ao-tm-hm-c.is-l2 {
    background: color-mix(in oklab, hsl(var(--ao-tm-h) 80% 70%) 56%, var(--ao-bg));
}
.ao-tm-hm-c.is-l3 {
    background: color-mix(in oklab, hsl(var(--ao-tm-h) 84% 72%) 80%, var(--ao-bg));
}
.ao-tm-hm-c.is-l4 {
    background: hsl(var(--ao-tm-h) 88% 76%);
    box-shadow: 0 0 8px hsl(var(--ao-tm-h) 85% 62% / 0.5);
}
/* Not measured is hatched, never level 0: "we could not read this day" and
 * "nothing happened this day" must not look alike. */
.ao-tm-hm-c.is-null {
    background: repeating-linear-gradient(45deg, var(--ao-tint-2) 0 2px, transparent 2px 4px);
}
.ao-tm-hm-c.is-today {
    outline: 1px solid var(--ao-fg-dim);
    outline-offset: 1px;
}
.ao-tm-hm-grid .ao-tm-hm-c:hover {
    outline: 1px solid var(--ao-fg);
    outline-offset: 1px;
}
.ao-tm-heat.is-unmeasured .ao-tm-hm-grid {
    opacity: 0.7;
}
/* Weekly totals under the week columns (same column track as the grid). */
.ao-tm-hm-weeks {
    align-items: end;
    column-gap: 3px;
    display: grid;
    grid-template-columns: repeat(var(--ao-tm-hm-cols, 53), var(--ao-tm-cell));
    height: 42px;
    margin-top: 8px;
    width: max-content;
}
.ao-tm-hm-wk {
    background: color-mix(in oklab, hsl(var(--ao-tm-h) 84% 72%) 72%, var(--ao-bg));
    border-radius: 2px 2px 0 0;
    height: 100%;
    min-height: 1px;
    transform: scaleY(var(--ao-tm-fill, 0));
    transform-origin: bottom center;
}
.ao-tm-hm-wk:hover {
    background: hsl(var(--ao-tm-h) 88% 78%);
}
.ao-tm-hm-wk.is-null {
    background: repeating-linear-gradient(45deg, var(--ao-tint-2) 0 2px, transparent 2px 4px);
    transform: none;
}
.ao-tm-hm-insights {
    display: grid;
    gap: 8px;
    grid-template-columns: repeat(4, minmax(0, 1fr));
}
.ao-tm-hm-insights:empty {
    display: none;
}
.ao-tm-hm-insights.is-mix {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    margin-top: auto;
}
.ao-tm-hm-ins {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: 12px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    padding: 9px 12px 10px;
}
.ao-tm-hm-ins-l {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ao-tm-hm-ins-v {
    font-family: var(--ao-mono);
    font-size: 20px;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.03em;
    line-height: 1.2;
}
.ao-tm-hm-ins-s {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tm-hm-foot {
    margin-top: auto;
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px 16px;
    justify-content: space-between;
}
.ao-tm-hm-readout {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
    min-height: 16px;
    min-width: 0;
    overflow-wrap: anywhere;
}
.ao-tm-hm-legend {
    align-items: center;
    color: var(--ao-fg-mute);
    display: inline-flex;
    font-size: var(--ao-fs-label);
    gap: 3px;
}
.ao-tm-hm-legend > span:first-child {
    margin-right: 4px;
}
.ao-tm-hm-legend > span:last-child {
    margin-left: 4px;
}
.ao-tm-hm-legend .ao-tm-hm-c {
    height: 11px;
    width: 11px;
}

/* ── skill radar ────────────────────────────────────────────────────────── */
.ao-tm-radar {
    display: grid;
    place-items: center;
}
.ao-tm-radar-svg {
    display: block;
    height: auto;
    max-width: 440px;
    overflow: visible;
    width: 100%;
}
.ao-tm-radar-ring {
    fill: none;
    stroke: var(--ao-border-soft);
    stroke-width: 1;
}
.ao-tm-radar-ring.is-outer {
    fill: var(--ao-tint);
    stroke: var(--ao-border);
}
.ao-tm-radar-spoke {
    stroke: var(--ao-border-soft);
    stroke-width: 1;
}
.ao-tm-radar-spoke.is-null {
    stroke: var(--ao-fg-mute);
    stroke-dasharray: 2 4;
}
.ao-tm-radar-avg {
    fill: var(--ao-tint);
    stroke: var(--ao-fg-mute);
    stroke-dasharray: 4 4;
    stroke-linejoin: round;
    stroke-width: 1.5;
}
.ao-tm-radar-me {
    transform-box: view-box;
    transform-origin: 190px 146px;
}
.ao-tm-radar-poly {
    fill: hsl(var(--ao-tm-h) 72% 60% / 0.24);
    filter: drop-shadow(0 0 10px hsl(var(--ao-tm-h) 80% 60% / 0.45));
    stroke: hsl(var(--ao-tm-h) 84% 70%);
    stroke-linejoin: round;
    stroke-width: 2;
}
.ao-tm-radar-dot {
    fill: hsl(var(--ao-tm-h) 88% 76%);
    stroke: var(--ao-surface);
    stroke-width: 2;
}
.ao-tm-radar-label {
    font-family: var(--ao-font-sans);
    font-size: 11px;
}
.ao-tm-radar-lab {
    fill: var(--ao-fg-dim);
    font-weight: 600;
}
.ao-tm-radar-pct {
    fill: var(--ao-fg);
    font-family: var(--ao-mono);
}
.ao-tm-radar-label.is-null .ao-tm-radar-lab,
.ao-tm-radar-label.is-null .ao-tm-radar-pct {
    fill: var(--ao-fg-mute);
}
.ao-tm-radar-legend {
    color: var(--ao-fg-dim);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 6px 16px;
}
.ao-tm-radar-key {
    align-items: center;
    display: inline-flex;
    gap: 7px;
    min-width: 0;
}
.ao-tm-radar-sw {
    border-top: 2px solid hsl(var(--ao-tm-h) 84% 70%);
    flex: none;
    width: 16px;
}
.ao-tm-radar-key.is-avg .ao-tm-radar-sw {
    border-top: 2px dashed var(--ao-fg-mute);
}
.ao-tm-radar-list {
    display: grid;
    gap: 10px 18px;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-tm-radar-row {
    align-items: baseline;
    display: grid;
    font-size: var(--ao-fs-meta);
    gap: 4px 8px;
    grid-template-columns: minmax(0, 1fr) auto;
    min-width: 0;
}
.ao-tm-radar-rl {
    color: var(--ao-fg-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tm-radar-rv {
    font-family: var(--ao-mono);
    white-space: nowrap;
}
.ao-tm-radar-row.is-null .ao-tm-radar-rv {
    color: var(--ao-fg-mute);
}
.ao-tm-radar-rt {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-tag);
    grid-column: 1 / -1;
    height: 3px;
    overflow: hidden;
    position: relative;
}
.ao-tm-radar-rf {
    background: hsl(var(--ao-tm-h) 80% 68%);
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-tm-fill, 0));
    transform-origin: left center;
}

/* ── work mix ───────────────────────────────────────────────────────────── */
.ao-tm-stack {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    display: flex;
    gap: 2px;
    height: 18px;
    overflow: hidden;
    transform-origin: left center;
}
.ao-tm-stack-seg {
    flex: 1 1 0;
    min-width: 3px;
    transition:
        opacity var(--ao-fast) var(--ao-ease),
        filter var(--ao-fast) var(--ao-ease);
}
.ao-tm-stack-seg.is-s0,
.ao-tm-mix-sw.is-s0 {
    background: hsl(var(--ao-tm-h) 88% 78%);
}
.ao-tm-stack-seg.is-s1,
.ao-tm-mix-sw.is-s1 {
    background: color-mix(in oklab, hsl(var(--ao-tm-h) 88% 78%) 80%, var(--ao-bg));
}
.ao-tm-stack-seg.is-s2,
.ao-tm-mix-sw.is-s2 {
    background: color-mix(in oklab, hsl(var(--ao-tm-h) 88% 78%) 63%, var(--ao-bg));
}
.ao-tm-stack-seg.is-s3,
.ao-tm-mix-sw.is-s3,
.ao-tm-stack-seg.is-s4,
.ao-tm-mix-sw.is-s4,
.ao-tm-stack-seg.is-s5,
.ao-tm-mix-sw.is-s5 {
    background: color-mix(in oklab, hsl(var(--ao-tm-h) 88% 78%) 48%, var(--ao-bg));
}
.ao-tm-stack-seg.is-other,
.ao-tm-mix-sw.is-other {
    background: var(--ao-fg-mute);
}
.ao-tm-mix.is-focus .ao-tm-stack-seg:not(.is-hot) {
    opacity: 0.25;
}
.ao-tm-mix.is-focus .ao-tm-mixrow:not(.is-hot) {
    opacity: 0.5;
}
.ao-tm-mix-total {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
    margin-top: -4px;
}
.ao-tm-mix-total b {
    color: var(--ao-fg);
    font-family: var(--ao-mono);
    font-weight: 600;
}
.ao-tm-mixlist {
    display: flex;
    flex-direction: column;
    gap: 2px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-tm-mixrow {
    align-items: center;
    border-radius: 9px;
    display: grid;
    font-size: var(--ao-fs-body);
    gap: 10px;
    grid-template-columns: 10px minmax(0, 1fr) auto auto 42px;
    padding: 8px 10px;
    transition:
        background var(--ao-fast) var(--ao-ease),
        opacity var(--ao-fast) var(--ao-ease);
}
.ao-tm-mixrow:hover,
.ao-tm-mixrow.is-hot {
    background: var(--ao-hover);
}
.ao-tm-mixrow:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: -2px;
}
.ao-tm-mix-sw {
    border-radius: 3px;
    height: 10px;
    width: 10px;
}
.ao-tm-mix-l {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tm-mix-n {
    color: var(--ao-fg-dim);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-tm-mix-c {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-tm-mix-p {
    font-family: var(--ao-mono);
    font-weight: 600;
    text-align: right;
}

/* ── ops breakdown ──────────────────────────────────────────────────────── */
.ao-tm-hbars {
    display: flex;
    flex-direction: column;
    gap: 11px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-tm-hbar-top {
    align-items: baseline;
    display: flex;
    font-size: var(--ao-fs-body);
    gap: 10px;
    justify-content: space-between;
}
.ao-tm-hbar-l {
    align-items: center;
    color: var(--ao-fg-dim);
    display: inline-flex;
    gap: 6px;
    min-width: 0;
}
.ao-tm-hbar-v {
    font-family: var(--ao-mono);
    font-weight: 600;
}
.ao-tm-hbar-track {
    background: var(--ao-tint-2);
    border-radius: var(--ao-r-bar);
    height: 6px;
    margin-top: 6px;
    overflow: hidden;
    position: relative;
}
.ao-tm-hbar-fill {
    background: linear-gradient(90deg, color-mix(in oklab, var(--ao-tm-k-ops) 45%, var(--ao-bg)), var(--ao-tm-k-ops));
    border-radius: inherit;
    inset: 0;
    position: absolute;
    transform: scaleX(var(--ao-tm-fill, 0));
    transform-origin: left center;
    transition: transform 620ms var(--ao-ease);
}
.ao-tm-deploys {
    display: flex;
    flex-direction: column;
    gap: 6px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-tm-deploy {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: 10px;
    display: grid;
    font-size: var(--ao-fs-body);
    gap: 12px;
    grid-template-columns: minmax(0, 1fr) auto auto;
    padding: 7px 10px;
}
.ao-tm-deploy-n {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ao-tm-deploy-r {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-meta);
}
.ao-tm-deploy-ok {
    background: var(--ao-ok-bg);
    border: 1px solid var(--ao-ok-bd);
    border-radius: var(--ao-r-tag);
    color: var(--ao-ok-fg);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    padding: 2px 7px;
    white-space: nowrap;
}
.ao-tm-deploy-ok.has-fail {
    background: var(--ao-warn-bg);
    border-color: var(--ao-warn-bd);
    color: var(--ao-warn-fg);
}
.ao-tm-support {
    display: grid;
    gap: 10px;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.ao-tm-support-stat {
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: 12px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    padding: 10px 12px;
}
.ao-tm-support-stat b {
    font-family: var(--ao-mono);
    font-size: 22px;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.03em;
}
.ao-tm-support-stat span {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-meta);
}
.ao-tm-support-stat.is-unmeasured b {
    color: var(--ao-fg-mute);
    font-weight: 400;
}

/* ── rhythm punchcard ───────────────────────────────────────────────────── */
.ao-tm-peak {
    align-items: center;
    background: hsl(var(--ao-tm-h) 60% 50% / 0.14);
    border: 1px solid hsl(var(--ao-tm-h) 60% 62% / 0.3);
    border-radius: var(--ao-r-tag);
    color: var(--ao-fg);
    display: inline-flex;
    flex: none;
    font-size: var(--ao-fs-meta);
    font-weight: 500;
    gap: 6px;
    padding: 4px 11px 4px 9px;
}
.ao-tm-peak .ao-ico {
    color: hsl(var(--ao-tm-h) 84% 74%);
}
.ao-tm-punch-scroll {
    overflow-x: auto;
    padding-bottom: 2px;
    scrollbar-width: thin;
}
.ao-tm-punch {
    align-items: center;
    display: grid;
    grid-template-columns: 30px repeat(24, minmax(10px, 1fr)) 34px;
    min-width: 310px;
    row-gap: 3px;
}
.ao-tm-punch-day,
.ao-tm-punch-tot,
.ao-tm-punch-hour {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: 9.5px;
}
.ao-tm-punch-tot {
    text-align: right;
}
.ao-tm-punch-hour {
    padding-top: 4px;
    white-space: nowrap;
}
.ao-tm-punch-c {
    border-radius: 6px;
    display: grid;
    height: 26px;
    place-items: center;
    transition: background var(--ao-fast) var(--ao-ease);
}
.ao-tm-punch-c:hover {
    background: var(--ao-tint-2);
}
.ao-tm-punch-dot {
    aspect-ratio: 1;
    background: color-mix(in oklab, hsl(var(--ao-tm-h) 88% 76%) 90%, var(--ao-bg));
    border-radius: 50%;
    box-shadow: 0 0 10px hsl(var(--ao-tm-h) 85% 62% / 0.35);
    transform: scale(var(--ao-tm-s, 0));
    width: min(22px, 92%);
}
.ao-tm-punch-c.is-zero .ao-tm-punch-dot {
    background: var(--ao-tint-strong);
    box-shadow: none;
    transform: scale(0.14);
}
.ao-tm-punch-c.is-peak .ao-tm-punch-dot {
    background: hsl(var(--ao-tm-h) 90% 80%);
    box-shadow:
        0 0 0 2px var(--ao-surface),
        0 0 0 3px hsl(var(--ao-tm-h) 85% 72%),
        0 0 18px hsl(var(--ao-tm-h) 85% 62% / 0.6);
}

/* ── top PRs ────────────────────────────────────────────────────────────── */
.ao-tm-prlist {
    display: flex;
    flex-direction: column;
    gap: 8px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.ao-tm-pr {
    align-items: center;
    background: var(--ao-tint);
    border: 1px solid var(--ao-border-faint);
    border-radius: 12px;
    color: inherit;
    display: grid;
    gap: 12px;
    grid-template-columns: 24px minmax(0, 1fr) auto 14px;
    overflow: hidden;
    padding: 11px 14px 13px 12px;
    position: relative;
    text-decoration: none;
    transition:
        background var(--ao-fast) var(--ao-ease),
        border-color var(--ao-fast) var(--ao-ease);
}
div.ao-tm-pr {
    grid-template-columns: 24px minmax(0, 1fr) auto;
}
a.ao-tm-pr:hover {
    background: var(--ao-hover);
    border-color: var(--ao-border);
}
a.ao-tm-pr:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-tm-pr-rank {
    color: var(--ao-fg-mute);
    font-family: var(--ao-mono);
    font-size: var(--ao-fs-strong);
    font-weight: 600;
}
.ao-tm-prwrap:first-child .ao-tm-pr-rank {
    color: var(--ao-tm-gold);
}
.ao-tm-pr-main {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}
.ao-tm-pr-title {
    -webkit-box-orient: vertical;
    display: -webkit-box;
    font-size: var(--ao-fs-strong);
    font-weight: 500;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    line-height: 1.35;
    overflow: hidden;
    overflow-wrap: anywhere;
}
.ao-tm-pr-meta {
    align-items: center;
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 4px 10px;
}
.ao-tm-pr-lines {
    display: inline-flex;
    font-family: var(--ao-mono);
    gap: 6px;
}
.ao-tm-pr-val {
    align-items: flex-end;
    display: flex;
    flex-direction: column;
    line-height: 1.1;
}
.ao-tm-pr-val b {
    font-family: var(--ao-mono);
    font-size: 18px;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    letter-spacing: -0.02em;
}
.ao-tm-pr-val span {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ao-tm-pr-val.is-unmeasured b {
    color: var(--ao-fg-mute);
    font-weight: 400;
}
.ao-tm-pr-go {
    color: var(--ao-fg-mute);
    display: grid;
    place-items: center;
    transition: color var(--ao-fast) var(--ao-ease);
}
a.ao-tm-pr:hover .ao-tm-pr-go {
    color: var(--ao-fg);
}
.ao-tm-pr-bar {
    background: linear-gradient(90deg, hsl(var(--ao-tm-h) 70% 52%), hsl(var(--ao-tm-h2) 84% 68%));
    bottom: 0;
    height: 2px;
    left: 0;
    position: absolute;
    right: 0;
    transform: scaleX(var(--ao-tm-fill, 0));
    transform-origin: left center;
}

/* ── recent activity timeline ───────────────────────────────────────────── */
.ao-tm-tl {
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
}
/* The rail every node sits on. */
.ao-tm-tl::before {
    background: linear-gradient(180deg, var(--ao-border), var(--ao-border-faint) 85%, transparent);
    bottom: 6px;
    content: '';
    left: 13.5px;
    position: absolute;
    top: 6px;
    width: 1px;
}
.ao-tm-tl-day {
    color: var(--ao-fg-mute);
    font-size: var(--ao-fs-label);
    font-weight: 600;
    letter-spacing: 0.1em;
    padding: 12px 0 6px 40px;
    text-transform: uppercase;
}
.ao-tm-tl-day:first-child {
    padding-top: 0;
}
.ao-tm-tl-item {
    display: grid;
    gap: 12px;
    grid-template-columns: 28px minmax(0, 1fr);
    padding: 5px 0;
    position: relative;
}
.ao-tm-tl-node {
    background: var(--ao-surface-2);
    border: 1px solid color-mix(in srgb, var(--ao-tm-accent, var(--ao-fg-mute)) 50%, transparent);
    border-radius: 50%;
    box-shadow: 0 0 0 3px var(--ao-surface);
    color: var(--ao-tm-accent, var(--ao-fg-dim));
    display: grid;
    height: 28px;
    place-items: center;
    position: relative;
    width: 28px;
}
.ao-tm-tl-body {
    min-width: 0;
    padding-top: 3px;
}
.ao-tm-tl-top {
    align-items: baseline;
    display: flex;
    gap: 10px;
    min-width: 0;
}
.ao-tm-tl-title {
    color: var(--ao-fg);
    font-size: var(--ao-fs-strong);
    font-weight: 500;
    min-width: 0;
    overflow: hidden;
    text-decoration: none;
    text-overflow: ellipsis;
    white-space: nowrap;
}
a.ao-tm-tl-title:hover {
    text-decoration: underline;
    text-decoration-color: var(--ao-border);
    text-underline-offset: 3px;
}
a.ao-tm-tl-title:focus-visible {
    outline: 2px solid var(--ao-focus);
    outline-offset: 2px;
}
.ao-tm-tl-kind {
    color: var(--ao-fg-mute);
    flex: none;
    font-size: var(--ao-fs-label);
    letter-spacing: 0.08em;
    margin-left: auto;
    text-transform: uppercase;
}
.ao-tm-tl-sub {
    color: var(--ao-fg-mute);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--ao-fs-meta);
    gap: 2px 10px;
    margin-top: 3px;
}
.ao-tm-tl-detail {
    font-family: var(--ao-mono);
    overflow-wrap: anywhere;
}
.ao-tm-more {
    align-self: flex-start;
}

/* ── not found ──────────────────────────────────────────────────────────── */
.ao-tm-404 {
    align-items: flex-start;
    display: flex;
    gap: 20px;
    padding: 28px;
}
.ao-tm-404-ico {
    background: var(--ao-tint-2);
    border: 1px solid var(--ao-border-soft);
    border-radius: 14px;
    color: var(--ao-fg-dim);
    display: grid;
    flex: none;
    height: 56px;
    place-items: center;
    width: 56px;
}
.ao-tm-404-txt {
    align-items: flex-start;
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}
.ao-tm-404-h {
    font-size: var(--ao-fs-h);
    font-weight: 600;
    overflow-wrap: anywhere;
}
.ao-tm-404-p {
    color: var(--ao-fg-dim);
    line-height: 1.5;
    margin: 0;
}
.ao-tm-404 .ao-btn {
    text-decoration: none;
}

/* ── profile entrances (only under .ao-tm-in; see the Team header) ─────── */
@keyframes ao-tm-pop {
    from {
        opacity: 0.55;
        transform: scale(0.3);
    }
}
@keyframes ao-tm-dot-in {
    from {
        transform: scale(0);
    }
}
@keyframes ao-tm-slide {
    from {
        opacity: 0.55;
        transform: translateX(-8px);
    }
}
@keyframes ao-tm-radar-in {
    from {
        opacity: 0.55;
        transform: scale(0.18);
    }
    to {
        opacity: 1;
        transform: none;
    }
}
.ao-tm-hstat.ao-tm-in {
    animation-delay: calc(var(--ao-tm-i, 0) * 70ms + 60ms);
}
/* Charts whose container carries .ao-tm-in animate their MARKS, not the
 * container: these override the generic rise. */
.ao-tm-hm-grid.ao-tm-in,
.ao-tm-hm-weeks.ao-tm-in,
.ao-tm-punch.ao-tm-in,
.ao-tm-hbars.ao-tm-in {
    animation: none;
}
.ao-tm-hm-weeks.ao-tm-in .ao-tm-hm-wk {
    animation: ao-tm-grow-y 620ms var(--ao-ease) backwards;
    animation-delay: calc(var(--ao-tm-col, 0) * 9ms + 320ms);
}
.ao-tm-hm-grid.ao-tm-in .ao-tm-hm-c {
    animation: ao-tm-pop 460ms var(--ao-ease) backwards;
    animation-delay: calc(var(--ao-tm-col, 0) * 9ms + 220ms);
}
.ao-tm-radar-me.ao-tm-in {
    animation: ao-tm-radar-in 900ms var(--ao-ease) 260ms backwards;
}
.ao-tm-stack.ao-tm-in {
    animation: ao-tm-grow 900ms var(--ao-ease) 240ms backwards;
}
.ao-tm-hbars.ao-tm-in .ao-tm-hbar-fill {
    animation: ao-tm-grow 820ms var(--ao-ease) backwards;
    animation-delay: calc(var(--ao-tm-i, 0) * 60ms + 280ms);
}
.ao-tm-punch.ao-tm-in .ao-tm-punch-dot {
    animation: ao-tm-dot-in 520ms var(--ao-ease) backwards;
    animation-delay: calc(var(--ao-tm-i, 0) * 16ms + 240ms);
}
.ao-tm-prwrap.ao-tm-in {
    animation-delay: calc(var(--ao-tm-i, 0) * 45ms + 200ms);
}
.ao-tm-prwrap.ao-tm-in .ao-tm-pr-bar {
    animation: ao-tm-grow 820ms var(--ao-ease) backwards;
    animation-delay: calc(var(--ao-tm-i, 0) * 45ms + 420ms);
}
.ao-tm-recent.ao-tm-in .ao-tm-tl-item {
    animation: ao-tm-slide 480ms var(--ao-ease) backwards;
    animation-delay: calc(var(--ao-tm-i, 0) * 32ms + 300ms);
}

/* ── profile responsive (container widths — see .ao-tm-page) ───────────── */
@container aotm (max-width: 1099.98px) {
    .ao-tm-hero {
        grid-template-columns: minmax(0, 1fr);
    }
}
@container aotm (max-width: 599.98px) {
    .ao-tm-hero {
        gap: var(--ao-s-5);
        padding: 20px 16px;
    }
    .ao-tm-hero-who {
        align-items: flex-start;
        flex-direction: column;
        gap: 14px;
    }
    .ao-tm-hero-name {
        font-size: 24px;
    }
    .ao-tm-hero-stats {
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-tm-hstat-num {
        font-size: clamp(26px, 15cqi, 46px);
    }
    .ao-tm-pcard {
        padding: 16px 14px 18px;
    }
    .ao-tm-mixrow {
        grid-template-columns: 10px minmax(0, 1fr) auto 38px;
    }
    .ao-tm-mix-c,
    .ao-tm-tl-kind {
        display: none;
    }
    .ao-tm-radar-list,
    .ao-tm-support {
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-tm-hm-insights,
    .ao-tm-hm-insights.is-mix {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .ao-tm-404 {
        flex-direction: column;
        padding: 22px 18px;
    }
}
/* Radar alone on a row (the two-column rows stack below 980px): chart left,
 * its reading right, instead of a 440px chart floating in a wide card. */
@container aotm (min-width: 640px) and (max-width: 979.98px) {
    .ao-tm-radar-card {
        align-items: center;
        column-gap: var(--ao-s-6);
        display: grid;
        grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    }
    .ao-tm-radar-card > .ao-tm-sec-head,
    .ao-tm-radar-card > .ao-tm-radar-legend,
    .ao-tm-radar-card > .ao-tm-note {
        grid-column: 1 / -1;
    }
    .ao-tm-radar-card .ao-tm-radar-list {
        grid-template-columns: minmax(0, 1fr);
    }
}
/* The console shell has no mobile layout (fixed 220px rail), so a phone
 * leaves the page ~120px. Nothing may spill past the card there; it just
 * has to stay unbroken (spec §6.2). */
@container aotm (max-width: 299.98px) {
    .ao-tm-hero {
        padding: 16px 12px;
    }
    .ao-tm-hero-who,
    .ao-tm-hero-id {
        width: 100%;
    }
    .ao-tm-hero-av {
        height: 72px;
        width: 72px;
    }
    .ao-tm-hero-av .ao-tm-av {
        font-size: 20px !important;
        height: 56px !important;
        width: 56px !important;
    }
    .ao-tm-hero-name {
        font-size: 20px;
    }
    .ao-tm-rankchip,
    .ao-tm-hero-streak,
    .ao-tm-peak,
    .ao-tm-gh {
        max-width: 100%;
        white-space: normal;
    }
    .ao-tm-hero-fact {
        align-items: flex-start;
        overflow-wrap: anywhere;
    }
    .ao-tm-hstat {
        padding: 12px 10px;
    }
    .ao-tm-pcard {
        padding: 14px 10px 16px;
    }
    .ao-tm-hm-insights,
    .ao-tm-hm-insights.is-mix {
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-tm-hm-legend {
        flex-wrap: wrap;
    }
    .ao-tm-mixrow {
        grid-template-columns: 10px minmax(0, 1fr) 38px;
    }
    .ao-tm-mix-n {
        display: none;
    }
    .ao-tm-deploy {
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-tm-tl-item {
        gap: 8px;
        grid-template-columns: 22px minmax(0, 1fr);
    }
    .ao-tm-tl-node {
        height: 22px;
        width: 22px;
    }
    .ao-tm-tl::before {
        left: 10.5px;
    }
    .ao-tm-tl-day {
        padding-left: 30px;
    }
    .ao-tm-tl-title {
        white-space: normal;
    }
}
@container aotm (max-width: 419.98px) {
    .ao-tm-pr {
        grid-template-columns: minmax(0, 1fr) auto;
    }
    div.ao-tm-pr {
        grid-template-columns: minmax(0, 1fr) auto;
    }
    .ao-tm-pr-rank,
    .ao-tm-pr-go {
        display: none;
    }
    .ao-tm-deploy {
        grid-template-columns: minmax(0, 1fr) auto;
    }
    .ao-tm-deploy-r {
        display: none;
    }
}

/* Overview → TEAM tab: the way into the full board (a ghost pill). */
.aolb-more {
    display: flex;
    justify-content: flex-end;
    margin-top: 10px;
}

/* ── entrances (only under .ao-tm-in; see the header) ───────────────────── */
@keyframes ao-tm-rise {
    from {
        opacity: 0.55;
        transform: translateY(16px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}
@keyframes ao-tm-grow {
    from {
        transform: scaleX(0);
    }
}
@keyframes ao-tm-grow-y {
    from {
        transform: scaleY(0);
    }
}
.ao-tm-in {
    animation: ao-tm-rise 560ms var(--ao-ease) backwards;
    animation-delay: calc(var(--ao-tm-i, 0) * 40ms);
}
.ao-tm-pod.ao-tm-in {
    animation-delay: calc(var(--ao-tm-i, 0) * 90ms + 140ms);
    animation-duration: 680ms;
}
.ao-tm-rowwrap.ao-tm-in {
    animation-delay: calc(var(--ao-tm-i, 0) * 40ms + 240ms);
}
.ao-tm-rowwrap.ao-tm-in .ao-tm-r-fill {
    animation: ao-tm-grow 820ms var(--ao-ease) backwards;
    animation-delay: calc(var(--ao-tm-i, 0) * 40ms + 380ms);
}
.ao-tm-pulse-stack.ao-tm-in {
    animation: ao-tm-grow-y 700ms var(--ao-ease) backwards;
    animation-delay: calc(var(--ao-tm-i, 0) * 12ms + 300ms);
}

/* ── responsive (container widths — see .ao-tm-page) ────────────────────── */
@container aotm (max-width: 1099.98px) {
    .ao-tm-r-sec {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
    .ao-tm-r-m:nth-child(n + 5) {
        display: none;
    }
}
@container aotm (max-width: 859.98px) {
    .ao-tm-row {
        grid-template-columns: 34px minmax(0, 1.3fr) minmax(0, 1fr) 88px 16px;
    }
    .ao-tm-r-sec,
    .ao-tm-r-streak {
        display: none;
    }
}
@container aotm (max-width: 699.98px) {
    .ao-tm-podium {
        grid-template-areas: 'p1' 'p2' 'p3';
        grid-template-columns: minmax(0, 1fr);
    }
    .ao-tm-warm {
        grid-template-columns: auto minmax(0, 1fr);
    }
    .ao-tm-warm-go {
        grid-column: 1 / -1;
        justify-self: start;
    }
    .ao-tm-bar {
        align-items: stretch;
        flex-direction: column;
    }
    .ao-tm-sync {
        align-self: flex-start;
    }
}
@container aotm (min-width: 300px) and (max-width: 699.98px) {
    /* Stacked, #2 and #3 become compact rows (avatar · name · number) so the
     * podium is not three phone-heights of cards; #1 keeps the full card. */
    .ao-tm-pod.is-p2,
    .ao-tm-pod.is-p3 {
        align-items: center;
        column-gap: 14px;
        display: grid;
        grid-template-areas:
            'top top top'
            'av name val'
            'av sub val';
        grid-template-columns: auto minmax(0, 1fr) auto;
        min-height: 0;
        padding: 14px 16px;
        row-gap: 2px;
        text-align: left;
    }
    .ao-tm-pod.is-p2 .ao-tm-pod-top,
    .ao-tm-pod.is-p3 .ao-tm-pod-top {
        grid-area: top;
        margin-bottom: 8px;
    }
    .ao-tm-pod.is-p2 > .ao-tm-av,
    .ao-tm-pod.is-p3 > .ao-tm-av {
        font-size: 17px !important;
        grid-area: av;
        height: 48px !important;
        margin: 0;
        width: 48px !important;
    }
    .ao-tm-pod.is-p2 .ao-tm-pod-name,
    .ao-tm-pod.is-p3 .ao-tm-pod-name {
        grid-area: name;
    }
    .ao-tm-pod.is-p2 .ao-tm-pod-sub,
    .ao-tm-pod.is-p3 .ao-tm-pod-sub {
        grid-area: sub;
        justify-content: flex-start;
    }
    .ao-tm-pod.is-p2 .ao-tm-pod-val,
    .ao-tm-pod.is-p3 .ao-tm-pod-val {
        align-items: flex-end;
        grid-area: val;
        margin: 0;
    }
    .ao-tm-pod.is-p2 .ao-tm-pod-num,
    .ao-tm-pod.is-p3 .ao-tm-pod-num {
        font-size: 30px;
    }
    .ao-tm-pod.is-p2 .ao-tm-pod-meta,
    .ao-tm-pod.is-p3 .ao-tm-pod-meta,
    .ao-tm-pod.is-p2 .ao-tm-pod-spark,
    .ao-tm-pod.is-p3 .ao-tm-pod-spark,
    .ao-tm-pod.is-p2 .ao-tm-area,
    .ao-tm-pod.is-p3 .ao-tm-area {
        display: none;
    }
}
@container aotm (max-width: 419.98px) {
    /* Eight segments (24H … ALL + Custom) must fit a phone without scrolling:
     * Custom drops to its calendar icon until a custom range is actually
     * chosen, and the padding tightens to 7px (9px overflowed a 343px body
     * by ~26px once 24H joined). */
    .ao-tm-seg-btn {
        padding: 7px 7px;
    }
    .ao-tm-seg-btn.is-custom[aria-pressed='false'] > span {
        display: none;
    }
}
@container aotm (max-width: 599.98px) {
    .ao-tm-row {
        column-gap: 12px;
        grid-template-areas:
            'rank who go'
            'rank pri go';
        grid-template-columns: 28px minmax(0, 1fr) 16px;
        padding: 12px 10px;
        row-gap: 10px;
    }
    .ao-tm-r-rank {
        grid-area: rank;
    }
    .ao-tm-r-who {
        grid-area: who;
    }
    .ao-tm-r-pri {
        grid-area: pri;
    }
    .ao-tm-r-go {
        grid-area: go;
    }
    .ao-tm-r-spark {
        display: none;
    }
    .ao-tm-pulse-chart {
        grid-template-rows: 150px 24px;
    }
}

@media (prefers-reduced-motion: reduce) {
    :where(html:not([data-motion='full'])) .ao-tm-in,
    :where(html:not([data-motion='full'])) .ao-tm-pod.ao-tm-in,
    :where(html:not([data-motion='full'])) .ao-tm-rowwrap.ao-tm-in,
    :where(html:not([data-motion='full'])) .ao-tm-rowwrap.ao-tm-in .ao-tm-r-fill,
    :where(html:not([data-motion='full'])) .ao-tm-pulse-stack.ao-tm-in,
    :where(html:not([data-motion='full'])) .ao-tm-move.is-bump.is-up,
    :where(html:not([data-motion='full'])) .ao-tm-move.is-bump.is-down,
    :where(html:not([data-motion='full'])) .ao-tm-card.has-ring::before,
    :where(html:not([data-motion='full'])) .ao-tm-card.has-ring:hover::before,
    :where(html:not([data-motion='full'])) .ao-tm-pod.is-p1::before,
    :where(html:not([data-motion='full'])) .ao-tm-av.is-spin::before,
    :where(html:not([data-motion='full'])) .ao-tm-sync-dot::after,
    :where(html:not([data-motion='full'])) .ao-tm-warm-ico::after,
    :where(html:not([data-motion='full'])) .ao-tm-hero-orbit,
    :where(html:not([data-motion='full'])) .ao-tm-hstat.ao-tm-in,
    :where(html:not([data-motion='full'])) .ao-tm-hm-grid.ao-tm-in .ao-tm-hm-c,
    :where(html:not([data-motion='full'])) .ao-tm-hm-weeks.ao-tm-in .ao-tm-hm-wk,
    :where(html:not([data-motion='full'])) .ao-tm-radar-me.ao-tm-in,
    :where(html:not([data-motion='full'])) .ao-tm-stack.ao-tm-in,
    :where(html:not([data-motion='full'])) .ao-tm-hbars.ao-tm-in .ao-tm-hbar-fill,
    :where(html:not([data-motion='full'])) .ao-tm-punch.ao-tm-in .ao-tm-punch-dot,
    :where(html:not([data-motion='full'])) .ao-tm-prwrap.ao-tm-in,
    :where(html:not([data-motion='full'])) .ao-tm-prwrap.ao-tm-in .ao-tm-pr-bar,
    :where(html:not([data-motion='full'])) .ao-tm-recent.ao-tm-in .ao-tm-tl-item {
        animation: none !important;
    }
    :where(html:not([data-motion='full'])) .ao-tm-card.has-ring,
    :where(html:not([data-motion='full'])) .ao-tm-card.has-ring:hover,
    :where(html:not([data-motion='full'])) .ao-tm-card.has-ring:focus-visible,
    :where(html:not([data-motion='full'])) .ao-tm-row:hover .ao-tm-r-go {
        transform: none;
    }
    :where(html:not([data-motion='full'])) .ao-tm-r-fill,
    :where(html:not([data-motion='full'])) .ao-tm-card.has-ring,
    :where(html:not([data-motion='full'])) .ao-refetching,
    :where(html:not([data-motion='full'])) .ao-tm-share-fill,
    :where(html:not([data-motion='full'])) .ao-tm-hbar-fill,
    :where(html:not([data-motion='full'])) .ao-tm-back-arrow {
        transition: none;
    }
    :where(html:not([data-motion='full'])) .ao-tm-back:hover .ao-tm-back-arrow {
        transform: none;
    }
}
