/* /Components/Layout/AuthLayout.razor.rz.scp.css */
.auth-page[b-s0g87za91x] {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-body);
    padding: 1rem;
}

.auth-card[b-s0g87za91x] {
    width: 100%;
    max-width: 380px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius);
    box-shadow: var(--shadow-md);
    padding: 2rem;
}

.auth-brand[b-s0g87za91x] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    font-size: 1.7rem;
    font-weight: 700;
    color: var(--accent);
    text-align: center;
    margin-bottom: 1.25rem;
    letter-spacing: -0.5px;
}

.auth-logo[b-s0g87za91x] {
    width: 40px;
    height: 40px;
    border-radius: 8px;
    box-shadow: var(--shadow-md);
}
/* /Components/Layout/DevUserSwitcher.razor.rz.scp.css */
/* Sits at the foot of the user menu's dropdown. */
.dev-switch[b-a7uxm970lq] {
    padding: 0.35rem 0.6rem 0.5rem;
}

.dev-switch-label[b-a7uxm970lq] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    margin-bottom: 0.35rem;
}

.dev-switch-label .badge[b-a7uxm970lq] {
    font-size: 0.6rem;
}

.dev-switch[b-a7uxm970lq]  .form-select,
.dev-switch .form-select[b-a7uxm970lq] {
    width: 100%;
    font-size: 0.82rem;
}
/* /Components/Layout/MainLayout.razor.rz.scp.css */
.page[b-zv0afgso55] {
    position: relative;
    display: flex;
    flex-direction: column;
}

main[b-zv0afgso55] {
    flex: 1;
    /* Without this a wide grid (e.g. the projection overview) stretches the flex item and the
       whole page scrolls sideways; min-width:0 lets it shrink so the grid scrolls inside its own
       overflow container instead. */
    min-width: 0;
}

/* No border, no shadow, and the same colour as the canvas: the menu shares the page's paper
   rather than sitting on a slab of its own. Whitespace is what separates them. */
.sidebar[b-zv0afgso55] {
    background-color: var(--bg-sidebar);
    border-right: none;
    box-shadow: none;
    position: relative;
}

/* Utility chrome, not a header band — it sits on the canvas with no fill and no rule. */
.top-row[b-zv0afgso55] {
    background-color: transparent;
    border-bottom: none;
    justify-content: flex-end;
    height: 3.5rem;
    display: flex;
    align-items: center;
}

    /* Utility links, not calls to action. */
    .top-row[b-zv0afgso55]  a, .top-row[b-zv0afgso55]  .btn-link {
        white-space: nowrap;
        text-decoration: none;
    }

    .top-row[b-zv0afgso55]  a:hover, .top-row[b-zv0afgso55]  .btn-link:hover {
        text-decoration: none;
    }

    .top-row[b-zv0afgso55]  a:first-child {
        overflow: hidden;
        text-overflow: ellipsis;
    }

@media (max-width: 640.98px) {
    .top-row[b-zv0afgso55] {
        justify-content: space-between;
    }
}

@media (min-width: 641px) {
    .page[b-zv0afgso55] {
        flex-direction: row;
    }

    .sidebar[b-zv0afgso55] {
        width: 250px;
        height: 100vh;
        position: sticky;
        top: 0;
    }

    .top-row[b-zv0afgso55] {
        position: sticky;
        top: 0;
        /* Sticky makes this a stacking context, so the user menu's own z-index counts only
           inside it — this value is what the whole header, dropdown included, is worth
           against page content. It has to clear anything a page positions. */
        z-index: 1030;
        /* The row carries no fill, so page content would scroll visibly under it. Frost it
           rather than filling it: the canvas still shows through, the text underneath does not. */
        backdrop-filter: blur(8px);
        background-color: color-mix(in srgb, var(--bg-body) 82%, transparent);
    }

    .top-row.auth[b-zv0afgso55]  a:first-child {
        flex: 1;
        text-align: right;
        width: 0;
    }

    .top-row[b-zv0afgso55], article[b-zv0afgso55] {
        padding-left: 2rem !important;
        padding-right: 1.5rem !important;
    }
}

/* ═══════════════════════════════════════════════════════════
   Horizontal menu mode (data-nav="horizontal" on <html>)

   The sidebar becomes a full-width bar above the content. Only above 992px —
   below that there is not enough width for the items, so it falls back to the
   sidebar and the toggle that sets this mode is hidden.
   ═══════════════════════════════════════════════════════════ */
@media (min-width: 992px) {
    [data-nav="horizontal"] .page[b-zv0afgso55] {
        flex-direction: column;
    }

    /* Height is auto so an open submenu panel grows the bar and pushes the page down, rather
       than covering the top of the content. */
    [data-nav="horizontal"] .sidebar[b-zv0afgso55] {
        width: 100% !important;
        height: auto;
        min-height: 3.5rem;
        position: sticky;
        top: 0;
        z-index: 1031;
        display: flex;
        align-items: flex-start;
        /* Opaque, and exactly the page's own colour, so content scrolls cleanly under it. The
           bar looked white against the dashboard because the warm wash was painting *below* it
           and stopped at its edge; the wash is lifted over the bar instead (Home.razor.css), so
           the glow runs across the chrome and the page as one surface. */
        background-color: var(--bg-body);
    }

    /* Collapsing means nothing on a bar. */
    [data-nav="horizontal"] .sidebar-toggle-btn[b-zv0afgso55] {
        display: none;
    }

    /* The utility row sits on the menu bar, so the chrome stays one row tall instead of two. It
       is pinned to the top-right rather than offset by a fixed amount, because the bar's height
       now varies with whether a submenu panel is open. The row is click-through except for its
       own controls, so it never swallows a click meant for the menu beneath it. */
    [data-nav="horizontal"] main > .top-row[b-zv0afgso55] {
        position: fixed;
        top: 0;
        right: 0;
        height: 3.5rem;
        width: auto;
        z-index: 1032;
        pointer-events: none;
        backdrop-filter: none;
        background-color: transparent;
    }

    /* ::deep, not a plain child selector: the user menu is its own component and carries its own
       scope id, so a scoped `> *` rule would skip it and leave it click-through — the two buttons
       here would work and the user chip would not. */
    [data-nav="horizontal"] main > .top-row[b-zv0afgso55]  > * {
        pointer-events: auto;
    }
}

/* ── Collapse control ──
   A ring on the sidebar's edge near the bottom, out of the way of the menu itself. The chevron
   points at what the click does: inwards to collapse, outwards once collapsed. */
.sidebar-toggle-btn[b-zv0afgso55] {
    position: absolute;
    bottom: 72px;
    right: -12px;
    width: 24px;
    height: 24px;
    padding: 0;
    border-radius: 50%;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-sm);
    display: none;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--text-secondary);
    transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
    z-index: 10;
}

.sidebar-toggle-btn:hover[b-zv0afgso55] {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-light);
}

.sidebar-toggle-btn svg[b-zv0afgso55] {
    width: 14px;
    height: 14px;
    transition: transform 0.15s ease;
}

/* Plain selector, not :global() — that is CSS Modules syntax, which Blazor passes through
   untouched and the browser then drops. Scoped CSS puts its marker on the last element, and the
   svg is ours, so an ancestor selector on <html> works as written. */
html.nav-collapsed .sidebar-toggle-btn svg[b-zv0afgso55] {
    transform: rotate(180deg);
}

/* Only where there is a sidebar to collapse. */
@media (min-width: 641px) {
    .sidebar-toggle-btn[b-zv0afgso55] {
        display: flex;
    }
}

#blazor-error-ui[b-zv0afgso55] {
    background: var(--bg-card);
    color: var(--danger);
    border-top: 3px solid var(--danger);
    border-radius: 12px 12px 0 0;
    bottom: 0;
    box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.1);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss[b-zv0afgso55] {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
        color: var(--text-secondary);
    }
/* /Components/Layout/NavMenu.razor.rz.scp.css */
/* Harvested from Trophyst's NavMenu, adapted to Promora's menu, which differs in two ways: the
   groups are CSS-only (a hidden checkbox per group drives its submenu, because the menu renders
   as static SSR) and there is a third level — Master Data → Customers / Products / Misc. */

.navbar-toggler[b-hq257zinvk] {
    appearance: none;
    cursor: pointer;
    width: 3.5rem;
    height: 2.5rem;
    color: var(--text-primary);
    position: absolute;
    top: 0.5rem;
    right: 1rem;
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
    background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%286, 102, 241, 1%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem var(--bg-card);
}

.navbar-toggler:checked[b-hq257zinvk] {
    background-color: var(--accent-light);
}

.top-row[b-hq257zinvk] {
    min-height: 3.5rem;
    height: 3.5rem;
    background-color: var(--bg-sidebar);
    border-bottom: none;
}

/* Wordmark: display face, uppercase and letter-spaced so it reads as a logotype rather than as
   a page heading. */
.navbar-brand[b-hq257zinvk] {
    font-family: var(--font-display);
    font-size: 1.02rem;
    color: var(--text-strong) !important;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.07em;
}

/* The mark carries its own colour and has a transparent centre, so it stands on the canvas rather
   than inside the filled square the letter P used to need — on that square it would have been
   blue on blue with the accent showing through its middle. */
.brand-mark[b-hq257zinvk] {
    width: 30px;
    height: 30px;
    flex-shrink: 0;
    object-fit: contain;
}

.nav-item[b-hq257zinvk] {
    font-size: 0.9rem;
    padding-bottom: 0.25rem;
}

    .nav-item:first-of-type[b-hq257zinvk] {
        padding-top: 1rem;
    }

/* Inline SVG icons (declared in NavMenu markup, so scoped without ::deep). */
.nav-icon[b-hq257zinvk] {
    width: 18px;
    height: 18px;
    margin-right: 14px;
    flex-shrink: 0;
}

/* Top-level icons sit in a hairline rounded square. A small detail, but a large part of why the
   reference design reads as considered rather than as a default icon-plus-label list. Deeper
   levels stay bare, so the hierarchy is still obvious at a glance. */
nav > .nav-item[b-hq257zinvk] >  .nav-link > .nav-icon,
nav > .nav-group > .nav-item > .nav-link > .nav-icon[b-hq257zinvk] {
    width: 30px;
    height: 30px;
    padding: 5px;
    margin-right: 12px;
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
    background: var(--bg-card);
    box-sizing: border-box;
    transition: border-color 0.18s ease, background 0.18s ease, color 0.18s ease;
}

/* NavLink renders its own <a> (needs ::deep); our group-toggle <label> is in-scope. */
.nav-item[b-hq257zinvk]  .nav-link,
.nav-item .nav-link[b-hq257zinvk] {
    color: var(--text-secondary);
    background: none;
    border: none;
    border-radius: 10px;
    height: 2.75rem;
    display: flex;
    align-items: center;
    width: 100%;
    padding: 0 12px;
    text-align: left;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
}

/* Active item: the accent carries it as colour and weight, not as a filled block. The icon's
   square inverts to solid accent so the eye finds it fast. */
.nav-item[b-hq257zinvk]  a.active {
    background: transparent;
    color: var(--accent);
    font-weight: 600;
}

nav > .nav-item[b-hq257zinvk] >  a.active > .nav-icon {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--text-on-accent);
}

.nav-item[b-hq257zinvk]  .nav-link:hover,
.nav-item .nav-link:hover[b-hq257zinvk] {
    background-color: var(--nav-hover-bg);
    color: var(--text-primary);
}

nav > .nav-item[b-hq257zinvk] >  .nav-link:hover > .nav-icon,
nav > .nav-group > .nav-item > .nav-link:hover > .nav-icon[b-hq257zinvk] {
    border-color: color-mix(in srgb, var(--accent) 45%, var(--border-color));
}

.nav-group-toggle[b-hq257zinvk] {
    user-select: none;
}

.nav-caret[b-hq257zinvk] {
    width: 0.85rem;
    height: 0.85rem;
    margin-left: auto;
    margin-right: 0;
    transition: transform 0.2s ease;
}

/* CSS-only collapse: a hidden checkbox toggled by the label drives the submenu and the caret. */
.nav-group-checkbox[b-hq257zinvk] {
    display: none;
}

.nav-submenu[b-hq257zinvk] {
    display: none;
}

.nav-group-checkbox:checked ~ .nav-submenu[b-hq257zinvk] {
    display: block;
}

.nav-group-checkbox:checked ~ .nav-item .nav-caret[b-hq257zinvk] {
    transform: rotate(180deg);
}

/* ── Second level ── */
.nav-submenu[b-hq257zinvk] {
    background-color: var(--bg-subtle);
    border-radius: var(--border-radius-sm);
    margin: 0 0.75rem 0.5rem 0.75rem;
    padding: 0.25rem 0;
}

.nav-submenu .nav-item[b-hq257zinvk] {
    padding-bottom: 0.125rem;
}

    .nav-submenu .nav-item:first-of-type[b-hq257zinvk] {
        padding-top: 0.25rem;
    }

.nav-submenu[b-hq257zinvk]  .nav-link,
.nav-submenu .nav-link[b-hq257zinvk] {
    height: 2.4rem;
    padding-left: 1.25rem;
    font-size: 0.85rem;
}

.nav-submenu .nav-icon[b-hq257zinvk] {
    width: 16px;
    height: 16px;
    margin-right: 12px;
}

/* ── Third level: sub-groups (Master Data → Customers / Products / Misc) ── */
.nav-subsubmenu[b-hq257zinvk] {
    background: none;
    margin: 0;
    padding: 0;
}

.nav-subsubmenu[b-hq257zinvk]  .nav-link {
    padding-left: 2.4rem;
    height: 2.2rem;
    font-size: 0.82rem;
}

.nav-scrollable[b-hq257zinvk] {
    display: none;
    background-color: var(--bg-sidebar);
    position: relative;
}

.navbar-toggler:checked ~ .nav-scrollable[b-hq257zinvk] {
    display: block;
}

@media (min-width: 641px) {
    .navbar-toggler[b-hq257zinvk] {
        display: none;
    }

    .nav-scrollable[b-hq257zinvk] {
        /* Flex column so the version footer pins to the bottom: the nav scrolls, the footer stays. */
        display: flex;
        flex-direction: column;
        height: calc(100vh - 3.5rem);
    }

    .nav-scrollable > nav[b-hq257zinvk] {
        flex: 1;
        overflow-y: auto;
        /* Bootstrap's .nav is flex-wrap: wrap — with the constrained height that wraps
           overflowing items into a second column beside the menu. Scroll instead. */
        flex-wrap: nowrap;
    }
}

.version-footer[b-hq257zinvk] {
    padding-top: 0.75rem;
    padding-bottom: 0.75rem;
    border-top: 1px solid var(--border-color);
    background-color: var(--bg-sidebar);
    flex-shrink: 0;
}

.version-link[b-hq257zinvk] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--text-muted);
    font-size: 0.8rem;
    text-decoration: none;
    transition: color 0.2s ease;
}

.version-link:hover[b-hq257zinvk] {
    color: var(--accent);
}

.version-link .nav-icon[b-hq257zinvk] {
    width: 14px;
    height: 14px;
    margin-right: 0;
}

/* ═══════════════════════════════════════════════════════════
   Horizontal menu mode (data-nav="horizontal" on <html>)

   Same markup, laid out as a top bar. Submenus become a full-width panel under
   the bar rather than a dropdown: the groups here are large — Master Data alone
   has three sections — and a panel lets them keep their sections and read in
   columns. Only above 992px; below that the items do not fit and the mode falls
   back to the sidebar.
   ═══════════════════════════════════════════════════════════ */
@media (min-width: 992px) {
    /* Brand sits at the left of the bar. */
    [data-nav="horizontal"] .top-row[b-hq257zinvk] {
        height: auto;
        min-height: 0;
        border-bottom: none;
        padding-right: 0.5rem;
        flex-shrink: 0;
        width: auto;
    }

    [data-nav="horizontal"] .top-row .container-fluid[b-hq257zinvk] {
        width: auto;
        padding-right: 0;
    }

    [data-nav="horizontal"] .nav-scrollable[b-hq257zinvk] {
        display: flex !important;
        flex-direction: row;
        align-items: flex-start;
        height: auto;
        min-height: 3.5rem;
        flex: 1;
        min-width: 0;
        position: static;
        /* Keep clear of the fixed top-right controls, which are out of flow and would otherwise
           be overlapped by the items as the window narrows. The width is measured and published
           by js/app.js; the fallback covers the moment before that runs. */
        padding-right: calc(var(--nav-utility-width, 20rem) + 1rem);
    }

    /* The markup carries Bootstrap's .flex-column, which only sets flex-direction — the element
       is display:block and relies on the sidebar being a column. Making it an actual flex row is
       what turns the list into a bar. Overflow stays visible so a panel can escape. */
    [data-nav="horizontal"] .nav-scrollable > nav[b-hq257zinvk] {
        display: flex;
        flex-direction: row !important;
        align-items: center;
        align-content: flex-start;
        flex-wrap: wrap;
        overflow: visible;
        min-width: 0;
    }

    /* A group is a wrapper div around its toggle and its panel. The wrapper has to sit in the bar
       as an ordinary item while its panel takes a full-width line of its own — so the wrapper is
       display:contents and its two children are laid out by the bar directly. */
    [data-nav="horizontal"] .nav-scrollable > nav > .nav-group[b-hq257zinvk] {
        display: contents;
    }

    [data-nav="horizontal"] .nav-scrollable > nav > .nav-item[b-hq257zinvk],
    [data-nav="horizontal"] .nav-scrollable > nav > .nav-group > .nav-item[b-hq257zinvk] {
        order: 0;
        height: 3.5rem;
        display: flex;
        align-items: center;
        padding: 0 1px !important;
    }

    [data-nav="horizontal"] .nav-item[b-hq257zinvk]  .nav-link,
    [data-nav="horizontal"] .nav-item .nav-link[b-hq257zinvk] {
        height: 2.4rem;
        line-height: 1;
        padding: 0 0.7rem;
        white-space: nowrap;
        border-radius: var(--border-radius-sm);
    }

    /* The boxed icons are a sidebar detail — at bar scale they crowd the row, so icons go back
       to bare glyphs here. */
    [data-nav="horizontal"] nav > .nav-item[b-hq257zinvk] >  .nav-link > .nav-icon,
    [data-nav="horizontal"] nav > .nav-group > .nav-item > .nav-link > .nav-icon[b-hq257zinvk] {
        width: 17px;
        height: 17px;
        padding: 0;
        margin-right: 8px;
        border: none;
        background: none;
        border-radius: 0;
    }

    [data-nav="horizontal"] nav > .nav-item[b-hq257zinvk] >  a.active > .nav-icon {
        background: none;
        color: var(--accent);
    }

    /* Active item is marked by an underline on the bar. */
    [data-nav="horizontal"] .nav-item[b-hq257zinvk]  a.active {
        position: relative;
    }

    [data-nav="horizontal"] .nav-item[b-hq257zinvk]  a.active::after {
        content: '';
        position: absolute;
        left: 0.7rem;
        right: 0.7rem;
        bottom: -0.55rem;
        height: 2px;
        border-radius: 2px;
        background: var(--accent);
    }

    [data-nav="horizontal"] .nav-caret[b-hq257zinvk] {
        margin-left: 4px;
    }

    /* Submenu → panel on its own line below the items. In flow, not absolute, so it pushes the
       page down instead of covering the top of it. */
    [data-nav="horizontal"] .nav-group > .nav-group-checkbox:checked ~ .nav-submenu[b-hq257zinvk] {
        order: 99;
        flex: 0 0 100%;
        margin: 0 0 0.65rem;
        padding: 1rem 1.25rem 1.1rem;
        display: grid;
        /* Fixed-width columns packed to the left rather than stretched across the viewport — on a
           wide screen a stretched grid puts 170px of empty space between an icon and its
           neighbour and is hard to scan. */
        grid-template-columns: repeat(auto-fill, 220px);
        justify-content: start;
        gap: 0 0.75rem;
        align-content: start;
        background: var(--bg-card);
        border: 1px solid var(--border-color);
        border-radius: var(--border-radius);
        box-shadow: var(--shadow-sm);
    }

    [data-nav="horizontal"] .nav-submenu[b-hq257zinvk]  .nav-link {
        padding-left: 0.6rem;
        height: 2.2rem;
    }

    /* A sub-group inside a panel becomes a section heading spanning the whole grid, with its
       items always visible underneath — collapsing a third level inside an already-open panel is
       one click too many, and the sections are what make a wide panel readable. */
    [data-nav="horizontal"] .nav-submenu .nav-subgroup[b-hq257zinvk] {
        display: contents;
    }

    [data-nav="horizontal"] .nav-submenu .nav-subgroup > .nav-item[b-hq257zinvk] {
        grid-column: 1 / -1;
        padding: 0 !important;
        margin-top: 0.5rem;
        border-top: 1px solid var(--border-subtle);
    }

    [data-nav="horizontal"] .nav-submenu .nav-subgroup:first-child > .nav-item[b-hq257zinvk] {
        margin-top: 0;
        border-top: none;
    }

    [data-nav="horizontal"] .nav-submenu .nav-subgroup-toggle[b-hq257zinvk] {
        font-size: 0.7rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: var(--text-muted);
        height: auto;
        padding: 0.7rem 0.6rem 0.3rem;
        pointer-events: none;
    }

    [data-nav="horizontal"] .nav-submenu .nav-subgroup-toggle .nav-icon[b-hq257zinvk],
    [data-nav="horizontal"] .nav-submenu .nav-subgroup-toggle .nav-caret[b-hq257zinvk] {
        display: none;
    }

    /* Third-level items are laid out by the panel's own grid, so the sub-menu wrapper steps out
       of the way and its items are always shown. The panel rule above is scoped to .nav-group's
       own child, so it never catches this one. */
    [data-nav="horizontal"] .nav-subsubmenu[b-hq257zinvk] {
        display: contents;
    }

    /* The sidebar footer has no place on a bar; the version link is reachable from /changelog. */
    [data-nav="horizontal"] .version-footer[b-hq257zinvk] {
        display: none;
    }
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-kcsie6nky2],
.components-reconnect-repeated-attempt-visible[b-kcsie6nky2],
.components-reconnect-failed-visible[b-kcsie6nky2],
.components-pause-visible[b-kcsie6nky2],
.components-resume-failed-visible[b-kcsie6nky2],
.components-rejoining-animation[b-kcsie6nky2] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-kcsie6nky2],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-kcsie6nky2],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-kcsie6nky2],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-kcsie6nky2],
#components-reconnect-modal.components-reconnect-retrying[b-kcsie6nky2],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-kcsie6nky2],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-kcsie6nky2],
#components-reconnect-modal.components-reconnect-failed[b-kcsie6nky2],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-kcsie6nky2] {
    display: block;
}


#components-reconnect-modal[b-kcsie6nky2] {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-kcsie6nky2 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-kcsie6nky2 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-kcsie6nky2 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-kcsie6nky2]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-kcsie6nky2 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-kcsie6nky2 {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-kcsie6nky2 {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-kcsie6nky2 {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-kcsie6nky2] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-kcsie6nky2] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-kcsie6nky2] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-kcsie6nky2] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-kcsie6nky2] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-kcsie6nky2] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-kcsie6nky2] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-kcsie6nky2 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-kcsie6nky2] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-kcsie6nky2 {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Layout/SignLayout.razor.rz.scp.css */
.sign-page[b-3a0ct16ol2] {
    min-height: 100vh;
    background: var(--bg-body, #f5f7fa);
    padding: 32px 16px;
    display: flex;
    justify-content: center;
    align-items: flex-start;
}

.sign-card[b-3a0ct16ol2] {
    width: 100%;
    max-width: 960px;
    background: var(--bg-card, #fff);
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 14px;
    padding: 28px 32px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .06);
}

.sign-brand[b-3a0ct16ol2] {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--accent, #2563eb);
    margin-bottom: 20px;
    padding-bottom: 14px;
    border-bottom: 2px solid var(--accent, #2563eb);
}

.sign-logo[b-3a0ct16ol2] {
    width: 28px;
    height: 28px;
}
/* /Components/Layout/UserMenu.razor.rz.scp.css */
.user-menu[b-lzro0634gc] {
    position: relative;
    margin-left: 1rem;
}

.user-chip[b-lzro0634gc] {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    background: none;
    border: 1px solid transparent;
    border-radius: 999px;
    padding: 0.3rem 0.8rem;
    color: var(--text-secondary);
    font-size: 0.9rem;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
}

.user-chip:hover[b-lzro0634gc] {
    background-color: var(--nav-hover-bg);
    border-color: var(--border-color);
}

.chip-icon[b-lzro0634gc] {
    width: 1.1rem;
    height: 1.1rem;
    flex-shrink: 0;
}

.chip-caret[b-lzro0634gc] {
    width: 0.75rem;
    height: 0.75rem;
    flex-shrink: 0;
}

.chip-name[b-lzro0634gc] {
    max-width: 14rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Invisible click-away layer under the dropdown */
.user-menu-backdrop[b-lzro0634gc] {
    position: fixed;
    inset: 0;
    z-index: 1040;
}

.user-menu-dropdown[b-lzro0634gc] {
    position: absolute;
    right: 0;
    top: calc(100% + 0.35rem);
    z-index: 1041;
    min-width: 15rem;
    background: var(--bg-elevated);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    box-shadow: var(--shadow-md);
    padding: 0.4rem;
}

.dropdown-user[b-lzro0634gc] {
    padding: 0.4rem 0.6rem;
}

.dropdown-entry[b-lzro0634gc] {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    width: 100%;
    background: none;
    border: none;
    border-radius: 6px;
    padding: 0.45rem 0.6rem;
    font-size: 0.88rem;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    text-align: left;
}

.dropdown-entry:hover[b-lzro0634gc] {
    background-color: var(--nav-hover-bg);
}

.entry-icon[b-lzro0634gc] {
    width: 1rem;
    height: 1rem;
    flex-shrink: 0;
}

/* ── Security tab ── */
.qr-box[b-lzro0634gc] {
    width: 180px;
    height: 180px;
    padding: 6px;
    /* Stays white in both themes on purpose: a QR reader needs dark-on-light to scan. */
    background: #fff;
    border: 1px solid var(--border-color);
    border-radius: 8px;
}

.recovery-codes[b-lzro0634gc] {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.25rem 1rem;
}

.recovery-codes code[b-lzro0634gc] {
    font-size: 0.85rem;
}
/* /Components/Pages/Agreements/Details.razor.rz.scp.css */
/* Agreement line grid — same readable sizing and two-line header style as the projection grid. */
.agreement-grid[b-dxsoruelzw] {
    font-size: 0.9rem;
}

.agreement-grid th[b-dxsoruelzw] {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    font-weight: 600;
    color: var(--text-secondary, #4b5563);
    white-space: normal;      /* multi-line headers */
    line-height: 1.15;
    vertical-align: bottom;
}

/* No spinner buttons — arrow keys navigate the grid, typing edits the value */
.agreement-grid input[type="number"][b-dxsoruelzw]::-webkit-outer-spin-button,
.agreement-grid input[type="number"][b-dxsoruelzw]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.agreement-grid input[type="number"][b-dxsoruelzw] {
    -moz-appearance: textfield;
    appearance: textfield;
}

/* The "why is this zero" mark in the support cell. Absolutely placed so it cannot be pushed onto
   a line of its own beneath the full-width number input in edit mode, which is how it came to sit
   under the box looking like a stray character. */
.soa-cell[b-dxsoruelzw] { position: relative; }

.soa-cell .soa-why[b-dxsoruelzw] {
    position: absolute;
    left: .3rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: .6875rem;
    line-height: 1;
    color: var(--bs-secondary-color, #6c757d);
    cursor: help;
}

/* Its own gutter inside the cell, so the mark never sits on the input's left edge where it would
   swallow clicks meant for the box. The figure is right-aligned, so the space costs nothing. */
.soa-cell .form-control[b-dxsoruelzw] { padding-left: 1.15rem; }

/* A line that does not land on the margin it was priced against. */
.margin-drift[b-dxsoruelzw] {
    margin-left: .2rem;
    font-size: .625rem;
    color: var(--bs-secondary-color, #6c757d);
    cursor: help;
}

/* ── Partial claims panel ───────────────────────────────────────────────────── */

/* The claim position: one row of figures that stays readable when it has to wrap. */
.claim-pos[b-dxsoruelzw] {
    display: flex;
    flex-wrap: wrap;
    gap: 1.75rem;
    padding: .6rem .85rem;
    border-radius: var(--border-radius);
    background: color-mix(in srgb, var(--bs-primary) 5%, var(--bg-subtle));
    border: 1px solid var(--border-color);
}

.claim-pos strong[b-dxsoruelzw] { font-size: 1.05rem; }

/* Rejected and cancelled claims stay on the list — the history is the point — but they are
   no longer part of the arithmetic, so they read as set aside rather than as current. */
.claim-void > td[b-dxsoruelzw] { opacity: .55; }
.claim-void > td:nth-child(2)[b-dxsoruelzw] { text-decoration: line-through; }

/* Inline reject/payment rows: an indent and a tint are enough to tie them to the claim above
   without a nested table. */
.claim-sub > td[b-dxsoruelzw] {
    background: var(--bg-subtle);
    border-top: 0;
}

.claim-pay[b-dxsoruelzw] {
    display: inline-block;
    margin-right: .75rem;
    white-space: nowrap;
}
/* /Components/Pages/Agreements/Index.razor.rz.scp.css */
/* The three rankable columns. Only these carry the affordance — the rest of the header is what you
   filter by, above the table, not what you sort by. */
.agr-sortable[b-oy7j7fupiq] {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.agr-sortable:hover[b-oy7j7fupiq] {
    color: var(--accent, #2563eb);
}
/* /Components/Pages/Agreements/Reporting.razor.rz.scp.css */
/* ── KPI cards: Insight360/mock style — white card, tinted icon chip, big value ── */

.soa-kpis[b-785yz4miuj] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 12px;
}

.soa-kpi[b-785yz4miuj] {
    background: var(--bg-card, #fff);
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 14px;
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}

.soa-kpi-top[b-785yz4miuj] {
    display: flex;
    align-items: center;
    gap: 10px;
}

.soa-kpi-icon[b-785yz4miuj] {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--kpi-color, #888) 14%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.soa-kpi-icon svg[b-785yz4miuj] {
    width: 20px;
    height: 20px;
    stroke: var(--kpi-color, #888);
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.soa-kpi-label[b-785yz4miuj] {
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--text-muted, #6c757d);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.soa-kpi-value[b-785yz4miuj] {
    font-size: 1.7rem;
    font-weight: 700;
    line-height: 1.1;
}

.soa-kpi-caption[b-785yz4miuj] {
    font-size: 0.74rem;
    color: var(--text-muted, #6c757d);
}

/* ── Investment flow ───────────────────────────────────────────────────────
   The same chevron language as the dashboard pipelines — interlocking stages tinted along a ramp
   so the colour itself says how far through the lifecycle you are looking. It is a separate set of
   rules rather than a reuse of .hd-flow because the two carry different things: that one shows a
   count and a share, this one money, a share of budget, and the gap to budget underneath. */
.ivf-head[b-785yz4miuj] {
    padding: 16px 18px 12px;
}

.ivf-title[b-785yz4miuj] {
    font-family: var(--font-display);
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text-strong);
}

.ivf-caption[b-785yz4miuj] {
    font-size: 13px;
    color: var(--text-secondary);
    margin-top: 2px;
}

.ivf-track[b-785yz4miuj] {
    display: flex;
    gap: 3px;
    margin: 0 14px;
    border-radius: 12px;
    /* Squares off the outer ends, which the chevron clip-path cannot round itself. */
    overflow: hidden;
    --flow-start: #e1ebfc;
    --flow-end: #ddf2e6;
    --flow-icon: #8d99a8;
    --notch: 14px;
}

[data-theme="dark"] .ivf-track[b-785yz4miuj] {
    --flow-start: #1e2a3d;
    --flow-end: #1c3029;
    --flow-icon: #7c8896;
}

.ivf-step[b-785yz4miuj] {
    flex: 1 1 0;
    min-width: 0;
    border: 0;
    padding: 16px 22px 14px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    cursor: pointer;
    background: color-mix(in srgb, var(--flow-end) var(--tint, 0%), var(--flow-start));
    /* Notched on the left, pointed on the right: each stage slots into the next. */
    clip-path: polygon(0 0, calc(100% - var(--notch)) 0, 100% 50%, calc(100% - var(--notch)) 100%, 0 100%, var(--notch) 50%);
    transition: transform .15s, filter .15s;
}

/* The two ends face outwards, so the flow reads as one bar with a direction. */
.ivf-first[b-785yz4miuj] { clip-path: polygon(0 0, calc(100% - var(--notch)) 0, 100% 50%, calc(100% - var(--notch)) 100%, 0 100%); }
.ivf-last[b-785yz4miuj]  { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, var(--notch) 50%); }

/* box-shadow would be clipped away with the corners; drop-shadow follows the chevron. */
.ivf-step:hover:not(:disabled)[b-785yz4miuj] {
    transform: translateY(-2px);
    filter: drop-shadow(0 5px 10px rgba(16, 24, 40, 0.16));
}

.ivf-step:focus-visible[b-785yz4miuj] { outline: 2px solid var(--accent); outline-offset: -3px; }
.ivf-step:disabled[b-785yz4miuj] { cursor: default; opacity: .62; }

.ivf-icon[b-785yz4miuj] {
    width: 36px; height: 36px;
    border-radius: 50%;
    background: var(--bg-card);
    color: var(--flow-icon);
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 9px;
    flex-shrink: 0;
}

.ivf-icon svg[b-785yz4miuj] {
    width: 18px; height: 18px;
    stroke: currentColor; fill: none;
    stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

.ivf-label[b-785yz4miuj] {
    font-size: 12px;
    font-weight: 600;
    line-height: 1.15;
    color: var(--text-secondary);
    display: flex;
    flex-direction: column;
    align-items: center;
}

.ivf-sublabel[b-785yz4miuj] {
    font-size: 10px;
    font-weight: 500;
    color: var(--text-muted);
}

.ivf-value[b-785yz4miuj] {
    font-size: 22px;
    font-weight: 700;
    color: var(--text-strong);
    line-height: 1.1;
    margin-top: 7px;
    white-space: nowrap;
}

.ivf-share[b-785yz4miuj] {
    font-size: 12px;
    color: var(--text-secondary);
    margin-top: 3px;
    min-height: 16px;
}

.ivf-delta[b-785yz4miuj] {
    font-size: 11px;
    color: var(--text-muted);
    margin-top: 10px;
    line-height: 1.25;
    min-height: 28px;
    display: flex;
    flex-direction: column;
}

.ivf-delta-note[b-785yz4miuj] { font-size: 10px; }

/* ── Lifecycle rail ── */
.ivf-rail[b-785yz4miuj] {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 18px 16px;
}

.ivf-rail-label[b-785yz4miuj] {
    font-size: 11px;
    color: var(--text-muted);
    white-space: nowrap;
    padding-left: 10px;
    border-left: 2px solid var(--border-color);
}

.ivf-rail-line[b-785yz4miuj] {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 2px;
    background: color-mix(in srgb, var(--accent) 45%, transparent);
    border-radius: 2px;
}

.ivf-rail-dot[b-785yz4miuj] {
    width: 9px; height: 9px;
    border-radius: 50%;
    background: var(--accent);
    flex-shrink: 0;
}

/* A stage with nothing in it is hollow, so the rail shows how far the money actually got. */
.ivf-rail-dot-empty[b-785yz4miuj] {
    background: var(--bg-card);
    box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent);
}

.ivf-note[b-785yz4miuj] {
    font-size: 12px;
    color: var(--text-muted);
    padding: 0 18px 16px;
}

/* Below about 1100px six chevrons cannot hold their figures, so the track scrolls sideways
   rather than crushing them. */
@media (max-width: 1100px) {
    .ivf-track[b-785yz4miuj] { overflow-x: auto; }
    .ivf-step[b-785yz4miuj] { flex: 0 0 178px; }
}

/* ── Investment split ──────────────────────────────────────────────────────
   A ranked bar list rather than a donut: five slices of similar size are hard to order by eye,
   and this is read top to bottom without effort. The bar is scaled against the largest row, not
   the total, so the smallest row is still a visible bar rather than a sliver. */

/* Ranked rows without a logo mark — the claim stages and the investment types are not customers,
   so the row drops the first column and gives the width to the name. Not clickable either: these
   two lists describe money already accounted for, and there is nothing behind a row to open. */
.rr-row[b-785yz4miuj] {
    grid-template-columns: minmax(90px, auto) minmax(40px, 1fr) auto 44px;
    cursor: default;
}

.rr-row:hover[b-785yz4miuj] { background: none; }

.rr-sub[b-785yz4miuj] {
    margin-left: 6px;
    font-weight: 400;
    font-size: 0.74rem;
    color: var(--text-muted);
}
/* /Components/Pages/AgreementSetup/SupportMatrix.razor.rz.scp.css */

/* ── Two questions, one table ────────────────────────────────────────────────
   Which categories offer a type, and which budgets may pay for it. Banded apart
   so the second is not read as more of the first. */
.matrix-band th[b-kzgjg0pl5t] {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    border-bottom: 0;
}

.matrix-budget[b-kzgjg0pl5t] { background: color-mix(in srgb, var(--accent) 6%, transparent); }

.matrix-key[b-kzgjg0pl5t] {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    margin-right: 4px;
}

.matrix-key-coop[b-kzgjg0pl5t] { background: var(--accent); }
.matrix-key-mdf[b-kzgjg0pl5t] { background: #0d9488; }

/* A type nobody can pay for. Stated under the row rather than as a badge on it:
   it is a consequence of the two cells just left of it, and it reads as one. */
.matrix-warn td[b-kzgjg0pl5t] {
    background: color-mix(in srgb, var(--danger, #dc4c3e) 8%, transparent);
    color: var(--danger, #dc4c3e);
    border-top: 0;
}
/* /Components/Pages/Ai/RunEditor.razor.rz.scp.css */
/* Bootstrap's .card sets display:flex, and a <details> told to be a flex container renders its
   contents whether it is open or not — the arrow turns, the panel never closes. The element has to
   stay display:block for the browser's own open/closed behaviour to work, so the card's look is
   taken from it without the layout mode that breaks it. */
details.card[b-5vw1lv1r4l] {
    display: block;
}

details.card > summary[b-5vw1lv1r4l] {
    list-style: none;
}

details.card > summary[b-5vw1lv1r4l]::-webkit-details-marker {
    display: none;
}

/* A caret of our own, since the native marker is suppressed to keep the card header's look. */
details.card > summary[b-5vw1lv1r4l]::after {
    content: "⌄";
    float: right;
    color: var(--text-muted);
    transition: transform .15s;
}

details.card[open] > summary[b-5vw1lv1r4l]::after {
    content: "⌃";
}
/* /Components/Pages/Assortment/AccountAssortment.razor.rz.scp.css */
/* Two panes: the ranged products on the left, the assignment panel pinned on the right. Below
   1200px the panel drops under the table rather than squeezing both. */
.assort-split[b-atjdkywr1c] {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 440px;
    gap: 1rem;
    align-items: start;
}
@media (max-width: 1199.98px) {
    .assort-split[b-atjdkywr1c] { grid-template-columns: minmax(0, 1fr); }
}
.assort-panel[b-atjdkywr1c] { position: sticky; top: 1rem; }

/* Panel hidden: the products take the whole width. */
.assort-split-solo[b-atjdkywr1c] { grid-template-columns: minmax(0, 1fr); }

/* The panel's own close, in its corner, over whichever header it is showing. */
.assort-panel-close[b-atjdkywr1c] {
    position: absolute;
    top: .6rem;
    right: .6rem;
    z-index: 2;
    font-size: .7rem;
}
.assort-table td[b-atjdkywr1c], .assort-table th[b-atjdkywr1c] { vertical-align: middle; }

/* The three assignment modes, as cards rather than bare radios, so the choice reads at a glance. */
.mode-cards[b-atjdkywr1c] { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .5rem; }
.mode-card[b-atjdkywr1c] {
    display: flex; gap: .5rem; align-items: flex-start;
    border: 1px solid var(--bs-border-color); border-radius: .5rem; padding: .5rem .6rem;
    cursor: pointer; line-height: 1.2; font-size: .9rem;
}
.mode-card.is-active[b-atjdkywr1c] { border-color: var(--bs-primary); background: rgba(var(--bs-primary-rgb), .06); }
.mode-card input[b-atjdkywr1c] { margin-top: .15rem; flex: none; }

/* Accounts grouped by country, several columns when the panel allows, scrolling inside the card. */
.acct-groups[b-atjdkywr1c] {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: .75rem;
    max-height: 48vh; overflow: auto; padding-right: .25rem;
}
.acct-group[b-atjdkywr1c] { border: 1px solid var(--bs-border-color); border-radius: .5rem; padding: .4rem .5rem; }
.acct-group-head[b-atjdkywr1c] {
    display: flex; align-items: center; gap: .4rem; cursor: pointer;
    padding-bottom: .3rem; margin-bottom: .3rem; border-bottom: 1px solid var(--bs-border-color);
}
.acct-row[b-atjdkywr1c] { display: flex; align-items: center; gap: .4rem; cursor: pointer; padding: .1rem 0; font-size: .9rem; }
.acct-row input[b-atjdkywr1c], .acct-group-head input[b-atjdkywr1c] { margin: 0; flex: none; }

/* The five figures typed into the grid. Narrow enough that the grid still breathes with the
   account panel open beside it, wide enough for a six-figure year — the side padding is trimmed
   so the narrower box loses none of its room for digits. */
.assort-num[b-atjdkywr1c] { width: 5.25rem; display: inline-block; padding-left: .4rem; padding-right: .4rem; }

/* The two share boxes draw a "%" inside on the right (.matrix-pct); they keep the room for it, or
   the figure runs over it. */
.matrix-pct > .assort-num[b-atjdkywr1c] { padding-right: 1.25rem; }

/* The currency after a price box — small and quiet, so the figure stays what is read first. */
.assort-cur[b-atjdkywr1c] { font-size: .7rem; color: var(--text-muted); margin-left: .2rem; vertical-align: middle; }
.assort-kpi-cur[b-atjdkywr1c] { font-size: .6em; font-weight: 500; color: var(--text-muted); }

/* A column that sorts on click. */
.assort-sortable[b-atjdkywr1c] { cursor: pointer; user-select: none; white-space: nowrap; }
.assort-sortable:hover[b-atjdkywr1c] { text-decoration: underline; }

/* ── Who carries a product ───────────────────────────────────────────────────
   The reporting screens' customer mark, shrunk to table-row height and set in a
   row that overlaps slightly: four of them have to live in the slack between the
   product name and the brand, and a strip of separate circles would have needed
   more width than that slack has. */
.assort-marks[b-atjdkywr1c] {
    display: inline-flex;
    align-items: center;
}

.assort-mark[b-atjdkywr1c] {
    width: 24px;
    height: 24px;
    font-size: 10px;
    border: 2px solid var(--bg-card);
    margin-left: -6px;
}

.assort-marks > .assort-mark:first-child[b-atjdkywr1c] { margin-left: 0; }

/* The overflow count is deliberately not one of the palette colours: it stands
   for several accounts rather than any one of them, and giving it a hue would
   make it read as another face in the row. */
.assort-marks > .isp-mark-others[b-atjdkywr1c] {
    background: var(--bg-subtle);
    color: var(--text-muted);
    font-size: 10px;
    letter-spacing: 0;
}

/* ── Three bands across the row ──────────────────────────────────────────────
   What the product is, what somebody decided it will do, and what that comes
   to. Tinted rather than ruled: eleven columns of numbers need telling apart at
   a glance, and a border between them is a line the eye has to find first.
   Both tints are faint enough to sit under a dark theme's text as well as a
   light one's, which a fixed pastel would not. */
.assort-band th[b-atjdkywr1c] {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 700;
    text-align: center;
    border-bottom: 0;
    padding-top: 6px;
    padding-bottom: 2px;
}

.assort-band-input[b-atjdkywr1c] {
    background: color-mix(in srgb, var(--accent) 7%, transparent);
}

.assort-band-calc[b-atjdkywr1c] {
    background: color-mix(in srgb, #0d9488 7%, transparent);
}

.assort-band .assort-band-input[b-atjdkywr1c] { color: var(--accent); }
.assort-band .assort-band-calc[b-atjdkywr1c] { color: #0d9488; }

[data-theme="dark"] .assort-band .assort-band-calc[b-atjdkywr1c] { color: #4fd1c5; }
[data-theme="dark"] .assort-band-calc[b-atjdkywr1c] { background: color-mix(in srgb, #4fd1c5 8%, transparent); }

/* The calculated band is read, not typed — so it never shows an input frame and
   its figures sit tight to the right where a column of numbers is compared. */
.assort-band-calc[b-atjdkywr1c] { font-variant-numeric: tabular-nums; }

/* ── The year's plan, totalled ───────────────────────────────────────────────
   A strip rather than cards: six figures that are read together as one sentence
   about the year, above a table that is read a row at a time. */
.assort-kpis[b-atjdkywr1c] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 1px;
    background: var(--border-color);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    overflow: hidden;
}

.assort-kpi[b-atjdkywr1c] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 14px;
    background: var(--bg-card);
}

.assort-kpi-label[b-atjdkywr1c] {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
}

.assort-kpi-value[b-atjdkywr1c] {
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
}

.assort-kpi-note[b-atjdkywr1c] {
    font-size: 0.7rem;
    color: var(--text-muted);
}

/* ── The Excel menu ──────────────────────────────────────────────────────────
   The same shape the planning sheets use, so a planner who has met one has met
   both. A backdrop rather than a blur listener: it closes on the next click
   wherever that lands, which is what a menu is expected to do. */
.assort-menu[b-atjdkywr1c] { position: relative; display: inline-block; }

.assort-caret[b-atjdkywr1c] { font-size: .7em; opacity: .7; }

.assort-menu-backdrop[b-atjdkywr1c] {
    position: fixed;
    inset: 0;
    z-index: 1040;
}

.assort-menu-list[b-atjdkywr1c] {
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    z-index: 1050;
    min-width: 230px;
    padding: 4px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-card);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
}

.assort-menu-item[b-atjdkywr1c] {
    display: block;
    width: 100%;
    padding: 6px 10px;
    border: 0;
    border-radius: 6px;
    background: none;
    text-align: left;
    font-size: .85rem;
    cursor: pointer;
    color: var(--text-primary);
}

.assort-menu-item:hover[b-atjdkywr1c] { background: var(--bg-subtle); }
.assort-menu-item:disabled[b-atjdkywr1c] { opacity: .5; cursor: default; }

.assort-menu-note[b-atjdkywr1c] {
    padding: 6px 10px 2px;
    border-top: 1px solid var(--border-subtle);
    margin-top: 4px;
    font-size: .72rem;
    color: var(--text-muted);
}

/* Room for the close button, so a long product name or the Clear link never runs under it. */
.assort-panel > .card-header[b-atjdkywr1c] { padding-right: 2.5rem; }
/* /Components/Pages/Budgets/Details.razor.rz.scp.css */

/* ── The two halves of a budget ──────────────────────────────────────────────
   Tinted apart so a column of COOP figures can be read down without the eye
   first finding which column it is in. Faint enough to sit under both themes'
   text, which a fixed pastel would not be. */
.budget-coop[b-fkyypn4v1b] { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.budget-mdf[b-fkyypn4v1b] { background: color-mix(in srgb, #7c3aed 6%, transparent); }
/* /Components/Pages/Catalogue/CampaignCalendar.razor.rz.scp.css */
/* ── The campaign calendar ───────────────────────────────────────────────────
   A label column and a track. Everything on the track is placed by percentage of the window, so the
   four views differ only in the window and the headings. Dated rather than a grid of cells: a
   campaign that starts on a Wednesday starts three sevenths into its week. */
.ccal[b-zutqrkvupv] { --ccal-label: 230px; font-size: .85rem; }

.ccal-filter[b-zutqrkvupv] { width: 150px; }
.ccal-filter-account[b-zutqrkvupv] { width: 190px; }
.ccal-filter-account[b-zutqrkvupv]  .form-control { padding: .25rem .5rem; font-size: .875rem; min-height: 0; }

.ccal-nav[b-zutqrkvupv] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    margin-left: var(--ccal-label);
    padding-bottom: .25rem;
}
.ccal-nav .btn-link[b-zutqrkvupv] { text-decoration: none; font-size: 1.1rem; line-height: 1; }
.ccal-nav .btn-link.small[b-zutqrkvupv] { font-size: .75rem; }
.ccal-period[b-zutqrkvupv] { min-width: 9rem; text-align: center; font-size: 1rem; }

.ccal-head[b-zutqrkvupv] {
    display: flex;
    position: sticky;
    top: 0;
    z-index: 6;
    background: var(--bg-card);
    border-bottom: 1px solid var(--border-color);
}
.ccal-head-title[b-zutqrkvupv] { font-weight: 600; display: flex; align-items: flex-end; padding-bottom: 4px; }
.ccal-head-bands[b-zutqrkvupv] { flex: 1; min-width: 0; }
.ccal-head-band[b-zutqrkvupv] { position: relative; height: 22px; }
.ccal-head-tiny[b-zutqrkvupv] { height: 16px; }
.ccal-head-tall[b-zutqrkvupv] { height: 38px; }
.ccal-head-cell[b-zutqrkvupv] {
    position: absolute;
    top: 0;
    bottom: 0;
    text-align: center;
    font-weight: 600;
    font-size: .75rem;
    line-height: 20px;
    overflow: hidden;
    white-space: nowrap;
    border-left: 1px solid var(--border-subtle);
}
.ccal-head-tiny .ccal-head-cell[b-zutqrkvupv] { font-size: .58rem; font-weight: 400; line-height: 15px; color: var(--text-muted); }
.ccal-head-sub[b-zutqrkvupv] { font-size: .7rem; font-weight: 400; line-height: 14px; color: var(--text-muted); }

.ccal-label[b-zutqrkvupv] { flex: 0 0 var(--ccal-label); width: var(--ccal-label); min-width: 0; }

.ccal-row[b-zutqrkvupv] { display: flex; border-bottom: 1px solid var(--border-subtle); }
.ccal-row-country[b-zutqrkvupv] { background: var(--bg-card); }
.ccal-row-supplier[b-zutqrkvupv] { background: color-mix(in srgb, var(--accent) 8%, transparent); }

.ccal-country[b-zutqrkvupv] {
    display: flex;
    align-items: center;
    gap: .4rem;
    border: 0;
    background: none;
    padding: 5px 4px;
    font-weight: 700;
    font-size: .9rem;
    color: var(--text-primary);
    text-align: left;
    cursor: pointer;
}
.ccal-chevron[b-zutqrkvupv] { width: 1rem; color: var(--text-muted); font-size: .8rem; }

.ccal-row-label[b-zutqrkvupv] {
    display: flex;
    align-items: center;
    gap: .4rem;
    padding: 4px 6px 4px 28px;
}
.ccal-row-supplier .ccal-row-label[b-zutqrkvupv] { font-weight: 600; }

.ccal-track-plain[b-zutqrkvupv] { flex: 1; position: relative; min-width: 0; }
.ccal-track[b-zutqrkvupv] { flex: 1; position: relative; min-width: 0; cursor: crosshair; touch-action: none; }

.ccal-track[b-zutqrkvupv]  .ccal-rule,
.ccal-track-plain[b-zutqrkvupv]  .ccal-rule {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--border-subtle);
    pointer-events: none;
}

.ccal-bar[b-zutqrkvupv] {
    position: absolute;
    height: 22px;
    min-width: 16px;
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 0 6px;
    border-radius: 5px;
    font-size: .75rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    cursor: grab;
    touch-action: none;
    z-index: 1;
}
.ccal-bar:hover[b-zutqrkvupv] { filter: brightness(.95); box-shadow: var(--shadow-md); }
.ccal-bar-supplier[b-zutqrkvupv] { background: var(--bar); color: var(--bar-text); }
.ccal-bar-account[b-zutqrkvupv] {
    background: color-mix(in srgb, var(--bar) 28%, var(--bg-card));
    border: 1px solid color-mix(in srgb, var(--bar) 55%, var(--bg-card));
    color: var(--text-primary);
}
.ccal-clip-l[b-zutqrkvupv] { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.ccal-clip-r[b-zutqrkvupv] { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.ccal-bar-tall[b-zutqrkvupv] { height: 46px; }

/* Above the picture layer, and clear of it on a bar that has one. */
.ccal-bar-body[b-zutqrkvupv] {
    position: relative;
    z-index: 1;
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 4px;
}
.ccal-bar-hasart .ccal-bar-body[b-zutqrkvupv] { padding-left: calc(min(78px, 45%) - 2px); }
.ccal-bar-text[b-zutqrkvupv] { display: flex; flex-direction: column; justify-content: center; line-height: 1.25; min-width: 0; overflow: hidden; }
.ccal-bar-name[b-zutqrkvupv] { overflow: hidden; text-overflow: ellipsis; }
.ccal-bar-dates[b-zutqrkvupv] { font-size: .66rem; font-weight: 500; opacity: .85; overflow: hidden; text-overflow: ellipsis; }

/* The picture, as on the planning strip: a panel at the head of the bar whatever its length, with a
   wash so it holds up over any photograph and a mask that fades it into the bar's colour rather
   than ending on a hard edge. */
.ccal-bar-hasart[b-zutqrkvupv]::before {
    content: "";
    position: absolute;
    top: 0; bottom: 0; left: 0;
    width: min(78px, 45%);
    background-image:
        linear-gradient(90deg, rgba(0,0,0,.45) 0%, rgba(0,0,0,.18) 60%, rgba(0,0,0,.05) 100%),
        var(--art);
    background-size: auto, cover;
    background-position: center, center;
    background-repeat: no-repeat, no-repeat;
    -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 62%, transparent 100%);
            mask-image: linear-gradient(90deg, #000 0%, #000 62%, transparent 100%);
    pointer-events: none;
}
.ccal-bar-link[b-zutqrkvupv] { flex: none; display: inline-flex; opacity: .8; }

.ccal[b-zutqrkvupv]  .ccal-icon { width: 14px; height: 14px; flex: none; }

/* Handed to the pointer script: it finds these by name and moves them by inline style. */
.mcal-grip[b-zutqrkvupv] { position: absolute; top: 0; bottom: 0; width: 6px; cursor: ew-resize; }
.ccal-grip-l[b-zutqrkvupv] { left: 0; }
.ccal-grip-r[b-zutqrkvupv] { right: 0; }
.ccal-track[b-zutqrkvupv]  .mcal-dragging { cursor: grabbing; z-index: 5; box-shadow: var(--shadow-md); }
.ccal-track[b-zutqrkvupv]  .mcal-ghost {
    position: absolute;
    top: 3px;
    bottom: 3px;
    border-radius: 5px;
    border: 2px dashed var(--accent);
    background: var(--accent-light);
    pointer-events: none;
    z-index: 2;
}

.ccal-legend[b-zutqrkvupv] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem 1.5rem;
    padding: .6rem .9rem;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-card);
    font-size: .8rem;
}
.ccal-legend-item[b-zutqrkvupv] { display: inline-flex; align-items: center; gap: .4rem; }
.ccal-legend[b-zutqrkvupv]  .ccal-icon { width: 18px; height: 18px; flex: none; }
.ccal-legend-types[b-zutqrkvupv] { display: inline-flex; flex-wrap: wrap; gap: .25rem .9rem; color: var(--text-muted); }
.ccal-legend-type[b-zutqrkvupv] { display: inline-flex; align-items: center; gap: .3rem; }
.ccal-dot[b-zutqrkvupv] { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
/* /Components/Pages/Catalogue/CustomerDetails.razor.rz.scp.css */

/* ── Logotype ──
   Same 34px circle the investment split uses, so what you upload is previewed at the size it will
   actually be drawn. object-fit keeps a non-square image from stretching. */
.cust-logo[b-4cp8y0yz7z] {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    flex-shrink: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--accent-light);
    border: 1px solid var(--border-color);
}

.cust-logo img[b-4cp8y0yz7z] {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.cust-logo-initials[b-4cp8y0yz7z] {
    font-size: 12px;
    font-weight: 700;
    color: var(--accent);
}

.cust-logo-lg[b-4cp8y0yz7z] {
    width: 56px;
    height: 56px;
}

.cust-logo-lg .cust-logo-initials[b-4cp8y0yz7z] { font-size: 18px; }

/* ── Header ──
   Sticky, with the page's own background behind it, so Save stays in reach down the long form.
   It sticks under the app's own top bar, which is itself sticky and 3.5rem tall from the tablet
   breakpoint up (MainLayout.razor.css); below that the bar scrolls away and 0 is right. */
.cust-head[b-4cp8y0yz7z] {
    position: sticky;
    top: 0;
    z-index: 20;
    background: var(--bg-body);
    padding: .25rem 0 .9rem;
    margin-bottom: .75rem;
    border-bottom: 1px solid var(--border-color);
}

@media (min-width: 641px) {
    .cust-head[b-4cp8y0yz7z] { top: 3.5rem; }
}

.cust-facts[b-4cp8y0yz7z] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem .9rem;
    color: var(--text-muted);
    font-size: .875rem;
    margin-top: .15rem;
}

/* ── The three cards ──
   Identity and commercial terms stacked on the left, sell-out reporting beside them — the two
   halves are about the same height, and one column of everything was a wall. */
.cust-grid[b-4cp8y0yz7z] {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
    align-items: start;
}

@media (min-width: 1200px) {
    .cust-grid[b-4cp8y0yz7z] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.cust-stores > summary[b-4cp8y0yz7z] {
    cursor: pointer;
    list-style: none;
}

.cust-stores > summary[b-4cp8y0yz7z]::-webkit-details-marker { display: none; }

.cust-stores > summary[b-4cp8y0yz7z]::before {
    content: "▸";
    display: inline-block;
    width: 1rem;
    color: var(--text-muted);
}

.cust-stores[open] > summary[b-4cp8y0yz7z]::before { content: "▾"; }
/* /Components/Pages/Changelog.razor.rz.scp.css */
.changelog-container[b-0y5o0m1a6a] {
    max-width: 800px;
}

.changelog-item[b-0y5o0m1a6a] {
    background: var(--bg-card, #fff);
    border-radius: 12px;
    margin-bottom: 1rem;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
    overflow: hidden;
}

.changelog-item.latest[b-0y5o0m1a6a] {
    border: 2px solid var(--accent, #2563eb);
}

.changelog-header[b-0y5o0m1a6a] {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 1rem 1.25rem;
    cursor: pointer;
    transition: background-color 0.2s ease;
}

.changelog-header:hover[b-0y5o0m1a6a] {
    background-color: var(--bg-subtle, #f5f7fa);
}

.version-badge[b-0y5o0m1a6a] {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-primary, #1f2937);
    padding: 0.25rem 0.75rem;
    background-color: var(--bg-subtle, #f5f7fa);
    border-radius: 6px;
}

.version-badge.badge-latest[b-0y5o0m1a6a] {
    background: linear-gradient(135deg, rgba(37, 99, 235, 0.15), rgba(37, 99, 235, 0.1));
    color: var(--accent, #2563eb);
}

.release-date[b-0y5o0m1a6a] {
    font-size: 0.875rem;
}

.expand-icon[b-0y5o0m1a6a] {
    color: var(--text-muted, #8a94a6);
    transition: transform 0.2s ease;
}

.expand-icon.expanded[b-0y5o0m1a6a] {
    transform: rotate(180deg);
}

.changelog-body[b-0y5o0m1a6a] {
    padding: 0 1.25rem 1.25rem;
    border-top: 1px solid var(--border-color, #e5e9f0);
}

.changes-list[b-0y5o0m1a6a] {
    list-style: none;
    padding: 0;
    margin: 1rem 0 0 0;
}

.changes-list li[b-0y5o0m1a6a] {
    position: relative;
    padding: 0.5rem 0 0.5rem 1.5rem;
    color: var(--text-secondary, #4b5563);
    line-height: 1.5;
}

.changes-list li[b-0y5o0m1a6a]::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.9rem;
    width: 6px;
    height: 6px;
    background-color: var(--accent, #2563eb);
    border-radius: 50%;
}
/* /Components/Pages/Customers/Reporting.razor.rz.scp.css */
/* ── KPI cards: same Insight360/mock style as the SOA dashboard ── */

.soa-kpis[b-drwu4qdj7j] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 12px;
}

.soa-kpi[b-drwu4qdj7j] {
    background: var(--bg-card, #fff);
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 14px;
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}

.soa-kpi-top[b-drwu4qdj7j] {
    display: flex;
    align-items: center;
    gap: 10px;
}

.soa-kpi-icon[b-drwu4qdj7j] {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--kpi-color, #888) 14%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.soa-kpi-icon svg[b-drwu4qdj7j] {
    width: 20px;
    height: 20px;
    stroke: var(--kpi-color, #888);
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.soa-kpi-label[b-drwu4qdj7j] {
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--text-muted, #6c757d);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.soa-kpi-value[b-drwu4qdj7j] {
    font-size: 1.7rem;
    font-weight: 700;
    line-height: 1.1;
}

.soa-kpi-caption[b-drwu4qdj7j] {
    font-size: 0.74rem;
    color: var(--text-muted, #6c757d);
}

/* ── Customer table ── */

.row-link[b-drwu4qdj7j] {
    cursor: pointer;
}

.sortable[b-drwu4qdj7j] {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.sortable:hover[b-drwu4qdj7j] {
    color: var(--accent, #2563eb);
}

/* ── KPI stacks beside the compact pie: two boxes share the column height ── */
.kpi-stack[b-drwu4qdj7j] {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.kpi-stack .soa-kpi[b-drwu4qdj7j] {
    flex: 1;
}

/* ── The two ranked cards under the headline figures ───────────────────────
   Both are isp-* lists (app.css) — the round logo mark, the name, a bar, the figures. What is
   local here is what each list does with its bar: the investment split draws two of them, and the
   ROI ranking draws one that can run either side of zero. */
/* Every column a fixed size but the bar. Each row is its own grid container, so an "auto" column
   is measured per row — a long customer name would step that row's bar in and leave the list with
   a ragged edge down the middle. Fixed columns make the rows line up, and make the axis below the
   ROI list able to echo the same template and land under the right column. */
.cbar-row[b-drwu4qdj7j] {
    grid-template-columns: 30px 8.5rem minmax(60px, 1fr) 4.6rem;
}

.cbar-axis-row[b-drwu4qdj7j] {
    padding-top: 2px;
    padding-bottom: 0;
    cursor: default;
}

.cbar-axis-row:hover[b-drwu4qdj7j] { background: none; }

/* Two thin bars where the single isp bar would be. */
.cbar-pair[b-drwu4qdj7j] {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.cbar-track[b-drwu4qdj7j] {
    position: relative;
    display: block;
    height: 9px;
    border-radius: 5px;
    background: var(--bg-subtle);
    overflow: hidden;
}

.cbar-fill[b-drwu4qdj7j] {
    position: absolute;
    top: 0;
    bottom: 0;
    border-radius: 5px;
    min-width: 2px;
}

.cbar-fill-committed[b-drwu4qdj7j] { left: 0; background: #2563eb; }
.cbar-fill-spent[b-drwu4qdj7j]     { left: 0; background: #0891b2; }

/* The header swatches carry the same two values — change them together. */
.cbar-key[b-drwu4qdj7j] {
    width: 10px;
    height: 10px;
    border-radius: 2px;
    display: inline-block;
}

.cbar-key-committed[b-drwu4qdj7j] { background: #2563eb; }
.cbar-key-spent[b-drwu4qdj7j]     { background: #0891b2; }

.cbar-nums[b-drwu4qdj7j] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1.25;
}

.cbar-num-sub[b-drwu4qdj7j] {
    font-size: 0.74rem;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

/* ── The diverging ROI bar ── */
.cbar-div[b-drwu4qdj7j] {
    height: 22px;
    overflow: visible;
}

.cbar-zero[b-drwu4qdj7j] {
    position: absolute;
    top: -2px;
    bottom: -2px;
    width: 1px;
    background: var(--border-color);
    z-index: 1;
}

.cbar-fill-pos[b-drwu4qdj7j] { background: #16a34a; }
.cbar-fill-bad[b-drwu4qdj7j],
.cbar-fill-neg[b-drwu4qdj7j] { background: #ef7a7a; }

/* Endpoints of the range, with zero sitting where it actually falls between them. */
.cbar-axis[b-drwu4qdj7j] {
    position: relative;
    display: block;
    height: 1em;
    font-size: 0.7rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.cbar-axis-min[b-drwu4qdj7j],
.cbar-axis-max[b-drwu4qdj7j],
.cbar-axis-zero[b-drwu4qdj7j] {
    position: absolute;
    top: 0;
    white-space: nowrap;
}

.cbar-axis-min[b-drwu4qdj7j] { left: 0; }
.cbar-axis-max[b-drwu4qdj7j] { right: 0; }

.cbar-axis-zero[b-drwu4qdj7j] {
    left: var(--zero, 0%);
    transform: translateX(-50%);
}

/* ── ROI pill ──────────────────────────────────────────────────────────────
   One width for all of them: the ROI column is scanned down, not read across, and chips that
   change width with their digits make a ragged edge that hides the pattern in the colours. */
.roi-pill[b-drwu4qdj7j] {
    display: inline-block;
    min-width: 4.4rem;
    padding: 2px 8px;
    border-radius: 999px;
    border: 1px solid transparent;
    font-size: 0.78rem;
    font-weight: 600;
    text-align: center;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.roi-pill-good[b-drwu4qdj7j] {
    background: color-mix(in srgb, #16a34a 14%, transparent);
    border-color: color-mix(in srgb, #16a34a 30%, transparent);
    color: #15803d;
}

.roi-pill-weak[b-drwu4qdj7j] {
    background: color-mix(in srgb, #d97706 14%, transparent);
    border-color: color-mix(in srgb, #d97706 30%, transparent);
    color: #b45309;
}

.roi-pill-flat[b-drwu4qdj7j] {
    background: var(--bg-subtle);
    border-color: var(--border-color);
    color: var(--text-secondary);
}

.roi-pill-bad[b-drwu4qdj7j] {
    background: color-mix(in srgb, #dc2626 13%, transparent);
    border-color: color-mix(in srgb, #dc2626 28%, transparent);
    color: #b91c1c;
}

/* No matched spend to measure — not a score, so it carries no colour at all. */
.roi-pill-none[b-drwu4qdj7j] {
    background: none;
    border-color: transparent;
    color: var(--text-muted);
}

/* The light-mode greens and reds go muddy on the ember ground. */
[data-theme="dark"] .roi-pill-good[b-drwu4qdj7j] { color: #5fd99a; }
[data-theme="dark"] .roi-pill-weak[b-drwu4qdj7j] { color: #f0c060; }
[data-theme="dark"] .roi-pill-bad[b-drwu4qdj7j]  { color: #f08a7f; }
[data-theme="dark"] .cbar-fill-pos[b-drwu4qdj7j] { background: #34c07a; }
[data-theme="dark"] .cbar-fill-neg[b-drwu4qdj7j] { background: #e0736f; }

/* A bar that runs past the frame ends in a zigzag rather than a clean edge, so it cannot be read
   as one that merely reaches the end of the scale. The teeth are on the outer end only — the end
   at zero stays square, because that end is exact. */
.cbar-clip-low[b-drwu4qdj7j] {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    clip-path: polygon(5px 0, 100% 0, 100% 100%, 5px 100%, 0 83%, 5px 66%, 0 50%, 5px 33%, 0 16%);
}

.cbar-clip-high[b-drwu4qdj7j] {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    clip-path: polygon(0 0, calc(100% - 5px) 0, 100% 16%, calc(100% - 5px) 33%, 100% 50%, calc(100% - 5px) 66%, 100% 83%, calc(100% - 5px) 100%, 0 100%);
}

.cbar-note[b-drwu4qdj7j] {
    margin-top: 8px;
    font-size: 0.72rem;
    line-height: 1.35;
    color: var(--text-muted);
}

/* The two halves tinted the same way the budget screen tints them, so a column
   means the same thing on both pages. */
.budget-coop[b-drwu4qdj7j] { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.budget-mdf[b-drwu4qdj7j] { background: color-mix(in srgb, #7c3aed 6%, transparent); }
/* /Components/Pages/Customers/ReportingDetails.razor.rz.scp.css */
/* ── KPI cards: same Insight360/mock style as the SOA dashboard ── */

.soa-kpis[b-uvx92ucib3] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 12px;
}

.soa-kpi[b-uvx92ucib3] {
    background: var(--bg-card, #fff);
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 14px;
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}

.soa-kpi-top[b-uvx92ucib3] {
    display: flex;
    align-items: center;
    gap: 10px;
}

.soa-kpi-icon[b-uvx92ucib3] {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--kpi-color, #888) 14%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.soa-kpi-icon svg[b-uvx92ucib3] {
    width: 20px;
    height: 20px;
    stroke: var(--kpi-color, #888);
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.soa-kpi-label[b-uvx92ucib3] {
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--text-muted, #6c757d);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.soa-kpi-value[b-uvx92ucib3] {
    font-size: 1.7rem;
    font-weight: 700;
    line-height: 1.1;
}

.soa-kpi-caption[b-uvx92ucib3] {
    font-size: 0.74rem;
    color: var(--text-muted, #6c757d);
}

/* ── Status dot in the agreements table ── */

.status-dot[b-uvx92ucib3] {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--dot, #6c757d);
    margin-right: 4px;
}

/* ── Detail pages: fixed 2 rows × 3 boxes (tidier than one long strip) ── */
.soa-kpis.two-rows[b-uvx92ucib3] {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 900px) {
    .soa-kpis.two-rows[b-uvx92ucib3] {
        grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    }
}
/* /Components/Pages/Home.razor.rz.scp.css */
/* ── Promora dashboard (hd-*) — the shared page furniture lives in app.css ── */

/* Greeting (kept for the pending-activation card) */
.hd-hello[b-40apetgema] {
    font-size: 28px;
    font-weight: 700;
    color: var(--text-strong);
}

.hd-subtitle[b-40apetgema] {
    color: var(--text-secondary);
    font-size: 14px;
}

/* KPI action cards */
.hd-kpis[b-40apetgema] {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.hd-kpi-row[b-40apetgema] {
    display: flex;
    gap: 14px;
}

.hd-kpi[b-40apetgema] {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    text-align: left;
    padding: 13px 14px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    cursor: pointer;
    transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
}

.hd-kpi:hover:not(:disabled)[b-40apetgema] {
    border-color: var(--kpi-color, var(--text-muted));
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
    transform: translateY(-2px);
}

.hd-kpi:disabled[b-40apetgema] { cursor: default; opacity: 0.85; }
.hd-kpi:focus-visible[b-40apetgema] { outline: 2px solid var(--kpi-color, var(--text-muted)); outline-offset: 2px; }

.hd-kpi-icon[b-40apetgema] {
    width: 34px;
    height: 34px;
    border-radius: 10px;
    background: var(--kpi-color, #ced4da);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.hd-kpi-icon svg[b-40apetgema] {
    width: 18px; height: 18px;
    stroke: currentColor; fill: none;
    stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

.hd-kpi-body[b-40apetgema] { min-width: 0; flex: 1; }

.hd-kpi-title[b-40apetgema] {
    font-size: 12.5px;
    font-weight: 700;
    color: var(--text-strong);
    line-height: 1.2;
}

.hd-kpi-desc[b-40apetgema] {
    font-size: 11px;
    color: var(--text-secondary);
    margin-top: 2px;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.hd-kpi-link[b-40apetgema] {
    display: inline-block;
    margin-top: 8px;
    font-size: 12px;
    font-weight: 600;
    color: var(--kpi-color, var(--text-secondary));
}

.hd-kpi-count[b-40apetgema] {
    font-size: 24px;
    font-weight: 700;
    line-height: 1;
    color: var(--text-strong);
    flex-shrink: 0;
}

.hd-panel-footnote[b-40apetgema] {
    padding: 8px 18px 2px;
    font-size: 12px;
    color: var(--text-muted);
}
.hd-panel-footnote a[b-40apetgema] { color: var(--text-secondary); }

/* Narrower viewports: let the balanced rows wrap to fewer, wider cards. */
@media (max-width: 1100px) {
    .hd-kpi-row[b-40apetgema] { flex-wrap: wrap; }
    .hd-kpi[b-40apetgema] { flex: 1 1 44%; }
}

@media (max-width: 560px) {
    .hd-kpi[b-40apetgema] { flex: 1 1 100%; }
}

/* Panel header */
.hd-panel-header[b-40apetgema] {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border-subtle);
}

.hd-panel-title[b-40apetgema] {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-strong);
}

.hd-panel-caption[b-40apetgema] {
    font-size: 12px;
    color: var(--text-muted);
    margin-top: 2px;
}

.hd-panel-action[b-40apetgema] {
    font-size: 13px;
    font-weight: 600;
    color: var(--accent);
    text-decoration: none;
    white-space: nowrap;
}

.hd-panel-action:hover[b-40apetgema] { text-decoration: underline; }
.hd-panel-body[b-40apetgema] { padding: 16px 18px; }
.hd-panel-body.p-0[b-40apetgema] { padding: 0; }

/* Pipeline */
.hd-pipeline-wrap[b-40apetgema] {
    display: flex;
    align-items: stretch;
    gap: 18px;
}

/* ── Flow ──────────────────────────────────────────────────────────────────
   The stages are chevrons that interlock, so the eye reads a direction instead of a row of boxes,
   and they are tinted along a ramp from the first stage to the last — the colour itself carries how
   far through the pipeline a stage sits. --tint is the position on that ramp, set per stage from
   the markup, which is what lets one rule serve pipelines of any length. */
.hd-flow[b-40apetgema] {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
    --flow-start: #e1ebfc;
    --flow-end: #ddf2e6;
    /* One metallic grey for every stage icon. The per-status colours still drive the badges and
       the action cards; inside the flow the tinted chevrons already carry the progression, and
       seven different icon colours on top of them was a colour too many. */
    --flow-icon: #8d99a8;
    --notch: 13px;
}

.hd-flow-track[b-40apetgema] {
    display: flex;
    gap: 3px;
    border-radius: 12px;
    /* Squares off the outer ends, which the chevron clip-path cannot round itself. */
    overflow: hidden;
}

.hd-flow-step[b-40apetgema] {
    flex: 1 1 0;
    min-width: 0;
    border: 0;
    padding: 15px 20px 13px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    cursor: pointer;
    background: color-mix(in srgb, var(--flow-end) var(--tint, 0%), var(--flow-start));
    /* Notched on the left, pointed on the right: each stage slots into the next. */
    clip-path: polygon(0 0, calc(100% - var(--notch)) 0, 100% 50%, calc(100% - var(--notch)) 100%, 0 100%, var(--notch) 50%);
    transition: transform .15s, filter .15s;
}

/* The two ends face outwards, so the flow reads as one bar with a direction. */
.hd-flow-first[b-40apetgema] {
    clip-path: polygon(0 0, calc(100% - var(--notch)) 0, 100% 50%, calc(100% - var(--notch)) 100%, 0 100%);
}

.hd-flow-last[b-40apetgema] {
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, var(--notch) 50%);
}

/* box-shadow would be clipped away with the corners; drop-shadow follows the chevron. */
.hd-flow-step:hover:not(:disabled)[b-40apetgema] {
    transform: translateY(-2px);
    filter: drop-shadow(0 5px 10px rgba(16, 24, 40, 0.16));
}

.hd-flow-step:focus-visible[b-40apetgema] { outline: 2px solid var(--accent); outline-offset: -3px; }
.hd-flow-step:disabled[b-40apetgema] { cursor: default; opacity: .62; }

.hd-flow-circle[b-40apetgema] {
    width: 34px; height: 34px;
    border-radius: 50%;
    background: var(--flow-icon);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 8px;
    flex-shrink: 0;
}

.hd-flow-circle svg[b-40apetgema] {
    width: 17px; height: 17px;
    stroke: currentColor; fill: none;
    stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

.hd-flow-label[b-40apetgema] {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    line-height: 1.2;
    color: var(--text-secondary);
    min-height: 24px;
    display: flex; align-items: center; justify-content: center;
}

.hd-flow-count[b-40apetgema] {
    font-size: 23px;
    font-weight: 700;
    color: var(--text-strong);
    line-height: 1;
    margin-top: 5px;
}

.hd-flow-share[b-40apetgema] {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .2px;
    color: var(--text-secondary);
    margin-top: 5px;
    min-height: 13px;
}

[data-theme="dark"] .hd-flow[b-40apetgema] {
    --flow-start: #1e2a3d;
    --flow-end: #1c3029;
    --flow-icon: #7c8896;
}

.hd-pipeline-summary[b-40apetgema] {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 14px;
    padding: 8px 18px;
    border-left: 1px solid var(--border-subtle);
    min-width: 150px;
}

.hd-summary-stat[b-40apetgema] { text-align: center; }

.hd-summary-num[b-40apetgema] {
    font-size: 26px;
    font-weight: 700;
    color: var(--text-strong);
    line-height: 1;
}

.hd-summary-accent[b-40apetgema] { color: var(--accent); }

.hd-summary-label[b-40apetgema] {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    font-weight: 600;
    color: var(--text-secondary);
    margin-top: 5px;
}

.hd-summary-divider[b-40apetgema] { height: 1px; background: var(--border-subtle); }

@media (max-width: 992px) {
    .hd-pipeline-wrap[b-40apetgema] { flex-direction: column; }
    .hd-flow-track[b-40apetgema] { overflow-x: auto; }
    .hd-flow-step[b-40apetgema] { flex: 0 0 148px; }
    .hd-pipeline-summary[b-40apetgema] {
        flex-direction: row;
        justify-content: space-around;
        border-left: none;
        border-top: 1px solid var(--border-subtle);
        padding-top: 14px;
    }
    .hd-summary-divider[b-40apetgema] { width: 1px; height: auto; }
}

@media (max-width: 560px) {
    .hd-flow-step[b-40apetgema] { flex: 0 0 130px; }
}

/* Table links inside panels */
[b-40apetgema] .table a {
    color: var(--accent);
    text-decoration: none;
    font-weight: 500;
}

[b-40apetgema] .table a:hover { text-decoration: underline; }
/* /Components/Pages/Products/Reporting.razor.rz.scp.css */
/* ── KPI cards: same Insight360/mock style as the SOA dashboard ── */

.soa-kpis[b-ezaktehu39] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 12px;
}

.soa-kpi[b-ezaktehu39] {
    background: var(--bg-card, #fff);
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 14px;
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}

.soa-kpi-top[b-ezaktehu39] {
    display: flex;
    align-items: center;
    gap: 10px;
}

.soa-kpi-icon[b-ezaktehu39] {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--kpi-color, #888) 14%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.soa-kpi-icon svg[b-ezaktehu39] {
    width: 20px;
    height: 20px;
    stroke: var(--kpi-color, #888);
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.soa-kpi-label[b-ezaktehu39] {
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--text-muted, #6c757d);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.soa-kpi-value[b-ezaktehu39] {
    font-size: 1.7rem;
    font-weight: 700;
    line-height: 1.1;
}

.soa-kpi-caption[b-ezaktehu39] {
    font-size: 0.74rem;
    color: var(--text-muted, #6c757d);
}

/* ── Customer table ── */

.row-link[b-ezaktehu39] {
    cursor: pointer;
}

.sortable[b-ezaktehu39] {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.sortable:hover[b-ezaktehu39] {
    color: var(--accent, #2563eb);
}

/* ── KPI stacks beside the compact pie: two boxes share the column height ── */
.kpi-stack[b-ezaktehu39] {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.kpi-stack .soa-kpi[b-ezaktehu39] {
    flex: 1;
}
/* /Components/Pages/Products/ReportingDetails.razor.rz.scp.css */
/* ── KPI cards: same Insight360/mock style as the SOA dashboard ── */

.soa-kpis[b-fprc174o8l] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 12px;
}

.soa-kpi[b-fprc174o8l] {
    background: var(--bg-card, #fff);
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 14px;
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}

.soa-kpi-top[b-fprc174o8l] {
    display: flex;
    align-items: center;
    gap: 10px;
}

.soa-kpi-icon[b-fprc174o8l] {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--kpi-color, #888) 14%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.soa-kpi-icon svg[b-fprc174o8l] {
    width: 20px;
    height: 20px;
    stroke: var(--kpi-color, #888);
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.soa-kpi-label[b-fprc174o8l] {
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--text-muted, #6c757d);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.soa-kpi-value[b-fprc174o8l] {
    font-size: 1.7rem;
    font-weight: 700;
    line-height: 1.1;
}

.soa-kpi-caption[b-fprc174o8l] {
    font-size: 0.74rem;
    color: var(--text-muted, #6c757d);
}

/* ── Status dot in the agreements table ── */

.status-dot[b-fprc174o8l] {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--dot, #6c757d);
    margin-right: 4px;
}

/* ── Detail pages: fixed 2 rows × 3 boxes (tidier than one long strip) ── */
.soa-kpis.two-rows[b-fprc174o8l] {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 900px) {
    .soa-kpis.two-rows[b-fprc174o8l] {
        grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    }
}
/* /Components/Pages/Projections/RrpPlanning.razor.rz.scp.css */
/* The price grid. Fifty-two columns of number, so every pixel of chrome is one the numbers do not
   get — the cells carry no borders of their own beyond a hairline, and the week rules do the work
   of separating them. */
.rrp-scroll[b-ww0nfi2h5q] {
    overflow-x: auto;
    max-height: 70vh;
    overflow-y: auto;
}

/* With the calendar folded away the grid takes the height it gave up. A cap rather than
   no cap at all: the sticky header and the tab strip above it only stay useful while the
   scroller is the thing that scrolls, and a table taller than the window puts the page
   back in charge of it. */
.rrp-scroll-tall[b-ww0nfi2h5q] { max-height: 84vh; }

/* Sized to its contents and no wider. min-width:100% was the mistake here: with 52 columns and a
   wide screen the browser had a thousand spare pixels to hand out, so every cell grew to four
   centimetres and a year became two metres of side-scrolling. A week column is now as wide as the
   number it holds. */
.rrp-grid[b-ww0nfi2h5q] {
    border-collapse: separate;
    border-spacing: 0;
    width: max-content;
    /* The same size the SOA tab reads at. The week columns pay for it in width — a five-digit
       price needs the room — and the year scrolls a little further as a result. Worth it: two
       tabs over one list that render at two different sizes read as two different tools. */
    font-size: 0.875rem;
}

.rrp-grid th[b-ww0nfi2h5q],
.rrp-grid td[b-ww0nfi2h5q] {
    border-right: 1px solid var(--border-subtle);
    border-bottom: 1px solid var(--border-subtle);
    padding: 0;
    white-space: nowrap;
}

/* The identifying columns stay put while the year scrolls past them — without this the grid is
   unusable two months in, because a column of numbers with no name against it says nothing. Five
   three of them: what identifies a product. Brand and department fold away with the rest, because
   they are read now and then rather than worked with. Each is sticky at its own offset, so the
   widths below and the lefts have to stay in step. */
.rrp-fix[b-ww0nfi2h5q] {
    position: sticky;
    z-index: 2;
    background: var(--bg-card);
    text-align: left;
    padding: 3px 8px;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The lefts are this grid's business; the WIDTHS are shared with the SOA tab (.rrp-c-* below),
   so the first four columns line up between the two views instead of each finding its own size —
   one too wide here, too narrow there. */
.rrp-f0[b-ww0nfi2h5q] { left: 0; padding: 3px 4px; text-align: center; }
.rrp-f1[b-ww0nfi2h5q] { left: 30px; }
.rrp-f2[b-ww0nfi2h5q] { left: 150px; }
.rrp-f3[b-ww0nfi2h5q] {
    left: 390px;
    border-right: 2px solid var(--border-color);
}

/* Assortment plans add who carries the product as a fifth sticky column, and the rule that ends
   the frozen block moves out to it. */
.rrp-f4[b-ww0nfi2h5q] {
    left: 510px;
    border-right: 2px solid var(--border-color);
}
.rrp-has-accts .rrp-f3[b-ww0nfi2h5q] { border-right: none; }

/* ── The four columns both tabs share ── */
.rrp-c-sel[b-ww0nfi2h5q]  { width: 30px;  min-width: 30px;  max-width: 30px; }
.rrp-c-art[b-ww0nfi2h5q]  { width: 120px; min-width: 120px; max-width: 120px; }
.rrp-c-prod[b-ww0nfi2h5q] { width: 240px; min-width: 240px; max-width: 240px; }
.rrp-c-cat[b-ww0nfi2h5q]  { width: 120px; min-width: 120px; max-width: 120px; }
.rrp-c-accts[b-ww0nfi2h5q] { width: 112px; min-width: 112px; max-width: 112px; }

/* A row's identity is not an emphasis. These are <th> in the grid because they label the row for
   a screen reader, which is a semantic, not an instruction to embolden them. */
.rrp-grid tbody th[b-ww0nfi2h5q] { font-weight: 400; }

/* The corner cell: sticky in both directions like the columns under it, but sized by them rather
   than by itself, so it can span the four and hold the control that folds the next six. */
/* Written as .rrp-grid thead .rrp-corner, not as .rrp-corner: ".rrp-grid thead th" below is the
   more specific selector and was winning the z-index, so the corner sat at 3 with the month
   headings and lost to them on document order — January slid over the button as the year
   scrolled. Every rule here that has to beat that one is qualified the same way. */
.rrp-grid thead .rrp-corner[b-ww0nfi2h5q] {
    position: sticky;
    left: 0;
    z-index: 5;
    background: var(--bg-subtle);
    text-align: left;
    padding: 2px 6px;
}

/* Small enough not to grow the row it sits in. */
.rrp-check[b-ww0nfi2h5q] { width: 13px; height: 13px; margin: 0; vertical-align: middle; cursor: pointer; }

/* The band a line follows, in the band's own colour. */
.rrp-band-dot[b-ww0nfi2h5q] {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
    display: inline-block;
}

/* The attributes are reference, not the point — they read one step quieter than the name. */
.rrp-attr[b-ww0nfi2h5q] { color: var(--text-secondary); }

.rrp-grid thead th[b-ww0nfi2h5q] {
    position: sticky;
    z-index: 3;
    background: var(--bg-subtle);
    font-weight: 600;
    color: var(--text-secondary);
    text-align: center;
    padding: 2px 4px;
}

.rrp-months th[b-ww0nfi2h5q] { top: 0; }
.rrp-weeknos th[b-ww0nfi2h5q] { top: 22px; }

/* The corner: sticky in both directions, so it sits above both the month row and the names. */
/* Left, not centred: these three head columns of text, and the SOA tab sets them the same way.
   The centring above is meant for the week and month headings, which sit over numbers. The
   checkbox column keeps it, because what it heads is centred too. */
.rrp-grid thead .rrp-fix[b-ww0nfi2h5q] {
    z-index: 4;
    background: var(--bg-subtle);
    text-align: left;
}

.rrp-grid thead .rrp-f0[b-ww0nfi2h5q] { text-align: center; }

.rrp-months th[b-ww0nfi2h5q] { font-size: 0.8rem; letter-spacing: 0.03em; }
.rrp-weeknos th.rrp-fix[b-ww0nfi2h5q] { font-size: 0.78rem; color: var(--text-secondary); }

/* Room for five digits and a thousands separator — "19 990" — and not a character more. Wider
   than it was, because the cells inside now render at the shared size. */
.rrp-weeknos th:not(.rrp-fix)[b-ww0nfi2h5q] {
    font-size: 0.75rem;
    color: var(--text-muted);
    width: 66px;
    min-width: 66px;
    max-width: 66px;
}

.rrp-cell[b-ww0nfi2h5q] { width: 66px; }

.rrp-prod[b-ww0nfi2h5q] { display: flex; align-items: center; gap: 6px; }

.rrp-prod-name[b-ww0nfi2h5q] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-remove[b-ww0nfi2h5q] {
    margin-left: auto;
    padding: 0 4px;
    line-height: 1;
    font-size: 1rem;
    text-decoration: none;
    opacity: 0;
}

.rrp-grid tbody tr:hover .rrp-remove[b-ww0nfi2h5q] { opacity: 1; }

/* ── The cells ──
   An input with no chrome at all: the grid is the chrome, and 52 bordered boxes a row would be a
   wall. It gains an outline only when it has focus. */
.rrp-input[b-ww0nfi2h5q] {
    width: 100%;
    min-width: 0;
    border: 0;
    background: transparent;
    padding: 3px 4px;
    text-align: right;
    font-size: 0.875rem;
    font-variant-numeric: tabular-nums;
    color: inherit;
}

.rrp-input:focus[b-ww0nfi2h5q] {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
    background: var(--bg-card);
}

/* Three states, and the order of the colours is the order of the work. Red is a price nobody but
   the planner has seen. Amber is one that has been handed over and is somebody else's to answer.
   Confirmed is plain — the absence of a colour is what "settled" looks like, and it is the state
   most of a finished sheet should be in.

   Amber rather than a second red, because "sent" is not a problem: a planner scanning a column
   wants the reds, which are still theirs, to be the only thing that shouts. */
.rrp-unconfirmed[b-ww0nfi2h5q] { color: #c0392b; }
.rrp-sent[b-ww0nfi2h5q] { color: #b26a00; }
.rrp-ok[b-ww0nfi2h5q] { color: var(--text-primary); }

/* Late is a third fact, and the cell already spends its text colour on confirmation and its
   background on the kind of price. So it gets an edge — visible down a column, and it cannot
   collide with either of the other two. */
.rrp-overdue[b-ww0nfi2h5q] { box-shadow: inset 2px 0 0 #c0392b; }

/* ── One tint, one meaning ─────────────────────────────────────────────────
   Four grades against the base price used to colour every cell in the sheet, with a legend under
   it to decode them — which made an ordinary year a quilt and gave the eye nowhere to land. The
   only cell worth finding is the one priced UNDER the campaign price: that is a cut the margin
   groups were never agreed against, and where the margin control stops telling the truth until an
   exception says what we will actually fund. So that cell alone is pink, and a white grid with a
   few pink cells needs no key. */
.rrp-deep[b-ww0nfi2h5q] { background: color-mix(in srgb, #e0518a 16%, transparent); }

[data-theme="dark"] .rrp-unconfirmed[b-ww0nfi2h5q] { color: #f08a7f; }
[data-theme="dark"] .rrp-sent[b-ww0nfi2h5q] { color: #e0a33c; }
[data-theme="dark"] .rrp-overdue[b-ww0nfi2h5q] { box-shadow: inset 2px 0 0 #f08a7f; }
[data-theme="dark"] .rrp-deep[b-ww0nfi2h5q] { background: color-mix(in srgb, #f07ba8 20%, transparent); }

/* ── Picking cells out ─────────────────────────────────────────────────────
   Excel's gesture and, as far as possible, Excel's look: the picked block is a wash with a border,
   not a colour of its own, so it reads as "these ones" over whatever the cells already say. */
.rrp-wk-head[b-ww0nfi2h5q] { user-select: none; }
.rrp-picking .rrp-wk-head[b-ww0nfi2h5q] { cursor: cell; }
.rrp-picking .rrp-wk-head:hover[b-ww0nfi2h5q] { color: var(--text-primary); }

/* ── Selection mode ────────────────────────────────────────────────────────
   The inputs stop taking the pointer entirely. That is the whole reason the mode exists: while a
   click could land on a price input, the browser was placing a caret and extending a text
   selection at the same time as we were trying to read a click, and a hair of movement between
   press and release made it a drag that fired no click at all. Inert inputs leave exactly one
   thing a click can mean. */
.rrp-picking .rrp-input[b-ww0nfi2h5q] {
    pointer-events: none;
    background: transparent;
    cursor: cell;
}

.rrp-picking td[b-ww0nfi2h5q] { cursor: cell; }
.rrp-picking[b-ww0nfi2h5q] { user-select: none; }

/* A single picked cell has to be as findable as a picked column, and a hairline outline on one
   66px cell among fifty-two was not: the count in the bar went up and the planner could not see
   which cell had done it. Wash and a real border, the way a spreadsheet marks a selection. */
.rrp-picked[b-ww0nfi2h5q] {
    box-shadow: inset 0 0 0 2px var(--accent, #2563eb);
    background-image: linear-gradient(color-mix(in srgb, #2563eb 14%, transparent),
                                      color-mix(in srgb, #2563eb 14%, transparent));
}
.rrp-grid thead .rrp-picked-head[b-ww0nfi2h5q] {
    background: color-mix(in srgb, #2563eb 16%, var(--bg-subtle));
    color: var(--text-primary);
}

/* The cell the panel on the right is describing. One at a time, so it can afford to be solid. */
.rrp-inspected[b-ww0nfi2h5q] { outline: 2px solid var(--accent, #2563eb); outline-offset: -2px; }

/* One frame, not two. Clicking a cell both inspects it (a ring on the cell) and focuses the input
   inside it (a ring of its own, two pixels in), which drew a box inside a box. The cell's ring is
   the one that survives: it is the same mark whether or not focus has since moved on, which is
   what the panel on the right is describing. An input reached by the arrow keys without a click
   still gets its own ring — there is no cell ring to collide with there. */
.rrp-inspected .rrp-input:focus[b-ww0nfi2h5q] { outline: none; }

/* ── Where an exception is set ─────────────────────────────────────────────
   A corner flag rather than a background: the background is already saying whether the price is
   under the campaign, and these two facts travel together — an exception usually exists BECAUSE
   the cell is pink — so they must be readable at once rather than overwriting each other. */
.rrp-exc[b-ww0nfi2h5q] { position: relative; }
.rrp-exc[b-ww0nfi2h5q]::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    border-top: 7px solid #7a3fa0;
    border-left: 7px solid transparent;
}

.rrp-grid thead .rrp-exc-head[b-ww0nfi2h5q] { box-shadow: inset 0 -2px 0 #7a3fa0; }

/* ── The product detail panel ──────────────────────────────────────────────
   Folded away by default: these are set once per product and then left alone, while the weeks are
   worked in every day. They sit between the name and the year so they scroll away with the weeks
   rather than eating the sticky column. */
/* It replaced the column heading, so it has to read as a control rather than as a label. */
.rrp-grid .rrp-detail[b-ww0nfi2h5q] {
    width: 96px;
    min-width: 96px;
    max-width: 96px;
    text-align: center;
    padding: 1px 3px;
}

.rrp-grid thead .rrp-detail[b-ww0nfi2h5q] { background: var(--bg-subtle); }

/* A tint down the panel so the eye knows where the year starts. */
.rrp-grid tbody .rrp-detail[b-ww0nfi2h5q] { background: color-mix(in srgb, var(--bg-subtle) 55%, transparent); }

/* The two price inputs used to be a size down and left-aligned, from when they lived in a folded
   detail panel. They are money in a column of money now: same size as every other figure, and
   ranged right with them. */
.rrp-detail-input[type="date"][b-ww0nfi2h5q] { padding: 2px; }

/* The marker chips carry their own colour, set inline from the marker. */
.rrp-marker[b-ww0nfi2h5q] {
    width: 100%;
    border: 1px solid var(--border-color);
    border-radius: 4px;
    background: transparent;
    font-size: 0.8rem;
    padding: 1px 2px;
    color: var(--text-primary);
}

/* ── The weeks a selected calendar block covers ────────────────────────────
   An OUTLINE rather than a background or an inset shadow, because both of those are already
   spoken for — the background says what kind of price a cell holds and the inset shadow says it is
   past its confirmation date. Outline is the one channel left, and it reads as a frame around the
   period rather than as another property of the price. */
.rrp-lit[b-ww0nfi2h5q] {
    outline: 2px solid color-mix(in srgb, var(--accent) 60%, transparent);
    outline-offset: -2px;
}

.rrp-weeknos th.rrp-lit-head[b-ww0nfi2h5q] {
    background: var(--accent);
    color: var(--text-on-accent);
    font-weight: 700;
}

/* What is lit, and how to stop. Sits under the calendar so it reads as part of it. */
.rrp-selbar[b-ww0nfi2h5q] {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    padding: 5px 10px;
    border-radius: var(--border-radius-sm, 6px);
    background: var(--accent-light);
    font-size: 0.78rem;
}

.rrp-selbar-dot[b-ww0nfi2h5q] {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
}

/* ── The Excel menu ──────────────────────────────────────────────────────
   Hand-rolled rather than Bootstrap's: this application ships Bootstrap's CSS but not its
   JavaScript, and the user menu in the header solves it the same way — a flag, a backdrop that
   catches the click outside, and an absolutely positioned list. */
.rrp-menu[b-ww0nfi2h5q] { position: relative; }

.rrp-menu-caret[b-ww0nfi2h5q] { font-size: 0.7rem; opacity: 0.7; }

.rrp-menu-backdrop[b-ww0nfi2h5q] {
    position: fixed;
    inset: 0;
    z-index: 1040;
}

.rrp-menu-list[b-ww0nfi2h5q] {
    position: absolute;
    right: 0;
    top: calc(100% + 0.35rem);
    z-index: 1041;
    min-width: 15rem;
    background: var(--bg-elevated);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    box-shadow: var(--shadow-md);
    padding: 0.35rem;
}

.rrp-menu-item[b-ww0nfi2h5q] {
    display: block;
    width: 100%;
    text-align: left;
    border: 0;
    background: none;
    border-radius: 6px;
    padding: 0.4rem 0.6rem;
    font-size: 0.82rem;
    color: var(--text-primary);
    cursor: pointer;
}

.rrp-menu-item:hover:not(:disabled)[b-ww0nfi2h5q] { background: var(--bg-subtle); }
.rrp-menu-item:disabled[b-ww0nfi2h5q] { opacity: 0.5; cursor: default; }

.rrp-menu-note[b-ww0nfi2h5q] {
    padding: 0.4rem 0.6rem 0.2rem;
    font-size: 0.72rem;
    color: var(--text-muted);
    border-top: 1px solid var(--border-subtle);
    margin-top: 0.3rem;
}

/* ── The two tabs ──────────────────────────────────────────────────────── */
/* The body sits flush under the tab strip, so the two read as one panel rather than a strip and
   a card that happen to be near each other. */
/* ── The tab strip and the cell inspector that shares its line ─────────────
   The panel sits level with the tabs, hard right. A reader clicking down a column keeps their eye
   at the top of the sheet; a panel under the grid would be below the fold on every screen the
   grid is worth filling. It has to survive being empty, so it holds its height. */
.rrp-tabrow[b-ww0nfi2h5q] {
    display: flex;
    align-items: flex-end;
    gap: 1rem;
    flex-wrap: wrap;
}

.rrp-tabrow .nav-tabs[b-ww0nfi2h5q] { flex: 0 0 auto; border-bottom: 0; }

/* Sits on the tabs' line rather than above the grid: it changes what the grid DOES, so it belongs
   where the grid is chosen, and it must be findable again to get back out. */
.rrp-pickbtn[b-ww0nfi2h5q] { flex: 0 0 auto; margin-bottom: 6px; white-space: nowrap; }

/* One line, and it stays one line. The parts are ordered by how much they are worth: the name and
   week say WHICH cell, the three figures are the answer, and the working is context. Only the two
   text ends may shrink, the working first and hardest — a truncated explanation is a small loss,
   a truncated margin is a wrong number. */
.rrp-inspector[b-ww0nfi2h5q] {
    flex: 1 1 22rem;
    min-width: 0;
    display: flex;
    align-items: baseline;
    flex-wrap: nowrap;
    white-space: nowrap;
    overflow: hidden;
    gap: 12px;
    min-height: 34px;
    padding: 6px 10px;
    font-size: 0.8rem;
    border-bottom: 1px solid var(--border-color);
}

.rrp-insp-name[b-ww0nfi2h5q] { flex: 0 1 auto; min-width: 3rem; overflow: hidden; text-overflow: ellipsis; }
.rrp-insp-wk[b-ww0nfi2h5q] { flex: 0 0 auto; color: var(--text-secondary); }

.rrp-insp-exc[b-ww0nfi2h5q] {
    flex: 0 0 auto;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 700;
    color: #7a3fa0;
    border: 1px solid currentColor;
    border-radius: 3px;
    padding: 0 4px;
}

.rrp-insp-fig[b-ww0nfi2h5q] { flex: 0 0 auto; display: inline-flex; align-items: baseline; gap: 5px; }

.rrp-insp-lbl[b-ww0nfi2h5q] { color: var(--text-secondary); font-size: 0.72rem; }

.rrp-insp-val[b-ww0nfi2h5q] { font-weight: 600; font-variant-numeric: tabular-nums; }

/* The same two tints the perspective banners use, so a figure means the same thing wherever it
   is read on this page. */
.rrp-insp-our .rrp-insp-lbl[b-ww0nfi2h5q] { color: #1d4ed8; }
.rrp-insp-cust .rrp-insp-lbl[b-ww0nfi2h5q] { color: #b45309; }

.rrp-insp-note[b-ww0nfi2h5q] {
    flex: 0 3 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--text-muted);
    font-size: 0.72rem;
}

.rrp-tabbody[b-ww0nfi2h5q] {
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

/* And the scroller inside it takes the same shape. app.css rounds all four corners of a
   .table-responsive that fills a card body — right for a card that is only a table, wrong under a
   tab strip: it clipped the SOA heading row's top corners, while the week grid's own scroller
   carries no radius and met the edge square. The two tabs were showing the same seam two ways.
   Square where the tabs meet it, rounded at the foot, in both. */
.rrp-tabbody > .card-body.p-0 > .table-responsive[b-ww0nfi2h5q],
.rrp-tabbody > .card-body.p-0 > .rrp-scroll[b-ww0nfi2h5q] {
    border-radius: 0 0 var(--border-radius) var(--border-radius);
}

.nav-tabs .nav-link[b-ww0nfi2h5q] { cursor: pointer; }

/* The SOA table is a plain table, not the week grid — no sticky columns, because sixteen columns
   fit where fifty-two do not. Its numbers line up the way the grid's do. */
.rrp-soa td[b-ww0nfi2h5q],
.rrp-soa th[b-ww0nfi2h5q] { white-space: nowrap; }

.rrp-soa td.text-end[b-ww0nfi2h5q],
.rrp-soa th.text-end[b-ww0nfi2h5q] { font-variant-numeric: tabular-nums; }

.rrp-soa .rrp-detail-input[b-ww0nfi2h5q] { width: 100%; }

/* Product carries no width on purpose — see the colgroup. It is the column that grows. */
.rrp-soa col:not([class])[b-ww0nfi2h5q] { width: auto; }

/* The house style shouts its table headings in small caps. Here that would put the SOA tab in a
   different voice from the week grid beside it, which is quieter — so inside this one table the
   headings read as words, at the grid's own size and weight. */
.rrp-soa > thead th[b-ww0nfi2h5q] {
    text-transform: none;
    letter-spacing: normal;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-secondary);
    background: var(--bg-subtle);
}

/* The same line under the header as the grid draws. */
.rrp-soa > thead[b-ww0nfi2h5q] { border-bottom: 1px solid var(--border-subtle); }

/* Sixteen columns do not fit a laptop, so the table scrolls rather than squeezing the names to
   nothing. Fixed layout, so the four shared columns keep the width the grid gives them. */
/* The sum of the widths below. Stated, because a fixed layout with no total stretches its
   columns to whatever the content wants — which is how this table ended up 30% wider than the
   grid it is supposed to line up with. */
.rrp-soa[b-ww0nfi2h5q] {
    table-layout: fixed;
    width: 100%;
    /* min-width is set inline: it depends on which optional columns are switched on. */
}

/* ── The two perspectives ──
   The same banner and the same tints the full-planning grid uses, because they are the same two
   ideas: what the line does to us, and what it does to the customer. A reader who knows one grid
   should not have to learn the other. */
.rrp-soa .grp-row th[b-ww0nfi2h5q] {
    font-size: 0.72rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-weight: 700;
    padding-top: 2px;
    padding-bottom: 2px;
}

/* The full-planning grids leave this stretch transparent. Here it sits directly opposite the
   week grid's month row, which is tinted — so it takes the same tint, and the banner row reads as
   a header in both tabs rather than as white space in one of them. */
.rrp-soa .grp-blank[b-ww0nfi2h5q] { background: var(--bg-subtle); border-right: 0; }
.rrp-soa .grp-our[b-ww0nfi2h5q] { background: rgba(37, 99, 235, 0.08); color: #1d4ed8; }
.rrp-soa .grp-customer[b-ww0nfi2h5q] { background: rgba(217, 119, 6, 0.10); color: #b45309; }
/* Both banners carry their colour down over the figures they head, at a fraction of the strength
   — enough to say where one perspective ends and the other begins as the eye runs along a row,
   not enough to compete with the numbers. The heading row takes the stronger of the two. */
.rrp-soa th.grp-our-col[b-ww0nfi2h5q] { background: rgba(37, 99, 235, 0.05); }
.rrp-soa td.grp-our-col[b-ww0nfi2h5q] { background: rgba(37, 99, 235, 0.025); }
.rrp-soa th.grp-customer-col[b-ww0nfi2h5q] { background: rgba(217, 119, 6, 0.06); }
.rrp-soa td.grp-customer-col[b-ww0nfi2h5q] { background: rgba(217, 119, 6, 0.03); }

/* The house's compact table sets its cells a size below what the week grid uses, which left the
   two price inputs — styled from the grid — visibly larger than the figures beside them. One size
   for every number on the page. */
.rrp-soa td[b-ww0nfi2h5q] { font-size: 0.875rem; }

.rrp-soa col.rrp-c-sel[b-ww0nfi2h5q]  { width: 30px; }
.rrp-soa col.rrp-c-art[b-ww0nfi2h5q]  { width: 120px; }
.rrp-soa col.rrp-c-cat[b-ww0nfi2h5q]  { width: 120px; }
.rrp-soa .rrp-c-band[b-ww0nfi2h5q]   { width: 160px; }
.rrp-soa .rrp-c-launch[b-ww0nfi2h5q] { width: 112px; }
.rrp-soa .rrp-c-brand[b-ww0nfi2h5q] { width: 110px; }
.rrp-soa .rrp-c-dept[b-ww0nfi2h5q]  { width: 95px; }
.rrp-soa .rrp-c-mark[b-ww0nfi2h5q]  { width: 92px; }
.rrp-soa .rrp-c-num[b-ww0nfi2h5q]   { width: 108px; }

/* Long names give way rather than pushing the numbers off the screen. */
.rrp-soa td[b-ww0nfi2h5q],
.rrp-soa th[b-ww0nfi2h5q] { overflow: hidden; text-overflow: ellipsis; }

/* ── One row height in both tabs ──
   The two tables are built differently — one is the week grid with its own padding, the other the
   house's compact table — and left alone they settle a few pixels apart, which is visible the
   moment you switch between them. Stated once, for both. */
.rrp-soa tbody td[b-ww0nfi2h5q],
.rrp-grid tbody th[b-ww0nfi2h5q],
.rrp-grid tbody td[b-ww0nfi2h5q] {
    height: 30px;
    padding-top: 1px;
    padding-bottom: 1px;
}

.rrp-soa .rrp-marker[b-ww0nfi2h5q],
.rrp-soa .rrp-input[b-ww0nfi2h5q] { padding-top: 1px; padding-bottom: 1px; }

/* The menu now serves two sheets, so it says which one it is offering before it offers it. */
.rrp-menu-head[b-ww0nfi2h5q] {
    padding: .35rem .75rem .15rem;
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-muted);
}

/* ── Assortment planning: the volume under the price ──
   A second line in a cell that is already 66px wide, so it has to earn its room: smaller, quieter,
   and tabular so a column of volumes reads as a column rather than as ragged text. Shown on its
   own it takes the price's place and sits where the price sat, which keeps a row's eye-line
   unchanged when the view is switched. */
.rrp-vol[b-ww0nfi2h5q] {
    padding: 0 4px 2px;
    text-align: right;
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    color: var(--text-secondary);
    white-space: nowrap;
}

/* Under a price it gets a hairline, or the two numbers read as one four-digit figure. */
.rrp-vol-under[b-ww0nfi2h5q] { border-top: 1px dotted var(--border-color); margin-top: 1px; padding-top: 1px; }

/* Who carries the product: the reporting screens' customer mark at row height, overlapping a
   little — four marks and an overflow count have to fit the column, and a strip of separate
   circles would need twice its width. Drawn like the Accounts column on assortment's Products tab,
   so one product reads the same on both screens. */
.rrp-c-accts[b-ww0nfi2h5q] { padding-top: 1px; padding-bottom: 1px; }

.rrp-acct[b-ww0nfi2h5q] {
    display: inline-flex;
    align-items: center;
    border-radius: 12px;
    vertical-align: middle;
}

.rrp-marks[b-ww0nfi2h5q] { display: inline-flex; align-items: center; }

.rrp-mark[b-ww0nfi2h5q] {
    width: 22px;
    height: 22px;
    font-size: 9px;
    border: 2px solid var(--bg-card);
    margin-left: -6px;
}

.rrp-marks > .rrp-mark:first-child[b-ww0nfi2h5q] { margin-left: 0; }

/* The overflow count stands for several accounts rather than any one, so it takes no palette hue. */
.rrp-marks > .isp-mark-others[b-ww0nfi2h5q] {
    background: var(--bg-subtle);
    color: var(--text-muted);
    letter-spacing: 0;
}


/* Not in the range at all, or not carried by the account on screen: the row is still there, but
   nothing in it is about this account. */
.rrp-acct-off[b-ww0nfi2h5q] { opacity: 0.45; }

/* ── Scope bar ──────────────────────────────────────────────────────────────
   Set apart from the filter card below it on purpose: it is the one control on the page that
   changes what the numbers mean rather than which of them are shown. */
.rrp-scope[b-ww0nfi2h5q] { border-left: 3px solid var(--accent); }
.rrp-scope-lbl[b-ww0nfi2h5q] { font-weight: 600; font-size: .85rem; }

/* ── Volumes ──
   A typed volume is a decision and a derived one is an expectation; the grid has to be able to
   say which without a legend. The dot does it in the space a cell has. */
/* BLOCK, and that is the whole of it: the week cells are `white-space: nowrap` so a price and a
   volume as two inline-blocks sat side by side, each asking for the full width of a 66px cell. The
   read-only volume never showed it because a div was already block-level. */
.rrp-vol-input[b-ww0nfi2h5q] {
    display: block;
    width: 100%;
    padding: 0 4px 1px;
    font-size: .72rem;
    color: var(--text-secondary);
    text-align: right;
}
.rrp-vol-typed[b-ww0nfi2h5q] {
    color: var(--text-primary);
    font-weight: 600;
}

/* Some accounts are not on the price the cell shows. Deliberately a marker and not a number —
   there is no average of two prices that a shop could charge. */
.rrp-mix[b-ww0nfi2h5q] {
    position: absolute;
    /* Top LEFT, the one corner a right-aligned number never reaches. Bottom right would have sat
       on the volume in the Both view and on the price in either of the others. */
    left: 2px;
    top: 1px;
    border: 0;
    background: none;
    padding: 0;
    line-height: 1;
    font-size: .5rem;
    color: var(--accent);
    cursor: pointer;
}
.rrp-cell[b-ww0nfi2h5q], td:has(> .rrp-mix)[b-ww0nfi2h5q] { position: relative; }

/* ── Who carries a product ──────────────────────────────────────────────────
   FIXED, not absolute. The pill lives in a sticky column inside a scrolling container, and an
   absolutely positioned list is clipped by it the moment the list is taller than its row. Fixed
   takes the panel out of that entirely; the coordinates come from the pointer. */
.rrp-acctpop[b-ww0nfi2h5q] {
    position: fixed;
    z-index: 1080;
    min-width: 190px;
    max-width: 280px;
    padding: 8px 10px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-card);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    font-size: 0.8rem;
}

.rrp-acctpop-head[b-ww0nfi2h5q] {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 4px;
}

.rrp-acctpop-name[b-ww0nfi2h5q] {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.rrp-acctpop-x[b-ww0nfi2h5q] {
    margin-left: auto;
    border: 0;
    background: none;
    padding: 0 2px;
    line-height: 1;
    font-size: 1rem;
    color: var(--text-secondary);
    cursor: pointer;
}

.rrp-acctpop-note[b-ww0nfi2h5q] {
    color: var(--text-secondary);
    margin-bottom: 4px;
}

/* Long ranges scroll rather than run off the screen — which is the reason the panel can be pinned
   at all, since a pointer cannot reach a scrollbar it has to leave the pill to touch. */
.rrp-acctpop-list[b-ww0nfi2h5q] {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 220px;
    overflow-y: auto;
}

.rrp-acctpop-list li[b-ww0nfi2h5q] {
    padding: 1px 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The account the sheet is currently showing, so the list answers "is this one of them?" without
   the reader comparing two names across the screen. */
.rrp-acctpop-me[b-ww0nfi2h5q] {
    font-weight: 600;
    color: var(--accent);
}

.rrp-acctpop-foot[b-ww0nfi2h5q] {
    margin-top: 6px;
    padding-top: 4px;
    border-top: 1px solid var(--border-subtle);
    font-size: 0.72rem;
    color: var(--text-secondary);
}

/* The marks are something you point at. */
.rrp-acct[b-ww0nfi2h5q] { cursor: pointer; }
.rrp-acct-open[b-ww0nfi2h5q] { outline: 2px solid var(--accent); outline-offset: -1px; }

/* ── Folding the calendar away ───────────────────────────────────────────────
   The header stays a header: the fold is a button only so it can be clicked and
   reached by keyboard, and it inherits the card header's own type rather than
   turning into a link in the middle of one. */
.rrp-fold[b-ww0nfi2h5q] {
    color: inherit;
    font: inherit;
    border: 0;
    background: none;
}

.rrp-fold:hover[b-ww0nfi2h5q] { color: var(--accent); }

.rrp-fold-caret[b-ww0nfi2h5q] {
    display: inline-block;
    width: 1em;
    color: var(--text-muted);
}

/* Support typed for the year: the box, with a marker before it when an exception holds it down. */
.rrp-soa-edit[b-ww0nfi2h5q] { display: flex; align-items: center; gap: .2rem; }
.rrp-soa-edit .rrp-detail-input[b-ww0nfi2h5q] { flex: 1; min-width: 0; }
.rrp-soa-exc[b-ww0nfi2h5q] { color: var(--bs-warning-text-emphasis, #997404); font-size: .7rem; cursor: help; }
/* /Components/Pages/Projections/RrpProductsTab.razor.rz.scp.css */
/* ── The Products tab ───────────────────────────────────────────────────────
   A long flat list, so everything here is in service of reading one line out of twenty thousand:
   the filters stay on screen, the header stays on screen, and the only colour on a row is the one
   that says what still has to happen to it. */

.rrp-prod[b-0lcctkgl1b] {
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

/* ── Filters ──
   One wrapping row rather than a grid. The order is the order somebody narrows in: what, then who,
   then when, then how far along it is. */
.rrp-prod-filters[b-0lcctkgl1b] {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    align-items: center;
    padding: .5rem .75rem;
}

.rrp-prod-weeks[b-0lcctkgl1b] {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
}

.rrp-prod-weeks input[b-0lcctkgl1b] {
    width: 4.5rem;
    text-align: center;
}

/* ── The state strip ──
   Counts that are also the way in. Flat until one is on, so the strip reads as information first
   and controls second — it is right above the list and must not compete with it. */
.rrp-prod-states[b-0lcctkgl1b] {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    padding: .4rem .75rem;
    background: var(--bg-subtle);
}

.rrp-prod-chip[b-0lcctkgl1b] {
    border: 1px solid var(--border-color);
    background: var(--bg-card);
    border-radius: 999px;
    padding: .1rem .7rem;
    font-size: .78rem;
    color: var(--text-secondary, inherit);
    line-height: 1.6;
}

.rrp-prod-chip:hover[b-0lcctkgl1b] { border-color: var(--accent); }

.rrp-prod-chip.on[b-0lcctkgl1b] {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 14%, var(--bg-card));
    font-weight: 600;
}

.rrp-prod-chip-n[b-0lcctkgl1b] {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

/* The same three colours the grid uses, so a price does not change meaning when it changes
   screen: red is still the planner's, amber is still waiting on somebody, settled is still plain. */
.rrp-prod-chip.draft .rrp-prod-chip-n[b-0lcctkgl1b] { color: #c0392b; }
.rrp-prod-chip.sent .rrp-prod-chip-n[b-0lcctkgl1b] { color: #b26a00; }
.rrp-prod-chip.overdue .rrp-prod-chip-n[b-0lcctkgl1b] { color: #c0392b; }

/* ── The action bar ── */
.rrp-prod-actions[b-0lcctkgl1b] {
    display: flex;
    flex-wrap: wrap;
    gap: .75rem;
    align-items: center;
    padding: .45rem .75rem;
}

/* ── The list ──
   A tall scroller with a stuck header: the filters above say what the list is, and scrolling past
   the column names in a table this long leaves every number unlabelled. */
.rrp-prod-scroll[b-0lcctkgl1b] {
    max-height: 64vh;
    overflow: auto;
}

.rrp-prod-table[b-0lcctkgl1b] {
    font-size: .82rem;
}

.rrp-prod-table thead th[b-0lcctkgl1b] {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--bg-subtle);
    border-bottom: 1px solid var(--border-color);
    white-space: nowrap;
    font-weight: 600;
}

.rrp-prod-table td[b-0lcctkgl1b],
.rrp-prod-table th[b-0lcctkgl1b] {
    padding: .25rem .5rem;
}

.rrp-prod-sort[b-0lcctkgl1b] { cursor: pointer; user-select: none; }
.rrp-prod-sort:hover[b-0lcctkgl1b] { color: var(--accent); }

.rrp-prod-tick[b-0lcctkgl1b] { width: 2rem; }

.rrp-prod-art[b-0lcctkgl1b] {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* The product name takes the slack and gives it back when the window is narrow — it is the one
   column that can be cut without losing the line's identity, because the article number is on it. */
.rrp-prod-name[b-0lcctkgl1b] {
    max-width: 22rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Shared versus own, said quietly. Which one a line is matters on every row, so it cannot be a
   badge — twenty thousand badges is a pattern, not a signal. */
.rrp-prod-shared[b-0lcctkgl1b] { color: var(--text-secondary, #6c757d); }

.rrp-prod-own[b-0lcctkgl1b] {
    font-weight: 600;
    box-shadow: inset 2px 0 0 var(--accent);
    padding-left: .4rem;
}

.rrp-prod-state[b-0lcctkgl1b] {
    font-size: .74rem;
    font-weight: 600;
    white-space: nowrap;
}

.rrp-prod-state.draft[b-0lcctkgl1b] { color: #c0392b; }
.rrp-prod-state.sent[b-0lcctkgl1b] { color: #b26a00; }
.rrp-prod-state.ok[b-0lcctkgl1b] { color: var(--text-secondary, #6c757d); font-weight: 400; }

[data-theme="dark"] .rrp-prod-chip.draft .rrp-prod-chip-n[b-0lcctkgl1b],
[data-theme="dark"] .rrp-prod-chip.overdue .rrp-prod-chip-n[b-0lcctkgl1b],
[data-theme="dark"] .rrp-prod-state.draft[b-0lcctkgl1b] { color: #f08a7f; }

[data-theme="dark"] .rrp-prod-chip.sent .rrp-prod-chip-n[b-0lcctkgl1b],
[data-theme="dark"] .rrp-prod-state.sent[b-0lcctkgl1b] { color: #e0a33c; }

/* Support typed on a line — narrow, like the figures around it. */
.rrp-prod-soa[b-0lcctkgl1b] { width: 5.5rem; display: inline-block; padding: 0 .35rem; height: 1.6rem; }

/* A margin exception is in force on this week. */
.rrp-prod-exc[b-0lcctkgl1b] { color: var(--bs-warning-text-emphasis, #997404); font-size: .7rem; margin-right: .25rem; cursor: help; }
/* /Components/Pages/Promoters/PromoterPerformance.razor.rz.scp.css */
/* Multi-select filter dropdown (native <details>; click-away handled globally in app.js).
   Same behaviour as the projection filters — scoped CSS means each page carries its own copy. */
.ms-dd[b-n46rn14a01] {
    position: relative;
}

.ms-dd > summary[b-n46rn14a01] {
    list-style: none;
    cursor: pointer;
    min-width: 9rem;
    white-space: nowrap;
}

.ms-dd > summary[b-n46rn14a01]::-webkit-details-marker {
    display: none;
}

.ms-panel[b-n46rn14a01] {
    position: absolute;
    z-index: 30;
    margin-top: 2px;
    background: var(--bs-body-bg, #fff);
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 8px;
    padding: 8px;
    min-width: 14rem;
    max-height: 320px;
    overflow: auto;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}

.ms-actions[b-n46rn14a01] {
    display: flex;
    align-items: center;
    padding-bottom: 6px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--border-color, #eee);
}

.ms-item[b-n46rn14a01] {
    display: block;
    font-size: 0.85rem;
    padding: 2px 0;
    cursor: pointer;
}

.ms-item input[b-n46rn14a01] {
    margin-right: 6px;
}

/* A folded-out organisation sits under its customer: same columns, quieter ground, so the
   indent reads as "part of the row above" rather than as another customer. */
.sub-row > td[b-n46rn14a01] {
    background-color: color-mix(in srgb, var(--bs-secondary-bg, #e9ecef) 45%, transparent);
    font-size: 0.9375rem;
}

/* ── KPI cards ───────────────────────────────────────────────────────────────
   The same shape the reporting dashboards use — card, tinted icon badge, label,
   value, caption — so a reader moving between them meets one kind of box rather
   than a brown panel here and a white card there.

   Copied rather than shared because these are scoped stylesheets and the block
   already lives in five of them. Lifting all six into app.css is worth doing;
   doing it from inside a promoter ticket would mean re-checking five reporting
   pages for a visual change nobody asked for. */

.soa-kpis[b-n46rn14a01] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 12px;
}

.soa-kpi[b-n46rn14a01] {
    background: var(--bg-card, #fff);
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 14px;
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}

.soa-kpi-top[b-n46rn14a01] {
    display: flex;
    align-items: center;
    gap: 10px;
}

.soa-kpi-icon[b-n46rn14a01] {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--kpi-color, #888) 14%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.soa-kpi-icon svg[b-n46rn14a01] {
    width: 20px;
    height: 20px;
    stroke: var(--kpi-color, #888);
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.soa-kpi-label[b-n46rn14a01] {
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--text-muted, #6c757d);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.soa-kpi-value[b-n46rn14a01] {
    font-size: 1.7rem;
    font-weight: 700;
    line-height: 1.1;
}

.soa-kpi-caption[b-n46rn14a01] {
    font-size: 0.74rem;
    color: var(--text-muted, #6c757d);
}

/* The against-the-others figure, which is the whole point of this page: every box
   above describes stores WITH a promoter, and on its own that is just a number.
   Colour carries the sign and an arrow repeats it, so the meaning survives both
   a monochrome print and a reader who cannot separate the two hues. */
.soa-kpi-delta[b-n46rn14a01] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.82rem;
    font-weight: 600;
}

.soa-kpi-delta.up[b-n46rn14a01] { color: var(--success, #2e9e5b); }
.soa-kpi-delta.down[b-n46rn14a01] { color: var(--danger, #dc4c3e); }
.soa-kpi-delta.flat[b-n46rn14a01] { color: var(--text-muted, #6c757d); }

.soa-kpi-delta svg[b-n46rn14a01] {
    width: 14px;
    height: 14px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* ── Growth pills above the comparison chart ─────────────────────────────────
   Four equal cells over four equal columns, so a pill sits over the pair it
   describes without any of the position maths an in-chart annotation needs —
   and without breaking when the card is narrow or a column has nothing to show.
   The padding matches the plot area's own inset so the cells line up with the
   bars rather than with the card. */
.pp-deltas[b-n46rn14a01] {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    padding: 0 2.6rem 2px 3.2rem;
    text-align: center;
}

.pp-delta[b-n46rn14a01] {
    display: inline-block;
    padding: 1px 9px;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
}

/* Tinted from the theme's own success/danger rather than fixed greens: the card
   behind this is white in one theme and near-black in the other, and a flat
   pastel that reads as "gentle" on white reads as "washed out" on dark. */
.pp-delta.up[b-n46rn14a01] {
    color: var(--success, #2e9e5b);
    background: color-mix(in srgb, var(--success, #2e9e5b) 14%, transparent);
}

.pp-delta.down[b-n46rn14a01] {
    color: var(--danger, #dc4c3e);
    background: color-mix(in srgb, var(--danger, #dc4c3e) 14%, transparent);
}

.pp-delta.flat[b-n46rn14a01] {
    color: var(--text-muted, #6c757d);
    background: color-mix(in srgb, var(--text-muted, #6c757d) 12%, transparent);
}

/* ── The chart's own legend ──
   Apex names every series, and this chart has four of them to draw two groups.
   Its legend is off and this says the same thing in the two entries a reader
   actually needs. */
.pp-legend[b-n46rn14a01] {
    display: inline-flex;
    gap: 14px;
    font-size: 0.78rem;
    color: var(--text-muted, #6c757d);
}

.pp-legend i[b-n46rn14a01] {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    margin-right: 5px;
}

.pp-dot.with[b-n46rn14a01] { background: #2563eb; }
.pp-dot.without[b-n46rn14a01] { background: #94a3b8; }

/* ── Dark mode ───────────────────────────────────────────────────────────────
   --success and --danger are defined once, for the light theme, and not
   redefined for dark — so on a near-black card the green lands around 3:1 and
   small bold text at that contrast is a squint. Lifted here the way the price
   grid lifts its own red and amber, rather than changing the global tokens and
   every badge in the application with them. */
[data-theme="dark"] .pp-delta.up[b-n46rn14a01],
[data-theme="dark"] .soa-kpi-delta.up[b-n46rn14a01] { color: #5fcf8a; }

[data-theme="dark"] .pp-delta.down[b-n46rn14a01],
[data-theme="dark"] .soa-kpi-delta.down[b-n46rn14a01] { color: #f08a7f; }

[data-theme="dark"] .pp-delta.up[b-n46rn14a01] { background: color-mix(in srgb, #5fcf8a 18%, transparent); }
[data-theme="dark"] .pp-delta.down[b-n46rn14a01] { background: color-mix(in srgb, #f08a7f 18%, transparent); }

/* The grid line colour is a light-theme grey baked into the chart options; on
   dark it draws as a near-white rule across the plot. */
[data-theme="dark"] .apexcharts-gridline[b-n46rn14a01] { stroke: #362e24; }

/* ── What the promoter is worth ──────────────────────────────────────────────
   Reads as a sum, because it is one: gain, less cost, equals what is left. Laid
   out as figures rather than bars on purpose — the cost is a couple of percent
   of the gain, so any drawing of the two to scale makes the cost disappear,
   which is exactly the complaint this answers. */
.pp-return[b-n46rn14a01] {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 10px;
    padding: 10px 14px;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-subtle);
}

.pp-return-fig[b-n46rn14a01] {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}

.pp-return-label[b-n46rn14a01] {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--text-muted);
}

.pp-return-value[b-n46rn14a01] {
    font-size: 1.05rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.pp-return-op[b-n46rn14a01] {
    font-size: 1.1rem;
    color: var(--text-muted);
    align-self: flex-end;
    padding-bottom: 2px;
}

/* The ratio is the one number somebody repeats out loud, so it gets the weight. */
.pp-return-ratio[b-n46rn14a01] {
    margin-left: auto;
    padding: 4px 12px;
    border-radius: 999px;
    font-weight: 700;
    color: var(--success, #2e9e5b);
    background: color-mix(in srgb, var(--success, #2e9e5b) 14%, transparent);
    white-space: nowrap;
}

/* Below 1x the promoter costs more than it brings in, which is the finding this
   page exists to make findable. */
.pp-return-ratio.below[b-n46rn14a01] {
    color: var(--danger, #dc4c3e);
    background: color-mix(in srgb, var(--danger, #dc4c3e) 14%, transparent);
}

[data-theme="dark"] .pp-return-ratio[b-n46rn14a01] {
    color: #5fcf8a;
    background: color-mix(in srgb, #5fcf8a 18%, transparent);
}

[data-theme="dark"] .pp-return-ratio.below[b-n46rn14a01] {
    color: #f08a7f;
    background: color-mix(in srgb, #f08a7f 18%, transparent);
}

/* The deduction the fourth column's bars cannot show, under its pill. */
.pp-delta-note[b-n46rn14a01] {
    display: block;
    margin-top: 2px;
    font-size: 0.68rem;
    color: var(--text-muted);
    white-space: nowrap;
}
/* /Components/Pages/Promoters/PromoterSheetDetails.razor.rz.scp.css */
/*
    The grid's number fields drop their spinners.

    Two reasons, and the second is the real one. They are visual clutter in a dense grid, where
    every row carries three of them. And they are now a lie: the arrow keys move between cells —
    see gridNavigation — so the little arrows promise an increment that pressing the arrow keys no
    longer performs. An affordance that does the opposite of what it depicts is worse than none.

    Typing, pasting and the arrows on the field itself all still work; only the rendered buttons go.
*/
.promoter-grid input[type="number"][b-ai9ozsj0yv]::-webkit-outer-spin-button,
.promoter-grid input[type="number"][b-ai9ozsj0yv]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}

.promoter-grid input[type="number"][b-ai9ozsj0yv] {
    -moz-appearance: textfield;
    appearance: textfield;
}
/* /Components/Pages/Sales/ActionSignals.razor.rz.scp.css */
/* Multi-select filter dropdown (native <details>; click-away handled globally in app.js).
   Same behaviour as the projection filters — scoped CSS means each page carries its own copy. */
.ms-dd[b-cuvxeq9y7r] {
    position: relative;
}

.ms-dd > summary[b-cuvxeq9y7r] {
    list-style: none;
    cursor: pointer;
    min-width: 9rem;
    white-space: nowrap;
}

.ms-dd > summary[b-cuvxeq9y7r]::-webkit-details-marker {
    display: none;
}

.ms-panel[b-cuvxeq9y7r] {
    position: absolute;
    z-index: 30;
    margin-top: 2px;
    background: var(--bs-body-bg, #fff);
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 8px;
    padding: 8px;
    min-width: 14rem;
    max-height: 320px;
    overflow: auto;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}

.ms-actions[b-cuvxeq9y7r] {
    display: flex;
    align-items: center;
    padding-bottom: 6px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--border-color, #eee);
}

.ms-item[b-cuvxeq9y7r] {
    display: block;
    font-size: 0.85rem;
    padding: 2px 0;
    cursor: pointer;
}

.ms-item input[b-cuvxeq9y7r] {
    margin-right: 6px;
}

/* A folded-out organisation sits under its customer: same columns, quieter ground, so the
   indent reads as "part of the row above" rather than as another customer. */
.sub-row > td[b-cuvxeq9y7r] {
    background-color: color-mix(in srgb, var(--bs-secondary-bg, #e9ecef) 45%, transparent);
    font-size: 0.9375rem;
}

/* ── Where the signal is concentrated ──────────────────────────────────────
   A ranked bar per category, drawn by hand rather than charted: the list is at
   most eight rows, each needs its name, its bar and its count on one line, and
   a chart library's category axis would cost a second scale to say the same
   thing. The fill takes the signal's own colour so the panel cannot be mistaken
   for the other tab's. */
.cat-bars[b-cuvxeq9y7r] {
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.cat-row[b-cuvxeq9y7r] {
    display: grid;
    grid-template-columns: minmax(110px, 190px) minmax(0, 1fr) 56px;
    align-items: center;
    gap: 10px;
    font-size: .875rem;
}

.cat-name[b-cuvxeq9y7r] {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-align: right;
    color: var(--text-strong);
}

.cat-track[b-cuvxeq9y7r] {
    height: 12px;
    border-radius: 6px;
    background: var(--bg-subtle);
    overflow: hidden;
}

.cat-fill[b-cuvxeq9y7r] {
    display: block;
    height: 100%;
    border-radius: 6px;
}

.cat-lost[b-cuvxeq9y7r] { background: #dc2626; }
.cat-over[b-cuvxeq9y7r] { background: #d97706; }

.cat-value[b-cuvxeq9y7r] {
    font-variant-numeric: tabular-nums;
    color: var(--text-secondary);
}

/* The availability tab has three figures, not four. */
.kpi-row-3[b-cuvxeq9y7r] {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 1200px) {
    .kpi-row-3[b-cuvxeq9y7r] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
    .kpi-row-3[b-cuvxeq9y7r] { grid-template-columns: 1fr; }
    .cat-row[b-cuvxeq9y7r] { grid-template-columns: minmax(90px, 130px) minmax(0, 1fr) 48px; }
}
/* /Components/Pages/Sales/MarketReporting.razor.rz.scp.css */
/* Multi-select filter dropdown (native <details>; click-away handled globally in app.js).
   Same behaviour as the projection filters — scoped CSS means each page carries its own copy. */
.ms-dd[b-9b2tvx0c8t] {
    position: relative;
}

.ms-dd > summary[b-9b2tvx0c8t] {
    list-style: none;
    cursor: pointer;
    min-width: 9rem;
    white-space: nowrap;
}

.ms-dd > summary[b-9b2tvx0c8t]::-webkit-details-marker {
    display: none;
}

.ms-panel[b-9b2tvx0c8t] {
    position: absolute;
    z-index: 30;
    margin-top: 2px;
    background: var(--bs-body-bg, #fff);
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 8px;
    padding: 8px;
    min-width: 14rem;
    max-height: 320px;
    overflow: auto;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}

.ms-actions[b-9b2tvx0c8t] {
    display: flex;
    align-items: center;
    padding-bottom: 6px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--border-color, #eee);
}

.ms-item[b-9b2tvx0c8t] {
    display: block;
    font-size: 0.85rem;
    padding: 2px 0;
    cursor: pointer;
}

.ms-item input[b-9b2tvx0c8t] {
    margin-right: 6px;
}

/* A folded-out organisation sits under its customer: same columns, quieter ground, so the
   indent reads as "part of the row above" rather than as another customer. */
.sub-row > td[b-9b2tvx0c8t] {
    background-color: color-mix(in srgb, var(--bs-secondary-bg, #e9ecef) 45%, transparent);
    font-size: 0.9375rem;
}

/* ── Customer and country marks ────────────────────────────────────────────*/
.mr-cust[b-9b2tvx0c8t] {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

/* Smaller than the mark on the ROI screens: this one sits in a dense table row. */
.mr-mark[b-9b2tvx0c8t] {
    width: 24px; height: 24px;
    font-size: 10px;
}

/* ── Trend ─────────────────────────────────────────────────────────────────*/
.mr-trend[b-9b2tvx0c8t] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px; height: 22px;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 700;
    line-height: 1;
}

.mr-trend-up[b-9b2tvx0c8t]   { color: var(--status-success); background: color-mix(in srgb, var(--success) 18%, transparent); }
.mr-trend-down[b-9b2tvx0c8t] { color: var(--status-danger);  background: color-mix(in srgb, var(--danger) 18%, transparent); }
.mr-trend-flat[b-9b2tvx0c8t] { color: var(--status-warning); background: color-mix(in srgb, var(--warning) 22%, transparent); }

/* ── Country split: ring beside its own numbers ───────────────────────────*/
.mr-split[b-9b2tvx0c8t] {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    align-items: center;
    gap: 12px;
}

.mr-split-chart[b-9b2tvx0c8t] { min-width: 0; }

.mr-country-table[b-9b2tvx0c8t] { font-size: .875rem; }
.mr-country-table thead th[b-9b2tvx0c8t] { border-top: 0; }

.mr-dot[b-9b2tvx0c8t] {
    display: inline-block;
    width: 9px; height: 9px;
    border-radius: 50%;
    margin-right: 8px;
    vertical-align: 1px;
}

/* ── Top selling stores ────────────────────────────────────────────────────
   A ranked list rather than a bar chart, because the position is what the
   panel is for and a category axis cannot carry a rank and a name at once. */
.mr-rank[b-9b2tvx0c8t] {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.mr-rank-row[b-9b2tvx0c8t] {
    display: grid;
    grid-template-columns: 24px minmax(90px, 230px) minmax(0, 1fr) 72px;
    align-items: center;
    gap: 10px;
    font-size: .875rem;
}

.mr-rank-no[b-9b2tvx0c8t] {
    width: 22px; height: 22px;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: 11px;
    font-weight: 700;
    background: var(--bg-subtle);
    color: var(--text-muted);
}

/* The podium is worth seeing from across the room; the rest is a list. */
.mr-rank-top[b-9b2tvx0c8t] {
    background: color-mix(in srgb, var(--warning) 26%, transparent);
    color: var(--status-warning);
}

.mr-rank-name[b-9b2tvx0c8t] {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--text-strong);
}

.mr-rank-track[b-9b2tvx0c8t] {
    height: 10px;
    border-radius: 5px;
    background: var(--bg-subtle);
    overflow: hidden;
}

.mr-rank-bar[b-9b2tvx0c8t] {
    display: block;
    height: 100%;
    border-radius: 5px;
    background: #2563eb;
}

.mr-rank-value[b-9b2tvx0c8t] {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--text-secondary);
}

/* ── Narrow screens ───────────────────────────────────────────────────────
   The KPI row's own breakpoints travelled with it into app.css. */
@media (max-width: 860px) {
    .mr-split[b-9b2tvx0c8t] { grid-template-columns: 1fr; }
    .mr-rank-row[b-9b2tvx0c8t] { grid-template-columns: 22px minmax(0, 1fr) 64px; }
    .mr-rank-track[b-9b2tvx0c8t] { display: none; }
}
/* /Components/Pages/Sales/SellOutPerformance.razor.rz.scp.css */
/* Multi-select filter dropdown (native <details>; click-away handled globally in app.js).
   Scoped CSS means each page carries its own copy — same as Market Reporting. */
.ms-dd[b-d16wr2z2ja] { position: relative; }
.ms-dd > summary[b-d16wr2z2ja] { list-style: none; cursor: pointer; min-width: 9rem; white-space: nowrap; }
.ms-dd > summary[b-d16wr2z2ja]::-webkit-details-marker { display: none; }

.ms-panel[b-d16wr2z2ja] {
    position: absolute;
    z-index: 30;
    margin-top: 2px;
    background: var(--bs-body-bg, #fff);
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 8px;
    padding: 8px;
    min-width: 14rem;
    max-height: 320px;
    overflow: auto;
    box-shadow: 0 6px 16px rgba(0, 0, 0, .12);
}

.ms-actions[b-d16wr2z2ja] {
    display: flex;
    align-items: center;
    padding-bottom: 6px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--border-color, #eee);
}

.ms-item[b-d16wr2z2ja] { display: block; font-size: .85rem; padding: 2px 0; cursor: pointer; }
.ms-item input[b-d16wr2z2ja] { margin-right: 6px; }

/* ── The table ────────────────────────────────────────────────────────────────
   Thirteen columns of numbers. Everything here is in service of keeping a row
   readable across that width: the name column stays put while the rest scrolls,
   and the two period blocks are separated by a rule so the eye can tell which
   half of the table it is in. */
.perf-table[b-d16wr2z2ja] { font-size: .8125rem; border-collapse: separate; border-spacing: 0; }

.perf-table th[b-d16wr2z2ja],
.perf-table td[b-d16wr2z2ja] { vertical-align: middle; white-space: nowrap; }

.perf-table .block-row th[b-d16wr2z2ja],
.perf-table .group-row th[b-d16wr2z2ja],
.perf-table .head-row th[b-d16wr2z2ja] {
    font-size: .6875rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--bs-secondary-color, #6c757d);
    font-weight: 600;
    text-align: center;
    background: var(--bs-tertiary-bg, #f8f9fa);
}

.perf-table .block-row th.block[b-d16wr2z2ja] {
    font-size: .75rem;
    color: var(--bs-body-color);
    border-bottom: 1px solid var(--border-color, #dee2e6);
}

/* ── Telling the two periods apart ─────────────────────────────────────────────
   Thirteen columns of numbers in one typeface is a wall, and the commonest mistake
   a reader can make here is taking a year-to-date figure for this week's. So the
   two blocks are tinted differently and separated by a rule.

   The tint is a background-IMAGE, not a background-colour, on purpose: that leaves
   the colour slot free for whatever the row or the heading already paints, so a
   block tint composes with the heading's own ground and the total row's instead of
   replacing it. Written as flat rgba rather than mixed from a theme token, because
   the tokens here are creams — mixing one into a cream page produced a tint that
   measured as different and looked identical. Weak on purpose: it has to group the
   columns without competing with the red and green that carry the meaning.

   The two tints are cool against warm, and NEITHER is the blue the rings are drawn
   in. This-week used to be tinted with the primary blue itself, which put a blue
   ring on a blue ground in the one column a reader looks at first. Slate separates
   the block just as well and leaves blue to mean "a figure", not "a period". */
.perf-table .cw-col[b-d16wr2z2ja] {
    background-image: linear-gradient(rgba(51, 65, 85, .07), rgba(51, 65, 85, .07));
}

.perf-table .ytd-col[b-d16wr2z2ja] {
    background-image: linear-gradient(rgba(180, 110, 20, .07), rgba(180, 110, 20, .07));
}

[data-theme="dark"] .perf-table .cw-col[b-d16wr2z2ja] {
    background-image: linear-gradient(rgba(148, 178, 222, .09), rgba(148, 178, 222, .09));
}

[data-theme="dark"] .perf-table .ytd-col[b-d16wr2z2ja] {
    background-image: linear-gradient(rgba(232, 180, 92, .08), rgba(232, 180, 92, .08));
}

/* The rule between "this week" and "year to date". The two tables are not the same width — the
   share table carries thirteen columns and the product table nine — so each names its own
   boundary rather than sharing a column number that only happens to line up. */
.share-table th:nth-child(2)[b-d16wr2z2ja],
.share-table td:nth-child(2)[b-d16wr2z2ja],
.share-table th:nth-child(8)[b-d16wr2z2ja],
.share-table td:nth-child(8)[b-d16wr2z2ja] { border-left: 2px solid var(--border-color, #ced4da); }

.product-table th:nth-child(5)[b-d16wr2z2ja],
.product-table td:nth-child(5)[b-d16wr2z2ja],
.product-table th:nth-child(7)[b-d16wr2z2ja],
.product-table td:nth-child(7)[b-d16wr2z2ja] { border-left: 2px solid var(--border-color, #ced4da); }

/* ── The heading, lifted off the rows ──────────────────────────────────────────
   It used to be the same weight and ground as the data under it, so on a long list
   the heading read as the first row. It now sits on its own surface, under a firm
   rule, and stays put while the rows scroll past. */
.perf-table thead th[b-d16wr2z2ja] {
    position: sticky;
    top: 0;
    z-index: 4;
    background-color: #e7e2d9;
}

[data-theme="dark"] .perf-table thead th[b-d16wr2z2ja] { background-color: #2b2521; }

.perf-table thead tr:last-child th[b-d16wr2z2ja] {
    border-bottom: 2px solid var(--bs-secondary-color, #6c757d);
}

.perf-table thead .sticky-name[b-d16wr2z2ja] { z-index: 5; background-color: #e7e2d9; }
[data-theme="dark"] .perf-table thead .sticky-name[b-d16wr2z2ja] { background-color: #2b2521; }

/* ── Sorting ─────────────────────────────────────────────────────────────────── */
.perf-table th.sortable[b-d16wr2z2ja] { cursor: pointer; user-select: none; white-space: nowrap; }
.perf-table th.sortable:hover[b-d16wr2z2ja] { background: var(--bs-secondary-bg, #dee2e6); }

.perf-table th.sorted[b-d16wr2z2ja] { color: var(--bs-body-color); }

.sort-mark[b-d16wr2z2ja] {
    display: inline-block;
    width: .75em;
    margin-left: .15rem;
    font-size: .625rem;
    opacity: .75;
}

.perf-table .num[b-d16wr2z2ja] { text-align: right; }
.perf-table .strong[b-d16wr2z2ja] { font-weight: 600; }
.perf-table .extra[b-d16wr2z2ja] { font-size: .6875rem; line-height: 1.2; }

/* The name column holds still while thirteen columns of numbers scroll past it. */
.perf-table .sticky-name[b-d16wr2z2ja] {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--bs-body-bg, #fff);
    text-align: left;
    min-width: 11rem;
}

.perf-table thead .sticky-name[b-d16wr2z2ja] { z-index: 3; background: var(--bs-tertiary-bg, #f8f9fa); }

.perf-table .total-row td[b-d16wr2z2ja] {
    font-weight: 600;
    background: var(--bs-tertiary-bg, #f1f3f5);
    border-top: 2px solid var(--border-color, #dee2e6);
}

/* ── Bars ─────────────────────────────────────────────────────────────────────
   A number and its bar share a cell: the number is the answer, the bar is the
   comparison, and putting the bar under rather than beside keeps the column
   narrow enough that thirteen of them fit. */
.bar[b-d16wr2z2ja] {
    height: 4px;
    margin-top: 3px;
    border-radius: 2px;
    background: var(--bs-secondary-bg, #e9ecef);
    overflow: hidden;
}

.bar-fill[b-d16wr2z2ja] { height: 100%; border-radius: 2px; background: var(--bs-primary, #0d6efd); }

/* ── Rings ────────────────────────────────────────────────────────────────── */
/* Ring, then figure, both anchored to the right of the cell.
   The figure is given a fixed width and tabular digits so "1%" and "100%" occupy the same space:
   without that the whole group shifts with the width of the number, and the rings wander left and
   right down the column instead of stacking. The coverage badge is ordered FIRST so it grows
   leftward — hanging it off the right-hand end would push the ring out of line on exactly the rows
   that most want comparing. */
.pct[b-d16wr2z2ja] { display: flex; align-items: center; justify-content: flex-end; gap: .35rem; white-space: nowrap; }

.pct .donut[b-d16wr2z2ja] { order: 2; }

.pct > span:not(.partial)[b-d16wr2z2ja] {
    order: 3;
    /* Wide enough for a BOLD "100%", which is what the total row holds — sized for the widest
       figure the column can show, not the widest ordinary one, or the total row's ring sits a
       pixel and a half out of line with every row above it. */
    min-width: 2.6rem;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.pct .partial[b-d16wr2z2ja] { order: 1; }

.donut[b-d16wr2z2ja] { flex: 0 0 auto; }
.donut circle[b-d16wr2z2ja] { fill: none; stroke-width: 5; }

/* The track is mixed from the INK, not set to a colour of its own.
   It used to be --bs-secondary-bg, which resolves to a cream on this theme —
   rgb(243, 236, 227) — and the two column grounds it sits on are creams three and
   ten units away from it. Measured as different, invisible on screen: the ring read
   as a floating arc with no circle behind it, and at 0% as nothing at all.
   A mix of currentColor composites over whatever is behind it, so the track stays a
   fixed step darker than its ground on every one of them — the two column tints, the
   heading's ground, the total row's — and inverts by itself in dark mode, where the
   ink is the cream and the ground is not. */
.donut .donut-track[b-d16wr2z2ja] { stroke: color-mix(in srgb, currentColor 30%, transparent); }
.donut .donut-value[b-d16wr2z2ja] { stroke: var(--bs-primary, #0d6efd); }

/* Last year's ring is quieter than this year's but still has to read against the
   track now sitting behind it, so it is mixed with the ground rather than left
   half-transparent over it. */
.donut.muted .donut-value[b-d16wr2z2ja] { stroke: color-mix(in srgb, var(--bs-primary, #0d6efd) 60%, transparent); }

/* Coverage, shown only when it is not the whole story — see MarginCell. */
.partial[b-d16wr2z2ja] {
    font-size: .625rem;
    padding: 0 .25rem;
    border-radius: 3px;
    background: var(--bs-warning-bg-subtle, #fff3cd);
    color: var(--bs-warning-text-emphasis, #664d03);
    cursor: help;
}

/* ── Change ───────────────────────────────────────────────────────────────── */
.delta[b-d16wr2z2ja] { font-variant-numeric: tabular-nums; }
.delta .arrow[b-d16wr2z2ja] { font-size: .625rem; margin-right: .15rem; }
/* Not the -text-emphasis tokens: in dark mode those are the DARK end of the ramp and all but
   vanish against the dark ground. These two read on both themes. */
.delta.up[b-d16wr2z2ja] { color: #1a9f5a; }
.delta.down[b-d16wr2z2ja] { color: #e05260; }
.delta.flat[b-d16wr2z2ja] { color: var(--bs-secondary-color, #6c757d); }
/* /Components/Shared/BudgetPots.razor.rz.scp.css */
/* ── The three pots ──────────────────────────────────────────────────────────
   COOP, MDF and the two together. Combined is given the same shape rather than
   a bigger one: it is the other two added up, not a more important number. */
.budget-types[b-adxhc2vubv] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 12px;
}

.budget-pot[b-adxhc2vubv] {
    padding: 12px 14px;
    border: 1px solid var(--border-color);
    border-left-width: 3px;
    border-radius: 10px;
    background: var(--bg-card);
}

.budget-pot-coop[b-adxhc2vubv] { border-left-color: var(--accent); }
.budget-pot-mdf[b-adxhc2vubv] { border-left-color: #7c3aed; }
.budget-pot-all[b-adxhc2vubv] { border-left-color: var(--text-muted); }

.budget-pot-head[b-adxhc2vubv] { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }

.budget-pot-title[b-adxhc2vubv] {
    font-size: .76rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
}

.budget-pot-note[b-adxhc2vubv] { font-size: .7rem; color: var(--text-muted); }

.budget-pot-value[b-adxhc2vubv] {
    font-size: 1.3rem;
    font-weight: 700;
    line-height: 1.2;
    margin: 2px 0 6px;
    font-variant-numeric: tabular-nums;
}

.budget-pot-code[b-adxhc2vubv] { font-size: .75rem; font-weight: 400; color: var(--text-muted); }

.budget-pot-split[b-adxhc2vubv] {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    margin-top: 6px;
    font-size: .72rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
/* /Components/Shared/CheckPicker.razor.rz.scp.css */
/* ── A checkbox list with its choices pinned on top ──
   Drawn like the account panel on assortment: a bordered box, a checkbox per line, groups headed
   by their own box. The chips sit above the scrolling list, never inside it, so scrolling cannot
   carry a choice out of sight. */
.ckp[b-6pfhoz5jxf] {
    border: 1px solid var(--border-color);
    border-radius: .5rem;
    padding: .45rem .55rem;
    background: var(--bg-card);
    height: 100%;
}

.ckp-head[b-6pfhoz5jxf] {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: .5rem;
    margin-bottom: .3rem;
}

.ckp-label[b-6pfhoz5jxf] { font-weight: 600; font-size: .85rem; }
.ckp-count[b-6pfhoz5jxf] { font-size: .75rem; color: var(--text-muted); white-space: nowrap; }

.ckp-chips[b-6pfhoz5jxf] {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    margin-bottom: .4rem;
}

.ckp-chip[b-6pfhoz5jxf] {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-size: .75rem;
    padding: .05rem .25rem .05rem .5rem;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
    background: color-mix(in srgb, var(--accent) 10%, var(--bg-card));
}

.ckp-chip .btn-close[b-6pfhoz5jxf] { font-size: .5rem; }

.ckp-search[b-6pfhoz5jxf] { margin-bottom: .35rem; }

.ckp-list[b-6pfhoz5jxf] {
    overflow: auto;
    border-top: 1px solid var(--border-color);
    padding-top: .3rem;
}

.ckp-row[b-6pfhoz5jxf],
.ckp-group[b-6pfhoz5jxf] {
    display: flex;
    align-items: center;
    gap: .45rem;
    cursor: pointer;
    padding: .12rem .1rem;
    font-size: .875rem;
    margin: 0;
}

.ckp-row:hover[b-6pfhoz5jxf] { background: var(--bg-subtle); border-radius: .25rem; }

.ckp-group[b-6pfhoz5jxf] {
    margin-top: .25rem;
    padding-bottom: .2rem;
    border-bottom: 1px solid var(--border-color);
}

.ckp-indent[b-6pfhoz5jxf] { padding-left: 1.1rem; }

.ckp-row input[b-6pfhoz5jxf],
.ckp-group input[b-6pfhoz5jxf] { margin: 0; flex: none; }
/* /Components/Shared/ImagePicker.razor.rz.scp.css */
/* The picture control. A preview, the two ways of setting one, and the shelf of shipped
   pictures — in that order, because the preview is what the reader is checking. */
.imgpick-top[b-w8xpx4kp83] {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.imgpick-preview[b-w8xpx4kp83] {
    width: 76px;
    height: 48px;
    border-radius: 6px;
    border: 1px solid var(--border-color);
    background: var(--bg-subtle);
    overflow: hidden;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.imgpick-preview img[b-w8xpx4kp83] { width: 100%; height: 100%; object-fit: cover; }

.imgpick-empty[b-w8xpx4kp83] {
    font-size: 0.7rem;
    color: var(--text-muted);
}

.imgpick-actions[b-w8xpx4kp83] { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* A shelf rather than a grid: it wraps, and a customer who adds twenty of their own does not get
   a wall of them in the middle of a form. */
.imgpick-shelf[b-w8xpx4kp83] {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
    max-height: 132px;
    overflow-y: auto;
}

.imgpick-tile[b-w8xpx4kp83] {
    width: 58px;
    height: 38px;
    padding: 0;
    border: 1px solid var(--border-color);
    border-radius: 5px;
    overflow: hidden;
    background: none;
    cursor: pointer;
}

.imgpick-tile:hover[b-w8xpx4kp83] { border-color: var(--accent); }
.imgpick-tile:focus-visible[b-w8xpx4kp83] { outline: 2px solid var(--accent); outline-offset: 1px; }
.imgpick-tile img[b-w8xpx4kp83] { width: 100%; height: 100%; object-fit: cover; display: block; }
/* /Components/Shared/MarketingCalendarStrip.razor.rz.scp.css */
/* The year strip. Rows are a label and a track; everything inside a track is positioned as a
   percentage of the year, so an event that starts mid-week starts mid-column. */
.mcal[b-fdqbocubxa] {
    --mcal-label: 150px;
    font-size: 0.78rem;
}

.mcal-head[b-fdqbocubxa],
.mcal-row[b-fdqbocubxa] {
    display: grid;
    grid-template-columns: var(--mcal-label) 1fr;
    align-items: center;
}

.mcal-label[b-fdqbocubxa] {
    display: flex;
    align-items: center;
    gap: 7px;
    padding-right: 10px;
    overflow: hidden;
}

.mcal-dot[b-fdqbocubxa] {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
}

.mcal-band-name[b-fdqbocubxa] {
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mcal-track[b-fdqbocubxa] {
    position: relative;
    height: 34px;
}

/* Double height, to match the projection calendar — but only on a band that has a picture to
   show. 34px gives a picture nothing to be; 68px on a band with no picture is empty rent, and a
   strip of five of them is most of a screen. */
.mcal-row-tall .mcal-track[b-fdqbocubxa] { height: 68px; }

.mcal-head .mcal-track[b-fdqbocubxa] { height: 18px; }
.mcal-weeks .mcal-track[b-fdqbocubxa] { height: 14px; }

.mcal-month[b-fdqbocubxa],
.mcal-week[b-fdqbocubxa] {
    position: absolute;
    top: 0;
    text-align: center;
    color: var(--text-secondary);
    font-size: 0.7rem;
    white-space: nowrap;
    overflow: hidden;
}

.mcal-month[b-fdqbocubxa] {
    font-weight: 600;
    border-left: 1px solid var(--border-color);
}

/* 52 numbers across a laptop screen is about 18px each — small, and only read when hunted for. */
.mcal-week[b-fdqbocubxa] {
    font-size: 0.6rem;
    color: var(--text-muted);
}

/* One rule per week, behind the bars. */
.mcal-rule[b-fdqbocubxa] {
    position: absolute;
    top: 2px;
    bottom: 2px;
    width: 1px;
    background: var(--border-subtle);
}

.mcal-row + .mcal-row[b-fdqbocubxa] { margin-top: 2px; }

.mcal-row .mcal-track[b-fdqbocubxa] {
    background: var(--bg-subtle);
    border-radius: 6px;
}

/* A bar is painted in its band's colour and carries the band's picture at its head — the same
   treatment the projection calendar gives a campaign window, so the two read as one family. */
.mcal-bar[b-fdqbocubxa] {
    position: absolute;
    top: 5px;
    bottom: 5px;
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 0 7px;
    border-radius: 6px;
    background: var(--band);
    color: #fff;
    /* Band colours are chosen by a person and some of them are pale. The shadow costs nothing and
       keeps the label legible on the light ones. */
    text-shadow: 0 1px 2px rgba(0, 0, 0, .45);
    box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
    font-weight: 600;
    overflow: hidden;
    white-space: nowrap;
}

/* ── The picture ──
   Its own layer, with a width in pixels rather than a share of the bar: a block that runs a
   quarter is a very wide box, and covering it scales the picture up until only a slice through
   the middle is left. A panel at the head, the same however long the block runs — the 45% ceiling
   is for blocks too short to give it even that.

   Two gradients do the work. The dark wash keeps white text readable over a photograph of unknown
   brightness; the mask fades the picture out over its last stretch so it settles into the band's
   colour instead of ending on a hard vertical edge. */
.mcal-bar-hasart[b-fdqbocubxa]::before {
    content: "";
    position: absolute;
    top: 0; bottom: 0; left: 0;
    width: min(78px, 45%);
    background-image:
        linear-gradient(90deg, rgba(0,0,0,.45) 0%, rgba(0,0,0,.18) 60%, rgba(0,0,0,.05) 100%),
        var(--art);
    background-size: auto, cover;
    background-position: center, center;
    background-repeat: no-repeat, no-repeat;
    -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 62%, transparent 100%);
            mask-image: linear-gradient(90deg, #000 0%, #000 62%, transparent 100%);
    pointer-events: none;
}

/* Two lines now there is room: what it is, and when. The dates were only in the tooltip before,
   which is no use to someone scanning the year. */
.mcal-bar-label[b-fdqbocubxa] {
    position: relative;   /* above the picture layer */
    z-index: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    line-height: 1.25;
    overflow: hidden;
}

/* Clear of the picture rather than over it — the same measurement, so the two cannot drift. */
.mcal-bar-hasart .mcal-bar-label[b-fdqbocubxa] { padding-left: calc(min(78px, 45%) - 2px); }

/* Too short for two lines: the name is the half worth keeping. */
.mcal-bar-tight .mcal-bar-dates[b-fdqbocubxa] { display: none; }
.mcal-bar-tight .mcal-bar-label[b-fdqbocubxa] { justify-content: center; }

.mcal-bar-dates[b-fdqbocubxa] {
    font-size: 0.66rem;
    font-weight: 500;
    opacity: 0.85;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mcal-bar-name[b-fdqbocubxa] {
    overflow: hidden;
    text-overflow: ellipsis;
}

/* A single day: a diamond on the day itself. A little larger now the rows are. */
.mcal-marker[b-fdqbocubxa] {
    position: absolute;
    top: 50%;
    width: 12px;
    height: 12px;
    margin-left: -6px;
    transform: translateY(-50%) rotate(45deg);
    border-radius: 1px;
}

.mcal-editable .mcal-bar[b-fdqbocubxa],
.mcal-editable .mcal-marker[b-fdqbocubxa] { cursor: pointer; }
.mcal-editable .mcal-row .mcal-track[b-fdqbocubxa] { cursor: copy; }
.mcal-editable .mcal-bar:hover[b-fdqbocubxa] { filter: brightness(1.06); }

/* ── Editing ──────────────────────────────────────────────────────────────
   Grips are inside the bar rather than outside it, so a narrow event is still grabbable in the
   middle to move — an edge handle that overhung would leave nothing to drag on a three-day block. */
.mcal-grip[b-fdqbocubxa] {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 7px;
    cursor: ew-resize;
}

.mcal-grip-l[b-fdqbocubxa] { left: 0; }
.mcal-grip-r[b-fdqbocubxa] { right: 0; }

.mcal-editable .mcal-bar[b-fdqbocubxa] { cursor: grab; touch-action: none; }
.mcal-editable .mcal-marker[b-fdqbocubxa] { cursor: grab; touch-action: none; }
.mcal-editable .mcal-row .mcal-track[b-fdqbocubxa] { cursor: crosshair; touch-action: none; }

.mcal-dragging[b-fdqbocubxa] {
    cursor: grabbing;
    z-index: 5;
    box-shadow: var(--shadow-md);
}

/* The block being dragged out of empty track, before it exists. */
.mcal-ghost[b-fdqbocubxa] {
    position: absolute;
    top: 5px;
    bottom: 5px;
    border-radius: 5px;
    border: 2px dashed var(--accent);
    background: var(--accent-light);
    pointer-events: none;
}

/* The block whose weeks the grid below is lighting up. */
.mcal-selected[b-fdqbocubxa] {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
    z-index: 4;
}
