/* /Components/Analytics/XvaAnalytic.razor.rz.scp.css */
/* The xVA analytic's own body. Card/header/chevron chrome belongs to SummaryTile and the pane's to
   DetailPane; what is here is the figure look, lifted verbatim from XvaTile.razor.css so the tile
   reads exactly as it did before there was one component drawing it, plus the pane-only parts
   (mode content, breakdown).

   The figure look moved to XvaHeadline.razor.css with the markup it styles, when the headline became
   its own component so the trades list could draw the same figures above its grid: CSS isolation is
   per file, so a rule left behind here would match nothing there. The two colour classes below stay
   because this file still uses one of them, on a failed run's message. */

.val-positive[b-cro6560xeo] { color: var(--token-rate); }
.val-negative[b-cro6560xeo] { color: var(--token-position); }

.xva-state-msg[b-cro6560xeo] {
    font-size: 12px;
    color: var(--cpd-text-subtle);
}

.xva-scope-summary[b-cro6560xeo] {
    margin-top: 8px;
    font-size: 10px;
    font-family: var(--cpd-font-mono);
    color: rgba(var(--cpd-contrast-rgb), calc(0.35 * var(--cpd-text-alpha-scale)));
}

.xva-run-btn[b-cro6560xeo] {
    margin-top: 8px;
}

.xva-progress[b-cro6560xeo] {
    margin-top: 8px;
}

.xva-mode-content[b-cro6560xeo] {
    margin-bottom: 8px;
}
/* /Components/Analytics/XvaAnalyticLens.razor.rz.scp.css */
/* The same two-column shape PageRenderer gives a pane-bearing tile, because this IS one — it just
   is not described by the Page DU. Kept byte-compatible with `.page-tile-pane-layout` on purpose: a
   reader should not be able to tell that the xVA pane comes from somewhere else on the page. */
.xva-lens[b-6jxlaztj1s] {
    display: flex;
    gap: var(--cpd-tile-gap);
    align-items: flex-start;
}

/* min-width: 0 is load-bearing rather than tidy: the profile grid inside the pane is wide, and
   without it the grid's intrinsic width wins the flex negotiation and stretches the whole page
   instead of scrolling inside the pane (docs/xva-lens-design.md §6). */
.xva-lens-main[b-6jxlaztj1s] {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--cpd-tile-gap);
}

.xva-lens-rail[b-6jxlaztj1s] {
    flex: 0 0 var(--cpd-pane-rail-w);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

/* Under ~1000px the rail plus a detail pane no longer fit, so the tile becomes a strip above the
   pane — the same breakpoint and the same treatment PageRenderer applies to its own pane layout. */
@media (max-width: 999.98px) {
    .xva-lens[b-6jxlaztj1s] {
        flex-direction: column;
        align-items: stretch;
    }

    .xva-lens-rail[b-6jxlaztj1s] {
        order: -1;
        flex: none;
    }
}
/* /Components/Analytics/XvaHeadline.razor.rz.scp.css */
/* The xVA figure look, moved here with the markup it styles when the headline became its own
   component: Blazor's CSS isolation stamps a component's scope attribute onto the markup compiled
   into its own .razor file, so these rules match nothing if they stay in XvaAnalytic.razor.css.
   Lifted verbatim from there (and, before that, from XvaTile.razor.css) so the tile reads exactly as
   it did before there was one component drawing it. */

.val-positive[b-8c5a526d9p] { color: var(--token-rate); }
.val-negative[b-8c5a526d9p] { color: var(--token-position); }

.xva-stat-grid[b-8c5a526d9p] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    /* 10px by design, NOT var(--cpd-tile-gap): these are paired figures inside one readout, not
       separate cards, and 16px between them read as two lists. */
    gap: 10px;
}

/* A figure that owns a whole row of the two-column grid (the adjusted price). A class rather than an
   inline style so the one-column rule below can take the span back: an inline `grid-column: span 2`
   would win the cascade and force an implicit second column. */
.xva-stat-wide[b-8c5a526d9p] { grid-column: span 2; }

/* Two 15px mono figures plus their labels stop fitting side by side once the tile is under about
   240px wide - the compact right rail (--cpd-pane-rail-w 240px, less the tile's own padding) is
   exactly there. The container is SummaryTile's root .summary-tile, which declares
   `container-type: inline-size`; unnamed, so this resolves to that nearest ancestor container
   whichever tile the body is rendered into - and a container query resolves against ancestors
   regardless of which component's stylesheet the rule came from, which is why the move is safe. */
@container (max-width: 239.98px) {
    .xva-stat-grid[b-8c5a526d9p] { grid-template-columns: 1fr; }
    .xva-stat-wide[b-8c5a526d9p] { grid-column: auto; }
}

.xva-stat[b-8c5a526d9p] {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.xva-stat-label[b-8c5a526d9p] {
    font-size: 9px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.35 * var(--cpd-text-alpha-scale)));
}

.xva-stat-value[b-8c5a526d9p] {
    font-family: var(--cpd-font-mono);
    font-size: 15px;
    font-weight: 600;
}

/* The "± 8" Monte Carlo standard error under each figure. 0.3 measured 2.7:1 in dark mode; 0.35 is
   the lowest rung that clears 3:1 in both themes, and is the tier the other 10px captions use. */
.xva-stat-se[b-8c5a526d9p] {
    font-family: var(--cpd-font-mono);
    font-size: 10px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.35 * var(--cpd-text-alpha-scale)));
}

/* This readout is a 95% interval (1.96σ). The simulation-settings dialog states its accuracy target
   at a user-selected threshold defaulting to the same 95%, so the two agree by default - and both
   say which basis they are on, so a non-default threshold cannot be silently mistaken for this one. */
.xva-stat-se-basis[b-8c5a526d9p] {
    font-size: 0.75em;
    letter-spacing: 0.03em;
    opacity: 0.6;
}

/* The pane's headline. Four figures across on a wide pane, folding to two and then one rather than
   shrinking the mono figures below where they are legible. */
.xva-headline[b-8c5a526d9p] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 16px;
    margin-bottom: 16px;
}

/* The run cell names a count, not money, so it is not a figure in the same weight as the three
   beside it. */
.xva-run-value[b-8c5a526d9p] {
    font-size: 13px;
    font-weight: 500;
}

/* What the figures are a total of, while a scope run is still streaming. Same 10px caption tier as
   the ± readouts: it qualifies the figures rather than competing with them. */
.xva-headline-caption[b-8c5a526d9p] {
    margin-top: 6px;
    font-size: 10px;
    font-family: var(--cpd-font-mono);
    color: rgba(var(--cpd-contrast-rgb), calc(0.35 * var(--cpd-text-alpha-scale)));
}
/* /Components/ClientErrorHost.razor.rz.scp.css */
/*
    The same three rules ErrorDetailsHost.razor.css carries, because scoped CSS is scoped to the
    component that declares it: the server dialog's stylesheet does not reach this one, and without
    these the stack trace renders in a two-row textarea nobody can read.

    Deliberately a subset, not a copy. The metadata list and the copy row keep the server's class
    names (so they inherit the same design tokens, which are document-global) but this dialog has no
    redacted variant, so there is nothing here for it. The custom properties - --cpd-space-*,
    --cpd-contrast-rgb, --cpd-font-mono, --cpd-radius-md - are written onto the document by the
    server chrome's theme provider and inherit into this subtree like any other CSS.
*/

.cpd-error-modal-meta[b-kzvirfregk] {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.25rem var(--cpd-space-md);
    margin-bottom: var(--cpd-space-lg);
}

.cpd-error-modal-meta dt[b-kzvirfregk] {
    font-weight: 600;
    opacity: 0.7;
}

.cpd-error-modal-meta dd[b-kzvirfregk] {
    margin: 0;
}

.cpd-error-modal-copy-row[b-kzvirfregk] {
    display: flex;
    align-items: center;
    gap: var(--cpd-space-sm);
    margin-bottom: var(--cpd-space-sm);
}

.cpd-error-modal-trace[b-kzvirfregk] {
    width: 100%;
    min-height: 20rem;
    max-height: 50vh;
    resize: vertical;
    font-family: var(--cpd-font-mono);
    font-size: 0.85rem;
    white-space: pre;
    background: rgba(var(--cpd-contrast-rgb), 0.06);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.18);
    border-radius: var(--cpd-radius-md);
    color: inherit;
    padding: var(--cpd-space-md);
}
/* /Components/PageDescription/PageRenderer.razor.rz.scp.css */
/* The renderer root is a named query container so the pane layout below can ask how much room
   IT has rather than how wide the viewport is - the two differ by the sidebar's width, which the
   user can flip between 250px and 56px at any moment. Named, because SummaryTile's own root is
   an (unnamed) inline-size container too and an unnamed @container would resolve to whichever is
   nearest. */
.page-renderer[b-hj3k3nuptm] {
    container-type: inline-size;
    container-name: page-renderer;
}

/* Replaces MudBlazor's `pa-4` on the flat tile so the padding follows the density tokens; the
   `mb-4` beside it is unchanged, being tile SEPARATION rather than tile density. */
.page-tile[b-hj3k3nuptm] {
    padding: var(--cpd-tile-pad);
}

.page-tile-header[b-hj3k3nuptm] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 0.75rem;
}

.page-tile-header-controls[b-hj3k3nuptm] {
    display: flex;
    gap: 0.5rem;
}

/* The optional two-column flat-tile layout (PageRenderer.RailTileIds): a fixed-width capture rail
   beside a column that takes whatever is left. minmax(0, 1fr) rather than 1fr on the main column so
   a wide child that cannot shrink (a schedule grid, an SVG chart) scrolls inside its own tile
   instead of forcing the whole grid wider and pushing the rail off-screen — the classic
   grid-blowout. The rail collapses to a full-width row on narrow viewports, where a 330px gutter
   plus a results column is unreadable; 1100px is where the results column stops fitting a
   twelve-column schedule grid. */
.page-renderer-rail-layout[b-hj3k3nuptm] {
    display: grid;
    grid-template-columns: 330px minmax(0, 1fr);
    gap: 1.5rem;
    align-items: start;
}

.page-renderer-rail[b-hj3k3nuptm],
.page-renderer-rail-main[b-hj3k3nuptm] {
    min-width: 0;
}

@media (max-width: 1100px) {
    .page-renderer-rail-layout[b-hj3k3nuptm] {
        grid-template-columns: minmax(0, 1fr);
    }
}

.page-tile-pane-layout[b-hj3k3nuptm] {
    display: flex;
    gap: var(--cpd-tile-gap);
    align-items: flex-start;
}

/* Independent verticals (owner-reported shakedown bug): before this, `.page-tile-pane-left` and
   `.page-tile-pane-right` were two flex-row siblings with NO height cap of their own, so the row's
   rendered height was simply `max(left, right)` and the page's single scroller (`article.content`
   in MainLayout.razor.css) carried both. Two symptoms fell out of that one fact: opening a tall
   pane (the trade editor, easily taller than the five-card rail) grew the row past the rail's own
   height, so the rail's `align-items: flex-start` top-alignment held but everything BELOW the row —
   the next tile, the xVA lens section Capture.razor renders as a sibling — got pushed down by
   however tall the pane happened to be; closing that pane the row shrank back to whatever the OTHER
   column measured, so a tall rail and a closed/short pane left a wide blank rectangle beside the
   rail before that same next-sibling content, reported as "a big empty gap when xVA is shown".
   Neither column should be able to move or resize the other at all - capping each one's OWN box at
   a generous share of the viewport and giving it its own scrollbar (rather than leaving either
   uncapped) makes the pair genuinely independent: the tallest either column's rendered box can ever
   get is this cap, so nothing past this row ever shifts because of what is open in either column,
   and a short/empty column just renders short - it no longer borrows height from its sibling.
   4.75rem matches the `calc(100vh - 4.75rem)` app.css already uses for "viewport minus the top-row
   chrome" (wwwroot/app.css's `.hero`); it undercounts whatever this renderer's own title row/topbar/
   alerts/flat tiles add above the pane row, so on a short viewport the box can still run a little
   past the fold before its OWN scrollbar takes over - preferable to a host-specific magic number,
   since PageRenderer has no idea which page (or how much chrome) sits above it. Reset to `none`/
   normal flow below the ~1000px breakpoint (see the container query), where the rail collapses to a
   wrapping strip and a second, viewport-height scroller per column would just be two unreadably
   short boxes, not two panes worth scrolling independently. */
.page-tile-pane-left[b-hj3k3nuptm] {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--cpd-tile-gap);
    max-height: calc(100vh - 4.75rem);
    overflow-y: auto;
}

.page-tile-pane-right[b-hj3k3nuptm] {
    flex: 0 0 var(--cpd-pane-rail-w);
    display: flex;
    flex-direction: column;
    gap: var(--cpd-tile-gap);
    max-height: calc(100vh - 4.75rem);
    overflow-y: auto;
}

/* When the pane layout has under ~1000px the 280px rail plus a detail pane no longer fit:
   the summary tiles become a wrapping strip ABOVE the detail pane instead. This is a
   container query, not a media query, so it also fires when the sidebar expands. */
@container page-renderer (max-width: 999.98px) {
    /* align-items has to be overridden, not just the direction. The row layout sets
       `flex-start` so the rail does not stretch to the detail pane's height; in COLUMN mode that
       same value is a cross-axis WIDTH constraint, so both children shrink-to-fit and the strip
       of summary tiles collapsed to ~28px wide - one word per line. Stretch is the column
       equivalent of what flex-start meant in a row. */
    .page-tile-pane-layout[b-hj3k3nuptm] { flex-direction: column; align-items: stretch; }

    /* The independent-scroller cap above is a WIDE-layout device only: stacked into one column,
       the strip-plus-pane is already read top-to-bottom by the page's own scroller, and capping
       either box to a viewport fraction here would just produce two cramped, separately-scrolling
       boxes stacked on top of each other instead of one readable column. */
    .page-tile-pane-left[b-hj3k3nuptm],
    .page-tile-pane-right[b-hj3k3nuptm] {
        max-height: none;
        overflow-y: visible;
    }

    .page-tile-pane-right[b-hj3k3nuptm]  { order: -1; flex: none; flex-direction: row; flex-wrap: wrap; }

    /* SummaryTile's root .summary-tile, so ::deep is required and the child combinator is NOT
       enough: the isolation rewriter appends the scope attribute to the LAST compound selector,
       so a bare `.page-tile-pane-right > *` compiles to `.page-tile-pane-right > *[b-<hash>]` -
       asking the child to carry THIS component's scope, which a child component's root never
       does. Verified in the emitted bundle; with ::deep it compiles to
       `.page-tile-pane-right[b-<hash>] > *`, which is the intended meaning.

       260px, not 220: a tile in this strip is itself a query container, and XvaTile's and
       SensitivityTile's stat grids drop to one column below 240px. A 220px basis put a wrapped
       tile the wrong side of that line, so the strip that exists to use the extra width
       rendered its figures stacked. 260 keeps every strip tile clear of the threshold. */
    .page-tile-pane-right[b-hj3k3nuptm] >  * { flex: 1 1 260px; min-width: 0; }
}

[b-hj3k3nuptm] .page-description-error {
    border: 1px dashed var(--mud-palette-error, #d32f2f);
    color: var(--mud-palette-error, #d32f2f);
    padding: 0.5rem 0.75rem;
    border-radius: 4px;
    font-weight: 600;
}

[b-hj3k3nuptm] .page-key-values-row {
    display: flex;
    justify-content: space-between;
    gap: 0.5rem;
}

[b-hj3k3nuptm] .page-field-select {
    min-width: var(--cpd-field-min);
}

/* Body.ControlGroup is a short field set (a Designation pane's three fields, a Details pane's
   legal name + recovery rate) — it had no CSS at all, so its MudTextField/MudSelect/MudNumericField
   children stacked one per line like a long form instead of sitting together as the short row they
   are. A wrapping flex row is the fix everywhere at once: fields sit side by side on a normal
   desktop width, and drop to their own line only when the row genuinely runs out of room, rather
   than every page hand-rolling its own MudStack/MudGrid wrapper for this. This is now the layout
   contract for every form section in the app — no per-page CSS should be needed on top of it. */
[b-hj3k3nuptm] .page-control-group {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--cpd-tile-gap);
}

/* --cpd-field-min matches .page-field-select's own min-width so a select's longest option still
   fits before the row wraps; the --cpd-field-max cap stops a lone short field (a numeric recovery
   rate) from stretching to fill whatever space the row has left, which read as "the field is
   broken", not "the field is short". Both tighten together under compact density (220/320 ->
   180/280), so the pair keeps that relationship at either density. */
[b-hj3k3nuptm] .page-control-group > * {
    flex: 1 1 var(--cpd-field-min);
    max-width: var(--cpd-field-max);
}

[b-hj3k3nuptm] .page-grid {
    width: 100%;
    border-collapse: collapse;
}

[b-hj3k3nuptm] .page-grid-row-nav {
    cursor: pointer;
}

/* The row's icon buttons are a single horizontal cluster, never a stack. Without this they are
   inline-blocks that wrap inside the (narrow, content-sized) sticky column — on Trades/View, whose
   rows carry three lens links plus a hedge link, they stacked one-per-line and quadrupled every
   row's height. nowrap makes the column size to the cluster instead of the cluster to the column. */
[b-hj3k3nuptm] .page-grid-row-controls {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 0.125rem;
}

/* A sticky column floats over the cells it covers, so it needs its own opaque background or the
   scrolled-under text shows through the lens icons. MudBlazor's own sticky styling assumes the
   default surface colour; this app themes the grid darker, hence the explicit surface token. The
   left border is what tells you the column is pinned rather than merely last.

   Specificity, not just source order: MudBlazor ships its own
   `.mud-data-grid .mud-table-cell.sticky-left, .mud-data-grid .mud-table-cell.sticky-right`
   rule (3 classes = 0,3,0) setting `background-color: var(--mud-palette-background-gray)` — its
   dark-theme default grey (#27272f), which clashes with this app's navy `--mud-palette-surface`.
   A plain `.page-grid-controls-header`/`.page-grid-controls-cell` selector (0,2,0) LOSES to that
   rule regardless of source order, so the pinned actions column rendered as a grey band on the
   Trades list and inside the hedge Composition pane. Repeating MudBlazor's own selector shape here
   plus our own marker class (0,4,0) beats it on specificity instead of relying on cascade order,
   which a future "simplify this selector" pass could silently break. Don't shorten this back to
   `.page-grid-controls-header`/`.page-grid-controls-cell` alone. */
[b-hj3k3nuptm] .mud-data-grid .mud-table-cell.sticky-right.page-grid-controls-header,
[b-hj3k3nuptm] .mud-data-grid .mud-table-cell.sticky-right.page-grid-controls-cell {
    background-color: var(--mud-palette-surface);
    border-left: 1px solid var(--mud-palette-table-lines);
}

[b-hj3k3nuptm] .mud-table-row:hover .mud-table-cell.sticky-right.page-grid-controls-cell {
    background-color: var(--mud-palette-table-hover);
}

[b-hj3k3nuptm] .tone-good {
    color: var(--mud-palette-success, #2e7d32);
}

[b-hj3k3nuptm] .tone-attention {
    color: var(--mud-palette-warning, #ed6c02);
}

[b-hj3k3nuptm] .tone-bad {
    color: var(--mud-palette-error, #d32f2f);
}

[b-hj3k3nuptm] .tone-neutral {
    color: inherit;
}
/* /Components/Pages/Analytics/LensScopePicker.razor.rz.scp.css */
/* The dropdown row: the identifier, and the muted trade count (plus a stored portfolio's
   description) beneath it. The row template exists because the detail must not reach the box after a
   pick — see LensScopeCandidate — so these two rules are what make the second line read as a caption
   rather than as part of the name.

   Scoped, not global, for the reason DECISIONS.md #50 gives for `@Assets`: a component in
   CPStudio.Client must not depend on a host `wwwroot` stylesheet for its own layout. The rest of this
   component's chrome (.scope-picker, .scope-picker-category, .scope-picker-item) is deliberately
   *not* here: those classes are the server ScopePicker's own, served document-wide, and duplicating
   them would make the two pickers drift apart visually while the two components still coexist. */

.scope-picker-option[b-3hiza2xh7y] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.scope-picker-option-label[b-3hiza2xh7y] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.scope-picker-option-detail[b-3hiza2xh7y] {
    font-size: 11px;
    letter-spacing: 0.02em;
    color: var(--cpd-text-subtle);
}
/* /Components/Pages/Analytics/Recon.razor.rz.scp.css */
.recon-card[b-mzgjdjgi11] {
    animation: fadeUp-b-mzgjdjgi11 0.3s cubic-bezier(0.16, 1, 0.3, 1) both 0.04s;
}

@keyframes fadeUp-b-mzgjdjgi11 {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

.recon-topbar[b-mzgjdjgi11] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 20px;
    gap: 12px;
    flex-wrap: wrap;
}

.recon-title-group[b-mzgjdjgi11] {
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 32px;
    flex-wrap: wrap;
}

.recon-title-block[b-mzgjdjgi11] {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.recon-page-title[b-mzgjdjgi11] {
    font-size: 20px;
    font-weight: 700;
    color: var(--cpd-contrast);
    letter-spacing: -0.03em;
}

/* Matches the secondary-coloured subtitle every Page-DU analytics lens gets for free from
   PageRenderer's Typo.body2/Color.Secondary title row — this file already uses the same
   rgba(255, 255, 255, *) scale for muted text elsewhere (.recon-date-label, .recon-empty-hint), so
   this follows that established convention rather than introducing a new token. */
.recon-page-subtitle[b-mzgjdjgi11] {
    font-size: 13px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.55 * var(--cpd-text-alpha-scale)));
}

.recon-status-chip[b-mzgjdjgi11] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    background: rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.06);
    border: 1px solid rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.25);
    border-radius: 6px;
    font-family: var(--cpd-font-mono);
    font-size: 12px;
    color: var(--cpd-contrast);
}

.recon-status-chip i[b-mzgjdjgi11] {
    color: var(--cpd-gold);
    font-size: 13px;
}

.recon-status-count[b-mzgjdjgi11] {
    color: rgba(var(--cpd-contrast-rgb), calc(0.5 * var(--cpd-text-alpha-scale)));
}

.recon-scope-clear[b-mzgjdjgi11] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    color: inherit;
    opacity: 0.6;
    cursor: pointer;
    padding: 0;
    margin-left: 2px;
    font-size: 11px;
}

.recon-scope-clear:hover[b-mzgjdjgi11] {
    opacity: 1;
    color: var(--cpd-gold);
}

.recon-meta-group[b-mzgjdjgi11] {
    display: flex;
    align-items: center;
    gap: 10px;
}

.recon-date-label[b-mzgjdjgi11] {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.45 * var(--cpd-text-alpha-scale)));
    margin: 0;
}

.recon-tolerance-group[b-mzgjdjgi11] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 0 6px 0 0;
    border-right: 1px solid rgba(var(--cpd-contrast-rgb), 0.08);
    margin-right: 2px;
}

.recon-tolerance-value[b-mzgjdjgi11] {
    background: rgba(var(--cpd-contrast-rgb), 0.04);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.12);
    color: var(--cpd-contrast);
    border-radius: 6px;
    padding: 6px 8px;
    font-family: var(--cpd-font-mono);
    font-size: 13px;
    width: 90px;
}

.recon-tolerance-mode[b-mzgjdjgi11] {
    background: rgba(var(--cpd-contrast-rgb), 0.04);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.12);
    color: var(--cpd-contrast);
    border-radius: 6px;
    padding: 6px 8px;
    font-family: var(--cpd-font-mono);
    font-size: 13px;
}

.recon-tolerance-value:focus[b-mzgjdjgi11],
.recon-tolerance-mode:focus[b-mzgjdjgi11] {
    outline: none;
    border-color: var(--cpd-gold);
    box-shadow: 0 0 0 2px rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.15);
}

.recon-date-select[b-mzgjdjgi11] {
    background: rgba(var(--cpd-contrast-rgb), 0.04);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.12);
    color: var(--cpd-contrast);
    border-radius: 6px;
    padding: 6px 10px;
    font-family: var(--cpd-font-mono);
    font-size: 13px;
    min-width: 160px;
}

.recon-date-select:focus[b-mzgjdjgi11] {
    outline: none;
    border-color: var(--cpd-gold);
    box-shadow: 0 0 0 2px rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.15);
}

.recon-table-card[b-mzgjdjgi11] {
    background: linear-gradient(135deg, rgba(var(--cpd-dark-rgb), 0.95) 0%, rgba(var(--cpd-panel-sheen-rgb), 0.95) 100%);
    border: 1px solid var(--cpd-gold-strong);
    border-radius: var(--cpd-radius-xl);
    box-shadow: var(--cpd-shadow-card);
    padding: 0.5rem 0;
    overflow-x: auto;
}

.recon-table[b-mzgjdjgi11] {
    width: 100%;
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
}

.recon-table thead th[b-mzgjdjgi11] {
    background: rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.05);
    color: var(--cpd-gold);
    font-weight: 600;
    text-transform: uppercase;
    font-size: 0.78rem;
    letter-spacing: 0.5px;
    border-bottom: 2px solid var(--cpd-gold-border);
    padding: 0;
    white-space: nowrap;
    text-align: left;
}

.recon-table thead th:first-child[b-mzgjdjgi11] { padding-left: 0.4rem; }
.recon-table thead th:last-child[b-mzgjdjgi11]  { padding-right: 0.4rem; }

.recon-sort-btn[b-mzgjdjgi11] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: 0.7rem 0.85rem;
    background: transparent;
    border: none;
    color: inherit;
    font: inherit;
    text-transform: inherit;
    letter-spacing: inherit;
    cursor: pointer;
    text-align: left;
}

.recon-sort-btn.num[b-mzgjdjgi11] {
    justify-content: flex-end;
    text-align: right;
}

/* ::deep is required here. The sort icon is rendered from Recon.razor.cs rather than
   from this component's .razor markup, so it never receives the scope attribute that
   scoped CSS rewrites these selectors to expect — without ::deep these three rules
   match nothing, which is why the sort indicators were previously unstyled.
   Sizing is width/height rather than font-size because the icon is now inline SVG. */
.recon-sort-btn:hover[b-mzgjdjgi11]  .recon-sort-icon {
    color: var(--cpd-gold);
    opacity: 1;
}

.recon-sort-btn[b-mzgjdjgi11]  .recon-sort-icon {
    width: 14px;
    height: 14px;
    color: var(--cpd-gold);
    opacity: 0.85;
}

.recon-sort-btn[b-mzgjdjgi11]  .recon-sort-icon.recon-sort-idle {
    opacity: 0.25;
}

.recon-table tbody td[b-mzgjdjgi11] {
    color: var(--cpd-text);
    background: transparent;
    border-bottom: 1px solid var(--cpd-border-subtle);
    padding: 0.55rem 0.85rem;
    font-family: var(--cpd-font-mono);
    font-size: 13px;
}

.recon-table tbody tr:hover td[b-mzgjdjgi11] {
    background: var(--cpd-gold-faint);
}

.recon-table tbody td:first-child[b-mzgjdjgi11],
.recon-table thead th:first-child[b-mzgjdjgi11] { padding-left: 1.25rem; }

.recon-table tbody td:last-child[b-mzgjdjgi11],
.recon-table thead th:last-child[b-mzgjdjgi11]  { padding-right: 1.25rem; }

.recon-table .col-text[b-mzgjdjgi11]  { width: 1%; white-space: nowrap; }
.recon-table .col-date[b-mzgjdjgi11]  { width: 1%; white-space: nowrap; }
.recon-table .col-ccy[b-mzgjdjgi11]   { width: 1%; white-space: nowrap; }
.recon-table .col-action[b-mzgjdjgi11]{ width: 1%; white-space: nowrap; text-align: right; }
.recon-table .num[b-mzgjdjgi11]       { text-align: right; white-space: nowrap; }

.recon-ccy-cell[b-mzgjdjgi11] {
    font-family: var(--cpd-font-mono);
    font-size: 12px;
    letter-spacing: 0.05em;
    color: rgba(var(--cpd-contrast-rgb), calc(0.7 * var(--cpd-text-alpha-scale)));
}

.recon-ccy-cell.ccy-multi[b-mzgjdjgi11] {
    color: var(--cpd-gold);
    cursor: help;
    border-bottom: 1px dotted rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.4);
}

.recon-chevron-btn[b-mzgjdjgi11] {
    background: transparent;
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.10);
    color: rgba(var(--cpd-contrast-rgb), calc(0.5 * var(--cpd-text-alpha-scale)));
    width: 28px;
    height: 28px;
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background .15s, color .15s, border-color .15s;
}

.recon-chevron-btn:hover[b-mzgjdjgi11] {
    background: rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.10);
    border-color: rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.5);
    color: var(--cpd-gold);
}

.recon-table tfoot tr.recon-total-foot td[b-mzgjdjgi11] {
    border-top: 2px solid var(--cpd-gold-border);
    background: rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.05);
    color: var(--cpd-contrast);
    font-family: var(--cpd-font-mono);
    font-size: 14px;
    font-weight: 600;
    padding: 0.85rem 0.85rem;
}

.recon-table tfoot tr.recon-total-foot + tr.recon-total-foot td[b-mzgjdjgi11] {
    border-top: 1px solid var(--cpd-gold-border);
}

.recon-table tfoot td.recon-total-label[b-mzgjdjgi11] {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--cpd-gold);
}

.recon-empty-row td[b-mzgjdjgi11] {
    padding: 0 !important;
}

.recon-empty-state[b-mzgjdjgi11] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 3rem 1rem;
    text-align: center;
}

.recon-empty-icon[b-mzgjdjgi11] {
    font-size: 32px;
    color: rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.35);
}

.recon-empty-title[b-mzgjdjgi11] {
    font-size: 15px;
    font-weight: 600;
    color: var(--cpd-contrast);
}

.recon-empty-hint[b-mzgjdjgi11] {
    font-size: 13px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.45 * var(--cpd-text-alpha-scale)));
    max-width: 480px;
}

.recon-error[b-mzgjdjgi11] {
    margin-bottom: 14px;
    padding: 10px 14px;
    background: var(--token-position-bg);
    border: 1px solid var(--token-position-border);
    border-radius: 8px;
    color: var(--token-position);
    font-size: 13px;
}

.recon-error-cell[b-mzgjdjgi11] {
    font-family: var(--cpd-font-sans);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--token-position);
    padding: 2px 8px;
    background: var(--token-position-bg);
    border-radius: 10px;
    border: 1px solid var(--token-position-border);
    cursor: help;
}

.recon-total-note[b-mzgjdjgi11] {
    margin-top: 10px;
    padding: 8px 14px;
    font-size: 12px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.55 * var(--cpd-text-alpha-scale)));
    border-left: 2px solid rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.3);
    background: rgba(var(--cpd-contrast-rgb), 0.02);
    border-radius: 4px;
}

.recon-total-note strong[b-mzgjdjgi11] {
    color: var(--cpd-contrast);
    font-weight: 600;
}

.val-zero[b-mzgjdjgi11]          { color: rgba(var(--cpd-contrast-rgb), calc(0.45 * var(--cpd-text-alpha-scale))); }
.val-within-tolerance[b-mzgjdjgi11] { color: rgba(var(--cpd-contrast-rgb), calc(0.55 * var(--cpd-text-alpha-scale))); }
.val-breach[b-mzgjdjgi11]        { color: var(--token-position); font-weight: 600; }
.val-neutral[b-mzgjdjgi11]       { color: rgba(var(--cpd-contrast-rgb), calc(0.45 * var(--cpd-text-alpha-scale))); }

/* Added by W4.7b, with the move into the browser. Two things the server version of this page did not
   need: a date control of its own (the shell's bar rendered one for it, and renders nothing on a
   migrated page — DECISIONS.md #25) and a three-state status line (#53). */

.recon-date-group[b-mzgjdjgi11] {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* `::deep`, because `.recon-date-select` is on a MudSelect — a child component — and scoped CSS only
   stamps its attribute on elements this component's own markup emits. Written without it first, and the
   browser pass is what found it: `getComputedStyle` read `min-width: 0px` where the rule says 160px,
   which is exactly the failure DECISIONS.md #39 records and #56 built the computed-style check for. A
   rendered page looks identical either way. */
.recon-date-group[b-mzgjdjgi11]  .recon-date-select {
    min-width: 160px;
}

/* The same rule as .recon-status, .hedges-status, .test-defaults-status and .instrument-status, and a
   deliberate fifth copy rather than a shared global class for the reason Hedges.razor.css records:
   scoped CSS is per-component here, and a global .cpd-status-line would make five WebAssembly pages
   depend on a host asset for their own layout. Five copies is where that trade stops being obvious —
   consolidating them is a follow-up, and it is one sweep across five files rather than a fifth of one. */
.recon-list-status[b-mzgjdjgi11] {
    margin: 12px 0 0;
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--cpd-text-subtle);
}
/* /Components/Pages/Analytics/ReconTrade.razor.rz.scp.css */
.recon-card[b-aehpfswsl6] {
    animation: fadeUp-b-aehpfswsl6 0.3s cubic-bezier(0.16, 1, 0.3, 1) both 0.04s;
}

@keyframes fadeUp-b-aehpfswsl6 {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

.recon-topbar[b-aehpfswsl6] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 20px;
    gap: 12px;
    flex-wrap: wrap;
}

.recon-title-group[b-aehpfswsl6] {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 32px;
}

.recon-page-title[b-aehpfswsl6] {
    font-size: 20px;
    font-weight: 700;
    color: var(--cpd-contrast);
    letter-spacing: -0.03em;
}

.recon-back-link[b-aehpfswsl6] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 6px;
    background: rgba(var(--cpd-contrast-rgb), 0.04);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.10);
    color: rgba(var(--cpd-contrast-rgb), calc(0.55 * var(--cpd-text-alpha-scale)));
    font-size: 14px;
    text-decoration: none;
    transition: background .15s, color .15s, border-color .15s;
}

.recon-back-link:hover[b-aehpfswsl6] {
    background: var(--cpd-gold-ring);
    border-color: rgba(var(--cpd-gold-rgb), 0.5);
    color: var(--cpd-gold);
}

.recon-meta-group[b-aehpfswsl6] {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.recon-chip[b-aehpfswsl6] {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    background: rgba(var(--cpd-contrast-rgb), 0.03);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.10);
    border-radius: 8px;
}

.recon-chip-label[b-aehpfswsl6] {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--cpd-text-subtle);
}

.recon-chip-value[b-aehpfswsl6] {
    font-family: var(--cpd-font-mono);
    font-size: 13px;
    font-weight: 500;
    color: var(--cpd-contrast);
}

.recon-date-input[b-aehpfswsl6] {
    background: transparent;
    border: none;
    color: var(--cpd-contrast);
    padding: 0;
    font-family: var(--cpd-font-mono);
    font-size: 13px;
}

.recon-date-input:focus[b-aehpfswsl6] {
    outline: none;
}

.recon-detail-card[b-aehpfswsl6] {
    background: linear-gradient(135deg, rgba(var(--cpd-dark-rgb), 0.95) 0%, rgba(var(--cpd-panel-sheen-rgb), 0.95) 100%);
    border: 1px solid var(--cpd-gold-strong);
    border-radius: var(--cpd-radius-xl);
    padding: var(--cpd-space-lg) 1.25rem;
    box-shadow: var(--cpd-shadow-card);
    overflow-x: auto;
}

.recon-table[b-aehpfswsl6] {
    width: 100%;
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
}

.recon-table thead th[b-aehpfswsl6] {
    background: rgba(var(--cpd-gold-rgb), 0.05);
    color: var(--cpd-gold);
    font-weight: 600;
    text-transform: uppercase;
    font-size: 0.85rem;
    letter-spacing: 0.5px;
    border-bottom: 2px solid var(--cpd-gold-border);
    padding: 0.85rem var(--cpd-space-lg);
    text-align: left;
}

.recon-table th.num[b-aehpfswsl6],
.recon-table td.num[b-aehpfswsl6] {
    text-align: right;
    white-space: nowrap;
}

.recon-table tbody td[b-aehpfswsl6] {
    padding: 0.7rem 1rem;
    color: var(--cpd-contrast);
    border-bottom: 1px solid rgba(var(--cpd-contrast-rgb), 0.05);
    font-family: var(--cpd-font-mono);
    font-size: 13px;
}

.recon-table tbody tr:hover td[b-aehpfswsl6] {
    background: var(--cpd-gold-faint);
}

.recon-table .col-date[b-aehpfswsl6] { white-space: nowrap; width: 1%; }
.recon-table .col-match[b-aehpfswsl6] { white-space: nowrap; width: 1%; }
.recon-table .col-ccy[b-aehpfswsl6] { white-space: nowrap; width: 1%; color: rgba(var(--cpd-contrast-rgb), calc(0.6 * var(--cpd-text-alpha-scale))); letter-spacing: 0.05em; }

.recon-empty[b-aehpfswsl6] {
    text-align: center;
    padding: 2.5rem 1rem;
    color: rgba(var(--cpd-contrast-rgb), calc(0.35 * var(--cpd-text-alpha-scale)));
    font-style: italic;
    font-family: inherit;
}

.recon-total-foot td[b-aehpfswsl6] {
    padding: 0.85rem var(--cpd-space-lg);
    border-top: 2px solid var(--cpd-gold-border);
    background: var(--cpd-gold-faint);
    color: var(--cpd-text);
    font-family: var(--cpd-font-mono);
    font-size: 14px;
    font-weight: 600;
}

.recon-total-foot td.num[b-aehpfswsl6] {
    text-align: right;
}

.recon-total-foot-diff[b-aehpfswsl6] {
    margin-right: 12px;
}

.recon-total-foot-label[b-aehpfswsl6] {
    font-family: var(--cpd-font-sans);
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--cpd-gold);
}

.val-positive[b-aehpfswsl6] { color: var(--token-rate); }
.val-negative[b-aehpfswsl6] { color: var(--token-position); }
.val-neutral[b-aehpfswsl6]  { color: rgba(var(--cpd-contrast-rgb), calc(0.45 * var(--cpd-text-alpha-scale))); }
.val-zero[b-aehpfswsl6]          { color: rgba(var(--cpd-contrast-rgb), calc(0.45 * var(--cpd-text-alpha-scale))); }
.val-within-tolerance[b-aehpfswsl6] { color: rgba(var(--cpd-contrast-rgb), calc(0.55 * var(--cpd-text-alpha-scale))); }
.val-breach[b-aehpfswsl6]        { color: var(--token-position); font-weight: 600; }

.recon-view-trade-link[b-aehpfswsl6] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    background: rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.06);
    border: 1px solid rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.25);
    border-radius: 6px;
    color: var(--cpd-contrast);
    font-size: 12px;
    text-decoration: none;
    transition: background .15s, border-color .15s, color .15s;
}

.recon-view-trade-link:hover[b-aehpfswsl6] {
    background: rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.12);
    border-color: var(--cpd-gold);
    color: var(--cpd-gold);
}

.recon-view-trade-link i[b-aehpfswsl6] {
    font-size: 12px;
    color: var(--cpd-gold);
}

.recon-tolerance-group[b-aehpfswsl6] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    background: rgba(var(--cpd-contrast-rgb), 0.03);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.10);
    border-radius: 8px;
}

.recon-tolerance-value[b-aehpfswsl6] {
    background: rgba(var(--cpd-contrast-rgb), 0.04);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.12);
    color: var(--cpd-contrast);
    border-radius: 6px;
    padding: 4px 8px;
    font-family: var(--cpd-font-mono);
    font-size: 13px;
    width: 80px;
}

.recon-tolerance-mode[b-aehpfswsl6] {
    background: rgba(var(--cpd-contrast-rgb), 0.04);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.12);
    color: var(--cpd-contrast);
    border-radius: 6px;
    padding: 4px 8px;
    font-family: var(--cpd-font-mono);
    font-size: 13px;
}

.recon-tolerance-value:focus[b-aehpfswsl6],
.recon-tolerance-mode:focus[b-aehpfswsl6] {
    outline: none;
    border-color: var(--cpd-gold);
    box-shadow: 0 0 0 2px rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.15);
}

.recon-fuzzy-banner[b-aehpfswsl6] {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 14px;
    padding: 10px 14px;
    background: rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.06);
    border: 1px solid rgba(var(--cpd-gold-rgb, 246, 212, 107), 0.3);
    border-radius: 8px;
    color: var(--cpd-contrast);
    font-size: 13px;
}

.recon-fuzzy-banner i[b-aehpfswsl6] {
    color: var(--cpd-gold);
    font-size: 14px;
}

.recon-fuzzy-banner strong[b-aehpfswsl6] {
    color: var(--cpd-gold);
}

.recon-fuzzy-banner-hint[b-aehpfswsl6] {
    color: rgba(var(--cpd-contrast-rgb), calc(0.55 * var(--cpd-text-alpha-scale)));
}

.recon-date-stack[b-aehpfswsl6] {
    display: inline-flex;
    flex-direction: column;
    line-height: 1.25;
}

.recon-date-stack .recon-date-stored[b-aehpfswsl6] {
    font-size: 12px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.55 * var(--cpd-text-alpha-scale)));
}

.recon-date-stack .recon-date-live[b-aehpfswsl6] {
    font-size: 13px;
    color: var(--cpd-contrast);
}

.match-exact[b-aehpfswsl6],
.match-fuzzy[b-aehpfswsl6],
.match-stored[b-aehpfswsl6],
.match-live[b-aehpfswsl6] {
    display: inline-block;
    font-family: var(--cpd-font-sans);
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 2px 8px;
    border-radius: 10px;
    border: 1px solid transparent;
}

.match-exact[b-aehpfswsl6]   { color: var(--token-rate);     background: var(--token-rate-bg);     border-color: var(--token-rate-border); }
.match-fuzzy[b-aehpfswsl6]   { color: var(--cpd-gold);       background: var(--cpd-gold-soft); border-color: var(--cpd-gold-border); }
.match-stored[b-aehpfswsl6]  { color: rgba(var(--cpd-contrast-rgb), calc(.55 * var(--cpd-text-alpha-scale))); background: rgba(var(--cpd-contrast-rgb),.04);    border-color: rgba(var(--cpd-contrast-rgb),.10); }
.match-live[b-aehpfswsl6]    { color: var(--token-position); background: var(--token-position-bg); border-color: var(--token-position-border); }

.recon-error[b-aehpfswsl6] {
    margin-bottom: 14px;
    padding: 10px 14px;
    background: var(--token-position-bg);
    border: 1px solid var(--token-position-border);
    border-radius: 8px;
    color: var(--token-position);
    font-size: 13px;
}

.recon-warn[b-aehpfswsl6] {
    margin-bottom: 14px;
    padding: 10px 14px;
    background: var(--cpd-gold-soft);
    border: 1px solid var(--cpd-gold-border);
    border-radius: var(--cpd-radius-lg);
    color: var(--cpd-text);
    font-size: 13px;
}

.recon-warn strong[b-aehpfswsl6] { color: var(--cpd-gold); }
.recon-warn-detail[b-aehpfswsl6] { color: rgba(var(--cpd-contrast-rgb), calc(0.55 * var(--cpd-text-alpha-scale))); }

/* The three-state load line (DECISIONS.md #36). Quiet by design — it is a status, not a heading —
   and it is also the element the W4.6 browser smoke run measures a computed style on, so a
   CPStudio.Client.styles.css that stopped being linked (DECISIONS.md #39) shows up as
   `font-size: 16px` rather than as a page that merely looks a little different. */
.recon-status[b-aehpfswsl6] {
    margin: 12px 0 0;
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--cpd-text-subtle);
}
/* /Components/Pages/Analytics/Sensitivities.razor.rz.scp.css */
/* The three-state load line (DECISIONS.md #53). The same rule as `.recon-status`, `.recon-list-status`,
   `.hedges-status`, `.test-defaults-status` and `.instrument-status`, and a deliberate further copy
   rather than a shared global class for the reason Hedges.razor.css records: scoped CSS is per-component
   here, and a global `.cpd-status-line` would make every migrated page depend on a host `wwwroot` asset
   for its own layout — the coupling DECISIONS.md #50 argues against for `@Assets`.

   W4.7b takes the copy count from four to seven, which is where the trade stops being obvious.
   Consolidating them is a follow-up and is one sweep across seven files rather than a seventh of one;
   it is recorded in DECISIONS.md #65 rather than hidden. */
.sensitivities-status[b-u6qgqlv3mf] {
    margin: 12px 0 0;
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--cpd-text-subtle);
}
/* /Components/Pages/Analytics/Valuation.razor.rz.scp.css */
/* The three-state load line (DECISIONS.md #53) — see Sensitivities.razor.css for why this rule is
   written once per page rather than once for the app, and for the follow-up that would fix it. */
.valuation-status[b-sylxtrdayy] {
    margin: 12px 0 0;
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--cpd-text-subtle);
}
/* /Components/Pages/CPStudioBasePage.razor.rz.scp.css */
/* Scoped styles for CPStudioBasePage's own template (header, loading overlay).
   Page-level layout primitives (.page-container, .page-title, .summary-*,
   buttons) live in wwwroot/common-page-styles.css so child pages can share
   them. */

.page-container[b-m1pfm3ys3l] {
    position: relative;
}

.loading-overlay[b-m1pfm3ys3l] {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(var(--cpd-dark-rgb), 0.95);
    backdrop-filter: blur(10px);
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
}

.loading-content[b-m1pfm3ys3l] {
    text-align: center;
}

.spinner-container[b-m1pfm3ys3l] {
    margin-bottom: var(--cpd-space-2xl);
}

.spinner[b-m1pfm3ys3l] {
    width: 60px;
    height: 60px;
    border: 4px solid rgba(var(--cpd-gold-rgb), 0.2);
    border-top-color: var(--cpd-gold);
    border-radius: 50%;
    animation: spin-b-m1pfm3ys3l 1s linear infinite;
    margin: 0 auto;
}

.loading-text[b-m1pfm3ys3l] {
    color: var(--cpd-text);
    font-size: 1.1rem;
}

@keyframes spin-b-m1pfm3ys3l {
    to {
        transform: rotate(360deg);
    }
}

.option-select[b-m1pfm3ys3l] {
    padding: var(--cpd-space-sm) var(--cpd-space-lg);
    background: var(--cpd-surface-2);
    border: 1px solid var(--cpd-border-strong);
    border-radius: var(--cpd-radius-md);
    color: var(--cpd-text);
    min-width: 150px;
    transition: all var(--cpd-transition-slow);
}

.option-select:focus[b-m1pfm3ys3l] {
    outline: none;
    border-color: var(--cpd-gold);
    background: var(--cpd-surface-3);
    box-shadow: 0 0 0 3px var(--cpd-gold-ring);
}
/* /Components/Pages/Hedging/Hedges.razor.rz.scp.css */
/* The three-state load line (DECISIONS.md #53). Identical to `.recon-status` and
   `.instrument-status`, and deliberately a fourth copy rather than a shared global class: scoped CSS
   is per-component by design here, and a `.cpd-status-line` in the host's global stylesheet would
   make four WebAssembly pages depend on a host asset for their own layout — the coupling
   DECISIONS.md #50 has just finished arguing against for `@Assets`. Worth revisiting if a fifth
   page wants it; recorded as a follow-up rather than hidden. */
.hedges-status[b-sdxvaeksx2] {
    margin: 12px 0 0;
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--cpd-text-subtle);
}
/* /Components/Pages/Hedging/MacroHedgeDetail.razor.rz.scp.css */
/* The three-state load line (DECISIONS.md #53) — see Hedges.razor.css for why this rule is
   repeated per page rather than hoisted into a global class. */
.macro-hedge-detail-status[b-fiwv0la2r6] {
    margin: 12px 0 0;
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--cpd-text-subtle);
}
/* /Components/Pages/Hedging/TestDefaults.razor.rz.scp.css */
/* The three-state load line (DECISIONS.md #53) — see Hedges.razor.css for why this rule is
   repeated per page rather than hoisted into a global class. */
.test-defaults-status[b-wasil5h6ol] {
    margin: 12px 0 0;
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--cpd-text-subtle);
}
/* /Components/Pages/Market/InstrumentQuoteChart.razor.rz.scp.css */
.quote-chart[b-arvnr6qm0m] {
    min-height: 18rem;
    border: 1px solid var(--cpd-gold-strong);
    border-radius: var(--cpd-radius-xl);
    background: linear-gradient(135deg, rgba(var(--cpd-dark-rgb), 0.92), rgba(var(--cpd-panel-sheen-rgb), 0.92));
    padding: var(--cpd-space-md);
}

.quote-chart svg[b-arvnr6qm0m] {
    display: block;
    width: 100%;
    height: auto;
}

.axis[b-arvnr6qm0m] {
    stroke: var(--cpd-border-strong);
    stroke-width: 1;
}

.quote-line[b-arvnr6qm0m] {
    fill: none;
    stroke: var(--cpd-gold);
    stroke-width: 2.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.quote-point[b-arvnr6qm0m] {
    fill: var(--cpd-dark);
    stroke: var(--cpd-gold);
    stroke-width: 2;
}

.axis-label[b-arvnr6qm0m] {
    fill: var(--cpd-accent);
    font-size: 0.75rem;
}

.chart-empty[b-arvnr6qm0m] {
    min-height: 15rem;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    color: var(--cpd-accent);
}

.chart-empty i[b-arvnr6qm0m] {
    color: var(--cpd-gold);
}
/* /Components/Pages/Market/InstrumentSwitchOptions.razor.rz.scp.css */
.instrument-switch-options[b-j4ao4pvqrz] {
    display: flex;
    flex-direction: column;
    gap: var(--cpd-space-md);
    margin-bottom: var(--cpd-space-xl);
}

.instrument-switch-card[b-j4ao4pvqrz] {
    background: linear-gradient(135deg, rgba(var(--cpd-dark-rgb), 0.94), rgba(var(--cpd-panel-sheen-rgb), 0.94));
    border: 1px solid var(--cpd-gold-border);
    border-radius: var(--cpd-radius-lg);
    padding: var(--cpd-space-md);
}

.switch-label[b-j4ao4pvqrz] {
    display: block;
    color: var(--cpd-accent);
    font-size: 0.76rem;
    font-weight: 600;
    margin-bottom: var(--cpd-space-xs);
    text-transform: uppercase;
}

.hero-select[b-j4ao4pvqrz] {
    display: grid;
    grid-template-columns: minmax(12rem, 1fr) minmax(16rem, 24rem);
    gap: var(--cpd-space-md);
    align-items: center;
    border-left: 4px solid var(--cpd-gold);
}

.switch-copy[b-j4ao4pvqrz] {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}

.switch-copy strong[b-j4ao4pvqrz] {
    color: var(--cpd-contrast);
    font-size: 1.15rem;
}

.switch-copy span:last-child[b-j4ao4pvqrz] {
    color: var(--cpd-gold);
    font-size: 0.85rem;
}

.instrument-select[b-j4ao4pvqrz] {
    width: 100%;
    min-height: 2.6rem;
    border: 1px solid var(--cpd-gold-border);
    border-radius: var(--cpd-radius-md);
    background: rgba(var(--cpd-dark-rgb), 0.88);
    color: var(--cpd-contrast);
    padding: 0.45rem 0.65rem;
}

.instrument-select-hero[b-j4ao4pvqrz] {
    border-color: var(--cpd-gold);
    box-shadow: 0 0 0 3px var(--cpd-gold-ring);
}

.instrument-select:focus-visible[b-j4ao4pvqrz] {
    outline: 2px solid var(--cpd-gold);
    outline-offset: 2px;
}

@media (max-width: 767.98px) {
    .hero-select[b-j4ao4pvqrz] {
        grid-template-columns: 1fr;
    }
}
/* /Components/Pages/Market/InstrumentView.razor.rz.scp.css */
.history-table[b-fj0pge35lv] {
    width: auto;
}

.history-table-container[b-fj0pge35lv] {
    background: linear-gradient(135deg, rgba(var(--cpd-dark-rgb), 0.95) 0%, rgba(var(--cpd-panel-sheen-rgb), 0.95) 100%);
    border: 1px solid var(--cpd-gold-strong);
    border-radius: var(--cpd-radius-xl);
    overflow-x: auto;
    overflow-y: visible;
    box-shadow: var(--cpd-shadow-card);
    padding: var(--cpd-space-md);
}

.history-table-container[b-fj0pge35lv]  .pagination {
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    margin-top: 1rem;
    padding: 0.5rem 0;
}

.history-table-container[b-fj0pge35lv]  .page-item .page-link {
    background: transparent !important;
    border: 1px solid rgba(var(--cpd-gold-rgb), 0.4) !important;
    color: var(--cpd-gold) !important;
    font-weight: 500 !important;
    border-radius: var(--cpd-radius-lg) !important;
    padding: 0.4rem 0.8rem !important;
}

.history-table-container[b-fj0pge35lv]  .page-item .page-link:hover {
    background: var(--cpd-gold-ring) !important;
    border-color: var(--cpd-gold) !important;
    color: var(--cpd-contrast) !important;
}

.history-table-container[b-fj0pge35lv]  .page-item.active .page-link {
    background: var(--cpd-gold) !important;
    border-color: var(--cpd-gold) !important;
    color: var(--cpd-dark) !important;
}

.history-table-container[b-fj0pge35lv]  td,
.history-table-container[b-fj0pge35lv]  th {
    padding: 0.75rem 1rem !important;
    border: none !important;
}

.history-table-container[b-fj0pge35lv]  thead th {
    background: var(--cpd-gold-faint) !important;
    color: var(--cpd-gold) !important;
    font-weight: 600 !important;
    text-transform: uppercase !important;
    font-size: 0.85rem !important;
    letter-spacing: 0.5px !important;
    border-bottom: 2px solid var(--cpd-gold-border) !important;
}

.history-table-container[b-fj0pge35lv]  tbody td {
    color: var(--cpd-text) !important;
    background: transparent !important;
    border-bottom: 1px solid var(--cpd-border-subtle) !important;
    vertical-align: top !important;
}

.history-table-container[b-fj0pge35lv]  tbody tr:hover td {
    background: var(--cpd-gold-faint) !important;
}

.history-table-container[b-fj0pge35lv]  table {
    width: 100% !important;
    min-width: 72rem !important;
}

.history-table-container[b-fj0pge35lv]  td:not(:last-child),
.history-table-container[b-fj0pge35lv]  th:not(:last-child) {
    border-right: 1px solid var(--cpd-border-subtle) !important;
}

.history-table-container[b-fj0pge35lv]  .bb-grid-filter.btn-light {
    display: inline-flex !important;
    align-items: center !important;
    gap: 0.35rem !important;
    min-height: 2rem !important;
    border: 1px solid var(--cpd-gold-border) !important;
    border-radius: var(--cpd-radius-md) !important;
    background: rgba(var(--cpd-dark-rgb), 0.82) !important;
    color: var(--cpd-gold) !important;
    box-shadow: none !important;
    padding: 0.25rem 0.55rem !important;
}

.history-table-container[b-fj0pge35lv]  .bb-grid-filter.btn-light:hover,
.history-table-container[b-fj0pge35lv]  .bb-grid-filter.btn-light:focus {
    border-color: var(--cpd-gold) !important;
    background: var(--cpd-gold-ring) !important;
    color: var(--cpd-contrast) !important;
}

.history-table-container[b-fj0pge35lv]  .bb-grid-filter.btn-light::after {
    margin-left: 0.25rem !important;
}

.history-table-container[b-fj0pge35lv]  .dropdown-menu {
    border: 1px solid var(--cpd-gold-border) !important;
    border-radius: var(--cpd-radius-lg) !important;
    background: rgba(var(--cpd-dark-rgb), 0.98) !important;
    box-shadow: var(--cpd-shadow-card) !important;
    color: var(--cpd-text) !important;
}

.history-table-container[b-fj0pge35lv]  .dropdown-item {
    color: var(--cpd-text) !important;
}

.history-table-container[b-fj0pge35lv]  .dropdown-item:hover,
.history-table-container[b-fj0pge35lv]  .dropdown-item:focus {
    background: var(--cpd-gold-faint) !important;
    color: var(--cpd-gold) !important;
}

.quote-value[b-fj0pge35lv] {
    display: block;
    white-space: nowrap;
}

.quote-kind[b-fj0pge35lv] {
    display: inline-block;
    margin-top: 0.2rem;
    padding: 0.15rem 0.4rem;
    border: 1px solid var(--cpd-gold-border);
    border-radius: var(--cpd-radius-sm);
    color: var(--cpd-gold);
    font-size: 0.72rem;
}

.instrument-detail[b-fj0pge35lv] {
    padding: var(--cpd-space-lg);
}

.detail-header[b-fj0pge35lv] {
    display: flex;
    justify-content: space-between;
    gap: var(--cpd-space-md);
    align-items: flex-start;
    margin-bottom: var(--cpd-space-md);
}

.detail-title[b-fj0pge35lv] {
    color: var(--cpd-contrast);
    font-weight: 600;
}

.detail-subtitle[b-fj0pge35lv] {
    color: var(--cpd-accent);
    font-size: 0.85rem;
}

.detail-pill[b-fj0pge35lv] {
    color: var(--cpd-gold);
    border: 1px solid var(--cpd-gold-border);
    background: var(--cpd-gold-faint);
    border-radius: var(--cpd-radius-sm);
    padding: 0.25rem 0.5rem;
    font-size: 0.8rem;
}

.quote-instances[b-fj0pge35lv] {
    margin-top: var(--cpd-space-md);
}

.quote-instances[b-fj0pge35lv]  table {
    min-width: 24rem !important;
}

.quote-instances[b-fj0pge35lv]  .instance-table {
    width: 100%;
}

.quote-instances[b-fj0pge35lv]  td,
.quote-instances[b-fj0pge35lv]  th {
    padding: 0.6rem 0.8rem !important;
}

.quote-instances[b-fj0pge35lv]  tbody td {
    vertical-align: middle !important;
}

/* The three-state load line (DECISIONS.md #36). It is also the element the W4.6 browser smoke run
   measures a computed style on, so a CPStudio.Client.styles.css that stopped being linked
   (DECISIONS.md #39) reads as `font-size: 16px` rather than as a page that looks slightly off. */
.instrument-status[b-fj0pge35lv] {
    margin: 12px 0 0;
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--cpd-text-subtle);
}
/* /Components/Tables/DataTable.razor.rz.scp.css */
/* The title row. Its shape is deliberately the same as PageRenderer's `.page-tile-header`, but it
   cannot BE that rule: PageRenderer's stylesheet is component-scoped without ::deep, so it matches
   only elements compiled into PageRenderer.razor itself. A header drawn here would simply go
   unstyled. That is the reason the header is the table's to draw rather than the caller's. */
.data-table-header[b-7gmm85ulgc] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 0.75rem;
}

/* No title means the parent already drew one and this row carries only the cluster, which then
   belongs at the right-hand end rather than stranded at the left. */
.data-table-header-actions-only[b-7gmm85ulgc] {
    justify-content: flex-end;
}

.data-table-header-actions[b-7gmm85ulgc] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.data-table-subtitle[b-7gmm85ulgc] {
    color: var(--cpd-text-subtle);
}

/* The clipboard status line, under the table where the design puts it. It is empty until a copy
   succeeds, so it must not reserve a line of height; aria-live announces it when it fills. */
.data-table-status[b-7gmm85ulgc] {
    display: block;
    margin-top: 0.375rem;
    font-size: 0.75rem;
    color: var(--cpd-text-subtle);
}

/* ------------------------------------------------------------------
   The grid rules below are copies of PageRenderer.razor.css's, for the same reason the header rules
   are: those are scoped to PageRenderer and a DataTable rendered anywhere else - a page that draws
   its own table rather than a Page description - would lose them. Inside PageRenderer both sets
   match and agree, so the duplication is inert there. Keep the two in step. */

[b-7gmm85ulgc] .page-grid {
    width: 100%;
    border-collapse: collapse;
}

/* The row's icon buttons are one horizontal cluster, never a stack: without nowrap they wrap inside
   the content-sized sticky column and quadruple every row's height. */
[b-7gmm85ulgc] .page-grid-row-controls {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 0.125rem;
}

/* A sticky column floats over the cells it covers and needs its own opaque background, and the
   selector has to repeat MudBlazor's own shape (0,4,0 beats its 0,3,0) or its grey default wins on
   specificity regardless of source order. Don't shorten this. */
[b-7gmm85ulgc] .mud-data-grid .mud-table-cell.sticky-right.page-grid-controls-header,
[b-7gmm85ulgc] .mud-data-grid .mud-table-cell.sticky-right.page-grid-controls-cell {
    background-color: var(--mud-palette-surface);
    border-left: 1px solid var(--mud-palette-table-lines);
}

[b-7gmm85ulgc] .mud-table-row:hover .mud-table-cell.sticky-right.page-grid-controls-cell {
    background-color: var(--mud-palette-table-hover);
}
/* /Components/Tables/TableCompactView.razor.rz.scp.css */
/* Every colour here is a --cpd-* token rather than the mock's literal hex: the app is already
   tokenised and renders in both light and dark, and a hard-coded panel colour is invisible in one
   of the two. */

.table-compact-text[b-jjhjfdkdsf] {
    display: block;
    width: 100%;
    min-height: 290px;
    box-sizing: border-box;
    padding: 12px 14px;
    font-family: var(--cpd-font-mono);
    font-size: 13px;
    line-height: 1.6;
    color: var(--cpd-text);
    background: rgba(var(--cpd-contrast-rgb), 0.03);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.1);
    border-radius: 6px;
    /* pre, not pre-wrap: a wrapped CSV row stops looking like a row, and the whole reason to show
       the text is that its shape is readable. It scrolls sideways instead. */
    white-space: pre;
    overflow: auto;
    resize: vertical;
}

.table-compact-text:focus[b-jjhjfdkdsf] {
    outline: none;
    /* The mock's gold focus ring, taken from the token rather than its literal hex. */
    border-color: var(--cpd-gold-border);
    box-shadow: 0 0 0 2px var(--cpd-gold-ring);
}

.table-compact-footer[b-jjhjfdkdsf] {
    margin-top: 0.5rem;
    font-size: 0.75rem;
    color: var(--cpd-text-subtle);
}
/* /Components/Tables/TableToolbar.razor.rz.scp.css */
/* Layout only. Every button in here is styled by wwwroot/trade-mode-switcher.css, which App.razor
   loads globally - the cluster has to look identical to the trade Capture page's mode-switcher /
   undo-redo pair, and the way to guarantee that is to share the rules rather than echo them. */

.table-toolbar[b-bolsuz8uhy] {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* The clipboard source elements. Off-screen rather than display:none, because the Clipboard path
   reads `.value` from the live element and a control that is not laid out at all is a weaker
   guarantee than one that is simply somewhere nobody looks. Fixed positioning keeps them out of
   every ancestor's scroll extent, so they can never widen a table or produce a stray scrollbar. */
.table-toolbar-source[b-bolsuz8uhy] {
    position: fixed;
    top: 0;
    left: -10000px;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.table-toolbar-status[b-bolsuz8uhy] {
    font-size: 0.75rem;
    color: var(--cpd-text-subtle);
}
/* /Components/Tiles/DetailPane.razor.rz.scp.css */
/* Heading / inner-container look lifted from XvaSection.razor.css. */
.detail-pane[b-75l95eko29] {
    margin-bottom: 24px;
}

.detail-pane-header[b-75l95eko29] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 12px;
}

.detail-pane-title[b-75l95eko29] {
    font-size: 14px;
    font-weight: 600;
    color: rgba(var(--cpd-contrast-rgb), calc(0.8 * var(--cpd-text-alpha-scale)));
    margin: 0 0 4px;
}

.detail-pane-subtitle[b-75l95eko29] {
    font-size: 11px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.35 * var(--cpd-text-alpha-scale)));
    margin: 0;
}

.detail-pane-header-actions[b-75l95eko29] {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

.detail-pane-close[b-75l95eko29] {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.12);
    border-radius: var(--cpd-radius-lg);
    color: rgba(var(--cpd-contrast-rgb), calc(0.5 * var(--cpd-text-alpha-scale)));
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.detail-pane-close:hover[b-75l95eko29] {
    color: var(--cpd-contrast);
    border-color: rgba(var(--cpd-contrast-rgb), 0.25);
    background: rgba(var(--cpd-contrast-rgb), 0.04);
}

/* min-width:0 + overflow-x lets wide MudDataGrids scroll instead of stretching the column. */
.detail-pane-body[b-75l95eko29] {
    min-width: 0;
    overflow-x: auto;
    background: rgba(var(--cpd-contrast-rgb), 0.02);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.07);
    border-radius: var(--cpd-radius-lg);
    padding: var(--cpd-tile-pad);
}
/* /Components/Tiles/MissingMarketData.razor.rz.scp.css */
.missing-data-msg[b-2mgzgn5nls] {
    font-size: 12px;
    color: var(--cpd-text-subtle);
}

.missing-data-title[b-2mgzgn5nls] {
    margin-bottom: 8px;
}

.missing-data-list[b-2mgzgn5nls] {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.missing-data-list li[b-2mgzgn5nls] {
    display: flex;
    gap: 8px;
}

.missing-data-tag[b-2mgzgn5nls] {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.35 * var(--cpd-text-alpha-scale)));
    white-space: nowrap;
}

.missing-data-items[b-2mgzgn5nls] {
    font-family: var(--cpd-font-mono);
    color: rgba(var(--cpd-contrast-rgb), calc(0.55 * var(--cpd-text-alpha-scale)));
}
/* /Components/Tiles/SummaryTile.razor.rz.scp.css */
/* Card base lifted from Capture's .results-card; hover + chevron from XvaTile.
   The gold left border is the active-tile indicator. */
.summary-tile[b-vpw0b5g3nf] {
    background: rgba(var(--cpd-contrast-rgb), 0.03);
    border: 1px solid rgba(var(--cpd-contrast-rgb), 0.07);
    border-left: 3px solid transparent;
    border-radius: var(--cpd-radius-lg);
    padding: var(--cpd-tile-pad);
    cursor: pointer;
    /* The tile is the query container its BODY components size themselves against: XvaTile's and
       SensitivityTile's stat grids drop from two columns to one below ~240px of tile width
       (@container rules in their own stylesheets). A container query rather than a media query
       because what changes here is the tile's width - the right rail narrows when the density
       preference flips, and the whole page reflows when the sidebar expands over it - neither of
       which the viewport width can see. inline-size, not size: the tile's height is its
       content's, and `container-type: size` would make it depend on an unset height instead. */
    container-type: inline-size;
    transition: border-color 0.15s, background 0.15s;
    user-select: none;
}

.summary-tile:hover[b-vpw0b5g3nf] {
    background: rgba(var(--cpd-contrast-rgb), 0.06);
    border-color: rgba(var(--cpd-contrast-rgb), 0.14);
}

/* Declared after :hover so the gold left border persists while hovering. */
.summary-tile.active[b-vpw0b5g3nf] {
    border-left-color: var(--cpd-gold);
}

.summary-tile-header[b-vpw0b5g3nf] {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.summary-tile-title[b-vpw0b5g3nf] {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--cpd-text-subtle);
}

.summary-tile-chevron[b-vpw0b5g3nf] {
    font-size: 12px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.3 * var(--cpd-text-alpha-scale)));
    transition: transform 0.2s;
}

.summary-tile-chevron.active[b-vpw0b5g3nf] {
    transform: rotate(180deg);
}

.summary-tile-body[b-vpw0b5g3nf] {
    margin-top: 12px;
}

/* Optional header controls (e.g. XvaTile's simulation-settings gear), sitting between the title and
   the chevron. `margin-left: auto` keeps the title left and this cluster hard against the chevron
   even though the header is a space-between flex row. Carries no padding of its own, so a caller
   that renders nothing into the slot leaves the header pixel-identical. */
.summary-tile-actions[b-vpw0b5g3nf] {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
}
/* /Components/Trades/SensitivitySection.razor.rz.scp.css */
/* Sensitivities risk-ladder body: measure selector + per-curve tables + skipped-curve
   notes. DetailPane provides the surrounding heading and card. */

.val-positive[b-z1kt4497a5] { color: var(--token-rate); }
.val-negative[b-z1kt4497a5] { color: var(--token-position); }

/* .results-table / .results-empty are TradeAnalysisPanel.razor.css conventions; scoped
   CSS doesn't cross component boundaries, so the rules are duplicated here verbatim. */
.results-table[b-z1kt4497a5] {
    width: 100%;
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
}

.results-table th[b-z1kt4497a5] {
    font-size: 9px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.35 * var(--cpd-text-alpha-scale)));
    padding: 5px 6px;
    border-bottom: 1px solid rgba(var(--cpd-contrast-rgb), 0.08);
    text-align: left;
}

.results-table td[b-z1kt4497a5] {
    padding: 5px 6px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.65 * var(--cpd-text-alpha-scale)));
    border-bottom: 1px solid rgba(var(--cpd-contrast-rgb), 0.03);
    font-family: var(--cpd-font-mono);
    font-size: 11px;
}

.results-table .date-cell[b-z1kt4497a5] { white-space: nowrap; }

.results-empty[b-z1kt4497a5] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 40px 16px;
    text-align: center;
}

.results-empty-icon[b-z1kt4497a5] {
    font-size: 28px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.15 * var(--cpd-text-alpha-scale)));
}

.results-empty-text[b-z1kt4497a5] {
    font-size: 13px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.3 * var(--cpd-text-alpha-scale)));
}

.sensitivity-measure-switcher[b-z1kt4497a5] {
    margin-bottom: var(--cpd-space-lg);
    width: fit-content;
}

/* .trade-mode-btn (trade-mode-switcher.css, global) is a fixed 28x28px square — sized for the
   single-glyph icon buttons it was built for (Capture's Full/Detailed/Compact/undo/redo cluster).
   This switcher reuses the same class for text labels ("Zero (exact)", "Par"), so the fixed square
   clipped "Zero (exact)" outright. Auto width/height + horizontal padding + no-wrap lets each
   button size to its own label at any viewport width, without touching the shared icon-button
   sizing other switchers still depend on. */
.sensitivity-measure-switcher .trade-mode-btn[b-z1kt4497a5] {
    width: auto;
    height: auto;
    min-height: 28px;
    padding: 5px 12px;
    font-size: 11px;
    white-space: nowrap;
}

.sensitivity-group[b-z1kt4497a5] {
    margin-bottom: 20px;
}

.sensitivity-group:last-child[b-z1kt4497a5] {
    margin-bottom: 0;
}

.sensitivity-group-title[b-z1kt4497a5] {
    font-size: 11px;
    font-weight: 600;
    color: rgba(var(--cpd-contrast-rgb), calc(0.5 * var(--cpd-text-alpha-scale)));
    margin: 0 0 8px;
}

.sensitivity-table th.num[b-z1kt4497a5],
.sensitivity-table td.num[b-z1kt4497a5] {
    text-align: right;
}

.sensitivity-magnitude-value[b-z1kt4497a5] {
    font-size: 10px;
    color: var(--cpd-text-subtle);
    margin-right: 6px;
    vertical-align: middle;
}

.sensitivity-bar-track[b-z1kt4497a5] {
    display: inline-block;
    width: 80px;
    height: 6px;
    background: rgba(var(--cpd-contrast-rgb), 0.06);
    border-radius: 3px;
    overflow: hidden;
    vertical-align: middle;
}

.sensitivity-bar-fill[b-z1kt4497a5] {
    height: 100%;
    border-radius: 3px;
    background: currentcolor;
}

.sensitivity-skipped[b-z1kt4497a5] {
    margin-top: 20px;
    padding-top: 12px;
    border-top: 1px solid rgba(var(--cpd-contrast-rgb), 0.06);
}

.sensitivity-skipped-list[b-z1kt4497a5] {
    margin: 0;
    padding-left: 18px;
    font-size: 11px;
    color: rgba(var(--cpd-contrast-rgb), calc(0.35 * var(--cpd-text-alpha-scale)));
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.sensitivity-missing-msg[b-z1kt4497a5] {
    font-size: 12px;
    color: var(--cpd-text-subtle);
}
/* /Components/Trades/XvaExposureChart.razor.rz.scp.css */
/* Series colours for the EE/EPE/ENE exposure profile.
   Kept as channel triplets rather than hexes so the solid strokes and the
   0.4-alpha error bars/whiskers derive from one value each — the previous
   version spelled every colour twice (#a78bfa and rgba(167, 139, 250, …)) and
   the two had to be kept in step by hand.

   Both themes are written out because these are different colours, not a flip
   of one: the dark set is the pastel Tailwind-400 family, which lands at
   1.7:1–2.6:1 against the ivory light background (--cpd-dark in light mode) and
   reads as barely-there wash. The light set is the -700 family, 4.6:1–5.6:1.
   3:1 is the floor for graphical objects, so the dark set is not merely
   unattractive in light mode, it's below contrast minimum.

   These are local to this component on purpose — no other chart in the app
   uses this palette (checked), so there's nothing to share with. */
.xva-chart[b-k088jml0oe] {
    --xva-ee-rgb: 167, 139, 250;
    --xva-epe-rgb: 52, 211, 153;
    --xva-ene-rgb: 248, 113, 113;

    border: 1px solid var(--cpd-gold-border);
    border-radius: var(--cpd-radius-lg);
    background: rgba(var(--cpd-contrast-rgb), 0.03);
    padding: 0.6rem;
    margin-top: 16px;
    margin-bottom: 16px;
}

:root[data-cpd-theme="light"] .xva-chart[b-k088jml0oe] {
    --xva-ee-rgb: 109, 40, 217;
    --xva-epe-rgb: 4, 120, 87;
    --xva-ene-rgb: 185, 28, 28;
}

.xva-chart svg[b-k088jml0oe] {
    display: block;
    width: 100%;
    height: auto;
}

.axis[b-k088jml0oe] {
    stroke: rgba(var(--cpd-contrast-rgb), 0.12);
    stroke-width: 1;
}

.zero-line[b-k088jml0oe] {
    stroke: rgba(var(--cpd-contrast-rgb), 0.15);
    stroke-width: 1;
    stroke-dasharray: 4 4;
}

.series-line[b-k088jml0oe] {
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.series-line.ee[b-k088jml0oe] { stroke: rgb(var(--xva-ee-rgb)); }
.series-line.epe[b-k088jml0oe] { stroke: rgb(var(--xva-epe-rgb)); }
.series-line.ene[b-k088jml0oe] { stroke: rgb(var(--xva-ene-rgb)); }

.err-bar[b-k088jml0oe] {
    stroke-width: 1;
}

.err-bar.ee[b-k088jml0oe] { stroke: rgba(var(--xva-ee-rgb), 0.4); }
.err-bar.epe[b-k088jml0oe] { stroke: rgba(var(--xva-epe-rgb), 0.4); }
.err-bar.ene[b-k088jml0oe] { stroke: rgba(var(--xva-ene-rgb), 0.4); }

.err-whisker[b-k088jml0oe] {
    stroke-width: 1;
}

.err-whisker.ee[b-k088jml0oe] { stroke: rgba(var(--xva-ee-rgb), 0.4); }
.err-whisker.epe[b-k088jml0oe] { stroke: rgba(var(--xva-epe-rgb), 0.4); }
.err-whisker.ene[b-k088jml0oe] { stroke: rgba(var(--xva-ene-rgb), 0.4); }

.series-pt[b-k088jml0oe] {
    fill: var(--cpd-dark, #0f1117);
    stroke-width: 1.5;
}

.series-pt.ee[b-k088jml0oe] { stroke: rgb(var(--xva-ee-rgb)); }
.series-pt.epe[b-k088jml0oe] { stroke: rgb(var(--xva-epe-rgb)); }
.series-pt.ene[b-k088jml0oe] { stroke: rgb(var(--xva-ene-rgb)); }

/* Cum-flow markers (left limit V(tᵢ⁻)) are filled to distinguish them from the hollow ex-flow points. */
.series-pt.cum.ee[b-k088jml0oe] { fill: rgb(var(--xva-ee-rgb)); }
.series-pt.cum.epe[b-k088jml0oe] { fill: rgb(var(--xva-epe-rgb)); }
.series-pt.cum.ene[b-k088jml0oe] { fill: rgb(var(--xva-ene-rgb)); }

.axis-label[b-k088jml0oe] {
    fill: rgba(var(--cpd-contrast-rgb), calc(0.35 * var(--cpd-text-alpha-scale)));
    font-size: 0.65rem;
}

.legend-swatch[b-k088jml0oe] {
    rx: 2;
}

.legend-swatch.ee[b-k088jml0oe] { fill: rgb(var(--xva-ee-rgb)); }
.legend-swatch.epe[b-k088jml0oe] { fill: rgb(var(--xva-epe-rgb)); }
.legend-swatch.ene[b-k088jml0oe] { fill: rgb(var(--xva-ene-rgb)); }

.legend-label[b-k088jml0oe] {
    fill: rgba(var(--cpd-contrast-rgb), calc(0.5 * var(--cpd-text-alpha-scale)));
    font-size: 0.65rem;
}
