/* ============================================================
   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;
    --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;
    --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 {
    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-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;
    --vantage-text:     #f2f2f2;
    --vantage-text-2:   #a8a8a8;
    --vantage-text-3:   #808080;
    --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-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-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. */
html[data-theme="light"] {
    --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;
    --vantage-brand-a:  #7c5cd6;
    --vantage-brand-b:  #d2603d;
    --vantage-brand-c:  #d9971f;
    --lms-success-ink: #12703a;
    --lms-warning-ink: #8a4b04;
    --lms-danger-ink: #b91c1c;
}

/* ─── 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,
.lms-topbar:not(.lms-tb-collapsed) #lms-tb-collapse {
    background: var(--vantage-fill-2);
    color: var(--vantage-text);
}

/* 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-surface);
    --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);
}
.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); }
.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"]),
#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"]) {
    /* 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"]),
#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="light"] #lms-panel-main input[type="date"]::-webkit-calendar-picker-indicator,
html[data-theme="light"] #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"]),
    #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-row-top { margin-top: 14px; }
/* 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], .st-enrol[hidden] { display: none; }
.st-state { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.st-state .st-row-top { margin-top: 0; }
.st-enrol { margin-top: 14px; }
.st-secret { font-size: 11px; }
.st-secret code { user-select: all; }
.st-input-code { width: 150px; }
.st-msg { margin-top: 10px; font-size: 12px; min-height: 16px; }

/* The chosen theme is named as well as outlined: a border alone asks the eye to
   compare four cards to find which one is different. */
.st-theme-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.st-theme-tick { color: var(--vantage-accent); font-size: 12px; opacity: 0; }
.st-theme-active .st-theme-tick { opacity: 1; }

@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); }

/* ─── 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;
    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; }
}

/* ─── 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; }

.dash-card {
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-lg);
    background: transparent;
}
.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; }

/* Facility utilisation: figures, not bars. Headroom leads because it is what
   limits new lending; the percentage supports it and only carries colour when
   a line is nearly gone. */
.dash-util-row {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 8px 14px;
    border-top: 1px solid var(--vantage-line-2);
}
.dash-util-id { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 8px; }
.dash-util-ref { font-size: 12.5px; white-space: nowrap; }
.dash-util-funder {
    font-size: 12px;
    color: var(--vantage-text-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dash-util-left {
    font-size: 12.5px;
    color: var(--vantage-text-2);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.dash-util-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-util-pct.dash-util-warn { color: var(--lms-warning-ink); }
.dash-util-pct.dash-util-bad  { color: var(--lms-danger-ink); }

/* Utilisation and maturity read against a limit, so they stay as bars, but as
   a rank of thin ticks rather than a solid block. A solid bar of saturated red
   at 98% is the loudest thing on the page by area, and these are context, not
   the headline; the worklist above is. Track and fill share one 5px rhythm
   measured from the same left edge, so the ticks line up across the join and
   the bar reads as one scale that happens to be lit part of the way. */
.dash-bar-row { padding: 6px 14px; border-top: 1px solid var(--vantage-line-2); }
.dash-bar-top { display: flex; justify-content: space-between; gap: 12px; font-size: 12px; margin-bottom: 6px; }
.dash-bar-top span:last-child { color: var(--vantage-text-3); font-variant-numeric: tabular-nums; text-align: right; }
.dash-bar-track {
    position: relative;
    /* Tall enough for the ticks to read as a rank rather than a dotted line,
       short enough that nine of them do not push the page into scrolling. */
    height: 10px;
    overflow: hidden;
    /* The unfilled remainder is a rule, not more ticks. Ticking both halves in
       tones a step apart made a 100% row and a 58% row look alike from a
       normal reading distance: the eye had to hunt for where one pattern
       stopped and the other began. A run of ticks against a plain line has an
       end you can see without looking for it. */
    background: linear-gradient( to bottom,
        transparent 0 4px, var(--vantage-line-2) 4px 6px, transparent 6px 10px );
}
.dash-bar-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    /* currentColor so the three states differ by one property. */
    color: var(--vantage-text-2);
    background: repeating-linear-gradient( to right,
        currentColor 0 2px, transparent 2px 5px );
}
/* Softened: the semantic inks at full strength were built for text and a 3px
   severity bar, not for a band this wide. */
.dash-bar-fill.dash-bar-warn { color: color-mix( in srgb, var(--lms-warning-text) 72%, transparent ); }
.dash-bar-fill.dash-bar-bad  { color: color-mix( in srgb, var(--lms-danger-text) 72%, transparent ); }

/* A clean book is the state this card spends most of its life in, so it
   confirms the checks ran rather than leaving a blank box that reads as a
   failure to load. */
.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. */
.dash-bar-empty { padding-bottom: 10px; }
.dash-bar-empty .dash-bar-top { margin-bottom: 0; }

/* 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. */
.dash-card-none {
    padding: 18px 14px 20px;
    border-top: 1px solid var(--vantage-line-2);
    font-size: 12.5px;
    color: var(--vantage-text-3);
}

/* ─── 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="light"] .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. */
.dash-kpis {
    display: grid;
    grid-template-columns: repeat( 4, 1fr );
    gap: 14px;
    margin-bottom: 14px;
}
.dash-kpi {
    padding: 13px 15px 12px;
    border: 1px solid var(--vantage-line);
    border-radius: var(--vantage-r-lg);
    transition: border-color 0.12s ease, background-color 0.12s ease;
}
.dash-kpi.dash-nav { cursor: pointer; }
.dash-kpi.dash-nav:hover { border-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-bar-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;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    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. */
.st-root {
    height: 100%;
    box-sizing: border-box;
    overflow-y: auto;
    padding: 28px 32px;
    background: var(--vantage-bg);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    font-size: 13px;
}
.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;
}

.st-themes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.st-theme {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px;
    border: 1px solid var(--vantage-line-2);
    border-radius: 12px;
    background: var(--vantage-fill);
    color: var(--vantage-text);
    font-family: var(--vantage-font-body);
    text-align: left;
    cursor: pointer;
    transition: border-color 0.12s ease, background-color 0.12s ease;
}
.st-theme:hover { background: var(--vantage-fill-2); }
.st-theme.st-theme-active {
    border-color: var(--vantage-accent);
    background: color-mix(in srgb, var(--vantage-accent) 12%, transparent);
}
.st-theme-swatch {
    position: relative;
    display: block;
    height: 52px;
    margin-bottom: 8px;
    border: 1px solid var(--vantage-line-2);
    border-radius: 8px;
    overflow: hidden;
}
.st-theme-swatch-bar { position: absolute; inset: 0 0 auto 0; height: 11px; }
.st-theme-swatch-side { position: absolute; inset: 11px auto 0 0; width: 34%; }
.st-swatch-graphite { background: #1b1b1b; }
.st-swatch-graphite .st-theme-swatch-bar  { background: #161616; }
.st-swatch-graphite .st-theme-swatch-side { background: #212121; }
.st-swatch-vantage  { background: #0a1114; }
.st-swatch-vantage .st-theme-swatch-bar   { background: #070d10; }
.st-swatch-vantage .st-theme-swatch-side  { background: #10181c; }
.st-swatch-oled     { background: #000000; }
.st-swatch-oled .st-theme-swatch-bar      { background: #000000; }
.st-swatch-oled .st-theme-swatch-side     { background: #0b0b0b; }
.st-swatch-light    { background: #fafafa; }
.st-swatch-light .st-theme-swatch-bar     { background: #f0f0f0; }
.st-swatch-light .st-theme-swatch-side    { background: #ffffff; }
.st-theme-name { font-size: 13px; font-weight: 500; }
.st-theme-hint { font-size: 11.5px; color: var(--vantage-text); }

/* 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;
}

.st-row { 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 {
    border-color: color-mix(in srgb, var(--lms-danger-text, #f87171) 30%, transparent);
    background: color-mix(in srgb, var(--lms-danger-text, #f87171) 9%, transparent);
    color: var(--lms-danger-text, #f87171);
}
.st-btn-danger:hover {
    background: color-mix(in srgb, var(--lms-danger-text, #f87171) 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); }

/* QR codes render dark-on-white; keep them on a white chip so they
   stay scannable in dark mode. */
.st-qr-frame {
    display: inline-block;
    padding: 10px;
    margin-bottom: 12px;
    background: #ffffff;
    border: 1px solid var(--vantage-line);
    border-radius: 10px;
    line-height: 0;
}

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