html, body { margin: 0; min-height: 100%; }
body { min-width: 320px; }
a { text-decoration: none; }

/* Generic layout helpers used by both pages/layout */
.page-shell { min-height: 100vh; }

/* MudMainContent as a sticky-footer flex column: page content grows to fill
   available space, footer sits below it and only gets pushed to the very
   bottom of the viewport when content is shorter than one screen. */
.main-content-shell { display: flex; flex-direction: column; min-height: 100vh; }
.main-content-body { flex: 1 1 auto; }

/* 30-day gold price chart (inline SVG; not a MudBlazor concern). Line/dot/gradient
   colors intentionally reuse the theme's --mud-palette-primary variable so a new
   skin's accent color applies here automatically, with no per-instance styling. */
.performance-chart { width: 100%; height: 100%; overflow: visible; }
.chart-container { min-height: 150px; }
.chart-grid { stroke: var(--mud-palette-lines-default); stroke-width: 1; }
.chart-line { fill: none; stroke: var(--mud-palette-primary); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.chart-dot { fill: var(--mud-palette-primary); stroke: var(--mud-palette-primary-contrast-text); stroke-width: 2; }
.chart-gradient-start { stop-color: var(--mud-palette-primary); stop-opacity: .38; }
.chart-gradient-end { stop-color: var(--mud-palette-primary); stop-opacity: .04; }
.chart-y, .chart-x { font-family: var(--mud-typography-default-family); fill: var(--mud-palette-text-secondary); font-size: 11px; }
.chart-x { text-anchor: start; }

/* Top-row cards (Total Account Value / 30 Day Gold Price / Live Gold Prices) */
.top-card { height: 100%; }
.top-card-content { height: 100%; }
.account-spacer { min-height: 16px; }
/* Fixed min-height (not content-driven) so the 1-line wallet row reserves the
   same vertical space as the 2-line gold row instead of collapsing to fit its
   own shorter content; AlignItems="Center" on each MudStack then centers
   whatever's actually inside that shared-height slot. */
.account-breakdown-row { border-top: 1px solid var(--mud-palette-lines-default); min-height: 67px; }

/* Live Gold Prices: white inset box flush to the card's top/left/right edges,
   rounded on all corners, revealing the outer grey card only at the bottom
   (behind the notice) and in the corner curve just above it. */
.price-outer-card { background: var(--mud-palette-background-gray); }
.price-inner { background: var(--mud-palette-surface); border-radius: 12px; padding: 20px 24px 9px; }
.price-notice { padding: 14px 25px 16px; }

/* Live Gold Prices mini table (2 static rows; not worth a full MudTable).
   Font size fixed at 14px to match the Recent Transactions MudTable below —
   these are two different mechanisms but should read as the same "kind" of
   tabular content, not two different scales. */
.price-table { color: var(--mud-palette-text-primary); font-size: 14px; }
.price-row { display: grid; grid-template-columns: .86fr 1.15fr 1.15fr; gap: 12px; align-items: center; padding: 10px 8px; }
.price-head { background: var(--mud-palette-table-striped); border-radius: 8px 8px 0 0; color: var(--mud-palette-text-primary); font-weight: 500; }
.price-head span:nth-child(n+2) { text-align: right; }
.quote-row { border-bottom: 1px solid var(--mud-palette-lines-default); }
.quote-row:last-child { border-bottom: 0; }
.currency-cell { display: flex; align-items: center; gap: 10px; }
.flag { font-size: 22px; line-height: 1; }
/* Currency code (e.g. "IDR") shares the exact same weight as the price value
   next to it — one rule, so they can't drift apart again; color is already
   the shared Heading tone via .price-table above (native <strong> would
   otherwise fall back to browser-default bold). */
.currency-cell strong, .quote-value { font-weight: 500; }
.quote-value { text-align: right; white-space: nowrap; }

/* Home's summary table and Transactions' full ledger are separate contracts.
   Their currently shared cell treatment is scoped through both explicit page
   variants so either can diverge without silently restyling the other (or a
   future MudTable). MudTable ships no header background at all
   (`.mud-table-head{display:table-header-group}` is its entire default rule).
   Applying the grey band to every header cell would show a rounded notch where
   adjacent cells meet, so only the outer two cells get the corner radius.
   Font-size is left unset (Mud's own 14px default already matches the target
   scale); color needs !important — MudTable has its own more-specific default
   that silently wins over a plain override for color (background/radius apply
   fine without it, only color is contested). */
.home-summary-table .mud-table-head .mud-table-cell,
.transactions-ledger-table .mud-table-head .mud-table-cell {
    background: var(--mud-palette-table-striped);
    color: var(--mud-palette-text-primary) !important;
    white-space: nowrap;
}
.home-summary-table .mud-table-head .mud-table-cell:first-child,
.transactions-ledger-table .mud-table-head .mud-table-cell:first-child { border-radius: 8px 0 0 8px; }
.home-summary-table .mud-table-head .mud-table-cell:last-child,
.transactions-ledger-table .mud-table-head .mud-table-cell:last-child { border-radius: 0 8px 8px 0; }

/* Recent Transactions body cells default to Mud's own text color (which
   resolves to our Heading tone via TextPrimary), making the whole table read
   darker/heavier than the rest of the page; plain data text should be Body,
   matching every other non-title/non-value text elsewhere. */
.home-summary-table .mud-table-body .mud-table-cell,
.transactions-ledger-table .mud-table-body .mud-table-cell { color: var(--text-body) !important; }

/* Recent Transactions: kind color depends on data (Buy/Sell/Transfer), but only
   ever takes one of these three theme colors, so a fixed class per kind covers
   it — no per-row inline color needed. */
.kind-buy { color: var(--mud-palette-success); }
.kind-sell { color: var(--mud-palette-error); }
.kind-transfer { color: var(--mud-palette-info); }
.kind-withdraw { color: var(--mud-palette-text-primary); }

/* Recent Transactions compact-history panel (Components/Shared/RecentActivityPanel.razor):
   locked IBX-inspired 2-line/2-column row, standardized across every ticket-family
   surface (Buy/Sell, Transfer, Top Up, Withdraw, Redeem) per
   src/dashboard/artifacts/mockups-review-round-one/README.md -- replaces the
   5-column table those pages used individually before. Class names/shape ported
   from that mockup's own tokens.css. */
.rth-compact-list { display: flex; flex-direction: column; }
.rth-compact-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; padding: 12px 2px; border-top: 1px solid var(--mud-palette-lines-default); }
.rth-compact-row:first-child { border-top: none; }
.rth-left { display: flex; flex-direction: column; gap: 3px; }
.rth-kind { display: flex; align-items: center; gap: 6px; font-size: 14.5px; font-weight: 600; }
.rth-date { font-size: 12.5px; }
.rth-right { text-align: right; flex: none; }
.rth-weight { font-size: 14.5px; font-weight: 700; color: var(--mud-palette-text-primary); }
.rth-value { font-size: 12.5px; }
.rth-status-chip { margin-left: 2px; }

/* MudLink defaults to Color.Primary via a `!important` CSS class; beating that
   for the muted footer legal links needs `!important` here too. */
.footer-link { color: var(--mud-palette-text-secondary) !important; }

/* Footer lives in MainLayout (skeleton-level, like the nav), not per-page —
   see .main-content-shell below. It's a direct child of MudMainContent, which
   already excludes the sidebar (margin-left at Lg+), so its own border-top
   spans edge-to-edge: sidebar border on the left, screen edge on the right,
   with no page-container padding wrapping it. Inner padding on the link row
   only (not the border) keeps the text inset without clipping the divider. */
.dashboard-footer { border-top: 1px solid var(--mud-palette-lines-default); }
.dashboard-footer-inner { padding: 16px 16px; }
@media (min-width: 960px) {
    .dashboard-footer-inner { padding: 16px 24px; }
}

/* Right-aligned on desktop (matches the original, back when there were
   compliance marks on the left to align against); centered on tablet/mobile
   for now — revisit once the rest of the responsive layout is settled. */
.footer-links-row { justify-content: center; }
@media (min-width: 1280px) {
    .footer-links-row { justify-content: flex-end; }
}

/* Nav drawer: MudBlazor's own DrawerVariant.Responsive depends on a JS-side
   breakpoint report that never resolves reliably under Blazor Server (it gets
   stuck showing display:none). We use plain DrawerVariant.Temporary instead
   (toggled purely by our own bool, no JS breakpoint dependency) and force it
   permanently open/static at Lg+ ourselves, the same way the app bar's
   show/hide already works — one plain CSS breakpoint, no framework magic. */
@media (min-width: 1280px) {
    .mud-drawer.mud-drawer-temporary { left: 0 !important; }
    /* Scoped to the drawer's own overlay (.mud-overlay-drawer) specifically —
       not the bare .mud-overlay class, which MudBlazor also reuses for the
       dialog backdrop. The earlier unscoped rule silently killed the dialog
       scrim at this breakpoint too (display:none on the shared parent), which
       is why the review dialog appeared to have no dimmed backdrop at all. */
    .mud-overlay-drawer { display: none !important; }
    .mud-main-content { margin-left: 225px; }

    /* MudMainContent always reserves top padding equal to --mud-appbar-height,
       even though the app bar itself is hidden at this breakpoint (d-lg-none).
       Overriding --mud-appbar-height itself doesn't work: MudThemeProvider
       injects its own <style> block into the DOM at runtime, which lands after
       this stylesheet in document order and re-asserts the variable regardless
       of selector specificity. Overriding the resulting property directly avoids
       that fight entirely. */
    .mud-main-content { padding-top: 0 !important; }
}

/* VIS-011: dialog backdrops measured ~7 RGB levels lighter than the locked Group
   2 captures. Scoped to the dialog overlay's own class (.mud-overlay-dialog),
   per DEC-031 -- never the bare .mud-overlay class, which MudBlazor also reuses
   for the drawer/popover overlays handled above. */
.mud-overlay-dialog.mud-overlay-dark { background-color: rgba(33, 33, 33, 0.54); border-color: rgba(33, 33, 33, 0.54); }

/* Mobile/tablet app bar and nav drawer */
.app-header-bar { border-bottom: 1px solid var(--mud-palette-lines-default); }
.appbar-logo { height: 28px; margin-left: 8px; }
.app-drawer { border-right: 1px solid var(--mud-palette-lines-default); }
.drawer-content { height: 100%; padding: 16px 20px 18px; }
/* Centered rather than left-padded: balances automatically for whatever width
   a future white-label logo happens to be, instead of hand-tuned padding that
   only looks right for this one logo at this one sidebar width. */
.drawer-brand-row { min-height: 56px; align-items: center; justify-content: center; margin-bottom: 22px; }
.drawer-brand-logo { width: 180px; height: auto; }
.identity-row { padding-top: 16px; position: relative; }
.identity-menu-button {
    align-items: center;
    background: transparent;
    border: 0;
    color: inherit;
    cursor: pointer;
    display: inline-flex;
    justify-content: center;
    padding: 6px;
}
.identity-menu {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    bottom: 46px;
    box-shadow: var(--mud-elevation-4);
    min-width: 128px;
    padding: 6px;
    position: absolute;
    right: 0;
    z-index: 10;
}
.identity-menu form { margin: 0; }
.identity-menu-item {
    background: transparent;
    border: 0;
    border-radius: 6px;
    color: var(--mud-palette-text-primary);
    cursor: pointer;
    font: inherit;
    padding: 9px 12px;
    text-align: left;
    width: 100%;
}
.identity-menu-item:hover,
.identity-menu-item:focus-visible { background: var(--mud-palette-action-default-hover); }

/* MudNavMenu's "Default" color variant styles .active as gold text on a plain
   grey hover-background, square corners, and (unlike its other color variants)
   never touches the icon at all. The original design does the opposite: soft
   gold-tinted background (a dedicated hand-picked tone, not a derived
   opacity-overlay — Mud's own --mud-palette-primary-hover landed a few RGB
   points too light/washed-out to match), dark heading-colored text, gold icon,
   rounded corners matching the other nav items' own radius. */
.mud-nav-link.active:not(.mud-nav-link-disabled) {
    background-color: var(--accent-soft) !important;
    color: var(--mud-palette-text-primary) !important;
    border-radius: 8px;
}
.mud-nav-link.active:not(.mud-nav-link-disabled) .mud-nav-link-icon {
    color: var(--mud-palette-primary) !important;
}

/* MudAvatar's default (medium) is 40px/20px font — a 2:1 ratio, set via the
   compound selector `.mud-avatar.mud-avatar-medium` (specificity 2 classes).
   Matching that specificity here (rather than a single class) is what actually
   wins, regardless of stylesheet order. Scaled to 32px/16px: same 2:1 ratio,
   smaller footprint next to "John Doe". */
.mud-avatar.identity-avatar { width: 32px; height: 32px; font-size: 16px; }

/* Buy & Sell ticket */

/* Segmented Buy/Sell mode selector: a full pill track, the active half rendered
   as its own smaller pill inset within it (not two adjacent buttons), matching
   the accepted mockup's floating-segment look. */
.mode-toggle {
    display: flex;
    background: var(--mud-palette-background-gray);
    border-radius: 999px;
    padding: 4px;
    gap: 4px;
}
.mode-btn {
    flex: 1 1 0;
    border: 1px solid transparent;
    background: transparent;
    border-radius: 999px;
    padding: 10px 16px;
    font: inherit;
    font-weight: 600;
    color: var(--text-body);
    cursor: pointer;
}
.mode-btn.active {
    background: var(--mud-palette-surface);
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

.ticket-box { background: var(--mud-palette-surface); }
.ticket-input-row { display: flex; align-items: center; gap: 12px; }
.ticket-field-icon {
    flex: 0 0 auto;
    background: var(--accent-soft);
    border-radius: 8px;
    padding: 6px;
    box-sizing: content-box;
}
/* GoldBarIcon's own SVG is shorter than it is wide (its 3-bar composition's
   real proportions), unlike every square Material icon it stands in for. A
   fixed 24x24 frame keeps its badge the same square size as a MudIcon's
   (matters wherever Class="ticket-field-icon" pairs it against
   AccountBalanceWallet), centering the shorter glyph inside without
   stretching it. */
.gold-bar-icon-frame {
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.ticket-amount-field { flex: 1 1 auto; }
.ticket-amount-field .mud-input-slot { font-size: 1.5rem; font-weight: 700; color: var(--mud-palette-text-primary); }
/* Flex items default to min-width:auto, which floors shrinking at the
   select's own content/padding width rather than the flex-basis below —
   min-width:0 is what actually lets it shrink down to sit snugly around
   "IDR"/"Gold" as in the accepted mockups. */
/* MudBlazor's own .mud-select rule sets flex-grow:1 at equal (single-class)
   specificity; !important is what actually wins here, not rule order. */
.ticket-unit-select { flex: 0 0 96px !important; width: 96px !important; min-width: 0 !important; max-width: 96px !important; }

/* A visible, indeterminate cue that a field is about to be recalculated
   from a debounced keystroke; always mounted, visibility-toggled rather than
   conditionally rendered so it can never itself cause a mount/unmount flash. */
.ticket-recalc-spinner { flex: 0 0 auto; }
.spinner-hidden { visibility: hidden; }

/* Stacks a second, centered line under the icon/rate/ring row while a refresh
   is in flight — matches the dialog's own review-summary-price-row/-status
   stacking, rather than cramming the status text into the same row. */
.ticket-divider { display: flex; flex-direction: column; align-items: center; gap: 6px; margin: 20px 0; }
.ticket-divider-top { display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap; }
.ticket-divider-status { text-align: center; }
.ticket-divider-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--accent-soft);
    color: var(--mud-palette-primary);
}
.ticket-rate-text { color: var(--mud-palette-primary); font-weight: 600; }
/* Rate fades to a muted tone while a refresh is actually in flight (failed/
   slow tick or stale retry), an extra visual cue alongside the ring/label. */
.rate-updating { color: var(--mud-palette-text-secondary) !important; transition: color .3s ease; }
.ticket-validation-message { display: block; }

/* Ambient Ring — chosen refresh-indicator direction (both ticket and dialog),
   see src/dashboard/artifacts/refresh-loader-review/PROGRESS.md. Idle: a
   quiet depleting ring next to the rate, no running countdown text. Active
   (refresh in flight or stale/retrying): the ring spins and a status label
   appears. Shared markup lives in Components/Shared/AmbientRefreshRing.razor. */
.ambient-ring-group { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ambient-ring { flex: none; }
.ambient-ring-arc { transition: stroke-dashoffset .95s linear; }
.ambient-ring-spinning { animation: ambient-ring-spin .9s linear infinite; transform-origin: center; }
@keyframes ambient-ring-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .ambient-ring-arc { transition: none; }
    .ambient-ring-spinning { animation: none; }
}
.ambient-ring-label { white-space: nowrap; }
/* Mud's Material-derived Button typography defaults to uppercase; the accepted
   mockups use normal sentence case throughout. */
.review-action-button { border-radius: 999px; padding-left: 24px; padding-right: 24px; text-transform: none; }

/* Review/Completed/Error dialogs (shared layout across all seven dialog states,
   Components/Dialogs/DialogTitleBar.razor) */
.dialog-title-row { display: flex; align-items: center; justify-content: space-between; width: 100%; }
.dialog-close-button { margin-right: -8px; }
/* VIS-015: the locked Group 2 captures use a bold title weight; MudText's Typo.h5
   default is a lighter weight that reads less distinctly from the dialog body. */
.dialog-title-text { font-weight: 700; }

/* Visually hidden but still screen-reader/keyboard accessible (StepUpDialog's
   per-box OTP labels); not scoped to one component since any future hidden-but-
   accessible label can reuse it. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Status pill (VIS-012): a compact badge for genuine status values (e.g. the
   "Pending" row in a submitted outcome dialog) instead of plain row text. */
.status-pill {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 600;
    background: color-mix(in srgb, var(--mud-palette-warning) 16%, var(--mud-palette-surface));
    color: var(--mud-palette-warning);
}
.dialog-secondary-button, .dialog-primary-button { border-radius: 999px; padding-left: 20px; padding-right: 20px; text-transform: none; }

.review-summary-box { background: var(--mud-palette-surface); overflow: hidden; }
.review-summary-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 20px;
    border-top: 1px solid var(--mud-palette-lines-default);
}
.review-summary-row:first-child { border-top: none; }
.review-summary-highlight { background: var(--accent-soft); }
/* REQ-072-003: optional density modifier (SummaryRow's Dense parameter), matching
   the lighter ~40px/10px-padding .summary-row scale already used by Transfer and
   Redeem's own summary rows. Only TopUp.razor's rows opt in. */
.review-summary-row-dense { padding: 10px 20px; }

.review-caveat-row { display: flex; align-items: flex-start; gap: 8px; }

/* The Buy/Sell price row stacks a second line under the price+ring while a
   refresh is in flight, instead of cramming the status text into the
   already space-between row — mirrors how the ticket's own divider already
   reads once its ring's label wraps. */
.review-summary-price-row { flex-direction: column; align-items: stretch; gap: 4px; }
.review-summary-price-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.review-summary-price-status { text-align: right; }

.outcome-status-row {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    border-radius: 50%;
    margin: 0 auto;
}
.outcome-status-success {
    background: color-mix(in srgb, var(--mud-palette-success) 16%, var(--mud-palette-surface));
    color: var(--mud-palette-success);
}
.outcome-status-error {
    background: color-mix(in srgb, var(--mud-palette-error) 12%, var(--mud-palette-surface));
    color: var(--mud-palette-error);
}
.outcome-status-text { color: var(--mud-palette-text-primary); font-weight: 600; }
/* Pending outcome (Top Up/Withdraw/Redeem submissions): distinct amber tone from
   success/error, per the locked mockups' .outcome-status-pending (#B98900) -- a
   submission that's merely received/pending is neither a success claim nor a
   failure. */
.outcome-status-pending {
    background: color-mix(in srgb, var(--mud-palette-warning) 16%, var(--mud-palette-surface));
    color: var(--mud-palette-warning);
}

/* Shared page-state panel (Components/Shared/PageStatePanel.razor), spec §7.3 */
.page-state-panel { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 40px 16px; }
.page-state-actions { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; }

/* Step-up (OTP) dialog (Components/Dialogs/StepUpDialog.razor): six discrete
   code boxes (VIS-006) rendered behind ONE real accessible input, rather than
   one underlined run -- keeps the single-field "6-digit verification code"
   label/fill contract the visual-capture catalogue and screen readers rely on. */
.otp-box-row { position: relative; display: flex; gap: 8px; justify-content: center; }
.otp-box {
    width: 44px;
    height: 52px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    font-weight: 700;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
}
.otp-box-active { border-color: var(--mud-palette-primary); border-width: 2px; }
/* The real input spans the whole box row, fully transparent, so it keeps
   capturing keyboard/paste/mobile-IME input and screen-reader focus while the
   decorative boxes behind it show the live value. */
.otp-hidden-input { position: absolute; inset: 0; opacity: 0; }
.otp-hidden-input input { width: 100%; height: 100%; cursor: text; }

/* Select-chip (Withdraw/Redeem account/product pickers), ported verbatim from the
   locked mockup's tokens.css. */
.select-chip { display: flex; align-items: center; justify-content: flex-start; gap: 12px; border: 1px solid var(--mud-palette-lines-default); border-radius: 10px; padding: 12px 14px; margin-bottom: 8px; cursor: pointer; background: none; width: 100%; text-align: left; font: inherit; }
.select-chip.active { border-color: var(--mud-palette-primary); background: var(--accent-soft); }
.select-chip-icon { flex: none; width: 36px; height: 36px; border-radius: 8px; background: var(--accent-soft); color: var(--mud-palette-primary); display: flex; align-items: center; justify-content: center; }
.select-chip.active .select-chip-icon { background: var(--mud-palette-surface); }
.select-chip-title { font-size: 14px; font-weight: 600; color: var(--mud-palette-text-primary); }
.select-chip-meta { font-size: 12.5px; color: var(--mud-palette-text-secondary); margin-top: 2px; }
.select-chip-check { margin-left: auto; color: var(--mud-palette-primary); flex: none; }
.add-link-row { display: flex; align-items: center; gap: 6px; color: var(--mud-palette-primary); font-size: 13.5px; font-weight: 600; padding: 8px 2px; text-decoration: none; }

/* "How to collect your gold" guide (Components/Shared/CollectionGuideContent.razor),
   ported verbatim from the locked Redeem mockup's tokens.css. */
.guide-card { background: var(--mud-palette-background-gray); }
.guide-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; cursor: pointer; background: none; border: none; width: 100%; text-align: left; font: inherit; padding: 0; }
.guide-step-title { font-size: 13.5px; font-weight: 700; color: var(--mud-palette-text-primary); margin: 16px 0 6px; }
.guide-list { margin: 0; padding-left: 18px; font-size: 13px; color: var(--text-body); line-height: 1.6; }
.guide-list li { margin-bottom: 6px; }
.guide-warn {
    display: flex;
    gap: 8px;
    align-items: flex-start;
    background: var(--accent-soft);
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 30%, var(--accent-soft));
    border-radius: 8px;
    padding: 10px 12px;
    font-size: 12.5px;
    color: var(--mud-palette-text-primary);
    margin: 12px 0 0;
}

/* Copyable reference code box (Top Up's permanent funding reference), ported
   verbatim from the locked mockup's tokens.css. */
.ref-box {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: var(--mud-palette-background-gray);
    padding: 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.ref-box .ref-label { font-size: 12px; color: var(--mud-palette-text-secondary); margin-bottom: 4px; }
.ref-box .ref-value { font-size: 17px; font-weight: 700; color: var(--mud-palette-text-primary); letter-spacing: .5px; }
.ref-copy { display: flex; align-items: center; gap: 5px; color: var(--mud-palette-primary); font-size: 13px; font-weight: 600; flex: none; background: none; border: none; cursor: pointer; padding: 0; text-decoration: none; }

/* Select-field (Redeem's Product/Pickup-location pickers) and qty-box (Redeem's
   Quantity control and multi-product line-item cards) share one bordered-field-box
   grammar -- border/radius/padding declared once here and consumed by both
   selectors, rather than .qty-box re-declaring .select-field's border/padding/
   icon-gutter rules a second time under a new name (task-072 REQ-072-004/005).
   min-width:0 on .sf-body is load-bearing: without it, a flex child floors its
   shrink width at its content's own size, which is exactly what forced this
   control wider than a 390px mobile viewport before MudSelect's displayed text
   was shortened (see Redeem.razor's own comment). */
.select-field, .qty-box { border: 1px solid var(--mud-palette-lines-default); border-radius: 10px; padding: 8px 14px; }
.select-field .sf-icon, .qty-box .sf-icon { flex: none; display: flex; }
.select-field { display: flex; align-items: center; gap: 10px; }
.select-field .sf-body { flex: 1 1 auto; min-width: 0; }
.sf-meta { color: var(--mud-palette-text-secondary); }

/* qty-box: the genuinely-different parts of the Quantity control / per-line-item
   card -- the stepper, the reserved-weight readout, and (for multi-product line
   items only) a name/meta header row with an anchored remove control. Border/
   radius/padding come from the shared rule above. */
.qty-box { display: flex; flex-direction: column; gap: 10px; }
.qty-box-header { display: flex; align-items: flex-start; gap: 10px; }
.qty-box-name-group { flex: 1 1 auto; min-width: 0; }
.qty-box-name { font-weight: 600; color: var(--mud-palette-text-primary); display: block; }
.qty-box-remove { flex: none; border: none; background: none; cursor: pointer; color: var(--mud-palette-text-secondary); padding: 2px; display: flex; align-items: center; border-radius: 6px; }
.qty-box-remove:hover { color: var(--mud-palette-text-primary); background: var(--mud-palette-table-striped); }
.qty-box-body { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.qty-box-body .qty-stepper { margin-top: 0; }
.qty-box-body .qty-stepper .qty-btn { width: 36px; height: 36px; }
.qty-box-readout { text-align: right; flex: none; }
.qty-box-readout-value { font-weight: 700; color: var(--mud-palette-text-primary); display: block; }
.qty-box-readout-label { font-size: 12px; color: var(--mud-palette-text-secondary); display: block; }

/* Product picker (REQ-072-005): already-added products render disabled with an
   "Added" badge instead of being removed from the list, so picking from it is a
   pure append action. */
.product-picker-item { width: 100%; min-width: 0; }
.product-picker-item-text { flex: 1 1 auto; min-width: 0; }
.product-picker-added-badge { margin-left: auto; font-size: 11px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; color: var(--mud-palette-text-secondary); }
.selected-products-heading-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.selected-products-count { color: var(--mud-palette-text-secondary); font-size: 13px; }

/* Transactions (Components/Pages/Transactions.razor), ported from the locked
   g3_transactions_d_receipt-menu mockup. */
.tabs-row { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
/* REQ-072-001: 42px -> 34px tall pills (8px off total height = 4px off each side);
   scoped to this page-unique class only -- table row height, Receipt button, and
   sidebar nav font are untouched. */
.tab { padding: 6px 20px; border-radius: 999px; border: 1px solid var(--mud-palette-lines-default); font-size: 14px; font-weight: 600; color: var(--text-body); background: var(--mud-palette-surface); cursor: pointer; }
.tab.active { background: var(--mud-palette-primary); border-color: var(--mud-palette-primary); color: var(--mud-palette-primary-text); }
.filters-row { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; align-items: center; }
.filter-select-shell { flex: none; }
.filter-date-select { width: 230px; }
.filter-status-select { width: 116px; }
.filter-chip-select { width: 100%; }
.filter-chip-select .mud-input { border: 1px solid var(--mud-palette-lines-default); border-radius: 10px; padding: 2px 10px; }

/* REQ-072-002: standardized ~14px field-text scale for compact select/input field
   wrappers whose input slot (and open-popover list items) have no font-size
   override and so fall back to MudBlazor's default ~16px. One shared rule,
   applied via Class="field-select-text" (closed state) + PopoverClass=
   "field-select-text" (open popover) on the MudSelect itself -- consumers:
   Settings' "Display language" selector and Transactions' .filter-chip-select
   date-range/status filters (identical latent gap, found by grep survey).
   Checked and not applicable: BuySell.razor's .ticket-unit-select already sets its
   own larger ticket-scale type via .ticket-amount-field/.ticket-unit-select rules
   and isn't part of this density defect; Redeem's .select-field-wrapped selects
   render their text through .sf-body/.sf-meta content, not MudSelect's own input
   slot, so they don't carry this gap either. */
.field-select-text .mud-input-slot,
.field-select-text.mud-list-item,
.field-select-text .mud-list-item,
.field-select-text .mud-select-value { font-size: 14px; }
/* REQ-079-021: the rule above never actually won against MudBlazor's own
   .mud-typography-subtitle1 class (applied to this same .mud-input-slot
   element by the outlined MudSelect variant) -- both rules have identical
   class-only specificity, and MudBlazor's own stylesheet loads after app.css,
   so its 16px/600 declaration won every tie. The displayed value text (e.g.
   "Last 90 days", "All") rendered oversized/bold against the approved mockup
   even though .field-select-text was already applied correctly in markup.
   !important is the narrowest reliable way to win this specific tie without
   restructuring MudBlazor's own internal class order. */
.field-select-text .mud-input-slot { font-size: 14px !important; font-weight: 400 !important; }
.transaction-export-button { margin-left: auto; }
.receipt-control { position: relative; display: inline-block; overflow: visible; }
.receipt-menu-button {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    padding: 7px 14px;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    background: var(--mud-palette-surface);
    cursor: pointer;
}
.receipt-menu-button.open { border-color: var(--mud-palette-primary); color: var(--mud-palette-primary); background: var(--accent-soft); }
.receipt-menu {
    position: absolute;
    top: 42px;
    left: 0;
    width: 168px;
    text-align: left;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    box-shadow: var(--mud-elevation-8);
    overflow: hidden;
    z-index: 5;
}
.receipt-menu-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 11px 14px;
    border: 0;
    font: inherit;
    font-size: 13.5px;
    color: var(--mud-palette-text-primary);
    background: var(--mud-palette-surface);
    cursor: pointer;
}
.receipt-menu-item:hover { background: var(--mud-palette-table-striped); }
.transactions-ledger-table .mud-table-container,
.transactions-ledger-table .mud-table-root,
.transactions-ledger-table .mud-table-body,
.transactions-ledger-table .mud-table-row,
.transactions-ledger-table .mud-table-cell { overflow: visible; }

@media (max-width: 960px) {
    .receipt-menu { right: 0; left: auto; }
}

@media (max-width: 600px) {
    .filter-select-shell { flex: 1 1 100%; width: 100%; }
    .transaction-export-button { margin-left: 0; }
}

/* Coming soon placeholder page (still-unbuilt nav destinations) */
.coming-soon-shell { min-height: 60vh; justify-content: center; }
.coming-soon-card { max-width: 420px; width: 100%; }

/* REQ-079-008: /logout confirmation page */
.logout-shell { min-height: 60vh; justify-content: center; }
.logout-card { max-width: 420px; width: 100%; }
.logout-form { width: 100%; }
.anonymous-page-shell { min-height: 100vh; background: var(--mud-palette-background); color: var(--text-body); }
.anonymous-message { max-width: 42rem; margin: 0 auto; padding: 4rem 1.5rem; }

/* Standard ticket workspace (TicketWorkspaceLayout.razor), ported from the
   locked g2_transfer_a_ticket_compact-history mockup. Reuses Buy/Sell's own
   .ticket-box/.ticket-input-row/.ticket-field-icon/.ticket-amount-field/
   .ticket-unit-select classes verbatim (same ticket-card idiom) rather than
   duplicating them. Buy/Sell intentionally retains its distinct proportional
   MudGrid geometry; see evidence/task-020/req-020-005/buy-sell-disposition.md. */
.ticket-workspace { display: grid; grid-template-columns: 1fr 360px; gap: 24px; align-items: start; }
.ticket-box-label { font-size: 15px; font-weight: 600; color: var(--mud-palette-text-primary); margin: 0 0 12px; }
.ticket-note { font-size: 13px; color: var(--mud-palette-text-secondary); margin-top: 8px; }
.qty-stepper { display: flex; align-items: center; gap: 14px; margin-top: 10px; }
.qty-stepper .qty-btn { width: 32px; height: 32px; border: 1px solid var(--mud-palette-lines-default); border-radius: 8px; color: var(--mud-palette-text-primary); }
.qty-stepper .qty-val { min-width: 24px; text-align: center; font-size: 17px; font-weight: 700; color: var(--mud-palette-text-primary); }

.recipient-search { border: 1px solid var(--mud-palette-lines-default); border-radius: 10px; padding: 4px; margin-bottom: 10px; }
.recipient-search .ticket-input-row { padding: 8px 10px; }
.recipient-chip { display: flex; align-items: center; gap: 12px; background: var(--accent-soft); border-radius: 10px; padding: 12px 14px; }
.recipient-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--mud-palette-surface);
    border: 1.5px solid var(--mud-palette-primary);
    color: var(--mud-palette-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 13px;
    flex: none;
}
.recipient-name { font-size: 14px; font-weight: 600; color: var(--mud-palette-text-primary); }
.recipient-meta { font-size: 12px; color: var(--mud-palette-text-secondary); }
.recipient-verified { margin-left: auto; display: flex; align-items: center; gap: 4px; color: var(--mud-palette-success); font-size: 12px; font-weight: 600; flex: none; }

.summary-list { display: flex; flex-direction: column; margin-top: 16px; }
.summary-row { display: flex; justify-content: space-between; padding: 10px 0; border-top: 1px solid var(--mud-palette-lines-default); font-size: 14px; }
.summary-row:first-child { border-top: none; }
.cta-row { display: flex; justify-content: flex-end; margin-top: 16px; }

@media (max-width: 960px) {
    .ticket-workspace { grid-template-columns: 1fr; }
}

/* Sign-in (Components/Pages/SignIn.razor, Components/Layout/AuthLayout.razor).
   Plain HTML/CSS, not MudBlazor -- this page renders statically (no interactive
   circuit; see SignIn.razor's own comment), ported from the locked
   g1_signin_final mockup using the --auth-* tokens AuthLayout injects from
   SkinDefinition. The locked hero's two dark gradient stops are semantic skin
   tokens alongside the primary end stop, so another brand can replace the
   complete hero palette without bypassing the white-label seam (DEC-028). */
.auth-shell { display: flex; min-height: 100vh; background: var(--auth-surface); font-family: var(--auth-font-family); }
.auth-shell .form-panel {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    padding: 56px 64px;
}
.auth-shell .form-logo { width: 400px; margin: 0 auto; }
.auth-shell .form-logo img { width: 190px; }
.auth-shell .form-center { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; }
.auth-card { width: 400px; }
.auth-heading { font-size: 24px; font-weight: 700; color: var(--auth-heading); margin: 0 0 6px; }
.auth-sub { font-size: 14px; color: var(--auth-secondary-text); margin: 0 0 30px; }
.auth-error { color: var(--auth-error); font-size: 13.5px; margin: 0 0 16px; }
.field-group { margin-bottom: 18px; }
.field-label { display: block; font-size: 13px; font-weight: 600; color: var(--auth-heading); margin-bottom: 6px; }
.field-input { display: flex; align-items: center; gap: 10px; border: 1px solid var(--auth-border); border-radius: 10px; padding: 12px 14px; }
.field-input input {
    border: none;
    outline: none;
    font: inherit;
    font-size: 15px;
    color: var(--auth-heading);
    flex: 1 1 auto;
    background: transparent;
    width: 100%;
}
.field-input:focus-within { border-color: var(--auth-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--auth-primary) 14%, transparent); }
.row-between { display: flex; align-items: center; margin: 4px 0 24px; font-size: 13px; }
.row-between a { color: var(--auth-primary); font-weight: 600; }
.auth-row-end { justify-content: flex-end; }
.link-button { border: 0; padding: 0; background: transparent; color: var(--auth-primary); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; }
.auth-row-center { justify-content: flex-start; }
/* REQ-079-007: the Google-rendered 304px-wide CAPTCHA widget otherwise sits
   flush to the card's left edge with no separation from the Sign in button
   below it; center it like the mockup's recaptcha-mock placement and give it
   the same 18px rhythm used by .field-group. */
.g-recaptcha { display: flex; justify-content: center; margin: 0 0 18px; }
.outcome-icon { width: 58px; height: 58px; display: flex; align-items: center; justify-content: center; margin: 0 auto 18px; border-radius: 50%; background: color-mix(in srgb, var(--auth-primary) 12%, transparent); color: var(--auth-primary); font-size: 32px; font-weight: 700; }

.cta-stack { display: flex; flex-direction: column; gap: 10px; }
.cta-btn { width: 100%; text-align: center; display: block; box-sizing: border-box; }
.sign-in-submit:disabled { opacity: 0.5; cursor: not-allowed; }
.pill-btn {
    border-radius: 999px;
    padding: 13px 20px;
    font: inherit;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    border: 1px solid transparent;
    text-decoration: none;
}
.pill-btn.primary { background: var(--auth-primary); color: var(--auth-primary-contrast); }
.pill-btn.secondary { background: var(--auth-surface); color: var(--auth-heading); border-color: var(--auth-border); }
.pill-btn:disabled { opacity: .5; cursor: not-allowed; }

.auth-shell .brand-panel {
    width: 46%;
    flex: none;
    position: relative;
    overflow: hidden;
    background: linear-gradient(160deg,
        var(--auth-hero-gradient-start) 0%,
        var(--auth-hero-gradient-middle) 45%,
        var(--auth-primary) 100%);
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 56px;
}
.brand-quote { color: var(--auth-primary-contrast); }
.brand-quote h2 { font-size: 34px; line-height: 1.25; font-weight: 700; margin: 0 0 16px; max-width: 460px; }
.brand-quote p { font-size: 15px; opacity: .8; max-width: 420px; line-height: 1.6; }
.brand-rings { position: absolute; right: -120px; bottom: -120px; width: 420px; height: 420px; border-radius: 50%; border: 40px solid color-mix(in srgb, var(--auth-primary-contrast) 6%, transparent); }
.brand-rings::before { content: ""; position: absolute; inset: 60px; border-radius: 50%; border: 28px solid color-mix(in srgb, var(--auth-primary-contrast) 6%, transparent); }

/* Personal onboarding (Components/Pages/Onboarding.razor). The customer-facing flow
   follows the approved compact mockup while retaining the auth-shell tokens and
   the existing server-backed onboarding service calls. */
.onboarding-form-center { align-items: flex-start; padding-top: 64px; }
.onboarding-shell .form-panel { padding: 34px clamp(28px, 6vw, 86px) 52px; }
.onboarding-shell .form-logo { width: min(100%, 660px); }
.onboarding-shell .form-logo img { display: block; width: 176px; }
.onboarding-shell .form-center { align-items: flex-start; justify-content: center; }
.onboarding-card { width: min(100%, 660px); color: var(--auth-body); }
.onboarding-kicker { margin: 0 0 10px; color: var(--auth-primary); font-size: 12px; letter-spacing: .11em; text-transform: uppercase; font-weight: 800; }
.onboarding-stage-heading { min-height: 28px; display: flex; align-items: center; justify-content: space-between; gap: 18px; margin: 0 0 10px; }
.onboarding-stage-heading .onboarding-kicker { margin: 0; }
.onboarding-step-badge { display: inline-flex; align-items: center; flex: none; border-radius: 999px; padding: 7px 12px; background: color-mix(in srgb, var(--auth-primary) 10%, var(--auth-surface)); color: var(--auth-primary); font-size: 12px; font-weight: 800; white-space: nowrap; }
.onboarding-title { margin: 0 0 10px; color: var(--auth-heading); font-size: clamp(29px, 3vw, 39px); line-height: 1.13; }
.onboarding-subtitle { margin: 0 0 27px; color: var(--auth-secondary-text); font-size: 16px; line-height: 1.55; }
.onboarding-section-title { margin: 25px 0 13px; color: var(--auth-heading); font-size: 16px; }
.onboarding-field { margin-bottom: 17px; }
.onboarding-label { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 7px; color: var(--auth-heading); font-size: 13px; font-weight: 700; }
.onboarding-control { width: 100%; min-height: 48px; padding: 12px 14px; border: 1px solid var(--auth-border); border-radius: 11px; background: var(--auth-surface); color: var(--auth-heading); outline: 0; font: inherit; font-size: 15px; }
.onboarding-control:focus { border-color: var(--auth-primary); box-shadow: 0 0 0 4px color-mix(in srgb, var(--auth-primary) 13%, transparent); }
.onboarding-textarea { min-height: 92px; resize: vertical; }
.onboarding-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.onboarding-password { position: relative; }
.onboarding-password .onboarding-control { padding-right: 70px; }
.onboarding-password-toggle { position: absolute; right: 8px; top: 7px; min-height: 34px; padding: 0 9px; border: 0; background: transparent; color: var(--auth-primary); font: inherit; font-size: 12px; font-weight: 800; cursor: pointer; }
.onboarding-rules { display: grid; grid-template-columns: 1fr 1fr; gap: 7px 12px; margin: -3px 0 18px; padding: 14px 16px; border-radius: 12px; background: color-mix(in srgb, var(--auth-primary) 10%, var(--auth-surface)); }
.onboarding-rule { color: var(--auth-secondary-text); font-size: 12px; }
.onboarding-rule::before { display: inline-block; width: 11px; margin-right: 7px; font-weight: 900; }
.onboarding-rule.unmet::before { content: "✕"; color: var(--auth-error); }
.onboarding-rule.met::before { content: "✓"; color: var(--auth-primary); }
.onboarding-captcha { min-height: 78px; }
.onboarding-panel { margin: 20px 0; padding: 18px; border: 1px solid var(--auth-border); border-radius: 14px; background: var(--auth-surface); }
.onboarding-panel h2 { margin: 0 0 6px; color: var(--auth-heading); font-size: 16px; }
.onboarding-checklist { display: grid; gap: 12px; margin: 18px 0 0; padding: 0; list-style: none; }
.onboarding-checklist li { display: flex; gap: 11px; color: var(--auth-body); line-height: 1.45; }
.onboarding-checklist li::before { content: "✓"; display: grid; place-items: center; flex: none; width: 23px; height: 23px; border-radius: 50%; background: color-mix(in srgb, var(--auth-primary) 10%, var(--auth-surface)); color: var(--auth-primary); font-weight: 900; }
.onboarding-actions { display: flex; gap: 12px; margin-top: 27px; }
.onboarding-actions .pill-btn.primary { flex: 1; }
.onboarding-actions .pill-btn { text-align: center; }
.onboarding-micro { color: var(--auth-secondary-text); font-size: 12px; line-height: 1.5; }
.onboarding-micro a, .onboarding-edit-link, .onboarding-consent a { color: var(--auth-primary); font-weight: 700; }
.onboarding-dialog-backdrop { position: fixed; z-index: 10; inset: 0; display: grid; place-items: center; padding: 16px; background: color-mix(in srgb, var(--auth-heading) 58%, transparent); }
.onboarding-dialog { width: min(500px, 100%); padding: 28px; border-radius: 18px; background: var(--auth-surface); box-shadow: 0 24px 80px color-mix(in srgb, var(--auth-heading) 35%, transparent); }
.onboarding-dialog .onboarding-title { font-size: 30px; }
.onboarding-dialog .onboarding-subtitle { margin-bottom: 22px; }
.onboarding-dialog .onboarding-actions { margin-top: 22px; }
.onboarding-code { font-size: 24px; letter-spacing: .24em; text-align: center; }
.onboarding-combobox, .onboarding-dial-combobox { position: relative; }
.onboarding-combobox .onboarding-control { padding-right: 44px; }
.onboarding-combobox-toggle { position: absolute; right: 5px; top: 5px; width: 38px; height: 38px; border: 0; border-radius: 8px; background: transparent; color: var(--auth-secondary-text); font: inherit; font-size: 17px; cursor: pointer; }
.onboarding-options { position: absolute; z-index: 6; top: calc(100% + 6px); left: 0; right: 0; max-height: 220px; overflow: auto; padding: 6px; border: 1px solid var(--auth-border); border-radius: 11px; background: var(--auth-surface); box-shadow: 0 18px 45px color-mix(in srgb, var(--auth-heading) 12%, transparent); }
.onboarding-option { display: flex; width: 100%; padding: 10px 11px; border: 0; border-radius: 7px; background: var(--auth-surface); color: var(--auth-heading); text-align: left; font: inherit; cursor: pointer; }
.onboarding-option:hover, .onboarding-option:focus { background: color-mix(in srgb, var(--auth-primary) 10%, var(--auth-surface)); outline: 0; }
.onboarding-phone { display: flex; min-height: 48px; border: 1px solid var(--auth-border); border-radius: 11px; background: var(--auth-surface); }
.onboarding-phone:focus-within { border-color: var(--auth-primary); box-shadow: 0 0 0 4px color-mix(in srgb, var(--auth-primary) 13%, transparent); }
.onboarding-dial-combobox { width: 98px; flex: none; }
.onboarding-dial-trigger { display: flex; align-items: center; justify-content: space-between; gap: 4px; width: 100%; height: 100%; padding: 0 7px 0 14px; border: 0; border-right: 1px solid var(--auth-border); border-radius: 10px 0 0 10px; background: color-mix(in srgb, var(--auth-primary) 10%, var(--auth-surface)); color: var(--auth-heading); font: inherit; font-weight: 700; cursor: pointer; }
.onboarding-dial-menu { position: absolute; z-index: 7; top: calc(100% + 6px); left: 0; width: min(300px, calc(100vw - 64px)); padding: 7px; border: 1px solid var(--auth-border); border-radius: 11px; background: var(--auth-surface); box-shadow: 0 18px 45px color-mix(in srgb, var(--auth-heading) 12%, transparent); }
.onboarding-dial-search { width: 100%; min-height: 42px; padding: 9px 11px; border: 1px solid var(--auth-border); border-radius: 8px; background: var(--auth-surface); color: var(--auth-heading); font: inherit; outline: 0; }
.onboarding-dial-search:focus { border-color: var(--auth-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--auth-primary) 13%, transparent); }
.onboarding-dial-options { max-height: 210px; overflow: auto; margin-top: 5px; }
.onboarding-dial-option { display: grid; grid-template-columns: 25px minmax(0, 1fr) auto; gap: 8px; align-items: center; width: 100%; padding: 9px 10px; border: 0; border-radius: 7px; background: var(--auth-surface); color: var(--auth-heading); text-align: left; font: inherit; cursor: pointer; }
.onboarding-dial-option:hover, .onboarding-dial-option:focus { background: color-mix(in srgb, var(--auth-primary) 10%, var(--auth-surface)); outline: 0; }
.onboarding-dial-option strong { color: var(--auth-primary); }
.onboarding-phone-number { min-width: 0; flex: 1; padding: 12px 13px; border: 0; border-radius: 0 10px 10px 0; background: transparent; color: var(--auth-heading); font: inherit; font-size: 15px; outline: 0; }
.onboarding-upload { display: flex; align-items: center; gap: 12px; min-height: 62px; padding: 12px; border: 1px dashed var(--auth-border); border-radius: 11px; cursor: pointer; }
.onboarding-browse { flex: none; border-radius: 8px; padding: 9px 13px; background: var(--auth-primary); color: var(--auth-primary-contrast); font-weight: 800; }
.onboarding-upload-copy { color: var(--auth-secondary-text); font-size: 12px; line-height: 1.4; }
.onboarding-file-input { position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0; }
.onboarding-review-stack { display: grid; gap: 12px; margin: 18px 0 24px; }
.onboarding-review-card { padding: 15px 17px; border: 1px solid var(--auth-border); border-radius: 13px; background: var(--auth-surface); }
.onboarding-review-heading { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 8px; }
.onboarding-review-heading h2 { margin: 0; color: var(--auth-heading); font-size: 15px; }
.onboarding-edit-link { padding: 3px; border: 0; background: transparent; font: inherit; font-size: 12px; cursor: pointer; }
.onboarding-review-card dl { margin: 0; }
.onboarding-review-card dl > div { display: grid; grid-template-columns: 145px minmax(0, 1fr); gap: 16px; padding: 7px 0; border-top: 1px solid color-mix(in srgb, var(--auth-border) 55%, transparent); font-size: 13px; line-height: 1.4; }
.onboarding-review-card dt { color: var(--auth-secondary-text); }
.onboarding-review-card dd { margin: 0; color: var(--auth-heading); font-weight: 700; text-align: right; }
.onboarding-verified { color: var(--auth-primary) !important; }
.onboarding-consent { display: flex; gap: 10px; align-items: flex-start; margin: 13px 0; color: var(--auth-body); font-size: 13px; line-height: 1.5; }
.onboarding-consent input { margin-top: 3px; accent-color: var(--auth-primary); }

@media (max-width: 560px) {
    .onboarding-shell .form-panel { padding: 24px 16px 84px; }
    .onboarding-shell .form-logo img { width: 160px; }
    .onboarding-form-center { padding-top: 42px; }
    .onboarding-title { font-size: 27px; }
    .onboarding-grid2 { grid-template-columns: 1fr; }
    .onboarding-actions { flex-direction: column-reverse; }
    .onboarding-actions .pill-btn { width: 100%; }
    .onboarding-upload { align-items: center; }
    .onboarding-review-card dl > div { grid-template-columns: 105px minmax(0, 1fr); gap: 10px; }
    .onboarding-dialog { padding: 24px; }
}

@media (max-width: 960px) {
    .auth-shell { flex-direction: column; }
    .auth-shell .brand-panel { display: none; }
    .auth-shell .form-panel { padding: 32px 24px; }
    .auth-card { width: 100%; max-width: 400px; }
    .auth-shell .form-logo { width: 100%; max-width: 400px; }
    .onboarding-shell .form-panel { padding: 26px 22px 84px; }
    .onboarding-shell .form-logo { width: 100%; max-width: none; }
    .onboarding-shell .auth-card { width: 100%; max-width: 660px; }
    .onboarding-form-center { padding-top: 56px; }
}

@media (max-width: 560px) {
    .onboarding-shell .form-panel { padding: 24px 16px 84px; }
    .onboarding-form-center { padding-top: 42px; }
}

/* Support nav item (Components/Layout/MainLayout.razor) -- a plain anchor carrying the
   same mud-nav-item/mud-nav-link/-icon/-text classes MudNavLink itself renders (verified
   live against the real DOM), so it looks identical to every other nav entry while giving
   full control over the external-navigation attributes. Only the trailing glyph is new. */
.nav-external-icon { margin-left: auto; color: var(--mud-palette-text-secondary); }

/* Settings (Components/Pages/Settings.razor), ported from the locked
   Group 3 Settings and g3_support_a_nav-hidden mockups. No bespoke tablet/mobile mockup exists
   (desktop-only, per the locked README) -- the single breakpoint below collapses the
   subnav/content grid to one column, the same "natural Mud" treatment already used for
   .ticket-workspace. */
.settings-grid { display: grid; grid-template-columns: 216px 1fr; gap: 24px; align-items: start; }
.settings-subnav { display: flex; flex-direction: column; gap: 2px; }
.settings-subnav-item { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-radius: 8px; font-size: 14px; font-weight: 500; color: var(--mud-palette-text-secondary); text-decoration: none; }
.settings-subnav-item.active { background: var(--accent-soft); color: var(--mud-palette-text-primary); font-weight: 600; }
.settings-subnav-item.active .mud-icon-root { color: var(--mud-palette-primary); }
.settings-content { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.settings-section { padding: 18px 20px; }
.settings-section-title { font-size: 13px; font-weight: 700; color: var(--mud-palette-text-secondary); text-transform: uppercase; letter-spacing: .3px; margin: 0 0 4px; display: block; }
.settings-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 0; border-top: 1px solid var(--mud-palette-lines-default); }
.settings-row:first-of-type { border-top: none; }
.settings-row .label { font-size: 14.5px; font-weight: 600; color: var(--mud-palette-text-primary); }
.settings-row .desc { font-size: 12.5px; color: var(--mud-palette-text-secondary); margin-top: 2px; }
.settings-row .value { font-size: 14px; color: var(--text-body); text-align: right; }
.settings-link-btn { color: var(--mud-palette-primary); font-size: 13.5px; font-weight: 600; flex: none; }
.settings-text-button { border: 0; background: transparent; cursor: pointer; font-family: inherit; padding: 4px 0; }
.settings-security-form { margin: 6px 0 12px; padding: 14px; border: 1px solid var(--mud-palette-lines-default); border-radius: 10px; display: grid; gap: 12px; }
.settings-form-actions { display: flex; justify-content: flex-end; }
.settings-security-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.totp-enrollment-form { margin: 6px 0 12px; padding: 18px; border: 1px solid var(--mud-palette-lines-default); border-radius: 10px; display: grid; grid-template-columns: 190px minmax(0, 1fr); gap: 16px 22px; align-items: start; }
.totp-enrollment-intro, .totp-enrollment-form .settings-form-actions, .totp-enrollment-form > .mud-input-control, .totp-enrollment-form > [role="alert"] { grid-column: 1 / -1; }
.totp-qr { width: 180px; height: 180px; padding: 8px; border: 1px solid var(--mud-palette-lines-default); background: var(--mud-palette-surface); border-radius: 8px; }
.totp-qr svg { display: block; width: 100%; height: 100%; }
.totp-manual-key { display: block; margin-top: 8px; padding: 10px 12px; border-radius: 6px; background: var(--surface-sunken); color: var(--mud-palette-text-primary); font-size: 14px; letter-spacing: .08em; overflow-wrap: anywhere; user-select: all; }
.settings-security-status { padding: 4px 0 12px; }
.bank-account-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; flex: none; }
.bank-account-action { border: 0; padding: 4px 0; background: transparent; cursor: pointer; font-family: inherit; }
.bank-account-remove { color: var(--mud-palette-error); }
.settings-add-bank-button { border: 0; background: transparent; cursor: pointer; font-family: inherit; width: auto; }
.bank-account-form { margin: 6px 0 12px; padding: 14px; border: 1px solid var(--mud-palette-lines-default); border-radius: 10px; display: grid; gap: 12px; }
.bank-account-form-actions { display: flex; justify-content: flex-end; }
.settings-select-field { min-width: 190px; }
.transaction-decision-reason { margin-top: 3px; max-width: 280px; color: var(--mud-palette-text-secondary); font-size: 12px; line-height: 1.35; white-space: normal; }

@media (max-width: 960px) {
    .settings-grid { grid-template-columns: 1fr; }
}

@media (max-width: 600px) {
    .totp-enrollment-form { grid-template-columns: 1fr; }
    .totp-qr { width: 168px; height: 168px; }
}
