/* ============================================================
   Vantage brand language (from the marketing site), introduced
   surface by surface. Pilot surface: the mobile bottom navigation
   and its full-screen menu. Nothing here touches desktop or any
   other screen; later phases re-point --lms-* tokens instead of
   restyling screens one by one.

   Sources of truth: the marketing site's globals.css palette
   (base #0a1114, hairline borders, lavender accent, gradient
   stops purple/warm/amber used sparingly) and its Satoshi +
   General Sans type pairing.
   ============================================================ */

@font-face {
    font-family: 'Satoshi';
    src: url('/fonts-lms/Satoshi-Bold.woff2') format('woff2');
    font-weight: 700;
    font-display: swap;
}
@font-face {
    font-family: 'Satoshi';
    src: url('/fonts-lms/Satoshi-Medium.woff2') format('woff2');
    font-weight: 500;
    font-display: swap;
}
@font-face {
    font-family: 'General Sans';
    src: url('/fonts-lms/GeneralSans-Regular.woff2') format('woff2');
    font-weight: 400;
    font-display: swap;
}
@font-face {
    font-family: 'General Sans';
    src: url('/fonts-lms/GeneralSans-Medium.woff2') format('woff2');
    font-weight: 500;
    font-display: swap;
}

/* Light is the app default; html.dark-mode overrides, mirroring the
   marketing site's two palettes. */
:root {
    --vantage-bg:       #fafafa;
    --vantage-surface:  #ffffff;
    --vantage-text:     #101418;
    --vantage-text-2:   #5b656d;
    --vantage-text-3:   #6a737b;
    --vantage-line:     rgba(16, 20, 24, 0.12);
    --vantage-line-2:   rgba(16, 20, 24, 0.06);
    --vantage-fill:     rgba(16, 20, 24, 0.045);
    --vantage-fill-2:   rgba(16, 20, 24, 0.09);
    --vantage-accent:   #101418;
    /* The ground under the shell's furniture, the side navigation above all.
       It follows the card surface in every theme but OLED, where a surface a
       shade off black defeats the point of the theme across the largest area
       on screen. Declared as a reference, so it resolves against whichever
       theme is on the root rather than freezing this one's value. */
    --vantage-chrome:   var(--vantage-surface);
    --vantage-brand-a:  #7c5cd6;
    --vantage-brand-b:  #d2603d;
    --vantage-brand-c:  #d9971f;
    --vantage-font-heading: 'Satoshi', 'Hanken Grotesk', sans-serif;
    --vantage-font-body:    'General Sans', 'Hanken Grotesk', sans-serif;
    --lms-success-ink: #12703a;
    --lms-warning-ink: #8a4b04;
    /* What attention becomes when colour-safe semantics are on. Amber and
       red fall 30 to 38 apart in sRGB under every dichromacy, which reads
       as one colour, and they are the arrears triage. Violet is 86 away.
       Named per scheme so the toggle only has to point at it. */
    --lms-warning-safe: #6a3fb0;
    --lms-danger-ink: #b91c1c;
}
/* --vantage-accent is the product's accent, and it is deliberately neutral.
   The marketing site keeps two: --accent (#cbb2ff, purple) which it uses on
   its own chrome, navbar and admin charts, and --lms-accent (#fafafa) which is
   what its rendering of this product uses to mark a selected row. The purple
   belongs to the website's hero gradient, described in its own stylesheet as
   "pulled from the grainy purple/amber hero asset", not to the application.
   Meaning-bearing colour in here is the semantic set instead: amber for work
   waiting, red for a breach, green for a pass. */

/* The shell behind the layout follows the palette. Legacy --lms-bg is
   re-pointed per surface rather than globally, so without this the body stayed
   on dark-mode.css's fixed #0a0a0c under every dark theme. It is normally
   covered by the sidebar and panel, but against a true black theme any sliver
   of it shows as a grey edge. */
html.dark-mode body,
html[data-theme] body,
/* The layout too, not only the body. lms.css paints it from legacy --lms-bg,
   which dark-mode.css fixes at #0a0a0c whichever theme is on the root, so an
   OLED screen carried three different blacks: the page, the shell furniture,
   and this. It shows in the gap beside the resize handle and anywhere the
   panels do not quite meet. */
html.dark-mode .lms-layout,
html[data-theme] .lms-layout {
    background-color: var(--vantage-bg);
}

/* ── Themes ──────────────────────────────────────────────────
   A theme only re-points these tokens, so every branded surface
   follows without any per-screen work. html.dark-mode stays in
   step for the legacy --lms-* sheet; see js-lms/settings.js.

   Graphite is the default: neutral greys with no colour cast, the
   scheme most desktop tools use, with the Vantage lavender kept as
   the accent so the product still reads as ours. */
html.dark-mode,
html[data-theme="graphite"] {
    --vantage-bg:       #1b1b1b;
    --vantage-surface:  #212121;
    --vantage-text:     #e8e8e8;
    --vantage-text-2:   #a1a1a1;
    --vantage-text-3:   #8b8b8b;
    --vantage-line:     rgba(255, 255, 255, 0.11);
    --vantage-line-2:   rgba(255, 255, 255, 0.065);
    --vantage-fill:     rgba(255, 255, 255, 0.05);
    --vantage-fill-2:   rgba(255, 255, 255, 0.10);
    --vantage-accent:   #fafafa;
    --vantage-brand-a:  #b18cff;
    --vantage-brand-b:  #e88b6c;
    --vantage-brand-c:  #f5b14c;
    --lms-success-ink: var(--lms-success-text);
    --lms-warning-ink: var(--lms-warning-text);
    --lms-warning-safe: #b394f0;
    --lms-danger-ink: var(--lms-danger-text);
}

/* True black, for OLED panels where an unlit pixel draws no power and renders
   as an actual black rather than a dark grey. Surfaces and lines have to work
   harder than in Graphite: against #000 a 5% white fill is nearly invisible,
   so fills and lines are lifted, and the surface steps up rather than down. */
html[data-theme="oled"] {
    --vantage-bg:       #000000;
    --vantage-surface:  #0b0b0b;
    /* The shell's furniture goes to true black. The side navigation is the
       largest continuous area on screen and it was the one part of an OLED
       theme that was not black; structure inside it comes from the hairlines,
       which this theme already lifts to 0.16 and 0.10 to carry exactly that. */
    --vantage-chrome:   #000000;
    --vantage-text:     #f2f2f2;
    --vantage-text-2:   #a8a8a8;
    /* #808080 measures 4.2 against a filled row in this theme. */
    --vantage-text-3:   #8a8a8a;
    --vantage-line:     rgba(255, 255, 255, 0.16);
    --vantage-line-2:   rgba(255, 255, 255, 0.10);
    --vantage-fill:     rgba(255, 255, 255, 0.07);
    --vantage-fill-2:   rgba(255, 255, 255, 0.13);
    --vantage-accent:   #ffffff;
    --vantage-brand-a:  #b18cff;
    --vantage-brand-b:  #e88b6c;
    --vantage-brand-c:  #f5b14c;
    --lms-success-ink: var(--lms-success-text);
    --lms-warning-ink: var(--lms-warning-text);
    --lms-warning-safe: #b394f0;
    --lms-danger-ink: var(--lms-danger-text);
}

/* The original brand palette: the same darks as the marketing site,
   with their blue-green cast. */
html[data-theme="vantage"] {
    --vantage-bg:       #0a1114;
    --vantage-surface:  #10181c;
    --vantage-text:     #fafafa;
    --vantage-text-2:   #96a2a8;
    --vantage-text-3:   #7d888e;
    --vantage-line:     rgba(255, 255, 255, 0.10);
    --vantage-line-2:   rgba(255, 255, 255, 0.06);
    --vantage-fill:     rgba(255, 255, 255, 0.05);
    --vantage-fill-2:   rgba(255, 255, 255, 0.10);
    --vantage-accent:   #fafafa;
    --vantage-brand-a:  #b18cff;
    --vantage-brand-b:  #e88b6c;
    --vantage-brand-c:  #f5b14c;
    --lms-success-ink: var(--lms-success-text);
    --lms-warning-ink: var(--lms-warning-text);
    --lms-warning-safe: #b394f0;
    --lms-danger-ink: var(--lms-danger-text);
}

/* Light re-states the :root values so it wins over the dark blocks
   above regardless of which class or attribute is present. */
/* Paper. It replaces Light, which was #fafafa on #ffffff: the most neutral
   grey a screen makes, and near enough to this that keeping both only made
   the picker longer. Warm off-white page, near-white surfaces that sit above
   it rather than dissolve into it, and warm near-black ink.
   It also measures better everywhere it was measured. The pairing that
   matters most is quiet ink on a filled row, 4.59 here against Light's 4.39,
   which is the measurement that failed on .st-note. */
html[data-theme="paper"] {
    --vantage-bg:       #f6f3ed;
    --vantage-surface:  #fffefb;
    --vantage-text:     #1b1815;
    --vantage-text-2:   #5e574e;
    --vantage-text-3:   #6f675e;
    --vantage-line:     rgba(27, 24, 21, 0.13);
    --vantage-line-2:   rgba(27, 24, 21, 0.065);
    --vantage-fill:     rgba(27, 24, 21, 0.045);
    --vantage-fill-2:   rgba(27, 24, 21, 0.09);
    --vantage-accent:   #1b1815;
    --vantage-brand-a:  #7c5cd6;
    --vantage-brand-b:  #d2603d;
    --vantage-brand-c:  #d9971f;
    --lms-success-ink: #1a6a3c;
    --lms-warning-ink: #8a4b04;
    --lms-warning-safe: #6a3fb0;
    --lms-danger-ink: #b02020;
}

/* Slate. The other darks differ from each other only in how dark they are;
   this one differs in hue. A dim blue-grey, lighter than Graphite, for a lit
   office where a near-black screen reads as a hole in the desk. */
html[data-theme="slate"] {
    --vantage-bg:       #171a1f;
    --vantage-surface:  #1e2229;
    --vantage-text:     #e4e8ee;
    --vantage-text-2:   #aab3bf;
    --vantage-text-3:   #9aa4b0;
    --vantage-line:     rgba(255, 255, 255, 0.11);
    --vantage-line-2:   rgba(255, 255, 255, 0.06);
    --vantage-fill:     rgba(255, 255, 255, 0.055);
    --vantage-fill-2:   rgba(255, 255, 255, 0.10);
    --vantage-accent:   #e4e8ee;
    --vantage-brand-a:  #b18cff;
    --vantage-brand-b:  #e88b6c;
    --vantage-brand-c:  #f5b14c;
    --lms-success-ink:  #6cc48f;
    --lms-warning-ink:  #e0a63d;
    --lms-warning-safe: #b394f0;
    --lms-danger-ink:   #f58a8a;
}

/* Sepia. The dark counterpart to Paper. Every other dark is neutral or cool,
   so somebody who wants a warm screen has had to give up dark to get one. */
html[data-theme="sepia"] {
    --vantage-bg:       #171310;
    --vantage-surface:  #1f1a16;
    --vantage-text:     #ece5dc;
    --vantage-text-2:   #b6aa9c;
    --vantage-text-3:   #aa9e92;
    --vantage-line:     rgba(255, 255, 255, 0.11);
    --vantage-line-2:   rgba(255, 255, 255, 0.06);
    --vantage-fill:     rgba(255, 255, 255, 0.055);
    --vantage-fill-2:   rgba(255, 255, 255, 0.10);
    --vantage-accent:   #ece5dc;
    --vantage-brand-a:  #b18cff;
    --vantage-brand-b:  #e88b6c;
    --vantage-brand-c:  #f5b14c;
    --lms-success-ink:  #6cc48f;
    --lms-warning-ink:  #e3a74a;
    --lms-warning-safe: #b394f0;
    --lms-danger-ink:   #f28e84;
}

/* Contrast, and Contrast dark. Not tastes. Some of a lender's staff cannot
   read a 6:1 label, and a procurement questionnaire will eventually ask. The
   bar in both is 7:1 rather than 4.5, and the hairlines are drawn strongly
   enough to be structure rather than suggestion.
   Both exist because the requirement does not go away when somebody prefers a
   dark screen, and a white ground is unusable for people with photophobia or
   astigmatism, who are much of why a dark scheme gets asked for at all. */
html[data-theme="contrast"] {
    --vantage-bg:       #ffffff;
    --vantage-surface:  #ffffff;
    --vantage-text:     #000000;
    --vantage-text-2:   #33383d;
    --vantage-text-3:   #3d4247;
    --vantage-line:     rgba(0, 0, 0, 0.38);
    --vantage-line-2:   rgba(0, 0, 0, 0.22);
    --vantage-fill:     rgba(0, 0, 0, 0.06);
    --vantage-fill-2:   rgba(0, 0, 0, 0.11);
    --vantage-accent:   #000000;
    --vantage-brand-a:  #5b3ca8;
    --vantage-brand-b:  #a8401f;
    --vantage-brand-c:  #8a6206;
    --lms-success-ink:  #0a5c2e;
    --lms-warning-ink:  #6b3a02;
    --lms-warning-safe: #4a2a86;
    --lms-danger-ink:   #96101a;
}

html[data-theme="contrast-dark"] {
    --vantage-bg:       #000000;
    --vantage-surface:  #000000;
    --vantage-chrome:   #000000;
    --vantage-text:     #ffffff;
    --vantage-text-2:   #e6e6e6;
    --vantage-text-3:   #d0d0d0;
    --vantage-line:     rgba(255, 255, 255, 0.42);
    --vantage-line-2:   rgba(255, 255, 255, 0.24);
    --vantage-fill:     rgba(255, 255, 255, 0.08);
    --vantage-fill-2:   rgba(255, 255, 255, 0.15);
    --vantage-accent:   #ffffff;
    --vantage-brand-a:  #c9aeff;
    --vantage-brand-b:  #f5a98d;
    --vantage-brand-c:  #ffcc70;
    --lms-success-ink:  #7cf0a8;
    --lms-warning-ink:  #ffc659;
    --lms-warning-safe: #cbb4ff;
    --lms-danger-ink:   #ff9d9d;
}

/* Colour-safe semantics. A second axis, not another scheme: it sits over
   whichever palette is chosen and only re-points attention. */
html[data-signal="safe"] {
    --lms-warning-ink: var(--lms-warning-safe);
}

/* ─── Pilot: mobile bottom navigation ──────────────────────── */

@media (max-width: 768px) {

    #lms-bottom-nav {
        background: color-mix(in srgb, var(--vantage-bg) 88%, transparent);
        backdrop-filter: blur(14px);
        -webkit-backdrop-filter: blur(14px);
        border-top: 1px solid var(--vantage-line);
    }
    .lms-bn-tab {
        font-family: var(--vantage-font-body);
        color: var(--vantage-text-3);
        transition: color 0.12s ease;
    }
    .lms-bn-tab:active .lms-bn-tab-ico { transform: scale(0.94); }
    .lms-bn-tab-ico { transition: background-color 0.15s ease, transform 0.1s ease; }
    .lms-bn-tab.lms-bn-active { color: var(--vantage-text); }
    .lms-bn-tab.lms-bn-active .lms-bn-tab-label { font-weight: 500; }
    .lms-bn-tab.lms-bn-active .lms-bn-tab-ico {
        background: color-mix(in srgb, var(--vantage-accent) 18%, transparent);
        color: var(--vantage-accent);
    }

    /* Bar badges carry the accent so an unread count reads at a glance. */
    #lms-bottom-nav .lms-bn-badge {
        background: var(--vantage-accent);
        color: var(--vantage-bg);
        border: none;
        font-weight: 600;
    }

    #lms-bn-sheet {
        background: var(--vantage-bg);
        font-family: var(--vantage-font-body);
    }
    .lms-bn-head-name {
        font-family: var(--vantage-font-heading);
        font-weight: 700;
        letter-spacing: -0.01em;
        color: var(--vantage-text);
    }
    .lms-bn-head-sub { color: var(--vantage-text-3); }
    .lms-bn-head .lms-avatar {
        background: var(--vantage-fill-2);
        color: var(--vantage-text);
    }
    .lms-bn-close {
        background: var(--vantage-fill);
        border-color: var(--vantage-line);
        color: var(--vantage-text-2);
    }

    .lms-bn-search input {
        -webkit-appearance: none;
        appearance: none;
        background: var(--vantage-fill);
        border-color: var(--vantage-line);
        color: var(--vantage-text);
        font-family: var(--vantage-font-body);
    }
    .lms-bn-search input::placeholder { color: var(--vantage-text-3); }
    .lms-bn-search input:focus { border-color: var(--vantage-accent); }

    .lms-bn-section {
        font-family: var(--vantage-font-heading);
        font-weight: 500;
        font-size: 12px;
        letter-spacing: 0.01em;
        color: var(--vantage-text-3);
    }

    .lms-bn-list {
        background: var(--vantage-fill);
        border-color: var(--vantage-line-2);
    }
    .lms-bn-row {
        color: var(--vantage-text);
        border-top-color: var(--vantage-line-2);
        font-family: var(--vantage-font-body);
    }
    .lms-bn-row:active { background: var(--vantage-fill-2); }
    .lms-bn-row.lms-bn-row-active { background: var(--vantage-fill-2); }
    .lms-bn-row.lms-bn-row-active .lms-bn-row-label { color: var(--vantage-text); }
    /* One neutral ink for every icon. The three brand hues used to cycle per
       section as a scanning aid, but the palette carries meaning everywhere
       else in the application, and a grid of pastel chips read as decoration
       rather than as navigation. The section headings do that job now. */
    .lms-bn-row-ico { color: var(--vantage-text-3); }

    /* The screen you are on, marked the way the sidebar marks it. */
    .lms-bn-row.lms-bn-row-active {
        background: color-mix(in srgb, var(--vantage-accent) 13%, transparent);
    }
    .lms-bn-row.lms-bn-row-active .lms-bn-row-ico { color: var(--vantage-accent); }

    /* A queue with items in it is work waiting, so it carries the warning ink;
       an ordinary count is just a number and stays quiet. Amber rather than the
       brand accent, because the accent already means "Vantage" and "you are
       here", and the dashboard settled amber as "this needs attention". A wash
       and coloured text rather than a solid pill: at this size a filled badge
       shouts, and there can be a dozen of them on screen at once.
       Qualified with html.dark-mode as well, because lms.css carries a
       `html.dark-mode .lms-node-count` rule that otherwise outranks a plain
       two-class selector and repaints these back to grey. */
    .lms-bn-row-count.lms-bn-attn,
    html.dark-mode .lms-bn-row-count.lms-bn-attn {
        background: color-mix(in srgb, var(--lms-warning-ink) 16%, transparent);
        border-color: transparent;
        color: var(--lms-warning-ink);
        font-weight: 600;
    }
    .lms-bn-section {
        font-family: var(--vantage-font-heading);
        color: var(--vantage-text-3);
    }
    /* A section total that includes a genuine attention item reads as
       attention, not a plain count; see .lms-node-count-attn's desktop
       equivalent above. */
    .lms-bn-section-count.lms-bn-section-count-attn,
    html.dark-mode .lms-bn-section-count.lms-bn-section-count-attn {
        background: color-mix(in srgb, var(--lms-warning-text) 16%, transparent);
        border: 0;
        color: var(--lms-warning-text);
        font-weight: 600;
    }

    .lms-bn-row-count,
    .lms-bn-badge {
        background: var(--vantage-fill-2);
        color: var(--vantage-text);
        border: 1px solid var(--vantage-line-2);
    }

    /* ── Chat, Discord-grade mobile ergonomics ── */

    /* Rail rows become finger-height rounded pills with roomier type. */
    #cd-rail-search {
        height: 42px;
        font-size: 15px;
        border-radius: 12px;
    }
    .cd-row {
        min-height: 44px;
        padding: 8px 12px;
        margin: 1px 8px;
        border-radius: 12px;
        font-size: 15px;
    }
    .cd-row-lead { width: 24px; font-size: 15px; }
    .cd-row-badge {
        min-width: 22px;
        height: 20px;
        border-radius: 10px;
        font-size: 12px;
        line-height: 20px;
    }
    .cd-section-head { font-size: 12.5px; padding: 2px 20px; }
    .cd-list-empty { font-size: 14px; }

    /* Messages read at phone size: larger body and author type. */
    .ch-msg-body { font-size: 15px; line-height: 1.5; }
    .ch-msg-author { font-size: 15px; }
    .ch-mention { border-radius: 6px; padding: 0 5px; }

    /* Composer: a rounder island; 16px input stops iOS zooming the
       page every time the field focuses. */
    .cd-composer { border-radius: 18px; padding: 6px 8px; }
    .cd-composer textarea.cd-input { font-size: 16px; }
    .cd-icon-btn { font-size: 19px; padding: 6px; }

    /* Unread total on the conversation back arrow, Discord-style:
       while inside one thread you can still see others need you. */
    .lms-mobile-back { position: relative; padding: 4px 6px; }
    .lms-back-badge {
        position: absolute;
        top: -4px;
        right: -8px;
        min-width: 17px;
        height: 16px;
        padding: 0 4px;
        border-radius: 9px;
        background: var(--vantage-accent);
        color: var(--vantage-bg);
        font-size: 10.5px;
        font-weight: 600;
        line-height: 16px;
        text-align: center;
    }

    /* Reaction / composer emoji picker: phones render emoji glyphs larger
       than the desktop 10-column grid assumes, so let the grid size itself
       from its cells and give each one a finger-sized target. */
    .lms-emoji-picker {
        width: auto !important;
        max-width: calc(100vw - 24px);
        grid-template-columns: repeat(8, 1fr) !important;
        -webkit-text-size-adjust: 100%;
        text-size-adjust: 100%;
    }
    .lms-emoji-picker span {
        font-size: 23px !important;
        padding: 6px 5px !important;
    }
}

/* Respect reduced-motion preferences for the menu's entrance. */
@media (prefers-reduced-motion: reduce) {
    #lms-bn-sheet { animation: none; }
    .lms-bn-tab, .lms-bn-tab-ico { transition: none; }
}

/* ─── Application top bar (desktop) ────────────────────────── */
/* The chrome that makes the product read as an application rather
   than a web page: sidebar collapse, screen history, a breadcrumb
   that always says where you are, and the command palette. */
/* The bar is a sibling above .lms-layout, so the shell becomes a column
   and the layout takes the remaining height (min-height:0 keeps its own
   scroll containers working). */
#main {
    display: flex;
    flex-direction: column;
}
#main > .lms-layout {
    flex: 1 1 auto;
    min-height: 0;
    height: auto;
}
.lms-topbar {
    position: relative;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 2px;
    height: 44px;
    padding: 0 10px 0 8px;
    background: var(--vantage-bg);
    border-bottom: 1px solid var(--vantage-line-2);
    font-family: var(--vantage-font-body);
}
.lms-tb-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--vantage-text-2);
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.lms-tb-btn svg { width: 17px; height: 17px; }
.lms-tb-btn:hover:not(:disabled) { background: var(--vantage-fill-2); color: var(--vantage-text); }
.lms-tb-btn:disabled { opacity: 0.3; cursor: default; }
/* Workspace mark: the V icon alone carries the brand in the bar, so the
   sidebar below is pure navigation and the wordmark is never repeated. */
.lms-tb-mark {
    display: block;
    width: 20px;
    height: 20px;
    margin: 0 8px 0 6px;
    background: url(/img-lms/vantage-icon.png) center / contain no-repeat;
}
html.dark-mode .lms-tb-mark { background-image: url(/img-lms/vantage-icon-white.png); }

.lms-tb-div {
    width: 1px;
    height: 18px;
    margin: 0 6px;
    background: var(--vantage-line-2);
}
/* Menu strip: File / Edit / View / Go / Help. */
.lms-tb-menus {
    display: flex;
    align-items: center;
    gap: 1px;
    margin-left: 4px;
}
.lms-menu-btn {
    height: 26px;
    padding: 0 9px;
    border: 0;
    border-radius: var(--vantage-r-sm);
    background: transparent;
    color: var(--vantage-text-2);
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    cursor: pointer;
    transition: background-color 0.1s ease, color 0.1s ease;
}
.lms-menu-btn:hover { background: var(--vantage-fill-2); color: var(--vantage-text); }
.lms-menu-btn.lms-menu-open {
    background: color-mix(in srgb, var(--vantage-accent) 16%, transparent);
    color: var(--vantage-text);
}
.lms-menu-pop,
.lms-gf-menu {
    position: fixed;
    z-index: 10002;
    min-width: 232px;
    max-width: 320px;
    padding: 5px;
    background: var(--vantage-surface);
    border: 1px solid var(--vantage-line);
    border-radius: 11px;
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.28);
    animation: lms-pop-in 0.1s ease-out;
}
.lms-menu-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: var(--vantage-r-sm);
    background: transparent;
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}
.lms-menu-item > span:not(.lms-menu-check):not(.lms-menu-hint):not(.lms-menu-arrow) { flex: 1; }
/* A parent item says which way its list opens, and what is currently chosen
   inside it, so the menu answers "which theme am I on?" without opening. */
.lms-menu-arrow { color: var(--vantage-text-3); font-size: 15px; line-height: 1; flex: none; }
.lms-menu-hint  { color: var(--vantage-text-2); font-size: 12px; flex: none; }
.lms-menu-item[aria-expanded="true"] { background: var(--vantage-fill-2); }
.lms-menu-sub { animation-duration: 0.08s; }
.lms-menu-item:hover:not(:disabled) { background: var(--vantage-fill-2); }
.lms-menu-item:disabled { opacity: 0.4; cursor: default; }
.lms-menu-sep {
    height: 1px;
    margin: 4px 8px;
    background: var(--vantage-line-2);
}
.lms-cp-title {
    flex: 1;
    font-family: var(--vantage-font-heading);
    font-weight: 500;
    font-size: 14.5px;
    color: var(--vantage-text);
}


/* Control groups: each job (history, create and chat) sits behind its own
   hairline so the bar reads as a few clusters rather than a row of icons. */
.lms-tb-group {
    display: flex;
    align-items: center;
    gap: 1px;
    margin-left: 7px;
    padding-left: 7px;
    border-left: 1px solid var(--vantage-line-2);
}
.lms-tb-btn { position: relative; }
.lms-tb-badge {
    position: absolute;
    top: 1px;
    right: 0;
    min-width: 15px;
    height: 14px;
    padding: 0 3px;
    border-radius: 8px;
    background: var(--vantage-accent);
    color: var(--vantage-bg);
    font-size: 9.5px;
    font-weight: 600;
    line-height: 14px;
    text-align: center;
}

/* Search sits between the left groups and the right cluster. With four
   groups on the left there is no room to centre it in the window without
   colliding, so it takes the space that is actually free. */
.lms-tb-search {
    margin: 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    width: min(360px, 30vw);
    height: 28px;
    padding: 0 8px 0 11px;
    border: 1px solid var(--vantage-line-2);
    border-radius: 9px;
    background: var(--vantage-fill);
    color: var(--vantage-text-3);
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    cursor: pointer;
    transition: border-color 0.12s ease, color 0.12s ease, background-color 0.12s ease;
}
.lms-tb-search:hover {
    border-color: var(--vantage-line);
    background: var(--vantage-fill-2);
    color: var(--vantage-text-2);
}
.lms-tb-search-ico { display: inline-flex; }
.lms-tb-search-ico svg { width: 14px; height: 14px; }
.lms-tb-search-label { flex: 1; text-align: left; color: var(--vantage-text-2); }

/* Utility cluster pinned right, the way desktop apps park settings. */
.lms-tb-right {
    display: flex;
    align-items: center;
    gap: 1px;
    margin-left: auto;
    padding-left: 8px;
}

/* Narrow windows: the field gives up its fixed width and the create and
   chat group folds away (both live in the File menu and the sidebar). */
@media (max-width: 1100px) {
    .lms-tb-search { width: auto; min-width: 128px; }
}
@media (max-width: 900px) {
    .lms-tb-group + .lms-tb-group { display: none; }
}
.lms-tb-kbd,
.lms-cp-kbd {
    padding: 1px 6px;
    border: 1px solid var(--vantage-line-2);
    border-radius: 5px;
    background: var(--vantage-bg);
    color: var(--vantage-text-3);
    font-family: var(--vantage-font-body);
    font-size: 10.5px;
    letter-spacing: 0.02em;
}

/* Collapsed sidebar: the panel and its drag handle fold away entirely.
   The toggle lives in the bar, so it is always reachable. */
.lms-layout.lms-sidebar-collapsed .lms-panel-left,
.lms-layout.lms-sidebar-collapsed .lms-resize-handle {
    display: none;
}

/* ─── Installed app: window controls overlay ────────────────
   In an installed window the browser normally draws its own title bar above
   the application, so the user gets two stacked bars where a desktop app has
   one. With window-controls-overlay (declared in manifest.webmanifest) the
   page is given the title bar strip and only the system minimise/maximise/
   close buttons stay on top, so the application bar becomes the title bar,
   the way VS Code and Cursor do it.

   The env() values describe the strip left free of those buttons: on Windows
   and Linux they sit on the right, on macOS on the left, so neither side can
   be assumed. Fallbacks keep this harmless anywhere the variables are absent. */
@media (display-mode: window-controls-overlay) {
    .lms-topbar {
        /* Never shorter than the bar's own rhythm, but grow if the platform
           reserves a taller strip, or the buttons would overhang the border. */
        height: max( 44px, env( titlebar-area-height, 44px ) );
        /* macOS keeps its traffic lights on the left, so start after them. */
        padding-left: calc( env( titlebar-area-x, 0px ) + 8px );
        /* Whatever is left over on the right is the window buttons. max()
           guards against a negative value if the variables are unavailable. */
        padding-right: max( 10px, calc( 100vw - env( titlebar-area-x, 0px )
                                              - env( titlebar-area-width, 100vw ) + 10px ) );
        /* The bar is now the title bar, so it has to move the window. */
        -webkit-app-region: drag;
        app-region: drag;
    }

    /* Anything clickable must opt out, or dragging swallows the click. Listed
       by element rather than by class so a control added later is covered. */
    .lms-topbar button,
    .lms-topbar input,
    .lms-topbar a,
    .lms-topbar select,
    .lms-topbar [role="button"],
    .lms-topbar [tabindex] {
        -webkit-app-region: no-drag;
        app-region: no-drag;
    }
}

/* A panel toggle reads as "on" while its panel is showing. */
.lms-tb-btn.lms-tb-btn-on,
/* The navigation carries its own hide control at its foot, so the bar's copy
   is only the way back: it appears while the navigation is away and is not
   there competing with it the rest of the time. */
.lms-topbar:not(.lms-tb-collapsed) #lms-tb-collapse { display: none; }

/* ─── Reordering the pins ──────────────────────────────────────
   The grip is quiet until the row is under the pointer or holds focus: it is
   an affordance for a thing people do rarely, and a column of dots on every
   pinned row reads as clutter the rest of the time. */
.lms-sidebar .lms-pinrow { cursor: default; }
.lms-sidebar .lms-grip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 12px;
    margin-right: 2px;
    flex-shrink: 0;
    color: var(--vantage-text-3);
    /* Present at rest, not revealed on hover. A grip nobody can see is a
       feature nobody knows about, which is the same criticism the pinning
       study made of hover-only affordances, and it applies here too. Quiet
       enough at 0.35 to stay out of the way of the names beside it. */
    opacity: 0.35;
    cursor: grab;
    transition: opacity 0.12s ease;
}
.lms-sidebar .lms-pinrow:hover .lms-grip,
.lms-sidebar .lms-pinrow:focus-within .lms-grip { opacity: 0.85; }
.lms-sidebar .lms-grip:active { cursor: grabbing; }
.lms-sidebar .lms-pinrow.lms-dragging { opacity: 0.45; }
/* Where it will land, drawn as a line rather than by moving the rows about
   under the pointer. */
.lms-sidebar .lms-pinrow.lms-drop-into { position: relative; }
.lms-sidebar .lms-pinrow.lms-drop-into::after {
    content: '';
    position: absolute;
    left: 8px;
    right: 8px;
    bottom: -1px;
    height: 2px;
    border-radius: 2px;
    background: var(--vantage-accent);
}
@media (pointer: coarse) {
    /* A finger cannot drag an HTML5 row and does not hover, so the grip is
       hidden and the long press menu carries Move up and Move down. */
    .lms-sidebar .lms-grip { display: none; }
    .lms-nav-menu .lms-row-act-menu-item { min-height: 44px; }
}
.lms-nav-menu .lms-row-act-menu-item[disabled] { opacity: 0.45; cursor: not-allowed; }
.lms-nav-menu .lms-row-act-menu-item[disabled]:hover { background: transparent; }

/* Rail only: the screen list is put away and the areas stay reachable. The
   column's width is an inline style from the layout, so it is overridden here
   rather than rewritten, and comes back exactly as it was. */
.lms-panel-left.lms-rail-only {
    width: 56px !important;
    min-width: 56px !important;
}
.lms-sidebar.lms-rail-only .lms-apanel { display: none; }
/* Nothing to resize when only the rail is showing. */
.lms-layout.lms-rail-only .lms-resize-handle { pointer-events: none; opacity: 0; }
.lms-sidebar.lms-rail-only .lms-arail { border-right: 0; }
/* The control moves under the icons rather than beside a list that is gone. */
.lms-sidebar.lms-rail-only .lms-collapse { margin: 0 auto; }
.lms-sidebar .lms-collapse.lms-collapse-on { color: var(--vantage-text); }

/* The hide control, at the foot of whichever navigation is drawn. */
.lms-sidebar .lms-arail-sp { flex: 1; }
.lms-sidebar .lms-collapse {
    width: 42px;
    height: 42px;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: var(--vantage-r-sm);
    background: transparent;
    color: var(--vantage-text-3);
    cursor: pointer;
    transition: background-color 0.15s cubic-bezier(0.4,0,0.2,1), color 0.15s cubic-bezier(0.4,0,0.2,1);
}
.lms-sidebar .lms-collapse:hover { background: var(--vantage-fill); color: var(--vantage-text); }
.lms-sidebar .lms-nav-foot {
    flex: none;
    padding: 4px 8px 8px;
    display: flex;
    justify-content: flex-end;
    border-top: 1px solid var(--vantage-line-2);
}

/* Right activity panel: docks the notifications list beside the content. */
.lms-right-panel {
    flex-shrink: 0;
    width: 320px;
    display: flex;
    flex-direction: column;
    background: var(--vantage-surface);
    border-left: 1px solid var(--vantage-line-2);
    overflow: hidden;
}
.lms-rp-head {
    flex-shrink: 0;
    padding: 11px 14px;
    border-bottom: 1px solid var(--vantage-line-2);
}
.lms-rp-title {
    font-family: var(--vantage-font-heading);
    font-weight: 500;
    font-size: 13.5px;
    color: var(--vantage-text);
}
/* The docked dropdown drops its popover geometry and fills the panel. */
#notif-dropdown.lms-rp-docked {
    position: static !important;
    width: auto !important;
    max-height: none !important;
    flex: 1;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    background: transparent !important;
    overflow-y: auto;
}
@media (max-width: 1100px) {
    .lms-right-panel { width: 280px; }
}
@media (max-width: 768px) {
    .lms-right-panel { display: none; }
}

/* ─── Command palette ──────────────────────────────────────── */
.lms-cp-overlay {
    position: fixed;
    inset: 0;
    z-index: 10001;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding-top: 12vh;
    background: color-mix(in srgb, #000 45%, transparent);
    animation: lms-fade-in 0.12s ease-out;
}
.lms-cp {
    width: min(560px, calc(100vw - 32px));
    background: var(--vantage-surface);
    border: 1px solid var(--vantage-line);
    border-radius: 14px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
    overflow: hidden;
    animation: lms-pop-in 0.14s ease-out;
}
.lms-cp-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--vantage-line-2);
}
.lms-cp-head-ico { display: inline-flex; color: var(--vantage-text-3); }
.lms-cp-head-ico svg { width: 16px; height: 16px; }
.lms-cp-input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 15px;
    outline: none;
}
.lms-cp-input::placeholder { color: var(--vantage-text-3); }
/* Beat the legacy global input:focus skin, which paints a blue ring in
   dark mode; that rule carries html.dark-mode, so match its specificity. */
.lms-cp-input:focus,
html.dark-mode .lms-cp-input:focus {
    border: 0;
    box-shadow: none;
    outline: none;
}
.lms-cp-list { max-height: 46vh; overflow-y: auto; padding: 6px; }
.lms-cp-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 10px;
    border-radius: var(--vantage-r-md);
    cursor: pointer;
    font-size: 13.5px;
    color: var(--vantage-text);
}
.lms-cp-item.lms-cp-active { background: color-mix(in srgb, var(--vantage-accent) 14%, transparent); }
.lms-cp-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    flex-shrink: 0;
    border-radius: var(--vantage-r-sm);
    background: var(--vantage-fill);
    color: var(--vantage-text-2);
}
.lms-cp-item.lms-cp-active .lms-cp-ico {
    background: color-mix(in srgb, var(--vantage-accent) 20%, transparent);
    color: var(--vantage-accent);
}
.lms-cp-ico svg { width: 15px; height: 15px; }
.lms-cp-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lms-cp-section { flex-shrink: 0; font-size: 12px; color: var(--vantage-text-3); }
.lms-cp-empty { padding: 22px; text-align: center; font-size: 13px; color: var(--vantage-text-3); }

@media (prefers-reduced-motion: reduce) {
    .lms-cp-overlay, .lms-cp { animation: none; }
}

/* Phones own their own navigation (bottom bar plus a slim header); the app
   bar is desktop chrome and would only steal vertical space. */
@media (max-width: 768px) {
    .lms-topbar { display: none; }
}
/* The phone header is only built at phone widths, but it is appended to the
   body rather than the layout, so a resize up to a desktop width would
   otherwise leave it on screen. Scoped to a min-width so it never competes
   with the rule in mobile.css that shows it. */
@media (min-width: 769px) {
    #lms-mobile-header { display: none; }
}

/* ─── Surface: desktop sidebar ─────────────────────────────── */
/* The workspace header is gone: the top bar carries the Vantage mark,
   so repeating the logo here only cost vertical space. On phones there
   is no top bar, so the header stays as the drawer's identity. */
@media (min-width: 769px) {
    .lms-sidebar .lms-ws { display: none; }
    .lms-sidebar .lms-nav { padding-top: 8px; }
}
/* Token remap scoped to the sidebar subtree: every rule and inline
   style inside it that reads an --lms-* variable picks up the brand
   values without being rewritten. */
.lms-sidebar {
    --lms-bg-panel: var(--vantage-chrome);
    --lms-border: var(--vantage-line);
    --lms-border-light: var(--vantage-line-2);
    --lms-text: var(--vantage-text);
    --lms-text-muted: var(--vantage-text-2);
    --lms-text-faint: var(--vantage-text-3);
    --lms-active-tint: var(--vantage-fill-2);
    font-family: var(--vantage-font-body);
}
/* ─── Two part navigation (View > Navigation) ──────────────────
   A rail of areas that never scrolls beside a panel showing one area, which
   is short enough to read whole. Rows are the same .lms-node.lms-leaf as the
   tree, so everything downstream of them is unchanged. */
.lms-sidebar.lms-nav-areas .lms-areas { display: flex; flex: 1; min-height: 0; }
.lms-sidebar.lms-nav-areas .lms-arail {
    width: 56px;
    overflow: visible;
    flex: none;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 6px 0;
    border-right: 1px solid var(--vantage-line-2);
}
.lms-sidebar.lms-nav-areas .lms-area {
    position: relative;
    width: 42px;
    height: 42px;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: var(--vantage-r-sm);
    background: transparent;
    color: var(--vantage-text-3);
    cursor: pointer;
    transition: background-color 0.15s cubic-bezier(0.4,0,0.2,1), color 0.15s cubic-bezier(0.4,0,0.2,1);
}
.lms-sidebar.lms-nav-areas .lms-area:hover { background: var(--vantage-fill); color: var(--vantage-text); }
.lms-sidebar.lms-nav-areas .lms-area-on {
    background: color-mix(in srgb, var(--vantage-accent) 13%, transparent);
    color: var(--vantage-text);
}
/* An icon alone is a guess until it has been learned, so it carries its name
   on hover and on keyboard focus.
   It has to read as something floating above the panel rather than a chip
   sitting in it: at the same tone as the hover fill, with no edge and no
   shadow, it looked like a stray label dropped between two rows. Solid
   surface, a hairline, a shadow, and a pointer joining it to its icon. */
.lms-sidebar.lms-nav-areas .lms-area::after {
    content: attr(data-label);
    position: absolute;
    left: calc(100% + 10px);
    top: 50%;
    transform: translateY(-50%) translateX(-3px);
    padding: 6px 10px;
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-sm);
    background: var(--vantage-surface);
    color: var(--vantage-text);
    font-size: 12.5px;
    line-height: 1.2;
    white-space: nowrap;
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.28);
    opacity: 0;
    pointer-events: none;
    /* A short delay so running the pointer down the rail does not flash ten
       labels on the way past. */
    transition: opacity 0.12s cubic-bezier(0.4,0,0.2,1) 0.35s,
                transform 0.12s cubic-bezier(0.4,0,0.2,1) 0.35s;
    z-index: 60;
}
.lms-sidebar.lms-nav-areas .lms-area::before {
    content: '';
    position: absolute;
    left: calc(100% + 5px);
    top: 50%;
    width: 7px;
    height: 7px;
    transform: translateY(-50%) rotate(45deg);
    background: var(--vantage-surface);
    border-left: 1px solid var(--vantage-line);
    border-bottom: 1px solid var(--vantage-line);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.12s cubic-bezier(0.4,0,0.2,1) 0.35s;
    z-index: 61;
}
.lms-sidebar.lms-nav-areas .lms-area:hover::after,
.lms-sidebar.lms-nav-areas .lms-area:hover::before,
.lms-sidebar.lms-nav-areas .lms-area:focus-visible::after,
.lms-sidebar.lms-nav-areas .lms-area:focus-visible::before { opacity: 1; }
.lms-sidebar.lms-nav-areas .lms-area:hover::after,
.lms-sidebar.lms-nav-areas .lms-area:focus-visible::after { transform: translateY(-50%) translateX(0); }
/* The panel header already names the area you are in, so it does not need
   telling twice. */
.lms-sidebar.lms-nav-areas .lms-area-on::after,
.lms-sidebar.lms-nav-areas .lms-area-on::before { content: none; }
/* Focus is keyboard-driven, so the label appears at once rather than after the
   pointer's delay. */
.lms-sidebar.lms-nav-areas .lms-area:focus-visible::after,
.lms-sidebar.lms-nav-areas .lms-area:focus-visible::before { transition-delay: 0s; }
/* Someone who has asked for less motion still needs the label, just not the
   fade: it appears at once instead. */
@media (prefers-reduced-motion: reduce) {
    .lms-sidebar.lms-nav-areas .lms-area::after,
    .lms-sidebar.lms-nav-areas .lms-area::before { transition: none; }
    .lms-sidebar.lms-nav-areas .lms-area:hover::after { transform: translateY(-50%) translateX(0); }
}
/* Work waiting inside a closed area, or folding one away hides the only thing
   somebody opened the navigation to find. Ink inverts with the theme: white on
   the dark-mode ink measured 2.8:1. */
.lms-sidebar.lms-nav-areas .lms-area-n {
    position: absolute;
    top: 4px;
    right: 4px;
    min-width: 15px;
    height: 15px;
    padding: 0 4px;
    border-radius: 8px;
    background: var(--lms-warning-ink);
    color: var(--vantage-bg);
    font-size: 9.5px;
    font-weight: 700;
    line-height: 15px;
    text-align: center;
}
.lms-sidebar.lms-nav-areas .lms-apanel { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.lms-sidebar.lms-nav-areas .lms-apanel-head { padding: 10px 12px 4px; flex: none; }
.lms-sidebar.lms-nav-areas .lms-apanel-title {
    font-family: var(--vantage-font-heading);
    font-weight: 700;
    font-size: 14px;
    letter-spacing: -0.01em;
}
.lms-sidebar.lms-nav-areas .lms-apanel-body { flex: 1; overflow-y: auto; padding: 0 6px 12px; }
.lms-sidebar.lms-nav-areas .lms-apanel-body .lms-node.lms-sub { padding-left: 10px; }
.lms-sidebar.lms-nav-areas .lms-needs { margin-bottom: 6px; }
.lms-sidebar.lms-nav-areas .lms-need { align-items: flex-start; height: auto; padding-top: 5px; padding-bottom: 5px; }
.lms-sidebar.lms-nav-areas .lms-need .lms-node-label { white-space: normal; }
.lms-sidebar.lms-nav-areas .lms-need-sub {
    display: block;
    font-size: 11.5px;
    color: var(--vantage-text-3);
}
.lms-sidebar.lms-nav-areas .lms-needs-none {
    margin: 0;
    padding: 6px 10px 10px;
    font-size: 12px;
    line-height: 1.5;
    color: var(--vantage-text-3);
}

/* The filled row stays: Ryan tried the rule-and-ink alternative in the app and
   preferred this. */
.lms-sidebar .lms-node.lms-selected {
    background: color-mix(in srgb, var(--vantage-accent) 13%, transparent);
    color: var(--vantage-text);
}
.lms-sidebar .lms-node.lms-selected .lms-ico { color: var(--vantage-accent); }

/* Keyboard focus has to be visible now that the rows can be reached without a
   pointer; they are divs, so nothing was drawing one. */
.lms-sidebar .lms-node:focus-visible {
    outline: 2px solid var(--lms-warning-ink);
    outline-offset: -2px;
    border-radius: var(--vantage-r-sm);
}
.lms-sidebar .lms-node-count,
html.dark-mode .lms-sidebar .lms-node-count {
    background-color: var(--vantage-fill-2);
    color: var(--vantage-text);
}
.lms-sidebar .lms-acct-name { font-family: var(--vantage-font-heading); font-weight: 500; }

/* Pinned group, and the pin affordance on every row. */
.lms-sidebar .lms-pins { padding-bottom: 4px; }
.lms-sidebar .lms-node { position: relative; }
.lms-sidebar .lms-pin {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    margin-left: 4px;
    flex-shrink: 0;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--vantage-text-3);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.12s ease, color 0.12s ease, background-color 0.12s ease;
}
.lms-sidebar .lms-node:hover .lms-pin { opacity: 0.75; }
.lms-sidebar .lms-pin:hover { opacity: 1; background: var(--vantage-fill-2); color: var(--vantage-text); }
.lms-sidebar .lms-pin.lms-pinned { opacity: 0.9; color: var(--vantage-accent); }
.lms-sidebar .lms-pin-ico { width: 13px; height: 13px; }
/* Touch has no hover to reveal it, so the pin stays visible there. */
@media (max-width: 768px) {
    .lms-sidebar .lms-pin { opacity: 0.5; width: 26px; height: 26px; }
}
/* A section total that includes a genuine attention item (a queue, an
   exception list) reads as attention, in the warning ink throughout this
   application; an ordinary row-count total stays the plain neutral badge
   below. It used to be the brand accent, which collides with the accent's
   other two jobs: marking the selected row, and simply meaning Vantage. */
.lms-sidebar .lms-section-header .lms-node-count.lms-node-count-attn,
html.dark-mode .lms-sidebar .lms-section-header .lms-node-count.lms-node-count-attn {
    background-color: color-mix(in srgb, var(--lms-warning-ink) 16%, transparent);
    color: var(--lms-warning-ink);
    font-weight: 600;
}

@media (max-width: 768px) {
    /* Toolbar buttons are 32px by design on a desktop, which is a fine mouse
       target and a poor thumb one. Declared here rather than in mobile.css
       because that file loads first and would lose the tie. */
    #lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button,
    .w2ui-toolbar .w2ui-tb-button,
    .lms-gf-bar .lms-gf-primary,
    .lms-gf-create .lms-gf-primary,
    .lms-gf-cols .lms-cols-btn { min-width: 44px; }
}

/* The account avatar still pointed at the legacy --lms-bg-alt/--lms-text pair,
   which never learned about the light theme: it painted a dark circle with dark
   text on a light page, so the initial was invisible. */
.lms-avatar {
    background: var(--vantage-fill-2);
    color: var(--vantage-text);
    border-color: var(--vantage-line);
}

/* ─── Editing ──────────────────────────────────────────────── */
/* Which cells can be edited was previously discoverable only by clicking one,
   and a click already opens the editor. A hairline on hover says "this one
   answers" without changing what a click does. */
#lms-panel-main .tabulator .tabulator-cell.tabulator-editable:hover {
    background: var(--vantage-fill);
    box-shadow: inset 0 0 0 1px var(--vantage-line);
    cursor: text;
}
/* A value the column itself will not accept never enters the change set; the
   cell goes back to what it held and says so for a moment. */
#lms-panel-main .tabulator .tabulator-cell.lms-cell-invalid {
    background: color-mix( in srgb, var(--lms-danger-ink) 18%, transparent ) !important;
    box-shadow: inset 2px 0 0 var(--lms-danger-ink);
}

/* ─── Review dialog ────────────────────────────────────────── */
/* What changed, in the words the screen uses, with what it was beside what it
   would become, and a way to put one of them back. */
.lms-rv-body { padding: 4px 2px 8px; }
.lms-rv-empty { color: var(--vantage-text-2); font-size: 13px; padding: 8px 2px; }
.lms-rv-rec + .lms-rv-rec { margin-top: 16px; }
.lms-rv-rec-head {
    font-family: var(--vantage-font-heading);
    font-size: 13px;
    padding-bottom: 5px;
    border-bottom: 1px solid var(--vantage-line);
}
.lms-rv-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.lms-rv-table td { padding: 8px 6px; border-bottom: 1px solid var(--vantage-line-2); vertical-align: baseline; }
.lms-rv-table tr:last-child td { border-bottom: 0; }
.lms-rv-field { color: var(--vantage-text-2); width: 34%; }
.lms-rv-from  { color: var(--vantage-text-2); text-align: right; text-decoration: line-through;
                text-decoration-color: var(--vantage-text-3); font-variant-numeric: tabular-nums; }
.lms-rv-arrow { color: var(--vantage-text-3); width: 18px; text-align: center; }
.lms-rv-to    { color: var(--vantage-text); font-variant-numeric: tabular-nums; }
.lms-rv-act   { width: 74px; text-align: right; }
.lms-rv-from em, .lms-rv-to em { color: var(--vantage-text-3); font-style: italic; }
.lms-rv-revert {
    padding: 3px 9px;
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-sm);
    background: transparent;
    color: var(--vantage-text-2);
    font-family: var(--vantage-font-body);
    font-size: 11.5px;
    cursor: pointer;
}
.lms-rv-revert:hover { background: var(--vantage-fill); color: var(--vantage-text); }

/* ─── Risk score ───────────────────────────────────────────── */
/* This screen carried forty inline styles, including its own font stack, so it
   rendered in Arial while the rest of the application rendered in the brand's
   typeface, and nothing in a stylesheet could reach its controls. */
.rs-root {
    /* The main panel clips its overflow, so a screen that is taller than the
       window has to do its own scrolling. The inline styles this replaced
       carried height:100% and overflow-y:auto; dropping them left the form
       unscrollable on a phone, where it is twice the height of the screen. */
    height: 100%;
    overflow-y: auto;
    box-sizing: border-box;
    padding: 26px 30px 60px;
}
.rs-root > * { max-width: 1180px; }
.rs-title {
    margin: 0 0 4px;
    font-family: var(--vantage-font-heading);
    font-weight: 700;
    font-size: 26px;
    letter-spacing: -0.02em;
}
.rs-subtitle { margin: 0 0 8px; font-family: var(--vantage-font-heading); font-weight: 500; font-size: 13px; }
.rs-card {
    padding: 14px 16px;
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-lg);
}
.rs-picker { max-width: 640px; margin: 16px 0 20px; }
.rs-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.rs-hint { font-size: 11.5px; color: var(--vantage-text-2); }
.rs-hint-block { margin: 8px 0 0; line-height: 1.55; }
.rs-label { display: block; margin-bottom: 5px; font-size: 12px; color: var(--vantage-text-2); }
.rs-input {
    width: 100%;
    height: 32px;
    padding: 0 10px;
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-sm);
    background-color: var(--vantage-fill);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13px;
}
.rs-input-wide { flex: 1; min-width: 260px; width: auto; }
.rs-upper { text-transform: uppercase; }

/* Two columns of fields beside the result, rather than one long column with
   two thirds of the panel empty beside it. */
.rs-grid { display: grid; grid-template-columns: minmax(0, 460px) minmax(0, 1fr); gap: 28px; align-items: start; }
.rs-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.rs-form { min-width: 0; }
.rs-error {
    margin-top: 12px;
    padding: 9px 12px;
    border-left: 3px solid var(--lms-danger-ink);
    border-radius: var(--vantage-r-sm);
    background: color-mix( in srgb, var(--lms-danger-ink) 12%, transparent );
    color: var(--lms-danger-ink);
    font-size: 12.5px;
}
.rs-error[hidden], .rs-result[hidden] { display: none; }
.rs-submit {
    margin-top: 20px;
    padding: 9px 22px;
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-sm);
    background: var(--vantage-fill-2);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13px;
    cursor: pointer;
}
.rs-submit:hover { background: var(--vantage-fill); }

.rs-summary { display: flex; align-items: center; gap: 32px; margin-bottom: 20px; padding: 20px 22px; }
.rs-eyebrow { margin-bottom: 5px; font-size: 11px; color: var(--vantage-text-3); }
.rs-score {
    font-family: var(--vantage-font-heading);
    font-weight: 700;
    font-size: 42px;
    line-height: 1;
    letter-spacing: -0.02em;
}
.rs-score-good { color: var(--lms-success-ink); }
.rs-score-warning { color: var(--lms-warning-ink); }
.rs-score-bad { color: var(--lms-danger-ink); }
.rs-band { font-size: 12px; }

.rs-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.rs-table th {
    padding: 7px 10px;
    border-bottom: 1px solid var(--vantage-line);
    color: var(--vantage-text-3);
    font-weight: 400;
    text-align: left;
}
.rs-table td { padding: 8px 10px; border-bottom: 1px solid var(--vantage-line-2); }
.rs-table .rs-num { text-align: right; font-variant-numeric: tabular-nums; }
.rs-table .rs-strong { font-weight: 500; }
.rs-table .rs-total td { border-top: 1px solid var(--vantage-line); border-bottom: 0; font-weight: 500; }

@media (max-width: 1100px) {
    .rs-grid { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
    .rs-fields { grid-template-columns: 1fr; }
    .rs-root { padding: 18px 14px 50px; }
    /* 32px is a mouse target. Every control on this form is one a thumb has to
       hit, and there are nine of them in a column. */
    .rs-input, .rs-submit { height: 44px; }
    .rs-submit { padding-inline: 20px; }
}

/* ─── Native form controls ─────────────────────────────────── */
/* A select and a date field the browser draws itself are the two places this
   product still looks like a form from 2009: a grey slab with a system chevron
   beside inputs that carry the application's own border, radius and type. The
   risk-score screen is a column of them. Styled here, once, rather than per
   screen, and scoped to the panel so vendor widgets that rely on native
   rendering are left alone. */
#lms-panel-main select:not(.tabulator-header-filter select):not([class*="tabulator"]):not(.lms-hedge-ccy-select),
#lms-panel-main input[type="date"],
#lms-panel-main input[type="datetime-local"] {
    height: 32px;
    padding: 0 10px;
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-sm);
    /* background-color, not the shorthand: the chevron below is a background
       image on the same element, and a shorthand here would reset it. */
    background-color: var(--vantage-fill);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13px;
}
#lms-panel-main select:not([class*="tabulator"]):not(.lms-hedge-ccy-select) {
    /* The system chevron goes with the system widget; this is the same mark
       the application's own menus use, drawn as a background image so the
       control keeps native keyboard behaviour. */
    appearance: none;
    padding-right: 30px;
    background-image: url( "data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b8b8b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E" );
    background-repeat: no-repeat;
    background-position: right 9px center;
    background-size: 14px;
}
#lms-panel-main select:hover:not([class*="tabulator"]):not(.lms-hedge-ccy-select),
#lms-panel-main input[type="date"]:hover { border-color: var(--vantage-line); background-color: var(--vantage-fill-2); }
/* The calendar button the browser supplies is a dark glyph on a dark field. */
#lms-panel-main input[type="date"]::-webkit-calendar-picker-indicator,
#lms-panel-main input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    filter: invert(0.65);
    cursor: pointer;
}
html[data-theme="paper"] #lms-panel-main input[type="date"]::-webkit-calendar-picker-indicator,
html[data-theme="paper"] #lms-panel-main input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    filter: none;
}

@media (max-width: 620px) {
    /* A thumb, not a pointer. Same selector as the rule above, :not()s and all:
       a shorter one carries less specificity and loses, and stating it after
       rather than before matters for the same reason. */
    #lms-panel-main select:not(.tabulator-header-filter select):not([class*="tabulator"]):not(.lms-hedge-ccy-select),
    #lms-panel-main input[type="date"],
    #lms-panel-main input[type="datetime-local"] { height: 44px; }
}

/* ─── Grid colour key ──────────────────────────────────────── */
/* A quiet strip naming what the row colours mean, on the screens that use
   them — the user guide's table, carried onto the screen it describes. */
.lms-grid-key {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 18px;
    padding: 7px 12px;
    border-bottom: 1px solid var(--vantage-line-2);
    font-size: 11.5px;
    color: var(--vantage-text-2);
}
.lms-grid-key-item { display: inline-flex; align-items: center; gap: 7px; }
.lms-grid-key-swatch {
    width: 16px;
    height: 12px;
    border-radius: 3px;
    border: 1px solid var(--vantage-line);
    flex: none;
}
.lms-grid-key-strike { text-decoration: line-through; color: var(--vantage-text-3); }
.lms-grid-key-bold { font-weight: 600; }
@media (max-width: 560px) { .lms-grid-key { gap: 4px 12px; padding: 6px 10px; } }

/* ─── Grid skin: the table study, applied ──────────────────── */
/* Dark themes were the last still zebra-striping (light dropped it in the
   redesign): stripes fought the row tints, the selection wash and the dirty
   amber. Hairlines and a hover wash do the row-tracking instead, matching
   every card on the dashboard. */
html.dark-mode .tabulator .tabulator-row { border-bottom: 1px solid var(--vantage-line-2) !important; }
html.dark-mode .tabulator .tabulator-row.tabulator-row-even { background-color: transparent !important; }

/* Rows breathe: 40px, or 32px under the View menu's Compact density. Cells
   centre their content in the row instead of padding to a height. */
:root { --lms-grid-row: 40px; }
html[data-density="compact"] { --lms-grid-row: 32px; }
#lms-panel-main .tabulator .tabulator-row { min-height: var(--lms-grid-row); }
#lms-panel-main .tabulator .tabulator-cell {
    display: inline-flex;
    align-items: center;
    height: var(--lms-grid-row);
    padding-top: 0;
    padding-bottom: 0;
}
/* A flex container ignores text-align, so the moment cells became flex the
   right-aligned money fell to the left of its column and the centred
   machinery hugged the padding edge — headers, which are not flexed, stayed
   put, and the grid read as out of line with itself. Tabulator writes its
   hozAlign as an inline text-align, so justify-content is mapped from it. */
#lms-panel-main .tabulator .tabulator-cell[style*="text-align: right"],
#lms-panel-main .tabulator .tabulator-cell[style*="text-align:right"] {
    justify-content: flex-end;
}
#lms-panel-main .tabulator .tabulator-cell[style*="text-align: center"],
#lms-panel-main .tabulator .tabulator-cell[style*="text-align:center"],
#lms-panel-main .tabulator .tabulator-cell.lms-row-sel-col,
#lms-panel-main .tabulator .tabulator-cell.lms-row-act-col,
#lms-panel-main .tabulator .tabulator-cell[tabulator-field="_lms_expand"] {
    justify-content: center;
}

/* Headers a step quieter than their data; the sorted column answers in full
   ink so the sort is findable without hunting for a 10px arrow. */
#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-col-title {
    font-size: 11.5px;
    color: var(--vantage-text-3);
    line-height: 36px;
}
#lms-panel-main .tabulator .tabulator-header { min-height: 36px; }
#lms-panel-main .tabulator .tabulator-col[aria-sort="ascending"] .tabulator-col-title,
#lms-panel-main .tabulator .tabulator-col[aria-sort="descending"] .tabulator-col-title {
    color: var(--vantage-text);
}

/* The select checkbox rests hidden and surfaces for the pointer, the
   keyboard, any existing selection, or a touch device — the study's reveal
   rules, restated against Tabulator's markup. The header's select-all is
   always visible. */
#lms-panel-main .tabulator .tabulator-cell.lms-row-sel-col input {
    opacity: 0;
    transition: opacity 0.1s ease;
}
#lms-panel-main .tabulator .tabulator-row:hover .lms-row-sel-col input,
#lms-panel-main .tabulator .tabulator-row:focus-within .lms-row-sel-col input,
#lms-panel-main .tabulator .tabulator-row.tabulator-selected .lms-row-sel-col input,
#lms-panel-main .tabulator.lms-has-sel .lms-row-sel-col input,
#lms-panel-main .lms-has-sel .tabulator .lms-row-sel-col input { opacity: 1; }

/* The ⋮ is always present, at rest, on every row. It used to reveal on hover
   like the checkbox beside it, but a checkbox is a control you go looking for
   having already decided to select something, whereas the ⋮ is how you find
   out what a row can do at all - hidden until hovered, it read as an empty
   column, and it is unreachable without a pointer. It stays quiet through
   colour rather than through absence. */
#lms-panel-main .tabulator .lms-row-act-btn {
    border: 0;
    background: transparent;
    color: var(--vantage-text-3);
    font-size: 15px;
    cursor: pointer;
    opacity: 1;
}
#lms-panel-main .tabulator .tabulator-row:hover .lms-row-act-btn,
#lms-panel-main .tabulator .lms-row-act-btn:hover,
#lms-panel-main .tabulator .lms-row-act-btn:focus-visible { color: var(--vantage-text); }

/* No pointer means no hover: everything hover-revealed is simply there. */
@media (hover: none) {
    #lms-panel-main .tabulator .lms-row-sel-col input { opacity: 1 !important; }
}

/* Select and actions now sit together at the row's start, frozen left, so one
   hairline closes the pair off from the data rather than one between them. */
#lms-panel-main .tabulator .tabulator-cell.lms-row-sel-col,
#lms-panel-main .tabulator .tabulator-col.lms-row-sel-col {
    border-right: 0 !important;
}
#lms-panel-main .tabulator .tabulator-cell.lms-row-act-col,
#lms-panel-main .tabulator .tabulator-col.lms-row-act-col {
    border-left: 0 !important;
    border-right: 1px solid var(--vantage-line-2) !important;
}

/* ─── Report viewer ────────────────────────────────────────── */
/* The generated report is a whole HTML document, shown in a frame inside the
   dialog rather than in a second browser window. */
.lms-report-loading { padding: 24px 4px; font-size: 12.5px; color: var(--vantage-text-2); }
.lms-report-frame[hidden] { display: none; }
.lms-report-frame {
    display: block;
    width: 100%;
    height: 100%;
    min-height: 420px;
    border: 0;
    border-radius: var(--vantage-r-sm);
    background: #fff;
}

/* ─── Row selection ────────────────────────────────────────── */
/* Selecting is its own act with its own control, so the checkbox leads the row
   and the whole cell answers a click, not the 13px box inside it. */
.lms-row-sel-col { cursor: pointer; }
.lms-row-sel-col input[type="checkbox"] {
    width: 14px;
    height: 14px;
    accent-color: var(--vantage-accent);
    cursor: pointer;
    vertical-align: middle;
}
@media (max-width: 768px) {
    .lms-row-sel-col input[type="checkbox"] { width: 18px; height: 18px; }
}

/* ─── Settings ─────────────────────────────────────────────── */
/* Two columns on a wide window: what you are on the left, how this device
   behaves on the right. One column left the content stranded against the left
   edge of a panel twice its width, which read as unfinished rather than short. */
.st-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; max-width: 1180px; }
.st-col { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.st-col > .st-card { margin: 0; }

/* Spacing that was carried on the elements themselves. */
.st-inline { margin-top: 10px; }
/* A control that cannot act should recede rather than sit there as a filled
   slab inviting a click that does nothing. */
.st-btn:disabled { opacity: 0.45; cursor: default; }
.st-btn-primary:disabled { background: var(--vantage-fill-2); color: var(--vantage-text-2); }
.st-hint-inline { margin: 0; }
.st-hint-block { margin-top: 14px; }
.st-hint-block[hidden] { display: none; }
.st-state { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.st-msg { margin-top: 10px; font-size: 12px; min-height: 16px; }


@media (max-width: 1100px) {
    .st-grid { grid-template-columns: 1fr; max-width: 640px; }
}

/* ─── Application bar: account ─────────────────────────────── */
/* At the right-hand end of the bar, where this belongs, rather than holding a
   permanent strip at the foot of the sidebar. */
/* Behind a hairline, the same way the bar separates history from create and
   chat: the account is a different kind of control from the view toggles it
   sits beside, and the rule says so without adding a word. */
.lms-tb-acct {
    position: relative;
    display: inline-flex;
    align-items: center;
    margin-left: 7px;
    padding-left: 7px;
    border-left: 1px solid var(--vantage-line-2);
}
.lms-tb-acct-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    max-width: 190px;
    height: 30px;
    padding: 0 9px 0 4px;
    border: 1px solid transparent;
    border-radius: 999px;
    background: transparent;
    color: var(--vantage-text-2);
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    cursor: pointer;
    transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}
.lms-tb-acct-btn:hover { background: var(--vantage-fill); color: var(--vantage-text); }
.lms-tb-acct-btn[aria-expanded="true"] { background: var(--vantage-fill-2); color: var(--vantage-text); }
.lms-tb-acct-btn .lms-avatar { width: 22px; height: 22px; font-size: 10px; flex: none; }
/* The name is the first thing to go when the bar runs short of room: losing a
   label is better than losing the control. */
.lms-tb-acct-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 1180px) {
    .lms-tb-acct-name { display: none; }
    .lms-tb-acct-btn { padding-right: 4px; }
}

.lms-tb-acct-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 10002;
    min-width: 210px;
    padding: 5px;
    border: 1px solid var(--vantage-line);
    border-radius: 11px;
    background: var(--vantage-surface);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.28);
    animation: lms-pop-in 0.1s ease-out;
}
.lms-tb-acct-menu[hidden] { display: none; }
/* The menu repeats the name and carries the organisation, which the bar itself
   has no room for and which matters on a shared machine. */
.lms-tb-acct-head { padding: 7px 10px 9px; border-bottom: 1px solid var(--vantage-line-2); margin-bottom: 4px; }
.lms-tb-acct-head-name { font-size: 13px; color: var(--vantage-text); }
.lms-tb-acct-head-sub  { margin-top: 2px; font-size: 11.5px; color: var(--vantage-text-2); }
.lms-tb-acct-menu .lms-acct-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: var(--vantage-r-sm);
    background: transparent;
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}
.lms-tb-acct-menu .lms-acct-item:hover { background: var(--vantage-fill-2); }

/* ─── Status pills ─────────────────────────────────────────── */
/* One shape for every status in the application, coloured by what the status
   means rather than by where it appears, and from tokens so it follows the
   theme instead of being the same hex in all four. */
.lms-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 9px 2px 8px;
    border-radius: var(--vantage-r-sm);
    font-size: 11px;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
}
.lms-pill-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.lms-pill-good    { color: var(--lms-success-ink); background: color-mix( in srgb, var(--lms-success-ink) 11%, transparent ); }
.lms-pill-warning { color: var(--lms-warning-ink); background: color-mix( in srgb, var(--lms-warning-ink) 11%, transparent ); }
.lms-pill-bad     { color: var(--lms-danger-ink);  background: color-mix( in srgb, var(--lms-danger-ink)  11%, transparent ); }
.lms-pill-neutral { color: var(--vantage-text-2);   background: var(--vantage-fill); }

/* ─── Hedges grid: Proposed CCY select + Hedge Status action button ──── */
/* Finance > Hedges (js-lms/lms.js). The button reuses .lms-pill's shape/inks
   as a genuine clickable <button> rather than a decorative span - a real
   UA-styled border/background would clash with the pill look, so both are
   reset here. Explicitly excluded from the generic #lms-panel-main select
   rule above (its own :not() list) rather than merely coming after it in
   source order: that rule is ID-scoped and beat this class-only selector on
   specificity regardless of order, silently handing this compact
   6-currency-code control the generic rule's 32px height, 10px/30px
   padding, and near-transparent --vantage-fill background meant for a
   full-width form select - the translucent background let the row's own
   hover/selected-row tint bleed through (reads as the control being
   "garbled" by whatever's behind it), and the oversized chevron gutter
   pushed a 3-letter code visibly off-centre in a ~140px grid cell. */
.lms-hedge-ccy-select {
    font: inherit;
    font-size: 12px;
    /* line-height must be set explicitly: `font: inherit` also inherits the
       surrounding grid cell's (taller) line-height, which otherwise pushes
       this control's single line of text toward the bottom of its 24px box
       rather than centering it vertically. box-sizing keeps the 24px height
       covering the border too, so line-height only needs to fill the space
       actually left for content. */
    box-sizing: border-box;
    height: 24px;
    line-height: 22px;
    padding: 0 20px 0 6px;
    text-align-last: center;
    border-radius: var(--vantage-r-sm);
    border: 1px solid var(--vantage-line);
    /* background-color, not the shorthand: the chevron below is a background
       image on the same element (same reasoning as the generic rule above). */
    background-color: var(--vantage-surface);
    background-image: url( "data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b8b8b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E" );
    background-repeat: no-repeat;
    background-position: right 4px center;
    background-size: 12px;
    appearance: none;
    color: var(--vantage-text);
}
/* The open dropdown's own option list is not reliably painted from the
   <select>'s background/color - most browsers render that popup with an
   OS-native background regardless of the closed control's own styling, and
   only honour an option's color/background when BOTH are set together on
   the option itself. Without this, dark mode's light --vantage-text was
   rendered on that native (light) popup background: readable when closed,
   genuinely invisible the moment the list opened. */
.lms-hedge-ccy-select option {
    background-color: var(--vantage-surface);
    color: var(--vantage-text);
}
button.lms-hedge-btn {
    border: none;
    font: inherit;
    cursor: pointer;
}
button.lms-hedge-btn:disabled {
    cursor: not-allowed;
    opacity: .55;
}

/* ─── Accessibility scaffolding ────────────────────────────── */
/* Present to a screen reader, absent to everything else. Used for the heading
   that names each screen: every screen needs one, and almost none of them show
   one, because the sidebar and the window title already say where you are. */
.lms-visually-hidden {
    position: absolute !important;
    /* Anchored rather than left at its static position: appended to the end of
       a body whose shell is already a full viewport tall, an unanchored copy
       lands just below the fold and gives the window a scrollbar. */
    top: 0; left: 0;
    width: 1px; height: 1px;
    margin: -1px; padding: 0; border: 0;
    clip-path: inset(50%);
    overflow: hidden; white-space: nowrap;
}

/* The first thing a keyboard reaches. Twenty-three tab stops used to separate
   the top of the page from the data, every one of them a sidebar control. */
.lms-skip-link {
    position: fixed;
    top: 8px; left: 8px;
    z-index: 200;
    padding: 9px 14px;
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-sm);
    background: var(--vantage-surface);
    color: var(--vantage-text) !important;
    font-family: var(--vantage-font-body);
    font-size: 13px;
    text-decoration: none;
    transform: translateY(-160%);
    transition: transform .12s ease-out;
}
.lms-skip-link:focus { transform: translateY(0); }

/* One focus style for the whole application, from the palette rather than the
   browser's default hairline. :where() keeps its specificity at zero so a
   component can still say something different. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 2px solid var(--vantage-accent);
    outline-offset: 2px;
}
/* Inputs that had removed the outline entirely and replaced it with nothing. */
.lms-tabgrid-search:focus-visible,
.lms-gf-search input:focus-visible,
.lms-rp-input:focus-visible {
    outline: 2px solid var(--vantage-accent);
    outline-offset: 1px;
}

/* ─── Grid: loading and failure ────────────────────────────── */
/* Over the table rather than instead of it: the columns stay where they are,
   so nothing jumps when the rows arrive. */
.lms-grid-overlay {
    position: absolute;
    inset: 0;
    z-index: 5;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 24px;
    text-align: center;
    background: color-mix( in srgb, var(--vantage-bg) 88%, transparent );
    backdrop-filter: blur(1px);
}
.lms-grid-overlay-text { font-size: 13px; color: var(--vantage-text-2); }
.lms-grid-overlay .lms-empty-title { font-family: var(--vantage-font-heading); font-size: 14px; }
.lms-grid-overlay .lms-empty-hint  { font-size: 12.5px; color: var(--vantage-text-2); max-width: 380px; }
.lms-grid-spinner {
    width: 20px; height: 20px;
    border: 2px solid var(--vantage-line);
    border-top-color: var(--vantage-accent);
    border-radius: 50%;
    animation: lms-spin .7s linear infinite;
}
@keyframes lms-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .lms-grid-spinner { animation-duration: 2.4s; }
}
.lms-grid-retry {
    margin-top: 2px;
    padding: 6px 14px;
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-sm);
    background: var(--vantage-fill);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    cursor: pointer;
}
.lms-grid-retry:hover { background: var(--vantage-fill-2); }

/* ─── Record panel ─────────────────────────────────────────── */
/* Docked under the grid it belongs to. Flat and edge to edge, like the grid:
   no rounded card on a surface that deliberately has none. */
#lms-record-panel {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    min-height: 0;
    border-top: 1px solid var(--vantage-line);
    background: var(--vantage-surface);
}
#lms-record-panel[hidden] { display: none; }

/* The whole top edge is the resize handle, so it does not need finding. */
.lms-rp-grab { height: 5px; margin-top: -3px; cursor: ns-resize; flex-shrink: 0; }
.lms-rp-grab:hover { background: color-mix(in srgb, var(--vantage-accent) 35%, transparent); }

.lms-rp-head {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 40px;
    padding: 0 8px 0 14px;
    flex-shrink: 0;
    border-bottom: 1px solid var(--vantage-line-2);
}
/* Title and subtitle share a baseline with each other; the pair as a whole is
   centred in the band, so the buttons opposite line up with it. */
.lms-rp-ident { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.lms-rp-title { font-family: var(--vantage-font-heading); font-size: 14px; font-weight: 500;
                white-space: nowrap; }
.lms-rp-sub { font-size: 12px; color: var(--vantage-text-2); max-width: 420px;
              overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lms-rp-acts { margin-left: auto; display: flex; gap: 2px; }
.lms-rp-icon {
    width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
    border: 0; border-radius: var(--vantage-r-sm); background: transparent;
    color: var(--vantage-text-2); font-size: 15px; cursor: pointer;
}
.lms-rp-icon:hover { background: var(--vantage-fill-2); color: var(--vantage-text); }

.lms-rp-body { flex: 1; min-height: 0; overflow: auto; padding: 4px 14px 10px; }
/* Columns rather than one long list: a record with twenty fields is a wall in
   a single column, and the panel is wide and short by shape. */
.lms-rp-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 0 26px; }
.lms-rp-fact {
    display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
    padding: 7px 0; border-bottom: 1px solid var(--vantage-line-2);
}
.lms-rp-k { font-size: 12.5px; color: var(--vantage-text-2); }
.lms-rp-v { font-size: 12.5px; text-align: right; font-variant-numeric: tabular-nums;
            word-break: break-word; }

/* Editable fields. The affordance stays quiet until the pointer is on the
   field, so a panel opened to read is a page of values rather than a form. */
.lms-rp-v.is-editable { cursor: text; border-radius: var(--vantage-r-sm); padding: 1px 5px; margin: -1px -5px; }
.lms-rp-v.is-editable:hover { background: var(--vantage-fill); }
.lms-rp-v.is-editable:focus-visible { outline: 2px solid var(--vantage-accent); outline-offset: 1px; }
.lms-rp-empty { color: var(--vantage-text-3); font-style: italic; }
.lms-rp-v.is-editing { background: var(--vantage-fill); padding: 0; margin: 0; }
.lms-rp-input {
    width: 100%;
    box-sizing: border-box;
    padding: 2px 6px;
    border: 1px solid var(--vantage-accent);
    border-radius: var(--vantage-r-sm);
    background: var(--vantage-bg);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    text-align: right;
}
/* Checkbox shape/colour lives in the shared rule further down (search
   "reshaped rather than left as the browser's raw control"), so every
   checkbox in the app - grid cells, popups, this panel - looks the same. */
select.lms-rp-input { text-align: left; }
/* Unsaved, said exactly as the grid says it on the row: the same amber wash and
   the same leading bar, so one record cannot look pending in one place and
   settled in the other. */
.lms-rp-fact.is-dirty {
    background: color-mix( in srgb, var(--vantage-brand-c) 15%, transparent );
    box-shadow: inset 2px 0 0 var(--vantage-brand-c);
    padding-left: 8px;
    margin-left: -8px;
}

/* Taskbar of parked records. Minimising keeps a record; this is where it is
   kept, so several can be held while another is read. Squared and flush, like
   the application bar it echoes: a parked record is a held window, not a
   filter, and the pill shape belongs to the filter chips above the grid. */
#lms-record-bar {
    flex-shrink: 0;
    display: flex;
    align-items: stretch;
    height: 31px;
    overflow-x: auto;
    border-top: 1px solid var(--vantage-line);
    background: var(--vantage-bg);
}
#lms-record-bar[hidden] { display: none; }
.lms-rp-chip {
    position: relative;
    display: inline-flex; align-items: center; gap: 8px; flex-shrink: 0;
    max-width: 260px;
    padding: 0 8px 0 12px;
    border: 0; border-right: 1px solid var(--vantage-line-2);
    background: transparent; color: var(--vantage-text-2);
    cursor: pointer; font-size: 12px; line-height: 1;
}
/* A hairline along the top edge marks it as held, in the same place a tab
   would carry it, and costs no space. */
.lms-rp-chip::before {
    content: ''; position: absolute; inset: 0 0 auto 0; height: 2px;
    background: color-mix( in srgb, var(--vantage-accent) 45%, transparent );
}
.lms-rp-chip:hover { background: var(--vantage-fill); color: var(--vantage-text); }
.lms-rp-chip:hover::before { background: var(--vantage-accent); }
.lms-rp-chip-t { font-weight: 500; white-space: nowrap; color: var(--vantage-text); }
.lms-rp-chip-s { color: var(--vantage-text-3); overflow: hidden;
                 text-overflow: ellipsis; white-space: nowrap; }
/* Held out of the way until wanted: a row of crosses along the foot of the
   screen is noise, and the record is discarded far less often than it is
   reopened. Focus brings it back for the keyboard. */
.lms-rp-chip-x {
    border: 0; background: transparent; color: var(--vantage-text-3);
    cursor: pointer; font-size: 13px; line-height: 1; padding: 3px 4px;
    opacity: 0; transition: opacity .12s linear;
}
.lms-rp-chip:hover .lms-rp-chip-x,
.lms-rp-chip-x:focus-visible { opacity: 1; }
.lms-rp-chip-x:hover { color: var(--vantage-text); }

/* The row on show, and the rows being held on the taskbar. */
#lms-panel-main .tabulator .tabulator-row.lms-rp-selected {
    background: color-mix(in srgb, var(--vantage-accent) 13%, transparent);
}
#lms-panel-main .tabulator .tabulator-row.lms-rp-parked {
    box-shadow: inset 3px 0 0 color-mix(in srgb, var(--vantage-accent) 55%, transparent);
}

/* Phones expand the row instead; the panel never mounts there. */
@media (max-width: 768px) {
    #lms-record-panel, #lms-record-bar { display: none !important; }
}

/* ─── Funder cash-flow schedule panel ──────────────────────── */
/* js-lms/funder_schedule_panel.js - a sibling to the record panel above,
   reusing its docking shape (grab handle, flat/edge-to-edge, border-top)
   but its own class prefix since it shows fetched schedule data rather
   than a grid row's own rendered columns. */
#lms-funder-schedule-panel {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    min-height: 0;
    border-top: 1px solid var(--vantage-line);
    background: var(--vantage-surface);
}
#lms-funder-schedule-panel[hidden] { display: none; }

.lms-fsp-grab { height: 5px; margin-top: -3px; cursor: ns-resize; flex-shrink: 0; }
.lms-fsp-grab:hover { background: color-mix(in srgb, var(--vantage-accent) 35%, transparent); }

.lms-fsp-head {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 40px;
    padding: 0 8px 0 14px;
    flex-shrink: 0;
    border-bottom: 1px solid var(--vantage-line-2);
}
.lms-fsp-title { font-family: var(--vantage-font-heading); font-size: 14px; font-weight: 500; }
.lms-fsp-close {
    margin-left: auto;
    width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
    border: 0; border-radius: var(--vantage-r-sm); background: transparent;
    color: var(--vantage-text-2); font-size: 15px; cursor: pointer;
}
.lms-fsp-close:hover { background: var(--vantage-fill-2); color: var(--vantage-text); }

.lms-fsp-body { flex: 1; min-height: 0; overflow: auto; padding: 10px 14px 14px; }
.lms-fsp-loading, .lms-fsp-empty, .lms-fsp-error { color: var(--vantage-text-2); font-style: italic; padding: 10px 0; }
.lms-fsp-error { color: var(--lms-danger-ink); }

.lms-fsp-schedule-head { display: flex; align-items: baseline; gap: 10px; margin: 14px 0 2px; }
.lms-fsp-schedule-head:first-child { margin-top: 0; }
.lms-fsp-schedule-funder { font-size: 13.5px; font-weight: 600; }
.lms-fsp-schedule-meta { font-size: 12px; color: var(--vantage-text-2); }
.lms-fsp-schedule-rate { font-size: 12.5px; color: var(--vantage-text-2); margin-bottom: 6px; }

.lms-fsp-table { width: 100%; border-collapse: collapse; font-size: 12.5px; margin-bottom: 6px; }
.lms-fsp-table th {
    text-align: left; font-weight: 600; color: var(--vantage-text-2);
    padding: 4px 8px; border-bottom: 1px solid var(--vantage-line);
}
.lms-fsp-table td { padding: 4px 8px; border-bottom: 1px solid var(--vantage-line-2); }
.lms-fsp-table .lms-fsp-num { text-align: right; font-variant-numeric: tabular-nums; }
.lms-fsp-row-projected { color: var(--vantage-text-2); }
.lms-fsp-leg-tag { margin-left: 6px; font-weight: 500; cursor: help; }
/* Secondary line inside a hedge-leg cell (exchange name under a contract code,
   last trading day under a delivery month): present but subordinate to the
   figure above it, so the table still scans on one line per leg. */
.lms-fsp-sub { font-size: 11px; color: var(--vantage-text-2); }
.lms-fsp-warn-ink { color: var(--lms-warning-ink); font-weight: 500; }

.lms-fsp-redemption { font-size: 12.5px; color: var(--vantage-text-2); padding: 4px 0 12px; }

/* Divides the cash-flow schedule from the proposed hedge below it in the
   same panel body (js-lms/funder_schedule_panel.js) - a plain rule rather
   than a second .lms-fsp-head bar, since this is a section within one
   scrolling body, not a second docked panel. */
.lms-fsp-section-head {
    font-family: var(--vantage-font-heading); font-size: 13px; font-weight: 600;
    margin: 18px 0 8px; padding-top: 12px; border-top: 1px solid var(--vantage-line-2);
}

@media (max-width: 768px) {
    #lms-funder-schedule-panel { display: none !important; }
}

/* ─── Surface: dashboard ───────────────────────────────────── */
.dash-root {
    --lms-bg: var(--vantage-bg);
    --lms-bg-panel: var(--vantage-fill);
    --lms-border: var(--vantage-line-2);
    --lms-text: var(--vantage-text);
    --lms-text-muted: var(--vantage-text-2);
    --lms-text-label: var(--vantage-text-3);
    font-family: var(--vantage-font-body);
    color: var(--vantage-text);
    background: var(--vantage-bg);
    padding: 22px 24px;
    height: 100%;
    overflow-y: auto;
    box-sizing: border-box;
}
.dash-head { margin-bottom: 18px; }
.dash-title {
    margin: 0 0 3px;
    font-family: var(--vantage-font-heading);
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.02em;
}
.dash-sub { font-size: 12.5px; color: var(--vantage-text-2); }

/* Attention on the left at roughly three fifths, because it is the reason to
   open the page; standing figures sit beside it rather than above it. */
.dash-grid { display: grid; grid-template-columns: 1.55fr 1fr; gap: 14px; align-items: start; }
/* On a wide monitor the cards used to stretch the full width of the panel and
   a facility row became a reference on the far left and a percentage on the far
   right with a foot of nothing between them. The page stops growing before the
   eye has to travel that far; the sidebar already anchors it to the left. */
.dash-root { max-width: 1560px; }
/* Grid and flex children default to min-width:auto, so a long reference would
   push a track wider than its container instead of wrapping inside it. */
.dash-col, .dash-card, .dash-at-body, .dash-bar-top span { min-width: 0; }
/* The pipeline reads left to right, so it runs under both columns rather than
   lengthening the taller one. Empty when no origination stage is permitted. */
.dash-col-wide { grid-column: 1 / -1; }
.dash-col-wide:empty { display: none; }

/* DESIGN_PROTOCOL.md, Section 0: a 1px outline round every panel is the
   default AI look. These are separated by surface instead, a step up from the
   page behind them. The ban applies to panels, not to the Tabulator grids
   further up this file, whose rules do real work across 25 columns. */
.dash-card {
    border: 0;
    border-radius: var(--vantage-r-lg);
    background: var(--vantage-surface);
}
.dash-card-head { display: flex; align-items: baseline; gap: 8px; padding: 11px 14px 8px; }
.dash-card-title { font-family: var(--vantage-font-heading); font-size: 13px; font-weight: 500; }
.dash-card-note { margin-left: auto; font-size: 11.5px; color: var(--vantage-text-3); }

/* Needs attention: a worklist, so rows rather than cards. */
.dash-at-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px;
    border-top: 1px solid var(--vantage-line-2);
}
.dash-at-sev { width: 3px; align-self: stretch; border-radius: 2px; flex-shrink: 0; }
.dash-at-sev-1 { background: var(--lms-danger-text); }
.dash-at-sev-2 { background: var(--lms-warning-text); }
.dash-at-sev-3 { background: var(--vantage-text-3); }
.dash-at-body { flex: 1; }
.dash-at-title { display: block; font-size: 13px; }
.dash-at-sub { display: block; margin-top: 1px; font-size: 11.5px; color: var(--vantage-text-3); }
.dash-at-value {
    font-family: var(--vantage-font-heading);
    font-weight: 500;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* This page carries more than one kind of percentage (loan to value and share
   drawn), so a bare % against a facility reference could be read as the other. */
.dash-at-unit { font-family: var(--vantage-font-body); font-weight: 400; font-size: 11px; color: var(--vantage-text-3); }
.dash-at-chev { color: var(--vantage-text-3); font-size: 15px; flex-shrink: 0; user-select: none; }
/* A reference never breaks across lines: half an id reads as a different loan. */
.dash-nowrap { white-space: nowrap; }

/* Standing figures. */
.dash-kv {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 7px 14px;
    border-top: 1px solid var(--vantage-line-2);
}
.dash-kv-k { font-size: 12px; color: var(--vantage-text-2); }
.dash-kv-v {
    font-family: var(--vantage-font-heading);
    font-weight: 700;
    font-size: 14px;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.dash-kv-big { font-size: 21px; }

/* Figures, not bars, on all three list cards. Facility utilisation always
   worked this way and was the clearest card on the page; maturity and
   concentration now follow it. A bar under a printed percentage restates the
   same number in a fuzzier language, and it forced a choice between drawing a
   0.2% bucket as an invisible sliver or a dishonest floored one. Colour
   appears only where a line is nearly gone or a name is concentrated. */
.dash-line-row {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 8px 14px;
    border-top: 1px solid var(--vantage-line-2);
}
.dash-line-id { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 8px; }
.dash-line-label { font-size: 12.5px; white-space: nowrap; }
.dash-line-sub {
    font-size: 12px;
    color: var(--vantage-text-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dash-line-money {
    font-size: 12.5px;
    color: var(--vantage-text-2);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.dash-line-pct {
    min-width: 52px;
    font-family: var(--vantage-font-heading);
    font-weight: 500;
    font-size: 12.5px;
    font-variant-numeric: tabular-nums;
    text-align: right;
    white-space: nowrap;
}
.dash-line-pct.dash-line-warn { color: var(--lms-warning-ink); }
.dash-line-pct.dash-line-bad  { color: var(--lms-danger-ink); }
/* A bucket with nothing in it says so where its money would be. */
.dash-line-none { color: var(--vantage-text-3); }

.dash-clear { display: flex; align-items: flex-start; gap: 12px; padding: 16px 14px; border-top: 1px solid var(--vantage-line-2); }
.dash-clear-ico {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 15px;
    color: var(--lms-success-text);
    background: color-mix(in srgb, var(--lms-success-text) 14%, transparent);
}
.dash-clear-title { font-size: 13px; margin-bottom: 3px; }
.dash-clear-sub { font-size: 11.5px; color: var(--vantage-text-3); line-height: 1.55; }

/* A figure that leads somewhere carries the same chevron as every other
   click-through on the page, and only shows it under the pointer. */
.dash-kv.dash-nav { cursor: pointer; }
.dash-kv-go {
    margin-left: 8px;
    color: var(--vantage-text-3);
    opacity: 0;
    transition: opacity 0.12s ease;
}
.dash-kv.dash-nav:hover .dash-kv-go,
.dash-kv.dash-nav:focus-visible .dash-kv-go { opacity: 1; }
.dash-kv-v.dash-kv-warn { color: var(--lms-warning-ink); }

/* A stage with nothing waiting in it is context, not news. */
.dash-pipe-empty .dash-pipe-label,
.dash-pipe-empty .dash-pipe-count { color: var(--vantage-text-3); }

/* An empty maturity bucket keeps its line but loses the meter, so the row is
   an absence rather than a measurement of nothing. */

/* The heading line carries the time the figures were read and the way to read
   them again, so "is this live?" has an answer on the page. */
.dash-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.dash-asat { color: var(--vantage-text-3); }
.dash-refresh {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex: none;
    padding: 6px 12px;
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-sm);
    background: transparent;
    color: var(--vantage-text-2);
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.dash-refresh svg { width: 14px; height: 14px; }
.dash-refresh:hover { background: var(--vantage-fill); color: var(--vantage-text); }

/* A card with nothing in it still holds its place on the page, and carries the
   three things an empty state owes the reader (DESIGN_PROTOCOL.md, Stage 3): a
   mark, a sentence saying what would fill it, and the way to go and do that. */
.dash-card-none {
    display: grid;
    justify-items: center;
    text-align: center;
    gap: 10px;
    padding: 24px 16px 26px;
    border-top: 1px solid var(--vantage-line-2);
    font-size: 12.5px;
    color: var(--vantage-text-3);
}
.dash-none-mark {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: var(--vantage-fill);
    color: var(--vantage-text-3);
}
.dash-none-line { max-width: 46ch; line-height: 1.55; }
.dash-none-cta {
    min-height: 34px;
    padding: 0 14px;
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-sm);
    background: var(--vantage-fill);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    cursor: pointer;
    transition: background-color 0.15s cubic-bezier(0.4,0,0.2,1), border-color 0.15s cubic-bezier(0.4,0,0.2,1);
}
.dash-none-cta:hover { background: var(--vantage-fill-2); border-color: var(--vantage-text-3); }

/* Disabled is drawn, not merely set: dimmed, cursor blocked, hover removed so
   the control stops inviting a press it will not honour. */
.dash-refresh:disabled,
.dash-none-cta:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}
.dash-refresh:disabled:hover,
.dash-none-cta:disabled:hover {
    background: var(--vantage-fill);
    border-color: var(--vantage-line);
}

/* ─── Dashboard: charts ────────────────────────────────────── */
/* Two series in a fixed order, validated against both surfaces with the
   palette checker rather than by eye: the brand lavender sits outside the
   lightness band on a dark surface, so it steps down there. Worst adjacent
   pair separates by 26.6 ΔE for deuteranopia on dark, 25.2 protan on light.
   Status inks stay reserved for status and never identify a series. */
.dash-viz {
    --dash-s1: #9b78e8;
    --dash-s2: #d95926;
}
html[data-theme="paper"] .dash-viz { --dash-s1: #7c5cd6; --dash-s2: #d2603d; }

.dash-trends { display: grid; grid-template-columns: 1.55fr 1fr; gap: 14px; margin-bottom: 14px; }
.dash-trends-none { grid-template-columns: 1fr; }
.dash-chart { padding: 4px 14px 12px; border-top: 1px solid var(--vantage-line-2); }
.dash-chart-plot { display: flex; gap: 10px; }
.dash-y-axis {
    display: flex; flex-direction: column; justify-content: space-between;
    flex: none; padding: 2px 0 0;
    font-size: 10px; color: var(--vantage-text-3);
    font-variant-numeric: tabular-nums; text-align: right;
}
.dash-plot { position: relative; flex: 1; min-width: 0; height: 132px; }
.dash-plot-short { height: 108px; }
.dash-plot svg { display: block; width: 100%; height: 100%; }
.dash-x-axis {
    display: flex; justify-content: space-between;
    margin-top: 6px; font-size: 10px; color: var(--vantage-text-3);
}
/* The one value worth labelling directly; the axis and the row beneath carry
   the rest, and a number on every point goes unread. */
.dash-endpoint {
    position: absolute; right: 0;
    transform: translateY(-150%);
    font-size: 11px; color: var(--vantage-text);
    font-variant-numeric: tabular-nums;
}

.dash-viz-legend { display: flex; gap: 16px; margin: 8px 0 10px; font-size: 11.5px; color: var(--vantage-text-2); }
.dash-viz-legend i { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 6px; }
.dash-key-adv { background: var(--dash-s1); }
.dash-key-rec { background: var(--dash-s2); }

/* Columns are capped rather than filling their slot, and separated by a gap in
   the surface colour rather than by a stroke around each one. */
.dash-cols { display: flex; align-items: flex-end; gap: 3px; height: 100%; }
.dash-col-pair { flex: 1; display: flex; align-items: flex-end; justify-content: center; gap: 2px; height: 100%; min-width: 0; }
.dash-col-pair > span { width: 100%; max-width: 10px; min-height: 2px; border-radius: 3px 3px 0 0; }
.dash-bar-adv { background: var(--dash-s1); }
.dash-bar-rec { background: var(--dash-s2); }
.dash-col-pair:hover > span { opacity: 0.75; }

@media (max-width: 1100px) {
    .dash-trends { grid-template-columns: 1fr; }
}

/* ─── Dashboard: headline figures ──────────────────────────── */
/* The four numbers that answer "how is the book". They were rows on a card
   halfway down the page, set in the same 13px as a funder's name. */
/* Exposure leads; headroom, arrears and rate sit beside it. Four equal boxes
   made the size of the book and the rate charged on it look like the same
   kind of fact. */
.dash-lead {
    display: grid;
    grid-template-columns: minmax( 0, 1.05fr ) minmax( 0, 1.35fr );
    gap: 10px 32px;
    align-items: end;
    margin-bottom: 16px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--vantage-line-2);
}
.dash-lead-side { display: grid; grid-template-columns: repeat( 3, minmax( 0, 1fr ) ); gap: 20px; }
.dash-lead-figure .dash-kpi-v { font-size: 40px; line-height: 1.02; }
.dash-lead-figure .dash-kpi-s { margin-top: 7px; }
@media ( max-width: 1100px ) {
    .dash-lead { grid-template-columns: 1fr; align-items: start; }
}
@media ( max-width: 720px ) {
    .dash-lead-side { grid-template-columns: 1fr; gap: 14px; }
}

.dash-kpis {
    display: grid;
    grid-template-columns: repeat( 4, 1fr );
    gap: 14px;
    margin-bottom: 14px;
}
.dash-kpi {
    padding: 0;
    transition: color 0.12s ease;
}
.dash-kpi.dash-nav { cursor: pointer; }
.dash-kpi.dash-nav:hover .dash-kpi-v { color: var(--vantage-accent); }

.dash-kpi-k { display: block; font-size: 11.5px; color: var(--vantage-text-2); }
.dash-kpi-v {
    display: block;
    margin-top: 5px;
    font-family: var(--vantage-font-heading);
    font-weight: 700;
    font-size: 23px;
    letter-spacing: -0.02em;
    /* Proportional figures: equal-width digits make a display-size number look
       loose. Tabular is for columns that align vertically, not for this. */
}
.dash-kpi-v.dash-kpi-bad { color: var(--lms-danger-ink); }
.dash-kpi-s { display: block; margin-top: 6px; font-size: 11.5px; color: var(--vantage-text-3); }

/* ─── Dashboard: arrears ageing ────────────────────────────── */
.dash-age { display: grid; grid-template-columns: repeat( 4, 1fr ); border-top: 1px solid var(--vantage-line-2); }
.dash-age-c { padding: 11px 14px; border-right: 1px solid var(--vantage-line-2); }
.dash-age-c:last-child { border-right: 0; }
.dash-age-k { display: block; font-size: 11px; color: var(--vantage-text-3); }
.dash-age-v {
    display: block;
    margin-top: 4px;
    font-family: var(--vantage-font-heading);
    font-weight: 500;
    font-size: 14px;
    font-variant-numeric: tabular-nums;
}
.dash-age-v.dash-age-bad  { color: var(--lms-danger-ink); }
.dash-age-v.dash-age-none { color: var(--vantage-text-3); }
.dash-age-n { display: block; margin-top: 2px; font-size: 10.5px; color: var(--vantage-text-3); }

@media (max-width: 1100px) {
    .dash-kpis { grid-template-columns: repeat( 2, 1fr ); }
}
@media (max-width: 560px) {
    .dash-kpis { grid-template-columns: 1fr; gap: 10px; }
    .dash-kpi-v { font-size: 20px; }
    /* Four columns of ageing on a phone leaves four cramped strips; two rows of
       two keeps every figure readable. */
    .dash-age { grid-template-columns: repeat( 2, 1fr ); }
    .dash-age-c:nth-child(2n) { border-right: 0; }
    .dash-age-c:nth-child(-n+2) { border-bottom: 1px solid var(--vantage-line-2); }
}

/* ─── Dashboard: waiting and failing ───────────────────────── */
/* The page's own shape, drawn in grey, so nothing jumps when the figures land.
   Deliberately calm: a dashboard is read, not watched. */
.dash-skel-card { padding-bottom: 6px; }
.dash-skel-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    padding: 11px 14px;
    border-top: 1px solid var(--vantage-line-2);
}
.dash-skel {
    display: block;
    height: 11px;
    border-radius: 4px;
    background: var(--vantage-fill);
    animation: dash-skel-pulse 1.6s ease-in-out infinite;
}
.dash-skel-title { width: 108px; height: 12px; }
.dash-skel-note  { width: 64px;  height: 10px; }
.dash-skel-label { width: 42%; }
.dash-skel-value { width: 74px; }
.dash-skel-row:nth-child(odd)  .dash-skel-label { width: 54%; }
.dash-skel-row:nth-child(3n)   .dash-skel-label { width: 34%; }
.dash-skel-card .dash-skel { animation-delay: calc( var(--i, 0) * 0.08s ); }
@keyframes dash-skel-pulse { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
    .dash-skel { animation: none; opacity: 0.7; }
}

.dash-failed {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 44px 24px;
    text-align: center;
}
.dash-failed .lms-empty-hint { max-width: 420px; }

@media (max-width: 560px) {
    /* On a phone the detail line under an attention item ran to three lines and
       gave every row a different height, which turns a list you scan into a
       list you read. Two lines, then an ellipsis: the row leads to the screen
       that holds the rest. */
    .dash-at-sub {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }
    .dash-at-title { font-size: 12.5px; }
}

@media (max-width: 900px) {
    .dash-grid { grid-template-columns: 1fr; }
    .dash-col-wide { grid-column: auto; }
}
@media (max-width: 640px) {
    .dash-root { padding: 18px 14px; }
    .dash-at-item, .dash-kv, .dash-line-row, .dash-clear { padding-left: 12px; padding-right: 12px; }
    .dash-card-head { padding: 12px 13px 9px; }
    .dash-kv-big { font-size: 22px; }
}

/* ─── Geometry ─────────────────────────────────────────────────
   One radius scale, so corners read as a system rather than as
   whatever each component was written with. Measured before this
   existed: eight different radii on a single screen, most of them
   the legacy 6px. */
:root {
    --vantage-r-pill: 999px;   /* pills, chips, badges */
    --vantage-r-sm:   8px;     /* rows, small controls */
    --vantage-r-md:   9px;     /* buttons, inputs, fields */
    --vantage-r-lg:   12px;    /* cards and panels */
    --vantage-r-xl:   14px;    /* dialogs */
}
.lms-sidebar .lms-node { border-radius: var(--vantage-r-sm); }
.lms-sidebar .lms-pin  { border-radius: var(--vantage-r-sm); }
/* Status pills come from the grid formatters with their own corner; a pill
   is a pill. */
#lms-panel-main .tabulator .tabulator-cell span[style*="border-radius"] { border-radius: var(--vantage-r-pill) !important; }
#lms-panel-main .lms-gf-bar .lms-tabgrid-search { border-radius: var(--vantage-r-md); }

/* ─── Edges ────────────────────────────────────────────────────
   Borders where a surface genuinely changes, and nowhere else.
   Panels that sit against each other need a hairline or the eye
   cannot tell where one ends. */
.lms-layout > .lms-panel-left { border-right: 1px solid var(--vantage-line-2); }
#lms-panel-main .lms-tabgrid-footer {
    border-top: 1px solid var(--vantage-line-2);
    padding: 0 16px;
    height: 34px;
    display: flex;
    align-items: center;
    font-size: 12px;
    color: var(--vantage-text-3);
    background: var(--vantage-bg);
}
/* The count lives in the filter bar above the grid. The footer is kept for any
   screen that has no such bar, and stands down where there is one, so the
   screen never states the same figure twice. */
#lms-panel-main .lms-tabgrid-footer[hidden] { display: none; }
/* The frozen actions and select columns float over scrolled content, so
   each needs an edge of its own or the rows appear to run underneath
   nothing. */
#lms-panel-main .tabulator .tabulator-cell.lms-row-act-col,
#lms-panel-main .tabulator .tabulator-col.lms-row-act-col,
#lms-panel-main .tabulator .tabulator-cell.lms-row-sel-col,
#lms-panel-main .tabulator .tabulator-col.lms-row-sel-col {
    border-right: 1px solid var(--vantage-line-2) !important;
}
/* The cell inherits Tabulator's 12px/8px cell padding, leaving 20px of content
   box in a 40px column, but the button inside is 25px. It therefore overflowed
   and the browser drew Tabulator's text-overflow ellipsis after it, so every
   row on every grid rendered as a vertical ellipsis followed by a stray "...".
   The button is centred by its own flex box and needs no side padding. */
#lms-panel-main .tabulator .tabulator-cell.lms-row-act-col,
#lms-panel-main .tabulator .tabulator-cell.lms-row-sel-col,
#lms-panel-main .tabulator .tabulator-col.lms-row-sel-col {
    padding-left: 0 !important;
    padding-right: 0 !important;
    text-align: center;
    text-overflow: clip;
}
/* The header's ellipsis lives on the inner title element, not the col box:
   without this the select-all header rendered as a checkbox followed by a
   stray dot on every grid. */
#lms-panel-main .tabulator .tabulator-col.lms-row-sel-col .tabulator-col-title {
    padding: 0;
    text-overflow: clip;
    text-align: center;
}

/* ─── Surface: main content area ───────────────────────────── */
/* The w2ui main panel hosts every content screen: the data grids
   and their toolbars, notifications, risk score, audit log and the
   admin screens. lms.css is almost entirely token-driven, so this
   single scoped remap re-skins all of them; screens with their own
   scopes below (dashboard, chat, settings) simply re-assert the
   same values or refine them. --lms-accent is the app's ink
   primary (high-contrast buttons and active states), so it maps to
   the brand ink pair, not the lavender hue. The broker, funder and
   investor portal shells share the same token vocabulary, so they
   join this scope rather than repeating it. */
#lms-panel-main,
.brk-shell,
.fnd-shell,
.inv-shell {
    --lms-font: var(--vantage-font-body);
    --lms-bg: var(--vantage-bg);
    --lms-bg-panel: var(--vantage-surface);
    --lms-bg-alt: var(--vantage-fill);
    --lms-border: var(--vantage-line);
    --lms-border-light: var(--vantage-line-2);
    --lms-text: var(--vantage-text);
    --lms-text-dim: color-mix(in srgb, var(--vantage-text) 86%, var(--vantage-bg));
    --lms-text-muted: var(--vantage-text-2);
    --lms-text-faint: var(--vantage-text-3);
    --lms-text-label: var(--vantage-text-3);
    --lms-active-tint: var(--vantage-fill-2);
    --lms-accent: var(--vantage-text);
    --lms-accent-text: var(--vantage-bg);
    --lms-accent-warm: var(--vantage-brand-b);
    /* Semantic row/cell tints: same meanings, but as quiet washes mixed
       into the brand background instead of the old saturated fills. The
       hues come from the semantic text tokens, which stay unmapped;
       "info" (active pipeline states) moves from legacy blue to the
       brand accent. */
    --lms-info-bg: color-mix(in srgb, var(--vantage-accent) 16%, var(--vantage-bg));
    --lms-success-bg: color-mix(in srgb, var(--lms-success-text) 14%, var(--vantage-bg));
    --lms-warning-bg: color-mix(in srgb, var(--lms-warning-text) 16%, var(--vantage-bg));
    --lms-warning-bg-2: color-mix(in srgb, var(--lms-warning-text) 11%, var(--vantage-bg));
    --lms-danger-bg: color-mix(in srgb, var(--lms-danger-text) 14%, var(--vantage-bg));
    --lms-highlight-bg: color-mix(in srgb, var(--vantage-brand-c) 26%, var(--vantage-bg));
    --lms-disabled-bg: var(--vantage-fill);
    background: var(--vantage-bg);
    font-family: var(--vantage-font-body);
}

/* Text selection and native control accents pick up the brand hue
   everywhere instead of the browser's default blue. */
::selection { background: color-mix(in srgb, var(--vantage-accent) 35%, transparent); }
:is(#lms-panel-main, .lms-popup-overlay, .lms-modal-overlay, #cd-root) input[type="radio"] {
    accent-color: var(--vantage-accent);
}

/* A checkbox is reshaped rather than left as the browser's raw control: a
   bare native checkbox (Tabulator's tickCross grid editor and the record
   panel's own editor both fall back to a plain <input type="checkbox">)
   reads as a foreign, unstyled widget dropped into an otherwise fully
   custom UI - square, unrounded, no relation to the accent colour used
   everywhere else a value is "on". appearance:none only removes the
   browser's own paint; the element is still a real checkbox, so keyboard
   and screen-reader behaviour are unaffected. */
:is(#lms-panel-main, .lms-popup-overlay, .lms-modal-overlay, #cd-root) input[type="checkbox"],
.lms-rp-input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    width: 16px;
    height: 16px;
    min-width: 16px;
    margin: 0;
    box-sizing: border-box;
    /* --vantage-line is a divider token (11% white in the default dark
       theme) - fine for separating two surfaces that are already visually
       distinct, but an unchecked checkbox has almost no fill contrast of
       its own (--vantage-surface sits a couple of percent off the row
       background it's drawn on), so the border was the only thing giving
       the control a visible shape and it read as much fainter than the
       text beside it. --vantage-text-3 is the same muted grey already used
       for secondary, legible-but-quiet content elsewhere, so the box now
       reads at roughly the same brightness as everything around it. */
    border: 1px solid var(--vantage-text-3);
    /* --vantage-r-sm (8px) is scaled for rows/inputs, not a 16px control -
       half that would draw a circle here, indistinguishable from a radio. */
    border-radius: 4px;
    background: var(--vantage-surface);
    cursor: pointer;
    position: relative;
    vertical-align: middle;
}
:is(#lms-panel-main, .lms-popup-overlay, .lms-modal-overlay, #cd-root) input[type="checkbox"]:checked,
.lms-rp-input[type="checkbox"]:checked {
    background: var(--vantage-accent);
    border-color: var(--vantage-accent);
}
/* The tick is drawn in --vantage-bg against the accent fill: that pairing
   is chosen to sit opposite each other in every theme (see the theme
   blocks above), so it stays legible whichever theme is active without a
   second colour to maintain. */
:is(#lms-panel-main, .lms-popup-overlay, .lms-modal-overlay, #cd-root) input[type="checkbox"]:checked::after,
.lms-rp-input[type="checkbox"]:checked::after {
    content: '';
    position: absolute;
    left: 4px;
    top: 1px;
    width: 4px;
    height: 8px;
    border: solid var(--vantage-bg);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
:is(#lms-panel-main, .lms-popup-overlay, .lms-modal-overlay, #cd-root) input[type="checkbox"]:focus-visible,
.lms-rp-input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--vantage-accent);
    outline-offset: 1px;
}

/* Tabulator paints the cell being edited with its own blue border. */
#lms-panel-main .tabulator .tabulator-cell.tabulator-editing {
    border: 1px solid var(--vantage-accent) !important;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vantage-accent) 18%, transparent);
}
#lms-panel-main .tabulator .tabulator-cell.tabulator-editing input,
#lms-panel-main .tabulator .tabulator-cell.tabulator-editing select {
    background: var(--vantage-surface);
    color: var(--vantage-text);
    border: none;
    outline: none;
    font-family: var(--vantage-font-body);
}

/* Screen titles inside the content area take the heading face. */
#lms-panel-main h2,
#lms-panel-main h3 {
    font-family: var(--vantage-font-heading);
    letter-spacing: -0.01em;
}

/* ── Grid toolbar: quiet ghost buttons, one high-contrast primary ── */
/* The bordered-box-per-button treatment predates the redesign; in the
   brand language actions are ghosts that reveal a fill on hover, and
   only the screen's creation action carries ink. Primary actions are
   recognised by their icons (plus / bolt) so every grid screen gets
   the treatment without per-screen wiring. */
/* The bars share a rhythm: application bar and grid bar at 44, the column
   header a step below at 40. Measured before this: 44, 49 and 47. */
.lms-gf-bar { min-height: 44px; box-sizing: border-box; padding-top: 7px; padding-bottom: 7px; }
#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-col-title { line-height: 40px; }
#lms-panel-main .tabulator .tabulator-header { min-height: 40px; }

/* A header and its own cells share a left edge. They differed by 4px, which
   came from the header's content wrapper padding rather than the title, so
   that wrapper gives up its inset and the title carries the whole 12px. */
#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-col-content { padding: 0; }
#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-col-title { padding-left: 12px; }
#lms-panel-main .tabulator .tabulator-cell { padding-left: 12px; }
#lms-panel-main .tabulator .tabulator-col.lms-col-right .tabulator-col-title { padding-left: 25px; padding-right: 12px; }
#lms-panel-main .tabulator .tabulator-header .tabulator-col { height: 40px; }
#lms-panel-main .lms-tabgrid-toolbar {
    padding: 10px 16px;
    background: var(--vantage-bg);
    border-bottom: 1px solid var(--vantage-line-2);
}
/* The right-aligned Columns/search cluster yields width before the
   row wraps: the search field shrinks to a floor first, so busy
   toolbars stay on one line at normal desktop widths. */
#lms-panel-main .lms-tabgrid-toolbar > div:last-child {
    flex: 0 1 auto;
    min-width: 0;
    gap: 6px !important;
}
#lms-panel-main .lms-tabgrid-search {
    flex: 0 1 170px;
    width: 170px;
    min-width: 96px;
}
/* One row, always: wrapping never engages flex-shrink (an item just
   drops to the next line at its full basis), so the toolbar forbids
   wrap and lets the search field compress instead. If a viewport is
   narrower than the buttons' floor, the row scrolls like mobile. */
#lms-panel-main .lms-tabgrid-toolbar {
    flex-wrap: nowrap;
    overflow-x: auto;
}
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button {
    background: transparent;
    border: 1px solid transparent;
    border-radius: 9px;
    height: 32px;
    padding: 0 10px;
    margin: 0 1px 0 0;
    font-size: 12.5px;
    font-weight: 500;
    white-space: nowrap;
    color: var(--vantage-text-2);
    transition: background-color 0.12s ease, color 0.12s ease;
}
/* Delete reveals its nature on hover rather than shouting all day. */
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:has(i.fa-times):hover:not(.disabled):not([disabled]) {
    background: color-mix(in srgb, var(--lms-danger-text) 10%, transparent);
    color: var(--lms-danger-text);
}
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:has(i.fa-times):hover:not(.disabled):not([disabled]) i {
    color: var(--lms-danger-text);
}
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:hover:not(.disabled):not([disabled]) {
    background: var(--vantage-fill-2);
    color: var(--vantage-text);
}
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button i { color: var(--vantage-text-3); }
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:hover:not(.disabled):not([disabled]) i { color: var(--vantage-text); }
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:has(i.fa-plus),
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:has(i.fa-bolt) {
    background: var(--vantage-text);
    color: var(--vantage-bg);
    font-weight: 600;
}
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:has(i.fa-plus) i,
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:has(i.fa-bolt) i { color: var(--vantage-bg); }
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:has(i.fa-plus):hover:not(.disabled):not([disabled]),
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:has(i.fa-bolt):hover:not(.disabled):not([disabled]) {
    background: var(--vantage-text);
    color: var(--vantage-bg);
    opacity: 0.88;
}
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:has(i.fa-plus):hover:not(.disabled):not([disabled]) i,
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button:has(i.fa-bolt):hover:not(.disabled):not([disabled]) i { color: var(--vantage-bg); }
/* One ink button per toolbar: when a bolt quick-action is present it
   is the primary, and the plus action steps down to a bordered
   secondary. */
#lms-panel-main .lms-tabgrid-toolbar:has(i.fa-bolt) button.w2ui-tb-button:has(i.fa-plus),
#lms-panel-main .lms-tabgrid-toolbar:has(i.fa-bolt) button.w2ui-tb-button:has(i.fa-plus):hover:not(.disabled):not([disabled]) {
    background: transparent;
    border-color: var(--vantage-line);
    color: var(--vantage-text);
    font-weight: 500;
    opacity: 1;
}
#lms-panel-main .lms-tabgrid-toolbar:has(i.fa-bolt) button.w2ui-tb-button:has(i.fa-plus) i { color: var(--vantage-text-2); }
#lms-panel-main .lms-tabgrid-toolbar:has(i.fa-bolt) button.w2ui-tb-button:has(i.fa-plus):hover:not(.disabled):not([disabled]) {
    background: var(--vantage-fill);
}
/* Ghost buttons group by proximity; separator fences between every
   pair just add clutter, so they go. */
#lms-panel-main .lms-tabgrid-toolbar .w2ui-tb-line { display: none; }
/* A disabled action fades almost entirely out of the row instead of
   sitting there as grey furniture. */
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button.disabled,
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button[disabled] {
    opacity: 0.3;
}
/* "Show changes" while active: danger stays, but as the brand's quiet
   tinted treatment rather than the old solid outline. */
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button.lms-tb-active,
html.dark-mode #lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button.lms-tb-active {
    background: color-mix(in srgb, var(--lms-danger-text) 12%, transparent);
    color: var(--lms-danger-text);
    outline: none;
    border-color: color-mix(in srgb, var(--lms-danger-text) 30%, transparent);
}
#lms-panel-main .lms-tabgrid-toolbar button.w2ui-tb-button.lms-tb-active i { color: var(--lms-danger-text); }
#lms-panel-main .lms-tabgrid-search {
    height: 32px;
    border: 1px solid var(--vantage-line);
    border-radius: 9px;
    padding: 0 12px;
    font-size: 13px;
    background: var(--vantage-fill);
    color: var(--vantage-text);
}
#lms-panel-main .lms-tabgrid-search:focus {
    border-color: var(--vantage-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vantage-accent) 22%, transparent);
}

/* ── Grid column headers: flat band, no vertical rules ───────────── */
/* Clear only the vertical rules between columns. Using the border-color
   shorthand here also wiped the header's own bottom edge, and because the
   dark-mode selector outranks the rule that restored it, the line survived
   in light mode only. */
#lms-panel-main .tabulator .tabulator-header,
#lms-panel-main .tabulator .tabulator-header .tabulator-col,
html.dark-mode #lms-panel-main .tabulator .tabulator-header,
html.dark-mode #lms-panel-main .tabulator .tabulator-header .tabulator-col {
    background-color: var(--vantage-bg) !important;
    border-top-color: transparent !important;
    border-left-color: transparent !important;
    border-right-color: transparent !important;
}
/* The header sits against the rows, so it keeps a real edge in every theme. */
#lms-panel-main .tabulator .tabulator-header,
html.dark-mode #lms-panel-main .tabulator .tabulator-header {
    border-bottom: 1px solid var(--vantage-line) !important;
}
#lms-panel-main .tabulator .tabulator-header .tabulator-col,
html.dark-mode #lms-panel-main .tabulator .tabulator-header .tabulator-col {
    border-bottom-color: transparent !important;
}
#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-col-title,
html.dark-mode #lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-col-title {
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    font-weight: 500;
    letter-spacing: 0;
    color: var(--vantage-text-2) !important;
}
/* ── Filtering: a bar above the grid, not inputs in the header ────
   The header carries titles only. The bar holds the quick search, a
   chip per active filter, and a button to add one, so what is
   narrowing the view is always visible. */
#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-header-filter {
    display: none;
}
.lms-gf-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    /* 7px keeps the bar at 44, matching the application bar above it. */
    padding: 7px 16px;
    border-bottom: 1px solid var(--vantage-line-2);
    background: var(--vantage-bg);
    overflow-x: auto;
    scrollbar-width: none;
}
.lms-gf-bar::-webkit-scrollbar { display: none; }

/* The quick search, moved out of the toolbar to sit with the filters. */
.lms-gf-search {
    position: relative;
    display: flex;
    align-items: center;
    flex-shrink: 0;
}
/* The toolbar's own search icon, floated inside the field. */
.lms-gf-search > i {
    position: absolute;
    left: 10px;
    display: inline-flex;
    color: var(--vantage-text-3);
    pointer-events: none;
}
.lms-gf-search > i svg { width: 14px; height: 14px; }
/* ID-scoped so it outranks the toolbar rule the field carried with it. */
#lms-panel-main .lms-gf-search .lms-tabgrid-search {
    height: 30px;
    width: 230px;
    padding: 0 10px 0 31px;
    border-radius: 9px;
}

.lms-gf-spacer { flex: 1; min-width: 8px; }
.lms-gf-count { font-size: 12.5px; color: var(--vantage-text-3); white-space: nowrap; }
.lms-gf-create { display: flex; align-items: center; gap: 6px; }
.lms-gf-cols { display: flex; align-items: center; }
/* Column visibility, moved out of the old action row. */
#lms-panel-main .lms-gf-bar button.lms-gf-colsbtn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 30px;
    margin: 0;
    padding: 0 11px;
    border: 1px solid transparent;
    border-radius: 9px;
    background: transparent;
    color: var(--vantage-text-2);
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    white-space: nowrap;
    cursor: pointer;
}
#lms-panel-main .lms-gf-bar button.lms-gf-colsbtn:hover {
    background: var(--vantage-fill-2);
    color: var(--vantage-text);
}
@media (max-width: 768px) {
    /* Icon only on a phone, where the label is not worth the width. */
    #lms-panel-main .lms-gf-bar button.lms-gf-colsbtn { padding: 0 9px; font-size: 0; gap: 0; }
    #lms-panel-main .lms-gf-bar button.lms-gf-colsbtn i { font-size: 13px; }
}
/* The screen's creation action, raised out of the old toolbar row. */
.lms-gf-primary {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 30px;
    padding: 0 13px;
    border: 0;
    border-radius: 9px;
    background: var(--vantage-text);
    color: var(--vantage-bg);
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: opacity 0.12s ease;
}
.lms-gf-primary:hover { opacity: 0.9; }
.lms-gf-primary i { color: var(--vantage-bg); }
.lms-gf-primary i svg { width: 15px; height: 15px; }

.lms-gf-chips { display: flex; align-items: center; gap: 6px; }
.lms-gf-chip {
    display: inline-flex;
    align-items: center;
    height: 28px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--vantage-accent) 15%, transparent);
    color: var(--vantage-text);
    white-space: nowrap;
}
.lms-gf-chip.lms-gf-editing {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--vantage-accent) 45%, transparent);
}
.lms-gf-chip-main {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 100%;
    padding: 0 4px 0 11px;
    border: 0;
    border-radius: 999px 0 0 999px;
    background: transparent;
    color: inherit;
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    cursor: pointer;
}
.lms-gf-chip-main b { font-weight: 500; color: var(--vantage-text-2); }
.lms-gf-chip-x {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 100%;
    padding: 0 7px 0 3px;
    border: 0;
    border-radius: 0 999px 999px 0;
    background: transparent;
    color: var(--vantage-text-2);
    cursor: pointer;
}
.lms-gf-chip-x svg { width: 11px; height: 11px; }
.lms-gf-chip-x:hover { color: var(--vantage-text); }

.lms-gf-add {
    flex-shrink: 0;
    height: 28px;
    padding: 0 12px;
    border: 1px dashed var(--vantage-line);
    border-radius: 999px;
    background: transparent;
    color: var(--vantage-text-3);
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    cursor: pointer;
    transition: color 0.12s ease, border-color 0.12s ease;
}
.lms-gf-add:hover { color: var(--vantage-text-2); border-color: var(--vantage-text-3); }

/* ── Floating action bar ─────────────────────────────────────────
   Contextual actions sit over the rows they act on so the bar above
   never has to move; one segment per thing that is true, so a
   selection and unsaved edits can coexist. */
.lms-fab {
    position: absolute;
    left: 50%;
    /* Rides above the record panel when one is open, so the bar that acts on a
       record never covers the record it is acting on. The panel sets the
       variable on the grid wrapper as it opens, resizes and closes. */
    bottom: calc( 18px + var( --lms-rp-h, 0px ) );
    transform: translateX(-50%);
    z-index: 40;
    display: flex;
    align-items: center;
    gap: 8px;
    max-width: calc(100% - 32px);
    padding: 7px 9px 7px 14px;
    border-radius: 999px;
    background: var(--vantage-surface);
    border: 1px solid var(--vantage-line);
    box-shadow: 0 12px 34px rgba(0, 0, 0, 0.34);
    font-size: 12.5px;
    white-space: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    animation: lms-pop-in 0.12s ease-out;
}
.lms-fab::-webkit-scrollbar { display: none; }
.lms-fab-seg { display: flex; align-items: center; gap: 6px; }
.lms-fab-sep { width: 1px; height: 20px; background: var(--vantage-line-2); flex-shrink: 0; }
.lms-fab-lead {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-right: 2px;
    font-weight: 500;
    color: var(--vantage-text);
}
.lms-fab-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.lms-fab-dot-sel { background: var(--vantage-accent); }
.lms-fab-dot-dirty { background: var(--vantage-brand-c); }
.lms-fab-act {
    height: 28px;
    padding: 0 10px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--vantage-text-2);
    font-family: var(--vantage-font-body);
    font-size: 12.5px;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.lms-fab-act:hover { background: var(--vantage-fill-2); color: var(--vantage-text); }
.lms-fab-danger:hover { background: color-mix(in srgb, var(--lms-danger-text) 12%, transparent); color: var(--lms-danger-text); }
.lms-fab-save {
    background: var(--vantage-brand-c);
    color: #1b1b1b;
    font-weight: 600;
}
.lms-fab-save:hover { background: var(--vantage-brand-c); color: #1b1b1b; opacity: 0.9; }

/* Pending edits are visible in the grid, not only in the bar. */
#lms-panel-main .tabulator .tabulator-cell.lms-cell-dirty {
    background: color-mix(in srgb, var(--vantage-brand-c) 15%, transparent) !important;
    box-shadow: inset 2px 0 0 var(--vantage-brand-c);
}

@media (prefers-reduced-motion: reduce) { .lms-fab { animation: none; } }
@media (max-width: 768px) {
    .lms-fab {
        left: 10px;
        right: 10px;
        transform: none;
        max-width: none;
        bottom: calc(70px + env(safe-area-inset-bottom, 0px));
    }
}

.lms-gf-pop-label {
    margin-bottom: 7px;
    font-size: 11.5px;
    color: var(--vantage-text-3);
}
.lms-gf-menu { min-width: 190px; max-height: 46vh; overflow-y: auto; z-index: 10001; }

.lms-hf-pop {
    position: fixed;
    z-index: 10000;
    min-width: 208px;
    padding: 10px;
    background: var(--vantage-surface);
    border: 1px solid var(--vantage-line);
    border-radius: 10px;
    box-shadow: 0 14px 36px rgba(0, 0, 0, 0.30);
    animation: lms-pop-in 0.1s ease-out;
}
.lms-hf-pop .tabulator-header-filter {
    display: block;
    width: 100%;
    height: auto;
    margin: 0;
    padding: 0;
}
@media (prefers-reduced-motion: reduce) {
    .lms-hf-pop { animation: none; }
}
@media (max-width: 768px) {
    .lms-gf-bar { padding: 8px 12px; }
    #lms-panel-main .lms-gf-search .lms-tabgrid-search { width: 150px; }
}

#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-header-filter input,
#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-header-filter select,
.lms-hf-pop .tabulator-header-filter input,
.lms-hf-pop .tabulator-header-filter select {
    background-color: var(--vantage-fill);
    border: 1px solid transparent;
    border-radius: 7px;
    height: 26px;
    padding: 0 8px;
    font-size: 12px;
    font-family: var(--vantage-font-body);
    color: var(--vantage-text);
    transition: border-color 0.12s ease, background-color 0.12s ease;
}
#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-header-filter input:hover,
#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-header-filter select:hover {
    border-color: var(--vantage-line);
}
.lms-hf-pop .tabulator-header-filter input,
.lms-hf-pop .tabulator-header-filter select {
    width: 100%;
    box-sizing: border-box;
    height: 30px;
    border-color: var(--vantage-line);
}
#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-header-filter input:focus,
#lms-panel-main .tabulator .tabulator-header .tabulator-col .tabulator-header-filter select:focus,
.lms-hf-pop .tabulator-header-filter input:focus,
.lms-hf-pop .tabulator-header-filter select:focus,
html.dark-mode .lms-hf-pop .tabulator-header-filter input:focus {
    background-color: var(--vantage-surface);
    border-color: var(--vantage-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vantage-accent) 18%, transparent);
}
#lms-panel-main .tabulator .tabulator-col-sorter .tabulator-arrow { opacity: 0.7; }

/* A header shares an edge with its values. Tabulator pads 25px on the right
   of every title for the sort arrow, which leaves a right-aligned header
   short of its figures, so those columns reclaim the space and take the
   arrow on the left instead. */
#lms-panel-main .tabulator .tabulator-col.lms-col-right .tabulator-col-title {
    padding-right: 8px;
    padding-left: 25px;
}
#lms-panel-main .tabulator .tabulator-col.lms-col-right .tabulator-col-sorter {
    left: 4px;
    right: auto;
}
/* The header's own content wrapper pads the right edge as well, which would
   leave the title a few pixels short of the cell text below it. */
#lms-panel-main .tabulator .tabulator-col.lms-col-right .tabulator-col-content {
    padding-right: 0;
}
#lms-panel-main .tabulator .tabulator-col.lms-col-center .tabulator-col-title {
    padding-left: 25px;
}
/* The select column is centered too (hozAlign: 'center'), but at 34px wide
   with headerSort: false it has no sort arrow to reserve that 25px for -
   reserving it anyway left only 8px of a 34px column for a 16px checkbox,
   clipping most of it against the column's own overflow:hidden. 12px
   matches the ordinary .tabulator-cell padding-left below (line ~2139), the
   same "header shares an edge with its cells" rule every other column
   follows, so the select-all checkbox lines up with the row checkboxes
   under it rather than sitting flush against the frozen edge. Higher
   specificity than the rule above (one more class) wins regardless of
   source order. */
#lms-panel-main .tabulator .tabulator-col.lms-row-sel-col.lms-col-center .tabulator-col-title {
    padding-left: 12px;
}

/* The old dark theme hardcoded a blue focus ring; branded scopes
   focus with the accent instead, matching the auth pages. */
html.dark-mode #lms-panel-main input:focus,
html.dark-mode #lms-panel-main select:focus,
html.dark-mode #lms-panel-main textarea:focus,
html.dark-mode #cd-root input:focus,
html.dark-mode #cd-root textarea:focus {
    border-color: var(--vantage-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vantage-accent) 22%, transparent);
}

/* ─── Motion ───────────────────────────────────────────────── */
/* Floating layers arrive instead of popping: a fast fade for the
   dimmed backdrop and a fade-and-settle for the panel itself.
   Durations stay under 150ms so the app never feels slowed down. */
@keyframes lms-fade-in { from { opacity: 0; } }
@keyframes lms-pop-in {
    from { opacity: 0; transform: scale(0.97) translateY(4px); }
}
.lms-popup-overlay,
.lms-modal-overlay {
    animation: lms-fade-in 0.12s ease-out;
}
.lms-popup-overlay .lms-popup-box,
.lms-modal-overlay > div {
    animation: lms-pop-in 0.14s ease-out;
}
#notif-dropdown,
.lms-emoji-picker {
    animation: lms-pop-in 0.12s ease-out;
}
@media (prefers-reduced-motion: reduce) {
    .lms-popup-overlay,
    .lms-modal-overlay,
    .lms-popup-overlay .lms-popup-box,
    .lms-modal-overlay > div,
    #notif-dropdown,
    .lms-emoji-picker { animation: none; }
}

/* ─── Dashboard click-through tiles ────────────────────────── */
.dash-root .dash-nav { cursor: pointer; transition: border-color 0.12s ease, background-color 0.12s ease; }
.dash-root .dash-nav:hover { border-color: var(--vantage-accent); }
.dash-root .dash-nav:focus-visible {
    outline: none;
    border-color: var(--vantage-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vantage-accent) 20%, transparent);
}
.dash-root .dash-at-item.dash-nav:hover {
    border-top-color: var(--vantage-line-2);
    background: var(--vantage-fill-2);
}

/* Origination pipeline strip: stage tiles joined by quiet chevrons. */
.dash-pipe { display: flex; flex-direction: column; }
.dash-pipe-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    /* 14px to match every other row on the dashboard: as rows rather than
       tiles, these were sitting flush to the card's edge while the cards
       beside them held their contents in by a comfortable margin. */
    padding: 9px 14px;
    border-bottom: 1px solid var(--vantage-line-2);
    cursor: pointer;
}
.dash-pipe-row:last-child { border-bottom: 0; }
.dash-pipe-row:hover { background: var(--vantage-fill); }
.dash-pipe-label { font-size: 12.5px; color: var(--vantage-text-2); }
.dash-pipe-count { font-size: 15px; font-weight: 500; font-variant-numeric: tabular-nums; }
@media (max-width: 768px) {
    .dash-pipe { -webkit-overflow-scrolling: touch; }
}

/* ─── Empty and loading states ─────────────────────────────── */
/* Shared quiet empty state: a muted stroke icon on a tinted chip,
   a short title, and a fainter hint. Used by the grid placeholder,
   the notifications dropdown, and the portal empties. */
.lms-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 34px 16px;
    text-align: center;
    font-family: var(--vantage-font-body);
    white-space: normal;
}
.lms-empty-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin-bottom: 6px;
    border-radius: 12px;
    background: var(--vantage-fill);
    color: var(--vantage-text-3);
}
.lms-empty-ico svg { width: 22px; height: 22px; }
.lms-empty-title {
    font-size: 13.5px;
    font-weight: 500;
    color: var(--vantage-text-2);
}
.lms-empty-hint {
    font-size: 12.5px;
    color: var(--vantage-text-3);
}
/* Tabulator centres the placeholder itself; flatten its default look. */
#lms-panel-main .tabulator .tabulator-placeholder .tabulator-placeholder-contents,
html.dark-mode #lms-panel-main .tabulator .tabulator-placeholder .tabulator-placeholder-contents {
    background: transparent;
    border: none;
    margin: 0;
    padding: 0;
    font-weight: normal;
    font-size: inherit;
    color: inherit;
    white-space: normal;
}

/* Grid loading overlay: quiet card with a brand spinner. */
#lms-panel-main .tabulator .tabulator-alert {
    background: color-mix(in srgb, var(--vantage-bg) 55%, transparent);
}
#lms-panel-main .tabulator .tabulator-alert .tabulator-alert-msg {
    background: var(--vantage-surface);
    border: 1px solid var(--vantage-line);
    border-radius: 12px;
    padding: 14px 22px;
    font-family: var(--vantage-font-body);
    font-size: 13px;
    font-weight: 500;
    color: var(--vantage-text-2);
}
#lms-panel-main .tabulator .tabulator-alert .tabulator-alert-msg.tabulator-alert-state-msg::before {
    content: '';
    display: inline-block;
    width: 14px;
    height: 14px;
    margin-right: 9px;
    vertical-align: -2px;
    border-radius: 50%;
    border: 2px solid var(--vantage-fill-2);
    border-top-color: var(--vantage-accent);
    animation: lms-spin 0.7s linear infinite;
}
@keyframes lms-spin { to { transform: rotate(360deg); } }

/* Portal loading and empty lines take the same quiet voice. */
html .brk-shell .brk-loading::before,
html .fnd-shell .fnd-loading::before,
html .inv-shell .inv-loading::before {
    content: '';
    display: inline-block;
    width: 13px;
    height: 13px;
    margin-right: 9px;
    vertical-align: -2px;
    border-radius: 50%;
    border: 2px solid var(--vantage-fill-2);
    border-top-color: var(--vantage-accent);
    animation: lms-spin 0.7s linear infinite;
}
html .brk-shell .brk-empty,
html .fnd-shell .fnd-empty,
html .inv-shell .inv-empty {
    display: block;
    padding: 22px;
    border: 1px dashed var(--vantage-line);
    border-radius: 12px;
    text-align: center;
    color: var(--vantage-text-3);
    background: var(--vantage-fill);
}

@media (prefers-reduced-motion: reduce) {
    #lms-panel-main .tabulator .tabulator-alert .tabulator-alert-msg.tabulator-alert-state-msg::before,
    html .brk-shell .brk-loading::before,
    html .fnd-shell .fnd-loading::before,
    html .inv-shell .inv-loading::before { animation: none; }
}

/* ─── Brand icon bridge ────────────────────────────────────── */
/* brand_icons.js swaps Font Awesome glyphs for inline stroke SVGs;
   the <i> element and its fa-* name class survive, so existing
   selectors and sizing contexts keep working. The svg tracks the
   local font-size and colour exactly as the font glyph did. */
i.lms-svg-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    vertical-align: -0.125em;
}
i.lms-svg-ico > svg {
    width: 1em;
    height: 1em;
    flex-shrink: 0;
}
/* Font Awesome's .fa-*::before content rules still target the kept
   name class; without the icon font-family they would render as a
   stray fallback glyph beside the svg. */
i.lms-svg-ico::before { content: none !important; }

/* ─── Surface: broker, funder and investor portals ─────────── */
/* The portals inject their own <style> at runtime, which lands
   after this sheet in the cascade; the `html` prefix gives these
   overrides the extra specificity they need to win. Token remaps
   come from the shared scope above. */
html .brk-shell,
html .fnd-shell,
html .inv-shell {
    font-family: var(--vantage-font-body);
}
html .brk-shell .brk-title,
html .fnd-shell .fnd-title,
html .inv-shell .inv-title {
    font-family: var(--vantage-font-heading);
    font-weight: 700;
    letter-spacing: -0.02em;
}
html .brk-shell .brk-section-title,
html .fnd-shell .fnd-section-title,
html .fnd-shell .fnd-lender-title,
html .inv-shell .inv-section-title {
    font-family: var(--vantage-font-heading);
    font-weight: 500;
    letter-spacing: -0.01em;
}
html .brk-shell .brk-platform,
html .fnd-shell .fnd-platform,
html .inv-shell .inv-platform {
    font-family: var(--vantage-font-heading);
    font-weight: 500;
}

/* Active nav takes the app's accent wash instead of a grey block. */
html .brk-shell .brk-nav-item.active,
html .fnd-shell .fnd-nav-item.active,
html .inv-shell .inv-nav-item.active {
    background: color-mix(in srgb, var(--vantage-accent) 13%, transparent);
    color: var(--vantage-text);
}
html .brk-shell .brk-nav-item.active i,
html .fnd-shell .fnd-nav-item.active i,
html .inv-shell .inv-nav-item.active i { color: var(--vantage-accent); }
html .brk-shell .brk-nav-item:hover:not(.active),
html .fnd-shell .fnd-nav-item:hover:not(.active),
html .inv-shell .inv-nav-item:hover:not(.active) {
    background: var(--vantage-fill);
}

/* KPI cards match the main dashboard: borders over shadows, Satoshi
   numerals in ink rather than a hue. */
html .brk-shell .brk-kpi-card,
html .fnd-shell .fnd-kpi-card,
html .inv-shell .inv-kpi-card {
    box-shadow: none;
    border-radius: 12px;
    border-color: var(--vantage-line-2);
    background: var(--vantage-fill);
}
html .brk-shell .brk-kpi-value,
html .fnd-shell .fnd-kpi-value,
html .inv-shell .inv-kpi-value {
    font-family: var(--vantage-font-heading);
    font-weight: 700;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    color: var(--vantage-text);
}

/* Tables take the main grids' flat header band. */
html .brk-shell .brk-table th,
html .fnd-shell .fnd-table th,
html .fnd-shell .fnd-subtable th,
html .inv-shell .inv-table th {
    background: transparent;
    border-bottom: 1px solid var(--vantage-line);
    font-size: 11.5px;
    font-weight: 500;
    color: var(--vantage-text-3);
}
html .brk-shell .brk-table,
html .fnd-shell .fnd-table,
html .inv-shell .inv-table {
    background: var(--vantage-fill);
    border-radius: 12px;
}
html .brk-shell .brk-table td,
html .fnd-shell .fnd-table td,
html .inv-shell .inv-table td { border-top: 1px solid var(--vantage-line-2); }

/* The portals' titles and figures wear the same faces the application does:
   every shell carried font-family Arial from its first commit, so the four
   customer-facing pages rendered in a typeface the product does not use. */
html .brk-shell .brk-title, html .inv-shell .inv-title,
html .fnd-shell .fnd-title, html .fnd-shell .fnd-lender-title,
html .cli-shell .cli-title,
html .brk-shell .brk-kpi-value, html .inv-shell .inv-kpi-value,
html .fnd-shell .fnd-kpi-value, html .cli-shell .cli-kpi-value {
    font-family: var(--vantage-font-heading);
    letter-spacing: -0.02em;
}

/* Pills: the same shape and the same inks as .lms-pill in the application, so a
   status means the same thing to a broker as it does to the lender. Stated here
   rather than inside each portal's own injected stylesheet, because this rule
   reaches into all three shells and would override them anyway.

   The portals print raw status codes, so a broker saw ACTIVE where the lender's
   own screens say Active; lowercasing with an uppercased first letter fixes the
   reading without touching three render functions, two of which have no demo
   login to test against. */
html .brk-shell .brk-stage,
html .brk-shell .brk-badge,
html .fnd-shell .fnd-status,
html .fnd-shell .fnd-covenant,
html .inv-shell .inv-status,
html .cli-shell .cli-status {
    /* inline-block, not inline-flex: ::first-letter below only applies to
       block containers, and these pills hold plain text with nothing to align. */
    display: inline-block;
    padding: 2px 9px;
    border-radius: var(--vantage-r-sm);
    font-size: 11px;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    text-transform: lowercase;
}
html .brk-shell .brk-stage::first-letter,
html .brk-shell .brk-badge::first-letter,
html .fnd-shell .fnd-status::first-letter,
html .fnd-shell .fnd-covenant::first-letter,
html .inv-shell .inv-status::first-letter,
html .cli-shell .cli-status::first-letter { text-transform: uppercase; }

html .brk-shell .brk-stage-active,
html .brk-shell .brk-badge-loan,
html .fnd-shell .fnd-status-active,
html .fnd-shell .fnd-covenant-pass,
html .inv-shell .inv-status-active,
html .cli-shell .cli-status-performing {
    color: var(--lms-success-ink);
    background: color-mix( in srgb, var(--lms-success-ink) 11%, transparent );
}
html .brk-shell .brk-badge-deal,
html .fnd-shell .fnd-covenant-warn,
html .cli-shell .cli-status-arrears {
    color: var(--lms-warning-ink);
    background: color-mix( in srgb, var(--lms-warning-ink) 11%, transparent );
}
html .brk-shell .brk-stage-rejected,
html .fnd-shell .fnd-status-closed,
html .fnd-shell .fnd-covenant-breach,
html .inv-shell .inv-status-closed,
html .cli-shell .cli-status-default {
    color: var(--lms-danger-ink);
    background: color-mix( in srgb, var(--lms-danger-ink) 11%, transparent );
}
html .brk-shell .brk-stage-redeemed,
html .fnd-shell .fnd-covenant-untested,
html .cli-shell .cli-status-redeemed,
html .cli-shell .cli-status-written-off,
html .cli-shell .cli-status-cancelled {
    color: var(--vantage-text-2);
    background: var(--vantage-fill);
}

/* ─── Surface: overlays, dialogs and floating menus ────────── */
/* Everything that floats above the page from document.body: popup
   record windows and the alert/confirm/prompt dialogs built on them
   (.lms-popup-overlay), the notifications dropdown, the chat modals
   (.lms-modal-overlay, assigned in channels.js / dm.js), and the
   vendor column and context menus. */
.lms-popup-overlay,
.lms-modal-overlay,
#notif-dropdown,
.tabulator-menu,
.w2ui-menu,
.w2ui-overlay {
    --lms-bg: var(--vantage-bg);
    --lms-bg-panel: var(--vantage-surface);
    --lms-bg-alt: var(--vantage-fill);
    --lms-border: var(--vantage-line);
    --lms-border-light: var(--vantage-line-2);
    --lms-text: var(--vantage-text);
    --lms-text-dim: color-mix(in srgb, var(--vantage-text) 86%, var(--vantage-bg));
    --lms-text-muted: var(--vantage-text-2);
    --lms-text-faint: var(--vantage-text-3);
    --lms-text-label: var(--vantage-text-3);
    --lms-active-tint: var(--vantage-fill-2);
    --lms-accent: var(--vantage-text);
    --lms-accent-text: var(--vantage-bg);
    font-family: var(--vantage-font-body);
}
/* Dialogs and record popups carried the pre-brand geometry: 6px corners,
   tinted header and footer bands and small bordered buttons. They now match
   the rest of the app, borders over shadows and one ink primary. */
.lms-popup-box {
    border-radius: 14px;
    border-color: var(--vantage-line);
    background: var(--vantage-surface);
    box-shadow: 0 20px 52px rgba(0, 0, 0, 0.34);
}
.lms-popup-title {
    padding: 14px 18px;
    background: transparent;
    border-bottom: 1px solid var(--vantage-line-2);
    border-radius: 0;
    font-family: var(--vantage-font-heading);
    font-size: 15px;
    font-weight: 500;
    letter-spacing: -0.01em;
}
.lms-popup-close-x {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    margin-right: -6px;
    border-radius: 8px;
    font-size: 15px;
    color: var(--vantage-text-3);
    transition: background-color 0.12s ease, color 0.12s ease;
}
.lms-popup-close-x:hover { background: var(--vantage-fill-2); color: var(--vantage-text); }
.lms-popup-body { background: transparent; padding: 4px 0; }
.lms-popup-footer {
    gap: 8px;
    padding: 14px 18px;
    background: transparent;
    border-top: 1px solid var(--vantage-line-2);
    border-radius: 0;
}
.lms-popup-btn {
    height: 36px;
    padding: 0 16px;
    border-radius: 9px;
    border: 1px solid var(--vantage-line);
    background: var(--vantage-fill);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13px;
    font-weight: 500;
    transition: background-color 0.12s ease, opacity 0.12s ease;
}
.lms-popup-btn:hover { background: var(--vantage-fill-2); }
.lms-popup-btn-primary,
.lms-popup-btn-primary:hover {
    border: 0;
    background: var(--vantage-text);
    color: var(--vantage-bg);
    font-weight: 600;
}
.lms-popup-btn-primary:hover { opacity: 0.9; }
.lms-popup-btn-danger,
.lms-popup-btn-danger:hover {
    border-color: color-mix(in srgb, var(--lms-danger-text) 30%, transparent);
    background: color-mix(in srgb, var(--lms-danger-text) 10%, transparent);
    color: var(--lms-danger-text);
    font-weight: 600;
}
.lms-popup-btn-danger:hover { background: color-mix(in srgb, var(--lms-danger-text) 16%, transparent); }
.lms-popup-btn:disabled { opacity: 0.45; }

/* Alert, confirm and prompt bodies. */
.lms-dialog-msg {
    padding: 18px;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--vantage-text);
}
.lms-dialog-input {
    width: calc(100% - 36px);
    margin: 0 18px 16px;
    height: 38px;
    padding: 0 12px;
    border: 1px solid var(--vantage-line);
    border-radius: 9px;
    background: var(--vantage-surface);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13.5px;
}
.lms-dialog-input:focus,
html.dark-mode .lms-dialog-input:focus {
    outline: none;
    border-color: var(--vantage-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vantage-accent) 20%, transparent);
}

/* The body-level chat modals are inline-styled; bring their shell in line. */
.lms-modal-overlay > div {
    background: var(--vantage-surface) !important;
    border-color: var(--vantage-line) !important;
    border-radius: 14px !important;
    box-shadow: 0 20px 52px rgba(0, 0, 0, 0.34) !important;
    font-family: var(--vantage-font-body);
}

/* ─── Surface: channels and direct messages ────────────────── */
/* Token remap over the whole chat shell (rail, channel and DM
   panels, thread panel, composer, mention menu). The row-action /
   context menu is a single shared component used by chat and the
   grids, so it is remapped globally here and stays uniform
   everywhere it appears. */
#cd-root,
.lms-row-act-menu,
.lms-emoji-picker {
    --lms-bg: var(--vantage-bg);
    --lms-bg-panel: var(--vantage-surface);
    --lms-bg-alt: var(--vantage-fill);
    --lms-border: var(--vantage-line);
    --lms-border-light: var(--vantage-line-2);
    --lms-text: var(--vantage-text);
    --lms-text-dim: color-mix(in srgb, var(--vantage-text) 86%, var(--vantage-bg));
    --lms-text-muted: var(--vantage-text-2);
    --lms-text-faint: var(--vantage-text-3);
    --lms-active-tint: var(--vantage-fill-2);
    /* Chat used the warm accent for links, send affordance and unread
       badges; attention cues shift to the brand accent so desktop and
       the mobile bottom bar agree. Data-viz meters elsewhere keep warm. */
    --lms-accent-warm: var(--vantage-accent);
    font-family: var(--vantage-font-body);
}

/* The chat panels are transparent and show the app shell behind
   them, which still carries the pre-brand background; paint the
   shell region under the chat so its darks match the sidebar's
   palette instead of the old neutral black. */
#cd-root { background: var(--vantage-bg); }

/* Headings take Satoshi: the chat title bar, the channel welcome
   header, and the rail's section labels. */
#cd-root .cd-chat-title,
#cd-root .ch-welcome-title {
    font-family: var(--vantage-font-heading);
    font-weight: 700;
    letter-spacing: -0.01em;
}
#cd-root .cd-section-head {
    font-family: var(--vantage-font-heading);
    font-weight: 500;
    letter-spacing: 0.01em;
}

/* Selected channel row: the same accent wash as the sidebar's
   selected node, so both panels speak one "you are here" language. */
#cd-root .cd-row.active {
    background: color-mix(in srgb, var(--vantage-accent) 13%, transparent);
    color: var(--vantage-text);
}
#cd-root .cd-row.active .cd-row-lead { color: var(--vantage-accent); }

/* Unread badges: solid accent with page-ink text, matching the
   bottom bar's badges (white text fails contrast on the pale dark-
   mode accent). */
#cd-root .cd-row-badge {
    background: var(--vantage-accent);
    color: var(--vantage-bg);
}

/* ─── Surface: settings ────────────────────────────────────── */
/* Small, self-contained screen; styled with the brand tokens
   directly rather than remapped, since its old markup was fully
   inline-styled. Left-set column, matching the marketing site. */
/* ─── Settings: sections and rows ──────────────────────────────
   The screen used to be four cards in a two column grid, which left two thirds
   of a wide window empty and had nowhere to put the next setting. It is a list
   of decisions now, grouped into sections with an index beside them, and a row
   per decision rather than a border around each one. */
.st-root .st-head { max-width: 62ch; }

.st-sections { min-width: 0; }
.st-sections > section { margin-top: 34px; }
.st-sections > section:first-child { margin-top: 26px; }
/* The heading, where the section's settings are kept, and then a rule closing
   the block. The rule used to sit between a heading and its own description,
   which reads as a heading for the rule. */
.st-sections section { scroll-margin-top: 16px; }
/* One definition. There were two, and the later one won, which is how this
   file has already lost .st-row, .st-inline, .st-themes and .st-btn-danger. */
.st-sec-head { display: flex; align-items: baseline; gap: 12px; padding: 0; }
.st-sec-head h2 {
    margin: 0;
    font-family: var(--vantage-font-heading);
    /* 16 against a 13.5 row label. At 15 against 14 the section heading and
       the row beneath it were the same voice. */
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.015em;
}
.st-sec-head .st-where { margin-left: auto; }
.st-sec-sub { margin: 5px 0 0; font-size: 12.5px; color: var(--vantage-text-3); max-width: 62ch; }
.st-sec-rule { margin-top: 9px; border-bottom: 1px solid var(--vantage-line); }

.st-row {
    display: flex;
    /* Centred, not top-aligned: a one-line control beside a three-line
       description sat level with the first line and read as attached to it. */
    align-items: center;
    gap: 24px;
    padding: 15px 0;
    border-bottom: 1px solid var(--vantage-line-2);
    border-top: 0;
}
.st-row:last-child { border-bottom: 0; }
.st-row-main { flex: 1; min-width: 0; }
.st-row-t { font-size: 13.5px; font-weight: 500; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.st-row-d { margin: 3px 0 0; font-size: 12.5px; color: var(--vantage-text-3); max-width: 60ch; }
.st-row-ctl { flex: none; min-width: 0; display: flex; align-items: center; gap: 9px; flex-wrap: wrap; justify-content: flex-end; }
/* A control too wide to share a line with its label takes the line beneath,
   still inside the same measure. */
.st-row-stack { display: block; }
/* block, not flex: this row's control is a picker followed by a caption, and
   as flex siblings the caption sat beside the pills on the last group's line. */
.st-row-stack .st-row-ctl { display: block; margin-top: 11px; }
@media (max-width: 620px) {
    .st-row { flex-direction: column; align-items: stretch; gap: 11px; }
    .st-row-ctl { width: 100%; justify-content: flex-start; align-items: flex-start; }
    /* A status block takes its own line rather than starting wherever the
       badge beside it happens to end, which on a phone left the two-factor
       pill indented by the width of the words "Your account" and reading as
       though it belonged to nothing. */
    .st-row-ctl > .st-state-area { flex-basis: 100%; }
}

/* Where a setting lives. Not decoration: pins follow the account and the rest
   follow the browser, and people only notice when they sign in elsewhere. */
.st-where {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 11.5px;
    color: var(--vantage-text-3);
    white-space: nowrap;
}
.st-state { font-size: 12.5px; color: var(--vantage-text-3); }
.st-state.st-state-on { color: var(--lms-success-ink); }

.st-seg { display: flex; gap: 3px; padding: 3px; background: var(--vantage-fill); border-radius: var(--vantage-r-sm); }
.st-seg button {
    min-height: 32px;
    padding: 0 11px;
    border: 0;
    border-radius: 4px;
    background: transparent;
    color: var(--vantage-text-2);
    font-family: var(--vantage-font-body);
    font-size: 13px;
    cursor: pointer;
    transition: background-color 0.15s cubic-bezier(0.4,0,0.2,1), color 0.15s cubic-bezier(0.4,0,0.2,1);
}
.st-seg button:hover { background: var(--vantage-fill-2); color: var(--vantage-text); }
.st-seg button[aria-checked="true"] { background: var(--vantage-fill-2); color: var(--vantage-text); font-weight: 600; }

.st-who { display: flex; align-items: center; gap: 12px; }
.st-avatar {
    width: 42px; height: 42px; border-radius: 50%;
    display: grid; place-items: center;
    background: var(--vantage-fill-2);
    font-family: var(--vantage-font-heading);
    font-weight: 700;
}
.st-who-n { display: block; font-size: 15px; }
.st-who-s { display: block; font-size: 12.5px; color: var(--vantage-text-3); }

.st-note {
    margin: 0 0 10px;
    padding: 10px 12px;
    background: var(--vantage-fill);
    border-radius: var(--vantage-r-sm);
    font-size: 12.5px;
    /* text-2, not text-3: this block sits on fill rather than surface, and the
       quieter ink measures 4.42:1 there, under the 4.5 this size needs. */
    color: var(--vantage-text-2);
    max-width: 62ch;
}
.st-note:empty { display: none; }
.st-inline { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
.st-confirm { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.st-state-area { font-size: 12.5px; color: var(--vantage-text-3); }


.st-root {
    height: 100%;
    box-sizing: border-box;
    overflow-y: auto;
    padding: 30px 24px 80px;
    /* One column, 690px, centred.
       It was a 170px index beside a 760px column. The index was five links
       duplicating five headings already on screen and spent its width doing
       it, and the column was wide enough that a description ended around
       x=700 while its control began at x=965: 250 to 350px of nothing between
       a label and the thing it controls, on every row. */
    display: block;
    max-width: 690px;
    margin: 0 auto;
    background: var(--vantage-bg);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13px;
}
/* The cap and the centring live on an inner wrapper, not on .st-root: that
   element is the screen's scroll container, and capping it moves its scrollbar
   inboard so the bar floats in the middle of the panel. */
.st-root { max-width: none; margin: 0; }
.st-root > .st-head,
.st-root > .st-sections { max-width: 690px; margin-inline: auto; }

.st-title {
    margin: 0 0 3px;
    font-family: var(--vantage-font-heading);
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.02em;
}
.st-lede {
    margin: 0 0 18px;
    font-size: 13px;
    color: var(--vantage-text-3);
}
.st-card {
    max-width: 620px;
    padding: 16px 18px;
    margin-bottom: 14px;
    background: var(--vantage-fill);
    border: 1px solid var(--vantage-line-2);
    border-radius: 12px;
}
.st-card-title {
    margin: 0 0 4px;
    font-family: var(--vantage-font-heading);
    font-size: 15px;
    font-weight: 500;
    letter-spacing: -0.01em;
}
.st-hint {
    margin: 0 0 14px;
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--vantage-text-2);
}
.st-hint:last-child { margin-bottom: 0; }

/* Segmented display-mode control: quiet track, active pill takes the
   accent wash used for selected states across the app. */
.st-seg {
    display: inline-flex;
    gap: 3px;
    padding: 3px;
    background: var(--vantage-fill);
    border: 1px solid var(--vantage-line-2);
    border-radius: 10px;
}
.st-seg-opt {
    min-width: 84px;
    padding: 7px 16px;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: var(--vantage-text-2);
    font-family: var(--vantage-font-body);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.st-seg-opt:hover { color: var(--vantage-text); }
.st-seg-opt.st-seg-active {
    background: color-mix(in srgb, var(--vantage-accent) 16%, transparent);
    color: var(--vantage-text);
}

/* Theme picker: a swatch showing each palette's bar, sidebar and
   canvas, so the choice is visible rather than a word. */
/* Two by two rather than a wrapping row: four fixed-width swatches never fit
   the card, so the last one was orphaned onto a line of its own. */
/* Account: identity on one row, then the facts about this session. */
.st-acct { display: flex; align-items: center; gap: 12px; }
.st-acct-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--vantage-fill-2);
    color: var(--vantage-text);
    font-family: var(--vantage-font-heading);
    font-size: 13px;
    font-weight: 600;
}
.st-acct-id { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.st-acct-name {
    font-family: var(--vantage-font-heading);
    font-size: 15px;
    font-weight: 500;
    letter-spacing: -0.01em;
}
.st-acct .st-hint { margin: 0; }
.st-facts { margin-top: 14px; border-top: 1px solid var(--vantage-line-2); }
.st-fact {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid var(--vantage-line-2);
}
.st-fact:last-child { border-bottom: 0; }
.st-fact-k { color: var(--vantage-text-2); }
.st-fact-v { font-variant-numeric: tabular-nums; }
/* A session pointed at the test database is worth saying loudly: it is the one
   fact here that changes what the numbers on every other screen mean. */
.st-env-test {
    padding: 1px 7px;
    border-radius: var(--vantage-r-pill);
    background: color-mix(in srgb, var(--lms-warning-text) 16%, transparent);
    color: var(--lms-warning-text);
    font-weight: 600;
}

/* A wrapping row of named pills, not a grid of cards.
   As cards this control was 825px tall in a page whose other rows are 48 to
   160: one control seventeen times the height of the shortest thing on the
   screen. Bare swatches were the other way out and are worse, because five of
   the nine schemes are near-black and at swatch size Graphite, Vantage, Slate,
   Sepia and OLED are one dark rectangle. A swatch tells options apart when
   they are hues; these are shades of one, so the names stay. */
.st-themes { display: flex; flex-wrap: wrap; gap: 6px; flex: 1; min-width: 0; }
.st-theme {
    /* colour and font stated: a button with neither takes the user agent's
       buttontext, which is near black, and the labels vanish on a dark
       surface. */
    color: var(--vantage-text-2);
    font: inherit;
    font-size: 12.5px;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 0 11px 0 8px;
    min-height: 30px;
    white-space: nowrap;
    background: transparent;
    border: 1px solid var(--vantage-line);
    border-radius: 8px;
    cursor: pointer;
    transition: border-color 0.15s cubic-bezier(0.4,0,0.2,1),
                background-color 0.15s cubic-bezier(0.4,0,0.2,1);
}
.st-theme:hover { background: var(--vantage-fill); color: var(--vantage-text); }
/* The selected card is marked by its border and by the tint under its label.
   Not by a wash over the whole card: the swatch is a sample of the theme's
   actual colours, and tinting it makes the chosen theme the one card that
   misreports what it is going to look like. */
.st-theme.st-theme-active {
    border-color: var(--vantage-accent);
    box-shadow: inset 0 0 0 1px var(--vantage-accent);
    color: var(--vantage-text);
    font-weight: 500;
}
/* The tint darkens the ground under this label, and the quiet ink measures
   3.87:1 on it, so the chosen card gets the next ink up. */
.st-theme.st-theme-active .st-theme-hint { color: var(--vantage-text-2); }
.st-theme-swatch {
    position: relative;
    display: block;
    flex: none;
    width: 17px;
    height: 17px;
    margin: 0;
    border: 1px solid rgba(128, 128, 128, 0.34);
    border-radius: 5px;
    overflow: hidden;
}
/* The chosen scheme's own description, under the picker: printing nine of
   them at once explains a choice already made. Indented to the pills, because
   tight under the last group it read as a label for that group. */
.st-theme-hint {
    display: block;
    margin: 9px 0 0 78px;
    font-size: 12px;
    color: var(--vantage-text-3);
}
@media (max-width: 620px) { .st-theme-hint { margin-left: 0; } }
/* A miniature of the application: title bar across the top, navigation rail
   down the left, content in the rest. The separators are drawn because at this
   size the themes' own one-shade borders disappear and the sample reads as a
   plain rectangle. */
.st-theme-swatch-bar { position: absolute; inset: 0 0 auto 0; height: 5px; border-bottom: 1px solid rgba(128,128,128,0.28); }
.st-theme-swatch-side { position: absolute; inset: 5px auto 0 0; width: 36%; border-right: 1px solid rgba(128,128,128,0.28); }
.st-swatch-graphite { background: #1b1b1b; }
.st-swatch-graphite .st-theme-swatch-bar  { background: #0f0f0f; }
.st-swatch-graphite .st-theme-swatch-side { background: #2b2b2b; }
.st-swatch-vantage  { background: #0a1114; }
.st-swatch-vantage .st-theme-swatch-bar   { background: #050a0c; }
.st-swatch-vantage .st-theme-swatch-side  { background: #1a262c; }
/* All three panes black, because that is now what the theme does: the sample
   is separated by its hairlines alone, exactly as the screen is. */
.st-swatch-oled     { background: #000000; }
.st-swatch-oled .st-theme-swatch-bar      { background: #000000; }
.st-swatch-oled .st-theme-swatch-side     { background: #000000; }
/* Groups inside the picker. The label is small and quiet because it is a
   signpost between cards, not a heading anybody reads on its own. */
#lms-theme-picker { display: flex; flex-direction: column; gap: 11px; min-width: 0; }
/* The group name sits beside its options rather than above them, so four
   groups cost four lines instead of eight. */
.st-theme-group { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; min-width: 0; }
.st-theme-glab { flex: none; width: 66px; margin: 0; font-size: 10.5px; color: var(--vantage-text-3); }

/* The automatic option shows both halves of what it will choose between. */
.st-swatch-system { background: linear-gradient(105deg, #1b1b1b 0 50%, #f6f3ed 50% 100%); }
.st-swatch-system .st-theme-swatch-bar,
.st-swatch-system .st-theme-swatch-side { background: transparent; border-color: rgba(128,128,128,0.34); }

.st-swatch-slate    { background: #171a1f; }
.st-swatch-slate .st-theme-swatch-bar     { background: #12151a; }
.st-swatch-slate .st-theme-swatch-side    { background: #262b33; }
.st-swatch-sepia    { background: #171310; }
.st-swatch-sepia .st-theme-swatch-bar     { background: #120f0d; }
.st-swatch-sepia .st-theme-swatch-side    { background: #26201b; }
.st-swatch-contrast { background: #ffffff; }
.st-swatch-contrast .st-theme-swatch-bar  { background: #ffffff; }
.st-swatch-contrast .st-theme-swatch-side { background: #ffffff; }
.st-swatch-contrast-dark { background: #000000; }
.st-swatch-contrast-dark .st-theme-swatch-bar  { background: #000000; }
.st-swatch-contrast-dark .st-theme-swatch-side { background: #000000; }
/* The two accessible schemes draw their sample from the hairlines alone,
   because that is what they do on screen: structure by line, not by fill. */
.st-swatch-contrast .st-theme-swatch-bar,
.st-swatch-contrast .st-theme-swatch-side { border-color: rgba(0,0,0,0.55); }
.st-swatch-contrast-dark .st-theme-swatch-bar,
.st-swatch-contrast-dark .st-theme-swatch-side { border-color: rgba(255,255,255,0.55); }

.st-swatch-paper    { background: #f6f3ed; }
.st-swatch-paper .st-theme-swatch-bar     { background: #efebe4; }
.st-swatch-paper .st-theme-swatch-side    { background: #fffefb; }

/* A menu item that reports a current selection. */
.lms-menu-item .lms-menu-check {
    width: 14px;
    flex-shrink: 0;
    color: var(--vantage-accent);
    text-align: center;
}

/* The old inline-group rule that used to live here shared its name with the
   settings row above and, being later in the file, silently won: it set
   align-items:center on every row, which pushed the colour scheme's label
   196px to the right of every other label on the page. The two things that
   needed one class each now have one class each, and this one is .st-inline. */
.st-inline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.st-btn {
    height: 36px;
    padding: 0 16px;
    border: 1px solid var(--vantage-line);
    border-radius: 9px;
    background: var(--vantage-fill);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: opacity 0.12s ease, background-color 0.12s ease;
}
.st-btn:hover { background: var(--vantage-fill-2); }
.st-btn-primary {
    border: 0;
    background: var(--vantage-text);
    color: var(--vantage-bg);
    font-weight: 600;
}
.st-btn-primary:hover { background: var(--vantage-text); opacity: 0.9; }
/* A disabled button has to look disabled. Without this a control that cannot
   be used (the install button before the browser offers a prompt, "Activate
   2FA" before a code is entered) rendered at full contrast and invited a
   click that silently did nothing. */
.st-btn:disabled,
.st-btn[disabled] { cursor: not-allowed; opacity: 0.42; }
.st-btn:disabled:hover { background: var(--vantage-fill); }
.st-btn-primary:disabled:hover { background: var(--vantage-text); opacity: 0.42; }
.st-btn-danger {
    /* danger-ink, not danger-text: the two differ in the light theme (#b91c1c
       against #dc2626) and the brighter one measures 3.78:1 on this tinted
       background, under the 4.5 a 13px label needs. -ink is the token that
       exists to be read as text. */
    border-color: color-mix(in srgb, var(--lms-danger-ink) 30%, transparent);
    background: color-mix(in srgb, var(--lms-danger-ink) 9%, transparent);
    color: var(--lms-danger-ink);
}
.st-btn-danger:hover {
    background: color-mix(in srgb, var(--lms-danger-ink) 15%, transparent);
}

.st-input {
    height: 36px;
    padding: 0 12px;
    border: 1px solid var(--vantage-line);
    border-radius: 9px;
    background: var(--vantage-surface);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13px;
}
.st-input:focus {
    outline: none;
    border-color: var(--vantage-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vantage-accent) 22%, transparent);
}

/* Status lines with a small leading dot: accent when 2FA is active,
   neutral otherwise. */
.st-status {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: var(--vantage-text-2);
}
.st-status::before {
    content: '';
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--vantage-text-3);
}
.st-status-on { color: var(--vantage-text); font-weight: 500; }
.st-status-on::before { background: var(--lms-success-text, #4ade80); }


@media (max-width: 768px) {
    .st-root { padding: 20px 16px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Print
   ═══════════════════════════════════════════════════════════════════════
   There was no print block in any of these files until now. A loan tape
   printed from OLED came out a black page, and from every scheme the
   navigation, the search box and the action buttons printed with it.
   A lender prints: schedules for a borrower, statements, a tape for an
   auditor. So the rules here are not a theme anybody picks, they apply
   over whichever one is on screen.

   Ink on paper, so: the palette is forced light regardless of the theme,
   every fill is dropped, structure comes from rules, and anything that
   exists only to be clicked is removed.
   ═══════════════════════════════════════════════════════════════════════ */

@media print {

    /* The tokens are re-pointed rather than each surface being overridden,
       for the same reason a theme re-points them: everything that follows
       them follows this too, including anything added later. */
    html, html[data-theme], html.dark-mode {
        --vantage-bg:       #ffffff;
        --vantage-surface:  #ffffff;
        --vantage-chrome:   #ffffff;
        --vantage-text:     #000000;
        --vantage-text-2:   #222222;
        --vantage-text-3:   #444444;
        --vantage-line:     #000000;
        --vantage-line-2:   #bbbbbb;
        --vantage-fill:     transparent;
        --vantage-fill-2:   transparent;
        --vantage-accent:   #000000;
        --lms-success-ink:  #000000;
        --lms-warning-ink:  #000000;
        --lms-danger-ink:   #000000;
        --lms-bg:           #ffffff;
        --lms-text:         #000000;
    }

    /* Colour is not carried onto paper. Some of these pages go out to a
       borrower or an auditor on whatever printer is nearest, and half of
       those are monochrome: a status that means one thing in red and
       another in amber means nothing once both come out grey. Every place
       that uses colour to say something also says it in words, so the
       words are what survive. */

    html, body {
        height: auto !important;
        overflow: visible !important;
        background: #ffffff !important;
        color: #000000 !important;
    }

    /* The shell is a scrolling application on screen and a stack of pages
       on paper: every fixed height and inner scroller has to be released
       or only the first screenful prints. */
    #main,
    #main > .lms-layout,
    .lms-layout,
    .lms-panel-main,
    .st-root,
    .dash-root,
    .lms-main {
        height: auto !important;
        max-height: none !important;
        min-height: 0 !important;
        overflow: visible !important;
        display: block !important;
        background: #ffffff !important;
    }

    /* Furniture. None of it does anything on paper, and the navigation
       alone is a third of the width. */
    .lms-topbar,
    .lms-sidebar,
    .lms-panel-left,
    .lms-resize-handle,
    #lms-bottom-nav,
    .lms-skip-link,
    .lms-fab,
    .st-index,
    .lms-cmdk,
    .lms-acct,
    [data-acct-menu],
    .lms-row-act,
    .lms-menu,
    .lms-tooltip,
    .notif-dropdown,
    #notif-dropdown {
        display: none !important;
    }

    /* Controls print as ink and tell the reader nothing. A disabled-looking
       button on a statement is worse than no button. */
    button,
    .st-btn,
    .lms-btn,
    input[type="search"],
    .lms-search,
    .st-seg,
    /* The whole picker, not just its cards: hiding only .st-themes left the
       group labels printed with nothing underneath them. */
    #lms-theme-picker,
    /* Grid furniture. Names taken off the live DOM rather than guessed: the
       toolbar, the search slot and the record count are all controls, and a
       printed tape with an empty search box at the top of it looks like a
       screenshot rather than a document. */
    .lms-tabgrid-toolbar,
    .lms-tabgrid-search,
    .lms-gf-search-slot,
    .lms-gf-search,
    .tabulator-header-filter,
    .tabulator-col-resize-handle,
    .tabulator-responsive-collapse-toggle,
    /* The bar above the grid: a search box and a record count, neither of
       which belongs on a document. */
    .lms-gf-bar,
    /* Selection, row actions and the responsive expander. Whole columns, not
       just their controls: hiding only the checkbox and the toggle left three
       empty columns holding 108px of the width a tape needs for its figures.
       Header and cell both, or the two fall out of step. */
    .tabulator-col.lms-row-sel-col,
    .tabulator-cell.lms-row-sel-col,
    .tabulator-col.lms-row-act-col,
    .tabulator-cell.lms-row-act-col,
    .tabulator-col.lms-rc-toggle-col,
    .tabulator-cell.lms-rc-toggle-col,
    .lms-spacer-col {
        display: none !important;
    }

    /* Grids. Tabulator draws its own colours inline, so those are overridden
       rather than inherited, and a row must not be split across a page. */
    table, .tabulator {
        width: 100% !important;
        border-collapse: collapse !important;
        background: #ffffff !important;
        color: #000000 !important;
        font-size: 9.5pt;
    }
    th, .tabulator-col {
        background: #ffffff !important;
        color: #000000 !important;
        border-bottom: 1pt solid #000000 !important;
        font-weight: 600;
    }
    td, .tabulator-cell {
        background: #ffffff !important;
        color: #000000 !important;
        border-top: 0.5pt solid #bbbbbb !important;
    }
    tr, .tabulator-row { page-break-inside: avoid; break-inside: avoid; }
    thead { display: table-header-group; }   /* repeat the head on every page */
    tfoot { display: table-footer-group; }

    /* A card is a box on screen because it needs to be picked out of a
       busy page. On paper the page is not busy. */
    .st-row, .dash-card, .card, .lms-card {
        background: #ffffff !important;
        border: 0 !important;
        box-shadow: none !important;
        page-break-inside: avoid;
        break-inside: avoid;
    }

    h1, h2, h3 { page-break-after: avoid; break-after: avoid; color: #000000 !important; }

    /* A printed page that does not say where it came from is not much use to
       whoever finds it in a file six months later. */
    @page {
        margin: 16mm 14mm;
    }

    /* A link that reads "here" is useless once it cannot be clicked. */
    a[href^="http"]::after {
        content: " (" attr(href) ")";
        font-size: 8pt;
        color: #444444;
    }
}

/* ── Settings, coarse pointer ───────────────────────────────────────────
   A finger is not a cursor. Every control on this screen was 28 to 32px
   tall, which is fine for a mouse and under the 44px a touch target needs.
   Written at the end of the file, after the base rules, because equal
   specificity is decided by order and the base was winning. */
@media (pointer: coarse) {
    .st-btn, .st-theme { min-height: 44px; }
    .st-seg { padding: 3px; }
    /* 44 on the segment, not on its track: the segment is the thing tapped. */
    .st-seg button { min-height: 44px; padding: 0 14px; }
    .st-input { height: 44px; }
}

/* ══ Two-factor enrolment dialog ═══════════════════════════════════════
   A native <dialog>, so the focus trap, the Escape handling, the inert
   background and the top layer come from the browser. The password step it
   replaced sat in the row's control column, where it was a 335px block with
   its own label, question and three controls wrapping in the gutter beside
   the row it belonged to. */
.st-dialog {
    padding: 0;
    border: 0;
    border-radius: 14px;
    max-width: 460px;
    width: calc(100% - 32px);
    background: var(--vantage-surface);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13px;
    box-shadow: 0 18px 60px rgba(0, 0, 0, 0.28), 0 0 0 1px var(--vantage-line);
    /* The step slides in from 12px to one side, and the browser's own
       dialog rule is overflow:auto, so for the length of the animation the
       dialog grew a horizontal scrollbar over 3px of travel. clip rather
       than hidden: it stops the overflow without making this a scroll
       container, which would take the vertical axis with it. */
    overflow-x: clip;
}
.st-dialog::backdrop { background: rgba(0, 0, 0, 0.42); backdrop-filter: blur(2px); }
.st-d-head { display: flex; align-items: flex-start; gap: 14px; padding: 18px 20px 0; }
.st-d-head h2 {
    margin: 0;
    font-family: var(--vantage-font-heading);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.015em;
}
.st-d-step { margin: 2px 0 0; font-size: 11.5px; color: var(--vantage-text-3); }
.st-d-step:empty { display: none; }
.st-d-x {
    margin-left: auto;
    appearance: none;
    background: transparent;
    border: 0;
    color: var(--vantage-text-3);
    cursor: pointer;
    border-radius: 7px;
    width: 30px; height: 30px;
    display: grid; place-items: center;
    font-size: 18px; line-height: 1;
}
.st-d-x:hover { background: var(--vantage-fill); color: var(--vantage-text); }
.st-d-body { padding: 14px 20px 4px; }
.st-d-body p { margin: 0 0 12px; color: var(--vantage-text-2); }
.st-d-centre { text-align: center; }
.st-d-label { display: block; margin-bottom: 6px; font-size: 12.5px; color: var(--vantage-text); font-weight: 500; }
.st-d-body .st-input { width: 100%; }
.st-d-foot { display: flex; gap: 9px; justify-content: flex-end; padding: 14px 20px 18px; flex-wrap: wrap; }
.st-d-left { margin-right: auto; }

/* Three steps, because the middle one is the only place a person gets stuck
   and it helps to know it is the middle. */
.st-d-prog { display: flex; gap: 6px; padding: 14px 20px 0; }
.st-d-prog[hidden] { display: none; }
.st-d-prog span { flex: 1; height: 3px; border-radius: 2px; background: var(--vantage-fill-2); position: relative; overflow: hidden; }
.st-d-prog span::after {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--vantage-accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 260ms cubic-bezier(0.4, 0, 0.2, 1);
}
.st-d-prog span[data-on]::after { transform: scaleX(1); }

/* A QR renders dark-on-white, so it keeps a white chip to stay scannable
   under a dark scheme. */
.st-d-qr {
    display: block;
    width: 196px;
    margin: 0 auto 14px;
    padding: 10px;
    background: #ffffff;
    border: 1px solid var(--vantage-line);
    border-radius: 10px;
    line-height: 0;
}
.st-dialog details { border-top: 1px solid var(--vantage-line-2); padding-top: 10px; }
.st-dialog summary {
    cursor: pointer;
    font-size: 12.5px;
    color: var(--vantage-text-2);
    list-style: none;
    display: flex;
    align-items: center;
    min-height: 34px;
}
.st-dialog summary::-webkit-details-marker { display: none; }
.st-dialog summary::before { content: '\25B8 '; color: var(--vantage-text-3); margin-right: 5px; }
.st-dialog details[open] summary::before { content: '\25BE '; }
.st-d-secret { font-size: 12px; }
.st-d-secret code { user-select: all; font-family: ui-monospace, Menlo, Consolas, monospace; letter-spacing: 0.04em; }
.st-d-code {
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-size: 21px;
    letter-spacing: 0.34em;
    text-align: center;
    height: 52px;
    padding-left: 0.34em;
}
.st-d-err { margin: 9px 0 0; color: var(--lms-danger-ink); font-size: 12.5px; min-height: 18px; }
.st-d-ok {
    width: 44px; height: 44px;
    border-radius: 50%;
    display: grid; place-items: center;
    margin: 2px auto 12px;
    background: color-mix(in srgb, var(--lms-success-ink) 14%, transparent);
    color: var(--lms-success-ink);
}

/* ── Motion ──────────────────────────────────────────────────────────────
   Each movement answers "where did that come from". The dialog rises off the
   surface it sits above; a step moves the way the sequence moves, forward
   from the right and back from the left, so pressing Back looks like going
   back. transform and opacity only, so none of it runs layout. */
@keyframes st-d-in    { from { opacity: 0; transform: translateY(10px) scale(0.985); } }
@keyframes st-d-out   { to   { opacity: 0; transform: translateY(6px) scale(0.99); } }
@keyframes st-d-bk-in { from { opacity: 0; } }
@keyframes st-d-fwd   { from { opacity: 0; transform: translateX(12px); } }
@keyframes st-d-back  { from { opacity: 0; transform: translateX(-12px); } }
@keyframes st-d-tick  { to   { stroke-dashoffset: 0; } }
@keyframes st-d-nudge { 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }

.st-dialog[open] { animation: st-d-in 210ms cubic-bezier(0.4, 0, 0.2, 1) both; }
.st-dialog[open]::backdrop { animation: st-d-bk-in 210ms cubic-bezier(0.4, 0, 0.2, 1) both; }
/* The exit is quicker than the entrance: nobody needs help understanding
   that a thing has gone. */
.st-dialog.closing { animation: st-d-out 140ms cubic-bezier(0.4, 0, 0.2, 1) both; }
.st-d-body[data-dir="fwd"],  .st-d-foot[data-dir="fwd"]  { animation: st-d-fwd 190ms cubic-bezier(0.4, 0, 0.2, 1) both; }
.st-d-body[data-dir="back"], .st-d-foot[data-dir="back"] { animation: st-d-back 190ms cubic-bezier(0.4, 0, 0.2, 1) both; }
/* The footer follows a beat behind, so the eye reads the content and then
   finds the buttons. */
.st-d-foot[data-dir] { animation-delay: 40ms; }
.st-d-ok { animation: st-d-in 220ms cubic-bezier(0.4, 0, 0.2, 1) both; }
.st-d-ok svg path { stroke-dasharray: 24; stroke-dashoffset: 24; animation: st-d-tick 320ms cubic-bezier(0.4, 0, 0.2, 1) 90ms both; }
.st-input.st-d-bad { border-color: var(--lms-danger-ink); animation: st-d-nudge 140ms cubic-bezier(0.4, 0, 0.2, 1); }

/* A phone gets a sheet, not a card floating in the middle of the screen. */
@media (max-width: 560px) {
    .st-dialog {
        max-width: none;
        width: 100%;
        margin: auto 0 0;
        border-radius: 16px 16px 0 0;
        max-height: 92vh;
        /* overflow-y, not the shorthand: overflow would reset the clip above
           and the scrollbar would come back on a phone. */
        overflow-y: auto;
    }
}
@media (pointer: coarse) {
    .st-d-x { width: 44px; height: 44px; }
    .st-dialog summary { min-height: 44px; }
}

/*
 * Reduce means reduce, not remove: the fade stays so a thing still appears,
 * the travel goes. Written in the same block as the animations above, because
 * separated from them it is the part that gets forgotten.
 */
@media (prefers-reduced-motion: reduce) {
    @keyframes st-d-in   { from { opacity: 0; } }
    @keyframes st-d-out  { to   { opacity: 0; } }
    @keyframes st-d-fwd  { from { opacity: 0; } }
    @keyframes st-d-back { from { opacity: 0; } }
    @keyframes st-d-nudge { from { opacity: 1; } }
    .st-dialog[open], .st-dialog.closing,
    .st-d-body[data-dir], .st-d-foot[data-dir] { animation-duration: 120ms; }
    .st-d-prog span::after { transition: none; }
    .st-d-ok svg path { stroke-dashoffset: 0; animation: none; }
}
