/*
 * Clair CRM — modern Code Red Safety-themed overrides.
 * Loaded AFTER the legacy sales_styles.css and bootstrap.min.css, so declarations
 * here win when specificity ties.
 *
 * Palette is deliberately limited:
 *   --crs-red       primary brand (alerts, links, primary actions)
 *   --crs-charcoal  secondary surface (navbar, header)
 *   --crs-gray-*    neutral scale for text / backgrounds / borders
 *   success/warn/danger lane for commission status semantics
 */

:root {
    /* brand */
    --crs-red:         #C8102E;
    --crs-red-dark:    #8E0A20;
    --crs-red-light:   #FCE8EC;
    --crs-red-tint:    #F9D6DC;

    /* neutrals */
    --crs-black:       #0D0D0D;
    --crs-charcoal:    #1A1A1A;
    --crs-slate:       #2D2D2D;
    --crs-gray-900:    #212529;
    --crs-gray-700:    #495057;
    --crs-gray-600:    #6C757D;
    --crs-gray-500:    #ADB5BD;
    --crs-gray-400:    #CED4DA;
    --crs-gray-300:    #DEE2E6;
    --crs-gray-200:    #E9ECEF;
    --crs-gray-100:    #F8F9FA;
    --crs-white:       #FFFFFF;

    /* semantic */
    --crs-success:     #2E8B57;
    --crs-success-bg:  #E8F5EE;
    --crs-warning:     #D97706;
    --crs-warning-bg:  #FEF5E7;
    --crs-danger:      #B91C1C;
    --crs-danger-bg:   #FDECEA;
    --crs-info:        #0C63E4;

    /* Money is ink, not a mood.
       Commission amounts were rendered in three different greens across the
       app (#047857 on invoice detail, --rb-green on the Book, #0b7a45 on the
       pipeline) while the Analytics dashboard already printed them in ink --
       so the same figure changed colour depending on which page a rep opened
       it from. Green also reads as "good news", which a commission figure is
       not required to be. Amounts use --crs-money; --crs-success stays for
       actual STATUS (a paid chip, a quota that was hit), which is what a
       colour is for. */
    --crs-money:       var(--crs-charcoal);

    /* typography */
    --crs-font-body:   "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
                       Roboto, "Helvetica Neue", Arial, sans-serif;
    --crs-font-mono:   "JetBrains Mono", "Fira Code", Consolas, Monaco, monospace;

    /* spacing + depth */
    --crs-radius:      6px;
    --crs-radius-lg:   10px;
    --crs-shadow-sm:   0 1px 2px 0 rgba(13, 13, 13, 0.06);
    --crs-shadow-md:   0 4px 14px -2px rgba(13, 13, 13, 0.10);
    --crs-shadow-lg:   0 20px 40px -12px rgba(13, 13, 13, 0.20);

    /* transitions */
    --crs-trans:       0.15s cubic-bezier(0.4, 0, 0.2, 1);

    /* One control height for the whole app. Before this there were four:
       .form-control at 2.3rem, .btn at Bootstrap's ~38px, .btn-sm at ~31px,
       and every Commission Book control at 44px -- so a search box, the
       button beside it, and the same control one page over were three
       different heights. 36px on a pointer; 44px wherever a finger is the
       input device, which is the accessible minimum and why the Book chose
       it in the first place. */
    --crs-control-h:   36px;
}

/* --------------------------------------------------------------------- *
 * Base                                                                   *
 * --------------------------------------------------------------------- */

html, body {
    height: 100%;
    margin: 0;
    padding: 0;
}
@media (max-width: 768px), (pointer: coarse) {
    :root { --crs-control-h: 44px; }
}
body {
    font-family: var(--crs-font-body) !important;
    font-feature-settings: "cv02", "cv03", "cv04", "cv11";
    background-color: var(--crs-gray-100) !important;
    color: var(--crs-gray-900);
    min-width: 0;                          /* sales_styles.css no longer sets 1340px */
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

h1, h2, h3, h4, h5, h6 {
    font-family: var(--crs-font-body);
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--crs-gray-900);
}
h1.dashboard_heading,
h2, h3, h4 {
    text-transform: none !important;
}
h1 { font-size: 1.875rem; font-weight: 700; }
h2 { font-size: 1.5rem; }
h3, .oppty-section-heading { font-size: 1.25rem; }
h4 { font-size: 1.1rem; }

a {
    color: var(--crs-red);
    transition: color var(--crs-trans);
}
a:hover { color: var(--crs-red-dark); text-decoration: none; }

code, pre, .mono { font-family: var(--crs-font-mono); }

/* --------------------------------------------------------------------- *
 * Global top header (`#header` in base.html)                             *
 * --------------------------------------------------------------------- */

/* base.html sets viewport-fit=cover, so the page now paints edge to edge and
   a landscape notch would sit on top of content. The navbar keeps its dark
   background under the notch (that is the point of cover) while its CONTENT
   is inset, and #content is inset the same way so no page ever puts a
   control under the cutout. max() so nothing shrinks below the normal
   padding on a device with no inset. */
#header.navbar {
    background: var(--crs-charcoal) !important;
    color: var(--crs-white);
    padding: max(0.6rem, env(safe-area-inset-top)) max(1.25rem, env(safe-area-inset-right))
             0.6rem max(1.25rem, env(safe-area-inset-left));
    /* One hairline, not a 3px racing stripe. The red band under the navbar
       was the loudest single element on every page and read as 2010s brand
       chrome; red now works as a spot colour (the logo, a primary button,
       the keyline on the headline figure) rather than a rule. */
    border-bottom: 1px solid var(--crs-gray-300);
    box-shadow: var(--crs-shadow-sm);
    position: sticky;
    top: 0;
    z-index: 1000;
    opacity: 1 !important;
    line-height: 1.2;
    flex-wrap: wrap;
    min-height: auto;
}
#header .logo,
#header .navbar-brand {
    font-family: var(--crs-font-body);
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: -0.01em;
    color: var(--crs-white) !important;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0;
    margin-right: 1rem;
}
#header .navbar-brand i { color: var(--crs-red); }
#header .brand-icon {
    width: 28px;
    height: 28px;
    display: inline-block;
    object-fit: contain;
    flex-shrink: 0;
}
@media (max-width: 480px) {
    #header .brand-icon { width: 24px; height: 24px; }
}
#header .navbar-toggler {
    color: var(--crs-white);
    border: 1px solid rgba(255, 255, 255, 0.25);
    padding: 0.3rem 0.55rem;
    background: transparent;
    font-size: 1rem;
    border-radius: var(--crs-radius);
}
#header .navbar-toggler:focus {
    outline: none;
    box-shadow: 0 0 0 0.2rem rgba(200, 16, 46, 0.35);
}
#header .navbar-toggler:hover { background: rgba(255, 255, 255, 0.08); }
#header .navbar-nav .nav-link {
    color: var(--crs-white) !important;
    font-weight: 500;
    padding: 0.4rem 0.85rem !important;
    border-radius: var(--crs-radius);
    transition: all var(--crs-trans);
    display: flex;
    align-items: center;
    gap: 0.3rem;
}
#header .navbar-nav .nav-link:hover,
#header .navbar-nav .nav-link:focus,
#header .navbar-nav .nav-item.show > .nav-link,
#header .navbar-nav .dropdown-toggle[aria-expanded="true"] {
    background: var(--crs-red);
    color: var(--crs-white) !important;
}
#header .navbar-nav .dropdown-toggle::after { margin-left: 0.35rem; }

/* Navbar workspace groups (Sep 16 2026). Team Summary and All Reps read
   as Sales pages while every link sits in one undifferentiated row, so
   the commission destinations now render under a "Commissions" eyebrow
   with a hairline before it. The label is stacked ABOVE the links, not
   beside them, for a reason: a stacked label costs zero horizontal
   space, and the one-row desktop bar (>=1200px, navbar-expand-xl) is
   still tight with five top-level items. The links themselves stay
   exactly one click away -- this is a heading, not a dropdown. */
#header .navbar-nav .nav-group {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
}
#header .navbar-nav .nav-group-label {
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    line-height: 1.2;
    text-transform: uppercase;
    color: var(--crs-gray-500);
    padding: 0 0.85rem 0.15rem;
    white-space: nowrap;
}
#header .navbar-nav .nav-group-links {
    display: flex;
    align-items: center;
    list-style: none;
    margin: 0;
    padding: 0;
}
@media (min-width: 1200px) {
    #header .navbar-nav .nav-group-commissions {
        margin-left: 0.45rem;
        padding-left: 0.55rem;
        margin-right: 0.45rem;
        padding-right: 0.55rem;
        border-left: 1px solid rgba(255, 255, 255, 0.18);
        border-right: 1px solid rgba(255, 255, 255, 0.18);
    }
}
@media (max-width: 1199px) {
    /* Collapsed drawer: the group is a full-width stack with its own
       heading, matching how the other nav items render there. */
    #header .navbar-nav .nav-group { width: 100%; align-items: stretch; }
    #header .navbar-nav .nav-group-links {
        flex-direction: column;
        align-items: stretch;
        width: 100%;
    }
    #header .navbar-nav .nav-group-label {
        padding: 0.6rem 0.9rem 0.2rem;
    }
    /* One continuous panel (browser report 2026-09-17): label and links
       shared no visual container here, so Commissions read as a floating
       heading between unrelated rows. Background + border wrap both, so
       Sales/Proposals above and More/account/Logout below stay clearly
       outside it. overflow:hidden keeps a hovered link's square
       highlight from squaring off past the panel's rounded corners.
       Scoped under body.clair-spacex -- and outspecifying the existing
       dark-theme border-left/right-color override just below in
       spacex-theme.css -- so all four sides land on the same #007AA5,
       not a mismatched pair. */
    body.clair-spacex #header .navbar-nav .nav-group-commissions {
        margin: 0.4rem 0;
        padding-bottom: 0.35rem;
        background: rgba(0, 59, 73, 0.4);
        border: 1px solid #007AA5;
        border-radius: var(--crs-radius);
        overflow: hidden;
    }
    body.clair-spacex #header .navbar-nav .nav-group-commissions .nav-group-links .nav-link {
        padding-left: 1.15rem !important;
    }
}
#header #logout_link { color: var(--crs-white) !important; }
#header #logout_link:hover { background: var(--crs-red); }

/* Logout is a <button type=submit> wrapped in a POST form so Django 5
   accepts it. Strip the native button chrome so it looks identical to
   the surrounding .nav-link anchors. */
#header form#logout-form {
    margin: 0 !important;
    padding: 0 !important;
    display: inline-block !important;
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
}
#header .logout-btn,
#header button#logout_link {
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    appearance: none !important;
    background: transparent !important;
    background-color: transparent !important;
    background-image: none !important;
    border: 0 !important;
    box-shadow: none !important;
    cursor: pointer;
    font: inherit;
    font-weight: 500;
    padding: 0.4rem 0.85rem !important;
    border-radius: var(--crs-radius) !important;
    color: var(--crs-white) !important;
    display: inline-flex !important;
    align-items: center;
    gap: 0.3rem;
    transition: all var(--crs-trans);
    line-height: 1.5;
    min-height: 0;
}
#header .logout-btn:hover,
#header .logout-btn:focus,
#header button#logout_link:hover,
#header button#logout_link:focus {
    background: var(--crs-red) !important;
    background-color: var(--crs-red) !important;
    color: var(--crs-white) !important;
    outline: none !important;
    box-shadow: none !important;
}
#header .logout-btn i { color: var(--crs-white) !important; }
@media (max-width: 1199px) {
    #header form#logout-form { width: 100%; display: block !important; }
    #header .logout-btn,
    #header button#logout_link {
        width: 100%;
        justify-content: flex-start !important;
        text-align: left;
    }
}
#header .dropdown-menu {
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius);
    box-shadow: var(--crs-shadow-lg);
    padding: 0.25rem;
    margin-top: 0.35rem;
}
#header .dropdown-item {
    color: var(--crs-gray-900);
    border-radius: calc(var(--crs-radius) - 2px);
    padding: 0.55rem 0.85rem;
    font-weight: 500;
    transition: background var(--crs-trans);
    display: flex;
    align-items: center;
    gap: 0.45rem;
}
#header .dropdown-item:hover,
#header .dropdown-item:focus {
    background: var(--crs-red-light);
    color: var(--crs-red-dark);
}
#header .dropdown-item i { color: var(--crs-red); margin-right: 0; width: 1.1rem; text-align: center; }

/* Collapsed drawer (<1200px, matching navbar-expand-xl): stack the nav
   under the brand. Covers phones AND the 992-1199 tablet/laptop band
   that used to be squeezed into a one-row layout. */
@media (max-width: 1199px) {
    /* Must keep the safe-area insets: a plain four-side padding here
       cancels them on the only breakpoint where a notch exists, which
       is where viewport-fit=cover has actually put content under it. */
    #header.navbar {
        padding: max(0.55rem, env(safe-area-inset-top)) max(0.9rem, env(safe-area-inset-right))
                 0.55rem max(0.9rem, env(safe-area-inset-left));
    }
    #header .navbar-collapse {
        width: 100%;
        margin-top: 0.55rem;
        padding: 0.4rem;
        background: rgba(255, 255, 255, 0.04);
        border-radius: var(--crs-radius);
    }
    #header .navbar-nav { width: 100%; }
    #header .navbar-nav .nav-item { width: 100%; }
    #header .navbar-nav .nav-link {
        width: 100%;
        justify-content: flex-start;
    }
    #header .navbar-nav .dropdown-menu,
    #header .navbar-nav .dropdown-menu-right {
        /* Stay inside the hamburger drawer — do not fly off-screen as
           dropdown-menu-right (Popper) would on a 390px viewport. */
        position: static !important;
        float: none !important;
        left: auto !important;
        right: auto !important;
        transform: none !important;
        background: var(--crs-white);
        width: 100% !important;
        max-width: 100%;
        border: none;
        margin: 0.2rem 0 0.4rem;
        box-shadow: none;
        padding: 0.2rem 0.4rem;
    }
    #header .brand-text { font-size: 0.95rem; }
    #header .user-name { max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    #header .auth-nav-link,
    #header .status .nav-link {
        min-height: 44px;
        padding: 0.7rem 0.9rem !important;
        display: inline-flex;
        align-items: center;
    }
}
.brand-text-short { display: none; }
@media (max-width: 480px) {
    #header .brand-text-full { display: none; }
    #header .brand-text-short { display: inline; }
}

/* --------------------------------------------------------------------- *
 * Content wrapper                                                        *
 * --------------------------------------------------------------------- */

#content {
    padding: 0;                          /* edge-to-edge; inner pages add their own */
    /* Landscape notch guard — 0 on every device without a cutout, so this
       does not change the desktop or portrait layout at all. */
    padding-left: env(safe-area-inset-left, 0px);
    padding-right: env(safe-area-inset-right, 0px);
    width: 100%;
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    /* No overflow-x here — it creates a sticky scroll context that offsets
       children (e.g. the sidebar-toggle) by `top:` even at scrollY=0. Wide
       tables use .table-responsive wrappers for their own horizontal scroll. */
    min-width: 0;
}
#content > * { width: 100%; }
/* Commissions pages use .container-fluid; restore breathing room around
   their cards/tables since #content itself no longer pads. */
.container-fluid {
    max-width: none !important;
    padding: 1rem 1.5rem !important;
    flex: 1 1 auto;
}
/* /sales/ flex-grid sits flush with the viewport on all sides. */
#content > .flex-grid { padding: 0; }

@media (max-width: 768px) {
    .container-fluid { padding: 0.75rem !important; }
}

/* --------------------------------------------------------------------- *
 * Bootstrap 4 color overrides                                            *
 * --------------------------------------------------------------------- */

.bg-primary {
    background-color: var(--crs-red) !important;
    border-color: var(--crs-red) !important;
}
body .btn-primary {
    background-color: var(--crs-red);
    border-color: var(--crs-red);
}
body .btn-primary:hover, body .btn-primary:focus {
    background-color: var(--crs-red-dark);
    border-color: var(--crs-red-dark);
    box-shadow: 0 0 0 0.2rem rgba(200, 16, 46, 0.25);
}
body .btn-primary:not(:disabled):not(.disabled).active,
body .btn-primary:not(:disabled):not(.disabled):active,
body .show > .btn-primary.dropdown-toggle {
    background-color: var(--crs-red);
    border-color: var(--crs-red);
}
body .btn-outline-primary {
    color: var(--crs-red);
    border-color: var(--crs-red);
}
body .btn-outline-primary:hover, body .btn-outline-primary:focus {
    background-color: var(--crs-red);
    color: var(--crs-white);
    border-color: var(--crs-red);
}
/* Active state on the period toggles (TTM / YTD / Range) — Bootstrap's
   default flips the outline button to its theme primary (blue), which
   clashes with our red branding and washes out the label. Force the
   same red+white pairing as :hover so the selected pill reads as
   "this is the active window". */
body .btn-outline-primary.active,
body .btn-outline-primary:not(:disabled):not(.disabled).active,
body .btn-outline-primary:not(:disabled):not(.disabled):active {
    background-color: var(--crs-red);
    color: var(--crs-white);
    border-color: var(--crs-red);
    box-shadow: none;
}
body .btn-outline-secondary {
    color: var(--crs-gray-700);
    border-color: var(--crs-gray-400);
}
body .btn-outline-secondary:hover,
body .btn-outline-secondary.active,
body .btn-outline-secondary:not(:disabled):not(.disabled).active,
body .btn-outline-secondary:not(:disabled):not(.disabled):active {
    background-color: var(--crs-charcoal);
    border-color: var(--crs-charcoal);
    color: var(--crs-white);
}
.text-primary { color: var(--crs-red) !important; }

/* buttons — generic modernization */
.btn {
    min-height: var(--crs-control-h);
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--crs-radius);
    font-weight: 500;
    transition: all var(--crs-trans);
    letter-spacing: 0;
}
.btn-sm { padding: 0.3rem 0.65rem; font-size: 0.8125rem; }
.btn-group > .btn.active {
    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.08);
}

/* --------------------------------------------------------------------- *
 * Cards (commissions KPI cards, etc.)                                    *
 * --------------------------------------------------------------------- */

.card {
    border: 1px solid var(--crs-gray-300) !important;
    border-radius: var(--crs-radius-lg) !important;
    box-shadow: var(--crs-shadow-sm);
    transition: transform var(--crs-trans), box-shadow var(--crs-trans);
    background: var(--crs-white);
}
/* No hover lift. Cards that grow a shadow on mouse-over suggest they are
   clickable, and most of these are not -- they are just panels. Shadow is
   reserved for things that genuinely float: menus and modals. */
.card-body {
    padding: 1rem 1.25rem;
}
.card .small.text-muted {
    color: var(--crs-gray-600) !important;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.7rem;
    margin-bottom: 0.25rem;
}
.card h4, .card h5 {
    font-weight: 700;
    margin-bottom: 0.1rem;
    color: var(--crs-gray-900);
}

/* --------------------------------------------------------------------- *
 * Tables                                                                 *
 * --------------------------------------------------------------------- */

.table {
    color: var(--crs-gray-900);
    background: var(--crs-white);
    border-radius: var(--crs-radius-lg);
    overflow: hidden;
    box-shadow: var(--crs-shadow-sm);
    border-collapse: separate;
    border-spacing: 0;
}
.table thead.thead-dark th,
.table thead th {
    background-color: var(--crs-charcoal) !important;
    color: var(--crs-white) !important;
    border: none !important;
    font-weight: 600;
    font-size: 0.82rem;
    letter-spacing: 0.025em;
    text-transform: uppercase;
    padding: 0.6rem 0.8rem;
    border-bottom: 2px solid var(--crs-red) !important;
    white-space: nowrap;
}
.table td, .table th {
    border-top: 1px solid var(--crs-gray-200);
    padding: 0.5rem 0.8rem;
    vertical-align: middle;
}
/* ---------------------------------------------------------------------
   .clair-table -- the shared table look, used by BOTH apps.

   Commissions reached this look first (commission_layout.css's
   .cv3-rg-table, September 2026); Sales was still raw Bootstrap, which
   the .table rules above paint charcoal with !important. Measured on
   production 2026-09-10: Sales headers near-black at 12.5px over 14.4px
   body text, Commissions white at 15px over 12px -- the same app, two
   table designs.

   This lives in clair_theme.css on purpose: commission_layout.css does
   not load on Sales pages, so the style had to come from the sheet both
   apps share, and it is written against the canonical --crs-* palette
   rather than the --cv3-* aliases.

   A table using this must NOT also carry Bootstrap's `table` class --
   `.table thead th` above is charcoal with !important and would win. See
   the memory note "clair_theme forces .table headers dark".
   --------------------------------------------------------------------- */
.clair-table {
    width: 100%;
    margin-bottom: 0;
    border-collapse: collapse;
    background: var(--crs-white);
    color: var(--crs-charcoal);
    font-size: 12px;
}
.clair-table thead th {
    background: var(--crs-white);
    color: var(--crs-gray-700);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-align: left;
    padding: 8px 14px 6px;
    vertical-align: bottom;
    /* The charcoal underline is what separates the header from the body
       once the header itself is white. */
    box-shadow: inset 0 -2px 0 var(--crs-charcoal);
    border: none;
    border-right: 1px solid var(--crs-gray-200);
    white-space: nowrap;
}
.clair-table thead th:last-child { border-right: none; }
.clair-table tbody td,
.clair-table tbody th {
    padding: 7px 14px;
    vertical-align: middle;
    border: none;
    border-bottom: 1px solid var(--crs-gray-200);
}
.clair-table tbody tr:last-child td { border-bottom: none; }
.clair-table tbody tr:hover { background: var(--crs-gray-100); }
/* Money and counts line up on the decimal, as they do on the commission
   grids. Opt in per cell with .clair-num. */
.clair-table .clair-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
/* State rows. Bootstrap's .table-active / -warning / -danger are styled
   above only under `.table`, which a .clair-table deliberately does not
   carry -- so without these the Forecasting totals bands would have lost
   their highlight when the table moved over. Same colours as the .table
   versions so a reader sees no change in meaning. */
.clair-table .table-active,
.clair-table tr.table-active {
    background-color: var(--crs-gray-200);
    font-weight: 600;
}
.clair-table .table-warning,
.clair-table tr.table-warning { background-color: var(--crs-warning-bg); }
.clair-table .table-danger,
.clair-table tr.table-danger { background-color: var(--crs-danger-bg); }
/* A state row keeps its colour on hover -- the hover tint would otherwise
   read as "this row is selected" over a totals band. */
.clair-table tbody tr.table-active:hover { background: var(--crs-gray-200); }

/* DataTables paints its own sort arrows into the header; keep room for
   them without the label colliding. */
.clair-table thead th.sorting,
.clair-table thead th.sorting_asc,
.clair-table thead th.sorting_desc { padding-right: 26px; }

.table.table-striped tbody tr:nth-of-type(odd) {
    background-color: var(--crs-gray-100);
}
.table tbody tr:hover {
    background-color: var(--crs-red-light) !important;
}
.table .table-active, .table tr.table-active {
    background-color: var(--crs-gray-200) !important;
    font-weight: 600;
}
.table .table-warning, .table tr.table-warning {
    background-color: var(--crs-warning-bg) !important;
}
.table .table-danger, .table tr.table-danger {
    background-color: var(--crs-danger-bg) !important;
}

.table a {
    color: var(--crs-red);
    font-weight: 500;
    border-bottom: 1px dashed transparent;
    transition: border-color var(--crs-trans);
}
.table a:hover {
    border-bottom-color: var(--crs-red);
}

/* DataTables polish (v2 class names: dt-container / dt-length / dt-search / dt-paging).
   Pagination selectors cover both the Bootstrap-4 integration markup (.page-item /
   .page-link / .active) and DataTables' own button class (.dt-paging-button). */
.dt-container { margin-top: 0.5rem; }
.dt-container .dt-length select,
.dt-container .dt-search input {
    border: 1px solid var(--crs-gray-400);
    border-radius: var(--crs-radius);
    padding: 0.25rem 0.6rem;
    font-size: 0.875rem;
}
.dt-container .dt-paging .dt-paging-button,
.dt-container .dt-paging .page-link {
    border-radius: var(--crs-radius) !important;
    color: var(--crs-gray-700) !important;
    border: 1px solid transparent;
    transition: all var(--crs-trans);
}
.dt-container .dt-paging .dt-paging-button.current,
.dt-container .dt-paging .dt-paging-button.current:hover,
.dt-container .dt-paging .page-item.active .page-link {
    background: var(--crs-red) !important;
    border-color: var(--crs-red) !important;
    color: var(--crs-white) !important;
}
.dt-container .dt-paging .dt-paging-button:hover,
.dt-container .dt-paging .page-item:not(.active) .page-link:hover {
    background: var(--crs-red-light) !important;
    border-color: var(--crs-red-tint) !important;
    color: var(--crs-red-dark) !important;
}

/* --------------------------------------------------------------------- *
 * Badges                                                                 *
 * --------------------------------------------------------------------- */

.badge {
    padding: 0.3em 0.55em;
    border-radius: 999px;
    font-weight: 600;
    letter-spacing: 0.02em;
    font-size: 0.72rem;
}
.badge-warning {
    background-color: var(--crs-warning-bg) !important;
    color: #9A5604 !important;
    border: 1px solid var(--crs-warning);
}
.badge-danger {
    background-color: var(--crs-danger-bg) !important;
    color: var(--crs-danger) !important;
    border: 1px solid var(--crs-danger);
}
.badge-info {
    background-color: #E8F1FE !important;
    color: var(--crs-info) !important;
    border: 1px solid var(--crs-info);
}
.badge-success {
    background-color: var(--crs-success-bg) !important;
    color: #236B43 !important;
    border: 1px solid var(--crs-success);
}

/* --------------------------------------------------------------------- *
 * Alerts                                                                 *
 * --------------------------------------------------------------------- */

.alert {
    border: 1px solid transparent;
    border-radius: var(--crs-radius);
    padding: 0.75rem 1rem;
    font-weight: 500;
}
.alert-warning {
    background: var(--crs-warning-bg);
    color: var(--crs-warning);
    border-color: var(--crs-warning);
}

/* --------------------------------------------------------------------- *
 * Forms                                                                  *
 * --------------------------------------------------------------------- */

.form-control, select.form-control, input.form-control {
    border: 1px solid var(--crs-gray-400);
    border-radius: var(--crs-radius);
    padding: 0.45rem 0.75rem;
    transition: border-color var(--crs-trans), box-shadow var(--crs-trans);
}
.form-control:focus {
    border-color: var(--crs-red);
    box-shadow: 0 0 0 0.2rem rgba(200, 16, 46, 0.15);
    outline: none;
}

/* --------------------------------------------------------------------- *
 * Commission dashboard fine-tuning                                       *
 * --------------------------------------------------------------------- */

.container-fluid {
    background: transparent;
}

/* KPI cards — make the headline number pop */
.row.mb-4 .card h4 {
    font-size: 1.4rem;
    color: var(--crs-gray-900);
    font-variant-numeric: tabular-nums;
}
.row.mb-4 .card .small {
    font-variant-numeric: tabular-nums;
    color: var(--crs-gray-600);
}

/* Period selector + filter button groups get a subtle card treatment */
form.form-inline {
    background: var(--crs-white);
    padding: 0.5rem 0.85rem;
    border-radius: var(--crs-radius);
    border: 1px solid var(--crs-gray-300);
    box-shadow: var(--crs-shadow-sm);
    display: inline-flex !important;
    align-items: center;
    gap: 0.5rem;
}
form.form-inline label { margin-bottom: 0 !important; }

/* h2 / h4 section headers get a subtle red underline accent */
.container-fluid h4 {
    border-bottom: 2px solid var(--crs-red);
    padding-bottom: 0.35rem;
    display: inline-block;
}

/* --------------------------------------------------------------------- *
 * Legacy /sales/ dashboard — sidebar + smrytats + login                  *
 * Overrides the teal/pink palette in sales_styles.css.                   *
 * --------------------------------------------------------------------- */

/* Sidebar: charcoal instead of teal */
.sidebar {
    background-color: var(--crs-charcoal) !important;
    color: var(--crs-white);
    padding: 1.25rem 0.75rem !important;
}
.sidebar hr {
    border-color: rgba(255, 255, 255, 0.12);
    margin: 1rem 0;
}
.sidebar #teamscore {
    color: var(--crs-white);
    font-weight: 600;
    text-align: center;
    padding: 0.5rem;
}

/* Sentiment buttons (thumbs up / meh / thumbs down) */
.flex-sentiment {
    display: flex;
    justify-content: center;
    gap: 0.5rem;
}
.sentiment {
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: var(--crs-radius);
    padding: 0.45rem 0.75rem;
    color: var(--crs-white);
    cursor: pointer;
    transition: all var(--crs-trans);
}
.sentiment:hover {
    background: var(--crs-red);
    border-color: var(--crs-red);
    transform: translateY(-1px);
}

/* Sidebar navigation links */
a.sidebar_link {
    display: block;
    background-color: transparent !important;
    color: var(--crs-white) !important;
    padding: 0.65rem 1rem !important;
    border-radius: var(--crs-radius);
    box-shadow: none !important;
    text-transform: none !important;
    font-weight: 500;
    transition: all var(--crs-trans);
    border-left: 3px solid transparent;
    margin-bottom: 2px;
}
a.sidebar_link i { color: var(--crs-red); margin-right: 0.5rem; }
a.sidebar_link:hover {
    background-color: rgba(200, 16, 46, 0.18) !important;
    border-left-color: var(--crs-red);
    color: var(--crs-white) !important;
    cursor: pointer;
    top: 0 !important;
}
a.sidebar_link:active {
    box-shadow: none !important;
    top: 0 !important;
    background-color: var(--crs-red) !important;
}
.sidebar ul { list-style: none; padding-left: 0; }
.sidebar li { margin-bottom: 2px; }

/* Summary stat cards (total open, total weighted, total number) */
.smry_stats > div {
    background-color: var(--crs-white) !important;
    border-radius: var(--crs-radius-lg);
    border: 1px solid var(--crs-gray-300);
    box-shadow: var(--crs-shadow-sm);
    padding: 0.75rem !important;
    transition: all var(--crs-trans);
}
.smry_stats > div:hover {
    box-shadow: var(--crs-shadow-md);
    transform: translateY(-1px);
}
.stats_amount {
    color: var(--crs-red);
    font-weight: 700 !important;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
}

/* Dashboard heading */
h1.dashboard_heading {
    text-transform: none !important;
    font-weight: 700;
    color: var(--crs-gray-900);
    font-size: 1.5rem;
    margin-bottom: 0.75rem;
}
h1.dashboard_heading::after {
    content: '';
    display: block;
    width: 3rem;
    height: 3px;
    background: var(--crs-red);
    margin-top: 0.4rem;
    border-radius: 3px;
}

/* Rep name filter indicator (executive view) */
.rep-name {
    background: var(--crs-red-light);
    color: var(--crs-red-dark);
    border-radius: var(--crs-radius);
    padding: 0.3rem 0.7rem;
    font-weight: 600;
    display: inline-block;
}

/* Login form. Capped at 440px wide so it doesn't stretch across the
   viewport on desktop. width:min() means it shrinks gracefully on
   smaller screens while keeping a 1rem gutter from the edges. The
   existing mobile media-query block further down sets width:100% +
   smaller padding for true mobile widths. */
#login_form {
    background: var(--crs-white);
    padding: 2rem 2.5rem 1.5rem;
    width: min(440px, calc(100vw - 2rem));
    max-width: 440px;
    border-radius: var(--crs-radius-lg);
    box-shadow: var(--crs-shadow-lg);
    color: var(--crs-gray-900) !important;
    min-width: 0;                      /* never force 320px — overflows a 375px phone */
    position: relative !important;     /* override sales_styles absolute + translate */
    top: auto !important;
    left: auto !important;
    transform: none !important;
    margin: 0 auto;
}
#login_form .login_btn,
#login_form .btn-lg {
    width: 100%;
    min-height: 48px;
    font-size: 1.05rem !important;
}
#login_form .form-control,
#login_form input[type=text],
#login_form input[type=email],
#login_form input[type=password] {
    font-size: 16px !important;        /* iOS will zoom if this is <16px */
    min-height: 44px;
}
#login_form.card { border: 0; }
#login_form .auth-footer { margin-top: 0.75rem; }
#login_form .auth-footer-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0.5rem 0;
    font-weight: 500;
}
/* Collaborator multi-select: shorter than size=8, still tall enough to tap. */
select.collaborator-select {
    min-height: 6.5rem;
    width: 100%;
}

/* Sticky save/cancel on phones — sits above the iOS home indicator. */
@media (max-width: 767.98px) {
    .form-sticky-actions {
        position: sticky;
        bottom: 0;
        z-index: 40;
        background: var(--crs-white);
        padding: 0.75rem 0.25rem;
        padding-bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px));
        border-top: 1px solid var(--crs-gray-300);
        box-shadow: 0 -6px 16px rgba(13, 13, 13, 0.08);
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
    }
    /* Long sales forms: never pin Create/Update over Amount. */
    .form-end-actions,
    .grid-new-oppty .form-sticky-actions,
    .edit-oppty-submit-wrap,
    .main_content form .form-end-actions {
        position: static !important;
        bottom: auto !important;
        box-shadow: none;
        border-top: 0;
        background: transparent;
    }
    .form-sticky-actions .login_btn,
    .form-sticky-actions .btn {
        flex: 1 1 auto;
        min-height: 44px;
        width: auto !important;
    }
    /* Thead column filters are unusable in a 390px scroll-head — hide
       them and use the .clair-filters-collapse panel the shared script
       injects above the table. */
    tr.dt-filter-row { display: none !important; }
}

/* Filters collapse is phone-only; desktop keeps the thead filter row. */
@media (min-width: 768px) {
    .clair-filters-collapse { display: none !important; }
}
/* Profile / password-change pages put #login_form as a direct #content child.
   `#content > * { width: 100% }` is more specific than `#login_form`, so
   re-assert the card width here. */
#content > #login_form {
    width: min(440px, calc(100vw - 2rem));
    margin: 2rem auto;
}
.image-codered-login,
.image-codered-logout {
    min-height: calc(100vh - 64px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem 1rem;
}
@media (max-width: 767.98px) {
    /* P2: skip the heavy full-bleed photo on phones — solid/gradient is
       cheaper and keeps the card readable when the keyboard is up. */
    .image-codered-login,
    .image-codered-logout {
        background-image: none;
        background: linear-gradient(180deg, #8E0A20 0%, #1A1A1A 72%);
    }
}
#login_form h1, #login_form h2, #login_form label {
    color: var(--crs-gray-900) !important;
}
/* sales_styles.css forces #hint_id_new_password1 { color:white } and
   #login_form { color:white } from the old full-bleed login photo.
   Confirmation help is already muted; make New password match. */
#login_form .help-block,
#login_form .form-text,
#login_form small,
#login_form #hint_id_new_password1,
#login_form #hint_id_new_password2,
#hint_id_new_password1,
#hint_id_new_password2 {
    color: var(--crs-gray-600, #6c757d) !important;
}
#login_form .login_btn {
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
    margin-left: 0;
    margin-right: 0;
}
.login_btn {
    background-color: var(--crs-red) !important;
    border: 2px solid var(--crs-red) !important;
    color: var(--crs-white) !important;
    border-radius: var(--crs-radius) !important;
    text-transform: none !important;
    font-weight: 600 !important;
    padding: 0.5rem 1.2rem !important;
    transition: all var(--crs-trans);
}
.login_btn:hover, .login_btn:focus {
    background-color: var(--crs-red-dark) !important;
    border-color: var(--crs-red-dark) !important;
    box-shadow: 0 0 0 0.2rem rgba(200, 16, 46, 0.25) !important;
    color: var(--crs-white) !important;
}

/* Generic form-control — legacy CSS strips borders; add them back */
.form-control {
    border: 1px solid var(--crs-gray-400) !important;
    border-radius: var(--crs-radius) !important;
    background: var(--crs-white) !important;
    color: var(--crs-gray-900) !important;
    min-height: var(--crs-control-h) !important;
    padding: 0.4rem 0.7rem !important;
}

/* Grid layout — page background neutral gray, fill available height
   below the header. The flex-grid used to be height:100vh which caused
   a double scrollbar because the header is sticky on top. */
.flex-grid, .main_content {
    background-color: var(--crs-gray-100) !important;
}
.flex-grid {
    height: auto !important;
    min-height: calc(100vh - 64px);   /* header is ~64px tall */
    width: 100%;
    grid-template-columns: minmax(230px, 260px) 1fr !important;
    grid-template-areas: 'sidebar main_content' !important;
    grid-gap: 0 !important;
}
.flex-grid > .sidebar { grid-area: sidebar; }
.flex-grid > .main_content { grid-area: main_content; }
.main_content {
    padding: 1.25rem !important;
    min-height: 100%;
    min-width: 0;                      /* lets children shrink inside grid */
}

/* Mobile sidebar drawer toggle (shows only on small screens). Reported
   as not reading as tappable -- a flush charcoal bar with a small icon
   font glyph gave no button affordance. Now a visible teal (Paradigm
   blue) border on the whole bar, a bordered icon chip (inline SVG, not
   an icon-font glyph, so it always renders), and a chevron that flips
   with aria-expanded instead of relying on the icon alone to read as
   "open". */
.sidebar-toggle {
    display: none;
    position: sticky;
    top: 0;
    z-index: 900;
    width: 100%;
    min-height: 44px;
    padding: 0.5rem 1rem;
    background: var(--crs-charcoal);
    color: var(--crs-white);
    border: none;
    border-bottom: 1px solid #007AA5;
    text-align: left;
    font-weight: 600;
    letter-spacing: 0.02em;
    cursor: pointer;
    align-items: center;
    gap: 0.6rem;
    /* Auto-hide-on-scroll transition (mobile) */
    transform: translateY(0);
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.15s ease;
    will-change: transform;
}
.sidebar-toggle.is-hidden { transform: translateY(-110%); }
.sidebar-toggle:hover,
.sidebar-toggle:active { background: #003b49; }
.sidebar-toggle-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border: 1px solid #8bcad8;
    border-radius: var(--crs-radius);
    color: #8bcad8;
    background: rgba(139, 202, 216, 0.12);
}
.sidebar-toggle-chevron {
    margin-left: auto;
    flex: 0 0 auto;
    color: #8bcad8;
    transition: transform 0.2s ease;
}
.sidebar-toggle[aria-expanded="true"] .sidebar-toggle-chevron { transform: rotate(180deg); }
.sidebar-toggle:focus { outline: none; box-shadow: 0 0 0 0.2rem rgba(0, 122, 165, 0.4); }

@media (max-width: 991.98px) {
    /* Only sales pages that use .flex-grid get the drawer toggle.
       Commission pages share base.html and must not show an empty bar. */
    body:has(.flex-grid) .sidebar-toggle { display: flex; }
    .flex-grid {
        grid-template-columns: 1fr !important;
        grid-template-areas: 'main_content' !important;
    }
    .flex-grid > .sidebar { display: none; }
    .flex-grid.sidebar-open {
        grid-template-columns: 1fr !important;
        grid-template-areas: 'sidebar' 'main_content' !important;
    }
    .flex-grid.sidebar-open > .sidebar {
        display: block;
        grid-area: sidebar;
        padding: 1rem 0.85rem !important;
    }
    .main_content { padding: 0.9rem !important; }
    .sidebar .btn-group .dropdown-menu {
        position: static !important;
        transform: none !important;
        width: 100%;
    }
}

/* Tables inside /sales/ dashboards */
#table_id {
    background-color: var(--crs-white);
    border-radius: var(--crs-radius-lg);
    overflow: hidden;
    box-shadow: var(--crs-shadow-sm);
    border: 1px solid var(--crs-gray-300);
}

/* FAQ row: download link + staff edit on one line.
   Mobile base.html sets `.d-flex { flex-wrap: wrap }` and sales_styles
   forces `a.sidebar_link` / `.btn` to width:100%, which dropped the
   pencil under the label. Dedicated row class avoids that wrap. */
.sidebar-faq-row {
    display: flex;
    flex-wrap: nowrap !important;
    align-items: center;
}
.sidebar-faq-row > a.sidebar_link {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
}
.faq-edit-button {
    flex: 0 0 auto;
    width: auto !important;
    min-width: 44px;
    align-self: center;
    color: var(--crs-white) !important;
    opacity: 0.7;
    transition: opacity var(--crs-trans);
}
.faq-edit-button:hover { opacity: 1; color: var(--crs-red) !important; }

/* --------------------------------------------------------------------- *
 * Sidebar filter dropdowns (Company / Sales Rep)                         *
 * --------------------------------------------------------------------- */

.sidebar form {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0 0.25rem;
    margin-top: 0.5rem;
}
.sidebar .btn-group {
    width: 100%;
    display: block;
}
.sidebar .btn-group > .dropdown-toggle {
    background: rgba(255, 255, 255, 0.06) !important;
    border: 1px solid rgba(255, 255, 255, 0.18) !important;
    color: var(--crs-white) !important;
    font-weight: 500;
    border-radius: var(--crs-radius) !important;
    padding: 0.55rem 0.85rem;
    /* !important: base.html's own mobile-only (<=768px) rule
       `.btn-group > .btn { width: auto !important; }` (meant for
       in-table/toolbar button rows) also matches this toggle -- it is a
       `.btn` inside a `.btn-group` too -- and !important beats this
       selector's higher specificity regardless of load order. Without
       it, all three sidebar triggers shrink to their own text width on
       a phone instead of matching the rail. */
    width: 100% !important;
    text-align: left;
    display: flex;
    align-items: center;
    justify-content: space-between;
    transition: all var(--crs-trans);
    box-shadow: none !important;
}
.sidebar .btn-group > .dropdown-toggle::before {
    content: '\f0b1';          /* far fa-id-badge — consistent icon */
    font-family: 'Font Awesome 5 Free';
    font-weight: 900;
    color: var(--crs-red);
    margin-right: 0.55rem;
    font-size: 0.85rem;
}
.sidebar .btn-group > .dropdown-toggle::after {
    color: var(--crs-gray-400);
    margin-left: auto;
}
.sidebar .btn-group > .dropdown-toggle:hover,
.sidebar .btn-group > .dropdown-toggle:focus,
.sidebar .btn-group > .dropdown-toggle[aria-expanded="true"] {
    background: rgba(200, 16, 46, 0.2) !important;
    border-color: var(--crs-red) !important;
    color: var(--crs-white) !important;
}
.sidebar .btn-group > .dropdown-toggle[aria-expanded="true"]::after {
    transform: rotate(180deg);
}

/* Dropdown menu itself (pops out to the right of the sidebar) */
.sidebar .btn-group .dropdown-menu {
    background: var(--crs-white);
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius-lg) !important;
    box-shadow: var(--crs-shadow-lg);
    padding: 0.3rem;
    min-width: 14rem;
    max-height: 60vh;
    overflow-y: auto;
}
/* .dropup is toggled by JS (base.html) when there isn't room below the
   button. The CDN's Bootstrap build only flips top/bottom under a
   .navbar-expand ancestor, so this sidebar case needs its own rule. */
.sidebar .btn-group.dropup .dropdown-menu {
    top: auto;
    bottom: 100%;
}
.sidebar .btn-group .dropdown-menu .dropdown-item {
    color: var(--crs-gray-900);
    border-radius: calc(var(--crs-radius) - 2px);
    padding: 0.5rem 0.75rem;
    font-weight: 500;
    font-size: 0.875rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    transition: background var(--crs-trans);
}
.sidebar .btn-group .dropdown-menu .dropdown-item i {
    color: var(--crs-red);
    width: 1rem;
    text-align: center;
}
.sidebar .btn-group .dropdown-menu .dropdown-item:hover {
    background: var(--crs-red-light);
    color: var(--crs-red-dark);
}
/* "Pinned" items (All, Mine) sit above the per-rep/per-company list with
   a muted icon; --divider marks the last pinned item, where the
   separating line belongs. */
.sidebar .btn-group .dropdown-menu .dropdown-item--pinned {
    font-weight: 600;
}
.sidebar .btn-group .dropdown-menu .dropdown-item--pinned i {
    color: var(--crs-gray-600);
}
.sidebar .btn-group .dropdown-menu .dropdown-item--divider {
    border-bottom: 1px solid var(--crs-gray-200);
    margin-bottom: 0.2rem;
    padding-bottom: 0.55rem;
}

/* Scrollbar for long rep lists */
.sidebar .btn-group .dropdown-menu::-webkit-scrollbar { width: 8px; }
.sidebar .btn-group .dropdown-menu::-webkit-scrollbar-thumb {
    background: var(--crs-gray-400);
    border-radius: 4px;
}
.sidebar .btn-group .dropdown-menu::-webkit-scrollbar-thumb:hover {
    background: var(--crs-gray-600);
}

/* --------------------------------------------------------------------- *
 * Sidebar report dropdown ("Download Report")                            *
 * Same .sidebar .btn-group / data-display="static" mechanism as the      *
 * Company / Sales Rep pickers above (dropup + max-height math lives in   *
 * base.html and already applies here for free). Everything below is a   *
 * targeted ADDITION scoped to .sidebar-reports-* -- it must never change *
 * how the plain .dropdown-item picker rows above look or behave.         *
 * --------------------------------------------------------------------- */

/* Both rules below need to out-specify a same-file/later-file rule that
   would otherwise win by specificity alone (browser review 2026-09-16:
   the trigger rendered TWO icons -- the inherited fa-briefcase
   ::before plus the real cloud-download-alt <i> -- and computed 40px
   tall, not 44px):
     .sidebar .btn-group > .dropdown-toggle::before   is (0,3,0)
     body.clair-spacex :is(.btn, ...) { min-height: 40px }  is (0,2,1)
   so a plain `.sidebar-reports-toggle { ... }` (0,1,0) loses both. The
   selector below matches the actual button (.sidebar .btn-group >
   .dropdown-toggle.sidebar-reports-toggle), landing at (0,4,0), which
   beats both regardless of file load order. */
.sidebar .btn-group > .dropdown-toggle.sidebar-reports-toggle {
    min-height: 44px;   /* explicit touch target, independent of --crs-control-h */
}
.sidebar .btn-group > .dropdown-toggle.sidebar-reports-toggle::before {
    content: none;   /* suppress the inherited fa-briefcase picker icon */
}
/* The real, only icon -- inline in the markup so its meaning (download,
   not a scope picker) doesn't depend on a CSS pseudo-element surviving. */
.sidebar-reports-toggle i {
    color: var(--crs-red);
    margin-right: 0.55rem;
    font-size: 0.85rem;
}

/* --------------------------------------------------------------------- *
 * One control family: Company / Sales Rep / Download Report              *
 * --------------------------------------------------------------------- *
 * The three rail triggers previously mismatched on width, height and
 * rhythm:
 *
 *   width   the two pickers live inside `.sidebar form`, which insets
 *           them by its own `padding: 0 0.25rem`. Download Report is a
 *           SIBLING of that form, so it ran 0.5rem wider.
 *   height  the pickers took body.clair-spacex's generic
 *           `:is(.btn, ...) { min-height: 40px }`, while Download Report
 *           had already declared 44px -- stack was 40 / 40 / 44.
 *   rhythm  the form's `gap: 0.5rem` cannot reach outside the form, so
 *           the third control sat flush against the pair above it.
 *
 * Fixed here rather than moving Download Report into the <form>: that
 * form is a GET filter, and a button inside it would inherit submit
 * semantics and the filter's querystring. Grant checks, menu contents
 * and every href are unchanged -- this block sets box metrics only.
 *
 * The min-height selector is `.sidebar .btn-group > .dropdown-toggle`
 * (0,3,0) deliberately: it must out-specify the generic 40px rule
 * (0,2,1), the same arithmetic the note further up this file describes.
 */
.sidebar .btn-group.sidebar-reports-group {
    margin-top: 0.5rem;
    padding: 0 0.25rem;   /* border-box: matches the form's inset exactly */
}
.sidebar .btn-group > .dropdown-toggle {
    min-height: 44px;
}
/* Fixed icon box so all three labels start at the same x -- fa-id-badge
   and fa-cloud-download-alt are not the same glyph width, so centring
   them in one box is what actually aligns the text beside them. */
.sidebar .btn-group > .dropdown-toggle::before,
.sidebar .btn-group > .dropdown-toggle.sidebar-reports-toggle i {
    flex: 0 0 auto;
    width: 1.1rem;
    text-align: center;
}

/* Two-line item: icon, then a title + a muted one-line description. The
   base `.sidebar .btn-group .dropdown-menu .dropdown-item` rule still
   supplies padding/radius/font-size/transition; this only changes the
   internal layout for items carrying a description. */
.sidebar-reports-item {
    align-items: flex-start;
    white-space: normal;
}
.sidebar-reports-item-text {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}
.sidebar-reports-item-title {
    font-weight: 600;
}
.sidebar-reports-item-desc {
    font-size: 0.75rem;
    font-weight: 400;
    color: var(--crs-gray-600);
    line-height: 1.3;
}
.sidebar-reports-item:hover .sidebar-reports-item-desc,
.sidebar-reports-item:focus .sidebar-reports-item-desc {
    color: inherit;
}
/* Group headers (Selected rep / company / Reports / Last 7 days /
   Forecasting) reuse Bootstrap's own .dropdown-header, already
   muted/no-hover by default -- just tightens the fit for this narrower
   menu. */
.sidebar-reports-menu .dropdown-header {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.5rem 0.75rem 0.2rem;
}
.sidebar-reports-menu .dropdown-header:first-child {
    padding-top: 0.25rem;
}
/* One scope note stated on the Reports header, instead of repeating
   "ignores the filters above" on every line beneath it (browser review
   2026-09-16: five repeats made the menu long enough to force a
   scroll). Resets the header's own uppercase/tracking so it reads as
   a normal-case aside, not a second heading. */
.sidebar-reports-group-note {
    text-transform: none;
    letter-spacing: normal;
    font-weight: 400;
    opacity: 0.75;
}
.sidebar-reports-group-note::before {
    content: '\2014';   /* em dash */
    margin: 0 0.3em;
}

/* --------------------------------------------------------------------- *
 * Drill-down sidebar report navigation                                   *
 * --------------------------------------------------------------------- *
 * Native <details>/<summary> groups (no JS) so the 12 other KPI/chart
 * pages and the other Sales reports do not become a wall of equally-
 * weighted buttons next to Back/Closed above. Same dark sidebar language
 * as a.sidebar_link -- these ARE .sidebar_link, plus a summary row styled
 * to match. */
.drill-nav-groups { margin-top: 0.5rem; }
.drill-nav-group + .drill-nav-group { margin-top: 2px; }
.drill-nav-summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.65rem 1rem;
    border-radius: var(--crs-radius);
    color: var(--crs-white);
    font-weight: 600;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    cursor: pointer;
    list-style: none;
}
.drill-nav-summary::-webkit-details-marker { display: none; }
.drill-nav-summary:hover { background-color: rgba(200, 16, 46, 0.18); }
.drill-nav-summary:focus-visible {
    outline: 2px solid var(--crs-red);
    outline-offset: -2px;
    border-radius: var(--crs-radius);
}
.drill-nav-caret {
    color: var(--crs-red);
    font-size: 0.7rem;
    transition: transform 0.12s ease;
}
.drill-nav-group[open] > .drill-nav-summary .drill-nav-caret { transform: rotate(90deg); }
.drill-nav-list { list-style: none; padding-left: 1.25rem; margin: 0.25rem 0 0.5rem; }
.drill-nav-list li { margin-bottom: 2px; }
.drill-nav-link { font-weight: 400; font-size: 0.92rem; }
.drill-nav-link[aria-current="page"] {
    background-color: rgba(200, 16, 46, 0.28) !important;
    border-left-color: var(--crs-red);
    font-weight: 600;
}

/* --------------------------------------------------------------------- *
 * Sales dashboard — KPI tiles, cards, and chart rows                     *
 * --------------------------------------------------------------------- */

.main_content { padding: 1.5rem !important; }

.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1rem;
    margin-bottom: 1.25rem;
}
.kpi-card {
    background: var(--crs-white);
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius-lg);
    box-shadow: var(--crs-shadow-sm);
    padding: 1rem 1.1rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    transition: all var(--crs-trans);
    position: relative;
    overflow: hidden;
    min-height: 110px;
}
.kpi-card::before {
    content: '';
    position: absolute; left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--crs-gray-300);
    transition: background var(--crs-trans);
}
/* No hover lift. The generic .card lost its lift when panels stopped
   claiming to be clickable; these two were the same pattern in a
   different file, so a KPI tile still rose under the cursor while the
   card beside it did not. The accent bar below is the real hover cue. */
.kpi-card:hover::before { background: var(--crs-red); }
.kpi-card--accent::before { background: var(--crs-red); }
.kpi-icon {
    color: var(--crs-red);
    font-size: 1.1rem;
    line-height: 1;
}
.kpi-label {
    color: var(--crs-gray-600);
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.kpi-value {
    font-size: 1.65rem;
    font-weight: 700;
    color: var(--crs-gray-900);
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    line-height: 1.15;
}
.kpi-value a {
    color: var(--crs-gray-900);
    text-decoration: none;
    border-bottom: 2px solid var(--crs-red);
}
.kpi-value a:hover { color: var(--crs-red); }

/* Generic section card */
/* ONE card for both halves of the app. Sales and Commissions each had
   their own -- same idea, different radius, different border grey, one with
   a shadow and one without -- so moving between them felt like moving
   between two products. This is the shared body: flat (the shadow was the
   dated half of the pair), 10px radius, one border colour, 16/20 padding.
   .cv3-card in commission_layout.css resolves to exactly these values. */
.sales-card {
    background: var(--crs-white);
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius-lg);
    box-shadow: none;
    padding: 16px 20px;
    margin-bottom: 1.25rem;
    display: block !important;
}
/* ONE section header for both halves of the app.

   Commissions had no equivalent: .cv3-card-title did double duty, heading a
   KPI card ("Commission Earned", where the FIGURE is the thing you read) and
   heading a section of table ("Books", "Who · Customers") with the same
   quiet 13px label. So a table on a Sales page announced itself and the same
   table on a Commissions page did not. The section cards opt in with
   .cv3-card-title--section and land here; KPI labels deliberately stay
   quiet, because a bold bordered heading above a big number competes with
   the number. */
/* Doubled class on the commission half: commission_layout.css loads AFTER
   this file, so its plain `.cv3-card-title` would win a specificity tie
   and the heading would keep the KPI label's 13px/500 while gaining only
   the rule underneath it -- measured exactly that before this. */
.sales-card-header,
.cv3-card-title.cv3-card-title--section {
    font-size: 1rem;
    font-weight: 600;
    color: var(--crs-gray-900);
    margin-bottom: 0.9rem;
    padding-bottom: 0.6rem;
    border-bottom: 1px solid var(--crs-gray-200);
    display: flex;
    align-items: center;
    gap: 0.5rem;
    text-transform: none;
}
/* The (?) and any status pill sit on the heading row, not stretched by it. */
.cv3-card-title.cv3-card-title--section > * { flex: 0 0 auto; }
.sales-card-header > i:first-child,
.cv3-card-title.cv3-card-title--section > i:first-child { color: var(--crs-red); flex-shrink: 0; }
.sales-card-header .sales-card-action { margin-left: auto; }
.sales-card-action {
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--crs-red);
    text-decoration: none;
    border: 1px solid var(--crs-gray-300);
    padding: 0.25rem 0.65rem;
    border-radius: var(--crs-radius);
    transition: all var(--crs-trans);
}
.sales-card-action:hover {
    background: var(--crs-red);
    color: var(--crs-white) !important;
    border-color: var(--crs-red);
}

.chart-row {
    display: grid;
    gap: 1rem;
    align-items: stretch;
}
.chart-row--two   { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }
.chart-row--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 992px) {
    .chart-row--two, .chart-row--three { grid-template-columns: 1fr; }
}
.chart-cell { min-width: 0; }
/* The canvas gets its own sizing box, exactly like .ranked-chart-box.
   Chart.js measures the canvas's PARENT; when that parent was the whole
   .chart-cell it also contained the keyboard drill-down links, so every
   layout pass added their height to the canvas and the chart grew ~6px
   per resize (myChart5 measured 199 -> 211 -> 223 over three round
   trips). The links are siblings of the box now, outside the measured
   area. `max-height` moved here too: capping the CANVAS is what caused
   the original ranked hit-area mismatch. */
.chart-canvas-box {
    position: relative;
    width: 100%;
    min-width: 0;
    height: 260px;
}
.chart-cell canvas { display: block; }
@media (max-width: 768px) {
    .chart-canvas-box { height: 240px; }
}

/* "Ranked list" charts live in a 2-up grid of small summary tiles;
   clicking the expand button in the header reveals the full list and
   the card spans the full row width. */
.ranked-grid {
    display: grid;
    /* minmax(0, 1fr), never a bare 1fr: a bare fr track cannot shrink
       below its item's min-content, and that min-content includes the
       inline pixel width Chart.js wrote onto the canvas during the
       previous, wider layout. Shrinking a desktop window to 390px left
       the track frozen at 454px and carried the expand button off the
       viewport where it could not be tapped. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 1rem;
    margin-bottom: 1.25rem;
}
.ranked-grid > .ranked-card {
    margin-bottom: 0;
    transition: grid-column 0.2s ease;
    min-width: 0;   /* same reason: let the card shrink with its track */
}
.ranked-grid > .ranked-card:not(.is-collapsed) { grid-column: 1 / -1; }
@media (max-width: 992px) {
    .ranked-grid { grid-template-columns: minmax(0, 1fr); }
    .ranked-grid > .ranked-card:not(.is-collapsed) { grid-column: 1; }
}
/* The header holds the title and the expand button. It must wrap rather
   than demand a width the phone does not have. */
.ranked-card > .sales-card-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
    min-width: 0;
}
.ranked-card > .sales-card-header > .chart-toggle { margin-left: auto; flex: none; }

/* Size the WRAPPER, never the canvas.
   Chart.js (responsive + maintainAspectRatio:false) measures the canvas's
   parent and writes that height onto the canvas inline. When the canvas
   itself carried `height: 240px !important`, that override won visually
   while Chart.js still drew to the parent's 331px -- so the bars were
   painted on one grid and hit-tested on another, and clicking a visible
   bar missed it by ~90px. The wrapper is the only element with a height,
   so the model and the box are the same box. */
.ranked-chart-box {
    position: relative;
    width: 100%;
    min-width: 0;
    height: 240px;                     /* collapsed-tile default */
    /* No max-height. The expanded height is computed from the bar count
       in charts.js (26px per row); a 520px cap clamped a 20-row customer
       chart back to ~14px per row, which is the crowding the per-row
       sizing exists to prevent. */
    transition: height 0.25s ease;
}
.ranked-chart {
    display: block;
    width: 100%;
}
/* Hide until a real series is mounted. An empty Chart.js instance (or a
   0-height canvas before expand) reads as a white hole. */
.ranked-card:not(.is-ready) .ranked-chart-box {
    display: none;
    height: 0;
}
.ranked-chart-status {
    display: none;
    margin: 0;
    padding: 0.45rem 0.85rem 0.7rem;
    font-size: 0.85rem;
    color: var(--crs-gray-600);
}
.ranked-card.is-loading .ranked-chart-status,
.ranked-card.is-error .ranked-chart-status,
.ranked-card.is-empty .ranked-chart-status {
    display: block;
}
.ranked-retry {
    margin-left: 0.35rem;
    padding: 0.15rem 0.55rem;
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius);
    background: transparent;
    color: var(--crs-gray-700);
    font-size: 0.8rem;
    cursor: pointer;
}
.ranked-retry:hover,
.ranked-retry:focus {
    background: var(--crs-red);
    border-color: var(--crs-red);
    color: var(--crs-white);
    outline: none;
}
.ranked-card:not(.is-collapsed) .ranked-chart-box {
    height: 440px;
}
@media (max-width: 768px) {
    .ranked-chart-box { height: 220px; }
    .ranked-card:not(.is-collapsed) .ranked-chart-box { height: 380px; }
}
@media (max-width: 480px) {
    .ranked-chart-box { height: 210px; }
    .ranked-card:not(.is-collapsed) .ranked-chart-box { height: 340px; }
}

/* Expand / collapse button in the card header */
.chart-toggle {
    margin-left: auto;
    background: transparent;
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius);
    color: var(--crs-gray-700);
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--crs-trans);
    flex-shrink: 0;
    padding: 0;
}
.chart-toggle:hover,
.chart-toggle:focus {
    background: var(--crs-red);
    border-color: var(--crs-red);
    color: var(--crs-white);
    outline: none;
}
.chart-toggle i { font-size: 0.85rem; }
.chart-toggle .collapse-icon { display: none; }
.ranked-card:not(.is-collapsed) .chart-toggle .expand-icon { display: none; }
.ranked-card:not(.is-collapsed) .chart-toggle .collapse-icon { display: inline-block; }

/* --------------------------------------------------------------------- *
 * Shared rep-code split indicators                                       *
 * --------------------------------------------------------------------- */

.badge-split {
    display: inline-block;
    background: var(--crs-red-light);
    color: var(--crs-red-dark);
    border: 1px solid var(--crs-red-tint);
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    padding: 0.1rem 0.5rem;
    margin-left: 0.35rem;
    vertical-align: middle;
    white-space: nowrap;
}
.is-split-row td {
    background: rgba(200, 16, 46, 0.04) !important;
    border-left-color: var(--crs-red) !important;
}
.is-split-row > td:first-child {
    border-left: 3px solid var(--crs-red) !important;
}
/* Rows attributed via a special commission rule get a gold/amber accent. */
.is-special-row td {
    background: rgba(217, 119, 6, 0.05) !important;
}
.is-special-row > td:first-child {
    border-left: 3px solid #D97706 !important;
}
.badge-special {
    display: inline-block;
    background: #FEF3E4;
    color: #78350F;
    border: 1px solid #FCD49B;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    padding: 0.1rem 0.55rem;
    margin-left: 0.35rem;
    vertical-align: middle;
    white-space: nowrap;
}
.badge-special i { color: #D97706; margin-right: 0.25rem; }
.is-correction-row td {
    background: rgba(79, 70, 229, 0.05) !important;
}
.is-correction-row > td:first-child {
    border-left: 3px solid #4F46E5 !important;
}
.badge-correction {
    display: inline-block;
    background: #EEF2FF;
    color: #3730A3;
    border: 1px solid #C7D2FE;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    padding: 0.1rem 0.55rem;
    vertical-align: middle;
    white-space: nowrap;
}

/* --------------------------------------------------------------------- *
 * Monthly-grid tables — fixed column widths so Monthly Revenue,          *
 * Actual vs Plan, Commission Earned, and Unpaid/Potential all share the  *
 * same month columns visually. Without table-layout:fixed each table     *
 * sizes its own columns from its own content, making the months drift    *
 * a few pixels off between stacked tables.                               *
 * --------------------------------------------------------------------- *
 *   col 1  = Metric (wider, labels vary)                                 *
 *   cols 2-13 = twelve months, equal share                               *
 *   col 14 = TTM Total (a bit wider for the bold totals)                 *
 * --------------------------------------------------------------------- */

/* Monthly grid sizing -------------------------------------------------------
 * Goals:
 *   1. Dollar amounts never wrap ($3,949,499 must sit on one line).
 *   2. Columns align PERFECTLY across the 4 stacked monthly tables
 *      (Monthly Revenue, Actual vs Plan, Commission Earned, Uncollected).
 *
 * Approach:
 *   * table-layout: fixed     -> the first-row cell widths are authoritative;
 *                                every cell beneath them in the same column
 *                                is forced to that exact width, regardless
 *                                of content length. This is what guarantees
 *                                alignment across tables.
 *   * Explicit width = sum of column widths + min-width: 100% so on wide
 *     viewports all 4 tables stretch proportionally (still matching each
 *     other); on narrow viewports they keep their base widths and the
 *     .table-responsive wrapper + sticky top-mirror scrollbar provide
 *     horizontal scroll.
 *   * white-space: nowrap + overflow: visible so numbers stay one-line
 *     and any accidental overflow leaks rather than wrapping.
 *
 * Column widths (sum = 116rem ≈ 1856px):
 *   first col (metric label)    = 13rem  (wraps long labels to 2 lines)
 *   12 month columns @ 8rem     = 96rem  (fits \$9,999,999 + trend-arrow pill)
 *   last col (TTM Total)        =  7rem
 *
 * Month columns were 6.5rem but the tinted trend-arrow pills on Above/Below
 * Quota cells pushed content past the cell boundary into neighbors. Bumped
 * to 8rem + switched overflow to hidden so any extreme value clips in-cell
 * rather than leaking out.
 * --------------------------------------------------------------------------- */
.monthly-grid {
    table-layout: fixed;
    /* Try to fit all 14 cells (metric + 12 months + total) within the
       page's container width. Tighter column widths + a slightly smaller
       font let realistic values like "$10,000.00" or "▼25.00%" sit on
       one line without wrapping or truncation. The .table-responsive
       wrapper still falls back to horizontal scroll on narrow screens.
       Width math: 12rem label + (12 × 5.75rem months) + 6.5rem total
                  = 12 + 69 + 6.5 = 87.5rem (~1,400px at 16px base) */
    width: 100%;
    min-width: calc(12rem + (12 * 5.75rem) + 6.5rem);
}
.monthly-grid th,
.monthly-grid td {
    white-space: nowrap;
    overflow: visible;
    word-break: normal;
    font-size: 0.82rem;
    padding: 0.4rem 0.45rem;
}
/* First column (metric label) — keep the full descriptor + (?) help
   button on one line so labels read cleanly without wrapping. Slightly
   smaller font + a wider column accommodate the longest label
   ("Cumulative Above/Below Quota ($)") plus the inline help pill. */
.monthly-grid thead th:first-child,
.monthly-grid tbody td:first-child {
    width: 12rem;
    white-space: normal;
    overflow-wrap: break-word;
    word-break: break-word;
    font-size: 0.82rem;
}
.monthly-grid thead th:last-child,
.monthly-grid tbody td:last-child {
    width: 6.5rem;
    font-weight: 600;
}
/* Each of the 12 month columns gets equal width. table-layout:fixed +
   evenly-distributed widths means narrow viewports compress columns
   uniformly instead of one column hogging the row. */
.monthly-grid thead th:not(:first-child):not(:last-child),
.monthly-grid tbody td:not(:first-child):not(:last-child) {
    width: 5.75rem;
}

/* Customer Accounts table — fit-to-page treatment for 21 columns
   (Customer No / Name / 12 months / 7 totals). Use a small font, tight
   padding, and word-wrapped headers to keep dollar values on single
   lines without forcing horizontal scroll on a typical desktop.
   DataTables sets inline `width: Npx` after init, so we override with
   !important — otherwise it expands to content-fit and overflows. */
#customers_table {
    table-layout: fixed !important;
    width: 100% !important;
    font-size: 0.72rem;
}
#customers_table th,
#customers_table td {
    box-sizing: border-box;
    padding: 0.25rem 0.25rem;
    white-space: nowrap;
    overflow: visible;
}
#customers_table thead th {
    white-space: normal !important;
    word-break: keep-all;
    overflow-wrap: normal;
    vertical-align: bottom;
    line-height: 1.15;
    padding-top: 5px;
    /* Total columns (right side) get a bit more room than month columns.
       Default to a tight cap; overrides below adjust per column slot. */
    max-width: 75px !important;
    width: 75px !important;
}
#customers_table thead th:nth-child(1),
#customers_table tbody td:nth-child(1) {
    white-space: nowrap !important;
    width: 56px !important;
    max-width: 56px !important;
}
#customers_table thead th:nth-child(2),
#customers_table tbody td:nth-child(2) {
    /* Customer name column — wrap onto multiple lines instead of
       truncating with ellipsis. The previous 110px / nowrap / ellipsis
       combination cut off long names ("Tesoro Refining & Marketing
       Company LLC" etc.) at the column edge; widening + allowing
       wrap keeps the full name readable on two-three lines. */
    white-space: normal !important;
    width: 200px !important;
    max-width: 200px !important;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

/* Per-tile scope disclaimer for the Unlockable Commission /
   Commission Earned pipeline tiles. Tucked under the meta line so it
   doesn't compete with the headline value but makes the tile's
   inclusion rules obvious at a glance. */
.cmp-stage-disclaimer {
    margin-top: 0.4rem;
    font-size: 0.7rem;
    line-height: 1.3;
    color: rgba(255, 255, 255, 0.85);
    display: flex;
    align-items: baseline;
    gap: 0.25rem;
    /* On the colored gradient tiles the lighter color reads as a hint
       rather than an active link; override on lighter tile variants
       below where contrast inverts. */
}
.cmp-stage-disclaimer > i {
    flex-shrink: 0;
    opacity: 0.85;
}
/* The Unlockable / Earned tiles have a white card body — restore
   normal muted-grey text so the disclaimer is legible. */
.pipeline-stage-unlockable .cmp-stage-disclaimer,
.pipeline-stage-payout .cmp-stage-disclaimer {
    color: var(--crs-gray-600, #5f6368);
}
.pipeline-stage-unlockable .cmp-stage-disclaimer > i,
.pipeline-stage-payout .cmp-stage-disclaimer > i {
    color: var(--crs-gray-500, #adb5bd);
}

/* Quota-scope disclaimer under the Commission Paid tile — clarifies
   that commission is summed across BOTH reps with and without a
   quota, since the adjacent Quota Tracking tile only counts reps
   with a target. Tight-spacing so it tucks under the trend chip
   without pushing the sparkline. */
.kpi-quota-scope-note {
    margin-top: 0.2rem;
    font-size: 0.7rem;
    line-height: 1.3;
}
.kpi-quota-scope-note > i {
    margin-right: 0.2rem;
}

/* With-quota / without-quota / total stack used on the team-scope
   invoice detail KPI tiles. The main tile value leads with the
   with-quota number (matches the chart bar that drilled here) and
   the stack below shows the without-quota slice + the all-rows
   total in a compact two-row block. */
.invoice-kpi-sub-stack {
    margin-top: 0.35rem;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    border-top: 1px solid rgba(0, 0, 0, 0.06);
    padding-top: 0.35rem;
}
.invoice-kpi-sub-line {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.4rem;
    font-size: 0.78rem;
    color: var(--crs-gray-600, #5f6368);
    line-height: 1.25;
}
.invoice-kpi-sub-line .invoice-kpi-sub-amount {
    font-variant-numeric: tabular-nums;
    font-weight: 500;
}
.invoice-kpi-sub-line .invoice-kpi-sub-label {
    font-size: 0.72rem;
    text-transform: lowercase;
    letter-spacing: 0.02em;
}
.invoice-kpi-sub-total {
    color: var(--crs-gray-900, #202124);
    font-weight: 600;
    border-top: 1px dashed rgba(0, 0, 0, 0.1);
    padding-top: 0.15rem;
    margin-top: 0.05rem;
}
.invoice-kpi-sub-total .invoice-kpi-sub-amount {
    font-weight: 700;
}

/* Per-column filter row injected below DataTables headers. Keeps the
   dropdown compact, white text on the dark thead background, and
   stops the filter cell from inheriting the column's sort cursor. */
table.dataTable thead tr.dt-filter-row th {
    padding: 4px 6px;
    background: #f8f9fa;
    border-top: 1px solid #dee2e6;
    cursor: default;
}
table.dataTable thead tr.dt-filter-row th .dt-col-filter {
    height: auto;
    padding: 2px 4px;
    font-size: 0.78rem;
    font-weight: 400;
    background: #fff;
    color: #212529;
    border: 1px solid #ced4da;
    width: 100%;
    max-width: 160px;
}

/* Multi-select column filter — checkbox-list dropdown used on the
   team summary table for the Rep and Manager columns so a viewer can
   pick several reps/managers at once and watch the footer totals roll
   up just for that subset. The wrapper is `position: relative` and the
   panel pops down absolutely so it doesn't shift the column width. */
table.dataTable thead tr.dt-filter-row th .dt-multi-filter {
    position: relative;
    width: 100%;
    max-width: 200px;
    text-align: left;
    font-weight: 400;
}
table.dataTable thead tr.dt-filter-row th .dt-multi-filter-btn {
    height: auto;
    padding: 2px 22px 2px 6px;
    font-size: 0.78rem;
    font-weight: 400;
    background: #fff;
    color: #212529;
    border: 1px solid #ced4da;
    border-radius: 0.2rem;
    width: 100%;
    text-align: left;
    cursor: pointer;
    position: relative;
    line-height: 1.4;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
table.dataTable thead tr.dt-filter-row th .dt-multi-filter-btn:hover {
    border-color: #adb5bd;
}
.dt-msf-caret {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.7rem;
    color: #6c757d;
}
.dt-multi-filter-panel {
    position: absolute;
    top: calc(100% + 2px);
    left: 0;
    z-index: 1080;
    min-width: 220px;
    max-width: 320px;
    background: #fff;
    border: 1px solid #ced4da;
    border-radius: 0.25rem;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
    padding: 0.4rem;
    font-weight: 400;
    color: #212529;
}
.dt-multi-filter-panel[hidden] { display: none; }
.dt-msf-head {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-bottom: 0.35rem;
}
.dt-msf-search {
    flex: 1;
    height: auto;
    padding: 2px 6px;
    font-size: 0.78rem;
}
.dt-msf-clear {
    /* sales_styles.css's global ".btn-group, .btn { width:100% !important }"
       (mobile full-width buttons) matches this too -- same specificity, so
       it wins on load order alone unless overridden here. Left unfixed, it
       forces Clear to claim ~all of .dt-msf-head's flex row, squeezing the
       search input (flex:1) down to a sliver. */
    width: auto !important;
    flex: 0 0 auto;
    padding: 0;
    font-size: 0.75rem;
    color: #6c757d;
    text-decoration: underline;
}
.dt-msf-clear:hover { color: #dc3545; text-decoration: underline; }
.dt-msf-list {
    max-height: 260px;
    overflow-y: auto;
    border-top: 1px solid #f0f0f0;
    padding-top: 0.25rem;
}
.dt-msf-option {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 2px 4px;
    margin: 0;
    font-size: 0.8rem;
    cursor: pointer;
    border-radius: 0.15rem;
}
.dt-msf-option:hover { background: #f6f7f9; }
.dt-msf-option > input[type="checkbox"] {
    margin: 0;
    flex-shrink: 0;
}
.dt-msf-option > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* No-quota banner on the per-rep dashboard. Surfaces a clear notice
   that the page is missing quota context (chart hidden, % to plan
   meaningless) so the user understands why those sections are absent. */
.rep-no-quota-banner {
    border-left: 4px solid #f59e0b;
}
.rep-no-quota-banner-title {
    font-size: 0.95rem;
    margin-bottom: 0.25rem;
}
.rep-no-quota-banner-title > i {
    color: #b45309;
    margin-right: 0.25rem;
}
.rep-no-quota-banner-body {
    font-size: 0.85rem;
    line-height: 1.45;
}

/* Per-rep dashboard title: when a profile maps to many BC codes (e.g.
   the House Accounts placeholder collects 30+ HOUSE* / unmapped codes
   into one Profile), the comma-joined code list runs off the page.
   Constrain the H2 itself so its child block can't push it past the
   viewport, then let the codes line wrap freely. */
.commission-dashboard-title {
    max-width: 100%;
    overflow-wrap: anywhere;
    word-break: break-word;
}
.commission-dashboard-title .dashboard-title-codes {
    display: block;
    /* Bound to viewport so an overflowing parent can't widen us.
       calc subtracts left+right page padding (~2rem each). */
    max-width: calc(100vw - 4rem);
    /* !important needed — somewhere up the stylesheet stack a rule on
       <small> (Bootstrap / our own helpers) sets white-space: nowrap
       which keeps the codes on a single line that overflows the
       viewport. Force-wrap so the long house-account code list
       breaks cleanly. */
    white-space: normal !important;
    font-size: 0.78rem;
    margin-top: 0.15rem;
    word-break: break-word;
    overflow-wrap: anywhere;
    line-height: 1.4;
    font-weight: 400;
}
/* The 12 month columns (cols 3-14): generous 88px each since the
   Summary column merged 6 right-side totals into a compact stacked
   cell. Months were 60px when 7 narrow totals competed for space; now
   they get the breathing room reclaimed. Fits "$10,000.00" cleanly. */
#customers_table thead th:nth-child(n+3):nth-child(-n+14),
#customers_table tbody td:nth-child(n+3):nth-child(-n+14) {
    width: 88px !important;
    max-width: 88px !important;
}
/* Summary column (last) — fixed 220px since the inline lines are at
   0.7-0.85rem and "$10,000.00 customer paid · $-500 customer owes" is
   ~205px at this font. Stacked vertically: My Invoiced headline + 3
   secondary lines (paid/owed · commission/percentages · customer total). */
#customers_table thead th:last-child,
#customers_table tbody td:last-child {
    width: 220px !important;
    max-width: 220px !important;
    text-align: left !important;
    vertical-align: top !important;
}
.customer-summary-cell {
    line-height: 1.3;
}
/* New stacked-line layout — every line is `<icon> <amount> <label>` so
   amounts line up vertically across the cell at the same horizontal
   position. flex + min-width on the icon column does the alignment. */
.cs-row {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 0.7rem;
    color: var(--crs-gray-700, #495057);
    margin-top: 2px;
}
.cs-icon {
    width: 14px;
    color: var(--crs-gray-500, #9ca3af);
    flex-shrink: 0;
    font-size: 0.72rem;
}
.cs-amount {
    font-weight: 600;
    color: var(--crs-gray-900, #212529);
    font-variant-numeric: tabular-nums;
}
.cs-label {
    color: var(--crs-gray-600, #6c757d);
    font-weight: 400;
}
/* Headline (Invoiced) — bigger, accented icon. */
.cs-headline {
    font-size: 0.85rem;
}
.cs-headline .cs-icon {
    color: var(--crs-charcoal, #1a1a1a);
    font-size: 0.85rem;
}
.cs-headline .cs-amount {
    font-size: 0.95rem;
}
/* Commission row — green tint to read as "money to you". */
.cs-commission {
    margin-top: 4px;
}
/* Same rule as every other commission figure: the amount is ink, and the
   icon beside it is not the place to reintroduce green money. */
.cs-commission .cs-icon {
    color: var(--crs-gray-600);
}
.cs-commission .cs-amount {
    color: var(--crs-money);
}
/* Potential commission — amber, sits directly under the "owed" line so
   the user reads "$X owed → $Y potential commission" as a single
   thought. Only rendered when ttm_potential_commission > 0. */
.cs-potential .cs-icon { color: #d97706; }
.cs-potential .cs-amount { color: #b45309; }
.cs-potential .cs-label { color: #92400e; font-style: italic; }

/* All links inside the customer-summary cell: keep the parent row's
   color (each row's own palette is meaningful — green for commission,
   red for owed, etc.) and only show a subtle underline on hover. */
.cs-link, .cs-link:hover, .cs-link:focus { text-decoration: none; color: inherit; }
.cs-link { cursor: pointer; }
.cs-link:hover { background: rgba(200, 16, 46, 0.04); border-radius: 3px; }
.cs-link:hover .cs-amount { text-decoration: underline; }
/* All-reps spend (final muted line). */
.cs-muted {
    color: var(--crs-gray-500, #adb5bd);
    font-style: italic;
}
.cs-muted .cs-amount {
    color: var(--crs-gray-600, #6c757d);
    font-weight: 500;
}

/* Customer Payment summary card on the invoice-lines drill-down. Lays
   out four blocks (status / total paid / still owed / paid date) in a
   single row with a payment-progress strip below. */
.invoice-payment-card {
    border-left: 3px solid var(--crs-red, #c8102e);
}
.invoice-payment-block {
    flex: 1 1 22%;
    padding: 0 1rem;
    border-right: 1px solid var(--crs-gray-200, #e5e7eb);
    min-width: 180px;
}
.invoice-payment-block:first-child { padding-left: 0; }
.invoice-payment-block:last-child  { border-right: none; }
.payment-progress-wrapper {
    width: 100%;
}
.payment-progress-bar {
    height: 8px;
    background: rgba(200, 16, 46, 0.14);   /* CRS red, low alpha = owed */
    border-radius: 4px;
    overflow: hidden;
    width: 100%;
}
.payment-progress-fill {
    display: block;
    height: 100%;
    width: var(--paid-pct, 0%);
    background: linear-gradient(90deg, #0f9d58 0%, #16a34a 100%);
    border-radius: 4px;
    transition: width 0.2s ease-out;
}

/* Payment progress bar — green fill on a light-red track. Width = paid
   ÷ invoiced %. Empty bar = nothing paid; full bar = fully paid. */
.cs-payment-bar {
    height: 6px;
    background: rgba(200, 16, 46, 0.12);   /* CRS red, low alpha = "owed" */
    border-radius: 3px;
    overflow: hidden;
    margin: 4px 0 2px;
}
.cs-payment-bar-fill {
    display: block;
    height: 100%;
    background: rgba(15, 157, 88, 0.85);   /* green = paid */
    border-radius: 3px;
    transition: width 0.2s ease-out;
}
.cs-payment-line {
    display: flex;
    justify-content: space-between;
    gap: 4px;
}
.cs-payment-line > span {
    display: inline-flex;
    align-items: center;
    gap: 3px;
}
.cs-payment-paid {
    color: #0b7a45;
    font-weight: 500;
}
.cs-payment-paid .fa-check-circle {
    color: #0f9d58;
}
.cs-payment-owed {
    color: var(--crs-gray-600, #6c757d);
}
.cs-payment-owed .fa-circle {
    color: var(--crs-gray-300, #dee2e6);
    font-size: 0.5rem;
}
.cs-payment-owed.is-owed {
    color: var(--crs-red, #c8102e);
    font-weight: 600;
}
.cs-payment-owed.is-owed .fa-exclamation-circle {
    color: var(--crs-red, #c8102e);
}

/* Customer share bars — visual indicator of what % of the rep's TTM
   revenue / commission this customer represents. Each pill has a tinted
   fill behind the text whose width = the % share, so the eye reads the
   share AT A GLANCE before reading the number. */
.customer-share-bars {
    display: flex;
    flex-direction: column;
    gap: 3px;
    margin-top: 3px;
}
.share-bar {
    position: relative;
    display: block;
    height: 18px;
    border: 1px solid var(--crs-gray-300, #dee2e6);
    border-radius: 3px;
    overflow: hidden;
    background: var(--crs-gray-100, #f6f7f9);
    line-height: 16px;
}
.share-bar-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: var(--pct, 0%);
    z-index: 0;
    /* Cap fill at 100% so values >100% don't overflow visually. */
    max-width: 100%;
}
.share-bar-fill-revenue   { background: rgba(29, 112, 184, 0.18); }   /* blue tint */
.share-bar-fill-commission{ background: rgba(15, 157, 88, 0.20); }    /* green tint */
.share-bar-text {
    position: relative;
    z-index: 1;
    padding: 0 6px;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--crs-gray-800, #1f2937);
    white-space: nowrap;
}

.split-hint {
    font-size: 0.72rem;
    color: var(--crs-gray-600);
    font-style: italic;
    line-height: 1.2;
    margin-top: 2px;
}

/* Customer-payment status pills on the invoice-detail / customer-detail
   table. Partial gets a saturated amber so it visually stands out among
   long lists of "paid" rows — that's the row the user usually wants to
   investigate ("why hasn't this closed yet?"). Paid is muted green;
   unpaid is muted red. Color choices match the dashboard's existing
   payment-progress bar so the page reads as a single visual language. */
.payment-status-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: lowercase;
    letter-spacing: 0.01em;
    line-height: 1.4;
    border: 1px solid currentColor;
}
.payment-status-pill .fas {
    font-size: 0.72rem;
}
.payment-status-paid {
    color: #0b7a45;
    background: #d1fae5;
    border-color: #6ee7b7;
}
.payment-status-partial {
    /* Saturated amber — the "needs attention" row. Higher contrast than
       paid/unpaid so it pops in a long list of green checkmarks. */
    color: #92400e;
    background: #fde68a;
    border-color: #f59e0b;
    box-shadow: 0 1px 0 rgba(245, 158, 11, 0.25);
}
.payment-status-unpaid {
    color: #991b1b;
    background: #fee2e2;
    border-color: #fca5a5;
}

/* "mixed basis" tag on the Commissionable KPI label — surfaces that
   the displayed total is a sum of rule-correct bases (some rows on
   gross basis, some on gross-margin basis), since the formula sub-line
   alone can't fully convey that. Same purple as the per-row basis-tag
   so the visual language stays consistent. */
.invoice-kpi-label .kpi-basis-tag {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-radius: 4px;
    /* Was purple, a hue used nowhere else. Its sibling .basis-tag-gross
       is already the gray chip; a basis tag names WHICH rule priced the
       row, which is a category, not a severity. */
    color: var(--crs-gray-700);
    background: var(--crs-gray-100);
    border: 1px solid var(--crs-gray-300);
    line-height: 1.4;
    vertical-align: 1px;
    cursor: help;
}
.invoice-kpi-label .kpi-basis-tag .fas {
    font-size: 0.6rem;
    margin-right: 2px;
}

/* Annotation under a deduct in the Commissionable formula sub-line —
   used to flag that "− Cost" only applies to GM rows. Subtle, italic,
   small font so it reads as a footnote not a competing value. */
.invoice-kpi-sub .deduct .deduct-note {
    font-style: italic;
    font-size: 0.78em;
    color: var(--crs-gray-500, #9ca3af);
    margin-left: 2px;
}

/* Earned vs Potential split shown under the Commission on These Rows
   KPI when a non-trivial potential exists. Two pills side-by-side
   joined by a "+" so the math reads: earned + potential = full picture
   of this month's posted-invoice commission story. */
.kpi-commission-split {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 4px;
    font-size: 0.75rem;
    flex-wrap: wrap;
    line-height: 1.4;
}
.kpi-commission-split .fas {
    font-size: 0.72rem;
    margin-right: 2px;
}
.kpi-commission-earned {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 10px;
    color: #0b7a45;
    background: #d1fae5;
    border: 1px solid #6ee7b7;
    font-weight: 600;
}
.kpi-commission-potential {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 10px;
    color: #92400e;
    background: #fde68a;
    border: 1px solid #f59e0b;
    font-weight: 600;
}
.kpi-commission-divider {
    color: var(--crs-gray-500, #9ca3af);
    font-weight: 700;
}

/* Formula appendix on the "across all invoices" subtitle of the
   Commissionable KPI tile — shows the unfiltered breakdown
   ($27,300 − PT $400 − L/D $400) so the user sees what makes up
   the all-invoices figure alongside the filtered formula above. */
.invoice-kpi-filtered .kpi-sub-formula {
    display: inline-block;
    color: var(--crs-gray-600, #6b7280);
    font-size: 0.85em;
    font-weight: 400;
    margin-left: 4px;
}

/* Per-row basis tag in the Commission Rate column. Distinguishes
   gross-basis rows (amount − PT − LD) from gross-margin-basis rows
   (amount − cost − PT − LD) so users can see at a glance which math
   was applied to a row's commission. Same shape as the bucket-mode
   tags so the row's "this is how the engine treated it" annotations
   read as a consistent set. */
.basis-tag {
    display: inline-block;
    margin-left: 4px;
    padding: 1px 6px;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-radius: 4px;
    border: 1px solid currentColor;
    line-height: 1.4;
    vertical-align: 1px;
    white-space: nowrap;
}
.basis-tag .fas { margin-right: 2px; font-size: 0.65rem; }
.basis-tag.basis-tag-gm {
    /* Same chip as .basis-tag-gross, distinguished by its own label and
       icon rather than by a colour the palette does not otherwise use. */
    color: var(--crs-gray-700);
    background: var(--crs-gray-100);
    border-color: var(--crs-gray-300);
}
.basis-tag.basis-tag-gross {
    color: var(--crs-gray-700, #374151);
    background: var(--crs-gray-100, #f3f4f6);
    border-color: var(--crs-gray-300, #d1d5db);
}

/* Active-filter banner — sits above the KPI tile strip whenever the
   user has toggled "Paid by Customer" or "Not Yet Paid". One canonical
   notification beats per-tile pills scattered across the page. Color
   shifts with the filter (green = paid, amber = unpaid) so the visual
   matches the row payment-status pills + the bucket-mode tags. */
.filter-status-banner {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 18px;
    margin-bottom: 1rem;
    border-radius: 12px;
    border: 1px solid;
    font-size: 0.92rem;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04),
                0 1px 2px rgba(0, 0, 0, 0.03);
    transition: box-shadow 0.15s ease;
}

/* "Commission earned this month" callout — shown on the All Invoices
   tab as the rep's paycheck-side number for the month (paid-mode
   commission across any invoice with cash collected this month).
   Distinct from the KPI tiles below it, which describe POSTED-in-month
   activity. Hidden whenever a sub-filter (Paid/Unpaid) is active — the
   filter banner takes over context. */
/* The page's headline figure. It was an emerald gradient panel with a 44px
   green coin disc, which made the single most-read number in the app look
   like a promotional banner -- and printed it in a colour no other page used
   for the same figure. It is now a plain white card with a red keyline: the
   number carries the emphasis, not the background. */
.earned-this-month-callout {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 14px 20px;
    margin-bottom: 0;
    border-radius: var(--crs-radius-lg);
    border: 1px solid var(--crs-gray-300);
    border-left: 3px solid var(--crs-red);
    background: var(--crs-white);
    box-shadow: none;
}
.earned-this-month-icon {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--crs-gray-100);
    color: var(--crs-gray-600);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.2rem;
}
.earned-this-month-body {
    flex: 1 1 auto;
    min-width: 0;
}
.earned-this-month-label {
    font-size: 0.85rem;
    color: var(--crs-gray-700);
    font-weight: 600;
    margin-bottom: 2px;
}
.earned-this-month-sub {
    font-weight: 400;
    color: var(--crs-gray-600);
    font-size: 0.78rem;
}
.earned-this-month-value {
    font-size: 1.65rem;
    font-weight: 700;
    color: var(--crs-money);
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}
/* The callout around it is white with a red keyline now; an emerald CTA
   was the last piece of the old green panel. */
.earned-this-month-link {
    flex: 0 0 auto;
    color: var(--crs-gray-700);
    font-weight: 600;
    font-size: 0.85rem;
    text-decoration: none;
    white-space: nowrap;
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px solid var(--crs-gray-300);
    background: var(--crs-white);
    transition: background 0.15s ease, border-color 0.15s ease;
}
.earned-this-month-link:hover {
    background: var(--crs-gray-100);
    border-color: var(--crs-gray-400);
    color: var(--crs-charcoal);
    text-decoration: none;
}
/* The CTA also renders as a <button> when it triggers a client-side
   tab toggle instead of navigating (so the page doesn't reload). The
   button defaults (gray border, autosizing, focus ring) would clash
   with the pill styling above, so we explicitly reset them. */
button.earned-this-month-link,
button.earned-this-month-link-toggle {
    cursor: pointer;
    font-family: inherit;
    line-height: inherit;
}
/* Focus is red everywhere else in the app; a green ring here was part of
   the old green callout, not a separate decision. */
button.earned-this-month-link:focus,
button.earned-this-month-link-toggle:focus {
    outline: 2px solid var(--crs-red);
    outline-offset: 1px;
}

/* Posted-mode rep — commission credits at invoice posting, not on
   customer payment. Visually shift to indigo to make it clear at a
   glance that the framing differs from the cash-driven default. */
/* Mode variants. Each of these used to repaint the whole callout -- indigo
   gradient for posted, slate for mixed, amber for unpaid -- AND recolour the
   headline figure with it, so the one number a rep came for changed colour
   four ways on one page. The card stays white and the amount stays ink; the
   mode is carried by the keyline, the icon, and the caption that already
   spells it out in words. Amber is kept for the unpaid variant because that
   figure is POTENTIAL commission, not earned -- a real difference in meaning,
   not a decoration. */
.earned-this-month-mode-posted {
    border-left-color: var(--crs-gray-500);
}
.earned-this-month-mode-posted .earned-this-month-icon {
    color: var(--crs-gray-600);
}
.earned-this-month-mode-posted .earned-this-month-sub,
.earned-this-month-mode-posted .earned-this-month-link {
    color: var(--crs-gray-700);
}

.earned-this-month-mode-mixed {
    border-left-color: var(--crs-gray-500);
}
.earned-this-month-mode-mixed .earned-this-month-icon {
    color: var(--crs-gray-600);
}
.earned-this-month-mode-mixed .earned-this-month-sub,
.earned-this-month-mode-mixed .earned-this-month-link {
    color: var(--crs-gray-700);
}

/* Paid-by-Customer filter variant. No overrides: it IS the default callout,
   and the tab above it already says which slice is on screen. */
.earned-this-month-mode-filter-paid {
    /* intentionally empty -- kept so a future tweak has somewhere to go */
}

/* Not-Yet-Paid: the headline is potential commission, not earned. The amber
   keyline and icon say so; the amount is still ink, because it is money. */
.earned-this-month-mode-filter-unpaid {
    border-left-color: var(--crs-warning);
}
.earned-this-month-mode-filter-unpaid .earned-this-month-icon {
    background: var(--crs-warning-bg);
    color: var(--crs-warning);
}
.earned-this-month-mode-filter-unpaid .earned-this-month-sub,
.earned-this-month-mode-filter-unpaid .earned-this-month-link {
    color: var(--crs-gray-700);
}

/* Mixed-mode breakdown row — shows the paid-mode + posted-mode
   sub-totals so the rep can see which slice came from each rule
   type. Two pills side-by-side under the headline value. */
.earned-this-month-breakdown {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 6px;
    font-size: 0.82rem;
    color: #334155;
    flex-wrap: wrap;
}
.earned-this-month-bd-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.7);
    border: 1px solid rgba(100, 116, 139, 0.2);
    font-weight: 600;
}
.earned-this-month-bd-item > i {
    opacity: 0.7;
}
.earned-this-month-bd-label {
    font-weight: 400;
    color: #475569;
    margin-left: 2px;
}
.earned-this-month-bd-sep {
    color: #94a3b8;
    font-weight: 700;
}

/* Per-tile filter chip — small inline pill appended to each KPI tile's
   label when a sub-filter (Paid/Unpaid) is active. Makes it explicit
   that the headline value on the tile is scoped to that filter, not
   the unfiltered set. The "SHOWING ONLY" banner above the tiles still
   declares the filter globally; this chip reinforces it at the point
   the user reads each value. */
.invoice-kpi-filter-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 8px;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0.01em;
    vertical-align: middle;
    white-space: nowrap;
    border: 1px solid;
}
.invoice-kpi-filter-tag > i {
    font-size: 0.65rem;
}
.invoice-kpi-filter-tag-paid {
    background: rgba(16, 185, 129, 0.12);
    border-color: rgba(16, 185, 129, 0.35);
    color: #065f46;
}
.invoice-kpi-filter-tag-unpaid {
    background: rgba(245, 158, 11, 0.12);
    border-color: rgba(245, 158, 11, 0.35);
    color: #92400e;
}

/* Per-tile contextual sub-label — appears just under the tile's
   headline value when a sub-filter is active. Explains in plain
   language what the number means under THIS filter (e.g. "$0 by
   definition — these invoices have been paid in full"). Pairs with
   the inline filter chip on the label row above. */
.invoice-kpi-filter-context {
    font-size: 0.78rem;
    line-height: 1.3;
    margin-top: 4px;
    margin-bottom: 4px;
    padding: 4px 8px;
    border-radius: 6px;
    border-left: 3px solid;
    font-style: italic;
}
/* One quiet note, three tabs. These lines were tinted green on Paid, amber
   on Unpaid and slate on All -- three coloured panels inside a white card,
   for a sentence that only explains the tile above it. The tab is already
   named; the note just reads. */
.invoice-kpi-filter-context.context-paid,
.invoice-kpi-filter-context.context-unpaid,
.invoice-kpi-filter-context.context-all {
    background: var(--crs-gray-100);
    border-left-color: var(--crs-gray-300);
    color: var(--crs-gray-700);
}
/* All-tab variant — neutral slate palette so the All view's per-tile
   context lines (e.g. "Face value of every invoice you posted this
   month") read as informational baseline, not a filter-specific
   override. Distinguishable from the green/amber filtered variants
   so the rep can tell at a glance which slice they're looking at. */

.filter-status-banner:hover {
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06),
                0 1px 3px rgba(0, 0, 0, 0.04);
}

/* Filter-icon disc on the left — gives the banner a sturdy anchor
   point and a clear "this is a filter notification" cue. */
.filter-status-banner .filter-status-icon-wrap {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    flex-shrink: 0;
    background: rgba(255, 255, 255, 0.55);
    border: 1px solid rgba(0, 0, 0, 0.06);
}
.filter-status-banner .filter-status-icon-wrap .fa-filter {
    font-size: 0.95rem;
}

/* Inline text block: prefix → arrow → bold label. The arrow gives
   the eye a path to the filter name without adding a colon. */
.filter-status-banner .filter-status-text {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    flex-wrap: wrap;
    line-height: 1.3;
}
.filter-status-banner .filter-status-prefix {
    color: var(--crs-gray-600, #6b7280);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.78rem;
}
.filter-status-banner .filter-status-arrow {
    font-size: 0.7rem;
    opacity: 0.55;
}
.filter-status-banner .filter-status-label {
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: -0.01em;
}

/* Clear-filter button — outlined, compact, dismissive without being
   loud. Hover feedback matches the banner color so the click target
   feels integrated. */
.filter-status-banner .filter-status-clear {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-left: auto;
    padding: 5px 12px;
    font-size: 0.82rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    background: rgba(255, 255, 255, 0.55);
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.05s ease;
    color: inherit;
}
.filter-status-banner .filter-status-clear:hover {
    background: rgba(255, 255, 255, 0.85);
}
.filter-status-banner .filter-status-clear:active {
    transform: translateY(1px);
}
.filter-status-banner .filter-status-clear .fa-times-circle {
    font-size: 0.85rem;
    opacity: 0.7;
}

/* Paid (green) variant — soft mint gradient with green text. */
.filter-status-banner-paid {
    color: #065f46;
    background: linear-gradient(135deg, #d1fae5 0%, #ecfdf5 100%);
    border-color: #6ee7b7;
}
.filter-status-banner-paid .filter-status-icon-wrap {
    color: #047857;
}
.filter-status-banner-paid .filter-status-arrow {
    color: #047857;
}

/* Unpaid (amber) variant — warm honey gradient with brown text. */
.filter-status-banner-unpaid {
    color: #78350f;
    background: linear-gradient(135deg, #fde68a 0%, #fef3c7 100%);
    border-color: #f59e0b;
}
.filter-status-banner-unpaid .filter-status-icon-wrap {
    color: #b45309;
}
.filter-status-banner-unpaid .filter-status-arrow {
    color: #b45309;
}

/* Shared "Totals" footer row across every commission-app table that
   carries a tfoot. Light gray fill + thicker top border so it visually
   separates from the data rows; numbers right-align via the dollar
   tabular-nums treatment that DataTables already applies. */
tfoot tr.table-totals-row td {
    background: var(--crs-gray-50, #f9fafb);
    border-top: 2px solid var(--crs-gray-300, #d1d5db);
    font-weight: 600;
    padding: 8px !important;
}
tfoot tr.table-totals-row td:first-child {
    text-align: left;
}

/* Tfoot deduction sub-line on the invoice-lines page. Shows the gross
   sum struck through followed by the PT/LD deductions, so the user
   sees how the smaller "commissionable" total was derived. */
.line-foot-deduction {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 8px;
    margin-top: 3px;
    font-size: 0.7rem;
    line-height: 1.3;
    color: var(--crs-gray-600, #6b7280);
}
.line-foot-deduction-orig {
    text-decoration: line-through;
    text-decoration-color: rgba(107, 114, 128, 0.55);
    color: var(--crs-gray-500, #9ca3af);
}
.line-foot-deduction-sub {
    color: var(--crs-red, #c8102e);
    font-weight: 500;
}

/* Override column on the invoice-lines drill-down. Stacks the per-line
   "Edit line" pencil (BCDocumentOverride on bcinvoiceline) above the
   per-Object-No "Override Object No" button (PassThroughObjectNo) when
   both apply. */
.line-override-cell {
    white-space: nowrap;
}
.line-override-cell .btn,
.line-override-cell .badge {
    display: inline-block;
    margin: 0;
}
.line-override-cell .btn + .btn,
.line-override-cell .btn + .badge {
    display: block;
    margin-top: 4px;
}

/* Per-line commission column on the invoice-lines drill-down. The
   banner above the table announces the rule + basis; cells just show
   the dollars. Hint text underneath calls out non-commissionable lines
   (pass-through / lost-damaged) so the $0.00 reads explicit. */
.line-commission-banner {
    border-left: 3px solid var(--crs-red, #c8102e);
    background: var(--crs-gray-50, #f9fafb);
}
.line-commission-banner .rate-pill {
    margin: 0 4px;
}
.line-commission-cell {
    text-align: right;
    white-space: nowrap;
}
.line-commission-hint {
    font-size: 0.68rem;
    color: var(--crs-gray-500, #9ca3af);
    font-style: italic;
    line-height: 1.2;
    margin-top: 1px;
}
.line-commission-footer {
    background: var(--crs-gray-50, #f9fafb);
    border-top: 2px solid var(--crs-gray-300, #d1d5db);
}
.line-commission-footer td { padding: 8px !important; }

/* Commission column "Earned: $X · paid-mode" sub-line. Shows the rep's
   actual booked commission for paid-mode rules (full × rate × paid_ratio)
   alongside the forecast in the main cell. Posted-mode rules render a
   simpler "earned at posting" tag — earned == forecast for those. */
.commission-earned-hint {
    font-size: 0.72rem;
    line-height: 1.25;
    margin-top: 3px;
    color: var(--crs-gray-700);
    white-space: nowrap;
}
.commission-earned-hint i {
    margin-right: 2px;
    color: var(--crs-green, #16a34a);
}
.commission-earned-fully i {
    color: var(--crs-green, #16a34a);
}
.commission-bucket-tag {
    display: inline-block;
    margin-left: 4px;
    padding: 0 5px;
    font-size: 0.62rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-radius: 4px;
    border: 1px solid currentColor;
    line-height: 1.4;
    vertical-align: 1px;
}
.commission-bucket-tag.bucket-paid {
    color: #92400e;
    background: #fef3c7;
    border-color: #fbbf24;
}
.commission-bucket-tag.bucket-posted {
    color: #1e40af;
    background: #dbeafe;
    border-color: #60a5fa;
}
.commission-bucket-tag.bucket-credited {
    color: #3f6212;
    background: #ecfccb;
    border-color: #a3e635;
}

/* Dashboard callout: "You share the following rep codes with other users." */
.split-banner {
    background: var(--crs-red-light);
    border: 1px solid var(--crs-red-tint);
    border-left: 3px solid var(--crs-red);
    border-radius: var(--crs-radius);
    padding: 0.9rem 1.1rem 1rem;
    margin-bottom: 1rem;
    color: var(--crs-gray-900);
    font-size: 0.9rem;
}
.split-banner .split-banner-title {
    display: flex;
    align-items: center;
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--crs-red-dark);
    margin: 0 0 0.45rem;
}
.split-banner .split-banner-title i { margin-right: 0.4rem; font-size: 0.85em; }
.split-banner-intro {
    margin: 0 0 0.7rem;
    line-height: 1.55;
    color: var(--crs-gray-700);
}
.split-banner ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
/* Shared-codes list: each code is its own bordered row, not a run-on
   line — the code, the rep's own %, and the split partners read as three
   distinct pieces instead of one dense sentence. */
.split-code-list li {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem;
    background: var(--crs-white);
    border: 1px solid var(--crs-red-tint);
    border-radius: var(--crs-radius);
    padding: 0.5rem 0.75rem;
    font-variant-numeric: tabular-nums;
}
.split-code-share { color: var(--crs-gray-900); }
.split-code-share strong { color: var(--crs-red-dark); }
.split-code-others { color: var(--crs-gray-600); font-size: 0.85rem; }
.split-banner li code {
    background: var(--crs-gray-100);
    border: 1px solid var(--crs-gray-300);
    border-radius: 4px;
    padding: 0.1rem 0.4rem;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--crs-red-dark);
}

/* Special-rules list: one card per rule, each internal line (name+badges /
   rate / condition / $ totals) on its own row instead of a single dense
   paragraph. */
.special-rule-list li {
    background: var(--crs-white);
    border: 1px solid var(--crs-red-tint);
    border-radius: var(--crs-radius);
    padding: 0.7rem 0.85rem;
}
.special-rule-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 0.3rem;
}
.special-rule-name { font-weight: 700; font-size: 0.95rem; color: var(--crs-gray-900); }
.special-rule-rate { color: var(--crs-gray-700); margin-bottom: 0.3rem; }
.special-rule-condition {
    color: var(--crs-gray-600);
    font-size: 0.85rem;
    margin-bottom: 0.3rem;
    word-break: break-word;
}
.special-rule-condition code {
    background: var(--crs-gray-100);
    border: 1px solid var(--crs-gray-300);
    border-radius: 4px;
    padding: 0.1rem 0.4rem;
    font-size: 0.8rem;
    color: var(--crs-gray-800, #1f2937);
}
.special-rule-and {
    display: inline-block;
    margin: 0 0.35rem;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--crs-gray-500);
}

/* Per-rule $ metrics under each rule in the special-rules banner. */
.special-rule-totals {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1.1rem;
    margin-top: 0.4rem;
    padding-top: 0.4rem;
    border-top: 1px dashed var(--crs-red-tint);
    font-size: 0.85rem;
}
.special-rule-metric { color: var(--crs-gray-700); }
.special-rule-metric strong {
    color: var(--crs-red-dark);
    font-variant-numeric: tabular-nums;
}
.special-rule-metric.special-rule-meta {
    color: var(--crs-gray-600);
    font-style: italic;
}

/* Per-rule badges in the Special commission rules banner. Show role
   (Default / Special / Bonus) and a "Excluded from quota" flag when the
   rule's revenue doesn't count toward % of Quota math. */
.rule-role-badge {
    display: inline-block;
    padding: 0.08rem 0.5rem;
    margin: 0 0.15rem;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    vertical-align: 1px;
    line-height: 1.4;
    background: var(--crs-gray-200, #e5e7eb);
    color: var(--crs-gray-800, #1f2937);
    border: 1px solid var(--crs-gray-300, #d1d5db);
}
.rule-role-badge.rule-role-special {
    background: rgba(200, 16, 46, 0.08);
    color: var(--crs-red-dark);
    border-color: var(--crs-red-tint, #fce8ec);
}
.rule-role-badge.rule-role-bonus {
    background: rgba(15, 157, 88, 0.10);
    color: #0b7a45;
    border-color: rgba(15, 157, 88, 0.25);
}
.rule-role-badge.rule-role-default {
    background: rgba(0, 102, 204, 0.10);
    color: #0b5fa6;
    border-color: rgba(0, 102, 204, 0.25);
}
.rule-role-badge.rule-role-noquota {
    background: rgba(217, 119, 6, 0.12);
    color: #92400e;
    border-color: rgba(217, 119, 6, 0.30);
}

/* View-filter pill buttons above the KPI cards (all / solo / shared). */
.view-filter {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    background: var(--crs-gray-100);
    border: 1px solid var(--crs-gray-300);
    border-radius: 999px;
    padding: 0.25rem;
}
.view-filter-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.9rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--crs-gray-700);
    text-decoration: none;
    transition: all var(--crs-trans);
    white-space: nowrap;
}
.view-filter-btn:hover {
    background: var(--crs-white);
    color: var(--crs-red);
    text-decoration: none;
}
.view-filter-btn.active {
    background: var(--crs-red);
    color: var(--crs-white);
    box-shadow: var(--crs-shadow-sm);
}
.view-filter-btn.active:hover { color: var(--crs-white); }
.view-filter-btn i { font-size: 0.8rem; }

/* Rep-name tooltip trigger on the Commission Dashboard heading */
.rep-name-tip {
    border-bottom: 1px dotted var(--crs-gray-500);
    cursor: help;
}

/* --------------------------------------------------------------------- *
 * Responsive "card" transformation for wide data tables on phones       *
 * Apply the `.responsive-cards` class to any <table> with <td data-label>*
 * cells. Below 768px, rows stack into readable cards with labeled       *
 * fields instead of forcing a horizontal scroll.                        *
 * DataTables' sort/search/paginate still work — we only change display. *
 * --------------------------------------------------------------------- */

@media (max-width: 768px) {
    .responsive-cards thead { display: none; }
    .responsive-cards,
    .responsive-cards tbody,
    .responsive-cards tr,
    .responsive-cards td {
        display: block;
        width: 100%;
        box-sizing: border-box;
    }
    .responsive-cards tr {
        background: var(--crs-white);
        border: 1px solid var(--crs-gray-300);
        border-left: 3px solid var(--crs-red);
        border-radius: var(--crs-radius);
        box-shadow: var(--crs-shadow-sm);
        margin-bottom: 0.75rem;
        padding: 0.65rem 0.85rem;
        /* Two-column mini-grid so "Amount + Win%" line up neatly */
        display: grid !important;
        grid-template-columns: 1fr 1fr;
        gap: 0.4rem 0.8rem;
    }
    .responsive-cards td {
        text-align: left !important;
        padding: 0 !important;
        border: none !important;
        background: transparent !important;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: normal;
    }
    .responsive-cards td::before {
        content: attr(data-label);
        display: block;
        font-size: 0.68rem;
        font-weight: 600;
        letter-spacing: 0.05em;
        text-transform: uppercase;
        color: var(--crs-gray-600);
        margin-bottom: 0.1rem;
    }
    /* Opportunity title spans full width, big and prominent */
    .responsive-cards td.oppty-name-cell {
        grid-column: 1 / -1;
        font-weight: 600;
        font-size: 0.95rem;
        padding-bottom: 0.2rem !important;
        border-bottom: 1px solid var(--crs-gray-200) !important;
        margin-bottom: 0.3rem;
    }
    .responsive-cards td.oppty-name-cell::before {
        display: none;
    }
    .responsive-cards td.oppty-name-cell a {
        color: var(--crs-red);
        font-weight: 600;
    }
    /* Amount stands out in brand red */
    .responsive-cards td.oppty-amount-cell {
        color: var(--crs-gray-900);
        font-weight: 700;
        font-size: 1rem;
        font-variant-numeric: tabular-nums;
    }
    /* Customer names: .table td { white-space:nowrap } + ellipsis clipped
       "Mechanical Sys…" while Amount sat empty. Full-width wrap. */
    .responsive-cards td.oppty-customer-cell,
    .responsive-cards td[data-label="Customer"] {
        grid-column: 1 / -1;
        white-space: normal !important;
        word-break: break-word;
        overflow-wrap: anywhere;
        overflow: visible;
        text-overflow: unset;
    }
    /* DataTables pagination / length / filter controls wrap cleanly */
    .dt-container .dt-length,
    .dt-container .dt-search { margin-bottom: 0.5rem; }
}
.chart-cell--text { padding: 0.25rem 0.25rem; }

/* KPI list (inside cards) */
.kpi-list {
    list-style: none;
    padding: 0;
    margin: 0;
}
.kpi-list li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.65rem 0;
    border-bottom: 1px solid var(--crs-gray-200);
    font-size: 0.95rem;
    color: var(--crs-gray-700);
}
.kpi-list li:last-child { border-bottom: none; }
.kpi-list li i { color: var(--crs-red); margin-right: 0.5rem; }
.kpi-list li span:last-child {
    font-weight: 700;
    color: var(--crs-gray-900);
    font-variant-numeric: tabular-nums;
}
/* Secondary metrics and the ranking rows: the LABEL AND THE VALUE are one
   link, so the number is a click target too. The anchor takes over the
   row's flex layout; the <li> stops being the flex parent so nothing
   shifts. One anchor per row -- no nesting. */
.kpi-list li:has(> .kpi-inline-drill) { display: block; padding: 0; }
a.kpi-inline-drill {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
    padding: 0.65rem 0;
    color: inherit;
    text-decoration: none;
}
.kpi-list--compact li:has(> .kpi-inline-drill) > a.kpi-inline-drill {
    padding: 0.4rem 0;
}
a.kpi-inline-drill .kpi-inline-label { text-decoration: underline dotted; text-underline-offset: 3px; }
a.kpi-inline-drill .kpi-inline-value {
    font-weight: 700;
    color: var(--crs-gray-900);
    font-variant-numeric: tabular-nums;
}
a.kpi-inline-drill:hover,
a.kpi-inline-drill:focus-visible { color: inherit; text-decoration: none; }
a.kpi-inline-drill:hover .kpi-inline-label,
a.kpi-inline-drill:focus-visible .kpi-inline-label { text-decoration: underline; }
a.kpi-inline-drill:hover .kpi-inline-value,
a.kpi-inline-drill:focus-visible .kpi-inline-value { text-decoration: underline; text-underline-offset: 3px; }
a.kpi-inline-drill:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }
.kpi-list--compact li { padding: 0.4rem 0; font-size: 0.9rem; }
.kpi-list .trophy { color: #D97706; }

.section-label {
    text-transform: uppercase;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--crs-gray-600);
    margin-bottom: 0.55rem;
}
.section-label i { color: var(--crs-red); margin-right: 0.35rem; }

.bounty-link {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.55rem 0.7rem;
    background: var(--crs-red-light);
    color: var(--crs-red-dark) !important;
    border-radius: var(--crs-radius);
    font-weight: 500;
    margin-bottom: 0.4rem;
    transition: all var(--crs-trans);
    cursor: pointer;
    text-decoration: none;
}
.bounty-link:hover {
    background: var(--crs-red);
    color: var(--crs-white) !important;
}
.bounty-link i { color: inherit !important; }

.bounty-empty {
    background: var(--crs-gray-100);
    border: 1px dashed var(--crs-gray-400);
    border-radius: var(--crs-radius);
    color: var(--crs-gray-600);
    padding: 0.75rem;
    font-size: 0.9rem;
}
.bounty-empty i { color: var(--crs-red); margin-right: 0.4rem; }

/* Open Opportunities table — tighten up */
#table_id { margin-top: 0.5rem; }
#table_id thead th {
    background: var(--crs-gray-100);
    color: var(--crs-gray-700);
    font-size: 0.78rem !important;
    text-transform: uppercase !important;
    letter-spacing: 0.04em;
    font-weight: 600;
    border-bottom: 2px solid var(--crs-gray-300);
    padding: 0.6rem 0.75rem;
}
#table_id tbody td {
    padding: 0.55rem 0.75rem;
    font-size: 0.9rem;
    color: var(--crs-gray-900);
}

/* --------------------------------------------------------------------- *
 * Deals closing soon (sidebar)                                           *
 * --------------------------------------------------------------------- */

.deals-closing {
    margin-top: 1.5rem;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.10);
    border-radius: var(--crs-radius);
    padding: 0.75rem;
}
.deals-closing-header {
    color: var(--crs-white);
    font-weight: 600;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding-bottom: 0.6rem;
    margin-bottom: 0.5rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.deals-closing-header i { color: var(--crs-red); }
.deals-closing-list {
    list-style: none;
    padding: 0;
    margin: 0;
    max-height: 280px;
    overflow-y: auto;
}
.deals-closing-list li { margin: 0; padding: 0; }
.deals-closing-list li + li { border-top: 1px solid rgba(255, 255, 255, 0.06); }
.deals-closing-list a {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.5rem 0.25rem;
    color: var(--crs-white) !important;
    text-decoration: none;
    font-size: 0.85rem;
    transition: background var(--crs-trans);
    border-radius: calc(var(--crs-radius) - 2px);
}
.deals-closing-list a:hover {
    background: rgba(200, 16, 46, 0.14);
    padding-left: 0.5rem;
}
.deals-closing-name {
    font-weight: 500;
    line-height: 1.3;
    overflow-wrap: break-word;
}
.deals-closing-date {
    font-size: 0.72rem;
    color: rgba(255, 255, 255, 0.6);
    letter-spacing: 0.02em;
}
.deals-closing-date i { margin-right: 0.2rem; }
.deals-closing-list::-webkit-scrollbar { width: 6px; }
.deals-closing-list::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.15);
    border-radius: 3px;
}
.deals-closing-list::-webkit-scrollbar-thumb:hover { background: var(--crs-red); }

/* --------------------------------------------------------------------- *
 * Toggle switches (.switch/.slider) — pink -> CRS red                    *
 * --------------------------------------------------------------------- */

.switch .slider { background-color: var(--crs-gray-500) !important; }
.switch input:checked + .slider {
    background-color: var(--crs-red) !important;
}
.switch input:focus + .slider {
    box-shadow: 0 0 0 0.2rem rgba(200, 16, 46, 0.25) !important;
}

/* --------------------------------------------------------------------- *
 * Mobile responsive tweaks (shared across sales + commissions)           *
 * --------------------------------------------------------------------- */

/* Let Bootstrap .row cells wrap naturally on mobile */
@media (max-width: 768px) {
    html, body { overflow-x: hidden; }
    .container-fluid { padding: 0.85rem !important; }

    /* Commissions dashboard: stack KPI cards and tighten spacing */
    .row > [class*="col-md-"],
    .row > [class*="col-lg-"] { margin-bottom: 0.75rem; }

    /* Typography scale-down so headings don't wrap awkwardly */
    h1 { font-size: 1.45rem; }
    h2 { font-size: 1.2rem; }
    h3, .oppty-section-heading { font-size: 1.05rem; }
    h4 { font-size: 0.95rem; }
    .kpi-value { font-size: 1.35rem; }
    .kpi-card { min-height: 90px; padding: 0.85rem 0.95rem; }

    /* Cards take less padding on mobile */
    .sales-card { padding: 0.9rem 0.95rem; margin-bottom: 0.9rem; }
    .sales-card-header {
        font-size: 0.95rem;
        flex-wrap: wrap;
        gap: 0.4rem;
    }
    .sales-card-action { font-size: 0.72rem; padding: 0.2rem 0.55rem; }

    /* Stack two/three-column chart rows */
    .chart-row--two, .chart-row--three { grid-template-columns: 1fr !important; }
    /* Phone height belongs to .chart-canvas-box, above. Capping the
       CANVAS is what let CSS and Chart.js disagree about the drawing
       box in the first place. */

    /* Force table-responsive wrappers to truly scroll horizontally */
    .table-responsive {
        -webkit-overflow-scrolling: touch;
        margin-bottom: 0.75rem;
    }
    .table { font-size: 0.82rem; }
    .table td, .table th { padding: 0.4rem 0.5rem !important; white-space: nowrap; }

    /* DataTables toolbar stacks vertically */
    .dt-container .dt-length,
    .dt-container .dt-search,
    .dt-container .dt-info,
    .dt-container .dt-paging {
        float: none !important;
        text-align: left !important;
        width: 100%;
        margin-bottom: 0.4rem;
    }
    .dt-container .dt-search input { width: 100%; max-width: none; }

    /* Commission page selector pills wrap */
    .period-selector, .period-selector .btn-group {
        display: flex;
        flex-wrap: wrap;
        gap: 0.35rem;
    }

    /* Buttons: full-width on small screens when part of a card footer */
    .sales-card .btn-block-sm { width: 100%; }

    /* Bootstrap d-flex/justify-content-between groups — allow wrap */
    .d-flex.justify-content-between { flex-wrap: wrap; gap: 0.5rem; }
}

/* Extra-tight layout for very narrow phones */
@media (max-width: 480px) {
    .kpi-grid { grid-template-columns: 1fr 1fr; gap: 0.6rem; }
    .kpi-card { padding: 0.75rem 0.85rem; min-height: 80px; }
    .kpi-value { font-size: 1.15rem; }
    .kpi-label { font-size: 0.72rem; }
    .main_content { padding: 0.7rem !important; }
    .sidebar .btn-group .dropdown-toggle { font-size: 0.9rem; padding: 0.45rem 0.6rem; }
}

/* Admin-like pages: make Django admin tables readable on mobile */
@media (max-width: 768px) {
    #content table, .change-list table, .change-form table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
}

/* --------------------------------------------------------------------- *
 * Mobile-friendly forms (create opportunity, edit profile, etc.)         *
 * --------------------------------------------------------------------- */

/* Create-opportunity grid collapses to a single column on phones; on
   tablets it uses 2 columns so "amount + win %" can live side-by-side. */
@media (max-width: 991.98px) {
    .grid-new-oppty {
        grid-template-areas:
            'hexagroup hexagroup'
            'project_branch project_branch'
            'customer customer'
            'name name'
            'collaborator collaborator'
            'amount win'
            'start-date duration'
            'state city'
            'type status'
            'lob lob'
            'notes notes'
            'submit submit' !important;
        grid-template-columns: 1fr 1fr !important;
        grid-gap: 0.6rem !important;
    }
    .new-oppty-btn { max-width: 12rem; width: auto; }
}
@media (max-width: 575.98px) {
    .grid-new-oppty {
        grid-template-areas:
            'hexagroup'
            'project_branch'
            'customer'
            'name'
            'collaborator'
            'amount'
            'win'
            'start-date'
            'duration'
            'state'
            'city'
            'type'
            'status'
            'lob'
            'notes'
            'submit' !important;
        grid-template-columns: 1fr !important;
    }
    .new-oppty-btn { max-width: none !important; width: 100%; }
}

/* Same treatment as .grid-new-oppty: two columns on tablet, one on phones.
   Covers create_contact / contact / activity / create_customer if they
   still use the legacy CSS grids (form-row pages already stack on xs). */
@media (max-width: 991.98px) {
    .grid {
        grid-template-columns: 1fr 1fr !important;
        max-width: 100% !important;
        grid-gap: 0.6rem !important;
    }
    .grid-name, .grid-web, .grid-form { grid-column: 1 / -1 !important; }
    .grid-new-contact {
        grid-template-areas:
            'fname lname'
            'company company'
            'title email'
            'cellp office'
            'notes notes'
            'btn btn' !important;
        grid-template-columns: 1fr 1fr !important;
    }
    .new-contact-btn { max-width: none !important; width: 100%; }
    .activity-grid {
        grid-template-areas:
            'date customer'
            'type type'
            'detail detail'
            'button button' !important;
        grid-template-columns: 1fr 1fr !important;
    }
    .activity-grid-item { padding-right: 0.5rem !important; }
    .activity-button-item { max-width: none !important; width: 100%; }
}
@media (max-width: 575px) {
    .grid {
        grid-template-columns: 1fr !important;
    }
    .grid-new-contact {
        grid-template-areas:
            'fname'
            'lname'
            'company'
            'title'
            'email'
            'cellp'
            'office'
            'notes'
            'btn' !important;
        grid-template-columns: 1fr !important;
    }
    .activity-grid {
        grid-template-areas:
            'date'
            'customer'
            'type'
            'detail'
            'button' !important;
        grid-template-columns: 1fr !important;
    }
    .activity-grid-item { padding-right: 0 !important; }
}

/* Touch-friendly form controls everywhere (applies to crispy-rendered
   inputs, selects, textareas). iOS zooms the page on focus if the input
   font-size is below 16px — keep it at 16px on mobile. */
@media (max-width: 768px) {
    .form-control, .form-select, input[type=text], input[type=email],
    input[type=password], input[type=number], input[type=date],
    input[type=tel], input[type=url], select, textarea {
        font-size: 16px !important;
        min-height: 2.75rem;
        padding: 0.55rem 0.75rem !important;
        width: 100% !important;
        max-width: 100% !important;
    }
    /* Commission period month <select> ("Year to date through Jul 2026").
       Bootstrap .form-control-sm sets height:~31px which iOS treats as
       authoritative over min-height, so the 16px value clips against the
       top border. Beat that with height:auto + a 44px min. */
    #period_select,
    #period_select_header,
    #endMonthForm select.form-control,
    #endMonthFormHeader select.form-control {
        height: auto !important;
        min-height: 44px !important;
        padding: 0.5rem 2rem 0.5rem 0.75rem !important;
        font-size: 16px !important;
        line-height: 1.25 !important;
        overflow: visible;
        box-sizing: border-box;
    }
    textarea.form-control, textarea { min-height: 6rem; }
    /* Field captions stay block + left. NEVER set display:block on
       .custom-control-label — that fills the control and Bootstrap's
       absolute ::before (left: -1.5rem) paints on the letters
       (He[x] Lead? / Bre[x]hing Air). * { padding: 0 } in
       sales_styles.css removes the 1.5rem gutter if we miss a selector. */
    label:not(.custom-control-label):not(.form-check-label):not(.clair-choice),
    .form-label,
    .control-label {
        font-size: 0.85rem;
        font-weight: 600;
        margin-bottom: 0.25rem !important;
        display: block;
        text-align: left;
    }
    label.custom-control-label,
    label.form-check-label,
    label.clair-choice {
        display: inline !important;
        font-weight: 400;
        margin-bottom: 0 !important;
        text-align: left;
    }
    .form-group {
        display: block;
        text-align: left;
    }
    .flex-grid > .main_content,
    .main_content form,
    .grid-new-oppty,
    .edit-oppty,
    .new-oppty-item,
    .form-row,
    #login_form {
        text-align: left !important;
    }
    .form-group { margin-bottom: 0.9rem !important; }
    .form-row { margin-left: 0 !important; margin-right: 0 !important; }
    .form-row > [class*="col-"] { padding-left: 0 !important; padding-right: 0 !important; }
    .btn { min-height: 2.75rem; font-size: 1rem; }
    .btn-block { width: 100% !important; }
    select.select2-hidden-accessible + .select2-container { width: 100% !important; }
    .select2-container .select2-selection--single,
    .select2-container--default .select2-selection--single { min-height: 2.75rem !important; }
    .select2-container--default .select2-selection--single .select2-selection__rendered {
        line-height: 2.6rem !important;
        font-size: 16px !important;
    }

    /* "Edit your information" / password-change panel (#login_form).
       Keep a 1rem gutter — width:100% made the red Change button
       ~6px wider than the inputs and kiss the 390px edge. */
    #login_form {
        width: min(440px, calc(100vw - 2rem)) !important;
        min-width: 0 !important;
        margin: 0.6rem auto !important;
        padding: 1.1rem 1rem !important;
        box-sizing: border-box;
    }
    #login_form .login_btn {
        width: 100% !important;
        max-width: 100%;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding: 0.7rem !important;
        box-sizing: border-box;
    }

    /* Any form wrapped in main_content: give it the card-style padding */
    .main_content form { padding: 0 0.25rem; }
    .crispy_flex { flex-direction: column; width: 100%; }

    /* Opportunity detail: contacts block is height:100vh inline — don't
       force a full-viewport empty well on a phone. */
    #contacts { height: auto !important; }

    /* Manual invoice line table: drop the 13-col th min-widths so the
       existing .table-responsive is the scroller, not the page. */
    #manual-lines-table th,
    #manual-lines-table td { min-width: 0 !important; }

    /* Collaborator <select multiple>: taller tap targets, 16px text */
    select.collaborator-select,
    #id_project_collaborator_reps,
    #id_base-project_collaborator_reps {
        min-height: 10rem;
        font-size: 16px !important;
    }
    select.collaborator-select option,
    #id_project_collaborator_reps option,
    #id_base-project_collaborator_reps option {
        padding: 0.45rem 0.5rem;
    }
    .search-input { width: 100% !important; }
    #search-glass { transform: none; }

    /* Auth / profile card: drop the absolute-center that can clip on a phone.
       Keep the 2rem viewport gutter so the Change button matches inputs. */
    #login_form {
        position: relative !important;
        top: auto !important;
        left: auto !important;
        transform: none !important;
        min-width: 0 !important;
        width: min(440px, calc(100vw - 2rem)) !important;
        max-width: calc(100vw - 2rem) !important;
        margin: 0.6rem auto !important;
        padding: 1.1rem 1rem !important;
        box-sizing: border-box;
    }
    .image-codered-login,
    .image-codered-logout {
        height: auto !important;
        min-height: calc(100vh - 64px);
        width: 100%;
        padding: 1.25rem;
    }

    /* Commission header titles + filter widgets that force a wide row */
    .commission-page-header h2 { white-space: normal !important; }
    .rep-filter-cell { min-width: 0 !important; max-width: none !important; width: 100%; }
    .controls-row .form-control-sm { min-width: 0 !important; width: 100%; }
    .controls-cell { width: 100%; }
    .range-form { flex-wrap: wrap !important; }
    .range-form > div { flex: 1 1 100%; min-width: 0; }

    /* Touch-sized nav + primary actions (~44px) */
    #header .navbar-toggler {
        min-width: 44px;
        min-height: 44px;
        padding: 0.55rem 0.75rem;
    }
    #header .navbar-nav .nav-link,
    #header .logout-btn,
    #header button#logout_link,
    #header .dropdown-item {
        min-height: 44px;
        padding: 0.7rem 0.9rem !important;
    }
    a.sidebar_link { min-height: 44px; }
    .sidebar-faq-row > a.sidebar_link { width: auto; }
    .login_btn, .main_content form .login_btn, #login_form .login_btn {
        width: 100% !important;
        min-height: 44px;
    }
}

/* Make the "Create Opportunity" heading + the potential-commission
   indicator wrap on small screens instead of running off the right. */
@media (max-width: 768px) {
    h1.main-h1, h1 {
        font-size: 1.2rem !important;
        line-height: 1.3;
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 0.5rem;
    }
    #commission-amount {
        font-size: 1rem !important;
        font-weight: 700;
        color: var(--crs-red) !important;
    }
}

/* --------------------------------------------------------------------- *
 * Clair form controls (Claude Design)                                    *
 * Boolean: .clair-choice--single  — one row, not a chip                  *
 * Multi:   .clair-choice-list + .clair-choice — wrap chips, never a grid *
 *                                                                        *
 * Edit-page He[x] Lead? / Bre[x]hing Air is three layers:                *
 *  1. BS4 .custom-control absolutely positions the input and paints      *
 *     label::before at left: -1.5rem.                                    *
 *  2. The old LOB pill CSS (removed, do not layer) re-showed that input  *
 *     at position:absolute; left: 0.65rem. Hexa Lead was not in those    *
 *     selectors, so it kept the -1.5rem fake box with no gutter.         *
 *  3. @media (max-width: 768px) { label { display: block } } hit         *
 *     .custom-control-label — the label fills the control and the        *
 *     absolute box paints on the letters.                                *
 * * { padding: 0 } in sales_styles.css is why a missed selector loses    *
 * the 1.5rem gutter immediately.                                         *
 *                                                                        *
 * CheckboxSelectMultiple is only OpportunityForm + DetailForm.           *
 * Invoice PT/LD/CM boxes are table cells — leave them.                   *
 * --------------------------------------------------------------------- */

.clair-choice--single,
.clair-choice--single.custom-control,
.clair-choice--single .custom-control,
.edit-oppty > .custom-control.custom-checkbox {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 44px;
    text-align: left;
    padding: 0;
    margin: 0;
    background: transparent;
    border: 0;
    white-space: normal;
}

.clair-choice--single input[type="checkbox"],
.clair-choice--single .custom-control-input,
.clair-choice--single .form-check-input,
.edit-oppty > .custom-control.custom-checkbox > input[type="checkbox"] {
    position: static !important;
    left: auto !important;
    top: auto !important;
    transform: none !important;
    opacity: 1 !important;
    z-index: auto !important;
    width: 16px !important;
    height: 16px !important;
    min-width: 16px;
    max-width: 16px !important;
    margin: 0 !important;
    flex: 0 0 auto;
    padding: 0 !important;
    float: none;
}

/* Create Hexa Lead sits in the same 15px gutter as the other fields.
   Bootstrap .custom-control padding-left: 1.5rem was the 41px indent. */
.grid-new-oppty .new-oppty-hexagroup,
.grid-new-oppty .new-oppty-hexagroup .clair-choice--single,
.grid-new-oppty .new-oppty-hexagroup .form-group {
    padding-left: 0;
    margin-left: 0;
}

.clair-choice--single .custom-control-label,
.clair-choice--single .form-check-label,
.clair-choice--single label,
.edit-oppty > .custom-control.custom-checkbox > label {
    position: static;
    display: inline;
    flex: 1 1 auto;
    min-width: 0;
    padding: 0;
    margin: 0;
    text-align: left;
    font-weight: 400;
    line-height: 1.35;
    cursor: pointer;
    white-space: normal;
}

.clair-choice--single .custom-control-label::before,
.clair-choice--single .custom-control-label::after,
.edit-oppty .custom-control-label::before,
.edit-oppty .custom-control-label::after {
    display: none !important;
    content: none !important;
}

.clair-choice-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: flex-start;
    align-items: flex-start;
    padding: 0.25rem 0;
    text-align: left;
}

.clair-choice,
.clair-choice-list .custom-control,
.clair-choice-list .form-check {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px 10px 12px;
    min-height: 44px;
    border: 1px solid #ced4da;
    border-radius: 999px;
    background: #fff;
    margin: 0;
    text-align: left;
    white-space: normal;
    cursor: pointer;
    user-select: none;
    font-weight: 400;
    line-height: 1.3;
}

.clair-choice:has(input:checked),
.clair-choice-list .custom-control:has(input:checked),
.clair-choice-list .form-check:has(input:checked) {
    background: #e8f4fd;
    border-color: #4a9fd5;
}

.clair-choice input[type="checkbox"],
.clair-choice-list .custom-control-input,
.clair-choice-list .form-check-input,
.clair-choice-list input[type="checkbox"] {
    position: static !important;
    left: auto !important;
    top: auto !important;
    transform: none !important;
    opacity: 1 !important;
    width: 16px !important;
    height: 16px !important;
    min-width: 16px;
    max-width: 16px !important;
    margin: 0 !important;
    flex: 0 0 auto;
    padding: 0 !important;
    float: none;
}

.clair-choice span,
.clair-choice-list .custom-control-label,
.clair-choice-list .form-check-label {
    position: static;
    display: inline;
    padding: 0;
    margin: 0;
    text-align: left;
    white-space: normal;
    overflow-wrap: anywhere;
    font-weight: 400;
    cursor: pointer;
}

.clair-choice-list .custom-control-label::before,
.clair-choice-list .custom-control-label::after {
    display: none !important;
    content: none !important;
}

/* Invoice add rhythm: captions left, primary action after the last field. */
.main_content form label:not(.custom-control-label):not(.form-check-label):not(.clair-choice),
.main_content form .form-label,
.main_content form .control-label,
.main_content form .form-group,
.edit-oppty,
.grid-new-oppty,
.form-row,
#login_form,
#login_form label:not(.custom-control-label):not(.form-check-label):not(.clair-choice) {
    text-align: left;
}

/* End-of-form actions — NOT sticky. position:sticky;bottom:0 pins the
   button to the first viewport (y≈783 after Amount) while Notes is
   still at y≈1682. Invoice add may keep .form-sticky-actions. */
.form-end-actions,
.grid-new-oppty .form-end-actions,
.edit-oppty-submit-wrap,
.main_content form .form-end-actions,
#login_form .form-end-actions {
    position: static !important;
    bottom: auto !important;
    z-index: auto;
    box-shadow: none;
    border-top: 0;
    background: transparent;
    margin-top: 0.75rem;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    width: 100%;
    max-width: 12rem;
}

@media (max-width: 575.98px) {
    .form-end-actions,
    .grid-new-oppty .form-end-actions,
    .new-oppty-btn,
    .edit-oppty-submit-wrap,
    .main_content form .form-end-actions,
    #login_form .form-end-actions {
        max-width: none;
        width: 100%;
        padding-bottom: env(safe-area-inset-bottom, 0px);
    }
    .form-end-actions .login_btn,
    .form-end-actions .btn,
    .new-oppty-btn .login_btn,
    .edit-oppty-submit {
        width: 100% !important;
        min-height: 48px;
    }
}

@media (min-width: 576px) {
    .form-end-actions .login_btn,
    .form-end-actions .btn,
    .new-oppty-btn .login_btn,
    .edit-oppty-submit-wrap .login_btn {
        max-width: 12rem;
        width: auto !important;
        min-height: 44px;
    }
}

/* --------------------------------------------------------------------- *
 * Opportunity DETAIL / EDIT page (/sales/<slug>) — mobile rules          *
 * --------------------------------------------------------------------- */

@media (max-width: 991.98px) {
    .edit-oppty {
        grid-template-columns: 1fr 1fr !important;
        max-width: 100% !important;
        grid-gap: 0.75rem !important;
        padding: 0 0.25rem;
    }
}
@media (max-width: 575px) {
    .edit-oppty {
        grid-template-columns: 1fr !important;
    }
}

@media (max-width: 768px) {
    .edit-oppty-submit {
        width: 100%;
        margin-left: 0 !important;
        margin-top: 0.5rem;
    }

    /* Upload + file list section — stack instead of side-by-side */
    .view-files-section {
        display: flex !important;
        flex-direction: column !important;
        height: auto !important;
        border-top: 1px solid var(--crs-red) !important;
        margin-top: 1.5rem !important;
        padding-top: 1rem;
        gap: 1rem;
    }
    .view-files-upload, .view-files-list { flex-grow: 1 !important; width: 100%; }
    .view-files-list > div[style*="justify-content: flex-end"] {
        justify-content: space-between !important;
        gap: 0.5rem;
        flex-wrap: wrap;
    }

    /* Similar-projects section: drop the fixed 100vh and the huge top spacing */
    .similar-projects-section {
        height: auto !important;
        border-top: 1px solid var(--crs-red);
        margin-top: 1.5rem !important;
    }
    #edit-project-name, #edit-project-name h1 {
        width: 100% !important;
        margin: 0.5rem 0 !important;
        padding-left: 0 !important;
    }
    #edit-project-name p { padding-left: 0 !important; font-size: 0.9rem !important; }
    #change-project { margin-bottom: 1rem !important; }
}

/* Desktop restore: the default inline styles on .view-files-section
   (display: flex; height: 100vh) were removed from the template, so
   reinstate them for wide screens. */
@media (min-width: 769px) {
    .view-files-section {
        display: flex;
        height: 100vh;
        border-top: 1px solid var(--crs-red);
        margin-top: 2rem;
    }
    .view-files-upload { flex-grow: 2; margin-top: 1rem; }
    .view-files-list { flex-grow: 4; }
    .similar-projects-section {
        border-top: 1px solid var(--crs-red);
        margin-top: 2rem;
        height: 100vh;
    }
}

/* Historical-month cells / columns ---------------------------------------
   Months overlaid from HistoricalCommissionData (hand-loaded pre-BC totals).
   Drill-down is available but shows summary data only. Style them so it's
   obvious at a glance the month is a totals-only entry — italic, slightly
   muted. The header gets a small clock icon (.historical-icon) and a subtle
   tinted background to mark the column. */
.historical-cell {
    color: var(--crs-gray-700, #495057);
    font-style: italic;
    border-bottom: 1px dotted var(--crs-gray-400, #ced4da);
}
a.historical-cell { text-decoration: none; }
a.historical-cell:hover { color: #2563eb; }
th.historical-col {
    background-color: #faf6ed !important;  /* warm parchment tint */
    cursor: help;
}
.historical-icon {
    font-size: 0.72em;
    margin-left: 3px;
    opacity: 0.75;
    color: var(--crs-gray-600, #6c757d);
}

/* Payment Pipeline — compact horizontal strip.
   Carries the "customer pays → commission grows" framing in one tight
   row instead of the prior 3-deep hero banner. Green left stripe keeps
   the "positive / incoming money" branding without eating real estate. */
.pipeline-strip {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0 0.7rem;
    padding: 0.55rem 0.85rem;
    background: linear-gradient(90deg, #f3faf5 0%, #ffffff 70%);
    border: 1px solid #cfe2d4;
    border-left: 3px solid #0f9d58;
    border-radius: 6px;
    font-size: 0.95rem;
    line-height: 1.4;
}
.pipeline-strip-title {
    font-weight: 600;
    color: #0b7a45;
    margin-right: 0.4rem;
    white-space: nowrap;
}
.pipeline-strip-title > i { margin-right: 4px; }
.pipeline-strip-flow {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0 0.45rem;
    font-variant-numeric: tabular-nums;
}
.pipeline-strip-label {
    color: var(--crs-gray-600, #5f6368);
    font-size: 0.82rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
}
.pipeline-strip-label-reward { color: #0b7a45; }
.pipeline-strip-amount {
    font-weight: 700;
    color: var(--crs-gray-900, #202124);
    font-size: 1rem;
}
.pipeline-strip-amount-reward {
    color: #0b7a45;
    font-size: 1.1rem;
}
.pipeline-strip-arrow {
    color: #0f9d58;
    font-size: 0.95rem;
    margin: 0 0.25rem;
    animation: pipeline-nudge 2.4s ease-in-out infinite;
}
@keyframes pipeline-nudge {
    0%,  100% { transform: translateX(0); }
    50%       { transform: translateX(3px); }
}
.pipeline-strip-note {
    color: var(--crs-gray-500, #8a8f99);
    font-size: 0.82rem;
    font-style: italic;
}

/* Help (?) button for the Payment Pipeline strip. Reuses .kpi-help
   styling but positioned inline at the right edge of the strip (the
   strip is horizontal flex; push the help button to the far right).
   Selector intentionally compound (.pipeline-strip .pipeline-strip-help +
   .kpi-help.pipeline-strip-help) so its specificity beats the plain
   .kpi-help rule further down in this file — otherwise source order
   gives .kpi-help's position:absolute the win and the button lands
   off-screen at top:8px right:8px of whatever ancestor happens to be
   positioned. */
.pipeline-strip .pipeline-strip-help,
.kpi-help.pipeline-strip-help {
    position: static !important;   /* override .kpi-help's absolute positioning */
    top: auto !important;
    right: auto !important;
    margin-left: auto;             /* pushes to right edge of the flex row */
    flex: 0 0 auto;
    align-self: center;
}

/* Current-month projection banner — slim strip showing this month's
   in-progress numbers + a linear projection to month-end. Sits between
   the headline KPIs and the commission pipeline. Visually distinct from
   the (green) Payment Pipeline strip — uses an amber/in-progress accent
   so reps register it as "this is still being shaped" not "this is settled." */
.current-month-banner {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0 0.9rem;
    padding: 0.65rem 1rem;
    background: linear-gradient(90deg, #fffbeb 0%, #ffffff 70%);
    border: 1px solid #fde68a;
    border-left: 3px solid #d97706;
    border-radius: 6px;
    line-height: 1.4;
}
.current-month-banner-title {
    font-weight: 600;
    color: #92400e;
    margin-right: 0.6rem;
    white-space: nowrap;
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
}
.current-month-banner-title > i {
    margin-right: 4px;
    font-size: 0.95em;
}
.current-month-banner-subtitle {
    color: var(--crs-gray-600, #5f6368);
    font-size: 0.78rem;
    font-weight: 500;
    font-style: italic;
}
.current-month-banner-flow {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0 1.1rem;
    flex: 1 1 auto;
}
.current-month-stat {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}
.current-month-stat-label {
    color: var(--crs-gray-600, #5f6368);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
}
.current-month-stat-value {
    font-weight: 700;
    color: var(--crs-gray-900, #202124);
    font-size: 1rem;
    font-variant-numeric: tabular-nums;
}
.current-month-stat-projected .current-month-stat-label { color: #92400e; }
.current-month-stat-projected .current-month-stat-value { color: #92400e; font-size: 1.1rem; }
.current-month-banner-arrow {
    color: #d97706;
    font-size: 0.9rem;
    margin: 0 0.15rem;
}

/* New responsive pipeline layout for the in-progress month banner.
   Replaces the wrap-prone single flex row with: a header strip
   (title · methodology · help) above, and a CSS-grid of metric
   cells below. Auto-fits column count to viewport — 4 across at
   1200px+, 2 across at ~600px, 1 column on phones. */
.current-month-banner {
    /* Override the default flex-row-wrap layout above so the new
       header + pipeline grid stacks vertically. flex-wrap MUST be
       reset to nowrap — the inherited "wrap" from the row-layout
       version interacts badly with column flex (browsers compute
       phantom-tall flex lines), inflating the banner from ~110px
       to ~325px even though every child is well under 100px tall. */
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 0.3rem;
    padding: 0.5rem 0.85rem;
}
.current-month-banner-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    line-height: 1.2;
}
.current-month-banner-method {
    flex: 1 1 auto;
    font-size: 0.72rem;
    color: var(--crs-gray-600, #5f6368);
    font-style: italic;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}
.current-month-banner-method > i {
    color: #92400e;
    font-style: normal;
}
.current-month-banner-warn {
    display: inline-flex;
    align-items: center;
    padding: 0.05rem 0.5rem;
    border-radius: 999px;
    background: rgba(245, 158, 11, 0.18);
    color: #92400e;
    font-style: normal;
    font-weight: 600;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.current-month-pipeline {
    /* Spans every column of the parent .cv3-month-4up grid — without
       this it's a single, non-spanning grid item confined to that
       grid's first track (~1/4 width), squeezing this whole auto-fit
       grid into a quarter of the available width. */
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 0.4rem;
    align-items: stretch;
}
.current-month-pipeline .cmp-stage {
    height: 100%;
}
.cmp-stage {
    background: rgba(255, 255, 255, 0.55);
    border: 1px solid rgba(146, 64, 14, 0.12);
    border-radius: 0.4rem;
    padding: 0.35rem 0.6rem;
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
    text-align: left;
    text-decoration: none;
    color: inherit;
    transition: background 150ms ease, border-color 150ms ease;
    font-family: inherit;
    line-height: 1.25;
    /* Reset native button defaults so <button class="cmp-stage"> reads
       identical to the <a class="cmp-stage"> siblings. */
    appearance: none;
}
.cmp-stage:hover {
    background: rgba(255, 255, 255, 0.95);
    border-color: rgba(146, 64, 14, 0.3);
    text-decoration: none;
    color: inherit;
}
button.cmp-stage {
    cursor: pointer;
}
.cmp-stage-label {
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    color: var(--crs-gray-600, #5f6368);
    letter-spacing: 0.04em;
}
.cmp-stage-actual {
    font-size: 1rem;
    font-weight: 700;
    color: var(--crs-gray-900, #202124);
    font-variant-numeric: tabular-nums;
}
.cmp-stage-projected {
    font-size: 0.72rem;
    color: #b45309;
    font-style: italic;
    font-variant-numeric: tabular-nums;
}
.cmp-arrow {
    color: #f59e0b;
    font-weight: 700;
    margin-right: 0.15rem;
    font-style: normal;
}
.cmp-stage-sub {
    font-size: 0.68rem;
    color: var(--crs-gray-600, #5f6368);
    font-weight: 500;
    margin-left: 0.25rem;
}
/* No-quota sub-stack stacked under each in-progress pipeline tile. The
   tile's headline value is the QUOTA'D-rep slice (matches the quota
   chart bar); this sub-stack adds the no-quota subtotal and the all-rep
   total in two compact rows so the user can tie back to the drill-down
   without a separate callout. */
.cmp-stage-substack {
    margin-top: 0.3rem;
    padding-top: 0.25rem;
    border-top: 1px solid rgba(146, 64, 14, 0.12);
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
}
.cmp-stage-subline {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.4rem;
    font-size: 0.7rem;
    line-height: 1.25;
    color: var(--crs-gray-600, #5f6368);
}
.cmp-stage-subline .cmp-stage-sublabel {
    font-size: 0.65rem;
    text-transform: lowercase;
    letter-spacing: 0.02em;
}
.cmp-stage-subline .cmp-stage-subvalue {
    font-variant-numeric: tabular-nums;
    font-weight: 500;
}
.cmp-stage-subline-total {
    color: var(--crs-gray-900, #202124);
    font-weight: 600;
    border-top: 1px dashed rgba(146, 64, 14, 0.18);
    padding-top: 0.15rem;
    margin-top: 0.05rem;
}
.cmp-stage-subline-total .cmp-stage-subvalue {
    font-weight: 700;
}
.cmp-stage-quota .quota-attainment-gauge {
    margin-top: 0.1rem;
}
.cmp-stage-quota .quota-attainment-track {
    height: 0.4rem;
}
.current-month-banner .current-month-banner-help,
.kpi-help.current-month-banner-help {
    /* Same specificity-bumping trick as .pipeline-strip-help — beat the
       later .kpi-help { position: absolute } rule in source order. */
    position: static !important;
    top: auto !important;
    right: auto !important;
    margin-left: auto;
    flex: 0 0 auto;
    align-self: center;
}

/* TTM / YTD segmented toggle in the dashboard top-right ------------------
   Groups two pill buttons as a segmented control. The ".active" button
   reads as the currently selected window; the other sits as an outline
   affordance. Sits next to the "Trailing 12 months ending" dropdown so
   the two together read as one Window picker. */
.period-mode-toggle .btn-group > .btn {
    border-radius: 0;
    padding: 0.25rem 0.7rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    min-width: 48px;
}
.period-mode-toggle .btn-group > .btn:first-child {
    border-top-left-radius: 4px;
    border-bottom-left-radius: 4px;
}
.period-mode-toggle .btn-group > .btn:last-child {
    border-top-right-radius: 4px;
    border-bottom-right-radius: 4px;
}
.period-mode-toggle .btn.active {
    /* hairline inset shadow to make the selected segment read as pressed */
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15);
}

/* Invoice-detail KPI tiles (5-across) ------------------------------------
   Same visual family as the dashboard KPI cards but color-coded per metric
   so the rep scans the row quickly: gray=input, green=collected,
   amber=outstanding, blue=calculated base, bold green=payoff. */
.invoice-kpis { gap: 0; }
.invoice-kpi-card {
    border: 1px solid var(--crs-gray-300, #e5e7eb);
    border-radius: 6px;
    margin-bottom: 0;
    height: 100%;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}
.invoice-kpi-card .card-body {
    padding: 0.85rem 1rem;
}
.invoice-kpi-label {
    font-size: 0.78rem;
    color: var(--crs-gray-600, #5f6368);
    font-weight: 600;
    margin-bottom: 6px;
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.invoice-kpi-label > i {
    opacity: 0.55;
    font-size: 0.82rem;
}

/* Source-stack lines on the A/R aging detail's Sources tile. Each
   row pairs a small source badge (BC / Hist) with a count + dollar
   amount so the rep can see both contributions at a glance. */
.aging-sources-stack {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 4px;
}
.aging-source-line {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.85rem;
    line-height: 1.25;
}
.aging-source-badge {
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    flex: 0 0 auto;
    min-width: 38px;
    text-align: center;
}
.aging-source-count {
    flex: 1 1 auto;
    color: var(--crs-gray-700, #5f6368);
}
.aging-source-amt {
    flex: 0 0 auto;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--crs-gray-900, #202124);
}
.aging-source-suppressed {
    font-size: 0.75rem;
    font-style: italic;
    color: var(--crs-gray-600, #80868b);
    margin-top: 2px;
}
.aging-source-suppressed > i {
    color: #b58105;
}

/* Aging-context tile's main value — slightly smaller than the dollar-
   amount tiles so the bucket label (e.g. "61-90 days past due")
   doesn't overflow the card width on narrow viewports. */
.aging-context-value {
    font-size: 1.15rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--crs-gray-900, #202124);
}

.invoice-kpi-value {
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    color: var(--crs-gray-900, #202124);
}
/* Subtext under the Commissionable tile showing the math trail
   (Total − PT − LD). Kept tiny and muted so it doesn't compete
   with the headline number. */
.invoice-kpi-sub {
    margin-top: 6px;
    font-size: 0.72rem;
    color: var(--crs-gray-600, #5f6368);
    font-variant-numeric: tabular-nums;
    line-height: 1.35;
    display: flex;
    flex-wrap: wrap;
    gap: 0 6px;
}
.invoice-kpi-sub .deduct {
    color: #a8261d;
    font-weight: 500;
}

/* Segmented control. One shape for "pick a view of the same data", modelled
   on the Book's .rb-seg, which was already the right control and the only
   one in the app that looked current. Selected face is charcoal: red is for
   primary ACTIONS, and a filter is not an action. */
.crs-seg-btn {
    border: 1px solid var(--crs-gray-300);
    background: var(--crs-white);
    color: var(--crs-gray-700);
    font-weight: 500;
    box-shadow: none;
}
.crs-seg-btn:hover {
    background: var(--crs-gray-100);
    color: var(--crs-charcoal);
}
.crs-seg-btn.active,
.crs-seg-btn:active {
    background: var(--crs-charcoal) !important;
    border-color: var(--crs-charcoal) !important;
    color: var(--crs-white) !important;
}
.crs-seg-btn:focus-visible {
    outline: 2px solid var(--crs-red);
    outline-offset: 2px;
    z-index: 1;
}

/* Category variants. Five tiles each wearing a different 3px left stripe --
   grey, green, amber, blue, and a green gradient -- turned a row of related
   figures into five unrelated ones, and none of the stripes meant anything a
   reader could act on. The stripes are gone; each tile already carries an
   icon that names its category, and the icons now carry the only colour.
   (The old block also had a dead `.invoke-kpi-reward` typo selector.) */
.invoice-kpi-neutral  .invoice-kpi-label > i { color: var(--crs-gray-500); }
.invoice-kpi-positive .invoice-kpi-label > i { color: var(--crs-success); }
.invoice-kpi-warning  .invoice-kpi-label > i { color: var(--crs-warning); }
.invoice-kpi-info     .invoice-kpi-label > i { color: var(--crs-gray-600); }
/* The "reward" tile is the commission figure. It repeats the page hero, so
   it is emphasised by SIZE, not by a green gradient panel. */
.invoice-kpi-reward .invoice-kpi-label > i { color: var(--crs-red); }
.invoice-kpi-reward .invoice-kpi-value {
    color: var(--crs-money);
    font-size: 1.5rem;   /* slightly larger — this is the money number */
    font-variant-numeric: tabular-nums;
}

/* Tighter gutters so 5 tiles fit neatly on wide screens. */
.invoice-kpis > [class*="col-"] {
    padding-left: 6px;
    padding-right: 6px;
}
.invoice-kpis > [class*="col-"]:first-child { padding-left: 15px; }
.invoice-kpis > [class*="col-"]:last-child  { padding-right: 15px; }

/* Invoice detail on a phone -----------------------------------------------
   Measured at 375px before this block: the first invoice row sat 2,309px
   down the page -- roughly three screens of preamble. Five KPI tiles
   stacked one per row came to 867px, the three status tabs wrapped into
   three full-width buttons (132px), and the table-action buttons sat on
   two rows (88px).

   A two-across grid was tried first and gained 31px: every tile carries a
   sentence of context under its figure, and halving the width made that
   sentence twice as tall as the width saved. So the tiles stay one per
   row and change SHAPE instead -- label and figure share the top line,
   the sentence runs full width beneath. Nothing is removed. */
@media (max-width: 767.98px) {
    /* Stacked, the Bootstrap row does not line up with the page. Its
       -15px side margins against 6px of column padding put the tiles 9px
       wider on each side than everything around them: measured, the hero
       callout, the scope chart and the status tabs all run 14 to 361 at
       375px while the tiles ran 5 to 370 -- a band sticking out past the
       column it belongs to. Zeroing both puts them on the same edges. */
    .invoice-kpis { margin-left: 0; margin-right: 0; }
    .invoice-kpis > [class*="col-"] {
        margin-bottom: 8px;
        padding-left: 0;
        padding-right: 0;
    }
    .invoice-kpis > [class*="col-"]:first-child { padding-left: 0; }
    .invoice-kpis > [class*="col-"]:last-child { padding-right: 0; }

    /* Label left, figure right, on one line. Everything else in the tile
       (the per-tab sentence, the PT/LD math trail, the quota split, the
       filtered sub-line) spans the full width below it. Scoped to
       .invoice-kpi-card so the dashboard's own .kpi-card-body is not
       touched. */
    .invoice-kpi-card .kpi-card-body {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: baseline;
        column-gap: 10px;
        row-gap: 4px;
        padding: 0.6rem 1.8rem 0.6rem 0.75rem;
    }
    .invoice-kpi-card .invoice-kpi-label {
        grid-column: 1;
        margin-bottom: 0;
        white-space: normal;
        overflow: visible;
        text-overflow: clip;
        line-height: 1.25;
    }
    .invoice-kpi-card .invoice-kpi-value {
        grid-column: 2;
        text-align: right;
        font-size: 1.2rem;
    }
    .invoice-kpi-card .invoice-kpi-filter-context,
    .invoice-kpi-card .invoice-kpi-sub,
    .invoice-kpi-card .invoice-kpi-sub-stack,
    .invoice-kpi-card .invoice-kpi-filtered,
    .invoice-kpi-card .invoice-kpi-scope-note {
        grid-column: 1 / -1;
    }
    .invoice-kpi-card .invoice-kpi-filter-context { margin-top: 0; }

    /* Approved cuts, 2026-09-09. Invoice Detail was ~1,800px of preamble
       before the first invoice row on a phone, and the three tall blocks
       left were all content, so neither of these went without Matt saying
       so. Both are hidden on PHONES ONLY -- the desktop page is unchanged,
       and nothing is removed from the markup, so a screen reader and a
       printout still have them.

       The per-tile sentence: five tiles x 73-122px, and every word of it is
       already one tap away behind that tile's own (?) button.
       The scope chart: 276px that restates the callout above it as a
       picture. The callout stays; it is the page's headline answer. */
    .invoice-kpi-card .invoice-kpi-filter-context { display: none; }
    #scopeVisual { display: none; }

    /* The three status controls are tabs, so on a phone they behave like
       tabs: one row that scrolls sideways, each keeping its full label.
       Stacked full-width they were 132px of buttons; this is one 44px
       row. The ID beats base.html's `.btn-group { flex-wrap: wrap }`. */
    #statusToggle {
        flex-wrap: nowrap;
        overflow-x: auto;
        /* A scroll box on one axis forces the other to clip, so the 4px
           the focus ring needs (2px outline at 2px offset) has to come
           from inside. Measured with the buttons flush against the box:
           0px above and below, which would have cut a keyboard user's
           ring off on every tab. */
        overflow-y: hidden;
        padding-top: 4px;
        padding-bottom: 4px;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    #statusToggle::-webkit-scrollbar { display: none; }
    #statusToggle > .crs-seg-btn {
        flex: 0 0 auto;
        white-space: nowrap;
        min-height: var(--crs-control-h);
    }

    /* Export / Collapse / Columns measure 315px together and the row is
       348px, so they only wrapped onto two rows because base.html grows
       every .btn-group child to fill. They size to content here instead.
       This row is deliberately NOT given overflow scrolling like the tabs
       above: two of the three open dropdown menus, and a scroll container
       would clip them. Three classes to out-specify base.html's own
       `.btn-group > .btn`, which is later in the document. */
    .btn-group[aria-label="Table actions"] > .btn,
    .btn-group[aria-label="Table actions"] > .btn-group,
    .btn-group[aria-label="Table actions"] > .dropdown {
        flex: 0 0 auto;
        /* sales_styles.css sets width:100% on EVERY .btn-group with
           !important, and base.html only walks that back for .btn
           children -- the Export dropdown is a nested .btn-group, so it
           kept filling the row on its own. */
        width: auto !important;
    }
    /* Content-sized the three still come to 409px against a 348px row, so
       Columns wraps. A joined segmented bar that wraps looks broken -- half
       a pill on each line -- so at this width they read as three separate
       chips instead. */
    .btn-group[aria-label="Table actions"] { gap: 6px; }
    .btn-group[aria-label="Table actions"] .btn {
        border-radius: var(--crs-radius, 6px) !important;
    }
}

/* Invoice-No cell on the invoice detail table — keep the edit pencil
   and the invoice link on the same line so the column can size to fit
   both side by side. Without nowrap the cell wraps to two lines. */
#invoice_table td.invoice-no-cell {
    white-space: nowrap;
}

/* Commission drilldown DataTables (invoice detail / invoice lines /
   pass-through / lost-damaged): min-width stops the stacked-letter
   collapse under scrollX. Do NOT nowrap the visible .dt-column-title —
   measured live 2026-09-12 after #222: "Customer Payment Status"
   (~204px) bled ~96px into the next 121px invoice-register column.
   Wrap at spaces only (keep-all) so COMMISSIONABLE stays one word.

   th { min-width } loses to DataTables 2's <col style="width"> plus
   table-layout:fixed. Measured live 2026-09-12 at 1280x800 (standard
   laptop): 11 cols shrank to 106px and COMMISSIONABLE (126px, keep-all)
   collided with Commission Rate. Honor 9.5rem on the shared colgroup
   so scrollX grows the table instead. */
#invoice_table thead th,
#invoice_table_wrapper .dt-scroll-head thead th,
#lines_table thead th,
#lines_table_wrapper .dt-scroll-head thead th,
#group_table thead th,
#group_table_wrapper .dt-scroll-head thead th {
    white-space: nowrap;
    min-width: 9.5rem;
}
#invoice_table_wrapper col,
#lines_table_wrapper col,
#group_table_wrapper col {
    min-width: 9.5rem !important;
}
/* DataTables 2 scrollX writes an inline table width equal to the shared
   colgroup floor. For the short PT/L&D drilldowns that can be ~762px, so
   the dark header pill and footer totals stay left-compressed inside a much
   wider card. Stretch the full split-scroll chain (wrapper divs, clone
   tables, and thead/tfoot rows) so fixed-layout columns redistribute the
   extra desktop width across the grid instead of leaving empty space on the
   right. */
#invoice_table_wrapper .dt-scroll,
#invoice_table_wrapper .dt-scroll-head,
#invoice_table_wrapper .dt-scroll-headInner,
#invoice_table_wrapper .dt-scroll-body,
#invoice_table_wrapper .dt-scroll-foot,
#invoice_table_wrapper .dt-scroll-footInner,
#invoice_table_wrapper .dt-scroll-headInner > table,
#invoice_table_wrapper .dt-scroll-body > table,
#invoice_table_wrapper .dt-scroll-footInner > table,
#invoice_table_wrapper .dt-scroll-head thead,
#invoice_table_wrapper .dt-scroll-head thead tr,
#invoice_table_wrapper .dt-scroll-foot tfoot,
#invoice_table_wrapper .dt-scroll-foot tfoot tr,
#lines_table_wrapper .dt-scroll,
#lines_table_wrapper .dt-scroll-head,
#lines_table_wrapper .dt-scroll-headInner,
#lines_table_wrapper .dt-scroll-body,
#lines_table_wrapper .dt-scroll-foot,
#lines_table_wrapper .dt-scroll-footInner,
#lines_table_wrapper .dt-scroll-headInner > table,
#lines_table_wrapper .dt-scroll-body > table,
#lines_table_wrapper .dt-scroll-footInner > table,
#lines_table_wrapper .dt-scroll-head thead,
#lines_table_wrapper .dt-scroll-head thead tr,
#lines_table_wrapper .dt-scroll-foot tfoot,
#lines_table_wrapper .dt-scroll-foot tfoot tr,
#group_table_wrapper .dt-scroll,
#group_table_wrapper .dt-scroll-head,
#group_table_wrapper .dt-scroll-headInner,
#group_table_wrapper .dt-scroll-body,
#group_table_wrapper .dt-scroll-foot,
#group_table_wrapper .dt-scroll-footInner,
#group_table_wrapper .dt-scroll-headInner > table,
#group_table_wrapper .dt-scroll-body > table,
#group_table_wrapper .dt-scroll-footInner > table,
#group_table_wrapper .dt-scroll-head thead,
#group_table_wrapper .dt-scroll-head thead tr,
#group_table_wrapper .dt-scroll-foot tfoot,
#group_table_wrapper .dt-scroll-foot tfoot tr {
    width: 100% !important;
    min-width: 100% !important;
    max-width: 100% !important;
}
#invoice_table_wrapper .dt-scroll-head thead th .dt-column-title,
#lines_table_wrapper .dt-scroll-head thead th .dt-column-title,
#group_table_wrapper .dt-scroll-head thead th .dt-column-title {
    white-space: normal;
    word-break: keep-all;
    overflow-wrap: normal;
    hyphens: none;
}
/* Visible group boundary on the invoice-detail table — first cell of
   each logical column group gets a slightly heavier left border so the
   grouping (Identity · Customer/Location · Money billed · Commission ·
   Customer payment) reads as visual sections rather than a long flat row. */
#invoice_table thead th.col-group-start,
#invoice_table tbody td.col-group-start {
    border-left: 2px solid var(--crs-charcoal, #1a1a1a) !important;
}
/* Light heading bar above the group's first column to label the section. */
#invoice_table thead th.col-group-start {
    position: relative;
}

/* Commission-rate pill (invoice detail table) --------------------------- */
.rate-pill {
    display: inline-block;
    padding: 1px 6px;
    font-size: 0.82em;
    font-weight: 600;
    line-height: 1.35;
    border-radius: 3px;
    white-space: nowrap;
}
.rate-pill-normal {
    background: rgba(108, 117, 125, 0.12);
    color: #4a5157;
}
.rate-pill-shared {
    background: rgba(13, 110, 253, 0.14);
    color: #084faa;
}
.rate-pill-special {
    background: rgba(200, 16, 46, 0.14);
    color: #8E0A20;
}

/* Trend arrows (commission dashboard variance cells) --------------------- */
.trend-arrow {
    /* Chunky tinted pill so direction reads at a glance. Kept narrow
       (padding 0 3px, margin-right 3px) so it fits inside the 8rem
       month columns alongside values like \$3,307,090 without overflow. */
    display: inline-block;
    padding: 0 3px;
    margin-right: 3px;
    font-size: 0.9em;
    font-weight: 900;
    line-height: 1.3;
    border-radius: 3px;
    vertical-align: 1px;
}
.trend-arrow.text-success {
    background: rgba(15, 157, 88, 0.16);
    color: #0b7a45 !important;
}
.trend-arrow.text-danger {
    background: rgba(217, 48, 37, 0.16);
    color: #a8261d !important;
}

/* Trend chips on KPI tiles — small pill with arrow + signed % change
   vs the prior equal window. Green = good direction, red = bad. */
.trend-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.1rem 0.45rem;
    margin-top: 0.25rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.4;
    font-variant-numeric: tabular-nums;
    border: 1px solid transparent;
}
.trend-chip-up {
    background: rgba(15, 157, 88, 0.10);
    color: #0b7a45;
    border-color: rgba(15, 157, 88, 0.25);
}
.trend-chip-down {
    background: rgba(217, 48, 37, 0.10);
    color: #a8261d;
    border-color: rgba(217, 48, 37, 0.30);
}
.trend-chip-flat {
    background: var(--crs-gray-100, #f6f7f9);
    color: var(--crs-gray-600, #6c757d);
    border-color: var(--crs-gray-200, #e5e7eb);
}

/* Commission page header — flex row containing back button, page title,
   and "Data as of" stamp. Rendered in base.html for all commission pages. */
.commission-page-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
    padding: 0.5rem 1rem;
}
.commission-page-header h2 {
    margin: 0;
    font-size: 1.35rem;
    white-space: nowrap;
}
/* sales_styles.css has a GLOBAL `.btn-group, .btn { width: 100% !important }`
   that balloons every button to its container width. For the inline action
   buttons in the page-header H2 (View in BC / Edit header / Export) this makes
   each button as wide as the whole H2, so they overflow and collide with the
   "Data as of" stamp. Restore content-sizing for buttons in the commission
   header (equal specificity to the global rule, but !important + later source
   order win); re-assert the fixed Back-button width AFTER so it still applies. */
.commission-page-header .btn { width: auto !important; }
.commission-page-header .btn-back {
    /* Was a hard `width: 120px !important`, sized for the short "← Back".
       Pages that name their destination -- "← Monthly Close" -- need 123px,
       so the label printed 5px outside the button's own border. A minimum
       keeps every short button the same uniform width (which is what the
       120px was for) while letting a longer label size to its own text. */
    min-width: 120px;
    text-align: center;
    flex-shrink: 0;
}
/* Back + Commission Home visual polish, global (this file loads on every
   page, unlike commission_layout.css's cv3 layer which is opt-in per
   page) -- the pair is injected by the script above onto EVERY commission
   page via .btn-back + .commission-home-btn, including pages like Book
   that don't wrap their content in .cv3-page, so a page-scoped fix would
   have missed most of the app. Same visual language as the cv3-btn-outline
   rules in commission_layout.css, expressed in this file's own --crs-*
   tokens since --cv3-* only exists where that stylesheet is loaded. */
.commission-page-header .btn-back,
.commission-page-header .commission-home-btn {
    border-radius: var(--crs-radius);
    font-weight: 500;
    transition: background var(--crs-trans), border-color var(--crs-trans), color var(--crs-trans);
}
.commission-page-header .btn-back {
    background: transparent;
    border-color: var(--crs-gray-300);
    color: var(--crs-gray-700);
}
.commission-page-header .btn-back:hover {
    background: var(--crs-gray-100);
    border-color: var(--crs-gray-600);
    color: var(--crs-charcoal);
}
.commission-page-header .commission-home-btn {
    background: transparent;
    border-color: var(--crs-red);
    color: var(--crs-red);
}
.commission-page-header .commission-home-btn:hover {
    background: var(--crs-red-light);
    border-color: var(--crs-red);
    color: var(--crs-red);
}
.commission-page-header .btn-back:focus-visible,
.commission-page-header .commission-home-btn:focus-visible {
    outline: 2px solid var(--crs-red);
    outline-offset: 1px;
}

/* Invoice-detail + PT/L&D toolbars. sales_styles.css's global
   `.btn-group, .btn { width: 100% !important }` is for mobile login /
   form buttons. On desktop it stretches Export Excel / Collapse Rows
   across the invoice-detail row (measured 633px / 645px against a
   1377px group) and the PT/L&D Export Excel next to the lead total
   (measured 1024px). The phone block already sizes
   [aria-label="Table actions"] to content; this is the all-viewport
   sibling so desktop matches. Do not remove the sales_styles rule. */
.clair-content-btn,
.btn-group[aria-label="Table actions"],
.btn-group[aria-label="Table actions"] > .btn,
.btn-group[aria-label="Table actions"] > .btn-group,
.btn-group[aria-label="Table actions"] > .dropdown,
.btn-group[aria-label="Table actions"] .btn {
    width: auto !important;
    flex: 0 0 auto;
}
.btn-group[aria-label="Table actions"] {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
    max-width: 100%;
}

/* PT/L&D + invoice-lines last-column actions live inside DataTables wrappers.
   Keep these in-table controls content-sized (not full-cell width) while
   leaving the page-header/table-toolbar export buttons untouched. */
#group_table_wrapper td:last-child .btn,
#group_table_wrapper td:last-child .btn-group,
#lines_table_wrapper td:last-child .btn,
#lines_table_wrapper td:last-child .btn-group {
    width: auto !important;
    min-width: unset;
    white-space: nowrap;
}
#group_table_wrapper td:last-child .btn,
#lines_table_wrapper td:last-child .btn {
    display: inline-flex;
}

/* "Data as of <timestamp>" stamp — site-wide indicator that the current
   page's numbers reflect data through the last BC sync run. Sits in the
   commission-page-header row (rendered in base.html). */
.data-as-of {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.7rem;
    margin-left: auto;
    font-size: 0.78rem;
    color: var(--crs-gray-600, #6c757d);
    background: var(--crs-gray-100, #f6f7f9);
    border: 1px solid var(--crs-gray-200, #e5e7eb);
    border-radius: 4px;
}
.data-as-of i { color: var(--crs-gray-500, #9ca3af); }
.data-as-of strong { color: var(--crs-gray-800, #1f2937); font-weight: 600; }
/* Cadence note ("refreshes nightly at 2:30 AM CT") — quieter than the
   timestamp so the eye lands on the freshness value first. gray-500 on
   this background measured 1.95:1, well under WCAG AA's 4.5:1 for 12px
   text; gray-600 measures 4.83:1 and is the tone the rest of the app's
   muted copy already uses. */
.data-as-of .data-as-of-cadence {
    color: var(--crs-gray-600, #6b7280);
    font-weight: 400;
    margin-left: 0.15rem;
}

/* Inc 7 — stale stamp is an amber chip, not a full-width banner.
   Higher specificity than commission_layout.css's quiet reset so the
   warning still shows on Analytics / All Reps (that sheet loads later). */
.commission-page-header .data-as-of.is-stale,
.data-as-of.is-stale {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    width: fit-content;
    max-width: 100%;
    padding: 0.35rem 0.7rem;
    background: var(--crs-warning-bg, #FEF5E7);
    border: 1px solid var(--crs-warning, #D97706);
    color: #8A4B08;
}
.data-as-of.is-stale i {
    color: var(--crs-warning, #D97706);
}
.data-as-of.is-stale strong {
    color: #7A3E06;
}
.data-as-of.is-stale .data-as-of-cadence {
    color: #A16207;
}
.data-as-of-stale-warn,
.data-as-of.is-stale .data-as-of-stale-warn {
    font-weight: 600;
    color: #9A3412;
}

/* Stronger keyboard focus on the stamp and controls injected into it
   (e.g. "How to read this page"). */
.data-as-of:focus-visible,
.data-as-of a:focus-visible,
.data-as-of button:focus-visible,
.data-as-of .cv3-how-to-read:focus-visible {
    outline: 3px solid var(--crs-red);
    outline-offset: 2px;
}
.data-as-of.is-stale:focus-visible,
.data-as-of.is-stale a:focus-visible,
.data-as-of.is-stale button:focus-visible,
.data-as-of.is-stale .cv3-how-to-read:focus-visible {
    outline-color: var(--crs-warning, #D97706);
}

/* Filtered KPI subtitle (invoice detail — shown when paid/unpaid toggle active) */
.invoice-kpi-filtered {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--crs-gray-700, #495057);
    margin-top: 0.25rem;
    padding-top: 0.2rem;
    border-top: 1px dashed var(--crs-gray-300, #dee2e6);
}

/* Shared-codes dropdown — sits inside the All / Solo / Shared / Special
   pill row when the rep has 2+ shared BC codes and the user wants to
   narrow Shared to a specific subset. */
.shared-codes-picker .dropdown-toggle::after {
    margin-left: 0.4rem;
    vertical-align: 0.18em;
}
.shared-codes-summary {
    color: var(--crs-gray-600, #6c757d);
    font-weight: 500;
    margin-left: 0.25rem;
}
.shared-codes-menu {
    /* Bootstrap drops dropdown-menu padding to 0; we want internal
       padding for the form contents. p-3 utility provides that, this
       just fixes scrollability + max height. */
    max-height: 320px;
    overflow-y: auto;
}
.shared-codes-menu .form-check {
    padding-left: 1.6rem;
    margin-bottom: 0.25rem;
}
.shared-codes-menu code {
    font-size: 0.85rem;
}

/* KPI tile help (?) icon ------------------------------------------------- */
.kpi-card-body {
    position: relative;
    /* Ensure the value + label don't end up under the absolute-positioned
       help button on narrow cards. */
    padding-right: 1.8rem;
    /* Flex column so the label sits at the top and the dollar value
       fills the remaining vertical space (anchored at the bottom).
       Without this, tiles without a sub-line have a big empty bottom
       chunk while tiles with a sub-line look full. */
    display: flex;
    flex-direction: column;
    min-height: 110px;
}
.kpi-card-body > h4 {
    margin-top: auto;     /* push value (and any sub-line) to the bottom */
    margin-bottom: 0;
    font-size: 1.6rem;
    font-weight: 600;
    line-height: 1.15;
}
.kpi-card-body > h4 + .small {
    margin-top: 0.35rem;
}
/* Tiny inline sparkline under a KPI tile's value — visualises the
   monthly trend that drives the headline number. Chart.js needs a
   positioned parent with an explicit height for `responsive: true,
   maintainAspectRatio: false` to clamp the canvas; without it Chart's
   resizer grows the canvas to fill the page. */
.kpi-sparkline-wrap {
    position: relative;
    margin-top: 0.4rem;
    height: 32px;
    width: 100%;
}
.kpi-sparkline {
    display: block;
}
/* Tall sparkline variant — used by the Commission Paid to Rep tile so
   the bar chart fills the same vertical real estate as the Quota
   Tracking chart next to it. flex: 1 lets it grow to fill the
   remaining card height; min-height keeps it from collapsing if the
   card itself is short. */
.kpi-sparkline-wrap-tall {
    height: auto;
    flex: 1 1 auto;
    min-height: 150px;
}
.kpi-sparkline-wrap-tall canvas { cursor: pointer; }
/* High / Low pills under the Commission Paid sparkline. Two small
   chips that pull the peak and trough months out of the bar chart so
   the rep doesn't have to mouse over to find them. Colors mirror the
   bars (green = peak, red = trough). */
.kpi-hl-caption {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.3rem;
    font-size: 0.7rem;
    line-height: 1.1;
    position: relative;
    z-index: 1;
    width: 100%;
}
.kpi-hl-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.1rem 0.4rem;
    border-radius: 999px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    border: 1px solid;
    position: static;
    max-width: 100%;
}
.kpi-hl-high { background: #ecfdf5; border-color: #a7f3d0; color: #047857; }
.kpi-hl-low  { background: #fef2f2; border-color: #fecaca; color: #b91c1c; }
.kpi-hl-current { background: #fffbeb; border-color: #fcd34d; color: #92400e; font-weight: 500; }
/* "vs last month" pill — same visual language as high/low. Up = green,
   down = red, flat = neutral. */
.kpi-hl-up   { background: #ecfdf5; border-color: #a7f3d0; color: #047857; }
.kpi-hl-down { background: #fef2f2; border-color: #fecaca; color: #b91c1c; }
.kpi-hl-flat { background: #f3f4f6; border-color: #d1d5db; color: #4b5563; }

/* Commission Due callout — sits directly under the main "Commission
   Paid" headline and breaks out the END-month commission that's
   excluded from the headline. Amber palette matches the "outstanding"
   semantics used by the Commission Due to Rep pipeline stage so reps
   get a consistent color for "earned but not yet paid out". */
.kpi-due-callout {
    display: inline-flex;
    align-items: baseline;
    gap: 0.4rem;
    margin-top: 0.25rem;
    padding: 0.25rem 0.55rem;
    border-radius: 0.4rem;
    background: #fffbeb;
    border: 1px solid #fcd34d;
    color: #b45309;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}
.kpi-due-callout-tag {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 700;
}
.kpi-due-callout-amount {
    font-size: 0.95rem;
    font-weight: 700;
    color: #92400e;
}
.kpi-hl-month {
    font-weight: 500;
    color: inherit;
    opacity: 0.78;
    font-variant-numeric: normal;
}
/* Short tag label that prefixes each kpi-hl-pill (Peak / Low / MoM)
   so the user can see at a glance what the chip means without hovering
   the tooltip. Slate-on-pill background pop keeps it readable across
   the green/red pill variants. */
.kpi-hl-tag {
    display: inline-block;
    margin-right: 0.35em;
    padding: 0.05em 0.4em;
    border-radius: 0.3em;
    background: rgba(15, 23, 42, 0.12);
    font-size: 0.65em;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1.4;
    vertical-align: middle;
    color: inherit;
}
/* Phone / tablet: pills wrap or stack below the canvas. Never overlap
   each other, the x-axis, or "How these numbers work". Current-month
   swatch gets its own row so it is not shoved to the far right. */
@media (max-width: 768px) {
    .kpi-hl-caption {
        align-items: flex-start;
        align-content: flex-start;
        gap: 0.4rem;
        margin-top: 0.55rem;
    }
    .kpi-hl-current { flex: 1 0 100%; }
}
@media (max-width: 576px) {
    .kpi-hl-caption {
        flex-direction: column;
        align-items: flex-start;
    }
    .kpi-hl-pill { width: max-content; }
}
/* Quota tracker — projected current-month subtext below the chart.
   Subtle amber fill keeps it visually separate from the 12-month
   actual bars so the user reads it as a side calculation. */
.quota-tracker-projected-caption {
    display: block;
    padding: 0.3rem 0.55rem;
    background: #fffbeb;
    border: 1px solid #fcd34d;
    border-radius: 0.4rem;
    color: #92400e;
    font-variant-numeric: tabular-nums;
}
.quota-tracker-projected-caption strong { color: #78350f; }
.quota-tracker-projected-meta {
    color: #b45309;
    margin-left: 0.4em;
}
/* Inline attainment gauge — sits inside the in-progress current-month
   banner under the "{Month} quota" cell. Filled bar = commissionable
   sales so far as % of that month's quota; the dashed marker is the
   projected end-of-month %. Bar visually caps at 100% width but the
   text label always shows the true projected % (so > 100% projections
   read as "projecting 327%" with the marker pinned to the right). */
.quota-attainment-gauge {
    margin-top: 0.35rem;
    width: 11rem;
    max-width: 100%;
}
.quota-attainment-track {
    position: relative;
    width: 100%;
    height: 0.55rem;
    background: rgba(15, 23, 42, 0.08);
    border-radius: 999px;
    overflow: hidden;
}
.quota-attainment-fill {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, #10b981 0%, #34d399 100%);
    border-radius: 999px;
    transition: width 400ms ease;
}
.quota-attainment-fill.is-under {
    background: linear-gradient(90deg, #ef4444 0%, #f87171 100%);
}
/* Projected fill — amber to read as "forecast" rather than actual.
   Diagonal stripe overlay reinforces "this is a projection, not a
   measured value". */
.quota-attainment-fill.is-projected {
    background:
        repeating-linear-gradient(
            45deg,
            rgba(255, 255, 255, 0.18) 0,
            rgba(255, 255, 255, 0.18) 4px,
            transparent 4px,
            transparent 8px
        ),
        linear-gradient(90deg, #f59e0b 0%, #fbbf24 100%);
}
.quota-attainment-marker {
    position: absolute;
    top: -3px; bottom: -3px;
    width: 2px;
    background: #1f2937;
    transform: translateX(-50%);
    pointer-events: none;
}
.quota-attainment-label {
    margin-top: 0.2rem;
    font-size: 0.7rem;
    color: #475569;
    line-height: 1.3;
}
.quota-attainment-label strong {
    color: #1e293b;
    font-variant-numeric: tabular-nums;
}
/* House Accounts callout — same visual rhythm as kpi-due-callout but a
   neutral slate palette so the eye groups it as "informational" (this
   slice doesn't go to a salesperson) rather than "due" (amber). Sits
   one line below the due pill on the team-summary Commission Paid tile. */
.kpi-house-callout {
    display: inline-flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.35rem;
    padding: 0.25rem 0.55rem;
    border-radius: 0.4rem;
    background: #f1f5f9;
    border: 1px solid #cbd5e1;
    color: #475569;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}
.kpi-house-callout-tag {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 700;
    color: #334155;
}
.kpi-house-callout-amount {
    font-size: 0.95rem;
    font-weight: 700;
    color: #1e293b;
}
.kpi-house-callout-btn {
    margin-left: auto;
    padding: 0.1rem 0.55rem;
    font-size: 0.7rem;
    line-height: 1.3;
    font-weight: 600;
    border-color: #94a3b8;
    color: #334155;
    background: #ffffff;
}
/* Range-total subtotal — sits beneath the Paid headline + the end-month Due
   pill on the Commission Paid tile and sums the two, so the user sees the
   full commission for the report range (incl. the end month) without either
   figure above it changing. The top rule reads as a "subtotal" line; neutral
   slate keeps it from competing with the amber due pill. */
.kpi-range-total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.4rem;
    margin-top: 0.4rem;
    padding-top: 0.35rem;
    border-top: 1px dashed #cbd5e1;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}
.kpi-range-total-tag {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 700;
    color: #475569;
}
.kpi-range-total-amount {
    font-size: 0.95rem;
    font-weight: 700;
    color: #1e293b;
}
.kpi-house-callout-btn:hover {
    background: #475569;
    border-color: #475569;
    color: #ffffff;
    text-decoration: none;
}
.kpi-house-callout-btn .fa-arrow-right {
    margin-left: 0.2rem;
    font-size: 0.65rem;
}
.kpi-house-callout-meta {
    font-size: 0.78rem;
    font-weight: 500;
    color: #64748b;
}
/* Section rail — short uppercase label above a band of related cards
   so the dashboard reads as discrete sections ("Headline", "Trends",
   etc.) rather than one long scroll. */
.dashboard-section-heading {
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--clair-muted, #6b7280);
    margin: 1.25rem 0 0.5rem;
    border-left: 3px solid var(--clair-primary, #2563eb);
    padding-left: 0.6rem;
}
.dashboard-section-heading small {
    font-weight: 500;
    text-transform: none;
    letter-spacing: 0;
    color: var(--clair-muted, #6b7280);
    margin-left: 0.4rem;
}
/* The FIRST section heading on a page doesn't need the big band gap —
   it sits right under the page-header toolbar. Recovers ~1.25rem of
   dead space at the top of the team summary / dashboards. */
.exec-overview > .dashboard-section-heading:first-child,
.container-fluid > .dashboard-section-heading:first-child {
    margin-top: 0.15rem;
}

/* Executive overview — action tiles + leaderboards + aging donut.
   Sits on top of team_summary / all_reps. Mirrors the screenshot:
   four wide action tiles in a row, then two leaderboards + a donut
   side-by-side beneath. */
.exec-overview { margin-bottom: 1.5rem; }
.exec-tiles {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.75rem;
    margin-bottom: 0.5rem;
}
.exec-tile {
    background: #fff;
    border-radius: 0.5rem;
    border: 1px solid #e5e7eb;
    padding: 0.85rem 1rem;
    /* Reserve space at the top-right for the absolute-positioned
       (?) help button so the tile label doesn't sit underneath it. */
    padding-right: 1.85rem;
    border-left: 4px solid #94a3b8;
    position: relative;
}
.exec-tile-label {
    text-transform: uppercase;
    font-size: 0.7rem;
    letter-spacing: 0.06em;
    font-weight: 600;
    color: #6b7280;
}
.exec-tile-value {
    font-size: 1.55rem;
    font-weight: 700;
    color: #111827;
    margin: 0.15rem 0 0.1rem;
}
.exec-tile-sub { font-size: 0.78rem; color: #6b7280; }
/* Driver line — shows the underlying receivables / pipeline $ that
   drives the headline commission number. Slightly smaller, in a tabular
   font so the dollar amounts line up across tiles. */
.exec-tile-meta {
    font-size: 0.72rem;
    color: #4b5563;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    margin-top: 0.2rem;
    letter-spacing: 0.01em;
}
.exec-tile-unlockable  { border-left-color: #10b981; }
.exec-tile-unlockable  .exec-tile-value { color: #10b981; }
.exec-tile-outstanding { border-left-color: #f59e0b; }
.exec-tile-outstanding .exec-tile-value { color: #d97706; }
.exec-tile-atrisk      { border-left-color: #ef4444; }
.exec-tile-atrisk      .exec-tile-value { color: #ef4444; }
.exec-tile-pipeline    { border-left-color: #2563eb; }
.exec-tile-pipeline    .exec-tile-value { color: #2563eb; }

/* Clickable tile — anchors to #team_table sorted by the relevant
   column. Override the bootstrap link defaults so the tile itself
   doesn't underline / re-color its inner text. */
a.exec-tile-link {
    text-decoration: none;
    color: inherit;
    cursor: pointer;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}
a.exec-tile-link:hover {
    text-decoration: none;
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(15, 23, 42, 0.08);
    color: inherit;
}
a.exec-tile-link:focus { outline: 2px solid var(--crs-red); outline-offset: 2px; }

/* Aging legend rows — clickable, Power BI-style cross-filter.
   Hover lifts the row; active row gets a tinted bg + bold weight; the
   other rows fade to muted while a filter is on. */
.exec-aging-legend-item {
    cursor: pointer;
    border-radius: 4px;
    padding-left: 0.25rem !important;
    padding-right: 0.25rem !important;
    transition: background-color 0.15s ease, opacity 0.15s ease;
    user-select: none;
}
.exec-aging-legend-item:hover {
    background-color: #f3f4f6;
}
.exec-aging-legend-item:focus-visible {
    outline: 2px solid var(--crs-red);
    outline-offset: 1px;
}
.exec-aging-legend-item.is-active {
    background-color: #eef2ff;
    font-weight: 600;
}
.exec-aging-legend-item.is-dim {
    opacity: 0.45;
}

/* Brief 0.9s yellow flash on the team_table column header that the
   user just sorted — confirms the click did something even if the
   page didn't visibly scroll (already at the top). */
.exec-sort-flash {
    background-color: #fef3c7 !important;
    transition: background-color 0.6s ease;
}

/* Rep / Manager name columns on the team summary table.
   These used to say `white-space: nowrap; width: 1%` -- the classic
   "shrink to content + don't wrap" table idiom. It only behaves that
   way under `table-layout: auto`. Every scroll table here is
   `table-layout: fixed` (see base.html), where `width: 1%` means
   literally one percent, and DataTables then measured these columns at
   0px and wrote `width: 0px` into the shared colgroup -- the rep name
   printed on top of the next column's dollars. It is also
   self-perpetuating: once a 0 is in the colgroup, the cell measures 0
   again on every later columns.adjust(), so nothing recovers it.
   A real width can't collapse, and wrapping (instead of nowrap) means a
   long name can never spill out of its own column either. Nothing is
   truncated -- a long name takes a second line. */
#team_table th:nth-child(1),
#team_table td:nth-child(1),
#team_table th:nth-child(2),
#team_table td:nth-child(2) {
    white-space: normal;
    width: 160px;
}

/* Money / metric columns: wrap the LABEL in the header (so multi-word
   names like "Commissionable Payments Received" stack vertically and
   the column itself stays narrow), but never wrap the dollar values
   in the body cells. Cap header column widths so DataTables doesn't
   expand them past the underlying data width.
   `!important` is needed because DataTables writes inline `width: Npx`
   on each th after init based on auto-measured content. We want the
   user's wrapping target to win over DataTables' auto-measure. */
/* .cv3-rg-table (a class, not #team_table) below: for scrollY-enabled
   DataTables, the header/footer a user actually SEES are split into
   separate .dt-scroll-head/.dt-scroll-foot clone <table>s that do NOT
   carry the original id="team_table" -- only #team_table's own class
   list gets copied onto them. An ID-scoped thead/tfoot selector here
   silently matches only the hidden zero-height "sizing" thead on the
   real (scroll-body) table, never what renders on screen. tbody stays
   #team_table-scoped -- that IS the real, visible body. */
.cv3-rg-table thead th {
    white-space: normal !important;
    /* Only break BETWEEN words (no mid-word splits like "COMM ISSION ABLE") */
    word-wrap: normal;
    overflow-wrap: normal;
    word-break: keep-all;
    vertical-align: bottom;
    /* Width sized so "COMMISSIONABLE" fits on a single line; longer
       multi-word labels wrap to 2-3 lines. */
    max-width: 140px !important;
    width: 140px !important;
    line-height: 1.25;
    padding-top: 8px;
}
/* Rep + Manager / Company columns. Same story as the #team_table rule
   above: `width: 1%` is the shrink-to-content idiom and it collapses to
   0px under `table-layout: fixed`, which is what every scroll table in
   this app uses. Measured on /commissions/team/commission-summary/
   (#cs_table) 2026-09-15: with all 13 columns shown, columns 0 and 1 --
   exactly the two this selector targets -- were the only ones at 0px.
   A real width, and wrapping rather than nowrap so an unusually long
   name takes a second line instead of spilling across its neighbour. */
.cv3-rg-table thead th:nth-child(1),
.cv3-rg-table thead th:nth-child(2) {
    white-space: normal !important;
    width: 160px !important;
    max-width: 160px !important;
}
#team_table tbody td {
    white-space: nowrap;
}
/* DataTables injects the sort-arrow span. Keep the label and arrow
   on separate visual lines when the label wraps. */
.cv3-rg-table thead th.sorting,
.cv3-rg-table thead th.sorting_asc,
.cv3-rg-table thead th.sorting_desc {
    padding-right: 18px; /* room for the sort arrow on the right */
}

/* Freeze the Rep (first) column when the team table scrolls
   horizontally, on all three split tables (header, body, footer) so
   the behavior is consistent regardless of which one a user is
   looking at. position: sticky needs the cell to have an opaque
   background so the underlying scrolled cells don't show through.
   The right-edge box shadow signals there's content scrolled off to
   the right. */
/* The body half was `#team_table tbody td:first-child` -- an id, so the
   OTHER cv3-rg-table built on this exact pattern (#cmx_table, the rep x
   month commission matrix) got a sticky HEADER cell with a non-sticky
   body under it: scroll sideways and the "Sales Rep" label stayed pinned
   while the rep names slid away beneath it. The class matches the real
   scroll-body table too (DataTables copies the class list, not the id --
   see the note above), so head, body and foot now freeze together, which
   is what this block always said it was for. */
.cv3-rg-table thead th:first-child,
.cv3-rg-table tbody td:first-child,
.cv3-rg-table tfoot td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background-color: #ffffff;
    box-shadow: 2px 0 4px -2px rgba(15, 23, 42, 0.12);
}
.cv3-rg-table thead th:first-child {
    /* Header sits ABOVE body cells so the body sticky column doesn't
       paint over the header on horizontal scroll. White, not the old
       Bootstrap thead-dark charcoal -- the rep grid no longer has a
       dark header band (see commission_layout.css "Rep Grid"). */
    z-index: 3;
    background-color: #ffffff;
}
/* No zebra striping in the redesign, so the old .table-striped odd-row
   sticky-cell tint no longer has a class to key off of. */

.exec-leaderboards {
    display: grid;
    grid-template-columns: 1fr 1fr 1.2fr;
    gap: 0.75rem;
}
.exec-board {
    background: #fff;
    border-radius: 0.5rem;
    border: 1px solid #e5e7eb;
    padding: 0.85rem 1rem;
}
.exec-board-title {
    font-size: 0.85rem;
    font-weight: 700;
    color: #374151;
    margin-bottom: 0.5rem;
}
.exec-board-title .fas { margin-right: 0.4rem; color: #6b7280; }
.exec-board-list {
    list-style: none;
    padding: 0;
    margin: 0;
}
.exec-board-list li {
    display: grid;
    grid-template-columns: 1fr auto auto;
    gap: 0.5rem;
    align-items: baseline;
    padding: 0.3rem 0;
    border-bottom: 1px solid #f3f4f6;
    font-size: 0.85rem;
}
.exec-board-list li:last-child { border-bottom: 0; }
.exec-board-list a { color: #1f2937; font-weight: 500; text-decoration: none; }
.exec-board-list a:hover { text-decoration: underline; }
.exec-board-list .exec-board-pct {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.exec-board-list .exec-board-pct-up   { color: #10b981; }
.exec-board-list .exec-board-pct-down { color: #ef4444; }
.exec-board-list .exec-board-amount {
    font-size: 0.75rem;
    color: #6b7280;
    font-variant-numeric: tabular-nums;
}
.exec-board-empty {
    grid-template-columns: 1fr !important;
    color: #9ca3af;
    font-style: italic;
}

/* Scope disclaimer for the Unlockable-by-aging pipeline stage —
   calls out that the figures only reflect rep-assigned invoices and
   exclude house accounts. Sits between the stage title and the
   stacked-bar graphic. */
.pipeline-stage-disclaimer {
    font-size: 0.72rem;
    line-height: 1.35;
    color: var(--crs-gray-600, #5f6368);
    background: var(--crs-gray-100, #f6f7f9);
    border: 1px solid var(--crs-gray-200, #e9ecef);
    border-left: 3px solid var(--crs-gray-400, #ced4da);
    padding: 0.4rem 0.55rem;
    margin: 0.25rem 0 0.5rem;
    border-radius: 4px;
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
}
.pipeline-stage-disclaimer > i {
    color: var(--crs-gray-500, #adb5bd);
    margin-top: 0.15rem;
    flex-shrink: 0;
}

/* Edit-overrides pencil shown next to invoice numbers in the drill-down.
   Subtle gray by default; warm amber on hover to match the in-progress
   semantics of other override / current-month UI. */
.invoice-override-edit-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    margin-right: 4px;
    color: var(--crs-gray-500, #adb5bd);
    font-size: 0.7rem;
    border-radius: 4px;
    transition: color 0.15s ease, background 0.15s ease;
}
.invoice-override-edit-link:hover,
.invoice-override-edit-link:focus {
    color: #d97706;
    background: #fff7ed;
    text-decoration: none;
    outline: none;
}

.exec-aging-flex {
    display: flex;
    align-items: center;
    gap: 0.85rem;
}
.exec-aging-canvas-wrap {
    position: relative;
    width: 130px;
    height: 130px;
    flex-shrink: 0;
}
.exec-aging-canvas-wrap canvas { display: block; }
.exec-aging-center {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    text-align: center;
}
.exec-aging-center-label {
    font-size: 0.65rem;
    text-transform: uppercase;
    color: #6b7280;
    letter-spacing: 0.04em;
}
.exec-aging-center-value {
    font-weight: 700;
    font-size: 0.9rem;
    color: #111827;
}
.exec-aging-legend {
    list-style: none;
    padding: 0;
    margin: 0;
    flex: 1;
    font-size: 0.8rem;
}
.exec-aging-legend li {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 0.4rem;
    align-items: center;
    padding: 0.15rem 0;
}
.exec-aging-swatch {
    width: 10px; height: 10px;
    border-radius: 2px;
    display: inline-block;
}
.exec-aging-swatch-0 { background: #10b981; }
.exec-aging-swatch-1 { background: #2563eb; }
.exec-aging-swatch-2 { background: #f59e0b; }
.exec-aging-swatch-3 { background: #ef4444; }
.exec-aging-swatch-4 { background: #991b1b; }

@media (max-width: 992px) {
    .exec-tiles, .exec-leaderboards { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 600px) {
    .exec-tiles, .exec-leaderboards { grid-template-columns: 1fr; }
}

/* ----------------------------------------------------------------- */
/* Quota Tracker tile (per-rep dashboard headline KPIs)              */
/* ----------------------------------------------------------------- */
/* Stretch the card to fill its row alongside the (taller) Commission
   Paid tile so the chart can absorb the otherwise-empty whitespace
   under the bar/percentage block. The column itself is already a flex
   item with stretch alignment (Bootstrap 4 default); these rules pass
   that height all the way down to .quota-tracker-chart-wrap so the
   chart grows to fill it. */
.quota-tracker-card.card {
    height: 100%;
    display: flex;
    flex-direction: column;
}
.quota-tracker-card .card-body {
    padding: 1rem 1.1rem;
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
}
.quota-tracker-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 0.85rem;
    margin: 0.25rem 0 0.5rem;
}
.quota-tracker-stat { flex: 1; min-width: 0; }
.quota-tracker-actual {
    font-size: 1.55rem;
    font-weight: 700;
    color: #111827;
    line-height: 1.15;
}
.quota-tracker-vs {
    font-size: 0.78rem;
    color: #6b7280;
    margin-top: 0.1rem;
}
.quota-tracker-status {
    text-align: right;
    padding: 0.45rem 0.75rem;
    border-radius: 0.45rem;
    border: 1px solid;
    min-width: 130px;
}
.quota-tracker-pct {
    font-size: 1.2rem;
    font-weight: 700;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}
.quota-tracker-state {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
    margin-top: 0.1rem;
}
.quota-tracker-status.status-on     { background: #ecfdf5; border-color: #a7f3d0; color: #047857; }
.quota-tracker-status.status-pace   { background: #fffbeb; border-color: #fcd34d; color: #b45309; }
.quota-tracker-status.status-behind { background: #fef2f2; border-color: #fecaca; color: #b91c1c; }

.quota-tracker-progress {
    position: relative;
    height: 8px;
    background: #f3f4f6;
    border-radius: 4px;
    overflow: hidden;
    margin-bottom: 0.65rem;
}
.quota-tracker-progress-fill {
    height: 100%;
    border-radius: 4px;
    transition: width 0.3s ease;
}
.quota-tracker-progress-fill { background: #2563eb; }
.quota-tracker-progress-fill.fill-on     { background: #10b981; }
.quota-tracker-progress-fill.fill-pace   { background: #f59e0b; }
.quota-tracker-progress-fill.fill-behind { background: #ef4444; }

/* Callout shown under the quota progress bar when there's revenue from
   reps without a quota — those sales are bucketed out of the chart +
   the % of quota math so the comparison is apples-to-apples, but the
   total surfaces here so it's still visible. */
.quota-tracker-no-quota {
    font-size: 0.75rem;
    color: var(--crs-gray-700, #495057);
    background: var(--crs-gray-100, #f6f7f9);
    border: 1px solid var(--crs-gray-200, #e9ecef);
    border-left: 3px solid var(--crs-gray-500, #adb5bd);
    border-radius: 4px;
    padding: 0.35rem 0.55rem;
    margin: 0.5rem 0 0.65rem;
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    line-height: 1.4;
}
.quota-tracker-no-quota > i {
    color: var(--crs-gray-500, #adb5bd);
    flex-shrink: 0;
    align-self: center;
}
.quota-tracker-no-quota strong {
    color: var(--crs-gray-900, #202124);
    font-variant-numeric: tabular-nums;
}
.quota-tracker-no-quota-meta {
    color: var(--crs-gray-500, #adb5bd);
    font-style: italic;
    font-size: 0.7rem;
    margin-left: auto;
}
/* Tick mark at 100% to show the quota target. The progress bar's max
   visible width is 100% so the marker sits at the right edge — but we
   keep it as a separate vertical bar so reps can see the threshold
   even when their fill is short. */
.quota-tracker-progress-target {
    position: absolute;
    top: -2px;
    bottom: -2px;
    right: 0;
    width: 2px;
    background: #1f2937;
}

.quota-tracker-chart-wrap {
    position: relative;
    /* Grow to absorb the slack space inside .quota-tracker-card so the
       chart fills whatever height the sibling Commission Paid tile
       (with its sparkline) sets. min-height keeps the chart legible
       on short cards (e.g. when the no-quota callout is hidden). */
    flex: 1 1 auto;
    min-height: 200px;
    margin-top: 0.4rem;
}
/* On a phone the legend wraps to several rows. At 12px text (the
   readable floor) that left a 220px canvas with only ~87px of actual
   plot -- the legend was the chart. The text stays 12px; the CARD gives
   up the height instead, and the shared layer tightens legend padding
   on narrow boxes. */
@media (max-width: 768px) {
    .quota-tracker-chart-wrap { min-height: 300px; }
}
.quota-tracker-chart-wrap canvas { display: block; cursor: pointer; }

/* ----------------------------------------------------------------- */
/* Commission pipeline graphic (per-rep dashboard)                   */
/* ----------------------------------------------------------------- */
/* Three-stage horizontal flow: aging buckets → total unlockable →
   commission outstanding. Reads as a money funnel — customer A/R
   collects on the left, the aged dollars convert into unlockable
   commission, and the most-recent month's earned commission spills
   out the right side as the rep's payout. */
.commission-pipeline {
    display: grid;
    grid-template-columns: minmax(0, 2.4fr) auto minmax(0, 1fr);
    align-items: stretch;
    gap: 0.5rem;
}
.pipeline-stage {
    background: #fff;
    border: 1px solid #e5e7eb;
    border-radius: 0.5rem;
    padding: 0.85rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    position: relative;
}
.pipeline-stage-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.pipeline-stage-title {
    text-transform: uppercase;
    font-size: 0.7rem;
    letter-spacing: 0.06em;
    font-weight: 600;
    color: #6b7280;
}
.pipeline-stage-help {
    position: static !important;
    width: 22px; height: 22px;
    border-radius: 50%;
    background: transparent;
    border: 1px solid #d1d5db;
    color: #6b7280;
    font-size: 0.7rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.pipeline-stage-help:hover {
    background: var(--crs-red, #c8102e);
    border-color: var(--crs-red, #c8102e);
    color: #fff;
}
.pipeline-stage-amount {
    font-size: 1.55rem;
    font-weight: 700;
    color: #111827;
    line-height: 1.15;
    margin-top: auto;
}
.pipeline-stage-sub { font-size: 0.78rem; color: #6b7280; }
.pipeline-stage-meta {
    font-size: 0.72rem;
    color: #4b5563;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
}
.pipeline-stage-unlockable { border-left: 4px solid #10b981; }
.pipeline-stage-unlockable .pipeline-stage-amount { color: #10b981; }
.pipeline-stage-payout     {
    border-left: 4px solid #10b981;
    background: linear-gradient(135deg, #ecfdf5 0%, #f0fdf4 100%);
    border-color: #a7f3d0;
    border-left-color: #10b981;
    box-shadow: 0 2px 8px rgba(16, 185, 129, 0.12);
}
.pipeline-stage-payout .cmp-stage-amount {
    font-size: 1.55rem;
    font-weight: 800;
    color: #059669;
    letter-spacing: -0.02em;
}
.pipeline-stage-payout .pipeline-stage-title {
    color: #059669;
    font-weight: 700;
}
.pipeline-stage-payout .pipeline-stage-amount { color: #059669; }
.pipeline-stage-aging      { border-left: 4px solid #2563eb; }

/* Full-width variant of .pipeline-stage-payout — reused as a Headline-KPI
   banner (Aug 2026) instead of the narrow rightmost pipeline stage. Same
   green treatment, but flows its header/amount/meta horizontally so the
   extra width reads as a banner instead of a tall card with empty sides. */
.kpi-banner-full {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1.5rem;
}
.kpi-banner-full .pipeline-stage-header {
    flex: 0 0 auto;
}
.kpi-banner-full .cmp-stage-amount {
    margin-top: 0;
}
.kpi-banner-full .cmp-stage-sub,
.kpi-banner-full .cmp-stage-meta,
.kpi-banner-full .cmp-stage-disclaimer {
    flex: 0 0 auto;
}
@media (max-width: 700px) {
    .kpi-banner-full { flex-direction: column; align-items: flex-start; }
}

.pipeline-buckets {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 0.4rem;
    margin-top: 0.2rem;
}

/* Single stacked-bar graphic — each segment width = its bucket's share
   of total outstanding receivables, so the geometry of the bar IS the
   breakdown. Replaces the 5-column grid for a more cohesive read. */
.pipeline-stack {
    display: flex;
    align-items: stretch;
    margin-top: 0.35rem;
    border: 1px solid #e5e7eb;
    border-radius: 0.4rem;
    overflow: hidden;
    background: #f9fafb;
    min-height: 84px;
}
.pipeline-stack-seg {
    /* flex-grow comes from the inline style (= share_pct). Setting a
       min-basis keeps near-zero buckets visible enough to label. */
    flex-basis: 0;
    flex-shrink: 0;
    min-width: 84px;
    padding: 0.55rem 0.7rem;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 0.15rem;
    border-right: 1px solid rgba(255, 255, 255, 0.85);
    /* Default tinted gradient — bucket-specific colors override below. */
    background: linear-gradient(180deg, #f3f4f6 0%, #e5e7eb 100%);
    color: #111827;
    transition: filter 0.15s ease;
    overflow: hidden;
}
.pipeline-stack-seg:last-child { border-right: 0; }
.pipeline-stack-seg:hover { filter: brightness(0.96); }
.pipeline-stack-seg.is-empty { opacity: 0.55; }

.pipeline-stack-seg-label {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 700;
    color: rgba(255, 255, 255, 0.92);
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}
.pipeline-stack-seg-amount {
    font-size: 1.05rem;
    font-weight: 700;
    color: #fff;
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.pipeline-stack-seg-meta {
    font-size: 0.7rem;
    color: rgba(255, 255, 255, 0.85);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Bucket-specific gradients — match the bar-fill colors used elsewhere
   so the visual language stays consistent across the dashboard. */
.pipeline-stack-seg.pipeline-bucket-0-30   { background: linear-gradient(180deg, #34d399 0%, #10b981 100%); }
.pipeline-stack-seg.pipeline-bucket-31-60  { background: linear-gradient(180deg, #60a5fa 0%, #2563eb 100%); }
.pipeline-stack-seg.pipeline-bucket-61-90  { background: linear-gradient(180deg, #fbbf24 0%, #f59e0b 100%); }
.pipeline-stack-seg.pipeline-bucket-91-120 { background: linear-gradient(180deg, #f87171 0%, #ef4444 100%); }
.pipeline-stack-seg.pipeline-bucket-120\+  { background: linear-gradient(180deg, #b91c1c 0%, #991b1b 100%); }
.pipeline-stack-seg.is-empty {
    /* No data → flat gray so it doesn't draw the eye. */
    background: linear-gradient(180deg, #e5e7eb 0%, #d1d5db 100%);
}
.pipeline-stack-seg.is-empty .pipeline-stack-seg-label,
.pipeline-stack-seg.is-empty .pipeline-stack-seg-amount,
.pipeline-stack-seg.is-empty .pipeline-stack-seg-meta {
    color: #6b7280;
}

/* Click-to-expand on a pipeline-stack segment.
   Default state shows the abbreviated value (.pipeline-stack-seg-short)
   and hides the full value (.pipeline-stack-seg-full). When a segment
   is clicked, JS adds .is-expanded to it and .has-expanded to the
   parent .pipeline-stack — the focused seg grows to dominate the row,
   the rest collapse to a min-width sliver, and the focused seg
   reveals its un-abbreviated values. Click again (or click another
   segment) to reset. */
.pipeline-stack-seg-short { display: inline; }
.pipeline-stack-seg-full  { display: none; }
.pipeline-stack-seg.is-expanded .pipeline-stack-seg-short { display: none; }
.pipeline-stack-seg.is-expanded .pipeline-stack-seg-full  { display: inline; }

.pipeline-stack-seg {
    cursor: pointer;
    /* Smooth size transition when a segment is focused / unfocused. */
    transition: filter 0.15s ease, flex-grow 0.25s ease, opacity 0.2s ease;
}
.pipeline-stack-seg:focus { outline: 2px solid var(--crs-red); outline-offset: -2px; }

/* When the parent stack has a focused segment, dim + collapse the
   non-focused segments. The focused seg gets a much higher flex-grow
   so it visibly dominates the row (proportions are no longer
   share-based — that's the whole point of focus mode). */
.pipeline-stack.has-expanded .pipeline-stack-seg {
    flex-grow: 0.4 !important;
    opacity: 0.55;
}
.pipeline-stack.has-expanded .pipeline-stack-seg.is-expanded {
    flex-grow: 6 !important;
    opacity: 1;
    box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.6);
}
/* In focused state, the expanded seg's full values get a touch more
   breathing room so the comma-formatted figure reads cleanly. */
.pipeline-stack-seg.is-expanded .pipeline-stack-seg-amount {
    font-size: 1.4rem;
    line-height: 1.2;
    white-space: normal;
}
.pipeline-stack-seg.is-expanded .pipeline-stack-seg-meta {
    font-size: 0.85rem;
    white-space: normal;
}
/* "View details" drill-down button inside an expanded segment. Hidden
   in the default (collapsed) state since the seg is too narrow to host
   it; revealed when the seg gains .is-expanded so the user has a clear
   action target after focusing a bucket. */
.pipeline-stack-seg-action {
    display: none;
    margin-top: 0.5rem;
    align-self: center;
    font-size: 0.8rem;
    font-weight: 600;
    color: #1f2937;
    background: rgba(255, 255, 255, 0.92);
    border: 1px solid rgba(0, 0, 0, 0.08);
    text-decoration: none;
}
.pipeline-stack-seg-action:hover,
.pipeline-stack-seg-action:focus {
    background: #ffffff;
    color: #111827;
    text-decoration: none;
}
.pipeline-stack-seg.is-expanded .pipeline-stack-seg-action {
    display: inline-block;
}

/* KPI drill-down links — clickable KPI values that navigate to detail pages. */
.kpi-drilldown-link {
    color: inherit;
    text-decoration: none;
    border-bottom: 2px dashed rgba(0, 0, 0, 0.15);
    transition: border-color 0.15s, color 0.15s;
    cursor: pointer;
}
.kpi-drilldown-link:hover,
.kpi-drilldown-link:focus {
    color: #2563eb;
    border-bottom-color: #2563eb;
    text-decoration: none;
}
a.kpi-drilldown-block {
    color: inherit;
    text-decoration: none;
    transition: box-shadow 0.15s, border-color 0.15s;
    cursor: pointer;
}
a.kpi-drilldown-block:hover,
a.kpi-drilldown-block:focus {
    box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.25);
    border-color: #2563eb;
    text-decoration: none;
    color: inherit;
}
a.pipeline-stage.kpi-drilldown-block:hover .pipeline-stage-amount,
a.pipeline-stage.kpi-drilldown-block:focus .pipeline-stage-amount {
    text-decoration: underline;
}
a.current-month-stat.kpi-drilldown-block {
    border-radius: 0.4rem;
    padding: 0.3rem 0.5rem;
}
a.current-month-stat.kpi-drilldown-block:hover .current-month-stat-value {
    color: #2563eb;
}
.pipeline-bucket {
    background: #f9fafb;
    border: 1px solid #e5e7eb;
    border-radius: 0.35rem;
    padding: 0.45rem 0.55rem;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}
.pipeline-bucket-label {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #6b7280;
    font-weight: 600;
}
.pipeline-bucket-amount {
    font-size: 1rem;
    font-weight: 700;
    color: #111827;
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
}
.pipeline-bucket-meta {
    font-size: 0.7rem;
    color: #6b7280;
    font-variant-numeric: tabular-nums;
}
.pipeline-bucket-bar {
    height: 4px;
    background: #e5e7eb;
    border-radius: 2px;
    margin-top: 0.25rem;
    overflow: hidden;
}
.pipeline-bucket-bar-fill {
    height: 100%;
    background: #2563eb;
    transition: width 0.25s ease;
}
.pipeline-bucket-0-30   .pipeline-bucket-bar-fill { background: #10b981; }
.pipeline-bucket-31-60  .pipeline-bucket-bar-fill { background: #2563eb; }
.pipeline-bucket-61-90  .pipeline-bucket-bar-fill { background: #f59e0b; }
.pipeline-bucket-91-120 .pipeline-bucket-bar-fill { background: #ef4444; }
.pipeline-bucket-120\+  .pipeline-bucket-bar-fill { background: #991b1b; }

.pipeline-bucket.is-overdue .pipeline-bucket-amount { color: #b91c1c; }
.pipeline-bucket-0-30 .pipeline-bucket-amount { color: #047857; }

.pipeline-arrow {
    display: flex;
    align-items: center;
    justify-content: center;
    color: #9ca3af;
    font-size: 1rem;
    padding: 0 0.25rem;
}

@media (max-width: 1100px) {
    .commission-pipeline { grid-template-columns: 1fr; }
    .pipeline-arrow { transform: rotate(90deg); height: 1.25rem; }
}
@media (max-width: 700px) {
    .pipeline-buckets { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Equal-height KPI tiles. Bootstrap rows already stretch their columns,
   but the inner .card defaults to its content height — so a tile with a
   sub-line (e.g. "vs Quota: ...") would stand taller than its neighbors.
   Force every .card whose body is a kpi-card-body to fill the column. */
.card:has(> .kpi-card-body) {
    height: 100%;
}
.kpi-help {
    /* Small circular pill — subtle when idle, brand-red and slightly
       raised on hover. Sized so it aligns with typical card padding. */
    position: absolute;
    top: 8px;
    right: 8px;
    width: 22px;
    height: 22px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--crs-gray-300, #e5e7eb);
    border-radius: 50%;
    background: var(--crs-gray-100, #f6f7f9);
    color: var(--crs-gray-600, #6c757d);
    font-size: 0.72rem;
    line-height: 1;
    opacity: 0.85;
    cursor: pointer;
    transition: background 0.18s ease, color 0.18s ease,
                border-color 0.18s ease, transform 0.18s ease,
                box-shadow 0.18s ease, opacity 0.18s ease;
}
.kpi-help:hover,
.kpi-help:focus {
    opacity: 1;
    background: var(--crs-red-light, #FCE8EC);
    color: var(--crs-red, #C8102E);
    border-color: var(--crs-red, #C8102E);
    outline: none;
    transform: scale(1.08);
    box-shadow: 0 2px 6px rgba(200, 16, 46, 0.22);
}
.kpi-help:active {
    transform: scale(0.94);
    box-shadow: 0 1px 2px rgba(200, 16, 46, 0.18) inset;
}
.kpi-help i { pointer-events: none; }

/* Inline variant of the help pill for cells inside the monthly-grid
   tables (e.g. the "Commissionable Amount" row labels). Same visual
   language as .kpi-help but inline-positioned next to the label text
   instead of absolute-positioned in a card corner. */
.row-help {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0;
    margin-left: 4px;
    border: 1px solid var(--crs-gray-300, #e5e7eb);
    border-radius: 50%;
    background: var(--crs-gray-100, #f6f7f9);
    color: var(--crs-gray-600, #6c757d);
    font-size: 0.65rem;
    line-height: 1;
    opacity: 0.85;
    cursor: pointer;
    vertical-align: middle;
    transition: background 0.18s ease, color 0.18s ease,
                border-color 0.18s ease, transform 0.18s ease,
                box-shadow 0.18s ease, opacity 0.18s ease;
}
.row-help:hover,
.row-help:focus {
    opacity: 1;
    background: var(--crs-red-light, #FCE8EC);
    color: var(--crs-red, #C8102E);
    border-color: var(--crs-red, #C8102E);
    outline: none;
    transform: scale(1.1);
    box-shadow: 0 2px 6px rgba(200, 16, 46, 0.22);
}
.row-help:active {
    transform: scale(0.94);
    box-shadow: 0 1px 2px rgba(200, 16, 46, 0.18) inset;
}
.row-help i { pointer-events: none; }

/* Modal body spacing */
#kpiHelpBody p  { margin-bottom: 0.7rem; }
#kpiHelpBody ul { margin-bottom: 0.7rem; padding-left: 1.2rem; }
#kpiHelpBody li { margin-bottom: 0.2rem; }

/* Commission-summary controls row ---------------------------------------
   Horizontal strip with:  [period]  [rep filter + inline Clear]  ...  [export]
   Implemented as CSS flex. Each .controls-cell is a column holding a small
   label + the control itself. Export gets pushed to the right via
   .controls-cell-right (margin-left: auto). Nothing stretches — every
   control sits at the natural content width of its select/button. */
.controls-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 14px 20px;
    margin-bottom: 1rem;
}
.controls-cell { display: flex; flex-direction: column; }
.controls-cell > label {
    font-size: 0.78rem;
    color: var(--crs-gray-600, #6c757d);
    margin-bottom: 4px;
    font-weight: 500;
}
.controls-cell > label .hint {
    font-weight: 400;
    color: var(--crs-gray-500, #9aa0a6);
    font-size: 0.75rem;
}
.controls-cell-right { margin-left: auto; }
.controls-row form { margin: 0; }
.controls-row .form-control-sm { min-width: 160px; }

/* --- Searchable chip-based rep filter -------------------------------------
   Replaces the previous native <select multiple>. Structure:
     .rep-filter-widget
       .rep-filter-inputwrap  (search icon + input + clear)
       .rep-filter-dropdown   (absolute-positioned options list)
       .rep-filter-chips      (selected rep pills with × buttons)
       select.rep-filter-hidden-select  (DOM-only source of truth)
*/
.rep-filter-cell { min-width: 320px; max-width: 420px; }
.rep-filter-widget {
    position: relative;
    width: 100%;
}
.rep-filter-inputwrap {
    position: relative;
    display: flex;
    align-items: stretch;
    gap: 6px;
}
.rep-filter-search-icon {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--crs-gray-500);
    font-size: 0.85rem;
    pointer-events: none;
}
input.rep-filter-search {
    flex: 1;
    /* Bootstrap's `.form-control-sm` ships a left padding of 0.5rem that
       overrides this rule due to specificity unless we force it. The
       icon sits at left: 10px (~14px wide) so the text needs to start
       at ~32px+ to clear it. */
    padding-left: 32px !important;
    border-radius: var(--crs-radius, 6px);
    border: 1px solid var(--crs-gray-300);
    transition: border-color 0.15s, box-shadow 0.15s;
}
input.rep-filter-search:focus {
    border-color: var(--crs-red);
    box-shadow: 0 0 0 3px var(--crs-red-tint);
    outline: none;
}
.rep-filter-clear-btn {
    background: transparent;
    color: var(--crs-gray-600);
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius, 6px);
    padding: 0 0.75rem;
    font-size: 0.78rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.15s;
    line-height: 1;
}
.rep-filter-clear-btn:hover {
    background: var(--crs-red-light);
    color: var(--crs-red-dark);
    border-color: var(--crs-red);
}
.rep-filter-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 30;
    max-height: 260px;
    overflow-y: auto;
    background: #fff;
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius, 6px);
    box-shadow: 0 6px 16px rgba(13, 13, 13, 0.12);
}
.rep-filter-item {
    padding: 0.45rem 0.75rem;
    cursor: pointer;
    font-size: 0.9rem;
    color: var(--crs-gray-900);
    border-bottom: 1px solid var(--crs-gray-100);
    transition: background 0.12s, color 0.12s;
}
.rep-filter-item:last-child { border-bottom: none; }
.rep-filter-item:hover,
.rep-filter-item:focus {
    background: var(--crs-red-light);
    color: var(--crs-red-dark);
    outline: none;
}
.rep-filter-item mark {
    background: transparent;
    color: inherit;
    font-weight: 700;
    padding: 0;
}
.rep-filter-empty {
    padding: 0.55rem 0.75rem;
    color: var(--crs-gray-600);
    font-style: italic;
    font-size: 0.85rem;
    text-align: center;
}
.rep-filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.5rem;
}
.rep-filter-chips:empty { display: none; }
.rep-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    background: var(--crs-red-light);
    color: var(--crs-red-dark);
    border: 1px solid var(--crs-red-tint);
    border-radius: 999px;
    padding: 0.2rem 0.4rem 0.2rem 0.7rem;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.2;
    transition: box-shadow 0.12s;
}
.rep-chip:hover { box-shadow: 0 1px 4px rgba(200, 16, 46, 0.15); }
.rep-chip-x {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: rgba(200, 16, 46, 0.15);
    color: var(--crs-red-dark);
    border: 0;
    border-radius: 50%;
    width: 1.15rem;
    height: 1.15rem;
    padding: 0;
    font-size: 0.95rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.12s;
}
.rep-chip-x:hover {
    background: var(--crs-red);
    color: #fff;
}
.rep-filter-hidden-select { display: none !important; }
/* Bootstrap 4 provides .text-success / .text-danger, but nail the exact
   shade we want so they read at a glance on white-background cells. */
.text-success { color: #0f9d58 !important; }
.text-danger  { color: #d93025 !important; }

/* ── Projection modal (current-month banner click) ────────────── */
button.current-month-stat-projected {
    background: none;
    border: 1px solid transparent;
    border-radius: 0.4rem;
    padding: 0.3rem 0.5rem;
    cursor: pointer;
    transition: border-color 0.18s, box-shadow 0.18s, background 0.18s;
    text-align: left;
}
button.current-month-stat-projected:hover,
button.current-month-stat-projected:focus {
    border-color: #d97706;
    box-shadow: 0 2px 8px rgba(217, 119, 6, 0.15);
    background: #fffbeb;
    outline: none;
}
button.current-month-stat-projected:hover .current-month-stat-value {
    text-decoration: underline;
}

.projection-breakdown { font-size: 0.92rem; }

.projection-formula {
    background: #f9fafb;
    border: 1px solid #e5e7eb;
    border-radius: 0.5rem;
    padding: 0.75rem 1rem;
}
.projection-formula-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.3rem 0;
}
.projection-formula-row + .projection-formula-row {
    border-top: 1px solid #f3f4f6;
}
.projection-formula-divider {
    border-top: 2px dashed #d1d5db !important;
    margin-top: 0.15rem;
    padding-top: 0.45rem;
}
.projection-formula-label {
    color: #374151;
    font-weight: 500;
}
.projection-formula-value {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: #111827;
}
.projection-formula-computed { color: #2563eb; }
.projection-formula-result {
    border-top: 2px solid #111827 !important;
    margin-top: 0.25rem;
    padding-top: 0.5rem;
}
.projection-formula-result .projection-formula-label {
    font-weight: 700;
    color: #111827;
}
.projection-formula-result .projection-formula-value {
    font-size: 1.05rem;
    color: #92400e;
}

.projection-drivers h6 {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #6b7280;
    font-weight: 600;
    margin-bottom: 0.5rem;
}
.projection-driver-card {
    background: #fff;
    border: 1px solid #e5e7eb;
    border-radius: 0.4rem;
    padding: 0.6rem 0.75rem;
    text-align: center;
}
.projection-driver-label {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: #6b7280;
    font-weight: 600;
    margin-bottom: 0.3rem;
}
.projection-driver-values {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    font-variant-numeric: tabular-nums;
}
.projection-driver-actual {
    font-weight: 700;
    color: #111827;
    font-size: 0.95rem;
}
.projection-driver-arrow {
    color: #9ca3af;
    font-size: 0.85rem;
}
.projection-driver-projected {
    font-weight: 700;
    color: #92400e;
    font-size: 0.95rem;
}
.projection-driver-sub {
    font-size: 0.68rem;
    color: #9ca3af;
    margin-top: 0.15rem;
}

.projection-chart-wrap {
    background: #f9fafb;
    border: 1px solid #e5e7eb;
    border-radius: 0.5rem;
    padding: 0.75rem;
    position: relative;
    height: 260px;
    /* Column layout so the heading takes its own height and the chart
       box takes the rest. Previously the canvas was sized against the
       whole 260px wrap and then pushed down by the heading, so it ran
       ~24px past the panel's bottom edge. */
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.projection-chart-box {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
}
.projection-chart-box canvas { display: block; }
.projection-chart-wrap h6 {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #6b7280;
    font-weight: 600;
    margin-bottom: 0.5rem;
}

#projectionModal .modal-header {
    border-bottom: 2px solid #f59e0b;
    background: #fffbeb;
}
#projectionModal .modal-title {
    color: #92400e;
    font-weight: 700;
    font-size: 1rem;
}
#projectionModal .modal-title i { margin-right: 0.35rem; }

#projectionModal .text-muted.small {
    font-size: 0.75rem;
    margin-top: 0.75rem;
}

/* Potential commission sub-line in earned callout */
.earned-this-month-potential {
    font-size: 0.82rem;
    color: #b45309;
    margin-top: 2px;
    font-weight: 500;
}
.earned-this-month-potential i {
    color: #d97706;
    margin-right: 3px;
    font-size: 0.75rem;
}

/* ---- Scope Visual (Invoice Detail) ---- */
.scope-visual {
    background: var(--clair-card-bg, #fff);
    border: 1px solid var(--clair-border, #e2e8f0);
    border-radius: 10px;
    padding: 14px 18px 12px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}
.scope-visual-header {
    font-size: 0.85rem;
    color: var(--clair-text-secondary, #475569);
    margin-bottom: 8px;
}
.scope-visual-header i {
    margin-right: 5px;
    opacity: 0.6;
}
.scope-visual-header strong {
    color: var(--clair-text, #1e293b);
}
.scope-visual-note {
    font-weight: 400;
    color: var(--clair-text-secondary, #64748b);
    font-size: 0.8rem;
}
/* Stacked bar */
.scope-visual-bar-wrap { margin-bottom: 8px; }
.scope-visual-bar {
    display: flex;
    height: 18px;
    border-radius: 9px;
    overflow: hidden;
    background: var(--clair-bg, #f1f5f9);
}
.scope-seg {
    min-width: 2px;
    transition: flex 0.3s ease;
}
.scope-seg-paid        { background: rgba(16, 185, 129, 0.75); }
.scope-seg-paid-other  { background: rgba(16, 185, 129, 0.35); }
.scope-seg-unpaid      { background: rgba(245, 158, 11, 0.60); }
/* Blue and purple were a fifth and sixth hue on a charcoal / red / status
   app, and neither said anything: this bar splits "posted this month" from
   "posted earlier", which is a foreground/background distinction, not a
   good/bad one. Ink for the month in focus, grey for the rest. Green is
   deliberately NOT reused -- it means paid, and this bar is not about
   payment. */
.scope-seg-this-month  { background: var(--crs-charcoal); }
.scope-seg-other-month { background: var(--crs-gray-400); }
/* Legend */
.scope-visual-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 16px;
    font-size: 0.78rem;
    color: var(--clair-text-secondary, #475569);
}
.scope-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    white-space: nowrap;
}
.scope-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 3px;
    flex-shrink: 0;
}
.scope-dot-paid        { background: rgba(16, 185, 129, 0.75); }
.scope-dot-paid-other  { background: rgba(16, 185, 129, 0.35); }
.scope-dot-unpaid      { background: rgba(245, 158, 11, 0.60); }
.scope-dot-this-month  { background: var(--crs-charcoal); }
.scope-dot-other-month { background: var(--crs-gray-400); }
/* Section label between bars */
.scope-visual-section-label {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--clair-text-secondary, #64748b);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-top: 10px;
    margin-bottom: 4px;
}
/* Info callout inside scope visual */
.scope-visual-callout {
    margin-top: 8px;
    padding: 8px 12px;
    font-size: 0.78rem;
    color: var(--clair-text-secondary, #475569);
    background: var(--crs-gray-100);
    border-left: 3px solid var(--crs-gray-300);
    border-radius: 0 6px 6px 0;
    line-height: 1.4;
}
.scope-visual-callout i {
    color: var(--crs-gray-600);
    margin-right: 4px;
}

/* --------------------------------------------------------------------- *
 * v3 mobile walk (390×844) — keep the existing hamburger / base.html    *
 * @media (max-width:768px) block intact. These rules only patch the     *
 * remaining signed-in pages from the live walk.                         *
 * --------------------------------------------------------------------- */

/* P0 /sales/: .table td { white-space:nowrap } + width:100% tables clip
   long opportunity names and .table-responsive does not scroll. */
td.oppty-name-cell,
.table td.oppty-name-cell,
.table th.oppty-name-cell {
    white-space: normal !important;
    word-break: break-word;
    overflow-wrap: anywhere;
    max-width: 14rem;
}
td.oppty-name-cell a {
    white-space: normal;
    word-break: break-word;
    overflow-wrap: anywhere;
}

/* P0 /commissions/: one shared horizontal scroller for the stacked
   monthly grids so Sales / Paid / Outstanding stay on the same month.
   Must stay the ONLY overflow-x box — base.html's bare-table wrap
   skips .monthly-grids-scroll so it cannot inject a per-table
   .table-responsive (those independently-scrolled and months drifted). */
.monthly-grids-scroll,
.table-responsive.monthly-grids-scroll {
    overflow-x: auto !important;
    overflow-y: visible;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x;
    overscroll-behavior-x: contain;
    max-width: 100%;
    margin-bottom: 0.75rem;
}
.monthly-grids-scroll .table-responsive {
    overflow: visible !important;
    max-width: none;
}
/* Beat `#content table { display:block; overflow-x:auto }` so the
   shared wrapper is the sticky containing block (not each table). */
.monthly-grids-scroll table,
.monthly-grid {
    display: table !important;
    overflow: visible !important;
}
.monthly-grids-scroll > h4,
.monthly-grids-scroll > p {
    position: sticky;
    left: 0;
    width: max-content;
    max-width: 100%;
}
.monthly-grid thead th:first-child,
.monthly-grid tbody td:first-child,
.monthly-grid tfoot th:first-child,
.monthly-grid tfoot td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: #fff;
    box-shadow: 1px 0 0 #dee2e6;
}
.monthly-grid thead th:first-child {
    background: #212529;
    color: #fff;
    z-index: 3;
}
.monthly-grid.table-striped tbody tr:nth-of-type(odd) td:first-child {
    background: #f2f2f2;
}
.monthly-grid tbody tr.table-active td:first-child {
    background: #d6d8db;
}

/* P1: DataTables scrollX already provides the scroller on team/all/
   invoice — hide the outer wrap so those pages don't nest two
   horizontal bars. Aging + the forecasting matrix are exceptions:
   they keep thead/tbody/tfoot as one table (no scrollX split) so
   TOTAL stays column-aligned, and this wrap is the only scroller. */
.table-responsive:has(.dt-container),
.table-responsive:has(.dataTables_wrapper),
.table-responsive.dt-scroll-wrap {
    overflow: hidden !important;
}
.table-responsive.dt-scroll-wrap.aging-scroll-wrap,
.table-responsive.dt-scroll-wrap:has(#aging_table) {
    overflow-x: auto !important;
    overflow-y: hidden !important;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x;
    overscroll-behavior-x: contain;
    max-width: 100%;
}
/* Forecasting matrix: one overflow box. pan-x alone + overflow-y:hidden
   ate vertical flicks (page couldn't scroll when the finger started on
   the table). Allow both axes; keep the wrap as the only scroller so
   LINE OF BUSINESS stays sticky and TOTAL stays column-aligned. */
.table-responsive.matrix-scroll-wrap,
.table-responsive:has(#forecast_table) {
    overflow-x: auto !important;
    overflow-y: visible !important;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x pan-y;
    overscroll-behavior-x: auto;
    max-width: 100%;
}
.matrix-scroll-wrap .dataTables_wrapper,
.matrix-scroll-wrap .dt-container,
.matrix-scroll-wrap .dataTables_scroll,
.matrix-scroll-wrap .dataTables_scrollBody,
#forecast_table_wrapper {
    overflow: visible !important;
}

/* P1: wide admin tables — pin the first / identity column while the
   rest pans. `#content table { overflow-x:auto }` made the TABLE the
   sticky containing block (and it doesn't scroll — .table-responsive
   does), so position:sticky on Register / Orphan / Doc-Drift was a
   no-op. Force the table out of that role. */
#content .admin-wide-table,
#content table.admin-wide-table,
.admin-wide-table {
    display: table !important;
    overflow: visible !important;
}
.admin-wide-table thead th:first-child,
.admin-wide-table tbody td:first-child,
.admin-wide-table tfoot td:first-child,
.admin-wide-table tfoot th:first-child,
.admin-wide-table th.table-col-sticky,
.admin-wide-table td.table-col-sticky {
    position: sticky !important;
    left: 0;
    z-index: 2;
    background: #fff;
    box-shadow: 1px 0 0 #dee2e6;
}
.admin-wide-table thead.thead-dark th:first-child,
.admin-wide-table thead.thead-dark th.table-col-sticky {
    background: #212529;
    color: #fff;
    z-index: 3;
}
.admin-wide-table thead.thead-light th:first-child,
.admin-wide-table thead.thead-light th.table-col-sticky {
    background: #e9ecef;
    z-index: 3;
}
.admin-wide-table.table-striped tbody tr:nth-of-type(odd) td:first-child,
.admin-wide-table.table-striped tbody tr:nth-of-type(odd) td.table-col-sticky {
    background: #f2f2f2;
}

/* P1: Monthly Close log cells — <pre> pre-wrap never kicked in because
   the parent .small.text-muted sized to the log (~1150px). Collapse
   into <details> and let the parent shrink. */
.admin-wide-table td.close-log-cell,
.admin-wide-table td.small.text-muted,
.admin-wide-table td:has(pre),
.admin-wide-table td:has(.trueup-log),
.admin-wide-table td:has(.trueup-log-wrap),
td:has(> pre),
td:has(> .trueup-log),
td:has(> .trueup-log-wrap) {
    white-space: normal !important;
    width: 100%;
    min-width: 0;
    max-width: 100%;
}
.trueup-log-wrap,
.close-log-inner,
.admin-wide-table td.close-log-cell > .small,
.admin-wide-table td.close-log-cell .small.text-muted {
    display: block;
    width: 100%;
    min-width: 0;
    max-width: 100%;
}
.admin-wide-table pre,
td pre,
.trueup-log,
.trueup-log-wrap pre {
    white-space: pre-wrap !important;
    word-break: break-word;
    overflow-wrap: anywhere;
    width: 100%;
    min-width: 0;
    max-width: 100%;
}

/* P1: quota bar — never let a >100% fill widen the card past the viewport. */
.quota-tracker-card,
.quota-tracker-card .card-body,
.quota-tracker-header,
.quota-tracker-stat {
    min-width: 0;
    max-width: 100%;
}
.quota-tracker-progress {
    overflow: hidden;
    max-width: 100%;
    min-width: 0;
}
.quota-tracker-progress-fill {
    max-width: 100%;
}

/* Monthly Close: the line between reading payroll data and writing it.
   Everything above the band is a queue or a report; the two cards inside it
   freeze a month and write backpay rows. Marked rather than merely ordered,
   because a red button and an amber button in a stack of cards read as two
   more cards. */
.close-danger-zone {
    margin: 1.25rem 0 0;
    padding: 0.9rem 0.9rem 0.1rem;
    border: 1px solid #e6c7c7;
    border-left: 4px solid var(--crs-red, #C8102E);
    border-radius: var(--crs-radius, 6px);
    background: #fdf7f7;
}
.close-danger-zone-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem 0.6rem;
    margin: 0 0 0.75rem;
    font-size: 0.95rem;
    font-weight: 700;
    color: #8a2027;
}
.close-danger-zone-head i { color: var(--crs-red, #C8102E); }
.close-danger-zone-head span {
    font-size: 0.82rem;
    font-weight: 400;
    color: var(--crs-gray-700, #495057);
}

/* P1 /sales/forecasting/: keep the LOB × branch/day matrix, pin LOB,
   and let one scroller carry the TOTAL footer. Reuses admin-wide-table
   sticky-first-col (class is on #forecast_table). */

/* ...and pin TOTAL to the right edge as well. Measured at 1440px: the table
   is 2,125px in a 1,377px box, so 763px hangs off the side and Total -- the
   one number most worth reading beside a row's label -- was the column
   furthest from it. With both ends pinned, only the branch columns move and
   every row keeps its name AND its total in view. Scoped to this table
   rather than to .admin-wide-table, whose other users have no total column
   in that position. */
#forecast_table thead th:last-child,
#forecast_table tbody td:last-child,
#forecast_table tbody th:last-child,
#forecast_table tfoot th:last-child,
#forecast_table tfoot td:last-child {
    position: sticky !important;
    right: 0;
    z-index: 2;
    background: #fff;
    box-shadow: -1px 0 0 #dee2e6;
}
#forecast_table thead.thead-dark th:last-child {
    background: #212529;
    color: #fff;
    z-index: 3;
}
#forecast_table.table-striped tbody tr:nth-of-type(odd) td:last-child {
    background: #f2f2f2;
}
/* The TOTAL row is .table-active, so its own background has to follow the
   cell into the sticky layer or the pinned corner shows white through. */
#forecast_table tbody tr.table-active th:first-child,
#forecast_table tbody tr.table-active td:last-child,
#forecast_table tbody tr.table-active th:last-child {
    background: #ecedee;
}

.forecast-toolbar .btn-group,
.forecast-toolbar .btn-group > .btn {
    width: auto !important;
}
.forecast-toolbar .btn-group {
    display: inline-flex;
    flex-wrap: wrap;
}
.forecast-toolbar .btn-group > .btn {
    flex: 0 0 auto;
}
.forecast-detail-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35rem 0.75rem;
    padding: 0.65rem 0.85rem;
    margin: 0 0.3rem 0.75rem;
    background: var(--crs-gray-100, #f2f2f2);
    border: 1px solid var(--crs-gray-300, #dee2e6);
    border-left: 3px solid var(--crs-red, #C8102E);
    border-radius: var(--crs-radius, 6px);
    font-size: 0.95rem;
}
.forecast-detail-summary-amount {
    margin-left: auto;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* P1 signed-in 404: compact card, no 100vh login gradient. */
.clair-404 {
    max-width: 28rem;
    margin: 1.5rem auto;
    padding: 0.5rem 0.75rem 1.5rem;
}
.clair-404-card {
    background: var(--crs-white, #fff);
    border: 1px solid var(--crs-gray-300, #dee2e6);
    border-left: 3px solid var(--crs-red, #C8102E);
    border-radius: var(--crs-radius, 6px);
    box-shadow: var(--crs-shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.06));
    padding: 1.25rem 1.1rem 1.35rem;
}
.clair-404-code {
    margin: 0 0 0.25rem;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--crs-red, #C8102E);
}
.clair-404-card h1 {
    margin: 0 0 0.5rem;
    font-size: 1.45rem;
    line-height: 1.25;
    word-break: break-word;
}
.clair-404-card p {
    margin: 0 0 1rem;
    color: var(--crs-gray-700, #495057);
}
.clair-404-back {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    width: auto !important;
    min-height: 44px;
    margin: 0;
    text-decoration: none;
}

@media (max-width: 768px) {
    /* P2: 44px tap targets on the remaining small chrome. */
    .kpi-value a,
    .kpi-list a,
    .kpi-card-body a,
    #header .navbar-brand,
    .chart-toggle,
    .monthly-grid td a,
    .table td > a:not(.btn) {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }
    .chart-toggle {
        width: 44px;
        height: 44px;
    }

    /* P2: DataTables Export / Columns / length / search stack full-width. */
    .dt-container .dt-length,
    .dt-container .dt-search,
    .dt-container .dt-buttons,
    .dt-container .dt-info,
    .dt-container .dt-paging,
    .clair-export-bar,
    .clair-export-bar .dt-buttons {
        float: none !important;
        width: 100% !important;
        max-width: 100%;
        display: flex;
        flex-direction: column;
        align-items: stretch;
        text-align: left !important;
        margin-bottom: 0.4rem;
    }
    .dt-container .dt-search input,
    .clair-export-bar .btn,
    .dt-buttons .btn {
        width: 100% !important;
        min-height: 44px;
    }
    /* Length <select> ("50" / "entries per page"): same iOS clip as the
       period month select — form-control-sm ~31px + * { padding: 0 }
       pins "50" to the top border of a tall full-width box. Keep it a
       compact 44px control beside its label, not a full-bleed column. */
    .dt-container .dt-length {
        flex-direction: row !important;
        align-items: center;
        gap: 0.5rem;
    }
    .dt-container .dt-length select {
        width: auto !important;
        min-width: 4.5rem;
        max-width: 7rem;
        height: auto !important;
        min-height: 44px !important;
        padding: 0.5rem 1.75rem 0.5rem 0.75rem !important;
        font-size: 16px !important;
        line-height: 1.25 !important;
        overflow: visible;
        box-sizing: border-box;
    }

    /* Forecasting toolbar: global `.btn { width:100% }` must not stack
       Granularity / Valuation into full-width columns. */
    .forecast-toolbar {
        align-items: flex-end;
    }
    .forecast-toolbar .controls-cell {
        width: auto;
        max-width: 100%;
    }
    .forecast-toolbar .btn-group,
    .forecast-toolbar .btn-group > .btn {
        width: auto !important;
        flex: 0 0 auto;
    }
    .forecast-toolbar #forecastMonthForm {
        width: auto;
        max-width: 100%;
        min-width: 0;
    }
    /* iOS native <select> clip: Bootstrap form-control-sm's ~31px height
       + sales_styles.css `* { padding: 0 }` + global `select { font-size:
       16px; min-height }` chops the top of "Aug 2026". Beat those with
       height:auto and a 44px min so the value is fully visible/centered.
       Extra right padding leaves room for the native caret. width:auto
       keeps it compact next to Granularity (global select is 100%). */
    .forecast-toolbar #month_select,
    .forecast-toolbar select {
        width: auto !important;
        max-width: 100%;
        min-width: 0;
        height: auto !important;
        min-height: 44px !important;
        padding: 0.45rem 2rem 0.45rem 0.75rem !important;
        font-size: 16px !important;
        line-height: 1.25;
        overflow: visible;
        box-sizing: border-box;
    }

    /* Matrix: pin LINE OF BUSINESS, leave the first data column in view
       so swipe is obvious, keep TOTAL in the same overflow box. */
    #forecast_table {
        width: max-content !important;
        min-width: 100%;
    }
    #forecast_table thead th:first-child,
    #forecast_table tbody td:first-child,
    #forecast_table tfoot th:first-child,
    #forecast_table tfoot td:first-child {
        min-width: 7.25rem;
        max-width: 8.5rem;
        width: 8.5rem;
        white-space: normal !important;
        word-break: break-word;
        overflow-wrap: anywhere;
    }
    #forecast_table thead th:not(:first-child),
    #forecast_table tbody td:not(:first-child),
    #forecast_table tfoot th:not(:first-child),
    #forecast_table tfoot td:not(:first-child) {
        min-width: 5.75rem;
        white-space: nowrap;
    }

    /* Forecasting detail cards: TOTAL amount under the label; names wrap.

       Why PR 158 lost at 390px: DataTables 2 still inited the table,
       wrapped tfoot cells in .dt-column-footer / .dt-column-title, and
       typed the amount th as dt-type-numeric. CSS grid on tfoot tr does
       not beat DT table layout / min-content (~487–498px). Phone JS now
       skips DataTables (same as #forecast_table). These rules stack the
       raw HTML tfoot and keep any leftover DT chrome from expanding. */
    .responsive-cards tfoot,
    .responsive-cards tfoot tr,
    .responsive-cards tfoot th,
    .responsive-cards tfoot td {
        display: block !important;
        width: 100%;
        max-width: 100%;
        min-width: 0;
        box-sizing: border-box;
        white-space: normal !important;
        overflow: visible;
        word-break: break-word;
        overflow-wrap: anywhere;
    }
    .responsive-cards tfoot tr {
        display: grid !important;
        grid-template-columns: minmax(0, 1fr);
        background: var(--crs-gray-100, #f2f2f2);
        border: 1px solid var(--crs-gray-300, #dee2e6);
        border-left: 3px solid var(--crs-red, #C8102E);
        border-radius: var(--crs-radius, 6px);
        padding: 0.65rem 0.85rem;
        margin-bottom: 0.75rem;
    }
    /* Beat base.html `.table-responsive table { display:table !important }`
       and `.table-responsive:has(.dt-container) { overflow:hidden }`. */
    .table-responsive:has(#forecast_detail_table),
    .table-responsive:has(#forecast_detail_table_wrapper) {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        overflow-x: visible !important;
        overflow-y: visible !important;
    }
    #forecast_detail_table_wrapper,
    #forecast_detail_table_wrapper.dt-container,
    .table-responsive:has(#forecast_detail_table) .dt-container {
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        overflow-x: visible !important;
    }
    #forecast_detail_table,
    #forecast_detail_table.responsive-cards,
    #forecast_detail_table.responsive-cards tbody,
    #forecast_detail_table.responsive-cards tfoot {
        display: block !important;
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        overflow-x: visible !important;
        overflow: visible !important;
    }
    #forecast_detail_table.responsive-cards tbody tr,
    #forecast_detail_table.responsive-cards tfoot tr {
        display: grid !important;
        grid-template-columns: minmax(0, 1fr);
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
    }
    #forecast_detail_table.responsive-cards tfoot th,
    #forecast_detail_table.responsive-cards tfoot td,
    #forecast_detail_table.responsive-cards tfoot .dt-column-footer,
    #forecast_detail_table.responsive-cards tfoot .dt-column-title,
    #forecast_detail_table.responsive-cards tfoot th.dt-type-numeric,
    #forecast_detail_table.responsive-cards tfoot th.text-right.dt-type-numeric {
        display: block !important;
        width: 100% !important;
        max-width: 100% !important;
        min-width: 0 !important;
        overflow: visible;
        text-overflow: unset;
        text-align: left !important;
        white-space: normal !important;
        word-break: break-word;
        overflow-wrap: anywhere;
    }
    #forecast_detail_table.responsive-cards tfoot th:last-child {
        font-weight: 700;
        font-variant-numeric: tabular-nums;
    }
    #forecast_detail_table.responsive-cards td {
        width: 100% !important;
        max-width: 100%;
        min-width: 0;
        overflow: visible;
        text-overflow: unset;
        white-space: normal !important;
        word-break: break-word;
        overflow-wrap: anywhere;
    }
    #forecast_detail_table.responsive-cards td.oppty-name-cell,
    #forecast_detail_table.responsive-cards td.oppty-name-cell a {
        display: block !important;
        width: 100%;
        max-width: 100%;
        min-width: 0;
        overflow: visible;
        text-overflow: unset;
        white-space: normal !important;
        word-break: break-word;
        overflow-wrap: anywhere;
    }
    #forecast_detail_table.responsive-cards td.oppty-amount-cell,
    #forecast_detail_table.responsive-cards th.oppty-amount-cell,
    #forecast_detail_table.responsive-cards td[data-label="Weighted"],
    #forecast_detail_table.responsive-cards td[data-label="Amount"],
    #forecast_detail_table.responsive-cards td[data-label="Full Amount"],
    #forecast_detail_table.responsive-cards td[data-label="Amount Here"] {
        overflow: visible;
        white-space: normal !important;
        overflow-wrap: anywhere;
        word-break: break-word;
    }

    /* Card-list tables: scroll with the page at ≤768px (deal similar
       opptys, contacts, search_contact, activity_list, needs_attention,
       forecast-detail). DT leftover .dt-container +
       .table-responsive:has(.dt-container) overflow:hidden +
       .table-responsive table { display:table } kept min-content ~498px.
       .table td > a { display:inline-flex } shrink-to-fits titles.
       Commissions wide matrices are not .responsive-cards — leave them. */
    .table-responsive:has(.responsive-cards),
    .table-responsive:has(.responsive-cards) .dt-container,
    .dt-container:has(.responsive-cards),
    #similar-projects,
    #similar-projects .table-responsive,
    #contacts .table-responsive {
        width: 100%;
        max-width: 100%;
        min-width: 0;
        overflow-x: visible !important;
        overflow-y: visible !important;
        touch-action: auto;
    }
    table.responsive-cards,
    table.responsive-cards tbody {
        display: block !important;
        width: 100% !important;
        max-width: 100%;
        min-width: 0;
        overflow-x: visible !important;
        overflow: visible !important;
    }
    table.responsive-cards tbody tr {
        width: 100% !important;
        max-width: 100%;
        min-width: 0;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }
    table.responsive-cards td {
        width: auto;
        max-width: 100%;
        min-width: 0;
        overflow: visible;
        text-overflow: unset;
        white-space: normal !important;
        word-break: break-word;
        overflow-wrap: anywhere;
    }
    table.responsive-cards td.oppty-name-cell,
    table.responsive-cards td.oppty-name-cell a,
    table.responsive-cards td > a:not(.btn) {
        display: block !important;
        width: 100%;
        max-width: 100%;
        min-width: 0;
        overflow: visible;
        text-overflow: unset;
        white-space: normal !important;
        word-break: break-word;
        overflow-wrap: anywhere;
    }
    #contacts { height: auto !important; }

    .clair-404 {
        margin: 1rem auto;
        max-width: 100%;
    }
    .clair-404-back {
        width: 100% !important;
    }
}

/* --------------------------------------------------------------------- *
 * Opportunity expand list — same component at every width.               *
 * Phone (max 767): 390px two-line grid. Desktop: one-line header grid.   *
 * Scoped to .clair-oppty-* only — do not restyle invoice tables,         *
 * checkboxes, or .dt-msf-option.                                         *
 * Explicit padding/margin: sales_styles.css has `* { padding: 0 }`.      *
 * No `label` rules here (mobile `label { display:block }` checkbox bug). *
 * --------------------------------------------------------------------- */

.clair-oppty-wrap {
    margin: 0;
    padding: 0;
}

.clair-oppty-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 0 0 10px;
    padding: 0;
}

.clair-oppty-search-wrap {
    display: flex;
    align-items: center;
    flex: 1 1 160px;
    min-width: 0;
    gap: 8px;
    margin: 0;
    padding: 8px 12px;
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius);
    background: var(--crs-white);
}

.clair-oppty-sort {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    gap: 6px;
    margin: 0;
    padding: 0;
}

.clair-oppty-sort-label {
    flex-shrink: 0;
    margin: 0;
    padding: 0;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--crs-gray-600);
}

.clair-oppty-sort-field {
    display: inline-block;
    width: auto;
    max-width: 10.5rem;
    min-width: 0;
    min-height: 36px;
    margin: 0;
    padding: 4px 8px;
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius);
    background: var(--crs-white);
    color: var(--crs-gray-900);
    font-size: 16px;
    line-height: 1.3;
    font-weight: 500;
}

/* My Customers — one row per account with a tag saying WHY it is the
   rep's, since the three sources (BC customer card, invoices, commission
   rules) genuinely differ and a customer can match more than one. */
.mycust-codes {
    margin-left: 8px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    color: var(--crs-gray-600, #6c757d);
}
.mycust-intro { margin: 10px 0 6px; font-size: 13px; }
.mycust-legend {
    list-style: none;
    margin: 0 0 12px;
    padding: 0;
    font-size: 12px;
    color: var(--crs-gray-600, #6c757d);
}
.mycust-legend li { margin-bottom: 4px; }
.mycust-note {
    margin: 0 0 12px;
    padding: 8px 10px;
    border: 1px solid var(--crs-gray-200, #e5e7eb);
    border-left: 3px solid var(--crs-gray-400, #b8bfc7);
    border-radius: 6px;
    background: var(--crs-gray-100, #f6f7f9);
    font-size: 12px;
}
.mycust-counts {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
    margin: 0 0 12px;
    font-size: 13px;
}
.mycust-search {
    display: flex;
    gap: 8px;
    margin: 0 0 12px;
}
.mycust-search input[type="search"] {
    flex: 1 1 260px;
    min-width: 0;
    min-height: 36px;
    padding: 4px 10px;
    border: 1px solid var(--crs-gray-300);
    border-radius: 999px;
}
.mycust-search button {
    min-height: 36px;
    padding: 4px 14px;
    border: 1px solid var(--crs-gray-300);
    border-radius: 999px;
    background: var(--crs-white);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}
.mycust-tag {
    display: inline-block;
    margin: 0 4px 2px 0;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    white-space: nowrap;
}
.mycust-tag--card { background: #e7f1ff; color: #14508c; }
.mycust-tag--inv  { background: #e6f6ec; color: #1b6b3a; }
.mycust-tag--rule { background: #fdf0e3; color: #8a4b09; }
/* Neutral gray, not a new hue: this names WHICH other reps share the BC
   code (a category), not a status/severity like the three above -- same
   reasoning already established for .kpi-basis-tag. */
.mycust-tag--split {
    background: var(--crs-gray-100);
    color: var(--crs-gray-700);
    border: 1px solid var(--crs-gray-300);
}

/* Filter chips. A chip IS the tag it filters on -- same three words, same
   three colours as .mycust-tag above -- so the control needs no legend of
   its own. Off state is a plain outline; the colour only arrives when the
   chip is doing something, which keeps a row of three from reading as three
   competing states. */
.mycust-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 0 0 12px;
}
.mycust-filters-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--crs-gray-600);
}
.mycust-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: var(--crs-control-h);
    padding: 4px 12px;
    border: 1px solid var(--crs-gray-300);
    border-radius: 999px;
    background: var(--crs-white);
    color: var(--crs-gray-700);
    font-size: 12px;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
}
.mycust-chip:hover { background: var(--crs-gray-100); }
.mycust-chip-n {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    opacity: 0.65;
}
.mycust-chip.is-on.mycust-chip--card { background: #e7f1ff; border-color: #9dc2ee; color: #14508c; }
.mycust-chip.is-on.mycust-chip--inv  { background: #e6f6ec; border-color: #9ed3b3; color: #1b6b3a; }
.mycust-chip.is-on.mycust-chip--rule { background: #fdf0e3; border-color: #e6bd85; color: #8a4b09; }
.mycust-chip.is-on.mycust-chip--split { background: #f3e8fb; border-color: #c9a3e3; color: #5b2a82; }
.mycust-chip.is-on.mycust-chip--solo { background: #e8f4f4; border-color: #9fcccc; color: #1d5c5c; }
.mycust-export { margin-left: auto; font-size: 13px; text-decoration: none; white-space: nowrap; }
.mycust-export:hover { text-decoration: underline; }
.mycust-chip.is-on .mycust-chip-n { opacity: 0.85; }
.mycust-chip:focus-visible,
.mycust-chip-clear:focus-visible {
    outline: 2px solid var(--crs-red);
    outline-offset: 2px;
}
.mycust-chip-clear {
    min-height: var(--crs-control-h);
    padding: 4px 10px;
    border: 0;
    background: none;
    color: var(--crs-gray-600);
    font-size: 12px;
    font-weight: 600;
    text-decoration: underline;
    cursor: pointer;
}
.mycust-chip-clear:hover { color: var(--crs-red); }
.mycust-status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 12px;
    margin: 0 0 8px;
}
.mycust-status:empty { margin: 0; }
.mycust-shown {
    margin: 0;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    color: var(--crs-gray-600);
}
.mycust-reset {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: var(--crs-control-h);
    padding: 4px 12px;
    border: 1px solid var(--crs-gray-300);
    border-radius: 999px;
    background: var(--crs-white);
    color: var(--crs-gray-700);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}
.mycust-reset:hover { background: var(--crs-gray-100); color: var(--crs-charcoal); }
.mycust-reset:focus-visible { outline: 2px solid var(--crs-red); outline-offset: 2px; }
.mycust-reset i { font-size: 10px; opacity: 0.7; }

/* A sorted table is FLAT: the parent rows are hidden, so the indent that
   made a child read as "under" something no longer has anything to sit
   under -- left in, it reads as a stray margin down the first column. */
.mycust-table.is-flat .mycust-child > td:first-child { padding-left: 12px; }

/* Sortable headers. The whole cell is the target, but the label is a real
   <button> so it is reachable and announceable by keyboard; the arrow is
   decorative and driven off aria-sort so there is one source of truth. */
.mycust-table th.mycust-sortable { padding: 0 !important; }
.mycust-sort-btn {
    display: flex;
    align-items: center;
    gap: 5px;
    width: 100%;
    min-height: var(--crs-control-h);
    padding: 8px 10px;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: inherit;
    cursor: pointer;
}
.mycust-table th.mycust-num .mycust-sort-btn { justify-content: flex-end; }
.mycust-sort-btn:hover { background: rgba(255, 255, 255, 0.12); }
.mycust-sort-btn:focus-visible {
    outline: 2px solid var(--crs-white);
    outline-offset: -3px;
}
.mycust-sort-i::before {
    content: "↕";              /* up-down: sortable, not sorted */
    font-size: 10px;
    opacity: 0.45;
}
th[aria-sort="ascending"] .mycust-sort-i::before  { content: "↑"; opacity: 1; }
th[aria-sort="descending"] .mycust-sort-i::before { content: "↓"; opacity: 1; }

.mycust-nomatch td {
    padding: 18px 12px;
    color: var(--crs-gray-600);
    font-size: 13px;
}
/* Opportunity detail for someone who cannot save it (not the rep, and not
   a listed collaborator). The fields stay visible -- they are the record --
   but stop looking like an invitation, and the note below says who can
   change it. */
.edit-oppty.is-readonly input,
.edit-oppty.is-readonly select,
.edit-oppty.is-readonly textarea {
    pointer-events: none;
    background: var(--crs-gray-100);
    color: var(--crs-gray-700);
}
.oppty-readonly-note {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 12px 0 0;
    padding: 10px 12px;
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius, 6px);
    background: var(--crs-gray-100);
    font-size: 13px;
    color: var(--crs-gray-700);
}
.oppty-readonly-note i { color: var(--crs-gray-500); }

.mycust-inline-clear {
    border: 0;
    background: none;
    padding: 0;
    color: var(--crs-red);
    font: inherit;
    font-weight: 600;
    text-decoration: underline;
    cursor: pointer;
}
.mycust-table .mycust-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.mycust-foot {
    margin: 6px 0 0;
    font-size: 12px;
    color: var(--crs-gray-600, #6c757d);
}
.mycust-switch {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 10px 0 0;
    font-size: 13px;
}
.mycust-switch select {
    min-height: 34px;
    padding: 2px 8px;
    border: 1px solid var(--crs-gray-300);
    border-radius: 6px;
    max-width: 280px;
}
/* The figures here deliberately exclude anything not tied to a named
   customer, so the caveat is a visible block rather than fine print — a
   rep comparing this to their dashboard should find the reason first. */
.mycust-warn {
    margin: 14px 0 4px;
    font-size: 12px;
    color: #8a4b09;
}
.mycust-caveats {
    margin: 0 0 4px;
    padding-left: 22px;
    font-size: 12px;
    color: var(--crs-gray-600, #6c757d);
}
.mycust-caveats li { margin-bottom: 3px; }
.mycust-note-small {
    margin: 6px 0 0;
    font-size: 12px;
    color: var(--crs-gray-600, #6c757d);
}
/* Corporate families and the per-customer site drawer. Uses the shared
   tokens throughout so this reads as the same app as everything else. */
.mycust-fam td {
    background: var(--crs-gray-100);
    border-top: 2px solid var(--crs-gray-300) !important;
}
.mycust-fam-name { font-weight: 600; color: var(--crs-gray-900); }
.mycust-fam-meta {
    margin-left: 8px;
    font-size: 11px;
    color: var(--crs-gray-600);
    font-variant-numeric: tabular-nums;
}
/* Children are indented so a family reads as one block, not six loose rows. */
.mycust-child > td:first-child { padding-left: 26px; }
.mycust-expand {
    border: 0;
    background: none;
    padding: 0 6px 0 0;
    color: var(--crs-gray-600);
    cursor: pointer;
    font-size: 11px;
}
.mycust-expand:hover { color: var(--crs-red); }
.mycust-expand i { transition: transform 0.12s ease; }
.mycust-expand.is-open i { transform: rotate(90deg); }
.mycust-expand:focus-visible {
    outline: 2px solid var(--crs-red);
    outline-offset: 2px;
    border-radius: 3px;
}
.mycust-sites-row > td {
    background: var(--crs-gray-100);
    padding: 10px 14px 12px 26px !important;
}
.mycust-sites { font-size: 12px; color: var(--crs-gray-700); }
.mycust-site-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--crs-white);
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius);
}
/* This table carries no Bootstrap `table` class, but it is NESTED inside
   one -- and `.table thead th` matches any th DESCENDING from a .table,
   so the app-wide charcoal !important reached it anyway and drew a second
   dark header inside the drawer. Dropping the class was not enough here;
   this out-specifies it the same way .cv3-rg-table does. */
.mycust-site-table thead th,
.mycust-table .mycust-site-table thead th {
    background: var(--crs-white) !important;
    color: var(--crs-gray-600) !important;
    border-bottom: 1px solid var(--crs-gray-300) !important;
}
.mycust-site-table th {
    text-align: left;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--crs-gray-600);
    padding: 7px 10px;
    border-bottom: 1px solid var(--crs-gray-300);
}
.mycust-site-table td {
    padding: 7px 10px;
    border-bottom: 1px solid var(--crs-gray-200);
    vertical-align: top;
}
.mycust-site-table tr:last-child td { border-bottom: 0; }
/* Ship-to code under its name, monospaced like every other BC identifier
   in the app. Hidden entirely when BC has no code for the site. */
/* Reference notes on the commission-ops screens. Every one of those pages
   opened with a paragraph explaining itself before the queue the operator
   came for; the words are all still there, one click away. Styled as a quiet
   line, not a banner, so it reads as a footnote you can open rather than an
   alert you must dismiss. */
/* Says what population a KPI tile counts, so a tile and the page callout
   showing different figures reads as two answers rather than a mistake. */
.invoice-kpi-scope-note {
    margin-top: 4px;
    font-size: 0.72rem;
    line-height: 1.35;
    color: var(--crs-gray-600);
}
.ops-intro {
    margin: 0 0 14px;
    font-size: 13px;
}
.ops-intro > summary {
    cursor: pointer;
    color: var(--crs-gray-700);
    padding: 6px 0;
    min-height: var(--crs-control-h);
    display: flex;
    align-items: center;
    gap: 6px;
    list-style: none;
}
.ops-intro > summary::-webkit-details-marker { display: none; }
.ops-intro > summary::before {
    content: "A";
    display: inline-block;
    transition: transform 0.12s ease;
    color: var(--crs-gray-500);
    font-size: 15px;
}
.ops-intro[open] > summary::before { transform: rotate(90deg); }
.ops-intro > summary:hover { color: var(--crs-charcoal); }
.ops-intro > summary:focus-visible {
    outline: 2px solid var(--crs-red);
    outline-offset: 2px;
    border-radius: 3px;
}
/* The prose inside keeps its own alert styling; just drop the extra gap. */
.ops-intro .alert { margin-bottom: 0; }
.mycust-site-code {
    display: block;
    font-family: var(--crs-font-mono);
    font-size: 10px;
    color: var(--crs-gray-600);
    margin-top: 1px;
}
.mycust-site-addr {
    display: block;
    font-size: 11px;
    color: var(--crs-gray-600);
}
.mycust-site-note {
    margin: 6px 0 0;
    font-size: 11px;
    color: var(--crs-gray-600);
}
.mycust-site-table .mycust-num {
    text-align: right;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.mycust-table .mycust-date {
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    color: var(--crs-gray-700, #495057);
}
/* Named rules sit under the "Commission rule" tag rather than in a tooltip:
   this is the one answer a rep actually chases down ("why am I paid here?"),
   so it has to survive a screenshot and a printout. */
.mycust-rules {
    list-style: none;
    margin: 4px 0 0;
    padding: 0;
    font-size: 11px;
    line-height: 1.45;
    color: var(--crs-gray-600, #6c757d);
}
.mycust-rules li { margin: 0; }
.mycust-rule-name { font-weight: 600; color: var(--crs-gray-700, #495057); }
.mycust-rule-bit::before { content: " · "; }

/* The BC customer count in "BC vs. the app" opens the list behind it. */
.mycust-code-custs summary { cursor: pointer; display: inline-block; color: inherit; text-decoration: underline dotted; }
.mycust-code-custs ul { list-style: none; margin: 6px 0 0; padding: 0; font-size: 12px; line-height: 1.5; text-align: left; display: inline-block; }
.mycust-code-custs li { margin-bottom: 4px; }
.mycust-viewsites { margin-left: 8px; padding: 0 8px; font-size: 11px; line-height: 18px; color: inherit; background: transparent; border: 1px solid currentColor; border-radius: 10px; opacity: .8; cursor: pointer; }
.mycust-viewsites:hover, .mycust-viewsites[aria-expanded="true"] { opacity: 1; }
.mycust-code-sites { display: block; margin: 6px 0 8px; }
.mycust-code-sites[hidden] { display: none; }

/* My BC Customers on a phone. The rep picker is a label beside a select;
   at 375px the label had 55px to itself and broke "Show customers for"
   over three lines beside a select that could not use the width either.
   Stacked, the label is one line and the select is a full-width tap
   target. The table below keeps its own sideways scroll -- it is 1,205px
   wide and every column on it is a figure someone reads. */
@media (max-width: 575.98px) {
    /* The search field and its button sit right beside .mycust-switch and
       were left at their 36px desktop height -- fine with a mouse, under
       the app's own 44px phone tap target (--crs-control-h is 44px on
       mobile, and .rb-nav is held to it by test). The picker next to them
       already had a phone rule; these were simply missed. */
    .mycust-search input[type="search"],
    .mycust-search button {
        min-height: 44px;
    }
    .mycust-switch {
        flex-direction: column;
        align-items: stretch;
        gap: 4px;
    }
    .mycust-switch select {
        max-width: none;
        min-height: var(--crs-control-h);
    }
}

/* Export links sit in the same toolbar as search and sort, and borrow the
   sort control's pill so the row reads as one set of table actions. */
.clair-oppty-export {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    margin-left: auto;
}
.clair-oppty-export-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    min-height: 36px;
    border: 1px solid var(--crs-gray-300);
    border-radius: 999px;
    background: var(--crs-white);
    color: var(--crs-gray-900);
    font-size: 12px;
    font-weight: 600;
    line-height: 1.3;
    text-decoration: none;
    white-space: nowrap;
}
.clair-oppty-export-link:hover {
    border-color: var(--crs-red, #c8102e);
    color: var(--crs-red, #c8102e);
    text-decoration: none;
}
/* Notes are free text and can run long; keep the expand readable rather
   than letting one entry stretch the panel. */
.clair-oppty-notes {
    white-space: pre-line;
    max-height: 9em;
    overflow-y: auto;
}

.clair-oppty-sort-dir {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
    margin: 0;
    padding: 4px 10px;
    min-height: 36px;
    border: 1px solid var(--crs-gray-300);
    border-radius: 999px;
    background: var(--crs-white);
    color: var(--crs-gray-900);
    font-size: 12px;
    font-weight: 600;
    line-height: 1.3;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.clair-oppty-sort-dir:hover,
.clair-oppty-sort-dir:focus {
    border-color: var(--crs-red);
    color: var(--crs-gray-900);
    outline: none;
}

.clair-oppty-sort-arrow {
    color: var(--crs-red);
    font-size: 13px;
    line-height: 1;
}

.clair-oppty-sort-hint {
    color: var(--crs-gray-700);
    white-space: nowrap;
}

/* Beat the global mobile `select { width:100% }` / min-height rule so the
   toolbar keeps its touch targets and wraps beside search on phones. */
@media (max-width: 768px) {
    .clair-oppty-sort-field {
        width: auto !important;
        max-width: 10.5rem !important;
        min-height: var(--crs-control-h) !important;
        padding: 4px 8px !important;
        font-size: 16px !important;
    }
    .clair-oppty-sort-dir {
        width: auto !important;
        min-height: var(--crs-control-h) !important;
        padding: 4px 10px !important;
    }
}

.clair-oppty-search-wrap .fa-search {
    color: var(--crs-gray-500);
    font-size: 13px;
    flex-shrink: 0;
}

.clair-oppty-search-go {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    line-height: 1;
    cursor: pointer;
    min-width: var(--crs-control-h);
    min-height: var(--crs-control-h);
}

.clair-oppty-search-go:focus {
    outline: 2px solid var(--crs-red);
    outline-offset: 2px;
}

.clair-oppty-page-note {
    margin: 8px 0 0;
    padding: 0;
    color: var(--crs-gray-600);
    font-size: 13px;
    line-height: 1.4;
}

.clair-oppty-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin: 12px 0 0;
    padding: 0;
}

.clair-oppty-pager-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    min-width: 88px;
    padding: 8px 14px;
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius);
    background: var(--crs-white);
    color: var(--crs-gray-900);
    font-size: 14px;
    text-decoration: none;
}

.clair-oppty-pager-link:hover {
    border-color: var(--crs-red);
    color: var(--crs-red);
    text-decoration: none;
}

.clair-oppty-pager-link.is-disabled {
    color: var(--crs-gray-500);
    pointer-events: none;
    opacity: 0.65;
}

.clair-oppty-pager-status {
    font-size: 13px;
    color: var(--crs-gray-600);
    padding: 0 6px;
}

.clair-oppty-per-page {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin: 8px 0 0;
    padding: 0;
    font-size: 13px;
    color: var(--crs-gray-600);
}

.clair-oppty-per-page-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 36px;
    min-width: 36px;
    padding: 4px 10px;
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius);
    background: var(--crs-white);
    color: var(--crs-gray-900);
    text-decoration: none;
}

.clair-oppty-per-page-link:hover {
    border-color: var(--crs-red);
    color: var(--crs-red);
    text-decoration: none;
}

.clair-oppty-per-page-link.is-current {
    border-color: var(--crs-red);
    color: var(--crs-red);
    font-weight: 600;
}

.clair-oppty-search {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
    outline: none;
    background: transparent;
    font-size: 16px;
    line-height: 1.3;
    color: var(--crs-gray-900);
    width: 100%;
}

.clair-oppty-search:focus-visible {
    outline: 2px solid var(--crs-red);
    outline-offset: 2px;
}

.clair-oppty-list {
    display: block;
    list-style: none;
    margin: 0;
    padding: 0;
    background: var(--crs-white);
    border: 1px solid var(--crs-gray-300);
    border-radius: var(--crs-radius);
    overflow: hidden;
}

.clair-oppty-item {
    display: block;
    margin: 0;
    padding: 0;
    border-bottom: 1px solid var(--crs-gray-200);
    background: var(--crs-white);
}

.clair-oppty-item:last-child { border-bottom: none; }

.clair-oppty-item[hidden] { display: none !important; }

.clair-oppty-empty {
    margin: 0;
    padding: 12px;
    color: var(--crs-gray-600);
    font-size: 13px;
}

/* Phone shows the expand list; the desktop table is switched on at 768px. */
.clair-oppty-table-wrap { display: none; }

.clair-oppty-summary {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr) auto;
    grid-template-areas:
        "expand primary status"
        "expand meta    meta";
    gap: 2px 8px;
    align-items: center;
    margin: 0;
    padding: 10px 12px;
    min-height: 52px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.clair-oppty-chevron {
    grid-area: expand;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    margin: 0;
    padding: 0;
}

.clair-oppty-chevron::before {
    content: '';
    display: block;
    width: 7px;
    height: 7px;
    border-right: 2px solid var(--crs-gray-500);
    border-bottom: 2px solid var(--crs-gray-500);
    transform: rotate(-45deg);
    transition: transform var(--crs-trans);
}

.clair-oppty-item.is-open .clair-oppty-chevron::before {
    transform: rotate(45deg);
}

.clair-oppty-name {
    grid-area: primary;
    min-width: 0;
    margin: 0;
    padding: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    font-size: 12.5px;
    line-height: 1.3;
    color: var(--crs-gray-900) !important;
}

.clair-oppty-name:hover { color: var(--crs-red) !important; }

.clair-oppty-chip {
    grid-area: status;
    display: inline-flex;
    align-items: center;
    justify-self: end;
    flex-shrink: 0;
    margin: 0;
    padding: 2px 8px;
    border: 1px solid var(--crs-gray-300);
    border-radius: 999px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: none;
    white-space: nowrap;
    line-height: 1.3;
    color: var(--crs-gray-900);
    background: var(--crs-gray-200);
}

.clair-oppty-chip--won {
    color: var(--crs-success);
    background: var(--crs-success-bg);
    border-color: #a7f3d0;
}

.clair-oppty-chip--lost {
    color: var(--crs-danger);
    background: var(--crs-danger-bg);
    border-color: #fecaca;
}

.clair-oppty-chip--closed {
    color: var(--crs-gray-600);
    background: var(--crs-gray-100);
    border-color: var(--crs-gray-300);
}

.clair-oppty-chip--open {
    color: var(--crs-gray-900);
    background: var(--crs-gray-200);
    border-color: var(--crs-gray-300);
}

.clair-oppty-chip--commit {
    color: var(--crs-info);
    background: #e8f1fd;
    border-color: #bfdbfe;
}

.clair-oppty-customer,
.clair-oppty-amount,
.clair-oppty-date {
    display: none;
}

.clair-oppty-meta {
    grid-area: meta;
    min-width: 0;
    margin: 0;
    padding: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 11.5px;
    line-height: 1.35;
    color: var(--crs-gray-600);
}

.clair-oppty-list .sep {
    display: inline;
    color: var(--crs-gray-500);
}

.clair-oppty-expand {
    margin: 0;
    padding: 8px 14px 14px 40px;
    background: var(--crs-white);
    border-top: 1px dashed var(--crs-gray-300);
}

.clair-oppty-expand[hidden] { display: none !important; }

.clair-oppty-detail {
    display: grid;
    /* 76px was shorter than COLLABORATOR (uppercase + tracking) at 390px. */
    grid-template-columns: max-content 1fr;
    gap: 6px 10px;
    margin: 0 0 10px;
    padding: 0;
}

.clair-oppty-detail dt {
    margin: 0;
    padding: 0;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--crs-gray-600);
    line-height: 1.4;
    white-space: nowrap;
}

.clair-oppty-detail dd {
    margin: 0;
    padding: 0;
    font-size: 13px;
    color: var(--crs-gray-900);
    line-height: 1.4;
    overflow-wrap: anywhere;
    word-break: break-word;
}

.clair-oppty-open-link {
    display: inline-block;
    margin: 0;
    padding: 6px 14px;
    min-height: 32px;
    box-sizing: border-box;
    text-align: center;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--crs-red) !important;
    background: var(--crs-white);
    border: 1px solid var(--crs-red);
    border-radius: 2px;
}

.clair-oppty-open-link:hover {
    background: var(--crs-red);
    color: var(--crs-white) !important;
}

/* Hidden rows must stay hidden even though a <tr> defaults to table-row. */
.clair-oppty-row[hidden] { display: none !important; }

@media (min-width: 768px) {
    .clair-oppty-sort-field { font-size: 13px; }

    /* Desktop is a real table. The expand list is the phone view only. */
    .clair-oppty-search:focus-visible {
    outline: 2px solid var(--crs-red);
    outline-offset: 2px;
}

.clair-oppty-list { display: none; }

    .clair-oppty-table-wrap {
        display: block;
        overflow-x: auto;
    }

    .clair-oppty-table {
        width: 100%;
        margin: 0;
        font-size: 13px;
    }

    .clair-oppty-table thead th {
        padding: 8px 10px;
        border-bottom: 2px solid var(--crs-gray-300);
        background: var(--crs-gray-100);
        font-size: 11px;
        font-weight: 600;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        color: var(--crs-gray-600);
        white-space: nowrap;
        vertical-align: bottom;
    }

    .clair-oppty-table tbody td {
        padding: 8px 10px;
        vertical-align: middle;
        color: var(--crs-gray-700);
    }

    /* Long opportunity names must not push Amount and Status off-screen. */
    .clair-oppty-table .col-name {
        max-width: 22rem;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .clair-oppty-table .col-name a { color: var(--crs-gray-900); }
    .clair-oppty-table .col-name a:hover { color: var(--crs-red) !important; }

    .clair-oppty-table .col-amount {
        text-align: right;
        font-weight: 600;
        color: var(--crs-gray-900);
        font-variant-numeric: tabular-nums;
        white-space: nowrap;
    }
    .clair-oppty-table .col-date,
    .clair-oppty-table .col-win {
        white-space: nowrap;
    }
    .clair-oppty-table .col-win { text-align: right; }
    .clair-oppty-table .col-status { white-space: nowrap; }

    .clair-oppty-table .clair-oppty-chip { display: inline-block; }

    .clair-oppty-row-empty td {
        padding: 12px;
        color: var(--crs-gray-600);
        text-align: left;
    }
}


/* =====================================================================
   Editorial Light (2026-09-14) -- global layer
   ---------------------------------------------------------------------
   Matt's approved direction from the paycheck mockup: warm-neutral
   ground, hairline borders, ONE red, and every dollar figure set in
   JetBrains Mono with tabular numerals so money reads as money. This
   block sits at the end of the file so it wins ties by source order;
   it overrides tokens and the shared KPI/label classes only -- no
   selector here touches layout, IDs, DataTables, or JS hooks.
   ===================================================================== */
:root {
    --crs-gray-100: #FAFAF9;
    --crs-gray-200: #EEEBE9;
    --crs-gray-300: #E6E3E1;
    --crs-gray-400: #CFCAC6;
    --crs-radius:    8px;
    --crs-radius-lg: 10px;
    --crs-shadow-sm: 0 1px 2px rgba(20, 20, 20, 0.05);
    --crs-shadow-md: 0 1px 2px rgba(20, 20, 20, 0.05), 0 8px 24px -12px rgba(20, 20, 20, 0.14);
    --crs-ed-label-size: 11px;
    --crs-ed-label-track: 0.12em;

    /* ---- The money type scale -------------------------------------
       Before this, "the big number on a card" was six different sizes
       depending on which page you were on -- 68px (commission hero),
       38px (Book), 34px (quota), 26.4px (Sales KPI), 26.4px and 21.6px
       (invoice detail) -- and Matt flagged two peer cards sitting side
       by side at 68px and 34px as simply looking wrong. Four steps now,
       roughly a 1.4 ratio apart, and every figure in the app picks one:

         hero    - the ONE figure a page exists to show
         lead    - the leading figure of a card
         support - secondary figures inside a card
         inline  - figures in strips, tiles and trails

       Each is a clamp so it still fits a phone. The `lead` and
       `support` ceilings are measured against the narrowest container
       that uses them: the Sales KPI tile is only 173px wide even at
       1440px, where 25.5px was the largest that fits "$114,339,160" --
       it was rendering at 26.4px and already overflowing by 6px. */
    --crs-fig-hero:    clamp(38px, 3.2vw, 46px);
    --crs-fig-lead:    clamp(26px, 2.4vw, 34px);
    --crs-fig-support: clamp(20px, 1.7vw, 24px);
    --crs-fig-inline:  15px;
}
body { background-color: var(--crs-gray-100); }

/* Money is set in mono, tight, tabular -- EVERY figure, not just the ones
   that happened to be listed first. `.cv3-num` and `.rb-num` are the shared
   base classes, so adding them here catches the stragglers that were still
   rendering in Inter (the A/R aging tiles, the Book nav trail) and any
   figure added later. */
.kpi-value,
.kpi-card-body > h4,
.invoice-kpi-card .kpi-card-body > h4,
.pq-money,
.cv3-num,
.rb-num,
.rb-figure,
.rb-quota-pct,
.clair-money,
.invoice-kpi-value,
.earned-this-month-value,
.cv3-num-plan,
.cv3-num-paid,
.cv3-num-range,
.cv3-num-pct {
    font-family: var(--crs-font-mono);
    font-weight: 700;
    letter-spacing: -0.035em;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
    /* Safety net, not the sizing fix below: a dollar figure is one
       unbroken token, so if one ever runs long enough to miss the
       money-scale's own headroom, normal wrap has nowhere to break and
       the card's overflow:hidden would clip it instead of shrinking to
       it. anywhere lets an outlier wrap onto a second line -- no card in
       this list uses a fixed/max-height, so nothing is ever cut off. */
    overflow-wrap: anywhere;
}
/* This was a flat `1.85rem`, and because this whole Editorial Light block
   sits at the END of the file it outranked the phone overrides earlier in
   it (the 1.35rem / 1.15rem rules) by source order alone. On a 390px phone
   the KPI cards are two-up with a ~150px value box, so "$114,339,160" ran
   to 201px and the card's own overflow chopped it to "$114,339,1" -- a
   figure that reads as a DIFFERENT, smaller number. Reported from a live
   phone screenshot 2026-09-15.

   A viewport-scaled size fixes it at every width without depending on
   which rule comes last. It now takes the shared `support` step of the
   money scale rather than its own one-off clamp: these tiles sit four
   across in a ~700px column, so their value box is only 173px even on a
   1440px screen -- the previous 26.4px ceiling was itself overflowing
   "$114,339,160" by 6px there. 24px measures 163px in that box. Nothing
   is ever truncated or abbreviated; the type gives way instead. */
/* Everything else that leads or supports a card joins the same scale, so
   "the big number" is one size per role rather than one per page.
   `.invoice-kpi-value` was 1.35rem and `.earned-this-month-value` 1.65rem
   on the same screen; both are support-tier figures inside a card. */
.invoice-kpi-value,
.earned-this-month-value,
.rb-quota-pct { font-size: var(--crs-fig-support); }
.rb-figure { font-size: var(--crs-fig-lead); }
.rb-nav-trail .rb-num,
.clair-money { font-size: var(--crs-fig-inline); }
/* The "additional sales outside quota months" figure was the last one
   still in the UI face -- it has no class of its own, so it is reached
   through the link that wraps it. */
.quota-tracker-no-quota strong {
    font-family: var(--crs-font-mono);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
}

.kpi-value,
.kpi-card-body > h4 {
    font-size: var(--crs-fig-support);
    line-height: 1.05;
}

/* Labels: small caps, tracked, quiet. The number is the loud part. */
.kpi-label,
.kpi-card-body > .small.text-muted,
.kpi-card-body > .text-muted.small,
.cv3-label,
.rb-label {
    font-size: var(--crs-ed-label-size) !important;
    font-weight: 600 !important;
    letter-spacing: var(--crs-ed-label-track) !important;
    text-transform: uppercase !important;
    color: var(--crs-gray-700) !important;
}

/* Cards: hairline + soft lift; the one accent bar marks the tile that
   leads a page (accent/selected), not every tile. */
.card,
.kpi-card {
    border-color: var(--crs-gray-300);
    border-radius: var(--crs-radius-lg);
    box-shadow: var(--crs-shadow-sm);
}
.kpi-card--accent {
    position: relative;
    overflow: hidden;
}
.kpi-card--accent::before {
    content: "";
    position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
    background: var(--crs-red);
}
/* Old KPI underline accent gives way to the bar above. */
.kpi-card-body > h4 { border-bottom: 0 !important; padding-bottom: 0 !important; }

/* The invoice drill-down's cells are `white-space: nowrap` (right for the
   money figure) with `overflow: visible`, inside a `table-layout: fixed`
   table. The secondary hint lines under a figure inherit that nowrap, so
   a long one -- "Non-cash guard fix (Aug 2026)", "Wide Refund/FCM
   phantom-cash..." -- ran up to 348px past its 160px cell and painted
   straight over the next column's numbers. Measured at 390px on
   /commissions/invoices/<rep>/2026/8/: td width 160px, scrollWidth 496px.
   These are explanatory prose, not figures, so they wrap inside their own
   cell instead. The amount above them keeps its single line, and no hint
   text is shortened. */
.split-hint,
.commission-earned-hint {
    white-space: normal;
    overflow-wrap: break-word;
}

/* DataTables' own record counter is a nowrap flex row. Once the counts
   are real ("Showing 1 to 50 of 202 entries") it needs ~380px, and on a
   390px phone its cell is 247px -- so it ran past the card edge. Let it
   take a second line. Counts are unchanged; only the wrapping is.

   DataTables' own CDN sheet sets it as `div.dt-container div.dt-info`, so
   both `.dt-info` and `.dt-container .dt-info` lose on specificity. That
   sheet is cross-origin, so its rules do NOT appear when you enumerate
   document.styleSheets from the page -- fetch the CDN file and grep it
   instead, which is how this selector was found. Match it element-for-
   element; clair_theme.css is linked after it in base.html, so source
   order settles the tie without needing !important. */
div.dt-container div.dt-info {
    white-space: normal;
    flex-wrap: wrap;
}

/* Tables: header row as tracked label, hairline rows, tabular money. */
table.table thead th,
.admin-wide-table thead th {
    font-size: var(--crs-ed-label-size);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
table.table td.text-right,
.admin-wide-table td.text-right,
table.table tfoot td,
.admin-wide-table tfoot td {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}
table.table tfoot td strong,
.admin-wide-table tfoot td strong { font-family: var(--crs-font-mono); letter-spacing: -0.02em; }

/* Page titles: a touch tighter, balanced wrap. */
.commission-page-header h2,
#content h1, #content h2 { letter-spacing: -0.02em; text-wrap: balance; }

/* Dollar amounts retain their existing formatting. */
.clair-money {
    font-family: var(--crs-font-mono);
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ *
 * Phone: text must not paint outside a fixed-layout scroll cell.
 *
 * Two rules that are each fine alone collide at <=768px:
 *   1. base.html pins .dt-scroll-head/body/foot tables to
 *      `table-layout: fixed` so DataTables' one shared <colgroup> keeps
 *      head, body and foot aligned (0px drift). A body column therefore
 *      CANNOT grow to fit its own content.
 *   2. the phone block above sets `.table td, .table th
 *      { white-space: nowrap }` so numbers stay on one line and the
 *      table scrolls sideways instead of squashing.
 *
 * Together: a cell that cannot grow, holding text that cannot wrap. The
 * text simply paints over the next column. Measured on
 * /commissions/invoice-lines/21/SI372884/ at 390px --
 * "SERVICE DATES: 3/23-3/29/2026" exceeded its cell by 42px,
 * "OT/AFTER 40HRS & SAT/DT SUN" by 41px, two more by 6-7px.
 *
 * Inside a fixed-layout scroll body, nowrap can only ever produce
 * overflow, so wrapping is released there -- and ONLY there, so ordinary
 * non-DataTables tables keep their horizontal scroll behaviour.
 *
 * `overflow-wrap: normal` is deliberate, not an oversight. It breaks at
 * spaces and hyphens, which is what a description is made of, and leaves
 * "$1,234.56" alone because it offers no break opportunity -- so this
 * cannot reintroduce money broken mid-digit. A single very long unbroken
 * token still overflows, exactly as it does today.
 * ------------------------------------------------------------------ */
@media (max-width: 768px) {
    .dt-scroll-body td,
    .dt-scroll-body th {
        white-space: normal;
        overflow-wrap: normal;
        word-break: normal;
    }
    /* Belt and braces for the figures: these classes mark money and
       counts, and they stay on one line whatever the column width. */
    .dt-scroll-body td.text-right,
    .dt-scroll-body th.text-right,
    .dt-scroll-body .clair-money,
    .dt-scroll-body .cv3-num {
        white-space: nowrap;
    }
}

/* ------------------------------------------------------------------ *
 * KPI drill-downs.
 *
 * Every dashboard tile is now a link to the rows behind it. The anchor
 * wraps the card's whole contents so the hit target is the card, but it
 * stays a plain <a href> -- focusable, right-clickable, and it works with
 * JavaScript off.
 * ------------------------------------------------------------------ */
.kpi-card .kpi-drill {
    display: block;
    color: inherit;
    text-decoration: none;
}
.kpi-card .kpi-drill:hover,
.kpi-card .kpi-drill:focus-visible {
    text-decoration: none;
    color: inherit;
}
/* Affordance without shifting layout: a card that can be opened lifts
   its border and underlines only the figure. */
.kpi-card:has(.kpi-drill):hover,
.kpi-card:has(.kpi-drill):focus-within {
    border-color: var(--crs-red, #C8102E);
}
.kpi-card .kpi-drill:hover .kpi-value,
.kpi-card .kpi-drill:focus-visible .kpi-value {
    text-decoration: underline;
    text-underline-offset: 3px;
}
.kpi-card .kpi-drill:focus-visible {
    outline: 3px solid #fff;
    outline-offset: 2px;
}

/* The keyboard route into every chart. A <canvas> cannot take focus, so
   each chart carries the same drill-downs as real links underneath it.
   Small and quiet, but never hidden -- a screen-reader-only list would
   leave sighted keyboard users with nothing to aim at. */
.chart-data-links {
    display: flex;
    flex-wrap: wrap;
    min-width: 0;   /* never widen a card past its grid track */
    gap: 4px 10px;
    margin: 6px 0 0;
    padding: 0 4px;
    list-style: none;
    font-size: 11px;
    line-height: 1.4;
}
.chart-data-links a {
    color: var(--crs-gray-600, #6b7280);
    text-decoration: underline dotted;
    text-underline-offset: 2px;
}
.chart-data-links a:hover,
.chart-data-links a:focus-visible { color: inherit; text-decoration: underline; }

/* ---- the drill-down page itself ---- */
.drill-breadcrumb { font-size: 12px; margin-bottom: 4px; }
.drill-breadcrumb span { margin: 0 6px; opacity: .6; }
.drill-title { margin: 0 0 4px; }
.drill-scope { margin: 0 0 6px; font-size: 13px; }
.drill-basis { margin: 0 0 14px; max-width: 70ch; font-size: 13px; opacity: .85; }
.drill-note { margin: 8px 0 16px; max-width: 70ch; font-size: 12px; opacity: .75; }
.drill-summary-caption {
    margin: 0 0 6px;
    font-size: 11px;
    letter-spacing: .04em;
    text-transform: uppercase;
    opacity: .7;
}
.drill-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 28px;
    margin-bottom: 8px;
}
.drill-stat { display: flex; flex-direction: column; }
.drill-stat-label {
    font-size: 10px; font-weight: 700; letter-spacing: .08em;
    text-transform: uppercase; opacity: .7;
}
.drill-stat-value { font-size: 22px; font-weight: 700; }
/* The honest-limits panel on the three company-wide ranked charts. */
.drill-limit {
    margin: 12px 0 18px; padding: 10px 14px;
    border-left: 3px solid var(--crs-red, #C8102E);
    font-size: 13px;
}
.drill-limit p { margin: 0 0 4px; }
.drill-limit-warning { font-weight: 600; }
.drill-locked { font-size: 11px; opacity: .7; }
.drill-search { display: inline-flex; gap: 6px; margin-left: auto; }
.drill-pager { display: flex; gap: 14px; align-items: center; padding: 10px 14px; font-size: 13px; }
.drill-empty { padding: 18px 14px; margin: 0; font-size: 14px; }
.drill-table td, .drill-table th { vertical-align: middle; }

/* --------------------------------------------------------------------- *
 * Drill-down table controls and sortable column headers                  *
 * --------------------------------------------------------------------- */

/* Search + "Export to Excel" as one wrapping group. `.drill-search` above
   pushes itself right with `margin-left: auto`; inside this wrapper the
   WRAPPER does that instead, otherwise the two controls each claim the
   free space and the export link is shoved past the card's right edge. */
.drill-table-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-left: auto;
}
.drill-table-controls .drill-search { margin-left: 0; flex-wrap: wrap; }
.drill-export { white-space: nowrap; }
.drill-export i { margin-right: 0.35em; }

/* Sortable headers are real links, so they must look and focus like
   controls without picking up the global `a` colour -- the header band is
   charcoal (`.table thead th`, !important) and a red link on it fails
   contrast. `inherit` at (0,1,0) beats the bare `a` rule at (0,0,1), and
   the hover/focus rules carry one extra class so they beat `a:hover`
   regardless of where in the file they land. */
.drill-table thead th { padding-top: 0.45rem; padding-bottom: 0.45rem; }
.drill-sort {
    /* Containing block for the `.sr-only` span below. `.sr-only` is
       `position: absolute` with no offsets, so with no positioned
       ancestor it is placed relative to the document's initial
       containing block instead of this link -- on the rightmost
       (Amount) header that pushed `document.scrollWidth` past the
       viewport at 390px even though the header itself fit and nothing
       visible was overflowing. `relative` here costs nothing (no
       offsets set) and keeps the hidden span's box inside the link. */
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.35em;
    color: inherit;
    text-decoration: none;
}
.drill-table .drill-sort:hover,
.drill-table .drill-sort:focus-visible {
    color: inherit;
    text-decoration: underline;
}
.drill-table .drill-sort:focus-visible {
    outline: 2px solid var(--crs-white, #fff);
    outline-offset: 2px;
    text-decoration: none;
}
/* Unsorted arrows stay faint so the ONE sorted column is findable at a
   glance; the sorted arrow is full strength and points the way the rows
   actually run. */
.drill-sort-icon { font-size: 0.8em; opacity: 0.4; }
.drill-sort.is-sorted .drill-sort-icon { opacity: 1; }

/* Phone: the controls take their own full-width line under the card
   title, and the search field is allowed to shrink. Without `min-width:
   0` a `type="search"` input keeps its default intrinsic width and pushes
   the card into a horizontal scroll at 390px. */
@media (max-width: 600px) {
    .drill-table-controls {
        margin-left: 0;
        width: 100%;
    }
    .drill-table-controls .drill-search { width: 100%; }
    .drill-search input[type="search"] { flex: 1 1 8rem; min-width: 0; }
    .drill-export { flex: 0 0 auto; }
}
/* Beta stamp: deliberately a plain flex bar OUTSIDE .commission-page-header's
   own grid (see the template comment) -- that grid auto-places the H2/
   Back-button chrome differently per page (a drill-down with a Back button
   occupies a different cell than the plain dashboard), and an earlier
   attempt at an explicit grid-row/-column here silently stole a cell from
   the title on several page shapes (caught by a grok review before this
   landed). A bar that isn't a grid child can't collide with that grid. */
.cv3-beta-stamp {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 8px;
    padding: 6px 20px 0;
    max-width: 100%;
}
.cv3-beta-stamp-pill {
    flex-shrink: 0;
}
.cv3-beta-stamp-note {
    font-size: 12px;
    /* --cv3-muted only gets SpaceX's inverted value on .cv3-page/.rep-book/
       .rb-chrome-host (see commission_layout.css); this element sits
       outside all three, so it currently reads correctly only because
       SpaceX ALSO inverts --crs-gray-700 on :root itself. If that :root
       inversion is ever narrowed the same way --cv3-muted already was,
       this note goes dark-on-dark -- confirmed via grok review 2026-09-22,
       not yet fixed since it isn't broken today. */
    color: var(--cv3-muted);
    white-space: normal;
    text-align: right;
}
.cv3-beta-stamp-note a {
    /* No !important: (0,2,1) already beats spacex-theme.css's generic
       `body.clair-spacex a` at (0,1,2) on specificity alone (confirmed via
       grok review). !important was tried and removed -- it also forced
       :hover to stay --crs-info instead of the theme's intended #fff, and
       broke the print stylesheet's `a { color: #000 !important }`. */
    color: var(--crs-info);
    font-weight: 600;
    text-decoration: underline;
}
@media (max-width: 767.98px) {
    /* Same fix shape as D-9 (mobile text-overflow): don't let the note's
       full sentence fight the pill for width on a phone -- stack below it
       instead of trying to share the row. */
    .cv3-beta-stamp {
        justify-content: flex-start;
        padding-left: 12px;
        padding-right: 12px;
    }
    .cv3-beta-stamp-note {
        flex-basis: 100%;
        text-align: left;
    }
}

