/* Noah custom styles — overrides on top of Bootstrap 5.

   Theme: Indigo / Amber. This is the visual signal that distinguishes Noah
   from its sibling app CellHub (blue/grey). Deep indigo sidebar, indigo
   primary accent, amber reserved for financial emphasis. Semantic status
   colors (good/warn/bad on badges, stat tiles) are separate from the brand
   accent — see docs/00_PROJECT.md.
   ───────────────────────────────────────────────────────────────────────── */

@import url('https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&family=Public+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap');

:root {
    --noah-ink:         #18172c;   /* body text */
    --noah-paper:       #f5f4fb;   /* body background */
    --noah-sub:         #6b6785;   /* muted text */
    --noah-border:      #e7e4f2;

    --noah-indigo:      #4f46e5;   /* primary accent */
    --noah-indigo-dark: #4338ca;   /* hover/active */
    --noah-indigo-tint: #eceafd;   /* chip background */

    --noah-gold:        #b45309;   /* financial emphasis, secondary accent */

    /* Semantic — deliberately distinct from the brand accent above */
    --noah-good:        #15803d;
    --noah-good-tint:   #eafaf0;
    --noah-bad:         #b91c1c;
    --noah-bad-tint:    #fdecec;
    --noah-warn:        #b45309;
    --noah-warn-tint:   #fdf3e7;
}

/* Body background + base typography */
body {
    background-color: var(--noah-paper);
    color: var(--noah-ink);
    font-family: 'Public Sans', system-ui, sans-serif;
}
h1, h2, h3, h4, h5, h6 {
    font-family: 'Sora', system-ui, sans-serif;
    font-weight: 700;
    letter-spacing: -0.01em;
}
.navbar-text {
    font-family: 'Sora', system-ui, sans-serif;
    font-weight: 700 !important;
}

/* Tabular figures — dollar amounts, dates, references, IDs. Apply this
   class wherever columns of numbers/dates need to line up. */
.mono {
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums;
}

/* Re-skin Bootstrap's primary to indigo so buttons, links, and badges that
   use .btn-primary / .text-primary / .bg-primary inherit the Noah accent
   without touching every template. */
.btn-primary {
    --bs-btn-bg: var(--noah-indigo);
    --bs-btn-border-color: var(--noah-indigo);
    --bs-btn-hover-bg: var(--noah-indigo-dark);
    --bs-btn-hover-border-color: var(--noah-indigo-dark);
    --bs-btn-active-bg: var(--noah-indigo-dark);
    --bs-btn-active-border-color: var(--noah-indigo-dark);
    --bs-btn-disabled-bg: var(--noah-indigo);
    --bs-btn-disabled-border-color: var(--noah-indigo);
}
.text-primary { color: var(--noah-indigo) !important; }
.bg-primary   { background-color: var(--noah-indigo) !important; }
.link-primary, a.text-primary { color: var(--noah-indigo) !important; }
.btn { border-radius: .5rem; }

/* Cards — softer border + layered shadow instead of Bootstrap's flat shadow-sm */
.card {
    border: 1px solid var(--noah-border) !important;
    border-radius: .85rem !important;
    box-shadow: 0 1px 2px rgba(24,23,44,.03), 0 6px 20px -14px rgba(24,23,44,.25) !important;
}
.card-header { background: #fff !important; }

/* Badges → dot + tinted-pill chips. Zero template changes required: every
   existing .badge.bg-* across all modules picks this up automatically. */
.badge {
    font-weight: 600;
    font-size: .72rem;
    padding: .32em .65em .32em .55em;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    gap: .35em;
}
.badge::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}
.badge.bg-success { background: var(--noah-good-tint) !important; color: var(--noah-good) !important; }
.badge.bg-danger  { background: var(--noah-bad-tint)  !important; color: var(--noah-bad)  !important; }
.badge.bg-warning { background: var(--noah-warn-tint) !important; color: var(--noah-warn) !important; }
.badge.bg-info    { background: var(--noah-indigo-tint) !important; color: var(--noah-indigo) !important; }
.badge.bg-primary { background: var(--noah-indigo-tint) !important; color: var(--noah-indigo) !important; }
.badge.bg-secondary,
.badge.bg-light {
    background: var(--noah-paper) !important;
    color: var(--noah-sub) !important;
    border: 1px solid var(--noah-border);
}

/* Count pill for card-header section counts, e.g. "Repair History (3)" */
.count-pill {
    background: var(--noah-paper);
    border: 1px solid var(--noah-border);
    color: var(--noah-sub);
    font-size: .68rem;
    font-weight: 700;
    padding: .1rem .55rem;
    border-radius: 999px;
}

/* Data tables — quiet uppercase headers, hover row, tabular alignment */
.table thead th {
    text-transform: uppercase;
    font-size: .68rem;
    letter-spacing: .06em;
    font-weight: 700;
    color: var(--noah-sub);
    background: transparent !important;
    border-bottom: 1px solid var(--noah-border) !important;
}
.table > :not(caption) > * > td {
    border-bottom-color: var(--noah-border);
}
.table-hover > tbody > tr:hover > * {
    --bs-table-hover-bg: #faf9fe;
}

/* Scorecard stat tiles — accent-striped, replaces plain centered columns.
   acc-{bad,good,warn,neutral} sets which edge color; semantic, not brand. */
.stat-tile {
    border: 1px solid var(--noah-border);
    border-left: 3px solid var(--noah-border);
    border-radius: .65rem;
    padding: .7rem .8rem;
    height: 100%;
}
.stat-tile.acc-bad     { border-left-color: var(--noah-bad); }
.stat-tile.acc-good    { border-left-color: var(--noah-good); }
.stat-tile.acc-warn    { border-left-color: var(--noah-warn); }
.stat-tile.acc-neutral { border-left-color: var(--noah-indigo); }
.stat-tile .lbl {
    font-size: .65rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--noah-sub);
    font-weight: 700;
}
.stat-tile .val {
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums;
    font-size: 1.2rem;
    font-weight: 600;
    margin-top: .3rem;
}
.stat-tile .val.text-danger  { color: var(--noah-bad) !important; }
.stat-tile .val.text-success { color: var(--noah-good) !important; }
.stat-tile .sub {
    font-size: .7rem;
    color: var(--noah-bad);
    margin-top: .15rem;
    font-weight: 600;
}

/* ─── Tenant dashboard v3 ─────────────────────────────────────────────────
   Component styles for /tenants/<id>. These live here, not in a template
   <style> block: the app's component CSS belongs in one file, and rules
   defined mid-body proved unreliable (the coverage strip lost its box and
   fill entirely). Colours carry literal fallbacks so a cell can never render
   invisible if a token fails to resolve. */

/* The hero "Tenant owes" tile — a bigger stat-tile with its own accent. */
.hero-tile {
    border: 1px solid var(--noah-border, #e7e4f2);
    border-left: 4px solid var(--noah-bad, #b91c1c);
    border-radius: .65rem;
    padding: .7rem .9rem;
    height: 100%;
    background: #fff;
}
.hero-tile.ok   { border-left-color: var(--noah-good, #15803d); }
.hero-tile.dark { border-left-color: var(--noah-warn, #b45309); }
.hero-tile .val {
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums;
    font-size: 1.6rem;
    font-weight: 600;
    margin-top: .2rem;
}

/* Attention queue — one row per thing that needs the owner. */
.attn-item {
    display: flex;
    align-items: center;
    gap: .7rem;
    border: 1px solid var(--noah-border, #e7e4f2);
    border-radius: .65rem;
    background: #fff;
    padding: .5rem .8rem;
    font-size: .85rem;
}
.attn-item .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.attn-item.warn .dot { background: var(--noah-warn, #b45309); }
.attn-item.bad  .dot { background: var(--noah-bad,  #b91c1c); }

/* Rent coverage strip — one cell per month, fill height = share received. */
.cov-strip { display: flex; gap: 3px; align-items: flex-end; flex-wrap: wrap; }
.cov-cell {
    width: 22px;
    height: 30px;
    border-radius: 3px;
    position: relative;
    border: 1px solid #d7d2ec;
    background: #fff;
    overflow: hidden;
}
.cov-cell .cov-fill {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    background: #15803d;
}
.cov-cell.partial .cov-fill { background: #d18616; }
.cov-cell.none    { border-color: #b91c1c; background: #fdecec; }
.cov-cell.unrated {
    background: repeating-linear-gradient(45deg, #fff, #fff 3px, #eeecf7 3px, #eeecf7 6px);
}
.cov-cell .cov-lbl {
    position: absolute;
    top: 1px; left: 0; right: 0;
    text-align: center;
    font-size: .5rem;
    font-weight: 700;
    color: #4b4767;
}

/* Sticky table headers need an OPAQUE background — the quiet-header rule
   above sets `background: transparent !important`, which on a sticky header
   lets the scrolling rows show straight through it. */
.sticky-head thead th {
    position: sticky; top: 0; z-index: 3;
    background: #f2f0fb !important;
    box-shadow: inset 0 -1px 0 var(--noah-border, #e7e4f2);
}
.sticky-head tfoot td {
    position: sticky; bottom: 0; z-index: 3;
    background: #f2f0fb !important;
    box-shadow: inset 0 1px 0 var(--noah-border, #e7e4f2);
}

/* A panel the attention queue jumped to, so the eye lands on it. */
@keyframes flash-attn { 0%, 100% { background: transparent; } 30% { background: #fff3cd; } }
.flash-attn { animation: flash-attn 1.4s ease-in-out; }

/* Remove number-input spinner buttons site-wide (Chrome/Edge/Safari + Firefox). */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

/* Sidebar background — deep indigo gradient replaces the old flat green. */
nav.noah-sidebar {
    background: linear-gradient(180deg, #211d4a, #191536);
}

/* Sidebar active link highlight (top-level nav). */
.sidebar .nav-link.active {
    background-color: rgba(129, 123, 255, 0.18);   /* soft indigo */
    border-left: 3px solid #8683f0;
    padding-left: calc(1rem - 3px);                /* default nav-link px is 1rem */
    color: #fff !important;
    font-weight: 600;
}

/* Sub-nav (ms-3 children) get the same accent at a lighter tint. */
.sidebar .nav-link.sb-sub-active {
    background-color: rgba(129, 123, 255, 0.14);
    border-left: 3px solid #8683f0;
    padding-left: calc(0.75rem - 3px);
    color: #fff !important;
    font-weight: 500;
}

/* Sidebar hover */
.sidebar .nav-link:hover:not(.disabled):not(.active):not(.sb-sub-active) {
    background-color: rgba(255, 255, 255, 0.08);
}

/* Sidebar — default (expanded) state */
nav.sidebar {
    width: 240px;
    min-height: 100vh;
    transition: width .15s ease;
}

/* Toggle chevron button — visible in both states */
#sb-toggle {
    background: transparent;
    border: none;
    color: rgba(255, 255, 255, .55);
    padding: .15rem .35rem;
    border-radius: .25rem;
    cursor: pointer;
    line-height: 1;
}
#sb-toggle:hover {
    color: #fff;
    background: rgba(255, 255, 255, .08);
}

/* ─── Collapsed state ─────────────────────────────────────────────── */
html.sb-collapsed nav.sidebar {
    width: 64px;
    padding-left: .5rem !important;
    padding-right: .5rem !important;
}
html.sb-collapsed nav.sidebar .sb-brand { display: none !important; }
html.sb-collapsed nav.sidebar .sb-brand-row { justify-content: center !important; }
html.sb-collapsed nav.sidebar .nav-link {
    font-size: 0 !important;
    text-align: center;
    padding-left: 0 !important;
    padding-right: 0 !important;
}
html.sb-collapsed nav.sidebar .nav-link > i {
    font-size: 1.1rem !important;
    margin-right: 0 !important;
}
html.sb-collapsed nav.sidebar .nav-link > span,
html.sb-collapsed nav.sidebar .nav-link > .badge,
html.sb-collapsed nav.sidebar .sb-hide,
html.sb-collapsed nav.sidebar hr {
    display: none !important;
}
html.sb-collapsed nav.sidebar li.ms-3 { margin-left: 0 !important; }
html.sb-collapsed nav.sidebar li.ms-3 .nav-link > i {
    font-size: .9rem !important;
    opacity: .85;
}

/* Make flash messages slightly compact */
.alert {
    padding: 0.5rem 0.75rem;
}

/* The main content column, beside the sidebar.

   min-width:0 is load-bearing, not tidying. A flex item defaults to
   min-width:auto, meaning it refuses to shrink below its content's
   min-content width — so one nowrap child (a tab strip, a balance strip, a
   wide table) makes the entire page wider than the window rather than
   scrolling inside its own box, and `overflow-x:auto` on that child cannot
   prevent it, because the child is not what grew. */
.noah-main { min-width: 0; }

/* ─── CFO: branch tab strip ───────────────────────────────────────────
   The sidebar says which part of CFO; these say which screen inside it.
   Kept visually quieter than Bootstrap's default tabs — this is a strip
   inside a page, not the page's own identity. */
.cfo-tabs {
    border-bottom: 1px solid var(--bs-border-color);
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
}
.cfo-tabs::-webkit-scrollbar { display: none; }
.cfo-tabs .nav-link {
    color: #6c757d;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    padding: .4rem .85rem;
    white-space: nowrap;
    font-size: .9rem;
}
.cfo-tabs .nav-link:hover { color: #495057; background: rgba(0, 0, 0, .03); }
.cfo-tabs .nav-link.active {
    color: #6f42c1;
    background: transparent;
    border-bottom-color: #8683f0;
    font-weight: 600;
}
.cfo-tabs .badge { font-size: .68rem; vertical-align: .1em; }

/* ─── CFO: one-row indicator strip ────────────────────────────────────
   Banking's balances + progress in a single ~76px band. It scrolls
   sideways rather than wrapping: the register below is already a long
   page, and a strip that wraps to three rows is the four-card block this
   replaced. */
.cfo-strip {
    display: flex;
    gap: .5rem;
    align-items: stretch;
    overflow-x: auto;
    padding-bottom: .25rem;
    scrollbar-width: thin;
}
.cfo-strip-gap { flex: 1 0 .5rem; }        /* pushes the stats to the right */

.cfo-chip {
    flex: 0 0 auto;
    min-width: 8.5rem;
    /* Capped so an account with a long name cannot push the rest off-screen
       on its own — the label ellipsises instead. */
    max-width: 11rem;
    padding: .4rem .7rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    background: #fff;
    text-decoration: none;
    color: inherit;
    transition: border-color .12s ease, box-shadow .12s ease;
}
.cfo-chip:hover { border-color: #8683f0; box-shadow: 0 1px 4px rgba(0, 0, 0, .07); }
.cfo-chip.is-on { border-color: #8683f0; background: rgba(134, 131, 240, .07); }
.cfo-chip-stat { min-width: 7.5rem; }
/* Same thin-mark treatment as the landing page's account bars. */
.cfo-chip-bar {
    height: 3px; border-radius: 2px; background: var(--cfo-trk); margin-top: .3rem;
}
.cfo-chip-bar > span {
    display: block; height: 100%; border-radius: 2px; background: var(--cfo-good);
}

.cfo-chip-k {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: #6c757d;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cfo-chip-v { font-size: 1.25rem; line-height: 1.2; font-weight: 600; }
.cfo-chip-s {
    font-size: .68rem;
    color: #6c757d;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ─── CFO: financial standing ─────────────────────────────────────────
   Status steps are the fixed four — never themed, never reused as a
   series colour. They pair with an icon and a label everywhere they are
   used, because warning and serious sit under 3:1 on a light surface by
   design and colour may never be the only thing carrying the meaning.
   The blue is the sequential ramp: 500 for a fill, 100 for its track. */
:root {
    /* FILL steps — for marks (bars, icons, rules). The fixed status four. */
    --cfo-good: #0ca30c;
    --cfo-warn: #fab219;
    --cfo-bad:  #d03b3b;

    /* INK steps — for TEXT, and they must be different steps. The fill amber
       sits at 1.83:1 on white: legal on a bar the icon and label also
       identify, unreadable as a numeral. These three clear 4.5:1 (7.54 /
       5.54 / 6.69), so a figure stays legible without leaning on its label. */
    --cfo-good-ink: #006300;
    --cfo-warn-ink: #8a6100;
    --cfo-bad-ink:  #b02525;

    --cfo-seq:  #256abf;   /* sequential blue, step 500 */
    --cfo-trk:  #cde2fb;   /* same ramp, step 100 — the unfilled track */
}

.cfo-standing {
    display: grid;
    /* 13rem, not 15: the health row is FIVE cards, and at 15rem the fifth
       wrapped alone onto a second line — which reads as a separate, lesser
       thing rather than the fifth of five equals. */
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: .75rem;
    align-items: stretch;
}

/* Hero figure — the single number the page leads with. Proportional
   figures, not tabular: at display sizes tabular-nums gives every digit
   the width of a 0 and the number reads loose. */
.cfo-hero {
    grid-column: span 2;
    padding: 1rem 1.25rem;
    border: 1px solid var(--bs-border-color);
    border-left: 4px solid var(--cfo-seq);
    border-radius: .5rem;
    background: #fff;
}
.cfo-hero-k {
    font-size: .72rem; text-transform: uppercase; letter-spacing: .05em;
    color: #6c757d;
}
.cfo-hero-v { font-size: 3rem; line-height: 1.05; font-weight: 600; }
.cfo-hero-s { font-size: .8rem; color: #6c757d; margin-top: .15rem; }
.cfo-hero-flow {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem 1.1rem;
    margin-top: .9rem;
    padding-top: .7rem;
    border-top: 1px solid var(--bs-border-color);
    font-size: .82rem;
}
.cfo-flow-in  { color: var(--cfo-good-ink); }
.cfo-flow-out { color: var(--cfo-bad-ink); }
.cfo-flow-net { margin-left: auto; }

.cfo-tile {
    padding: .7rem .9rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    background: #fff;
    display: flex;
    flex-direction: column;
}
.cfo-tile-k {
    font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
    color: #6c757d; font-weight: 600;
}
.cfo-tile-v { font-size: 1.6rem; line-height: 1.15; font-weight: 600; }
.cfo-tile-accts { margin: .5rem 0 .35rem; }
.cfo-tile-s { font-size: .72rem; margin-top: auto; padding-top: .35rem; }

.cfo-acct { font-size: .75rem; margin-bottom: .4rem; }
/* 3px is the "thin mark" spec: the bar is context for the figure beside
   it, never the thing being read. */
.cfo-acct-bar {
    height: 3px; border-radius: 2px; background: var(--cfo-trk); margin-top: .15rem;
}
.cfo-acct-bar > span {
    display: block; height: 100%; border-radius: 2px; background: var(--cfo-seq);
}

/* Meter — a ratio against a real limit. Nothing unbounded goes in one. */
.cfo-meter {
    padding: .7rem .9rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    background: #fff;
    text-decoration: none;
    color: inherit;
    display: block;
}
.cfo-meter:hover { border-color: #8683f0; }
.cfo-meter-k {
    font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
    color: #6c757d; font-weight: 600;
}
.cfo-meter-v { font-size: 1.6rem; line-height: 1.15; font-weight: 600; }
.cfo-meter-track {
    height: 8px; border-radius: 4px; background: var(--cfo-trk); margin: .3rem 0 .25rem;
}
.cfo-meter-fill { height: 100%; border-radius: 4px; }
.cfo-meter-s { font-size: .72rem; color: #6c757d; }

/* Health count — status colour, always with an icon and a label. */
.cfo-health {
    padding: .7rem .9rem;
    border: 1px solid var(--bs-border-color);
    border-left: 4px solid transparent;
    border-radius: .5rem;
    background: #fff;
    text-decoration: none;
    color: inherit;
    display: block;
}
.cfo-health:hover { box-shadow: 0 1px 4px rgba(0, 0, 0, .07); }
.cfo-health.is-ok  { border-left-color: var(--cfo-good); }
.cfo-health.is-ok  i,
.cfo-health.is-ok  .cfo-health-n { color: var(--cfo-good-ink); }
.cfo-health.is-bad { border-left-color: var(--cfo-bad); }
.cfo-health.is-bad i,
.cfo-health.is-bad .cfo-health-n { color: var(--cfo-bad-ink); }
.cfo-health-n { font-size: 1.6rem; line-height: 1.15; font-weight: 600; }
.cfo-health-k { font-size: .78rem; font-weight: 600; }
.cfo-health-s { font-size: .72rem; color: #6c757d; }

@media (max-width: 700px) {
    .cfo-hero { grid-column: span 1; }
    .cfo-hero-v { font-size: 2.25rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   BOARD — open threads
   ───────────────────────────────────────────────────────────────────────────
   Two colour systems, doing two different jobs, deliberately kept apart:

     KIND    identifies WHAT a card is (compliance, rent, vacancy…). Distinct
             hue per kind, DESATURATED, living on the card's left rail, its
             icon chip and its heading.
     URGENCY says how a ROW stands (overdue, due, quiet…). Saturated, small,
             always right-aligned, always icon + word — never colour alone.

   If both competed for attention neither would read, so kind is quiet and
   urgency is loud. Owner, 2026-08-19: the first version was "very functional
   but not inviting", and its Due / Needs-work / Gone-quiet split described the
   mechanism rather than the work.
   ═════════════════════════════════════════════════════════════════════════ */

:root {
    --board-crimson: #b91c1c;  --board-crimson-tint: #fdecec;
    --board-rose:    #9f1239;  --board-rose-tint:    #fdeef2;
    --board-amber:   #b45309;  --board-amber-tint:   #fdf3e7;
    --board-violet:  #7c3aed;  --board-violet-tint:  #f3ecfd;
    --board-teal:    #0f766e;  --board-teal-tint:    #e6f5f3;
    --board-indigo:  #4f46e5;  --board-indigo-tint:  #eceafd;
    --board-blue:    #0369a1;  --board-blue-tint:    #e6f2fa;
    --board-slate:   #475569;  --board-slate-tint:   #eef1f5;
}

/* ── Kind cards ─────────────────────────────────────────────────────────── */
.board-card { position: relative; overflow: hidden; }

/* The left rail is the whole identity cue. 4px reads at a glance and is small
   enough that eight of them on one screen do not become a rainbow. */
.board-card::before {
    content: ''; position: absolute; inset: 0 auto 0 0; width: 4px;
    background: var(--kind-color, var(--noah-indigo));
}
.board-card .card-body { padding-left: 1.15rem; }

.board-card__icon {
    width: 2.1rem; height: 2.1rem; border-radius: .6rem;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--kind-tint, var(--noah-indigo-tint));
    color: var(--kind-color, var(--noah-indigo));
    font-size: 1.05rem; flex-shrink: 0;
}
.board-card__title {
    font-family: 'Sora', system-ui, sans-serif; font-weight: 700;
    font-size: .95rem; letter-spacing: -0.01em; color: var(--noah-ink);
    margin: 0; line-height: 1.2;
}
.board-card__blurb { font-size: .76rem; color: var(--noah-sub); margin: .1rem 0 0; }
.board-card__count {
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums;
    background: var(--kind-tint, var(--noah-indigo-tint));
    color: var(--kind-color, var(--noah-indigo));
    font-weight: 600; font-size: .78rem;
    border-radius: 999px; padding: .12rem .55rem;
}

.board-kind--crimson { --kind-color: var(--board-crimson); --kind-tint: var(--board-crimson-tint); }
.board-kind--rose    { --kind-color: var(--board-rose);    --kind-tint: var(--board-rose-tint); }
.board-kind--amber   { --kind-color: var(--board-amber);   --kind-tint: var(--board-amber-tint); }
.board-kind--violet  { --kind-color: var(--board-violet);  --kind-tint: var(--board-violet-tint); }
.board-kind--teal    { --kind-color: var(--board-teal);    --kind-tint: var(--board-teal-tint); }
.board-kind--indigo  { --kind-color: var(--board-indigo);  --kind-tint: var(--board-indigo-tint); }
.board-kind--blue    { --kind-color: var(--board-blue);    --kind-tint: var(--board-blue-tint); }
.board-kind--slate   { --kind-color: var(--board-slate);   --kind-tint: var(--board-slate-tint); }

/* ── Rows ───────────────────────────────────────────────────────────────── */
.board-row {
    display: flex; gap: .75rem; align-items: flex-start;
    padding: .6rem .25rem; border-top: 1px solid var(--noah-border);
    transition: background-color .15s ease;
}
.board-row:first-of-type { border-top: 0; }
.board-row:hover { background: var(--noah-paper); }
.board-row__title {
    font-weight: 600; font-size: .875rem; color: var(--noah-ink);
    text-decoration: none; display: block; line-height: 1.35;
}
a.board-row__title:hover { color: var(--noah-indigo); text-decoration: underline; }
.board-row__meta { font-size: .76rem; color: var(--noah-sub); }
.board-row__note {
    font-size: .78rem; color: var(--noah-sub); margin-top: .15rem;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ── Urgency pills ──────────────────────────────────────────────────────── */
/* Icon + word, always. `color-not-only`: these must survive greyscale. */
.board-pill {
    display: inline-flex; align-items: center; gap: .28rem;
    font-size: .72rem; font-weight: 600; letter-spacing: .01em;
    border-radius: 999px; padding: .18rem .5rem; white-space: nowrap;
    border: 1px solid transparent;
}
.board-pill--overdue { background: var(--noah-bad-tint);  color: var(--noah-bad);  border-color: #f6c9c9; }
.board-pill--due     { background: var(--noah-warn-tint); color: var(--noah-warn); border-color: #f3d9b5; }
.board-pill--quiet   { background: var(--board-slate-tint); color: var(--board-slate); border-color: #dde3ec; }
.board-pill--open    { background: #fff; color: var(--noah-sub); border-color: var(--noah-border); }
.board-pill--waiting { background: #fff; color: var(--noah-sub); border-color: var(--noah-border); font-style: italic; }

/* A signal is computed, not a thread anyone owns. Marked so the difference is
   visible without reading: it has no history and cannot be noted on. */
.board-chip-signal {
    font-size: .66rem; font-weight: 600; text-transform: uppercase;
    letter-spacing: .04em; color: var(--noah-sub);
    background: var(--noah-paper); border: 1px dashed var(--noah-border);
    border-radius: .35rem; padding: .05rem .3rem;
}

/* ── The tally strip ────────────────────────────────────────────────────── */
.board-tally { display: flex; flex-wrap: wrap; gap: .5rem; }
.board-tally__item {
    display: inline-flex; align-items: baseline; gap: .4rem;
    border: 1px solid var(--noah-border); background: #fff;
    border-radius: .6rem; padding: .45rem .75rem;
}
.board-tally__n {
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums; font-weight: 600; font-size: 1.1rem;
}
.board-tally__label { font-size: .74rem; color: var(--noah-sub); }
.board-tally__item--overdue { border-color: #f6c9c9; background: var(--noah-bad-tint); }
.board-tally__item--overdue .board-tally__n { color: var(--noah-bad); }
.board-tally__item--due     { border-color: #f3d9b5; background: var(--noah-warn-tint); }
.board-tally__item--due     .board-tally__n { color: var(--noah-warn); }

/* ── Rent tile ──────────────────────────────────────────────────────────── */
.board-tile__figure {
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums;
    font-size: 1.35rem; font-weight: 600; color: var(--noah-ink); line-height: 1.1;
}
.board-tile__label {
    font-size: .72rem; color: var(--noah-sub); text-transform: uppercase;
    letter-spacing: .04em; margin-top: .15rem;
}
.board-tile__cell { padding: .35rem 0; }
.board-tile__cell + .board-tile__cell { border-left: 1px solid var(--noah-border); }
@media (max-width: 767.98px) { .board-tile__cell + .board-tile__cell { border-left: 0; } }

/* ── Empty state ────────────────────────────────────────────────────────── */
.board-empty { text-align: center; padding: 2.5rem 1rem; }
.board-empty__icon { font-size: 2rem; color: var(--noah-good); }

/* Motion: 150–300ms, and nothing at all for anyone who asked for less. */
@media (prefers-reduced-motion: reduce) {
    .board-row { transition: none; }
}

/* ── Card head + scrolling body ─────────────────────────────────────────────
   The header carries the kind's tint as a band, not just an icon. Owner,
   2026-08-21: "each of the panels.. the header should have a distinguishing
   color/tint". The band is the tint at low opacity with the rail colour
   underlining it — identity, not alarm; the urgency pills inside are still the
   only saturated thing on the card.

   The ROWS scroll, the header does not. "Maybe scroll the 4 panels so the whole
   page doesn't scroll as much?" — so a card is capped and takes its overflow
   internally, which also means eight kinds never push the rent tile off the
   bottom of the world. 20rem is about five rows: enough that most cards never
   scroll at all, short enough that the worst one cannot dominate. */
.board-card__head {
    display: flex; align-items: flex-start; gap: .55rem;
    padding: .85rem 1rem .7rem 1.15rem;
    background: var(--kind-tint, var(--noah-indigo-tint));
    border-bottom: 1px solid var(--kind-color, var(--noah-border));
}
.board-card__rows {
    padding: .35rem 1rem .6rem 1.15rem;
    max-height: 20rem; overflow-y: auto; overscroll-behavior: contain;
}
/* A scrollbar that only appears when there is something to scroll to. */
.board-card__rows::-webkit-scrollbar { width: 8px; }
.board-card__rows::-webkit-scrollbar-thumb {
    background: var(--noah-border); border-radius: 999px;
}
.board-card__none { font-size: .78rem; color: var(--noah-sub); margin: .5rem 0 .25rem; }

/* ── The filter bar ─────────────────────────────────────────────────────────
   One bar for the whole board. Chips are BUTTONS: they toggle, they say so
   with aria-pressed, and an off chip keeps its count so you can see what
   turning it back on would give you.

   Priority is deliberately NOT in the urgency palette. Red and amber mean a
   date has passed or is coming; a rank is a judgement, so it gets its own hue
   and its own shape — a square monospace letter, never a wide pill. */
.board-filters {
    display: flex; flex-wrap: wrap; align-items: center; gap: .4rem;
}
.board-filters__legend {
    font-size: .72rem; text-transform: uppercase; letter-spacing: .05em;
    color: var(--noah-sub); margin-right: .15rem;
}
.board-filters__sep {
    width: 1px; height: 1.35rem; background: var(--noah-border); margin: 0 .3rem;
}
.board-filters__reset {
    border: 0; background: none; color: var(--noah-sub);
    font-size: .74rem; text-decoration: underline; padding: .2rem .3rem;
}
.board-filters__reset:hover { color: var(--noah-ink); }

.board-chip {
    display: inline-flex; align-items: center; gap: .35rem;
    font-size: .76rem; font-weight: 600; line-height: 1;
    border: 1px solid var(--noah-border); background: #fff; color: var(--noah-sub);
    border-radius: 999px; padding: .35rem .6rem .35rem .35rem;
    transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
/* OFF is the state that has to be obvious, not ON: a board is normally
   unfiltered, so a switched-off chip is the exception and wears the strike. */
.board-chip:not(.is-on) { opacity: .55; text-decoration: line-through; }
.board-chip:hover { border-color: var(--noah-ink); }
.board-chip__key {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.15rem; height: 1.15rem; border-radius: .3rem;
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-size: .68rem; font-weight: 700;
    background: var(--noah-paper); color: var(--noah-sub);
}
.board-chip__n {
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums; font-size: .7rem; opacity: .75;
}
.board-chip--H.is-on { border-color: var(--board-violet); color: var(--board-violet); }
.board-chip--H.is-on .board-chip__key { background: var(--board-violet); color: #fff; }
.board-chip--M.is-on { border-color: var(--noah-border); color: var(--noah-ink); }
.board-chip--M.is-on .board-chip__key { background: var(--noah-paper); color: var(--noah-ink); }
.board-chip--L.is-on { border-color: var(--noah-border); color: var(--noah-sub); }
.board-chip--parked { padding-left: .6rem; }
.board-chip--parked.is-on {
    border-color: var(--board-slate); background: var(--board-slate-tint);
    color: var(--board-slate);
}

/* ── Priority mark on a row ─────────────────────────────────────────────────
   Only H and L are drawn. Medium is the default and drawing it would put a
   badge on nearly every row, which is the same as putting one on none. */
.board-pri {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.1rem; height: 1.1rem; border-radius: .3rem; flex-shrink: 0;
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-size: .66rem; font-weight: 700; line-height: 1;
}
.board-pri--H { background: var(--board-violet); color: #fff; }
.board-pri--M { background: var(--noah-paper); color: var(--noah-sub); }
.board-pri--L {
    background: #fff; color: var(--noah-sub);
    border: 1px dashed var(--noah-border);
}

/* Parked: the quietest thing on the board, and hidden by default anyway. */
.board-pill--parked {
    background: var(--noah-paper); color: var(--noah-sub);
    border-color: var(--noah-border); font-style: italic;
}
.board-tally__item--parked { opacity: .8; }

.board-empty__filtered {
    text-align: center; color: var(--noah-sub); font-size: .82rem;
}

/* ── One thread: the page header ────────────────────────────────────────────
   The detail page opens with the kind stated in its own colour, so the answer
   to "what am I looking at" arrives before the title has to be read. */
.board-thread { overflow: hidden; }
.board-thread__head {
    display: flex; align-items: center; gap: .6rem;
    padding: .8rem 1rem;
    background: var(--kind-tint, var(--noah-indigo-tint));
    border-bottom: 1px solid var(--kind-color, var(--noah-border));
}
.board-thread__kind {
    font-family: 'Sora', system-ui, sans-serif; font-weight: 700;
    font-size: .9rem; color: var(--kind-color, var(--noah-ink)); line-height: 1.2;
}

/* ── Section headers on the thread page ─────────────────────────────────────
   ROLE COLOURS, NOT KIND COLOURS. Four identical grey CAPS labels made every
   box on this page look equally important, and the two that END a thread
   looked exactly like the two that describe it. So: link = slate, write =
   indigo, attach = teal, rank = violet, resolve = green, defer = amber. Each
   carries an icon as well, because colour alone is not a signal. */
.board-sec {
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
    padding: .6rem .95rem;
    background: var(--sec-tint, var(--noah-paper));
    border-bottom: 1px solid var(--noah-border);
    border-left: 3px solid var(--sec-color, var(--noah-border));
}
.board-sec > i { color: var(--sec-color, var(--noah-sub)); font-size: .95rem; }
.board-sec > span {
    font-family: 'Sora', system-ui, sans-serif; font-weight: 700;
    font-size: .82rem; color: var(--noah-ink);
}
.board-sec > small { font-size: .72rem; color: var(--noah-sub); }
.board-sec--link  { --sec-color: var(--board-slate);  --sec-tint: var(--board-slate-tint); }
.board-sec--write { --sec-color: var(--board-indigo); --sec-tint: var(--board-indigo-tint); }
.board-sec--file  { --sec-color: var(--board-teal);   --sec-tint: var(--board-teal-tint); }
.board-sec--rank  { --sec-color: var(--board-violet); --sec-tint: var(--board-violet-tint); }
.board-sec--close { --sec-color: var(--noah-good);    --sec-tint: var(--noah-good-tint); }
.board-sec--park  { --sec-color: var(--board-amber);  --sec-tint: var(--board-amber-tint); }

/* One step in the narrative. The rail makes a list of notes read as a
   sequence rather than as a stack of unrelated sentences. */
.board-step {
    position: relative; padding: .45rem 0 .5rem .85rem;
    border-bottom: 1px solid var(--noah-border); font-size: .875rem;
}
.board-step:last-child { border-bottom: 0; }
.board-step::before {
    content: ''; position: absolute; left: .15rem; top: .75rem;
    width: .4rem; height: .4rem; border-radius: 50%;
    background: var(--board-indigo);
}

.board-file {
    display: flex; align-items: center; gap: .25rem;
    padding: .4rem 0; border-bottom: 1px solid var(--noah-border);
    font-size: .84rem;
}
.board-file:last-of-type { border-bottom: 0; }

/* The short explanations under Record and Park. The owner asked what these
   buttons do; the answer belongs beside the button, not in a doc. */
.board-note-list {
    list-style: none; padding: 0; margin: 0;
    font-size: .75rem; color: var(--noah-sub); line-height: 1.45;
}
.board-note-list li { position: relative; padding-left: .8rem; margin-top: .3rem; }
.board-note-list li::before {
    content: '·'; position: absolute; left: .2rem; font-weight: 700;
}

/* Rank picker: three buttons, one press, no save step. */
.board-prigroup { display: flex; gap: .4rem; }
.board-prigroup__btn {
    flex: 1; display: inline-flex; align-items: center; justify-content: center;
    gap: .35rem; padding: .45rem .3rem;
    border: 1px solid var(--noah-border); background: #fff;
    border-radius: .5rem; font-size: .78rem; font-weight: 600;
    color: var(--noah-sub);
}
.board-prigroup__btn:hover { border-color: var(--noah-ink); color: var(--noah-ink); }
.board-prigroup__btn.is-on {
    border-color: var(--board-violet); background: var(--board-violet-tint);
    color: var(--board-violet);
}
.board-prigroup__btn.is-on .board-chip__key {
    background: var(--board-violet); color: #fff;
}

@media (prefers-reduced-motion: reduce) {
    .board-chip { transition: none; }
}


/* ── Kind picker ────────────────────────────────────────────────────────────
   Opening an item starts with choosing among eight nouns. A bare dropdown made
   the owner ask what they meant, so every option shows its definition and a
   concrete example, and the whole vocabulary is visible at once instead of
   hidden behind a click. Reuses the board's kind tones so the choice made here
   looks like the card it will land in. */
.board-kindpick {
    display: flex; gap: .6rem; align-items: flex-start; width: 100%; height: 100%;
    border: 1px solid var(--noah-border); border-radius: .7rem;
    padding: .7rem .8rem; cursor: pointer; background: #fff;
    transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}
.board-kindpick:hover { border-color: var(--kind-color, var(--noah-indigo)); }

/* .btn-check is visually hidden by Bootstrap but stays focusable, so the ring
   has to be drawn on the label — never remove it. */
.btn-check:focus-visible + .board-kindpick {
    outline: 2px solid var(--noah-indigo); outline-offset: 2px;
}
.btn-check:checked + .board-kindpick {
    border-color: var(--kind-color, var(--noah-indigo));
    background: var(--kind-tint, var(--noah-indigo-tint));
    box-shadow: inset 0 0 0 1px var(--kind-color, var(--noah-indigo));
}

.board-kindpick__label {
    display: block; font-family: 'Sora', system-ui, sans-serif;
    font-weight: 700; font-size: .875rem; color: var(--noah-ink); line-height: 1.2;
}
.board-kindpick__blurb {
    display: block; font-size: .76rem; color: var(--noah-sub); margin-top: .1rem;
}
.board-kindpick__eg {
    display: block; font-size: .72rem; color: var(--noah-sub);
    opacity: .85; margin-top: .2rem; font-style: italic;
}

@media (prefers-reduced-motion: reduce) {
    .board-kindpick { transition: none; }
}

/* The trio picker on the item form.

   Owner, 2026-08-20: "Property, Tenant and company trio need to work better..
   maybe a field, I type Newsome, it fills all 3?" One name resolves to one
   row, and this card shows the three facts that follow from it. The slot the
   item actually BINDS to is ringed, because the other two are context — the
   form must not read as though it filed the thread in three places. */
.board-bind {
    border: 1px solid var(--noah-border); border-radius: .7rem;
    background: var(--noah-paper); padding: .7rem .8rem;
}
.board-bind[hidden] { display: none; }

.board-bind__slots { display: flex; flex-wrap: wrap; gap: .5rem; }
.board-bind__slot {
    flex: 1 1 9rem; min-width: 0;
    border: 1px solid var(--noah-border); border-radius: .5rem;
    background: #fff; padding: .4rem .55rem;
}
.board-bind__k {
    display: block; font-size: .68rem; letter-spacing: .04em;
    text-transform: uppercase; color: var(--noah-sub);
}
.board-bind__v {
    display: block; font-size: .84rem; font-weight: 600;
    color: var(--noah-ink); overflow-wrap: anywhere;
}
.board-bind__slot.is-empty .board-bind__v {
    font-weight: 400; color: var(--noah-sub);
}

/* Hidden until the slot owns the item — one ring per card, never three. */
.board-bind__owns { display: none; }
.board-bind__slot.is-bound {
    border-color: var(--noah-indigo); background: var(--noah-indigo-tint);
    box-shadow: inset 0 0 0 1px var(--noah-indigo);
}
.board-bind__slot.is-bound .board-bind__owns {
    display: inline-block; margin-top: .15rem;
    font-size: .66rem; letter-spacing: .04em; text-transform: uppercase;
    font-weight: 700; color: var(--noah-indigo);
}

.board-bind__foot {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: .75rem; margin-top: .5rem;
}
.board-bind__note { margin: 0; font-size: .76rem; color: var(--noah-sub); }
.board-bind__note--warn { color: var(--noah-warn); font-weight: 600; }

/* The suggestion list, drawn on the body with fixed positioning (see the
   template) so no scrolling ancestor can clip it. */
.board-bind__list {
    position: fixed; z-index: 1080; display: none;
    max-height: 17rem; overflow: auto; min-width: 20rem;
}
.board-bind__tag {
    font-size: .64rem; letter-spacing: .04em; text-transform: uppercase;
    white-space: nowrap; color: var(--noah-sub);
    border: 1px solid var(--noah-border); border-radius: .35rem;
    padding: 0 .3rem;
}
.board-bind__manual summary { cursor: pointer; }

/* Entity links on a board row. Muted until hovered: the title is the primary
   target and two competing blue links per row would fight it. */
.board-row__entity {
    color: var(--noah-sub); text-decoration: none;
    border-bottom: 1px dotted transparent;
}
.board-row__entity i { margin-right: .25rem; }
.board-row__entity:hover {
    color: var(--noah-indigo); border-bottom-color: var(--noah-indigo);
}

/* ── Universal search (docs/modules/search/00_search.md) ─────────────────
   The box sits in the top bar on every page. The panel is absolutely
   positioned inside the input's wrapper rather than fixed on the body: the
   header is not a scrolling ancestor, so there is nothing here to clip it,
   and staying in flow keeps it glued to the input on resize. */
.us-box { width: min(28rem, 46vw); }
.us-box .form-control { border-radius: 999px; background: var(--noah-paper); }
.us-box .form-control:focus { background: #fff; }

.us-icon {
    position: absolute; left: .9rem; top: 50%; transform: translateY(-50%);
    color: var(--noah-sub); pointer-events: none; font-size: .9rem;
}
/* The hint fades out once you are typing — it has done its teaching. */
.us-kbd {
    position: absolute; right: .55rem; top: 50%; transform: translateY(-50%);
    font-size: .62rem; color: var(--noah-sub); background: #fff;
    border: 1px solid var(--noah-border); border-radius: .3rem;
    padding: .05rem .3rem; pointer-events: none;
}
.us-box .form-control:focus ~ .us-kbd { opacity: 0; }

.us-panel {
    display: none; position: absolute; z-index: 1080;
    top: calc(100% + .35rem); left: 0; right: 0;
    max-height: 24rem; overflow-y: auto;
    background: #fff; border: 1px solid var(--noah-border);
    border-radius: .6rem;
}
.us-panel.show { display: block; }

/* Group headers are labels, not rows — they must never look clickable. */
.us-group {
    font-size: .64rem; letter-spacing: .06em; text-transform: uppercase;
    color: var(--noah-sub); background: var(--noah-paper);
    border-bottom: 1px solid var(--noah-border);
}
/* .active is set by the keyboard handler; hover mirrors it so mouse and
   keyboard agree about what "the selected row" looks like. */
.us-panel .list-group-item.active,
.us-panel .list-group-item:hover {
    background: var(--noah-indigo-tint); color: var(--noah-ink);
    border-color: var(--noah-border);
}

/* ═══════════════════════════════════════════════════════════════════════════
   REPAIRS AGAINST THE BUILD — the property panel and /cfo/repairs
   ───────────────────────────────────────────────────────────────────────────
   One class per chart ROLE (`rx-<role>`), and `report_charts.ROLES` names
   every one; a test holds the two lists together, so a role without a rule
   here fails the suite instead of rendering a black mark.

     build        what a house cost to build out — a quiet stone, context
     repair       what it has cost to fix since — the one strong hue
     repair-soft  the part of that which is not wear: turnover and upkeep
     trade-*      seven trade groups, the validated categorical order
                  (blue, orange, aqua, yellow, magenta, green) plus a grey
                  catch-all. The ORDER is what passed the colour-blind check
                  between neighbours — `repair_economics.TRADE_GROUPS` keeps it.

   Three trade hues sit under 3:1 on white, which is why every chart that uses
   them prints a legend with the dollar figure beside each swatch.
   ═════════════════════════════════════════════════════════════════════════ */
:root {
    --rx-build:       #c3bfd2;
    --rx-repair:      #4a3aa7;
    --rx-repair-soft: #bdb4ee;
    --rx-band:        rgba(110, 104, 150, .11);
    --rx-trade-plumb: #2a78d6;
    --rx-trade-heat:  #eb6834;
    --rx-trade-appl:  #1baf7a;
    --rx-trade-env:   #eda100;
    --rx-trade-gen:   #e87ba4;
    --rx-trade-upk:   #008300;
    --rx-trade-oth:   #b1afbe;
    --rx-grid:        #ebeaf2;
    --rx-axis:        #c8c6d6;
    --rx-muted:       #7c7a92;
}

.rx-build        { fill: var(--rx-build);       background: var(--rx-build); }
.rx-repair       { fill: var(--rx-repair);      background: var(--rx-repair); }
.rx-repair-soft  { fill: var(--rx-repair-soft); background: var(--rx-repair-soft); }
.rx-trade-plumb  { fill: var(--rx-trade-plumb); background: var(--rx-trade-plumb); }
.rx-trade-heat   { fill: var(--rx-trade-heat);  background: var(--rx-trade-heat); }
.rx-trade-appl   { fill: var(--rx-trade-appl);  background: var(--rx-trade-appl); }
.rx-trade-env    { fill: var(--rx-trade-env);   background: var(--rx-trade-env); }
.rx-trade-gen    { fill: var(--rx-trade-gen);   background: var(--rx-trade-gen); }
.rx-trade-upk    { fill: var(--rx-trade-upk);   background: var(--rx-trade-upk); }
.rx-trade-oth    { fill: var(--rx-trade-oth);   background: var(--rx-trade-oth); }
.rx-band         { fill: var(--rx-band);        background: var(--rx-band); }

/* A 2px surface gap between ring slices and around scatter marks — never a
   border drawn in a colour of its own. */
.rx-gap, .rx-ring-edge { stroke: #fff; stroke-width: 2; }
/* The hover target behind a column or a row — bigger than the mark, and
   faintly lit so the reader can see which one the tooltip belongs to. */
.rx-hit  { fill: transparent; }
.rx g:hover > .rx-hit { fill: rgba(110, 104, 150, .07); }

.rx-chart { width: 100%; height: auto; display: block; overflow: visible; }
/* The full-card charts are drawn 1000 wide. On a phone they scroll sideways
   in their own box rather than shrink their labels to 4px. */
.rx-scroll { overflow-x: auto; }
.rx-wide   { min-width: 680px; }
.rx-chart text, .rx-ring text { font-family: inherit; }
.rx-grid  { stroke: var(--rx-grid); stroke-width: 1; }
.rx-base  { stroke: var(--rx-axis); stroke-width: 1; }
.rx-ax    { fill: var(--rx-muted); font-size: 10.5px; font-variant-numeric: tabular-nums; }
.rx-ax-t  { fill: var(--noah-sub); font-size: 11px; }
.rx-band-l { fill: var(--noah-sub); font-size: 9.5px; letter-spacing: .05em; }
.rx-quad  { fill: var(--rx-muted); font-size: 11px; font-style: italic; }
.rx-pt    { fill: var(--noah-ink); font-size: 12px; font-weight: 600; }
.rx-row-l { fill: var(--noah-ink); font-size: 12.5px; font-weight: 600; }
.rx-row-s { fill: var(--rx-muted); font-size: 10.5px; }
.rx-val   { fill: var(--noah-ink); font-size: 11px; font-variant-numeric: tabular-nums; }
.rx-pct   { fill: var(--noah-ink); font-size: 16px; font-weight: 700; }

/* Figure strip — the headline numbers, one rule between each. */
.rx-strip {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
    border-block: 1px solid var(--noah-border); margin-bottom: .75rem;
}
.rx-strip-inline { border: 0; margin: 0; grid-template-columns: repeat(4, auto); }
.rx-fig {
    display: grid; grid-template-rows: auto 1fr auto; gap: .1rem;
    padding: .6rem 1rem .6rem 0;
}
.rx-fig + .rx-fig { padding-left: 1rem; border-left: 1px solid var(--noah-border); }
.rx-fig small {
    font-size: .68rem; text-transform: uppercase; letter-spacing: .06em;
    color: var(--noah-sub); font-weight: 600;
}
.rx-fig b     { font-size: 1.35rem; font-weight: 700; line-height: 1.2; }
.rx-fig span  { font-size: .74rem; color: var(--noah-sub); }
.rx-fig.is-key b { color: var(--rx-repair); }
.rx-strip-inline .rx-fig b { font-size: 1.1rem; }

.rx-note { font-size: .82rem; color: var(--noah-sub); margin-bottom: 1rem; }
.rx-note b { color: var(--noah-ink); }
.rx-open { background: var(--rx-repair); color: #fff; font-weight: 500; }
.rx-foot { font-size: .74rem; color: var(--rx-muted); margin: .25rem 0 0; }
.rx-h {
    font-size: .7rem; text-transform: uppercase; letter-spacing: .08em;
    color: var(--noah-sub); font-weight: 600; margin-bottom: .5rem;
}

.rx-legend { display: flex; flex-wrap: wrap; gap: .25rem 1rem; font-size: .76rem; color: var(--noah-sub); }
.rx-legend span { display: inline-flex; align-items: center; gap: .4rem; }
.rx-sw { display: inline-block; width: 11px; height: 11px; border-radius: 3px; flex: none; }
.rx-sw-round { border-radius: 50%; }
.rx-sw-diamond { border-radius: 1px; transform: rotate(45deg) scale(.85); }
.rx-sw-line { outline: 1px solid var(--noah-border); }

/* The ring and its legend — the legend carries every dollar figure. */
.rx-ring-row { display: grid; grid-template-columns: 140px minmax(0, 1fr); gap: 1rem; align-items: center; }
.rx-ring { width: 140px; height: 140px; display: block; }
.rx-ring-v { fill: var(--noah-ink); font-size: 17px; font-weight: 700; }
.rx-ring-k { fill: var(--rx-muted); font-size: 9px; letter-spacing: .08em; }
.rx-dl { display: grid; gap: .3rem; font-size: .78rem; }
.rx-dl-i { display: grid; grid-template-columns: 11px minmax(0, 1fr) auto 2.6rem; gap: .1rem .5rem; align-items: baseline; }
.rx-dl-i .rx-sw { transform: translateY(1px); }
.rx-dl-v { font-variant-numeric: tabular-nums; text-align: right; }
.rx-dl-p { font-variant-numeric: tabular-nums; text-align: right; color: var(--rx-muted); }
.rx-dl-s { grid-column: 2 / -1; font-size: .7rem; color: var(--rx-muted); margin-top: -.15rem; }

.rx-jobs { display: grid; }
.rx-job {
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: .6rem;
    padding: .4rem 0; border-top: 1px solid var(--noah-border);
    align-items: baseline; font-size: .84rem;
}
.rx-job-n { font-size: .74rem; color: var(--rx-muted); text-decoration: none; font-variant-numeric: tabular-nums; }
.rx-job-n:hover { color: var(--rx-repair); text-decoration: underline; }
.rx-job-t { overflow-wrap: anywhere; }
.rx-job-t small { color: var(--rx-muted); margin-left: .35rem; }
.rx-job-a { font-variant-numeric: tabular-nums; }
.rx-tag {
    font-size: .62rem; letter-spacing: .06em; text-transform: uppercase;
    background: var(--noah-indigo-tint); color: var(--noah-sub);
    padding: .05rem .4rem; border-radius: .25rem; margin-left: .35rem; white-space: nowrap;
}

@media (max-width: 575.98px) {
    .rx-ring-row { grid-template-columns: 1fr; justify-items: center; }
    .rx-dl { width: 100%; }
    .rx-strip-inline { grid-template-columns: repeat(2, auto); }
}
