/* ==========================================================================
   FL510 — BILLING MODULES SHELL (operator-accepted design, 2026-07-20)
   --------------------------------------------------------------------------
   Applies the accepted /Portal/Billing visual: a two-tier portal nav (desktop
   persistent rail + mobile #bl-portal :target sheet), a KPI summary strip, and
   the module surfaces presented as content panes (desktop) / sheet-styled pages
   (mobile). The heavy module CONTENT partials from #333 keep their markup; this
   file wraps them in the shell and restyles the events workbench + evidence.

   TOKEN RECONCILIATION (translation discipline): every color/space/radius here
   derives from the EXISTING three-tier design system (wwwroot/css/tokens.css).
   No forked palette. The billing-local --bl-* tokens below are COMPONENT-tier
   locals that reference SEMANTIC --ds-* tokens (Material-3 component tier) — so
   light/dark still swap in ONE place (the semantic tier), including the manual
   [data-theme] toggle. PER-TAIL HUES DO NOT COME FROM --ds-aircraft-N (corrected
   2026-07-30): that eight-slot palette is superseded reference only. A tail's hue is
   the operator's PICKED colour, else the colour DERIVED from its registration —
   resolved by Services/DesignSystemPalette.Resolve and emitted by Razor as the inline
   --ds-ac-l/--ds-ac-d pair plus the .ds-tail marker class. Never the mockup's ad-hoc
   --t-N* hues. NOTE: the --bl-accent local below has NO producer today (grep-verified);
   it renders its own fallback until a Razor site sets it.

   SCOPE: everything is under `.billing-shell` (which also carries `.ds`), so the
   opt-in contract holds — no bare element is styled, no other page is touched.
   ========================================================================== */

.billing-shell {
    /* --- surfaces / ink (semantic tier) --- */
    --bl-bg: var(--ds-surface);
    --bl-surface: var(--ds-surface-raised);
    --bl-surface-2: color-mix(in srgb, var(--ds-surface-raised) 88%, var(--ds-line));
    --bl-line: var(--ds-line);
    --bl-line-strong: color-mix(in srgb, var(--ds-line) 55%, var(--ds-text-secondary));
    --bl-ink: var(--ds-text-primary);
    --bl-ink-2: var(--ds-text-secondary);
    /* 92%, not 78% (FW6c review, measured in a real engine). --bl-ink-3 is the small-label ink —
       10-12.5px, so WCAG normal-size text at a 4.5:1 floor, never the 3:1 large-text one. At 78% it
       measured 3.58:1 on the hardest light surface (.bl-statcell) and 3.87:1 on paper: under floor
       for the 23 places it colours text, and it had been that way since the shell shipped. The mix
       runs toward the theme's OWN surface, so a bigger share is monotonically safer in both themes —
       dark was already clear at 78% (4.94:1 on that same statcell) and only improves. Measured after:
       4.91:1 light / 6.46:1 dark. The third ink tier still reads as one: rgb(99,109,115) against
       --ds-text-secondary's rgb(85,96,103). */
    --bl-ink-3: color-mix(in srgb, var(--ds-text-secondary) 92%, var(--ds-surface));
    --bl-ink-faint: color-mix(in srgb, var(--ds-text-secondary) 52%, var(--ds-surface));

    /* --- primary (accent) --- */
    --bl-primary: var(--ds-accent);
    --bl-primary-on: var(--ds-accent-on);
    --bl-primary-wash: color-mix(in srgb, var(--ds-accent) 15%, var(--ds-surface));
    /* Text ON --bl-primary-wash, same construction and same reason as the status -ink locals below:
       the raw accent on its own wash measured 4.04:1 light / 6.43:1 dark. Now 6.14 / 7.97. */
    --bl-primary-ink: color-mix(in srgb, var(--ds-accent) 62%, var(--ds-text-primary));

    /* --- semantic status + derived washes --- */
    /* The -ink locals are the TEXT colour to use ON the matching wash, and they exist because the
       raw status hue is not one (measured, FW6c review): --ds-ok on --bl-good-wash is 4.13:1 in
       light theme, under the 4.5:1 SC 1.4.3 floor. Mixing the hue toward --ds-text-primary keeps
       the theme swap at the semantic tier — that token is dark ink on light and light ink on dark —
       so the SAME expression darkens the label on paper and lightens it on the dark surface.
       Measured after: light ok 6.27 / danger 7.00 / warn 6.93; dark ok 8.06 / danger 7.45 / warn 7.44
       (before: light 4.13 / 4.50 / 4.89, dark 6.67 / 5.72 / 5.91). */
    --bl-good: var(--ds-ok);
    --bl-good-wash: color-mix(in srgb, var(--ds-ok) 16%, var(--ds-surface));
    --bl-good-ink: color-mix(in srgb, var(--ds-ok) 62%, var(--ds-text-primary));
    --bl-warn: var(--ds-warn);
    --bl-warn-wash: color-mix(in srgb, var(--ds-warn) 18%, var(--ds-surface));
    --bl-warn-ink: color-mix(in srgb, var(--ds-warn) 62%, var(--ds-text-primary));
    --bl-crit: var(--ds-danger);
    --bl-crit-wash: color-mix(in srgb, var(--ds-danger) 16%, var(--ds-surface));
    --bl-crit-ink: color-mix(in srgb, var(--ds-danger) 62%, var(--ds-text-primary));
    --bl-info: var(--ds-accent);
    --bl-info-wash: color-mix(in srgb, var(--ds-accent) 12%, var(--ds-surface));

    /* --- geometry / elevation / motion (primitive+component tiers) --- */
    --bl-radius: var(--ds-radius-3);
    --bl-radius-sm: var(--ds-radius-2);
    --bl-shadow-card: var(--ds-shadow-1);
    --bl-shadow-pop: var(--ds-shadow-2);
    --bl-shadow-sheet: 0 -8px 40px color-mix(in srgb, var(--ds-text-primary) 22%, transparent);
    --bl-ease: var(--ds-ease);
    --bl-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

    background: var(--bl-bg);
    min-height: 100vh;
    min-height: 100svh;
    color: var(--bl-ink);
}

/* App frame: rail (desktop) + main column. */
.billing-shell .bl-app { min-height: 100vh; min-height: 100svh; }
.billing-shell .bl-main { min-width: 0; display: flex; flex-direction: column; }
.billing-shell .bl-rail { display: none; }
.billing-shell .tnum { font-variant-numeric: tabular-nums; }
.billing-shell .bl-mono { font-family: var(--bl-mono); font-variant-numeric: tabular-nums; }

/* ============ appbar: topbar + KPI strip ============ */
.billing-shell .bl-appbar {
    position: sticky; top: 0; z-index: 30;
    background: color-mix(in srgb, var(--bl-bg) 84%, transparent);
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    border-bottom: 1px solid var(--bl-line);
}
.billing-shell .bl-topbar {
    display: flex; align-items: center; gap: 12px;
    padding: calc(env(safe-area-inset-top, 0px) + 12px) 16px 10px;
}
.billing-shell .bl-brand { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.billing-shell .bl-eyebrow {
    font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--bl-ink-3);
}
.billing-shell .bl-brand h1 {
    margin: 0; font-size: 17px; font-weight: 650; letter-spacing: -.01em;
    display: flex; align-items: center; gap: 8px; line-height: 1.2;
}
.billing-shell .bl-livedot {
    width: 7px; height: 7px; border-radius: 50%; background: var(--bl-good);
    box-shadow: 0 0 0 3px var(--bl-good-wash); flex: none;
}
.billing-shell .bl-topbar .bl-spacer { flex: 1; }
.billing-shell .bl-iconbtn {
    width: 40px; height: 40px; border-radius: 10px; border: 1px solid var(--bl-line);
    background: var(--bl-surface); display: grid; place-items: center; color: var(--bl-ink-2);
    transition: background .15s var(--bl-ease), border-color .15s; flex: none; text-decoration: none;
}
.billing-shell .bl-iconbtn:hover { background: var(--bl-surface-2); border-color: var(--bl-line-strong); }
.billing-shell .bl-iconbtn svg { width: 18px; height: 18px; }

.billing-shell .bl-kpis {
    display: flex; align-items: center; gap: 8px;
    padding: 2px 16px 12px; overflow-x: auto; scrollbar-width: none; margin: 0;
}
.billing-shell .bl-kpis::-webkit-scrollbar { display: none; }
.billing-shell .bl-kpis .bl-plabel { flex: none; font-size: 12px; font-weight: 650; color: var(--bl-ink-2); }
.billing-shell .bl-kpi {
    flex: none; display: inline-flex; align-items: center; gap: 8px; text-decoration: none;
    padding: 7px 11px; border-radius: 10px; background: var(--bl-surface); border: 1px solid var(--bl-line);
    min-height: 40px; transition: border-color .15s, background .15s;
}
.billing-shell .bl-kpi:hover { border-color: var(--bl-line-strong); background: var(--bl-surface-2); }
.billing-shell .bl-kpi .bl-kl { font-size: 11px; font-weight: 600; color: var(--bl-ink-3); white-space: nowrap; }
.billing-shell .bl-kpi .bl-kv {
    font-size: 13px; font-weight: 750; letter-spacing: -.01em;
    font-variant-numeric: tabular-nums; color: var(--bl-ink); white-space: nowrap;
}
.billing-shell .bl-kpi.is-warn .bl-kv { color: var(--bl-warn); }
.billing-shell .bl-kpi.is-good .bl-kv { color: var(--bl-good); }

/* ============ mobile module-card menu ============ */
.billing-shell .bl-menu { padding: 16px; }
.billing-shell .bl-grid { display: grid; gap: 12px; }
.billing-shell .bl-card {
    position: relative; text-align: left; width: 100%; text-decoration: none; color: inherit;
    background: var(--bl-surface); border: 1px solid var(--bl-line); border-radius: var(--bl-radius);
    box-shadow: var(--bl-shadow-card); padding: 15px; display: flex; flex-direction: column; gap: 10px;
    transition: transform .16s var(--bl-ease), border-color .16s, box-shadow .16s;
}
.billing-shell .bl-card:hover { transform: translateY(-2px); border-color: var(--bl-line-strong); box-shadow: var(--bl-shadow-pop); }
.billing-shell .bl-card:active { transform: translateY(0) scale(.995); }
.billing-shell .bl-card.is-primary::before {
    content: ""; position: absolute; left: 0; top: 14px; bottom: 14px; width: 3px; border-radius: 3px; background: var(--bl-primary);
}
.billing-shell .bl-card .bl-chead { display: flex; align-items: flex-start; gap: 11px; }
.billing-shell .bl-card .bl-glyph {
    width: 34px; height: 34px; border-radius: 9px; flex: none; display: grid; place-items: center;
    background: var(--bl-surface-2); color: var(--bl-ink-2); border: 1px solid var(--bl-line);
}
.billing-shell .bl-card.is-primary .bl-glyph { background: var(--bl-primary-wash); color: var(--bl-primary); border-color: transparent; }
.billing-shell .bl-card .bl-glyph svg { width: 18px; height: 18px; }
.billing-shell .bl-card .bl-ctitle { flex: 1; min-width: 0; }
.billing-shell .bl-card .bl-kicker {
    font-size: 10.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--bl-ink-3);
}
.billing-shell .bl-card h2 { margin: 1px 0 0; font-size: 16px; font-weight: 640; letter-spacing: -.01em; }
.billing-shell .bl-card .bl-go { color: var(--bl-ink-faint); flex: none; margin-top: 3px; transition: transform .16s var(--bl-ease), color .16s; }
.billing-shell .bl-card:hover .bl-go { transform: translateX(3px); color: var(--bl-primary); }
.billing-shell .bl-card .bl-go svg { width: 17px; height: 17px; }
.billing-shell .bl-headline { display: flex; align-items: baseline; gap: 8px; }
.billing-shell .bl-headline .bl-big { font-size: 27px; font-weight: 680; letter-spacing: -.02em; line-height: 1; font-variant-numeric: tabular-nums; }
.billing-shell .bl-headline .bl-unit { font-size: 12px; color: var(--bl-ink-3); font-weight: 500; }
.billing-shell .bl-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.billing-shell .bl-chip {
    display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600; line-height: 1;
    padding: 5px 9px; border-radius: 999px; background: var(--bl-surface-2); color: var(--bl-ink-2); border: 1px solid var(--bl-line);
}
.billing-shell .bl-chip .n { font-variant-numeric: tabular-nums; color: var(--bl-ink); font-weight: 700; }
.billing-shell .bl-chip.is-hero { background: var(--bl-good-wash); border-color: transparent; color: var(--bl-good); }
.billing-shell .bl-chip.is-hero .n { color: var(--bl-good); }
.billing-shell .bl-chip.is-attn { background: var(--bl-warn-wash); border-color: transparent; color: var(--bl-warn); }
.billing-shell .bl-chip.is-attn .n { color: var(--bl-warn); }
@media (min-width: 720px) {
    .billing-shell .bl-grid { grid-template-columns: 1fr 1fr; }
    .billing-shell .bl-card.is-primary { grid-column: 1 / -1; }
}

/* ============ portal nav (shared two-tier chrome) ============ */
.billing-shell .bl-pnav { display: flex; flex-direction: column; gap: 2px; padding: 6px 10px 2px; margin: 0; }
.billing-shell .bl-pitem {
    display: flex; align-items: center; gap: 10px; padding: 10px; border-radius: 10px; min-height: 44px;
    color: var(--bl-ink-2); text-decoration: none; font-size: 13px; font-weight: 600;
    transition: background .13s, color .13s;
}
.billing-shell .bl-pitem svg { width: 17px; height: 17px; flex: none; opacity: .8; }
.billing-shell .bl-pitem .bl-lbl { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.billing-shell .bl-pitem .bl-cnt {
    margin-left: auto; font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums;
    padding: 2px 7px; border-radius: 99px; background: var(--bl-surface-2); border: 1px solid var(--bl-line); color: var(--bl-ink-3);
}
.billing-shell .bl-pitem .bl-cnt.is-attn { color: var(--bl-warn); background: var(--bl-warn-wash); border-color: transparent; }
.billing-shell .bl-pitem:hover { background: var(--bl-surface-2); color: var(--bl-ink); }
.billing-shell .bl-pitem[aria-current="page"] { background: var(--bl-primary-wash); color: var(--bl-primary); }
.billing-shell .bl-pitem[aria-current="page"] svg { opacity: 1; }

/* Group divider inside the single Portal nav list. The accepted design names eight tier-1 sections;
   the five below the divider (Reviews, Notifications, Signatures, Permissions, Configuration) are the
   rest of what _Layout's site-header reaches, and they are in the SAME list so suppressing that header
   cannot strand them (see _PortalNav.cshtml). Declared outside the 900px block: the mobile #bl-portal
   sheet renders the same partial and needs the same divider.

   NOTE the ink: `--bl-ink-2`, NOT the `--bl-ink-3` its neighbours `.bl-rail__label` use. Measured in
   a browser at 1280x800 light: `--bl-ink-3` at 10px renders 3.6804:1, under SC 1.4.3's 4.5:1, and
   `.bl-rail__label` fails at exactly that ratio today. Re-toning the operator's accepted rail labels
   is not this slice's call, so the pre-existing failures are recorded in BACKLOG 125 with their
   measurements — but a NEW element is not going to be added below the floor. */
.billing-shell .bl-pgroup {
    display: block; font-size: 10px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
    color: var(--bl-ink-2); padding: 14px 10px 6px; margin-top: 4px; border-top: 1px solid var(--bl-line);
}

/* Sign out — POST form, rendered in the desktop rail foot AND the mobile #bl-portal sheet. It exists
   because suppressing _Layout's site-header (internal-design-build-spec.md §4 step 3) removed the ONLY
   sign-out control the billing shell had — measured 1 -> 0 occurrences of Account/SignOut on all four
   billing routes. Mirrors the external shell's `.ps-signout` rules — DUPLICATED, not imported: this
   file is asserted to have no dependency on the shared portal stylesheet
   (ExternalPortalDesignSurfaceTests.BillingShell_KeepsItsOwnChromeIntact), so do not name that file
   here. 44px min-height is the repo touch standard
   (REVIEW_CHECKLIST §6a; the WCAG 2.2 SC 2.5.8 floor is 24px). Declared OUTSIDE the 900px block because
   below 900px .bl-rail is display:none and the sheet is the only nav there is. */
.billing-shell .bl-signout { margin: 0; padding: 6px 10px 2px; }
.billing-shell .bl-signout__btn {
    display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px; border-radius: 10px;
    min-height: 44px; background: none; border: 0; cursor: pointer; text-align: left;
    color: var(--bl-ink-2); font: inherit; font-size: 13px; font-weight: 600;
    transition: background .13s, color .13s;
}
.billing-shell .bl-signout__btn svg { width: 17px; height: 17px; flex: none; opacity: .8; }
.billing-shell .bl-signout__btn:hover { background: var(--bl-surface-2); color: var(--bl-ink); }

/* ============ scrim + sheets ============ */
.billing-shell .bl-scrim {
    position: fixed; inset: 0; z-index: 40; background: color-mix(in srgb, var(--ds-c-ink-900) 42%, transparent);
    opacity: 0; visibility: hidden; transition: opacity .3s var(--bl-ease), visibility .3s;
}
.billing-shell .bl-scrim.is-show { opacity: 1; visibility: visible; }

/* The mobile portal-nav sheet: pure-CSS :target no-JS fallback, JS-enhanced. */
.billing-shell .bl-sheet {
    background: var(--bl-surface); display: flex; flex-direction: column;
}
.billing-shell #bl-portal.bl-sheet {
    position: fixed; z-index: 50; left: 0; right: 0; bottom: 0; max-height: 90vh;
    border-radius: 20px 20px 0 0; box-shadow: var(--bl-shadow-sheet);
    transform: translateY(100%); visibility: hidden;
    transition: transform .34s var(--bl-ease), visibility 0s linear .34s;
    will-change: transform;
}
.billing-shell #bl-portal.bl-sheet.is-open,
.billing-shell #bl-portal.bl-sheet:target {
    transform: translateY(0); visibility: visible;
    transition: transform .34s var(--bl-ease), visibility 0s;
}
body:has(.billing-shell #bl-portal:target) .billing-shell .bl-scrim { opacity: 1; visibility: visible; }
.billing-shell .bl-grip { width: 38px; height: 4px; border-radius: 99px; background: var(--bl-line-strong); margin: 9px auto 0; flex: none; }
.billing-shell .bl-sheet-head {
    display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--bl-line); flex: none;
}
.billing-shell .bl-sheet-head .bl-glyph {
    width: 32px; height: 32px; border-radius: 9px; flex: none; display: grid; place-items: center;
    background: var(--bl-primary-wash); color: var(--bl-primary);
}
.billing-shell .bl-sheet-head .bl-glyph svg { width: 17px; height: 17px; }
.billing-shell .bl-sheet-title { flex: 1; min-width: 0; }
.billing-shell .bl-sheet-title .bl-kicker { font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--bl-ink-3); }
.billing-shell .bl-sheet-title h2 { margin: 1px 0 0; font-size: 17px; font-weight: 660; letter-spacing: -.01em; }
.billing-shell .bl-closebtn {
    width: 40px; height: 40px; border-radius: 9px; border: 1px solid var(--bl-line); background: var(--bl-surface);
    display: grid; place-items: center; color: var(--bl-ink-2); flex: none; text-decoration: none;
}
.billing-shell .bl-closebtn:hover { background: var(--bl-surface-2); }
.billing-shell .bl-closebtn svg { width: 16px; height: 16px; }
.billing-shell #bl-portal .bl-sheet-body { overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 6px 2px calc(20px + env(safe-area-inset-bottom, 0px)); }

/* ============ module content pane (each route's body) ============ */
.billing-shell .bl-panes { padding: 8px 12px 60px; }
.billing-shell .bl-modulehead {
    display: flex; align-items: center; gap: 12px; padding: 14px 6px 8px;
}
.billing-shell .bl-modulehead .bl-glyph {
    width: 34px; height: 34px; border-radius: 9px; flex: none; display: grid; place-items: center;
    background: var(--bl-primary-wash); color: var(--bl-primary);
}
.billing-shell .bl-modulehead .bl-glyph svg { width: 18px; height: 18px; }
.billing-shell .bl-modulehead .bl-kicker { font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--bl-ink-3); }
.billing-shell .bl-modulehead h2 { margin: 1px 0 0; font-size: 19px; font-weight: 660; letter-spacing: -.01em; }
.billing-shell .bl-backlink {
    display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600;
    color: var(--bl-ink-2); text-decoration: none; padding: 8px 4px; min-height: 44px;
}
.billing-shell .bl-backlink:hover { color: var(--bl-primary); }

/* ============ events workbench (restyles the #333 workbench's own classes) ============ */
.billing-shell .billing-filter-form { margin: 0 0 8px; }
.billing-shell .billing-filter-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
    background: var(--bl-surface); border: 1px solid var(--bl-line); border-radius: var(--bl-radius-sm); padding: 12px;
}
.billing-shell .billing-filter-actions { grid-column: 1 / -1; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.billing-shell .billing-reason-breakdown { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 4px; }
.billing-shell .billing-reason-chip {
    display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600;
    padding: 5px 9px; border-radius: 999px; background: var(--bl-surface-2); color: var(--bl-ink-2); border: 1px solid var(--bl-line);
}
.billing-shell .billing-reason-chip.is-clean { background: var(--bl-good-wash); color: var(--bl-good); border-color: transparent; }
.billing-shell .billing-unclassified-note {
    background: var(--bl-warn-wash); border: 1px solid color-mix(in srgb, var(--bl-warn) 26%, transparent);
    border-radius: var(--bl-radius-sm); padding: 12px; margin: 10px 0;
}
.billing-shell .billing-bulk-release {
    background: var(--bl-surface); border: 1px solid var(--bl-line); border-radius: var(--bl-radius-sm); padding: 14px; margin: 10px 0;
}
.billing-shell .billing-bulk-release h3 { margin: 0 0 4px; font-size: 15px; }

/* freshness + Sync-now strip (folded billing-events sync action) */
.billing-shell .billing-events-sync-strip {
    display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap; padding: 8px 2px; margin: 10px 0;
    border-top: 1px solid var(--bl-line); border-bottom: 1px solid var(--bl-line);
}
.billing-shell .billing-events-sync-now { margin: 0; }
.billing-shell .billing-events-sync-now button {
    font-size: 12.5px; font-weight: 650; color: var(--bl-primary); background: none; border: none;
    padding: 8px 6px; min-height: 40px; cursor: pointer; text-decoration: underline; text-underline-offset: 2px;
}

/* event rows */
.billing-shell .billing-event-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.billing-shell .billing-event-row {
    position: relative; background: var(--bl-surface); border: 1px solid var(--bl-line);
    border-radius: var(--bl-radius-sm); padding: 12px 12px 12px 18px; overflow: hidden;
    transition: border-color .14s, box-shadow .14s;
}
.billing-shell .billing-event-row::before {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--bl-accent, var(--bl-line-strong));
}
.billing-shell .billing-event-row:hover { border-color: var(--bl-line-strong); box-shadow: var(--bl-shadow-card); }
.billing-shell .billing-event-row__head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.billing-shell .billing-event-row__head strong { font-family: var(--bl-mono); font-size: 13px; font-weight: 700; }
.billing-shell .billing-event-row__when { margin-left: auto; font-size: 12px; color: var(--bl-ink-3); font-variant-numeric: tabular-nums; }
.billing-shell .billing-event-row__description { font-size: 13px; color: var(--bl-ink-2); margin: 6px 0; }
.billing-shell .billing-event-row__facts { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 12px; margin: 8px 0 0; }
.billing-shell .billing-event-row__facts dt { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--bl-ink-3); margin: 0; }
.billing-shell .billing-event-row__facts dd { font-size: 12.5px; color: var(--bl-ink); margin: 1px 0 0; }

/* status pills */
.billing-shell .billing-event-status {
    display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 700; letter-spacing: .02em;
    padding: 3px 9px; border-radius: 999px; background: var(--bl-surface-2); color: var(--bl-ink-2);
}
.billing-shell .billing-event-status::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.billing-shell .billing-event-status.is-pending { background: var(--bl-warn-wash); color: var(--bl-warn); }
.billing-shell .billing-event-status.is-ready { background: var(--bl-good-wash); color: var(--bl-good); }
.billing-shell .billing-event-status.is-muted { background: var(--bl-surface-2); color: var(--bl-ink-3); }

.billing-shell .billing-event-evidence-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 10px; }
.billing-shell .billing-event-evidence-link { font-size: 12.5px; font-weight: 600; color: var(--bl-primary); text-decoration: none; }
.billing-shell .billing-event-review { margin-top: 10px; }
.billing-shell .billing-event-review > summary { cursor: pointer; font-size: 12.5px; font-weight: 650; color: var(--bl-ink-2); min-height: 40px; display: flex; align-items: center; }

/* ============ evidence panel (source cards + verdict + clip + meters) ============ */
.billing-shell .bl-evidence { border-top: 1px solid var(--bl-line); padding: 14px 12px; display: flex; flex-direction: column; gap: 12px; }
.billing-shell .bl-evsection-label { font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--bl-ink-3); margin: 0; }
.billing-shell .bl-evgrid { display: grid; grid-template-columns: 1fr; gap: 9px; }
.billing-shell .bl-src {
    background: var(--bl-surface-2); border: 1px solid var(--bl-line); border-radius: 11px;
    padding: 11px 12px; display: flex; flex-direction: column; gap: 6px; min-width: 0;
}
.billing-shell .bl-srctag { display: flex; align-items: center; gap: 8px; }
.billing-shell .bl-badge { font-size: 10px; font-weight: 750; letter-spacing: .04em; padding: 3px 7px; border-radius: 6px; flex: none; }
.billing-shell .bl-badge.is-airbly { background: var(--bl-primary-wash); color: var(--bl-primary); }
.billing-shell .bl-badge.is-adsb { background: color-mix(in srgb, var(--ds-aircraft-3) 18%, var(--bl-surface)); color: var(--ds-aircraft-3); }
/* FW8b (2026-08-10): the derived canonical row (no Airbly source hydrated the record) — a neutral badge on
   the shell's own ink tokens, so it never reads as either telemetry source in light or dark. */
.billing-shell .bl-badge.is-record { background: var(--bl-surface-2); color: var(--bl-ink-2); border: 1px solid var(--bl-line); }
.billing-shell .bl-srcrole { margin-left: auto; font-size: 10.5px; color: var(--bl-ink-faint); font-weight: 650; letter-spacing: .03em; }
.billing-shell .bl-srcline { font-size: 12.5px; color: var(--bl-ink-2); }
.billing-shell .bl-srcline b { color: var(--bl-ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.billing-shell .bl-srcsub { font-family: var(--bl-mono); font-variant-numeric: tabular-nums; font-size: 11px; color: var(--bl-ink-3); line-height: 1.5; }
.billing-shell .bl-verdict {
    display: flex; gap: 10px; padding: 11px 12px; border-radius: 11px;
    background: var(--bl-good-wash); border: 1px solid color-mix(in srgb, var(--bl-good) 22%, transparent);
}
.billing-shell .bl-verdict .bl-vicon { color: var(--bl-good); flex: none; margin-top: 1px; }
.billing-shell .bl-verdict .bl-vicon svg { width: 16px; height: 16px; display: block; }
.billing-shell .bl-verdict .bl-vtext { font-size: 12.5px; line-height: 1.5; color: var(--bl-ink); }
.billing-shell .bl-verdict.is-conflict { background: var(--bl-crit-wash); border-color: color-mix(in srgb, var(--bl-crit) 26%, transparent); }
.billing-shell .bl-verdict.is-conflict .bl-vicon { color: var(--bl-crit); }
.billing-shell .bl-clipline {
    display: flex; gap: 8px; align-items: baseline; padding: 0 2px;
    font-family: var(--bl-mono); font-variant-numeric: tabular-nums; font-size: 11px; line-height: 1.55; color: var(--bl-ink-2);
}
.billing-shell .bl-clipline .bl-ck { color: var(--bl-info); font-weight: 700; letter-spacing: .06em; flex: none; }
.billing-shell .bl-clipline.is-conflict .bl-ck { color: var(--bl-crit); }

/* Meters — the FL510 timing vocabulary: Engine (billing) · TIS (air) · TTAF · clip window.
   The legacy engine-hours meter name FL510 does not use is deliberately absent. */
.billing-shell .bl-meters {
    display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
    background: var(--bl-line); border: 1px solid var(--bl-line); border-radius: 11px; overflow: hidden;
}
.billing-shell .bl-meter { background: var(--bl-surface-2); padding: 10px 12px; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.billing-shell .bl-meter .bl-ml { font-size: 10px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--bl-ink-3); }
.billing-shell .bl-meter .bl-mv { font-family: var(--bl-mono); font-size: 14px; font-weight: 750; letter-spacing: -.01em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.billing-shell .bl-meter .bl-mv small { font-size: 10.5px; font-weight: 600; color: var(--bl-ink-3); }
.billing-shell .bl-meter .bl-mv.is-empty { color: var(--bl-ink-faint); }

/* ============ desktop ≥ 900px — persistent rail + content pane ============ */
@media (min-width: 900px) {
    .billing-shell .bl-app { display: flex; align-items: stretch; }
    .billing-shell .bl-rail {
        display: flex; flex-direction: column; width: 240px; flex: none;
        position: sticky; top: 0; align-self: flex-start; height: 100vh; height: 100svh;
        background: var(--bl-surface); border-right: 1px solid var(--bl-line); z-index: 35; overflow-y: auto;
    }
    .billing-shell .bl-rail__label {
        font-size: 10px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase; color: var(--bl-ink-3); padding: 18px 20px 8px;
    }
    .billing-shell .bl-rail__nav { display: flex; flex-direction: column; gap: 3px; padding: 0 10px 10px; }
    .billing-shell .bl-navitem {
        display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: 10px; min-height: 42px;
        border: 1px solid transparent; color: var(--bl-ink-2); text-decoration: none; font-size: 13px; font-weight: 600;
        transition: background .13s, color .13s;
    }
    .billing-shell .bl-navitem svg { width: 17px; height: 17px; flex: none; opacity: .85; }
    .billing-shell .bl-navitem .bl-lbl { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .billing-shell .bl-navitem .bl-cnt {
        margin-left: auto; flex: none; font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
        padding: 2px 8px; border-radius: 99px; background: var(--bl-surface-2); border: 1px solid var(--bl-line); color: var(--bl-ink-2);
    }
    .billing-shell .bl-navitem .bl-cnt.is-attn { color: var(--bl-warn); background: var(--bl-warn-wash); border-color: transparent; }
    .billing-shell .bl-navitem .bl-cnt.is-ok { color: var(--bl-good); background: var(--bl-good-wash); border-color: transparent; }
    .billing-shell .bl-navitem:hover { background: var(--bl-surface-2); color: var(--bl-ink); }
    .billing-shell .bl-navitem[aria-current="page"] { background: var(--bl-primary-wash); color: var(--bl-primary); }
    .billing-shell .bl-navitem[aria-current="page"] svg { opacity: 1; }
    .billing-shell .bl-rail .bl-pnav { padding: 6px 10px 2px; }
    /* Rail foot pins sign-out to the bottom of the 100svh rail (mirrors .ps-rail__foot).
       STICKY, and that is load-bearing rather than cosmetic: the rail now carries 13 tier-1 links,
       a group divider and 4 module links, which overflows an 800px-tall viewport — measured, the
       non-sticky foot rendered at top 925 / bottom 969 in a 1280x800 window, i.e. off-screen and
       failing a centre-point hit test until the rail was scrolled. Sticky keeps sign-out on screen
       at every rail scroll position. */
    .billing-shell .bl-rail__spacer { flex: 1; }
    .billing-shell .bl-rail__foot {
        position: sticky; bottom: 0; z-index: 1; background: var(--bl-surface);
        border-top: 1px solid var(--bl-line); padding: 8px 16px;
    }
    .billing-shell .bl-rail__foot .bl-signout { padding: 0; }
    .billing-shell .bl-rail__foot .bl-signout__btn { padding: 8px 10px; margin-left: -10px; }

    .billing-shell .bl-main { flex: 1; min-width: 0; }
    .billing-shell .bl-topbar { padding: 18px 28px 10px; }
    .billing-shell .bl-kpis { padding: 2px 28px 14px; }
    .billing-shell #bl-menuBtn { display: none; }
    .billing-shell .bl-panes { padding: 18px 28px 60px; max-width: 1140px; width: 100%; }
    .billing-shell .bl-scrim { display: none !important; }
    /* The #bl-portal sheet is MOBILE-ONLY chrome (mobile-design-standards.md §3: "#portal is
       redirected away"). The external shell already hides #ext-portal at this breakpoint; this file
       hid the scrim and the menu button but not the sheet itself, so a desktop viewport landing on
       a URL carrying #bl-portal painted the bottom sheet OVER the rail. Observed at 1280x800:
       getComputedStyle(#bl-portal).display === "flex", and a centre-point hit test on the rail's
       sign-out button returned an A.bl-pitem from inside the sheet. Pre-existing; fixed here because
       the sheet now carries sign-out and the full tier-1 set, so overlaying is no longer cosmetic. */
    .billing-shell #bl-portal { display: none !important; }

    .billing-shell .bl-evgrid { grid-template-columns: 1fr 1fr; }
    .billing-shell .bl-evgrid .bl-span { grid-column: 1 / -1; }
    .billing-shell .bl-meters { grid-template-columns: repeat(4, 1fr); }
    .billing-shell .billing-filter-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .billing-shell .billing-event-row__facts { grid-template-columns: repeat(3, 1fr); }
}

/* On desktop the mobile module-card menu still shows on the LANDING (the menu of
   modules); it is the landing body, not a sheet. Sub-view pages render their own
   content in the pane. Nothing to hide here — the landing IS the menu. */

/* ============ harmonize the module CONTENT partials inside the shell ============
   The Financial / Mappings / Shadow module bodies keep their #333 markup (account
   cards, tables, .btn actions). Nudge them toward the shell surface so they don't
   read as a foreign panel. The .ds base already lifts their inputs/type. */
.billing-shell .account-card {
    background: var(--bl-surface); border: 1px solid var(--bl-line); border-radius: var(--bl-radius);
    box-shadow: var(--bl-shadow-card); color: var(--bl-ink);
}
.billing-shell .account-stat { color: var(--bl-ink); }
.billing-shell .account-field-help { color: var(--bl-ink-3); }
.billing-shell .account-badge { background: var(--bl-surface-2); border-color: var(--bl-line); color: var(--bl-ink-2); }
.billing-shell .flight-log-table-wrap { overflow-x: auto; }
.billing-shell .flight-log-table th { color: var(--bl-ink-3); }
.billing-shell .flight-log-table td, .billing-shell .flight-log-table th { border-color: var(--bl-line); }
.billing-shell .contact-alert { border-radius: var(--bl-radius-sm); }
.billing-shell .btn {
    min-height: 44px; border-radius: var(--bl-radius-sm); font-weight: 600;
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.billing-shell .btn-primary { background: var(--bl-primary); border-color: transparent; color: var(--bl-primary-on); }
.billing-shell .btn-primary:hover { filter: brightness(1.05); }

/* ============ FW6c — the residual billing surfaces join the shell ============
   ShadowMonth, ShadowMonthDiff and the CardPointe Gateway posture page rendered on the legacy
   _Layout site-header until this wave (the build spec's "#shadow built" row is false — see the
   FW2 corrections addendum recorded in docs/COMPLETION-PLAN.md section 5.2). They are now
   _BillingModuleLayout pages, so everything below exists for two reasons only:

   (a) THE DARK-MODE TRAP, docs/AREAS/mobile-design-standards.md section 8. site.css has no dark
       theme; every colour in it is a light-theme literal. Those literals were harmless while these
       views only ever rendered on light-only _Layout, and become unreadable the moment the view
       lands inside a shell that follows prefers-color-scheme and the [data-theme] toggle. The rule
       there is a SCOPED HARMONIZATION LAYER, never per-page patches, so each addition below
       re-points a light literal at a --bl-* token that already carries both themes.
       Two of these were ALREADY WRONG before this wave, on Financial and Mappings, which have
       rendered .account-card h2 at the literal #0b3d91 inside this shell since 2026-07-20.
   (b) The approved design's own vocabulary for the sheets these pages translate: the #shadow
       statgrid + owner-delta diff, and #gateway's .denied permission block.
   ------------------------------------------------------------------------------------------- */

/* Sentinel. Asserted by BillingResidualSurfaceDesignTests as a PARSED top-level selector, not as
   raw text: an unterminated comment above this point swallows every rule between it and the next
   close marker while a Contains-style guard keeps passing (the FW5c owner-collapse defect). */
.billing-shell .bl-fw6c-sentinel { display: none; }

/* ---- legacy-content harmonization, continued ---- */
.billing-shell .account-card h2,
.billing-shell .account-card h3,
.billing-shell .account-section h2 { color: var(--bl-ink); }
/* Only the GAP is re-spaced to the shell rhythm. The COLUMN COUNT is site.css's
   (`repeat(auto-fit, minmax(220px, 1fr))` from its 760px breakpoint) and is deliberately not
   overridden here: this selector also matches the Events workbench KPI row and the eight legacy
   Gateway-posture panels, both of which are live pages this wave did not convert. An earlier
   revision of this block forced `grid-template-columns: 1fr` above 900px, which measured as 3
   columns at 860px and 1 column at 1280px — widening the window REDUCED the column count. */
.billing-shell .account-card-grid { display: grid; gap: 12px; }
/* The wash is the background, so the TEXT takes the -ink local, never the raw status hue: measured
   in a real engine, the raw hue on its own wash is 4.13:1 (ok) and 4.50:1 (danger) in light theme —
   at or under the SC 1.4.3 floor. The border keeps the hue: it is decoration beside a text label,
   not the boundary that identifies a control. */
.billing-shell .contact-alert-success {
    background: var(--bl-good-wash); color: var(--bl-good-ink); border: 1px solid color-mix(in srgb, var(--bl-good) 30%, transparent);
}
.billing-shell .contact-alert-error {
    background: var(--bl-crit-wash); color: var(--bl-crit-ink); border: 1px solid color-mix(in srgb, var(--bl-crit) 30%, transparent);
}
.billing-shell .contact-alert-warning {
    background: var(--bl-warn-wash); color: var(--bl-warn-ink); border: 1px solid color-mix(in srgb, var(--bl-warn) 30%, transparent);
}
.billing-shell .contact-alert-link { color: inherit; font-weight: 700; margin-left: 6px; }
.billing-shell .btn-secondary {
    background: var(--bl-surface); color: var(--bl-ink); border: 1px solid var(--bl-line-strong);
}
.billing-shell .btn-secondary:hover { background: var(--bl-surface-2); border-color: var(--bl-line-strong); color: var(--bl-ink); }
.billing-shell .btn-outline-danger {
    background: var(--bl-surface); color: var(--bl-crit); border: 1px solid color-mix(in srgb, var(--bl-crit) 38%, transparent);
}
.billing-shell .btn-outline-danger:hover { background: var(--bl-crit-wash); color: var(--bl-crit); }
.billing-shell .form-label { color: var(--bl-ink-2); font-weight: 650; }
.billing-shell .contact-field > span,
.billing-shell .contact-field label,
.billing-shell .contact-field legend { color: var(--bl-ink-2); }
.billing-shell .contact-field { min-height: 44px; }
/* Control borders take --bl-ink-3, NOT --bl-line: a card hairline measures far under the 3:1
   SC 1.4.11 floor for the boundary that IDENTIFIES a control. The external shell reached the same
   finding and added its own field-border token; this file states the rule rather than naming that
   file, because a regression guard asserts the billing shell references it nowhere. */
.billing-shell .form-control,
.billing-shell .contact-input,
.billing-shell textarea.form-control,
.billing-shell input[type="file"].form-control {
    font-size: max(16px, 1rem);
    background: var(--bl-surface-2); color: var(--bl-ink);
    border: 1px solid var(--bl-ink-3); border-radius: var(--bl-radius-sm);
    padding: 10px 11px; width: 100%;
}
.billing-shell fieldset { border: 1px solid var(--bl-line); border-radius: var(--bl-radius-sm); padding: 12px; margin: 0; }
.billing-shell fieldset legend { font-size: 12px; padding: 0 6px; }
.billing-shell details > summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; color: var(--bl-ink); }

/* ---- approved-design vocabulary the residual sheets need ---- */
.billing-shell .bl-sectlbl {
    font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
    color: var(--bl-ink-3); margin: 14px 0 6px;
}
.billing-shell .bl-statgrid {
    display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
    background: var(--bl-line); border: 1px solid var(--bl-line); border-radius: var(--bl-radius-sm); overflow: hidden;
}
.billing-shell .bl-statcell { background: var(--bl-surface-2); padding: 13px 14px; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.billing-shell .bl-statcell .bl-sl { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--bl-ink-3); }
.billing-shell .bl-statcell .bl-sv { font-size: 20px; font-weight: 700; letter-spacing: -.02em; line-height: 1.15; font-variant-numeric: tabular-nums; }
.billing-shell .bl-statcell .bl-sv small { font-size: 11px; font-weight: 600; color: var(--bl-ink-3); letter-spacing: 0; }
.billing-shell .bl-statcell.is-ok .bl-sv { color: var(--bl-good); }
.billing-shell .bl-statcell.is-warn .bl-sv { color: var(--bl-warn); }
.billing-shell .bl-statcell.is-crit .bl-sv { color: var(--bl-crit); }
.billing-shell .bl-note { font-size: 12.5px; color: var(--bl-ink-3); line-height: 1.5; }
/* NOT HERE, deliberately: .bl-stackcard, .bl-actrow and the .bl-diff owner's-rate block. The mock's
   #shadow sheet designs a $150.00 -> $157.50 diff and an "Owner delta +5.0%" cell, but no view model
   in this estate computes either, so the markup was correctly not invented (see ShadowMonthDiff.cshtml)
   — and a stylesheet for markup that does not exist is dead code the parse guard would then pin as
   required. When a slice supplies the VM fields, the rules come back with their consumers. */

/* In-page jump strip. NOT primary navigation: every chip is a real link inside the module a page
   already belongs to, which is how the approved design treats a third tier of CONTENT. */
.billing-shell .bl-submodnav { display: flex; gap: 7px; flex-wrap: wrap; padding: 4px 0 10px; margin: 0; }
.billing-shell .bl-subchip {
    display: inline-flex; align-items: center; min-height: 44px; text-decoration: none;
    font-size: 12px; font-weight: 650; padding: 7px 13px; border-radius: 999px; color: var(--bl-ink-2);
    background: var(--bl-surface-2); border: 1px solid var(--bl-line);
}
.billing-shell .bl-subchip:hover { border-color: var(--bl-line-strong); color: var(--bl-ink); }
.billing-shell .bl-subchip[aria-current="page"] { background: var(--bl-primary-wash); border-color: transparent; color: var(--bl-primary-ink); }

/* Month stepper. Prev/next are real links carrying the month in the query, so it works with JS off. */
.billing-shell .bl-stepper { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 2px 0 10px; }
.billing-shell .bl-sbtn {
    display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 8px 13px;
    border-radius: var(--bl-radius-sm); border: 1px solid var(--bl-line-strong); background: var(--bl-surface);
    color: var(--bl-ink); text-decoration: none; font-size: 12.5px; font-weight: 650;
}
.billing-shell .bl-sbtn:hover { background: var(--bl-surface-2); }
.billing-shell .bl-pos { font-size: 12.5px; font-weight: 700; color: var(--bl-ink); font-variant-numeric: tabular-nums; padding: 0 4px; }

/* Permission denied — names the missing capability and who grants it. The approved design uses this
   whole-surface on Gateway posture and inline beside an action the reader cannot take. */
.billing-shell .bl-denied {
    margin: 12px 0; padding: 16px; border-radius: var(--bl-radius); display: flex; gap: 13px; align-items: flex-start;
    background: var(--bl-surface-2); border: 1px solid var(--bl-line);
}
.billing-shell .bl-denied .bl-dicon {
    width: 36px; height: 36px; border-radius: 10px; flex: none; display: grid; place-items: center;
    background: var(--bl-warn-wash); color: var(--bl-warn);
}
.billing-shell .bl-denied .bl-dicon svg { width: 18px; height: 18px; }
.billing-shell .bl-denied h3 { margin: 0 0 4px; font-size: 14px; font-weight: 660; color: var(--bl-ink); }
.billing-shell .bl-denied p { margin: 0; font-size: 12.5px; color: var(--bl-ink-3); line-height: 1.5; }
.billing-shell .bl-denied p + p { margin-top: 7px; }
.billing-shell .bl-denied a { color: var(--bl-primary); font-weight: 650; }
.billing-shell .bl-denied code {
    font-family: var(--bl-mono); font-size: 11px; background: var(--bl-surface);
    border: 1px solid var(--bl-line); padding: 1px 6px; border-radius: 6px; color: var(--bl-ink-2);
}
.billing-shell .bl-denied.is-inline { margin: 10px 0 0; }

@media (min-width: 900px) {
    .billing-shell .bl-statgrid.is-three { grid-template-columns: repeat(3, 1fr); }
    .billing-shell .bl-statgrid.is-four { grid-template-columns: repeat(4, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
    .billing-shell * { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}
