/* ═══════════════════════════════════════════════════════════════════════
   TD Coach — UI kit. THE stylesheet for every new and rebuilt page.
   Loaded on every page by templates/dashboard.html, AFTER style.css and
   BEFORE dashboard.css (the shell). Macros: templates/_ui.html.
   Behaviour: static/js/ui.js. How to build a page with it: v1/BUILDING.md.

   Rules of the kit
   - Every class starts with `ui-`. Nothing here restyles a legacy class,
     except the clearly marked block at the very bottom (section 26).
   - Must also work on a page that does NOT load style.css (a standalone page
     shown in an iframe, the error pages). So the brand variables are
     re-declared here with the same names and the same values.
   - The only inline style a template may write is a data variable:
     style="--w:42%"  style="--pct:31%;--pace:90%". Never a colour or a size.
   - Two cut points only: 767.98px (phone) and 1023.98px (the rail goes behind
     the menu button). Do not add another.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1. TOKENS ─────────────────────────────────────────────────────────── */
:root {
    /* Brand — identical to style.css. Do not change values here. */
    --gold:        #C9A84C;
    --gold-light:  #E8D48B;
    --gold-dark:   #A68A3E;
    --gold-glow:   rgba(201, 168, 76, 0.15);
    --black:       #0A0A0A;
    --dark:        #141414;
    --dark-card:   #1A1A1A;
    --dark-hover:  #222222;
    --dark-border: #2A2A2A;
    --text:        #F0F0F0;
    --text-muted:  #888888;   /* legacy pages only. New work uses --ui-muted. */
    --green:       #2ECC71;
    --green-bg:    rgba(46, 204, 113, 0.12);
    --red:         #E74C3C;
    --red-bg:      rgba(231, 76, 60, 0.12);
    --orange:      #E67E22;
    --orange-bg:   rgba(230, 126, 34, 0.12);
    --blue:        #3498DB;
    --blue-bg:     rgba(52, 152, 219, 0.12);

    /* Surfaces, darkest to lightest */
    --ui-bg:       var(--black);        /* the page                          */
    --ui-sunken:   var(--dark);         /* table head, bar tracks, inputs    */
    --ui-surface:  var(--dark-card);    /* tiles, cards, tables              */
    --ui-raised:   var(--dark-hover);   /* hover rows, pressed controls      */
    --ui-overlay:  #262626;             /* menus, dialogs, toasts            */

    /* Lines */
    --ui-border:          var(--dark-border);
    --ui-border-strong:   #3A3A3A;              /* hover, dividers in overlays */
    --ui-border-control:  #6E6E6E;              /* inputs, switches: 3:1 min   */
    --ui-border-accent:   rgba(201, 168, 76, 0.34);

    /* LEGACY ALIAS. Older tabs say var(--border) (56 times) and nothing ever
       defined it, so those borders vanished or took the text colour. This
       makes them draw. New work uses --ui-border; a builder who rebuilds a
       tab replaces var(--border) there. */
    --border: var(--ui-border);

    /* Text. Contrast on --ui-surface (#1A1A1A) in brackets. */
    --ui-text:     var(--text);         /* 15.3:1 */
    --ui-text-2:   #B8B8B8;             /*  8.8:1  descriptions             */
    --ui-muted:    #9A9A9A;             /*  6.2:1  labels, notes (5.1 on overlay) */
    --ui-disabled: #7A7A7A;             /*  4.1:1  disabled only            */

    /* Accent = gold. Actions, current selection, targets. Never decoration. */
    --ui-accent:       var(--gold);     /* 7.6:1 as text */
    --ui-accent-hover: var(--gold-light);
    --ui-accent-tint:  var(--gold-glow);
    --ui-on-accent:    var(--black);    /* 8.7:1 on gold */

    /* Status. *-fill is for bars and dots, the plain name is for text. */
    --ui-good:       var(--green);              /* 8.3:1 */
    --ui-good-fill:  var(--green);
    --ui-good-tint:  rgba(46, 204, 113, 0.14);
    --ui-bad:        #F4776A;                   /* 6.4:1 — --red is 4.0 on its own tint, so text uses this */
    --ui-bad-fill:   var(--red);
    --ui-bad-tint:   rgba(231, 76, 60, 0.14);
    --ui-warn:       #F0A04B;                   /* 8.2:1 */
    --ui-warn-fill:  var(--orange);
    --ui-warn-tint:  rgba(230, 126, 34, 0.14);
    --ui-info:       #5DADE2;                   /* 7.1:1 */
    --ui-info-tint:  rgba(52, 152, 219, 0.14);
    --ui-danger:       #C0392B;                 /* white text on it: 5.4:1 */
    --ui-danger-hover: #A93226;

    /* Type — one family, fixed sizes, 12px floor */
    --ui-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --ui-fs-xs:  0.75rem;     /* 12  notes, deltas, table head     */
    --ui-fs-sm:  0.8125rem;   /* 13  labels, table cells, buttons  */
    --ui-fs-md:  0.875rem;    /* 14  body                          */
    --ui-fs-lg:  1rem;        /* 16  card titles, inputs on phone  */
    --ui-fs-xl:  1.25rem;     /* 20  dialog title, tile value (phone) */
    --ui-fs-2xl: 1.5rem;      /* 24  page title, tile value        */
    --ui-fs-3xl: 1.75rem;     /* 28  strip tile value              */
    --ui-fs-4xl: 2.125rem;    /* 34  one hero number per page, max */
    --ui-lh-tight: 1.15;
    --ui-lh-snug:  1.35;
    --ui-lh-body:  1.5;

    /* Space — 4px base. Use these and nothing in between. */
    --ui-1: 4px;   --ui-2: 8px;   --ui-3: 12px;  --ui-4: 16px;
    --ui-5: 20px;  --ui-6: 24px;  --ui-8: 32px;  --ui-10: 40px;  --ui-12: 48px;

    /* Shape */
    --ui-r-sm:   6px;     /* buttons, inputs, badges, menu items */
    --ui-r-md:   10px;    /* tiles, cards                        */
    --ui-r-lg:   12px;    /* tables, strips, dialogs             */
    --ui-r-full: 999px;   /* pills, chips, switches              */

    /* Depth — only things that float get a shadow */
    --ui-shadow-pop:   0 8px 24px rgba(0, 0, 0, 0.55), 0 1px 2px rgba(0, 0, 0, 0.4);
    --ui-shadow-modal: 0 24px 64px rgba(0, 0, 0, 0.65), 0 2px 6px rgba(0, 0, 0, 0.4);

    /* Focus ring — 13.4:1 on the page, 10.8:1 on raised */
    --ui-focus-color: var(--gold-light);
    --ui-focus-width: 2px;
    --ui-focus-gap:   2px;

    /* Motion */
    --ui-ease: cubic-bezier(0.16, 1, 0.3, 1);
    --ui-fast: 120ms;
    --ui-med:  200ms;

    /* Layers */
    --ui-z-sticky: 20;
    --ui-z-menu:   300;
    --ui-z-toast:  400;

    /* Layout */
    --ui-page-max: 1320px;
    --ui-control-h: 36px;       /* buttons, inputs, range toggle on desktop */
    --ui-control-h-touch: 44px; /* same controls on a phone                 */
}

/* ── 2. BASE ───────────────────────────────────────────────────────────── */
.ui-page {
    max-width: var(--ui-page-max);
    font-family: var(--ui-font);
    font-size: var(--ui-fs-md);
    line-height: var(--ui-lh-body);
    color: var(--ui-text);
    -webkit-font-smoothing: antialiased;
}
.ui-page *, .ui-page *::before, .ui-page *::after,
.ui-modal, .ui-modal *, .ui-toasts, .ui-toasts *, .ui-menu-list, .ui-menu-list * { box-sizing: border-box; }

.ui-page :where(h1, h2, h3, h4, p, ul, ol, figure, dl, dd),
.ui-modal :where(h1, h2, h3, h4, p, ul, ol) { margin: 0; padding: 0; }
.ui-page :where(ul, ol), .ui-modal :where(ul, ol) { list-style: none; }

/* Screen-reader only */
.ui-sr {
    position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Numbers line up in columns */
.ui-num, .ui-tile-value, .ui-tile-delta, .ui-goal-nums, .ui-funnel-count, .ui-funnel-step {
    font-variant-numeric: tabular-nums;
}

/* Tones — one vocabulary, used by deltas, values, badges */
.ui-tone-good { color: var(--ui-good); }
.ui-tone-bad  { color: var(--ui-bad); }
.ui-tone-warn { color: var(--ui-warn); }
.ui-tone-flat,
.ui-tone-none { color: var(--ui-muted); }

/* Icons (inline SVG from ui_icon) */
.ui-icon { width: 16px; height: 16px; flex: 0 0 auto; display: inline-block; vertical-align: -3px;
    fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.ui-icon--lg { width: 20px; height: 20px; vertical-align: -4px; }
.ui-icon--xl { width: 28px; height: 28px; }

/* Focus — the same ring on everything that takes focus */
.ui-page :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible,
.ui-modal :where(a, button, input, select, textarea, [tabindex]):focus-visible,
.ui-menu-list :where(a, button):focus-visible,
.ui-toasts :where(a, button):focus-visible {
    outline: var(--ui-focus-width) solid var(--ui-focus-color);
    outline-offset: var(--ui-focus-gap);
}
.ui-page :where(a, button, input, select, textarea):focus:not(:focus-visible) { outline: none; }

/* The legacy sheet lifts every <button> on hover. Kit controls stay put. */
button[class*="ui-"], button[class*="ui-"]:hover, button[class*="ui-"]:active { transform: none; }

/* Links inside page text */
.ui-link { color: var(--ui-accent); text-decoration: none; font-weight: 600; }
.ui-link:hover { color: var(--ui-accent-hover); text-decoration: underline; text-underline-offset: 3px; }

/* Vertical rhythm between blocks on a page */
.ui-stack > * + * { margin-top: var(--ui-6); }
.ui-stack--tight > * + * { margin-top: var(--ui-3); }

/* ── 3. PAGE HEADER ────────────────────────────────────────────────────── */
.ui-page-header {
    display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
    gap: var(--ui-4) var(--ui-6);
    margin-bottom: var(--ui-5);
}
.ui-page-heading { min-width: 0; flex: 1 1 320px; }
.ui-page-title {
    font-size: var(--ui-fs-2xl); font-weight: 700; line-height: var(--ui-lh-tight);
    letter-spacing: -0.015em; color: var(--ui-text); text-wrap: balance;
}
.ui-page-desc {
    margin-top: var(--ui-1); font-size: var(--ui-fs-md); color: var(--ui-text-2);
    max-width: 68ch; text-wrap: pretty;
}
.ui-asof {
    display: inline-flex; align-items: center; gap: 6px;
    margin-top: var(--ui-2); font-size: var(--ui-fs-xs); color: var(--ui-muted);
}
.ui-asof-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ui-good-fill); flex: 0 0 auto; }
.ui-asof--stale { color: var(--ui-warn); }
.ui-asof--stale .ui-asof-dot { background: var(--ui-warn-fill); }
.ui-asof--none .ui-asof-dot { background: var(--ui-border-control); }
.ui-page-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; min-width: 0; max-width: 100%; }

/* ── 4. RANGE TOGGLE ───────────────────────────────────────────────────── */
.ui-range {
    display: inline-flex; max-width: 100%;
    background: var(--ui-sunken); border: 1px solid var(--ui-border);
    border-radius: var(--ui-r-sm); padding: 3px; gap: 2px;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
    position: relative;   /* keeps hidden screen-reader text inside the scroller */
}
.ui-range::-webkit-scrollbar { display: none; }
.ui-range-item {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: calc(var(--ui-control-h) - 8px);
    padding: 0 var(--ui-3); border-radius: 4px;
    font-size: var(--ui-fs-sm); font-weight: 600; white-space: nowrap;
    color: var(--ui-muted); text-decoration: none;
    transition: background var(--ui-fast), color var(--ui-fast);
}
.ui-range-item:hover { color: var(--ui-text); background: var(--ui-raised); }
.ui-range-item[aria-current="true"] { background: var(--ui-accent-tint); color: var(--ui-accent); }
.ui-range-item:focus-visible { outline-offset: -2px; }
.ui-range-note { font-size: var(--ui-fs-xs); color: var(--ui-muted); text-align: right; }

/* ── 5. SECTION HEADING ────────────────────────────────────────────────── */
.ui-section {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--ui-1) var(--ui-3);
    margin: var(--ui-8) 0 var(--ui-3);
}
.ui-section:first-child { margin-top: 0; }
.ui-section-title {
    font-size: var(--ui-fs-xs); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--ui-accent); line-height: var(--ui-lh-snug);
}
.ui-section-note { font-size: var(--ui-fs-sm); color: var(--ui-muted); flex: 1 1 200px; min-width: 0; }
.ui-section-link { margin-left: auto; font-size: var(--ui-fs-sm); font-weight: 600; color: var(--ui-accent); text-decoration: none; white-space: nowrap; }
.ui-section-link:hover { color: var(--ui-accent-hover); }
/* A heading INSIDE a card or a list item (ui.subhead). Quieter than a section
   title, louder than body text. */
.ui-subhead { margin: 0; font-size: var(--ui-fs-md); font-weight: 600; line-height: var(--ui-lh-snug); color: var(--ui-text); overflow-wrap: anywhere; }

/* ── 6. KPI TILE ───────────────────────────────────────────────────────── */
.ui-tiles {
    display: grid; gap: var(--ui-3);
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.ui-tile {
    position: relative; min-width: 0;
    display: flex; flex-direction: column;
    background: var(--ui-surface); border: 1px solid var(--ui-border);
    border-radius: var(--ui-r-md); padding: var(--ui-4);
    transition: border-color var(--ui-fast), background var(--ui-fast);
}
.ui-tile-label { font-size: var(--ui-fs-sm); font-weight: 500; color: var(--ui-muted); line-height: var(--ui-lh-snug); }
.ui-tile-value {
    margin-top: var(--ui-1);
    font-size: var(--ui-fs-2xl); font-weight: 700; line-height: var(--ui-lh-tight);
    letter-spacing: -0.02em; color: var(--ui-text); overflow-wrap: anywhere;
}
.ui-tile-value--good { color: var(--ui-good); }
.ui-tile-value--ok   { color: var(--ui-accent); }
.ui-tile-value--bad  { color: var(--ui-bad); }
.ui-tile-value--none { color: var(--ui-muted); }
.ui-tile-unit { font-size: var(--ui-fs-md); font-weight: 600; color: var(--ui-muted); letter-spacing: 0; }
.ui-tile-delta { margin-top: var(--ui-2); font-size: var(--ui-fs-xs); font-weight: 600; line-height: var(--ui-lh-snug); }
.ui-tile-arrow { font-size: inherit; }
.ui-tile-prev { color: var(--ui-muted); font-weight: 500; }
.ui-tile-target { margin-top: var(--ui-1); font-size: var(--ui-fs-xs); color: var(--ui-accent); line-height: var(--ui-lh-snug); }
/* Label row: the label, then a small (i). The long explanation of the number
   (definition) is not printed under it; it is a tooltip on the (i), shown on
   hover, keyboard focus and tap. CSS only. The text stays in the DOM and is the
   button's description (aria-describedby). The tooltip is fixed and anchored to
   its (i), so a strip's rounded clip cannot cut it and it flips to stay on screen. */
.ui-tile-head { display: flex; align-items: center; gap: var(--ui-1); min-width: 0; }
.ui-tile-head .ui-tile-label { min-width: 0; }
.ui-tip-btn {
    position: relative; z-index: 1;            /* above the tile link's full-tile overlay */
    flex: none; display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; margin: -2px 0; padding: 0;
    border: 0; border-radius: 50%; background: transparent; color: var(--ui-muted);
    cursor: help; anchor-name: --ui-tip;
    transition: color var(--ui-fast);
}
.ui-tip-btn .ui-icon { width: 15px; height: 15px; }
.ui-tip-btn::after { content: ''; position: absolute; inset: -8px; }   /* bigger tap target */
.ui-tip-btn:hover, .ui-tip-btn:focus-visible { color: var(--ui-accent); }
.ui-tip-btn:focus-visible { outline: var(--ui-focus-width) solid var(--ui-focus-color); outline-offset: 1px; }
.ui-tile { anchor-scope: --ui-tip; }
.ui-tip {
    position: fixed; z-index: var(--ui-z-menu);
    position-anchor: --ui-tip; position-area: bottom span-right;
    position-try-fallbacks: flip-inline, flip-block, flip-block flip-inline;
    margin: 6px 0;
    width: max-content; max-width: min(260px, calc(100vw - 32px));
    padding: var(--ui-2) var(--ui-3);
    background: var(--ui-overlay); color: var(--ui-text);
    border: 1px solid var(--ui-border-strong); border-radius: var(--ui-r-md);
    box-shadow: var(--ui-shadow-pop);
    visibility: hidden; opacity: 0; pointer-events: none;
    transition: opacity var(--ui-fast), visibility var(--ui-fast);
}
.ui-tile:has(.ui-tip-btn:hover) .ui-tip,
.ui-tile:has(.ui-tip-btn:focus) .ui-tip,
.ui-tile:has(.ui-tip-btn:focus-visible) .ui-tip { visibility: visible; opacity: 1; }
.ui-tip .ui-tile-def { margin: 0; font-size: var(--ui-fs-xs); font-weight: 400; color: var(--ui-text); line-height: var(--ui-lh-snug); text-wrap: pretty; overflow-wrap: anywhere; letter-spacing: 0; }
/* Old browsers without anchor positioning: under the label, inside the tile. */
@supports not (anchor-name: --a) {
    .ui-tip { position: absolute; top: var(--ui-8); left: var(--ui-3); max-width: min(260px, calc(100% - var(--ui-6))); }
}
/* Phones: the full width of the screen, 16px in from each side, under the (i). */
@media (max-width: 767.98px) {
    @supports (anchor-name: --a) {
        .ui-tip { position-area: none; position-try-fallbacks: none; top: anchor(bottom); left: 16px; right: 16px; width: auto; max-width: none; }
    }
}
.ui-tile-link {
    margin-top: auto; padding-top: var(--ui-3);
    font-size: var(--ui-fs-xs); font-weight: 600; color: var(--ui-accent); text-decoration: none;
}
/* The link covers the whole tile, so the tile is one big target. */
.ui-tile-link::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.ui-tile:has(.ui-tile-link):hover { border-color: var(--ui-border-strong); background: var(--ui-raised); }
.ui-tile:has(.ui-tile-link):hover .ui-tile-link { color: var(--ui-accent-hover); }
.ui-tile-link:focus-visible { outline: none; }
.ui-tile-link:focus-visible::after { outline: var(--ui-focus-width) solid var(--ui-focus-color); outline-offset: -2px; }
.ui-tile--flag { border-color: rgba(230, 126, 34, 0.45); }
.ui-tile--flag .ui-tile-label { color: var(--ui-warn); }
/* The one hero number of a page (ui.hero). Same tile, the largest value in
   the scale and the gold edge of the strip. One per page, at most. */
.ui-tile--hero { border-color: var(--ui-border-accent); padding: var(--ui-5); }
.ui-tile--hero .ui-tile-value { font-size: var(--ui-fs-4xl); }

/* ── 7. HERO KPI STRIP ─────────────────────────────────────────────────── */
/* One band, hairlines between numbers. Set apart by the gold edge and the
   larger value — not by a glow. 4–8 tiles. data-count picks the columns so
   there is never an empty cell. */
.ui-strip {
    display: grid; gap: 1px;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    background: var(--ui-border);
    border: 1px solid var(--ui-border-accent);
    border-radius: var(--ui-r-lg); overflow: hidden;
}
.ui-strip > .ui-tile { border: 0; border-radius: 0; padding: var(--ui-4) var(--ui-5); }
.ui-strip .ui-tile-value { font-size: var(--ui-fs-3xl); }
.ui-strip[data-count="1"] { grid-template-columns: minmax(0, 1fr); }
.ui-strip[data-count="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ui-strip[data-count="3"],
.ui-strip[data-count="6"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ui-strip[data-count="5"] { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.ui-strip[data-count="7"] > :last-child { grid-column: span 2; }
/* In a strip the link is a corner arrow, to save a row. The whole tile is still the target. */
.ui-strip .ui-tile-link { position: static; margin: 0; padding: 0; }
.ui-strip .ui-tile-link-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
.ui-strip .ui-tile-link-arrow { position: absolute; top: var(--ui-4); right: var(--ui-5); font-size: var(--ui-fs-md); color: var(--ui-muted); transition: color var(--ui-fast), transform var(--ui-fast); }
.ui-strip .ui-tile:hover .ui-tile-link-arrow { color: var(--ui-accent); transform: translateX(2px); }
.ui-strip .ui-tile:has(.ui-tile-link) .ui-tile-head { padding-right: var(--ui-6); }

/* Groups of strips with a label each (Overview: Money / Delivery / Pipeline) */
.ui-groups { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--ui-4); }
.ui-group { min-width: 0; grid-column: span 4; display: flex; flex-direction: column; }
.ui-group > .ui-strip { flex: 1 1 auto; }
.ui-group--half { grid-column: span 2; }
.ui-group-label {
    font-size: var(--ui-fs-xs); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--ui-accent); margin-bottom: var(--ui-2);
}

/* ── 8. CARD (a plain container; never nest one inside another) ─────────── */
.ui-card {
    background: var(--ui-surface); border: 1px solid var(--ui-border);
    border-radius: var(--ui-r-lg); padding: var(--ui-5); min-width: 0;
}
.ui-card--flush { padding: 0; overflow: hidden; }
.ui-card-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--ui-1) var(--ui-3); margin-bottom: var(--ui-4); }
.ui-card-title { font-size: var(--ui-fs-lg); font-weight: 600; color: var(--ui-text); line-height: var(--ui-lh-snug); }
.ui-card-note { font-size: var(--ui-fs-sm); color: var(--ui-muted); }

/* Two-column page body */
.ui-split { display: grid; gap: var(--ui-6); grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); align-items: start; }
.ui-split--reverse { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }   /* 1/3 | 2/3 */
.ui-cols-2 { display: grid; gap: var(--ui-4); grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }

/* ── 9. DATA TABLE ─────────────────────────────────────────────────────── */
.ui-toolbar {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--ui-3);
    margin-bottom: var(--ui-3);
}
.ui-toolbar-grow { flex: 1 1 220px; min-width: 0; max-width: 360px; }
.ui-toolbar-end { margin-left: auto; display: flex; gap: var(--ui-2); flex-wrap: wrap; }
.ui-toolbar-count { font-size: var(--ui-fs-sm); color: var(--ui-muted); }

.ui-table-wrap {
    position: relative;   /* without this, hidden screen-reader text in a cell widens the whole page */
    overflow: auto; -webkit-overflow-scrolling: touch;
    background: var(--ui-surface); border: 1px solid var(--ui-border);
    border-radius: var(--ui-r-lg);
    max-width: 100%;
}
.ui-table-wrap--tall { max-height: min(70vh, 640px); }   /* 15+ rows: scroll inside, header stays */
.ui-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--ui-fs-sm); color: var(--ui-text); }
.ui-table th, .ui-table td { padding: 10px var(--ui-3); text-align: left; vertical-align: middle; white-space: nowrap; }
.ui-table thead th {
    position: sticky; top: 0; z-index: 2;
    background: var(--ui-sunken); color: var(--ui-muted);
    font-size: var(--ui-fs-xs); font-weight: 600; line-height: var(--ui-lh-snug);
    border-bottom: 1px solid var(--ui-border);
}
.ui-table tbody td { border-bottom: 1px solid rgba(255, 255, 255, 0.05); }
.ui-table tbody tr:last-child td { border-bottom: 0; }
.ui-table tbody tr:hover td { background: var(--ui-raised); }
.ui-table .ui-num { text-align: right; }
.ui-table .ui-wrap { white-space: normal; min-width: 200px; overflow-wrap: anywhere; }   /* a long link breaks instead of widening the table (T4.15) */
/* A narrower wrapping cell (status + a hint, a folded "How to fix"), so a wide table fits 1440 (QA T4.15). */
.ui-table .ui-wrap--sm { min-width: 140px; }
/* A table with many number columns (Attribution's report): wrap it in
   <div class="ui-table-many">. Headings wrap onto two lines and cells are a
   little tighter, so twelve numbers fit a 1440 screen (QA T4.15). */
.ui-table-many .ui-table th, .ui-table-many .ui-table .ui-sort { white-space: normal; }
.ui-table-many .ui-table th, .ui-table-many .ui-table td { padding-left: var(--ui-2); padding-right: var(--ui-2); }
.ui-table-many .ui-table th:first-child, .ui-table-many .ui-table td:first-child { padding-left: var(--ui-3); }
.ui-table-many .ui-table .ui-wrap { min-width: 140px; }
.ui-table td.ui-cell-muted, .ui-table tr.ui-row-muted td { color: var(--ui-muted); }
.ui-table td.ui-cell-good { color: var(--ui-good); font-weight: 600; }
.ui-table td.ui-cell-bad { color: var(--ui-bad); font-weight: 600; }
.ui-table .ui-col-menu { width: 1%; text-align: right; padding-right: var(--ui-2); }
.ui-table--dense th, .ui-table--dense td { padding-top: 7px; padding-bottom: 7px; }
.ui-table-foot { margin-top: var(--ui-3); font-size: var(--ui-fs-xs); color: var(--ui-muted); line-height: 1.6; max-width: 90ch; }

/* Sortable header: the whole header cell is a button */
.ui-sort {
    all: unset; box-sizing: border-box; cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
    font: inherit; color: inherit; border-radius: 4px;
}
.ui-sort:hover { color: var(--ui-text); }
.ui-num .ui-sort { flex-direction: row-reverse; }
.ui-sort-icon { width: 8px; height: 12px; position: relative; flex: 0 0 auto; opacity: 0.55; }
.ui-sort-icon::before, .ui-sort-icon::after {
    content: ''; position: absolute; left: 0; border: 4px solid transparent;
}
.ui-sort-icon::before { top: -3px; border-bottom-color: currentColor; }
.ui-sort-icon::after  { bottom: -3px; border-top-color: currentColor; }
th[aria-sort="ascending"], th[aria-sort="descending"] { color: var(--ui-text); }
th[aria-sort="ascending"] .ui-sort-icon, th[aria-sort="descending"] .ui-sort-icon { opacity: 1; color: var(--ui-accent); }
th[aria-sort="ascending"] .ui-sort-icon::after { opacity: 0.25; }
th[aria-sort="descending"] .ui-sort-icon::before { opacity: 0.25; }

/* Person cell */
.ui-person { display: flex; align-items: center; gap: var(--ui-3); min-width: 0; }
.ui-avatar {
    width: 32px; height: 32px; border-radius: 50%; flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--ui-raised); border: 1px solid var(--ui-border-strong);
    color: var(--ui-text-2); font-size: var(--ui-fs-xs); font-weight: 700; letter-spacing: 0.02em;
}
/* A profile photo lies over the initials (features/photos.py). If it fails
   to load, ui.js removes it and the initials are what is left. */
.ui-avatar.has-photo, .user-avatar.has-photo { position: relative; overflow: hidden; }
.ui-avatar-img {
    position: absolute; inset: 0; width: 100%; height: 100%; display: block;
    object-fit: cover; border-radius: 50%; background: var(--ui-raised);
}
.ui-avatar--xl { width: 96px; height: 96px; font-size: 28px; }
.ui-photo-edit { display: flex; align-items: center; gap: var(--ui-4); flex-wrap: wrap; }
.ui-photo-actions { display: flex; flex-wrap: wrap; gap: var(--ui-2); align-items: center; }
.ui-photo-actions [hidden] { display: none; }
.ui-photo-file { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.ui-photo-file:focus-visible + .ui-btn { outline: 2px solid var(--ui-accent); outline-offset: 2px; }
/* The crop box (static/js/photos.js): the square is what is saved, the ring
   is what the round avatar shows. Everything outside the ring is dimmed. */
.ui-crop-stage {
    position: relative; width: min(320px, 100%); aspect-ratio: 1; margin: 0 auto; overflow: hidden;
    border-radius: var(--ui-r-lg); background: var(--ui-raised); cursor: grab; touch-action: none; user-select: none;
}
.ui-crop-stage:active { cursor: grabbing; }
.ui-crop-canvas { display: block; width: 100%; height: 100%; }
.ui-crop-ring {
    position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
    border: 2px solid rgba(255, 255, 255, 0.9); box-shadow: 0 0 0 999px rgba(0, 0, 0, 0.62);
}
.ui-crop-zoom { display: flex; align-items: center; gap: var(--ui-3); font-size: var(--ui-fs-sm); }
.ui-crop-zoom input { flex: 1 1 auto; min-width: 0; accent-color: var(--ui-accent); }
.ui-avatar-btn { appearance: none; background: none; border: 0; padding: 0; margin: 0; border-radius: 50%; cursor: pointer; min-width: 32px; min-height: 32px; display: inline-flex; }
@media (pointer: coarse) { .ui-avatar-btn { position: relative; } .ui-avatar-btn::after { content: ''; position: absolute; inset: -6px; } }
.ui-avatar-btn:focus-visible { outline: 2px solid var(--ui-accent); outline-offset: 2px; }
.ui-person-name { font-weight: 600; color: var(--ui-text); }
.ui-person-sub { font-size: var(--ui-fs-xs); color: var(--ui-muted); }

/* ── 10. EMPTY STATE ───────────────────────────────────────────────────── */
.ui-empty {
    display: flex; flex-direction: column; align-items: center; text-align: center;
    padding: var(--ui-10) var(--ui-5);
    background: var(--ui-surface); border: 1px dashed var(--ui-border-strong);
    border-radius: var(--ui-r-lg);
}
.ui-empty[hidden] { display: none; }
.ui-empty-icon {
    width: 48px; height: 48px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--ui-raised); color: var(--ui-muted); margin-bottom: var(--ui-3);
}
.ui-empty-title { font-size: var(--ui-fs-lg); font-weight: 600; color: var(--ui-text); }
.ui-empty-text { margin-top: var(--ui-1); font-size: var(--ui-fs-md); color: var(--ui-text-2); max-width: 52ch; text-wrap: pretty; }
.ui-empty-how { margin-top: var(--ui-2); font-size: var(--ui-fs-sm); color: var(--ui-muted); max-width: 52ch; text-wrap: pretty; }
.ui-empty .ui-empty-action { margin-top: var(--ui-4); }
.ui-empty--inline { padding: var(--ui-5) var(--ui-4); border: 0; background: transparent; }
.ui-empty--inline .ui-empty-icon { width: 36px; height: 36px; }

/* ── 11. BADGE, SOURCE-ERROR CHIP ──────────────────────────────────────── */
.ui-badge {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 2px var(--ui-2); border-radius: var(--ui-r-sm);
    font-size: var(--ui-fs-xs); font-weight: 600; line-height: 1.5; white-space: nowrap;
    background: rgba(255, 255, 255, 0.08); color: var(--ui-text-2);
}
.ui-badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.ui-badge--plain::before { display: none; }
.ui-badge--good { background: var(--ui-good-tint); color: var(--ui-good); }
.ui-badge--bad  { background: var(--ui-bad-tint);  color: var(--ui-bad); }
.ui-badge--warn { background: var(--ui-warn-tint); color: var(--ui-warn); }
.ui-badge--info { background: var(--ui-info-tint); color: var(--ui-info); }
.ui-badge--gold { background: var(--ui-accent-tint); color: var(--ui-accent); }

/* Chart key: names each colour of a chart (QA 8.4). Swatch colours match the
   chart's own (dashboard.html gold / green / red at the same strength). */
.ui-chart-key {
    display: flex; flex-wrap: wrap; gap: var(--ui-2) var(--ui-4);
    margin: var(--ui-3) 0 0; padding: 0; list-style: none;
    font-size: var(--ui-fs-xs); color: var(--ui-text-2);
}
.ui-chart-key-item { display: inline-flex; align-items: center; gap: var(--ui-2); }
.ui-chart-key-swatch { width: 12px; height: 12px; border-radius: 3px; flex: none; opacity: 0.8; }
.ui-chart-key-swatch--accent { background: var(--ui-accent); }
.ui-chart-key-swatch--good { background: var(--ui-good-fill); }
.ui-chart-key-swatch--bad { background: var(--ui-bad-fill); }
.ui-chart-key-swatch--info { background: var(--ui-info); }

.ui-chips { display: flex; flex-wrap: wrap; gap: var(--ui-2); margin-bottom: var(--ui-4); }
.ui-chip-error {
    display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
    padding: var(--ui-1) var(--ui-3); border-radius: var(--ui-r-full);
    background: var(--ui-bad-tint); color: var(--ui-bad);
    font-size: var(--ui-fs-xs); font-weight: 500; line-height: 1.5; overflow-wrap: anywhere;
}
.ui-chip-error-name { font-weight: 700; }

/* ── 12. STALE BANNER (and other page-level notices) ───────────────────── */
.ui-banner {
    display: flex; align-items: flex-start; gap: var(--ui-3);
    padding: var(--ui-3) var(--ui-4); margin-bottom: var(--ui-4);
    background: var(--ui-warn-tint); border: 1px solid rgba(230, 126, 34, 0.4);
    border-radius: var(--ui-r-md);
    font-size: var(--ui-fs-sm); color: var(--ui-text); line-height: var(--ui-lh-body);
}
.ui-banner-icon { color: var(--ui-warn); margin-top: 1px; }
.ui-banner-body { flex: 1 1 auto; min-width: 0; }
.ui-banner-title { font-weight: 600; }
.ui-banner-list li + li { margin-top: 2px; }
.ui-banner-link { color: var(--ui-accent); font-weight: 600; text-decoration: none; white-space: nowrap; align-self: center; }
.ui-banner-link:hover { color: var(--ui-accent-hover); }
.ui-banner-close {
    all: unset; box-sizing: border-box; cursor: pointer; align-self: center;
    width: 28px; height: 28px; border-radius: var(--ui-r-sm);
    display: inline-flex; align-items: center; justify-content: center; color: var(--ui-text-2);
}
.ui-banner-close:hover { background: rgba(255, 255, 255, 0.08); color: var(--ui-text); }
.ui-banner--bad  { background: var(--ui-bad-tint);  border-color: rgba(231, 76, 60, 0.45); }
.ui-banner--bad .ui-banner-icon { color: var(--ui-bad); }
.ui-banner--good { background: var(--ui-good-tint); border-color: rgba(46, 204, 113, 0.4); }
.ui-banner--good .ui-banner-icon { color: var(--ui-good); }
.ui-banner--info { background: var(--ui-info-tint); border-color: rgba(52, 152, 219, 0.4); }
.ui-banner--info .ui-banner-icon { color: var(--ui-info); }

/* ── 13. BUTTONS ───────────────────────────────────────────────────────── */
.ui-btn {
    appearance: none; -webkit-appearance: none; box-sizing: border-box; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center; gap: var(--ui-2);
    min-height: var(--ui-control-h); padding: 0 var(--ui-4);
    border: 1px solid transparent; border-radius: var(--ui-r-sm);
    font-family: var(--ui-font); font-size: var(--ui-fs-sm); font-weight: 600; line-height: 1;
    text-decoration: none; white-space: nowrap; margin: 0;
    transition: background var(--ui-fast), border-color var(--ui-fast), color var(--ui-fast);
}
.ui-btn--primary { background: var(--ui-accent); color: var(--ui-on-accent); }
.ui-btn--primary:hover { background: var(--ui-accent-hover); color: var(--ui-on-accent); }
.ui-btn--secondary { background: var(--ui-raised); color: var(--ui-text); border-color: var(--ui-border-strong); }
.ui-btn--secondary:hover { background: #2C2C2C; border-color: #4A4A4A; color: var(--ui-text); }
.ui-btn--ghost { background: transparent; color: var(--ui-text-2); }
.ui-btn--ghost:hover { background: var(--ui-raised); color: var(--ui-text); }
.ui-btn--danger { background: var(--ui-danger); color: #FFFFFF; }
.ui-btn--danger:hover { background: var(--ui-danger-hover); color: #FFFFFF; }
.ui-btn--sm { min-height: 28px; padding: 0 var(--ui-3); font-size: var(--ui-fs-xs); }
.ui-btn--block { width: 100%; }
.ui-btn:active { filter: brightness(0.94); }
.ui-btn:disabled, .ui-btn[aria-disabled="true"] {
    cursor: not-allowed; background: var(--ui-raised); color: var(--ui-disabled);
    border-color: var(--ui-border); filter: none;
}
.ui-btn[aria-busy="true"] { cursor: progress; opacity: 0.75; }
.ui-btn-row { display: flex; flex-wrap: wrap; gap: var(--ui-2); align-items: center; }

/* ── 14. ROW OVERFLOW MENU ─────────────────────────────────────────────── */
.ui-menu { position: relative; display: inline-block; }
.ui-menu-btn {
    all: unset; box-sizing: border-box; cursor: pointer;
    width: 32px; height: 32px; border-radius: var(--ui-r-sm);
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--ui-text-2);
}
.ui-menu-btn:hover, .ui-menu-btn[aria-expanded="true"] { background: var(--ui-raised); color: var(--ui-text); }
.ui-table tbody tr:hover .ui-menu-btn { background: rgba(255, 255, 255, 0.06); }
/* position: fixed + coordinates set by ui-kit.js, so a scrolling table
   can never clip the menu. */
.ui-menu-list {
    position: fixed; z-index: var(--ui-z-menu); top: 0; left: 0;
    min-width: 200px; max-width: min(280px, calc(100vw - 24px));
    padding: var(--ui-1); margin: 0;
    background: var(--ui-overlay); border: 1px solid var(--ui-border-strong);
    border-radius: var(--ui-r-md); box-shadow: var(--ui-shadow-pop);
    font-family: var(--ui-font);
}
.ui-menu-list[hidden] { display: none; }
.ui-menu-item {
    all: unset; box-sizing: border-box; cursor: pointer;
    display: flex; align-items: center; gap: var(--ui-2); width: 100%;
    min-height: 34px; padding: 0 var(--ui-3); border-radius: var(--ui-r-sm);
    font-size: var(--ui-fs-sm); font-weight: 500; color: var(--ui-text); text-decoration: none;
}
.ui-menu-item:hover, .ui-menu-item:focus-visible { background: rgba(255, 255, 255, 0.08); color: var(--ui-text); }
.ui-menu-item:focus-visible { outline-offset: -2px; }
.ui-menu-item--danger { color: var(--ui-bad); }
.ui-menu-item--danger:hover, .ui-menu-item--danger:focus-visible { background: var(--ui-bad-tint); color: var(--ui-bad); }
.ui-menu-item[aria-disabled="true"] { color: var(--ui-disabled); cursor: not-allowed; background: none; }
.ui-menu-sep { border: 0; height: 1px; background: var(--ui-border-strong); margin: var(--ui-1) 0; }
.ui-menu-note { padding: var(--ui-1) var(--ui-3) var(--ui-2); font-size: var(--ui-fs-xs); color: var(--ui-muted); }

/* ── 15. MODAL / CONFIRM DIALOG (native <dialog>) ──────────────────────── */
.ui-modal {
    width: min(480px, calc(100vw - 32px)); max-height: calc(100dvh - 48px);
    padding: 0; margin: auto; overflow: hidden;
    background: var(--ui-overlay); color: var(--ui-text);
    border: 1px solid var(--ui-border-strong); border-radius: var(--ui-r-lg);
    box-shadow: var(--ui-shadow-modal);
    font-family: var(--ui-font); font-size: var(--ui-fs-md); line-height: var(--ui-lh-body);
}
.ui-modal--wide { width: min(640px, calc(100vw - 32px)); }
.ui-modal::backdrop { background: rgba(0, 0, 0, 0.72); }
.ui-modal[open] { display: flex; flex-direction: column; animation: ui-modal-in var(--ui-med) var(--ui-ease); }
.ui-modal-form { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; margin: 0; }
.ui-modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--ui-3); padding: var(--ui-5) var(--ui-5) 0; }
.ui-modal-head .ui-banner-close { flex-shrink: 0; }   /* a long, wrapping title never squeezes the close button */
.ui-modal-title { font-size: var(--ui-fs-xl); font-weight: 600; line-height: var(--ui-lh-snug); text-wrap: balance; }
.ui-modal-body { padding: var(--ui-4) var(--ui-5) var(--ui-5); overflow-y: auto; color: var(--ui-text-2); }
.ui-modal-body > * + * { margin-top: var(--ui-4); }
.ui-modal-foot {
    display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--ui-2);
    padding: var(--ui-4) var(--ui-5); border-top: 1px solid var(--ui-border-strong); background: rgba(0, 0, 0, 0.18);
}
@keyframes ui-modal-in { from { opacity: 0; transform: translateY(8px) scale(0.985); } to { opacity: 1; transform: none; } }
/* A side drawer: the same native modal (focus kept inside, Escape closes it,
   the page behind is inert), docked to the right edge at full height.
   <dialog class="ui-modal ui-modal--drawer"> */
.ui-modal--drawer {
    width: min(520px, 100vw); max-width: 100vw; height: 100dvh; max-height: 100dvh;
    margin: 0 0 0 auto; border-radius: 0; border-width: 0 0 0 1px;
}
.ui-modal--drawer[open] { animation: ui-drawer-in var(--ui-med) var(--ui-ease); }
.ui-modal--drawer .ui-modal-head { padding-top: calc(var(--ui-5) + env(safe-area-inset-top, 0px)); padding-bottom: var(--ui-4); border-bottom: 1px solid var(--ui-border-strong); }
.ui-modal--drawer .ui-modal-body { flex: 1 1 auto; padding-top: var(--ui-5); }
.ui-modal--drawer .ui-modal-foot { padding-bottom: calc(var(--ui-4) + env(safe-area-inset-bottom, 0px)); }
@keyframes ui-drawer-in { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }

/* ── 16. TOAST ─────────────────────────────────────────────────────────── */
/* A toast never lies on top of the page. The toasts sit in a band at the top
   of the content pane and the page moves down by the band's height, which
   ui.js measures into --ui-toast-h (without the script: the height of one
   toast). Where they used to float, bottom right, they covered the row menus
   and the save bar for as long as they showed. */
.ui-toasts {
    position: fixed; z-index: var(--ui-z-toast);
    top: 0; right: 0; left: var(--sidebar-w, 0px);
    display: flex; flex-direction: column; gap: var(--ui-2); align-items: flex-end;
    pointer-events: none; font-family: var(--ui-font);
}
.ui-toasts:has(.ui-toast) {
    pointer-events: auto;      /* a solid band: no click reaches what has scrolled under it */
    padding: var(--ui-2) var(--ui-8);
    background: var(--ui-bg); border-bottom: 1px solid var(--ui-border);
}
body:has(.ui-toast) .shell-main { margin-top: var(--ui-toast-h, 72px); }
body:has(.ui-toast) .subtab-bar { top: var(--ui-toast-h, 72px); }
/* The page moves down to make room, wherever it is scrolled to; and a field
   or a link that is scrolled to (Tab key, #anchor) stops below the band. */
html:has(.ui-toast) { overflow-anchor: none; scroll-padding-top: calc(var(--ui-toast-h, 72px) + var(--ui-2)); }
.ui-toast {
    pointer-events: auto; width: min(480px, 100%);
    display: flex; align-items: flex-start; gap: var(--ui-3);
    padding: var(--ui-3) var(--ui-3) var(--ui-3) var(--ui-4);
    background: var(--ui-overlay); border: 1px solid var(--ui-border-strong);
    border-radius: var(--ui-r-md);
    font-size: var(--ui-fs-sm); color: var(--ui-text); line-height: var(--ui-lh-snug);
    animation: ui-toast-in var(--ui-med) var(--ui-ease);
}
.ui-toast-icon { margin-top: 1px; color: var(--ui-muted); }
.ui-toast--good .ui-toast-icon { color: var(--ui-good); }
.ui-toast--bad .ui-toast-icon  { color: var(--ui-bad); }
.ui-toast--bad { border-color: rgba(231, 76, 60, 0.5); }
.ui-toast-text { flex: 1 1 auto; min-width: 0; padding-top: 1px; }
.ui-toast-close {
    all: unset; box-sizing: border-box; cursor: pointer; flex: 0 0 auto;
    width: 24px; height: 24px; border-radius: 4px; color: var(--ui-muted);
    display: inline-flex; align-items: center; justify-content: center;
}
.ui-toast-close:hover { background: rgba(255, 255, 255, 0.08); color: var(--ui-text); }
/* One action in a toast ("Make a rule"): window.uiToast(text, tone, {label, run}). */
.ui-toast-action {
    all: unset; box-sizing: border-box; cursor: pointer; flex: 0 0 auto;
    min-height: 24px; padding: 0 var(--ui-2); border-radius: 4px;
    font-weight: 600; color: var(--ui-accent);
}
.ui-toast-action:hover { background: var(--ui-accent-tint); }
.ui-toast-action:focus-visible { outline: var(--ui-focus-width) solid var(--ui-focus-color); outline-offset: var(--ui-focus-gap); }
@keyframes ui-toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ── 17. FORM FIELD ────────────────────────────────────────────────────── */
.ui-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.ui-label { font-size: var(--ui-fs-sm); font-weight: 600; color: var(--ui-text); }
.ui-label-opt { font-weight: 400; color: var(--ui-muted); }
.ui-input, .ui-select, .ui-textarea {
    appearance: none; -webkit-appearance: none; box-sizing: border-box; width: 100%; margin: 0;
    min-height: var(--ui-control-h); padding: 0 var(--ui-3);
    background: var(--ui-sunken); color: var(--ui-text);
    border: 1px solid var(--ui-border-control); border-radius: var(--ui-r-sm);
    font-family: var(--ui-font); font-size: var(--ui-fs-md); line-height: 1.4;
    transition: border-color var(--ui-fast), background var(--ui-fast);
}
.ui-textarea { padding: var(--ui-2) var(--ui-3); min-height: 88px; resize: vertical; }
.ui-input::placeholder, .ui-textarea::placeholder { color: var(--ui-muted); opacity: 1; }
.ui-input:hover, .ui-select:hover, .ui-textarea:hover { border-color: #8A8A8A; }
.ui-input:focus, .ui-select:focus, .ui-textarea:focus { border-color: var(--ui-accent); }
.ui-select {
    padding-right: 34px; cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23B8B8B8' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 12px center;
}
.ui-select option { background: var(--ui-overlay); color: var(--ui-text); }
.ui-input:disabled, .ui-select:disabled, .ui-textarea:disabled { color: var(--ui-disabled); border-color: var(--ui-border-strong); cursor: not-allowed; }
.ui-hint { font-size: var(--ui-fs-xs); color: var(--ui-muted); line-height: var(--ui-lh-snug); }
.ui-error { font-size: var(--ui-fs-xs); color: var(--ui-bad); font-weight: 500; line-height: var(--ui-lh-snug); }
.ui-field--error .ui-input, .ui-field--error .ui-select, .ui-field--error .ui-textarea { border-color: var(--ui-bad); }
.ui-search { position: relative; }
.ui-search .ui-icon { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--ui-muted); pointer-events: none; }
.ui-search .ui-input { padding-left: 34px; }
.ui-form { display: grid; gap: var(--ui-4); }
.ui-form--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ui-form-full { grid-column: 1 / -1; }

/* Choice chips: a row of real checkboxes drawn as buttons (hours, days).
   <fieldset class="ui-choices-set"><legend class="ui-label">Days</legend>
     <div class="ui-choices"><label class="ui-choice"><input type="checkbox" name="d" value="1"><span>Mon</span></label>…</div>
   </fieldset>
   The box covers the whole chip, so the whole chip is the tap target.
   Picked = filled gold AND bold, so it reads without colour. */
.ui-choices-set { border: 0; margin-inline: 0; margin-bottom: 0; padding: 0; min-width: 0; }
.ui-choices-set > legend { padding: 0; margin-bottom: var(--ui-2); }
.ui-choices-set > .ui-hint { margin-bottom: var(--ui-2); }
.ui-choices { display: flex; flex-wrap: wrap; gap: var(--ui-1); }
.ui-choices--hours { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); }
.ui-choice { position: relative; display: inline-flex; min-width: 0; }
.ui-choice > input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.ui-choice > span {
    display: inline-flex; align-items: center; justify-content: center; width: 100%;
    min-width: 44px; min-height: 32px; padding: 0 var(--ui-2);
    border: 1px solid var(--ui-border-control); border-radius: var(--ui-r-sm);
    font-size: var(--ui-fs-sm); font-variant-numeric: tabular-nums; color: var(--ui-text-2);
    transition: background var(--ui-fast), border-color var(--ui-fast), color var(--ui-fast);
}
.ui-choices--hours .ui-choice > span { min-width: 0; }
.ui-choice > input:hover + span { border-color: var(--ui-text-2); color: var(--ui-text); }
.ui-choice > input:checked + span { background: var(--ui-accent); border-color: var(--ui-accent); color: var(--ui-on-accent); font-weight: 700; }
/* Settings > Users & Access: the role checkboxes in their groups, and the
   chips that show each person's roles in the table. */
.ui-roles-group { margin: var(--ui-2) 0 var(--ui-1); font-size: var(--ui-fs-xs); font-weight: 600; color: var(--ui-text-2); }
.ui-roles-warn { margin-top: var(--ui-2); color: var(--ui-warn); }
.ui-role-chips { display: inline-flex; flex-wrap: wrap; gap: var(--ui-1); }
/* A dangerous choice (Full access): ticked, the chip turns red, not gold, and
   its badge drops its own tint so the text reads on the red (black on --red
   5.2:1; unticked the badge is --ui-bad on its tint, 5.0:1+ on any surface). */
.ui-choice--danger > input:checked + span { background: var(--ui-bad-fill); border-color: var(--ui-bad-fill); color: var(--black); }
.ui-choice--danger > input:checked + span .ui-badge { background: transparent; color: var(--black); }
.ui-choice > input:focus-visible + span { outline: var(--ui-focus-width) solid var(--ui-focus-color); outline-offset: var(--ui-focus-gap); }

/* ── 18. TOGGLE SWITCH (a real checkbox with role="switch") ────────────── */
.ui-switch { position: relative; display: inline-flex; align-items: center; gap: var(--ui-3); cursor: pointer; min-height: 28px; }
.ui-switch-input { position: absolute; opacity: 0; width: 40px; height: 24px; margin: 0; cursor: pointer; }
.ui-switch-track {
    position: relative; flex: 0 0 auto; width: 40px; height: 24px; border-radius: var(--ui-r-full);
    background: var(--ui-sunken); border: 1px solid var(--ui-border-control);
    transition: background var(--ui-fast), border-color var(--ui-fast);
}
.ui-switch-track::after {
    content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%;
    background: var(--ui-text-2); transition: transform var(--ui-med) var(--ui-ease), background var(--ui-fast);
}
.ui-switch-input:checked + .ui-switch-track { background: var(--ui-accent); border-color: var(--ui-accent); }
.ui-switch-input:checked + .ui-switch-track::after { transform: translateX(16px); background: var(--ui-on-accent); }
.ui-switch-input:focus-visible + .ui-switch-track { outline: var(--ui-focus-width) solid var(--ui-focus-color); outline-offset: var(--ui-focus-gap); }
.ui-switch-input:disabled, .ui-switch-input:disabled ~ * { cursor: not-allowed; }
.ui-switch-input:disabled + .ui-switch-track { background: var(--ui-raised); border-color: var(--ui-border-strong); border-style: dashed; }
.ui-switch-input:disabled + .ui-switch-track::after { background: var(--ui-disabled); }
.ui-switch-text { font-size: var(--ui-fs-sm); color: var(--ui-text); }

/* ── 19. PILL NAV (second level, under the subtab bar) ─────────────────── */
.ui-pills {
    display: flex; gap: var(--ui-2); margin: 0 0 var(--ui-5);
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
    position: relative;
    padding: 2px;      /* room for the focus ring inside the scroller */
}
.ui-pills::-webkit-scrollbar { display: none; }
.ui-pill {
    display: inline-flex; align-items: center; min-height: 32px; padding: 0 var(--ui-3);
    flex: 0 0 auto;    /* never squeezed: the row scrolls instead (six project views on a phone ran the words into the edges) */
    border: 1px solid var(--ui-border-strong); border-radius: var(--ui-r-full);
    font-size: var(--ui-fs-sm); font-weight: 500; color: var(--ui-text-2);
    text-decoration: none; white-space: nowrap; background: transparent;
    transition: background var(--ui-fast), color var(--ui-fast), border-color var(--ui-fast);
}
.ui-pill:hover { background: var(--ui-raised); color: var(--ui-text); }
.ui-pill[aria-current="page"] { background: var(--ui-accent-tint); border-color: var(--ui-border-accent); color: var(--ui-accent); font-weight: 600; }

/* ── 20. FUNNEL ────────────────────────────────────────────────────────── */
/* Straight bars, length = share of the first stage. No tapered shape. */
.ui-funnel, .ui-funnel-list { display: grid; gap: var(--ui-2); }
.ui-funnel-head, .ui-funnel-stage {
    display: grid; align-items: center; column-gap: var(--ui-4);
    grid-template-columns: minmax(96px, 150px) minmax(0, 1fr) 64px minmax(96px, 140px);
}
.ui-funnel-head { font-size: var(--ui-fs-xs); font-weight: 600; color: var(--ui-muted); padding-bottom: var(--ui-1); border-bottom: 1px solid var(--ui-border); }
.ui-funnel-head > :nth-child(3), .ui-funnel-head > :nth-child(4) { text-align: right; }
.ui-funnel-name { font-size: var(--ui-fs-sm); font-weight: 500; color: var(--ui-text); min-width: 0; }
.ui-funnel-bar { height: 22px; border-radius: 4px; background: var(--ui-sunken); overflow: hidden; }
.ui-funnel-bar > span { display: block; height: 100%; width: max(var(--w, 0%), 3px); background: var(--ui-accent); border-radius: 4px; }
.ui-funnel-stage--last .ui-funnel-bar > span { background: var(--ui-good-fill); }
.ui-funnel-count { font-size: var(--ui-fs-lg); font-weight: 700; text-align: right; color: var(--ui-text); }
.ui-funnel-step { font-size: var(--ui-fs-xs); color: var(--ui-muted); text-align: right; }
.ui-funnel-step strong { color: var(--ui-text); font-weight: 600; }
.ui-funnel-total { margin-top: var(--ui-2); padding-top: var(--ui-3); border-top: 1px solid var(--ui-border); font-size: var(--ui-fs-sm); color: var(--ui-text-2); }
.ui-funnel-total strong { color: var(--ui-text); }

/* ── 21. PROGRESS TO GOAL ──────────────────────────────────────────────── */
.ui-goal { min-width: 0; }
.ui-goal-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--ui-1) var(--ui-3); }
.ui-goal-label { font-size: var(--ui-fs-md); font-weight: 600; color: var(--ui-text); }
.ui-goal-nums { margin-top: var(--ui-2); display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--ui-1) var(--ui-2); }
.ui-goal-value { font-size: var(--ui-fs-2xl); font-weight: 700; line-height: var(--ui-lh-tight); letter-spacing: -0.02em; color: var(--ui-text); }
.ui-goal-target { font-size: var(--ui-fs-md); color: var(--ui-muted); }
.ui-goal-pct { margin-left: auto; font-size: var(--ui-fs-lg); font-weight: 700; color: var(--ui-text); }
.ui-goal-track {
    position: relative; height: 10px; margin-top: var(--ui-3); margin-bottom: 28px;
    background: var(--ui-sunken); border: 1px solid var(--ui-border); border-radius: var(--ui-r-full);
}
.ui-goal-fill {
    display: block; height: 100%; width: min(var(--pct, 0%), 100%);
    background: var(--ui-accent); border-radius: var(--ui-r-full);
}
.ui-goal--done .ui-goal-fill { background: var(--ui-good-fill); }
/* Pace marker = where the number should be today */
.ui-goal-pace {
    position: absolute; top: -5px; bottom: -5px; left: min(var(--pace, 0%), 100%);
    width: 2px; margin-left: -1px; background: var(--ui-text); border-radius: 1px;
}
.ui-goal-pace::after {
    content: 'Today'; position: absolute; top: calc(100% + 3px); left: 50%; transform: translateX(-50%);
    font-size: var(--ui-fs-xs); font-weight: 600; line-height: 1; color: var(--ui-text-2); white-space: nowrap;
}
.ui-goal-pace--end::after { left: auto; right: 0; transform: none; }
.ui-goal-note { font-size: var(--ui-fs-xs); color: var(--ui-muted); line-height: var(--ui-lh-snug); }
.ui-goal-list > * + * { margin-top: var(--ui-5); padding-top: var(--ui-5); border-top: 1px solid var(--ui-border); }

/* ── 22. ATTENTION LIST ────────────────────────────────────────────────── */
.ui-attn-list { display: grid; }
.ui-attn {
    position: relative; display: flex; align-items: center; gap: var(--ui-3);
    padding: var(--ui-3) var(--ui-4); min-height: 52px;
    border-bottom: 1px solid var(--ui-border);
}
.ui-attn:last-child { border-bottom: 0; }
.ui-attn:hover { background: var(--ui-raised); }
.ui-attn-icon {
    width: 28px; height: 28px; border-radius: 50%; flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--ui-warn-tint); color: var(--ui-warn);
}
.ui-attn--bad .ui-attn-icon  { background: var(--ui-bad-tint);  color: var(--ui-bad); }
.ui-attn--info .ui-attn-icon { background: var(--ui-info-tint); color: var(--ui-info); }
.ui-attn-body { flex: 1 1 auto; min-width: 0; }
.ui-attn-text { font-size: var(--ui-fs-sm); font-weight: 500; color: var(--ui-text); line-height: var(--ui-lh-snug); }
.ui-attn-why { font-size: var(--ui-fs-xs); color: var(--ui-muted); line-height: var(--ui-lh-snug); margin-top: 1px; }
.ui-attn-link { flex: 0 0 auto; font-size: var(--ui-fs-xs); font-weight: 600; color: var(--ui-accent); text-decoration: none; white-space: nowrap; }
.ui-attn-link::after { content: ''; position: absolute; inset: 0; }
.ui-attn:hover .ui-attn-link { color: var(--ui-accent-hover); }
.ui-attn-link:focus-visible { outline: none; }
.ui-attn-link:focus-visible::after { outline: var(--ui-focus-width) solid var(--ui-focus-color); outline-offset: -2px; }

/* ── 23. ROLE EDITOR (permission groups) ───────────────────────────────── */
.ui-perm-group { background: var(--ui-surface); border: 1px solid var(--ui-border); border-radius: var(--ui-r-lg); overflow: hidden; }
.ui-perm-group + .ui-perm-group { margin-top: var(--ui-3); }
.ui-perm-head {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--ui-2) var(--ui-3);
    padding: var(--ui-3) var(--ui-4); background: var(--ui-sunken); border-bottom: 1px solid var(--ui-border);
}
.ui-perm-title { font-size: var(--ui-fs-md); font-weight: 600; color: var(--ui-text); }
.ui-perm-count { font-size: var(--ui-fs-xs); color: var(--ui-muted); }
.ui-perm-all { margin-left: auto; }
.ui-perm-row {
    display: flex; align-items: center; justify-content: space-between; gap: var(--ui-4);
    padding: var(--ui-3) var(--ui-4); border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.ui-perm-row:last-child { border-bottom: 0; }
.ui-perm-info { min-width: 0; }
.ui-perm-name { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ui-2); font-size: var(--ui-fs-sm); font-weight: 500; color: var(--ui-text); }
.ui-perm-desc { font-size: var(--ui-fs-xs); color: var(--ui-muted); line-height: var(--ui-lh-snug); margin-top: 1px; }
.ui-perm-row--locked .ui-perm-name { color: var(--ui-text-2); }
.ui-perm-lock { color: var(--ui-muted); }

/* Sticky save bar for long forms */
.ui-savebar {
    position: sticky; bottom: 0; z-index: var(--ui-z-sticky);
    display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--ui-2) var(--ui-3);
    margin-top: var(--ui-5); padding: var(--ui-3) var(--ui-4);
    background: var(--ui-overlay); border: 1px solid var(--ui-border-strong); border-radius: var(--ui-r-md);
    box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.45);
}
.ui-savebar-note { margin-right: auto; font-size: var(--ui-fs-sm); color: var(--ui-text-2); }

/* ── 24. BREAKPOINTS ───────────────────────────────────────────────────── */
/* 390 phone · 768 tablet · 1024 desktop (rail shows) · 1440 wide          */

@media (max-width: 1023.98px) {
    .ui-split, .ui-split--reverse { grid-template-columns: minmax(0, 1fr); }
    /* The rail is behind the menu button and the header is fixed: the band sits under the header. */
    .ui-toasts { top: var(--header-h, 56px); left: 0; }
    .ui-toasts:has(.ui-toast) { padding: var(--ui-2) var(--ui-4); }
    body:has(.ui-toast) .subtab-bar { top: calc(var(--header-h, 56px) + var(--ui-toast-h, 72px)); }
    html:has(.ui-toast) { scroll-padding-top: calc(var(--header-h, 56px) + var(--ui-toast-h, 72px) + var(--ui-2)); }
    .ui-strip[data-count="5"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .ui-strip[data-count="5"] > :nth-last-child(-n+2) { grid-column: auto; }
}

@media (max-width: 767.98px) {
    .ui-page-header { align-items: stretch; margin-bottom: var(--ui-4); }
    .ui-page-heading { flex-basis: 100%; }
    .ui-page-title { font-size: 1.375rem; }
    .ui-page-actions { align-items: stretch; width: 100%; }
    .ui-range { width: 100%; }
    /* Every control a thumb uses is 44px tall on a phone (QA 7.5). */
    .ui-range-item { min-height: var(--ui-control-h-touch); flex: 1 0 auto; padding: 0 6px; font-size: var(--ui-fs-xs); }
    .ui-range-note { text-align: left; }

    .ui-section { margin-top: var(--ui-6); }
    .ui-section-link { margin-left: 0; display: inline-flex; align-items: center; min-height: var(--ui-control-h-touch); }
    .ui-section-note { flex-basis: 100%; }

    .ui-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ui-2); }
    .ui-tile { padding: var(--ui-3); }
    .ui-tile-value { font-size: var(--ui-fs-xl); }
    .ui-tile--hero { padding: var(--ui-4); }
    .ui-tile--hero .ui-tile-value { font-size: var(--ui-fs-3xl); }   /* one step down, like every tile */

    .ui-strip,
    .ui-strip[data-count="3"], .ui-strip[data-count="5"], .ui-strip[data-count="6"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .ui-strip[data-count="1"] { grid-template-columns: minmax(0, 1fr); }
    .ui-strip > .ui-tile { padding: var(--ui-3); }
    .ui-strip .ui-tile-link-arrow { top: var(--ui-3); right: var(--ui-3); }
    .ui-strip .ui-tile-value { font-size: 1.375rem; }
    .ui-strip[data-count="7"] > :last-child { grid-column: auto; }
    .ui-strip[data-count="3"] > :last-child,
    .ui-strip[data-count="5"] > :last-child,
    .ui-strip[data-count="7"] > :last-child { grid-column: 1 / -1; }
    .ui-groups { grid-template-columns: minmax(0, 1fr); }
    .ui-group, .ui-group--half { grid-column: auto; }

    .ui-cols-2, .ui-form--2 { grid-template-columns: minmax(0, 1fr); }
    .ui-card { padding: var(--ui-4); }

    /* Tables scroll inside their own box. The first column stays put.
       Widths (QA 7.2): the pinned first column takes at most 34vw and the
       menu column ~52px, which leaves a window of ~180px at 390px wide. Every
       other text cell is capped to that window and wraps inside it, so each
       column can be read whole without scrolling it half out of view.
       Numbers stay on one line: they are short, and a split number misleads. */
    .ui-table--pin th:first-child, .ui-table--pin td:first-child {
        position: sticky; left: 0; z-index: 1; background: var(--ui-surface);
        box-shadow: 1px 0 0 var(--ui-border);
        max-width: 34vw; min-width: 30vw;
        white-space: normal; overflow-wrap: break-word; word-break: normal;
    }
    /* Names and emails in the pinned column wrap; nothing is cut (QA 7.3).
       The avatar is dropped there: its 44px is worth more as text. */
    .ui-table--pin td:first-child .ui-person { gap: 0; }
    .ui-table--pin td:first-child .ui-avatar { display: none; }
    .ui-table--pin td:first-child .ui-person > div,
    .ui-table--pin td:first-child :where(.ui-person-name, .ui-person-sub) { min-width: 0; overflow-wrap: break-word; }
    .ui-table--pin td:first-child.ui-wrap, .ui-table--pin td:first-child .ui-wrap { min-width: 0; }
    /* break-word, not anywhere: a column is never squeezed narrower than its
       longest word, it only breaks a word longer than the window (a URL). */
    .ui-table td:not(:first-child):not(.ui-num):not(.ui-col-menu) {
        white-space: normal; overflow-wrap: break-word;
        max-width: calc(66vw - 90px);
    }
    .ui-table td.ui-wrap { min-width: 0; }
    /* The whole header cell is the sort button: 44px tall, full width (QA 7.5). */
    .ui-table th:has(> .ui-sort) { padding: 0; }
    .ui-table .ui-sort { display: flex; width: 100%; min-height: var(--ui-control-h-touch); padding: 0 var(--ui-3); }
    .ui-table .ui-num .ui-sort { justify-content: flex-start; }
    .ui-table--pin thead th:first-child { z-index: 3; background: var(--ui-sunken); }
    .ui-table--pin tbody tr:hover td:first-child { background: var(--ui-raised); }
    /* The row menu stays put at the right edge, so it is always in reach:
       the columns between the name and the menu scroll under it. */
    .ui-table .ui-col-menu {
        position: sticky; right: 0; z-index: 1; background: var(--ui-surface);
        box-shadow: -1px 0 0 var(--ui-border);
        padding-left: var(--ui-1); padding-right: var(--ui-1);
    }
    .ui-table thead th.ui-col-menu { z-index: 3; background: var(--ui-sunken); }
    .ui-table tbody tr:hover td.ui-col-menu { background: var(--ui-raised); }
    /* The open menu hangs over the rows below it: its cell goes on top of theirs. */
    .ui-table td.ui-col-menu:has([aria-expanded="true"]) { z-index: 4; }
    .ui-hide-sm { display: none !important; }

    .ui-toolbar-grow { max-width: none; flex-basis: 100%; }
    .ui-toolbar-end { margin-left: 0; width: 100%; }
    .ui-toolbar-end .ui-btn { flex: 1 1 auto; }

    .ui-btn, .ui-input, .ui-select { min-height: var(--ui-control-h-touch); }
    .ui-btn--sm { min-height: var(--ui-control-h-touch); }
    .ui-input, .ui-select, .ui-textarea { font-size: var(--ui-fs-lg); }   /* 16px stops iOS zooming in */
    .ui-menu-btn { width: 44px; height: 44px; }
    .ui-menu-item { min-height: 44px; }
    .ui-pill { min-height: var(--ui-control-h-touch); }
    .ui-banner-close { width: 44px; height: 44px; margin: -8px -8px -8px 0; }
    .ui-modal-head .ui-banner-close { margin: -10px -10px 0 0; }
    /* The whole label is the switch's tap target, 44px tall. */
    .ui-switch { min-height: var(--ui-control-h-touch); }
    .ui-switch-input { top: 0; left: 0; width: 100%; height: 100%; }
    /* A link's tap area grows to 44px without moving the text: the padding
       adds 28px, the negative margin takes the same 28px back out of layout. */
    .ui-link { display: inline-block; min-width: 44px; padding-block: 14px; margin-block: -14px; }
    .ui-banner-link { display: inline-flex; align-items: center; min-height: var(--ui-control-h-touch); }
    summary.ui-card-title { padding-block: 11px; margin-block: -11px; }
    .ui-range-item, .ui-btn--sm { min-width: 44px; justify-content: center; }

    .ui-funnel-head { display: none; }
    .ui-funnel-list { gap: var(--ui-4); }
    .ui-funnel-stage { grid-template-columns: minmax(0, 1fr) auto; row-gap: 6px; }
    .ui-funnel-name  { grid-column: 1; grid-row: 1; }
    .ui-funnel-count { grid-column: 2; grid-row: 1; }
    .ui-funnel-bar   { grid-column: 1 / -1; grid-row: 2; height: 14px; }
    .ui-funnel-step  { grid-column: 1 / -1; grid-row: 3; text-align: left; }

    .ui-attn { flex-wrap: wrap; align-items: flex-start; padding: var(--ui-3); row-gap: var(--ui-1); }
    .ui-attn-body { flex-basis: calc(100% - 40px); }
    .ui-attn-link { flex-basis: 100%; padding-left: 40px; display: inline-flex; align-items: center; min-height: var(--ui-control-h-touch); }

    .ui-perm-all { margin-left: 0; }
    .ui-choice > span { min-height: var(--ui-control-h-touch); }
    .ui-choices--hours { grid-template-columns: repeat(6, minmax(0, 1fr)); }
    .ui-modal-foot { flex-direction: column-reverse; }
    .ui-modal-foot .ui-btn { width: 100%; }
    .ui-savebar .ui-btn { flex: 1 1 auto; }
    .ui-toasts { align-items: stretch; }
    .ui-toasts:has(.ui-toast) { padding: var(--ui-2) var(--ui-3); }
    .ui-toast { width: 100%; padding: var(--ui-1) var(--ui-1) var(--ui-1) var(--ui-3); align-items: center; }
    .ui-toasts { gap: var(--ui-1); }
    .ui-toast-close { width: 44px; height: 44px; margin: 0; }
}

/* A toast shown while a modal dialog is open. ui.js moves the toast region
   into the dialog (the top layer hides anything outside it). There it is a
   plain row at the bottom of the dialog, under the buttons, instead of the
   fixed band at the top of the screen, which on a phone lay over the dialog's
   title and its close button. The page behind does not move down for it.
   The doubled class outweighs the Tasks-page toast rules in work.css. */
dialog[open] > .ui-toasts.ui-toasts {
    position: static; order: 99; flex: 0 0 auto;
    top: auto; right: auto; bottom: auto; left: auto; max-width: none; width: auto;
    align-items: stretch; padding: 0; background: none; border: 0;
}
dialog[open] > .ui-toasts.ui-toasts:has(.ui-toast) {
    padding: var(--ui-2) var(--ui-3) var(--ui-3); pointer-events: auto;
    background: rgba(0, 0, 0, 0.18); border-top: 1px solid var(--ui-border-strong); border-bottom: 0;
}
dialog[open] > .ui-toasts.ui-toasts .ui-toast { width: 100%; }
body:has(dialog[open] > .ui-toasts .ui-toast) .shell-main { margin-top: 0; }
body:has(dialog[open] > .ui-toasts .ui-toast) .subtab-bar { top: 0; }
@media (max-width: 1023.98px) {
    body:has(dialog[open] > .ui-toasts .ui-toast) .subtab-bar { top: var(--header-h, 56px); }
}

/* ── 25. REDUCED MOTION ────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    [class*="ui-"], [class*="ui-"]::before, [class*="ui-"]::after {
        animation: none !important; transition: none !important; scroll-behavior: auto !important;
    }
}

/* ═══════════════════════════════════════════════════════════════════════
   26. LEGACY CALM-DOWN (design ruling 2: stays on).
   The only rules in this file that touch non-`ui-` classes. They make the
   pages nobody has rebuilt yet sit quietly next to the new ones: no glow, no
   lift on hover, no gradient text, no fade-in. The shell itself (rail, subtab
   bar, pill row, phone menu) is styled in dashboard.css.
   ═══════════════════════════════════════════════════════════════════════ */
body { background: var(--ui-bg); background-attachment: scroll; }

.card, .card:hover, .badge:hover { transform: none; animation: none; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
.card { background: var(--ui-surface); }
.card:hover { border-color: var(--ui-border); }
.highlight-card::before { display: none; }
.content { animation: none; }

/* Gradient text. `-webkit-text-fill-color: transparent` paints the letters
   with the background — and paints an emoji as a solid blob, because an emoji
   is a picture, not an outline. Plain text colour fixes both (criterion 42). */
.page-header h1,
.metric-value, .thermo-value, .metric-card.gold .metric-value {
    background: none; -webkit-text-fill-color: currentColor; -webkit-background-clip: border-box; background-clip: border-box;
}
.page-header h1 { color: var(--ui-text); letter-spacing: -0.015em; }
.page-sub { color: var(--ui-text-2); }

/* The legacy sheet lifts every <button> and grows every badge on hover. */
.content button:hover, .content .btn:hover, .content .badge:hover { transform: none; }

/* No sideways page scroll on a phone (criterion 30). Older tabs put wide
   tables and rows straight into a card, and lay cards out in `1fr` columns
   that grow to fit their widest child. On a phone the column may shrink, and
   a card that is still too narrow for its table scrolls INSIDE ITSELF. */
@media (max-width: 767.98px) {
    .content .grid-2, .content .grid-3, .content .grid-4 { grid-template-columns: minmax(0, 1fr); }
    .content .card { min-width: 0; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .content .table-wrapper { max-width: 100%; }
}

/* Banner on a phone: the words get the full width, the link sits under them. */
@media (max-width: 767.98px) {
    .ui-banner { flex-wrap: wrap; }
    .ui-banner-body { flex: 1 1 0; }
    .ui-banner-close { order: 2; align-self: flex-start; }
    .ui-banner-link { order: 3; flex: 0 0 100%; padding-left: calc(20px + var(--ui-3)); align-self: flex-start; }
}

/* Hyros-replacement spec, criterion 13 (QA 3.3): a long unbroken value — a
   58-character campaign name, a 60-character email — in a page description or
   a card note (the Attribution breadcrumb and the Leads "Report row" line are
   card notes) wraps instead of pushing the page sideways on a phone. */
.ui-page-desc, .ui-card-note { overflow-wrap: anywhere; }

/* Security > Findings: the status control stacks (status, note, Save) in one narrow
   cell so the table fits at 1440 and Save is never pushed off the right edge. */
.ui-inline-form { display: grid; grid-template-columns: 9.5rem; gap: var(--s-1, 4px); justify-items: start; }
.ui-inline-form .ui-select, .ui-inline-form .ui-input { width: 100%; min-width: 0; }

/* A subhead that sits between a strip or a table and the next table (Security > Assets)
   needs air above it and a little below, or it touches both. */
.ui-strip + .ui-subhead, .ui-table-wrap + .ui-subhead { margin-top: var(--ui-6); }
.ui-subhead + .ui-table-wrap { margin-top: var(--ui-2); }

/* Finance > Taxes / Cash typed-in forms: one column of fields does not need 1100px, and
   the first label should not touch the table above it. */
form.ui-form[data-fp-form] { max-width: 640px; margin-top: var(--ui-4); }
/* Daily Brief (tabs/_daily_brief.html): the Overview card and Overview > Daily Brief. */
.db-brief { display: flex; flex-direction: column; gap: var(--ui-2); }
.db-meta { font-size: var(--ui-fs-xs); color: var(--ui-muted); margin: 0; }
.db-headline { font-size: var(--ui-fs-md); font-weight: 600; margin: 0; line-height: var(--ui-lh-snug); }
.db-sub { font-size: var(--ui-fs-sm); font-weight: 600; color: var(--ui-muted); margin: var(--ui-2) 0 0; }
.db-top3, .db-sections { margin: 0; padding-left: 1.25em; display: flex; flex-direction: column; gap: var(--ui-1); line-height: 1.5; }

/* ── Security > Overview (tabs/sec_overview.html) ─────────────────────────
   The health score reads first: a big number, a 0–100 colour band, then the
   trend. The nine inputs sit in one even grid with the same freshness line. */
.sec-top { margin-bottom: var(--ui-8); }
.sec-health .ui-tile--hero .ui-tile-value { font-size: clamp(3rem, 2.2rem + 2.4vw, 4.25rem); letter-spacing: -0.04em; font-variant-numeric: tabular-nums; }
.sec-health .ui-tile--hero .ui-tile-unit { font-size: var(--ui-fs-lg); }
.sec-health--bad  .ui-tile--hero { border-color: rgba(244, 119, 106, 0.45); }
.sec-health--good .ui-tile--hero { border-color: rgba(46, 204, 113, 0.40); }
.sec-health .ui-tile--hero .ui-tile-target { font-size: var(--ui-fs-sm); font-weight: 600; color: var(--ui-text); }
.sec-band {
    position: relative; height: 8px; border-radius: 999px; overflow: hidden;
    background: linear-gradient(90deg, rgba(244,119,106,.28) 0 50%, rgba(240,160,75,.28) 50% 80%, rgba(46,204,113,.28) 80% 100%);
}
.sec-band { margin-top: var(--ui-1); }
.sec-band-svg { display: block; }
.sec-band-fill { fill: var(--ui-accent); }
.sec-health--bad  .sec-band-fill { fill: var(--ui-bad); }
.sec-health--good .sec-band-fill { fill: var(--ui-good); }
.sec-band-scale { display: flex; justify-content: space-between; margin: 0; font-size: var(--ui-fs-xs); color: var(--ui-muted); }
.sec-spark { margin: var(--ui-2) 0 0; }
.sec-formula summary { cursor: pointer; }
.sec-formula p { margin-top: var(--ui-2); }

.sec-tiles { margin-bottom: var(--ui-10); }
.sec-tiles .ui-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.sec-tiles .ui-tile-value { order: 1; }
.sec-tiles .ui-tile-head { order: 0; }
/* Freshness: the same quiet line, in the same place, on every tile. */
.sec-tiles .ui-tile-target {
    order: 3; margin-top: auto; padding-top: var(--ui-2);
    display: flex; align-items: center; gap: 6px; color: var(--ui-muted);
}
.sec-tiles .ui-tile-target::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .6; flex: none; }
.sec-tiles .ui-tile-link { order: 4; margin-top: 0; padding-top: var(--ui-2); }
@media (max-width: 767.98px) {
    .sec-tiles .ui-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ui-2); }
    .sec-tiles .ui-tile { padding: var(--ui-3); }
    .sec-top { margin-bottom: var(--ui-6); }
}

/* Record now (tabs/record_now.html): one screen to start the daily video.
   Fits 1440x900 with no scrolling; stacks at phone width. */
.rn { display: flex; flex-direction: column; gap: 12px; }
.rn-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.rn-title { font-size: clamp(40px, 4.4vw, 56px); line-height: 1; font-weight: 800; letter-spacing: -0.02em; margin: 0; color: var(--ui-text); }
.rn-date { margin: 4px 0 0; color: var(--ui-muted); font-size: 18px; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.rn-flag { color: var(--ui-warn); background: var(--ui-warn-tint); border-radius: 6px; padding: 2px 8px; font-size: 14px; }
.rn-go { display: flex; align-items: center; gap: 16px; }
.rn-timer { font-variant-numeric: tabular-nums; font-size: 40px; font-weight: 700; color: var(--ui-muted); min-width: 4ch; text-align: right; }
.rn-live .rn-timer { color: var(--ui-bad); }
.rn-btn-go:focus-visible, .rn .ui-btn:focus-visible { outline: 2px solid var(--ui-accent); outline-offset: 2px; }
.rn-btn-go { font-size: 20px; padding: 14px 28px; min-height: 56px; }
.rn-hook { margin: 0; font-size: 21px; line-height: 1.35; color: var(--ui-text); border-left: 4px solid var(--ui-accent); padding: 4px 0 4px 16px; }
.rn-grid { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 16px; }
.rn-prompter { background: var(--ui-surface); border: 1px solid var(--ui-border); border-radius: 12px; padding: 24px 28px; display: flex; flex-direction: column; min-height: 280px; outline: none; }
.rn-live .rn-prompter { border-color: var(--ui-border-accent); }
.rn-prompter:focus-visible { box-shadow: 0 0 0 2px var(--ui-accent); }
.rn-item { flex: 1; }
.rn-count { margin: 0; color: var(--ui-muted); font-size: 14px; text-transform: uppercase; letter-spacing: 0.08em; }
.rn-item-title { margin: 4px 0 12px; font-size: 44px; line-height: 1.1; font-weight: 800; color: var(--ui-text); }
.rn-talk { margin: 0 0 10px; font-size: 34px; line-height: 1.25; color: var(--ui-text); }
.rn-number { margin: 18px 0 6px; font-size: 32px; line-height: 1.25; font-weight: 700; }
.rn-number mark { background: var(--ui-accent-tint); color: var(--ui-accent); border-radius: 8px; padding: 2px 10px; box-decoration-break: clone; -webkit-box-decoration-break: clone; }
.rn-show { margin: 0; color: var(--ui-muted); font-size: 18px; }
.rn-nav { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 16px; }
.rn-hint { color: var(--ui-muted); font-size: 13px; }
.rn-side { display: flex; flex-direction: column; gap: 12px; }
.rn-check { margin: 0; border: 1px solid var(--ui-border); border-radius: 12px; padding: 12px 16px 14px; background: var(--ui-surface); }
.rn-check legend { padding: 0 6px; color: var(--ui-muted); font-size: 13px; text-transform: uppercase; letter-spacing: 0.06em; }
.rn-tick { display: flex; gap: 10px; align-items: flex-start; padding: 5px 0; font-size: 16px; line-height: 1.35; cursor: pointer; color: var(--ui-text); }
.rn-tick input { width: 20px; height: 20px; margin: 1px 0 0; accent-color: var(--ui-accent); flex: none; }
.rn-tick input:checked + span { color: var(--ui-muted); text-decoration: line-through; }
.rn-obs, .rn-done { border: 1px solid var(--ui-border); border-radius: 12px; padding: 12px 16px; background: var(--ui-surface); }
.rn-obs p, .rn-done p { margin: 4px 0; font-size: 15px; }
.rn-obs a { color: var(--ui-accent); white-space: nowrap; }
.rn-side, .rn-obs, .rn-prompter { min-width: 0; }
.rn-obs-line { display: flex; gap: 6px; align-items: baseline; }
.rn-obs-where { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rn-k { color: var(--ui-muted); font-size: 13px; }
.rn-done-row { display: flex; gap: 8px; margin-top: 6px; }
.rn-done-row input[type=url] { flex: 1; min-width: 0; min-height: 40px; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--ui-border-control); background: var(--ui-sunken); color: var(--ui-text); font-size: 15px; }
.rn-msg { min-height: 1.3em; color: var(--ui-text); word-break: break-all; }
.rn-done code, .rn-cmd code { color: var(--ui-accent); }
.rn-done code { font-size: 13px; }
.rn-package { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; border-top: 1px solid var(--ui-border); padding-top: 10px; font-size: 16px; color: var(--ui-text); }
.rn-thumb { font-weight: 700; letter-spacing: 0.02em; }
.rn-muted { color: var(--ui-muted); }
.rn-asof { margin-left: auto; font-size: 13px; }
.rn-none { background: var(--ui-surface); border: 1px solid var(--ui-border); border-radius: 12px; padding: 32px; }
.rn-none h2 { margin: 0 0 8px; font-size: 28px; }
.rn-cmd { background: var(--ui-sunken); border-radius: 8px; padding: 14px 16px; font-size: 18px; overflow-x: auto; }
@media (max-width: 1023.98px) {
  .rn-grid { grid-template-columns: 1fr; }
  .rn-prompter { min-height: 0; padding: 18px; }
  .rn-item-title { font-size: 30px; }
  .rn-talk { font-size: 24px; }
  .rn-number { font-size: 22px; }
  .rn-hook { font-size: 18px; }
  .rn-go { width: 100%; justify-content: space-between; }
  .rn-timer { font-size: 32px; }
  .rn-hint { display: none; }
  .rn-asof { margin-left: 0; }
}
/* ── Finance > AI > Usage (tabs/ai_usage.html) ──────────────────────────── */
.aiu { --aiu-chris: var(--ui-accent); --aiu-company: var(--ui-info);
       --aiu-other: var(--ui-text-2); --aiu-unknown: var(--ui-muted); }
.aiu-headline { font-size: var(--ui-fs-lg); line-height: var(--ui-lh-snug); color: var(--ui-text);
                margin: 0 0 var(--ui-4); max-width: 70ch; }
.aiu-now { margin: var(--ui-2) 0 var(--ui-4); }
.aiu-acct--chris { --c: var(--aiu-chris); }
.aiu-acct--company { --c: var(--aiu-company); }
.aiu-acct--other { --c: var(--aiu-other); }
.aiu-acct--unknown { --c: var(--aiu-unknown); }
/* Model families: neutral greys, so the bar never reads as an account split. */
.aiu-fam--opus { --c: var(--ui-text-2); }
.aiu-fam--sonnet { --c: var(--ui-muted); }
.aiu-fam--haiku, .aiu-fam--other { --c: var(--ui-border); }
.aiu-clamp { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
             line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
.aiu-share { margin: 0 0 var(--ui-6); }
.aiu-share-bar { display: flex; gap: 2px; height: 14px; border-radius: 4px; overflow: hidden;
                 background: var(--ui-sunken); margin: var(--ui-1) 0 var(--ui-2); }
.aiu-seg { display: block; height: 100%; width: max(var(--w, 0%), 3px); background: var(--c); }
.aiu-key { list-style: none; margin: var(--ui-2) 0 0; padding: 0; display: flex; flex-wrap: wrap;
           gap: var(--ui-2) var(--ui-5); font-size: var(--ui-fs-sm); color: var(--ui-text-2); }
.aiu-key li { display: inline-flex; align-items: center; gap: var(--ui-2); }
.aiu-swatch { width: 12px; height: 12px; border-radius: 3px; flex: none; background: var(--c);
              display: inline-block; }
.aiu-bars { list-style: none; margin: 0 0 var(--ui-6); padding: 0; display: grid; gap: var(--ui-2); }
.aiu-bar-row { display: grid; align-items: center; column-gap: var(--ui-4);
               grid-template-columns: minmax(140px, 240px) minmax(0, 1fr) 64px; }
.aiu-bar-name { font-size: var(--ui-fs-sm); color: var(--ui-text); overflow-wrap: anywhere; }
.aiu-bar { height: 16px; border-radius: 4px; background: var(--ui-sunken); overflow: hidden; }
.aiu-bar > span { display: block; height: 100%; width: max(var(--w, 0%), 3px);
                  background: var(--ui-accent); border-radius: 4px; }
.aiu-bar-val { font-size: var(--ui-fs-sm); font-variant-numeric: tabular-nums; text-align: right; }
.aiu-days { margin: 0 0 var(--ui-6); }
.aiu-cols { list-style: none; margin: 0; padding: 0; display: flex; align-items: stretch;
            gap: 3px; height: 160px; }
.aiu-col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: var(--ui-1); }
.aiu-col-stack { flex: 1 1 auto; display: flex; flex-direction: column-reverse; gap: 1px;
                 background: var(--ui-sunken); border-radius: 3px; overflow: hidden; }
.aiu-col-seg { display: block; flex: none; height: var(--pct, 0%); min-height: 2px; background: var(--c); }
.aiu-col-day { font-size: var(--ui-fs-xs); color: var(--ui-muted); text-align: center;
               font-variant-numeric: tabular-nums; line-height: 1; }
.aiu-cols[data-count="30"] .aiu-col:nth-child(odd) .aiu-col-day { visibility: hidden; }
.aiu-how p { margin: 0 0 var(--ui-3); max-width: 80ch; }
@media (max-width: 767.98px) {
    .aiu-bar-row { grid-template-columns: minmax(0, 1fr) auto; row-gap: var(--ui-1); }
    .aiu-bar { grid-column: 1 / -1; grid-row: 2; }
    .aiu-headline { font-size: var(--ui-fs-md); }
    .aiu-cols { height: 120px; gap: 2px; }
    .aiu-cols[data-count="30"] .aiu-col:not(:nth-child(5n)) .aiu-col-day { visibility: hidden; }
    .aiu-cols[data-count="30"] .aiu-col:nth-child(5n) .aiu-col-day { visibility: visible; }
}

/* Content calendar: today. A soft yellow wash, not a bright one, so the eye lands on it
   (Chris, 2026-10-09). Month grid: the day-number cell and the posts cell under it.
   Week list: the whole day block. */
#calendar-month td[aria-current="date"],
#calendar-month td.ui-cal-today { background: rgba(255, 221, 87, 0.13); }
#calendar-month td[aria-current="date"] { box-shadow: inset 0 2px 0 rgba(255, 221, 87, 0.55); color: var(--ui-accent); }
.ui-cal-today-block { background: rgba(255, 221, 87, 0.10); box-shadow: inset 3px 0 0 rgba(255, 221, 87, 0.55);
    border-radius: 8px; padding: 4px 12px 10px; margin: 8px -12px; }

/* Content calendar: the week grid, the day dialog and the post preview
   (Chris, 2026-10-09). Same tokens as the rest of the kit; nothing new. */
#calendar-week td[aria-current="date"],
#calendar-week td.ui-cal-today { background: rgba(255, 221, 87, 0.13); }
#calendar-week td[aria-current="date"] { box-shadow: inset 0 2px 0 rgba(255, 221, 87, 0.55); color: var(--ui-accent); }
/* Seven even columns. Narrower than 7 x 124px the grid scrolls sideways inside
   its wrapper, as the month grid does; ui.js starts it on today. */
#calendar-week { table-layout: fixed; min-width: 868px; }
#calendar-week td { vertical-align: top; white-space: normal; max-width: none; }
#calendar-week .ui-stack--tight > * + * { margin-top: var(--ui-2); }

/* A day number that opens the day's posts. */
.ui-cal-day {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 24px; min-height: 28px; padding: 0 var(--ui-1); margin: -4px 0 -4px calc(-1 * var(--ui-1));
    border-radius: var(--ui-r-sm); color: inherit; text-decoration: underline;
    text-decoration-color: var(--ui-border-control); text-underline-offset: 3px; cursor: pointer;
}
.ui-cal-day:hover { background: var(--ui-raised); color: var(--ui-text); text-decoration-color: currentColor; }

/* One post in the week grid: time and platform, then two lines of its title. */
.ui-btn.ui-cal-chip, .ui-btn.ui-cal-row {
    display: flex; flex-direction: column; align-items: flex-start; justify-content: center;
    gap: var(--ui-1); width: 100%; height: auto; min-width: 0;
    padding: var(--ui-2); text-align: left; white-space: normal; font-weight: 400;
}
.ui-cal-chip { border: 1px solid var(--ui-border); }
.ui-cal-chip:hover { border-color: var(--ui-border-strong); }
.ui-cal-chip-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ui-1) var(--ui-2); }
.ui-cal-chip-title {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
    overflow-wrap: anywhere; font-size: var(--ui-fs-xs); line-height: var(--ui-lh-snug); color: var(--ui-text-2);
}

/* The day dialog: every post of the day, one row each. */
.ui-cal-daylist > li + li { margin-top: var(--ui-2); }
.ui-btn.ui-cal-row { padding: var(--ui-3); border: 1px solid var(--ui-border); min-height: var(--ui-control-h-touch); }
.ui-cal-row:hover { border-color: var(--ui-border-strong); }
.ui-cal-row-title { font-size: var(--ui-fs-md); line-height: var(--ui-lh-snug); color: var(--ui-text); overflow-wrap: anywhere; }

/* The post dialog: the video or pictures, then the words that go out. */
.ui-cal-media {
    display: flex; justify-content: center; overflow: hidden;
    background: var(--ui-sunken); border: 1px solid var(--ui-border); border-radius: var(--ui-r-md);
}
.ui-cal-media--strip { justify-content: flex-start; gap: var(--ui-2); overflow-x: auto; padding: var(--ui-2); }
.ui-cal-file { display: block; width: 100%; max-height: min(420px, 52dvh); object-fit: contain; background: var(--black); }
video.ui-cal-file { min-height: 200px; }
.ui-cal-media--strip .ui-cal-file { width: auto; height: 240px; flex: 0 0 auto; border-radius: var(--ui-r-sm); }
.ui-cal-caption { white-space: pre-wrap; overflow-wrap: anywhere; color: var(--ui-text); max-width: 70ch; }
.ui-modal [data-ui-slot] > .ui-subhead { margin-top: var(--ui-5); }
.ui-modal [data-ui-slot] > .ui-subhead + .ui-cal-caption { margin-top: var(--ui-2); }
.ui-cal-title:focus { outline: none; }
@media (max-width: 767.98px) {
    .ui-cal-day { min-width: 44px; min-height: 44px; }
    .ui-cal-media--strip .ui-cal-file { height: 200px; }
}

/* Content calendar + Pipeline: the last booked day and the first open day of
   each channel line (Chris, 2026-10-15). The sentence on top, and the same
   two tags on their days in the grid. Kit tokens only. */
.ui-booked {
    margin: var(--ui-3) 0; padding: var(--ui-3) var(--ui-4);
    background: var(--ui-raised); border: 1px solid var(--ui-border); border-radius: var(--ui-r-md);
}
.ui-booked-line { margin: 0; line-height: 1.6; }
.ui-booked-line + .ui-booked-line { margin-top: var(--ui-2); }
.ui-cal-mark {
    display: inline-block; padding: 0 6px; border-radius: var(--ui-r-sm);
    font-size: var(--ui-fs-xs); font-weight: 600; line-height: 1.6; white-space: nowrap;
    border: 1px solid var(--ui-border-strong); color: var(--ui-text);
}
.ui-cal-mark--last { border-color: var(--ui-accent); color: var(--ui-accent); }
.ui-cal-mark--open { border-style: dashed; border-color: var(--ui-accent); color: var(--ui-text); }
td > .ui-cal-mark { display: block; width: max-content; margin-top: var(--ui-1); }

/* ── 30. KIT ADDITIONS (Books, 2026-10-10): searchable grouped select,
   date range dropdown, resizable table, row checkboxes, tree labels.
   Same tokens as everything above; nothing new in colour or size. ─────── */

/* Resizable table: fixed layout, so the columns share the width and a long
   cell is cut with "…" instead of pushing the table sideways. */
.ui-table--resize { table-layout: fixed; }
.ui-table--resize th, .ui-table--resize td { overflow: hidden; text-overflow: ellipsis; }
.ui-table--resize td > div, .ui-table--resize td > a, .ui-table--resize th > .ui-sort { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.ui-table--resize td > a { display: block; }
.ui-table--resize thead th { position: sticky; }
/* Starting widths are shares of the table, so the hints never add up to more
   than the screen. A drag sets a width in px, kept in the viewer's browser. */
.ui-w-xs { width: 5%; }
.ui-w-sm { width: 8%; }
.ui-w-md { width: 11%; }
.ui-w-lg { width: 15%; }
.ui-w-xl { width: 22%; }
.ui-col-resize {
    position: absolute; top: 0; right: 0; width: 9px; height: 100%;
    cursor: col-resize; touch-action: none; z-index: 3;
}
.ui-col-resize::after {
    content: ''; position: absolute; right: 4px; top: 25%; bottom: 25%; width: 1px;
    background: var(--ui-border-strong); transition: background var(--ui-fast);
}
.ui-col-resize:hover::after, .ui-col-resize:focus-visible::after, .ui-col-resize.is-dragging::after { background: var(--ui-accent); }
.ui-col-resize:focus-visible { outline: none; }
.ui-table-wrap--resize.is-resizing { cursor: col-resize; user-select: none; }

/* A number or name in a report that opens the rows behind it. */
.ui-cell-link { color: inherit; text-decoration: none; }
.ui-cell-link:hover, .ui-cell-link:focus-visible { color: var(--ui-accent); text-decoration: underline; text-underline-offset: 3px; }

/* Row checkboxes. */
.ui-table .ui-col-check { width: 40px; padding-right: 0; text-align: center; }
.ui-check { width: 16px; height: 16px; margin: 0; accent-color: var(--ui-accent); cursor: pointer; vertical-align: middle; }
.ui-check:disabled { cursor: not-allowed; opacity: 0.5; }

/* Tree labels: an account under its parent. */
.ui-tree { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }
.ui-tree-1 { padding-left: var(--ui-4); }
.ui-tree-2 { padding-left: var(--ui-8); }
.ui-tree-3 { padding-left: var(--ui-12); }
.ui-tree-4 { padding-left: calc(var(--ui-12) + var(--ui-4)); }
.ui-tree-5 { padding-left: calc(var(--ui-12) + var(--ui-8)); }

/* Date range dropdown. */
.ui-range-select { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--ui-2); }
.ui-range-select .ui-select { width: auto; min-width: 160px; }
.ui-range-select-custom { display: inline-flex; align-items: center; gap: var(--ui-2); color: var(--ui-muted); }
.ui-range-select-custom[hidden] { display: none; }
.ui-range-select-custom .ui-input { width: auto; min-width: 140px; }
.ui-range-select.is-live [data-ui-range-apply] { display: none; }
.ui-range-select.is-live.is-custom [data-ui-range-apply] { display: inline-flex; }

/* Searchable grouped select: the box that opens from a select or a button. */
.ui-combo-btn {
    all: unset; box-sizing: border-box; cursor: pointer; display: inline-flex; align-items: center;
    gap: var(--ui-2); max-width: 100%; min-height: 28px; padding: 0 var(--ui-2);
    border: 1px solid transparent; border-radius: var(--ui-r-sm); color: var(--ui-text);
}
.ui-combo-btn:hover, .ui-combo-btn[aria-expanded="true"] { border-color: var(--ui-border-control); background: var(--ui-sunken); }
.ui-combo-btn--muted { color: var(--ui-warn); }
.ui-combo-btn:disabled { cursor: default; color: var(--ui-muted); }
.ui-combo-btn:disabled:hover { border-color: transparent; background: none; }
.ui-combo-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.ui-combo-caret { flex: 0 0 auto; width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 5px solid var(--ui-muted); }
.ui-combo-pop {
    position: fixed; z-index: var(--ui-z-menu); top: 0; left: 0;
    width: min(360px, calc(100vw - 24px)); max-height: min(420px, 70vh);
    display: flex; flex-direction: column;
    background: var(--ui-overlay); border: 1px solid var(--ui-border-strong);
    border-radius: var(--ui-r-md); box-shadow: var(--ui-shadow-pop); font-family: var(--ui-font);
}
.ui-combo-pop[hidden] { display: none; }
.ui-combo-pop .ui-input { margin: var(--ui-2); width: calc(100% - 2 * var(--ui-2)); }
.ui-combo-list { overflow-y: auto; overscroll-behavior: contain; padding: 0 var(--ui-1) var(--ui-1); margin: 0; list-style: none; }
.ui-combo-group { padding: var(--ui-2) var(--ui-2) var(--ui-1); font-size: var(--ui-fs-xs); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ui-accent); }
.ui-combo-opt {
    padding: 6px var(--ui-3); border-radius: var(--ui-r-sm); cursor: pointer;
    font-size: var(--ui-fs-sm); color: var(--ui-text-2); overflow-wrap: anywhere;
}
.ui-combo-opt[aria-selected="true"] { color: var(--ui-accent); font-weight: 600; }
.ui-combo-opt.is-active { background: rgba(255, 255, 255, 0.08); color: var(--ui-text); }
.ui-combo-empty { padding: var(--ui-3); font-size: var(--ui-fs-sm); color: var(--ui-muted); }

/* A bar of bulk actions over a table. */
.ui-bulkbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ui-2) var(--ui-3); margin-bottom: var(--ui-3); padding: var(--ui-2) var(--ui-3); background: var(--ui-sunken); border: 1px solid var(--ui-border); border-radius: var(--ui-r-md); }
.ui-bulkbar-count { font-size: var(--ui-fs-sm); color: var(--ui-muted); }
.ui-filters { display: grid; gap: var(--ui-3); grid-template-columns: repeat(4, minmax(0, 1fr)); align-items: end; margin-bottom: var(--ui-3); }
.ui-filters .ui-field { min-width: 0; }

@media (max-width: 1023.98px) {
    .ui-filters { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 767.98px) {
    .ui-table--resize { min-width: 760px; }
    .ui-filters { grid-template-columns: minmax(0, 1fr); }
    .ui-range-select { justify-content: flex-start; }
    .ui-range-select-custom { flex-wrap: wrap; }
    .ui-check { width: 20px; height: 20px; }
    .ui-combo-btn { min-height: 40px; }
}

/* ── Automation > Machines (tabs/machines.html) ────────────────────────────
   Overview: three link cards, the totals strip, two charts. A machine's page:
   its strip, two 48-hour charts, its jobs. Charts are server-drawn SVG; the
   series colours are the dark steps of the dataviz categorical order
   (blue, orange, aqua, yellow, magenta, green), never the status colours. */
.mch { --mch-main: #3987e5; --mch-m2: #d95926; --mch-vps: #199e70; }
.mch-c--main { --c: var(--mch-main); }
.mch-c--m2 { --c: var(--mch-m2); }
.mch-c--vps { --c: var(--mch-vps); }
.mch-ai--none { --c: #5A5A5A; }
.mch-ai--local { --c: #3987e5; }
.mch-ai--groq { --c: #d95926; }
.mch-ai--claude_company { --c: #199e70; }
.mch-ai--claude_chris { --c: #c98500; }
.mch-ai--claude_api { --c: #d55181; }
.mch-ai--gpt { --c: #9085e9; }
.mch-ai--personal { --c: #8A8A8A; }
.mch-muted { color: var(--ui-muted); font-weight: 400; }
.mch-bad { color: var(--ui-bad); font-weight: 600; }
.mch-back { margin: 0 0 var(--ui-2); font-size: var(--ui-fs-sm); }
.mch-state { margin: 0 0 var(--ui-4); }

.mch-cards { list-style: none; margin: var(--ui-6) 0 var(--ui-8); padding: 0;
             display: grid; gap: var(--ui-3); grid-template-columns: repeat(3, minmax(0, 1fr)); }
.mch-card { position: relative; display: flex; flex-direction: column; gap: var(--ui-2); height: 100%;
            padding: var(--ui-5); background: var(--ui-surface); border: 1px solid var(--ui-border);
            border-radius: var(--ui-r-md); color: var(--ui-text); text-decoration: none;
            transition: border-color var(--ui-fast), background var(--ui-fast); }
.mch-card:hover { border-color: var(--ui-border-strong); background: var(--ui-raised); }
.mch-card:focus-visible { outline: var(--ui-focus-width) solid var(--ui-focus-color); outline-offset: var(--ui-focus-gap); }
.mch-card-head { display: flex; align-items: center; gap: var(--ui-2); padding-right: var(--ui-6); }
.mch-card-name { font-size: var(--ui-fs-lg); font-weight: 600; min-width: 0; overflow-wrap: anywhere; margin-right: auto; }
.mch-card-mem { display: flex; align-items: baseline; gap: var(--ui-2); margin-top: var(--ui-2); }
.mch-card-num { font-size: var(--ui-fs-3xl); font-weight: 700; line-height: var(--ui-lh-tight);
                letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.mch-card-num--none { color: var(--ui-muted); }
.mch-card .mch-muted { font-size: var(--ui-fs-sm); }
.mch-meter { display: block; height: 6px; }
.mch-meter--none { border-radius: 3px; background: var(--ui-sunken); }
.mch-meter-track { fill: var(--ui-sunken); }
.mch-meter-fill { fill: var(--ui-text-2); }
.mch-meter-fill--bad { fill: var(--ui-bad-fill); }
.mch-card-jobs { font-size: var(--ui-fs-sm); color: var(--ui-text-2); }
.mch-card-go { position: absolute; top: var(--ui-5); right: var(--ui-5); color: var(--ui-muted);
               transition: color var(--ui-fast), transform var(--ui-fast); }
.mch-card:hover .mch-card-go { color: var(--ui-accent); transform: translateX(2px); }
.mch-card--down { border-color: rgba(244, 119, 106, 0.40); }
.mch-card--asleep .mch-card-num { color: var(--ui-muted); }
.mch-asleep-note { margin: var(--ui-2) 0 var(--ui-4); color: var(--ui-text-2); }

.mch-charts { display: grid; gap: var(--ui-3); grid-template-columns: repeat(2, minmax(0, 1fr));
              margin: var(--ui-4) 0 var(--ui-8); }
.mch-panel { min-width: 0; padding: var(--ui-4) var(--ui-5); background: var(--ui-surface);
             border: 1px solid var(--ui-border); border-radius: var(--ui-r-md); }
.mch-panel > .ui-subhead { margin-bottom: var(--ui-3); }
.mch-chart { margin: 0; }
.mch-plot { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--ui-2); }
.mch-scale { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column;
             justify-content: space-between; height: 160px; font-size: var(--ui-fs-xs);
             color: var(--ui-muted); text-align: right; font-variant-numeric: tabular-nums; line-height: 1; }
.mch-svg { display: block; overflow: visible; }
.mch-grid { stroke: var(--ui-border); stroke-width: 1; vector-effect: non-scaling-stroke; }
.mch-grid--base { stroke: var(--ui-border-strong); }
.mch-ref { stroke: var(--ui-muted); stroke-width: 1.5; stroke-dasharray: 5 4; vector-effect: non-scaling-stroke; }
.mch-line { fill: none; stroke: var(--c); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round;
            vector-effect: non-scaling-stroke; }
.mch-time { display: flex; justify-content: space-between; margin: var(--ui-1) 0 0 var(--ui-8);
            font-size: var(--ui-fs-xs); color: var(--ui-muted); }
.mch-key { list-style: none; margin: var(--ui-3) 0 0; padding: 0; display: flex; flex-wrap: wrap;
           gap: var(--ui-2) var(--ui-5); font-size: var(--ui-fs-sm); color: var(--ui-text-2); }
.mch-key li { display: inline-flex; align-items: center; gap: var(--ui-2); }
.mch-key strong { color: var(--ui-text); font-variant-numeric: tabular-nums; }
.mch-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; display: inline-block; background: var(--c); }
.mch-swatch--ref { height: 0; border-top: 2px dashed var(--ui-muted); background: none; border-radius: 0; width: 14px; }
.mch-bars { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--ui-3); }
.mch-bar-row { display: grid; align-items: center; column-gap: var(--ui-3);
               grid-template-columns: minmax(80px, 140px) minmax(0, 1fr) 36px; }
.mch-bar-name { font-size: var(--ui-fs-sm); color: var(--ui-text); overflow-wrap: anywhere; }
.mch-bar { display: block; height: 14px; }
.mch-bar rect { fill: var(--c); }
.mch-bar-val { font-size: var(--ui-fs-sm); font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }
.mch-all { margin-top: var(--ui-3); }
.mch-all > summary { cursor: pointer; font-size: var(--ui-fs-sm); font-weight: 600; color: var(--ui-accent);
                     padding: var(--ui-2) 0; width: max-content; }
.mch-all > summary:hover { color: var(--ui-accent-hover); }
.mch-all[open] > summary { margin-bottom: var(--ui-2); }
@media (max-width: 1023.98px) {
    .mch-charts { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 767.98px) {
    .mch-cards { grid-template-columns: minmax(0, 1fr); gap: var(--ui-2); margin: var(--ui-4) 0 var(--ui-6); }
    .mch-card { padding: var(--ui-4); }
    .mch-card-go { top: var(--ui-4); right: var(--ui-4); }
    .mch-card-num { font-size: var(--ui-fs-2xl); }
    .mch-panel { padding: var(--ui-3); }
    .mch-bar-row { grid-template-columns: minmax(0, 1fr) auto; row-gap: var(--ui-1); }
    .mch-bar { grid-column: 1 / -1; grid-row: 2; }
}

/* Treasury > Financials: "Where these numbers come from" steps. */
.fin-steps { margin: 0; padding-left: 1.4em; display: grid; gap: var(--ui-2); color: var(--ui-text-2); line-height: var(--ui-lh-snug); }
.fin-steps strong { color: var(--ui-text); }

/* Treasury > Confirm: one card per row waiting for a yes. */
.cf-row { display: grid; gap: var(--ui-3); }
.cf-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--ui-3); }
.cf-what { margin: 0; font-weight: 600; color: var(--ui-text); overflow-wrap: anywhere; }
.cf-meta, .cf-guess { margin: 0; color: var(--ui-text-2); }
.cf-money { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cf-money--in { color: var(--ui-good, #3fb950); }
.cf-saved { margin: 0; color: var(--ui-good); font-weight: 600; }
.cf-done { opacity: 0.7; transition: opacity 0.6s; }
.cf-error[hidden] { display: none; }

/* Profit and loss (Books > Reports, Treasury > Reports): every amount in full. */
#pnlMonths th, #pnlMonths td { white-space: nowrap; }
#pnlMonths td:first-child { position: sticky; left: 0; background: var(--ui-surface, var(--ui-bg)); z-index: 1; }
