/* ═════════════════════════════════════════════════════════════════════════
   RENTLY DASHBOARD SYSTEM — global structural utility layer
   ─────────────────────────────────────────────────────────────────────────
   The Nordic "Control Panel" structural vocabulary (the admin `.adm-*` look),
   re-encoded ONCE as token-driven, section-agnostic global classes so non-hero
   CRUD/info pages stop hand-rolling inline <style> blocks. This is the
   companion to the 7 dashboard primitive COMPONENTS in
   Server/Components/Shared/Dashboards/ — primitives cover hero-pattern pages;
   these utilities cover the white-band surfaces (actionbar / page-header /
   cards / tables / chips / empty-states / buttons).

   LOAD ORDER
   ──────────
   MUST be linked AFTER `rently-dashboard-tokens.css` in App.razor — every rule
   below consumes the `:root --rently-*` tokens and the `.rently-shell`
   `--section-accent` fallback declared there.

   COLLISION POLICY (do not break the primitives)
   ──────────────────────────────────────────────
   Blazor scoped CSS stamps a `[b-xxxxx]` attribute on a primitive's elements,
   but a GLOBAL rule with the same class name still matches them and would leak.
   So the two stems the primitives own — `.rently-section-header*`
   (DashboardSectionHeader) and `.rently-pill*` (DashboardStatusPill) — are
   RESERVED and never declared here. The utility equivalents use distinct names:
       content divider  →  .rently-content-header   (NOT .rently-section-header)
       square badge     →  .rently-chip             (the rounded dot-pill stays
                                                      the DashboardStatusPill component)
   Every other name below was verified absent from all 7 primitives' element
   classes, so nothing here can leak onto a primitive.

   ACCENT + FALLBACK CONVENTION
   ────────────────────────────
   `--section-accent` is set inline by DashboardShell. Every accent reference
   here carries an inline fallback — var(--section-accent, var(--rently-primary))
   — so a utility used OUTSIDE a shell still renders in brand teal instead of
   transparent/black. Accent FILLS and ICONS use the raw accent (3:1 is enough
   for a UI component / large glyph). Accent-coloured SMALL TEXT is darkened via
   color-mix(... 70%, #000) — for teal this lands ≈ --rently-primary-dark
   (#256f7a, ~5.8:1) to clear WCAG AA 4.5:1; coral/amber are validated at their
   batch sign-off.

   SCOPE
   ─────
   Structure only. No hero gradient / KPI visual recipe lives here (deferred to
   Batch 1 / Store showcase). `::deep` is intentionally absent — it is illegal
   in a global stylesheet; MudBlazor components (e.g. MudTable) still need a
   per-page scoped `::deep` rule to be themed.

   FONT SIZES
   ──────────
   The token layer intentionally has no font-size scale (only tracking/leading),
   so every font-size below is a literal matching the Nordic `.adm-*` type ramp
   (e.g. 1.375rem page title · 0.95rem section title · 0.85rem table cell ·
   0.7rem eyebrow/chip). These are deliberate, not missed tokens.
   ═════════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────────────────────────────────
   Page scaffold — the frost background for a dashboard surface.
   (Named `.rently-page`; `.rently-shell` is owned by the DashboardShell primitive.)
   ───────────────────────────────────────────────────────────────────────── */
.rently-page {
    background: var(--rently-shell-bg);
    min-height: 100%;
    overflow-x: hidden;
    padding: 0;
}

/* ─────────────────────────────────────────────────────────────────────────
   Action bar — top white toolbar band (filters / search / primary action).
   ───────────────────────────────────────────────────────────────────────── */
.rently-actionbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--rently-space-6);
    padding: var(--rently-space-3) var(--rently-space-8);
    background: var(--rently-card-bg);
    border-bottom: 1px solid var(--rently-border);
    flex-wrap: wrap;
}

.rently-actionbar__left {
    display: flex;
    align-items: center;
    gap: var(--rently-space-2);
    min-width: 0;
}

.rently-actionbar__right {
    display: flex;
    align-items: center;
    gap: var(--rently-space-3);
    margin-left: auto;
}

/* ─────────────────────────────────────────────────────────────────────────
   Page header — white identity band for NON-hero pages (the "real gap" closer).
   Icon tints from the section accent; title uses the Nordic page-title ramp.
   ───────────────────────────────────────────────────────────────────────── */
.rently-page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--rently-space-8);
    padding: var(--rently-space-7) var(--rently-space-8);
    background: var(--rently-card-bg);
    border-bottom: 1px solid var(--rently-border);
    flex-wrap: wrap;
}

.rently-page-header__title {
    display: flex;
    align-items: center;
    gap: var(--rently-space-6);
    min-width: 0;
}

.rently-page-header__icon {
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--rently-radius-lg);
    /* Decorative section glyph — always paired with the adjacent __h1 text, so it
       carries no unique meaning; consumers must mark it aria-hidden="true"
       (WCAG 1.4.11-exempt). Raw accent on an 8% tint measures ~2.85:1, matching
       the admin .adm-page-header__icon precedent. The Phase 0.3 a11y contract
       codifies the aria-hidden requirement. */
    background: color-mix(in srgb, var(--section-accent, var(--rently-primary)) 8%, var(--rently-card-bg));
    color: var(--section-accent, var(--rently-primary));
    flex-shrink: 0;
}

.rently-page-header__h1 {
    font-size: 1.375rem;            /* Nordic page-title size — no exact token */
    font-weight: 700;
    color: var(--rently-text-primary);
    letter-spacing: var(--rently-tracking-tight);
    line-height: var(--rently-leading-snug);
    margin: 0;
    font-family: var(--rently-font-display);
}

.rently-page-header__sub {
    font-size: 0.82rem;             /* no exact token */
    color: var(--rently-text-tertiary);
    line-height: var(--rently-leading-normal);
    margin: 0.15rem 0 0;
}

.rently-page-header__tools {
    display: flex;
    align-items: center;
    gap: var(--rently-space-3);
    margin-left: auto;
    flex-wrap: wrap;
}

/* ─────────────────────────────────────────────────────────────────────────
   Content header — lightweight divider above a content block.
   (Renamed from section-header to avoid the DashboardSectionHeader primitive.)
   ───────────────────────────────────────────────────────────────────────── */
.rently-content-header {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;                    /* tight Nordic divider gap — no token */
    padding: var(--rently-space-6) var(--rently-space-8) var(--rently-space-3);
}

.rently-content-header__eyebrow {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: var(--rently-tracking-wider);
    font-weight: 600;
    /* Small accent text: on LIGHT the color-mix darkens the raw accent (~3:1) to clear AA. That mix is a
       light-surface assumption, so on a shell-less DARK page it darkened onto the dark page (3.13:1 / 2.56:1
       on a card — SC 1.4.3 FAIL). D46 threads --rently-accent-ink-fallback (dark-only #74d0dc, >=8.22:1)
       between --section-accent-text and the mix; light stays byte-unchanged. */
    color: var(--section-accent-text, var(--rently-accent-ink-fallback, color-mix(in srgb, var(--section-accent, var(--rently-primary)) 70%, #000000)));
}

.rently-content-header__title {
    font-size: 0.95rem;             /* no exact token */
    font-weight: 600;
    color: var(--rently-text-strong);
    margin: 0;
    font-family: var(--rently-font-display);
}

.rently-content-header__subtitle {
    font-size: 0.78rem;             /* no exact token */
    color: var(--rently-text-tertiary);
    font-weight: 400;
    margin: 0;                      /* reset UA <p> margin, like the sibling header blocks */
}

/* ─────────────────────────────────────────────────────────────────────────
   Card — base content surface. `--accent` + `__bar` adds a 3px section-accent
   spine on the left edge.
   ───────────────────────────────────────────────────────────────────────── */
.rently-card {
    position: relative;
    border-radius: var(--rently-radius-lg);
    padding: var(--rently-space-6) 1.125rem;   /* 1.125rem x-pad — no exact token */
    background: var(--rently-card-bg);
    border: 1px solid var(--rently-border);
    transition: box-shadow var(--rently-transition-fast);
}

.rently-card:hover {
    box-shadow: var(--rently-shadow-2);
}

/* Opt OUT of the hover lift, for cards that are page SECTIONS rather than affordances.
   `.rently-card` bundles a surface recipe (padding/radius/border/background) with an interaction
   affordance (the shadow lift), and the two get separated the moment the recipe is reused as a plain
   container — which is what happened on RentalDetailsPage, where nine section wrappers moved onto the
   recipe and started lifting under the cursor as though they were clickable. That is a false
   affordance, and at nine per page it reads as the page twitching.
   The alternative — a per-page `:hover { box-shadow: none }` — is what
   `.rently-console-toolbar:hover` below already does one-off; this names the intent instead so it
   stops being re-derived. `none` is the correct value because the base rule sets NO resting
   box-shadow — only `transition: box-shadow` — so the whole shadow is the hover affordance and
   removing it returns the card to its true resting state rather than making it recede. */
.rently-card--static:hover {
    box-shadow: none;
}

.rently-card--accent {
    overflow: hidden;               /* clip the spine to the card radius */
}

.rently-card__bar {
    position: absolute;
    top: 0;
    left: 0;
    width: 3px;
    height: 100%;
    border-radius: 0 2px 2px 0;
    background: var(--section-accent, var(--rently-primary));
}

/* ─────────────────────────────────────────────────────────────────────────
   Table — plain-element data table (Nordic header + subtle row dividers).
   NOTE: MudTable renders its own DOM — theme it per-page with a scoped ::deep
   rule; ::deep cannot live in this global file.
   ───────────────────────────────────────────────────────────────────────── */
.rently-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--rently-card-bg);
}

.rently-table th {
    text-align: left;
    background: var(--rently-subtle-bg);
    color: var(--rently-text-secondary);
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: var(--rently-tracking-wide);
    border-bottom: 1px solid var(--rently-border);
    padding: var(--rently-space-3) var(--rently-space-6);
}

.rently-table td {
    /* source divider #f3f4f6 snapped to the nearest token (visually identical) */
    border-bottom: 1px solid var(--rently-border-subtle);
    padding: var(--rently-space-2) var(--rently-space-6);
    font-size: 0.85rem;
    color: var(--rently-text-body);
}

.rently-table tbody tr:hover {
    background: color-mix(in srgb, var(--section-accent, var(--rently-primary)) 4%, var(--rently-card-bg));
}

/* Horizontal-scroll affordance for a wide table on narrow viewports — wrap a
   .rently-table in <div class="rently-table-wrap"> so cells scroll instead of crushing.
   Promoted from the Store showcase's page-scoped .sto-table-wrap (Phase 1.5); additive,
   no existing .rently-table consumer changes. */
.rently-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.rently-table-wrap > .rently-table {
    min-width: 460px;
}

/* ─────────────────────────────────────────────────────────────────────────
   Chip — small square status badge (distinct from the rounded DashboardStatusPill).
   Semantic variants reuse the AA-validated status `-bg`/`-text` token pairs.
   ───────────────────────────────────────────────────────────────────────── */
.rently-chip {
    display: inline-block;
    padding: 0.125rem var(--rently-space-2);   /* 0.125rem y-pad — no token */
    border-radius: var(--rently-radius-xs);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--rently-tracking-wide);
    white-space: nowrap;
}

.rently-chip--success {
    background: var(--rently-ok-bg);
    color: var(--rently-ok-text-strong);
}

.rently-chip--warning {
    background: var(--rently-warning-bg);
    color: var(--rently-warning-text-strong);
}

.rently-chip--failed {
    background: var(--rently-critical-bg);
    color: var(--rently-critical-text-strong);
}

.rently-chip--info {
    background: var(--rently-info-bg);
    color: var(--rently-info-text-strong);
}

.rently-chip--accent {
    background: color-mix(in srgb, var(--section-accent, var(--rently-primary)) 10%, var(--rently-card-bg));
    /* Small accent text on a 10%-accent tinted chip. The color-mix darkening is a light-surface assumption;
       on a shell-less dark chip (#203547) it was the family's worst cell — 2.21:1 (below even the 3:1 bar).
       D46 threads --rently-accent-ink-fallback (dark-only #74d0dc -> 6.9:1 floor / 7.10 live); light byte-unchanged. */
    color: var(--section-accent-text, var(--rently-accent-ink-fallback, color-mix(in srgb, var(--section-accent, var(--rently-primary)) 70%, #000000)));
}

/* ─────────────────────────────────────────────────────────────────────────
   Add-card — the dashed "add an item" tile used in card grids. GLOBAL because
   it is applied to a MudCard root, which carries no scoped [b-xxx] attribute
   (a companion *.razor.css rule would silently never match). No border-radius
   here — the original inline style set none, so MudCard's own default applies.
   ───────────────────────────────────────────────────────────────────────── */
.rently-add-card {
    height: 100%;
    min-height: 160px;
    border: 2px dashed var(--rently-border);
    display: flex;
    align-items: center;
    justify-content: center;
}

.rently-add-card--clickable {
    cursor: pointer;
}

.rently-add-card__icon {
    font-size: 40px;
    color: var(--section-accent);
}

/* ─────────────────────────────────────────────────────────────────────────
   Empty / loading / error states — centred placeholder blocks.
   Base `.rently-empty-state` composes with the existing global
   `.rently-empty-state__art` (rently-loading.css).
   ───────────────────────────────────────────────────────────────────────── */
.rently-empty-state,
.rently-loading-state,
.rently-error-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
}

.rently-empty-state {
    gap: var(--rently-space-4);
    padding: var(--rently-space-10) var(--rently-space-9);
    color: var(--rently-text-tertiary);
}

.rently-loading-state,
.rently-error-state {
    gap: var(--rently-space-6);
    padding: var(--rently-space-11) var(--rently-space-9);
}

/* ─────────────────────────────────────────────────────────────────────────
   FAB-safe action rows (session-5 F5) — opt-in reservation of the fixed FAB
   column (two 60px FABs at right:20px) for bottom-anchored, right-aligned
   action rows, so a Publish/Save CTA can never sit under the back-to-top or
   Companion FAB. Generalises the reservation the landing max-width formula
   already makes by hand. padding-inline-end (not margin) so the row's card
   surface still reaches its edge; !important because consumers' scoped
   padding shorthands ((0,2,0) after the [b-xxx] rewrite) would otherwise
   out-rank this global (0,1,0) utility.
   ───────────────────────────────────────────────────────────────────────── */
.rently-fab-safe {
    padding-inline-end: max(var(--rently-space-6), var(--rently-fab-gutter, 100px)) !important;
}

@media (max-width: 599.98px) {
    /* Action rows stack full-width on phones; 60px FAB + 20px breathing is the floor. */
    .rently-fab-safe {
        padding-inline-end: max(var(--rently-space-6), 80px) !important;
    }
}

/* ─────────────────────────────────────────────────────────────────────────
   Buttons — plain <button>/<a> styled to the brand (matches the MudButton
   theme + .adm-run-btn: 8px radius, text-transform none). Hover/focus tint
   from the section accent.
   ───────────────────────────────────────────────────────────────────────── */
.rently-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--rently-space-2);
    border-radius: var(--rently-radius-md);
    font-family: var(--rently-font-display);
    font-weight: 600;
    font-size: 0.875rem;
    text-transform: none;
    min-height: 36px;               /* compact action height; 44px via .rently-touch-target ≤960 */
    padding: 0 var(--rently-space-7);
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    transition: background var(--rently-transition-fast),
                border-color var(--rently-transition-fast),
                color var(--rently-transition-fast);
}

/* Primary — fills with the calm teal DEFAULT + white label (StoreOrderDetails Pt3 flip: red = chrome, not
   buttons). A scope may still override via --rently-btn-primary-bg/-border/-hover (e.g. a section wanting an
   accent primary). Inside a hero, DashboardHero inverts this to a white fill (see DashboardHero.razor.css). */
.rently-btn--primary {
    background: var(--rently-btn-primary-bg, var(--rently-btn-primary-default));
    color: var(--rently-btn-primary-text, var(--rently-text-on-accent));
    border-color: var(--rently-btn-primary-border, var(--rently-btn-primary-default));
}

/* D45 — ANCHOR-FORM label-ink pin. THE DEFECT: site.css's global link rule
   (a:hover, a:focus { color: var(--rz-link-hover-color) }) is specificity (0,1,1) and
   out-specifies this variant's resting (0,1,0) label ink, so an <a class="rently-btn--primary">
   repainted its label to the projected brand red on interaction while the <button> form —
   not an <a> — stayed correct. Measured 1.36:1 on the hover fill and 1.13:1 on the resting
   fill (focus without hover): effectively invisible, SC 1.4.3 FAIL. Restated here on the
   interaction states at (0,2,0), which beats (0,1,1) with NO !important.
   RESTORED to the white-label ratios the <button> form always had: 6.94:1 on the hover fill
   (#21626b) and 5.78:1 on the resting fill (#256f7a) — SC 1.4.3 pass at the 4.5:1 normal-text
   bar in BOTH cells (they are two distinct cells; do not quote one figure for both).
   The ink is the SAME value as resting (the hover moves only the background + border-color),
   so the <button> form is computed-identical — this pin restores the anchor to button parity.
   The hijack red is NOT the static site.css #a72e1f: PaletteProjection.EmitRadzenRole
   re-emits --rz-secondary-dark live as Darken(BrandSecondary, 0.85) = #cb3725, and Radzen
   10.4.4 material-base.css derives --rz-link-hover-color from --rz-secondary-dark. (Do not
   consult wwwroot/css/material3-*.css — deleted at D45; they were never loaded and named
   the wrong token.) NOT SYS-07: different pair, different cause, no accepted decision.
   :focus and NOT :focus-visible is load-bearing — the hijacker is a:focus, which matches a
   MOUSE-clicked anchor; a :focus-visible pin would leave the click-then-move-pointer-away
   cell (bg reverts to resting, label stays red = the worst 1.13:1 cell) unfixed.
   Placed BEFORE .rently-btn--primary:disabled and the generic .rently-btn:disabled so those
   still win the (0,2,0) tie on source order and a hovered-disabled button stays grey. */
.rently-btn--primary:hover,
.rently-btn--primary:focus {
    color: var(--rently-btn-primary-text, var(--rently-text-on-accent));
}

.rently-btn--primary:hover {
    background: var(--rently-btn-primary-hover, color-mix(in srgb, var(--rently-btn-primary-default) 88%, #000000));
    border-color: var(--rently-btn-primary-hover, color-mix(in srgb, var(--rently-btn-primary-default) 88%, #000000));
}

.rently-btn--primary:disabled,
.rently-btn--primary[disabled] {
    background: var(--rently-muted-bg);
    color: var(--rently-text-muted);
    border-color: var(--rently-muted-bg);
    cursor: not-allowed;
}

.rently-btn--outline {
    background: var(--rently-card-bg);
    color: var(--rently-text-secondary);
    border-color: var(--rently-btn-outline-border, var(--rently-btn-outline-border-default));
}

/* D45 — :focus ONLY (defect + mechanism in the --primary block above). This variant's :hover
   below DELIBERATELY moves the label to the accent ink at the SAME (0,2,0), so a :hover pin
   here would tie and clobber it — :focus is the only state the link rule still reached
   (measured 5.11:1 light / 2.86:1 dark, the latter a genuine SC 1.4.3 fail; both render a
   destructive-red label on a neutral secondary action).
   ORDER IS LOAD-BEARING: this pin must stay ABOVE the :hover rule. On hover+focus (i.e. a
   click) both match at (0,2,0) and the later rule wins — so :hover must come second to keep
   the accent hover ink. */
.rently-btn--outline:focus {
    color: var(--rently-text-secondary);
}

.rently-btn--outline:hover {
    /* D46 — middle fallback --rently-accent-ink-fallback (dark-only #74d0dc) sits between
       --section-accent-text and the color-mix. On a shell-less dark page the mix darkened the
       accent to 2.36:1 here; the token lifts it to >=7.4:1 (live 7.56 default palette; 7.42 floor
       when the engine is absent and the 6% wash uses the lighter static dark primary). Light: token
       undefined -> mix applies -> byte-unchanged (5.37:1). */
    color: var(--section-accent-text, var(--rently-accent-ink-fallback, color-mix(in srgb, var(--section-accent, var(--rently-primary)) 70%, #000000)));
    border-color: color-mix(in srgb, var(--section-accent, var(--rently-primary)) 40%, var(--rently-border-strong));
    background: color-mix(in srgb, var(--section-accent, var(--rently-primary)) 6%, var(--rently-card-bg));
}

.rently-btn--ghost {
    background: transparent;
    color: var(--rently-text-secondary);
    border-color: transparent;
}

/* D45 — :focus ONLY, the --outline twin (same reasoning, same ordering constraint: this pin
   must stay ABOVE the :hover rule below so the accent hover wins the (0,2,0) tie on a click).
   NOTE: background is transparent, so this variant's hijacked ratio depended on whatever
   backdrop it sat on rather than on a token — on a dark card it matched --outline's 2.86:1. */
.rently-btn--ghost:focus {
    color: var(--rently-text-secondary);
}

.rently-btn--ghost:hover {
    /* D46 — same middle fallback as --outline:hover. Ghost's 8% wash mixes with transparent, so it
       composites over the CARD (#1e293b): shell-less dark measured 2.27:1 there (2.82 on the page);
       the token lifts both to >=7.15:1 (worst = ghost on card; 9.03 on the page). Light byte-unchanged (4.89:1). */
    color: var(--section-accent-text, var(--rently-accent-ink-fallback, color-mix(in srgb, var(--section-accent, var(--rently-primary)) 70%, #000000)));
    background: color-mix(in srgb, var(--section-accent, var(--rently-primary)) 8%, transparent);
}

/* ─────────────────────────────────────────────────────────────────────────
   Semantic action variants — the calm button hierarchy (NEW platform policy:
   red is CHROME, not buttons). Literal WCAG 2.1 AA-validated fills
   (accessibility-expert). Adopted via the Store Order Details example and rolled
   out at the per-section flip — as of D45 (2026-07-15) these are LIVE: 27 usages
   across 13 files (StoreOrderDetails, OrderDetails, ManageAccount, CoursePlayer,
   ConfirmationDialog, …). (Corrected at D45: this header used to read "no live
   page uses these classes yet", true when written, stale since.) Every one of the
   27 is <button>-form — ZERO anchors — so the D45 label-ink pins below are
   DEFENSIVE (they cost nothing and make a future <a> variant safe by default);
   they are NOT live SC 1.4.3 remediations, unlike the --primary/--outline/--ghost
   pins above. Placed BEFORE the generic .rently-btn:disabled guard below so that,
   at equal specificity, disabled still wins for a hovered-disabled semantic button.
   ───────────────────────────────────────────────────────────────────────── */
.rently-btn--confirm {
    background: var(--rently-btn-confirm-bg);
    color: var(--rently-btn-confirm-text);
    border-color: var(--rently-btn-confirm-bg);
}

/* D45 — anchor-form label-ink pin (mechanism in the --primary block above). DEFENSIVE:
   0 anchor-form usages today; :hover sets no ink, so an <a> form would hijack on both states. */
.rently-btn--confirm:hover,
.rently-btn--confirm:focus {
    color: var(--rently-btn-confirm-text);
}

.rently-btn--confirm:hover {
    background: color-mix(in srgb, var(--rently-btn-confirm-bg) 88%, #000000);
    border-color: color-mix(in srgb, var(--rently-btn-confirm-bg) 88%, #000000);
}

.rently-btn--caution {
    background: var(--rently-btn-caution-bg);
    color: var(--rently-btn-caution-text);
    border-color: var(--rently-btn-caution-border);
}

/* D45 — anchor-form label-ink pin (see --primary). DEFENSIVE: 0 anchor-form usages today. */
.rently-btn--caution:hover,
.rently-btn--caution:focus {
    color: var(--rently-btn-caution-text);
}

.rently-btn--caution:hover {
    background: color-mix(in srgb, var(--rently-btn-caution-bg) 90%, #000000);
    border-color: color-mix(in srgb, var(--rently-btn-caution-border) 88%, #000000);
}

.rently-btn--destructive {
    background: var(--rently-btn-destructive);
    color: var(--rently-btn-destructive-text);
    border-color: var(--rently-btn-destructive);
}

/* D45 — anchor-form label-ink pin (see --primary). DEFENSIVE: 0 anchor-form usages today. */
.rently-btn--destructive:hover,
.rently-btn--destructive:focus {
    color: var(--rently-btn-destructive-text);
}

.rently-btn--destructive:hover {
    background: color-mix(in srgb, var(--rently-btn-destructive) 88%, #000000);
    border-color: color-mix(in srgb, var(--rently-btn-destructive) 88%, #000000);
}

/* Destructive in CONTEXT (red chrome present): outline, not filled — keeps "red = chrome"
   legible. The filled .rently-btn--destructive is reserved for point-of-no-return confirms.
   D46 fill/ink SPLIT: the ink + border use --rently-critical-text-strong (#b91c1c light / #fca5a5 dark),
   NOT the fill token --rently-btn-destructive (#c7351f). #c7351f is white-label-safe as a FILL but fails
   as an INK on a dark surface (2.76 card / 3.36 page) AND marginally on the light hover wash (4.35). The
   -strong token already carries the theme-correct danger ink (it is the repo's outlined-error ink) and is
   NOT reprojected by the palette engine, so it is dark-safe by declaration. In non-admin / portalled-dialog
   scope this converges .rently-btn--destructive-outline with .mud-button-outlined-error (tokens.css:1411/1417
   route Mud's outlined-error to the SAME token, both modes); the .adm-shell white-island guard freezes Mud's
   copy to the #b91c1c literal instead, but .rently-btn never renders inside .adm-shell (census-verified) so
   they do not sit side-by-side there. Mirrors the accent-family
   fill/ink split (tokens.css: --section-accent-fill is theme-independent, only the -text/-strong ink lifts).
   The 8% :hover WASH keeps the fill token — it must stay a danger-red tint, not a pink one. */
.rently-btn--destructive-outline {
    background: transparent;
    color: var(--rently-critical-text-strong);
    border-color: var(--rently-critical-text-strong);
}

/* D45 label-ink pin (see --primary); ink value moved to --rently-critical-text-strong at D46.
   DEFENSIVE for the hijack (0 anchor-form usages today), but ALSO the dark/light contrast fix:
   :hover tints only the background wash, so the ink must be restated here at the theme-correct value. */
.rently-btn--destructive-outline:hover,
.rently-btn--destructive-outline:focus {
    color: var(--rently-critical-text-strong);
}

.rently-btn--destructive-outline:hover {
    background: color-mix(in srgb, var(--rently-btn-destructive) 8%, transparent);
    border-color: var(--rently-critical-text-strong);
}

/* Focus ring uses the darkened --section-accent-text, NOT the raw accent (contract C-7):
   the 2px outline-offset exposes the #f8f9fb frost behind the button, where raw teal
   (2.93:1) / coral (2.99:1) / amber (2.04:1) fall below SC 1.4.11's 3:1. The darkened
   text colour clears 3:1 on both white and frost for every section.
   D46 — that C-7 reasoning was LIGHT-only ("#f8f9fb frost", darken-for-AA). On a shell-less DARK page the
   same color-mix darkened the ring onto the dark card to 2.56:1 — a live SC 1.4.11 + 2.4.7 failure on a
   REQUIRED focus indicator. The middle --rently-accent-ink-fallback (dark-only #74d0dc) now lifts the ring
   to 8.22:1 on the card / 10.03:1 on the page; LIGHT keeps the frost-safe darkened accent (token undefined
   -> mix applies, byte-unchanged). --rently-btn-focus overrides still win where a page sets one. */
.rently-btn:focus-visible {
    outline: 2px solid var(--rently-btn-focus, var(--section-accent-text, var(--rently-accent-ink-fallback, color-mix(in srgb, var(--section-accent, var(--rently-primary)) 70%, #000000))));
    outline-offset: 2px;
}

/* Disabled state for ALL variants (previously only --primary had one). Placed after the variant :hover
   rules so, at equal specificity, it wins for a hovered-disabled outline/ghost button too — the hover
   accent tint can't leak onto a disabled control (WCAG 1.4.1 affordance). */
.rently-btn:disabled,
.rently-btn[disabled] {
    background: var(--rently-muted-bg);
    color: var(--rently-text-muted);
    border-color: var(--rently-muted-bg);
    cursor: not-allowed;
}

/* ─────────────────────────────────────────────────────────────────────────
   Grid — generic responsive content grid (closes more inline <style>).
   ───────────────────────────────────────────────────────────────────────── */
.rently-grid {
    display: grid;
    gap: var(--rently-space-4);
}

.rently-grid--2 { grid-template-columns: repeat(2, 1fr); }
.rently-grid--3 { grid-template-columns: repeat(3, 1fr); }
.rently-grid--4 { grid-template-columns: repeat(4, 1fr); }

/* ─────────────────────────────────────────────────────────────────────────
   Section dashboard rail-grid (Initiative C · G1) — pins the sidebar rail track.
   The section layouts (FranchiseLayout / SuccessAmbassadorLayoutNoMaxWidth /
   UserDashboardLayoutNoMaxWidth) host the rail in a RadzenLayout grid. The track
   used to be `auto`, which sizes to the rail subtree's MAX-CONTENT — so it
   ballooned to ~1095px and crushed the body to ~335px @1440 (the rail's own
   width:264px constrains the rail box, NOT the auto track). Pin the track to the
   shared rail-width token instead; minmax(0,1fr) lets the body shrink (a bare 1fr
   has implicit min-width:auto and would re-subsidise the rail).

   Collapse-tracking is preserved purely in CSS: a static-SSR layout cannot read
   the InteractiveServer rail's `_collapsed` field, so :has() lets the ancestor grid
   react to the rail's .rently-sidebar--collapsed class and retarget the track to the
   collapsed token (the token is declared on the grid element — the same element that
   owns grid-template-columns — so var() resolves where it's declared).

   Fully-qualified selector so it outranks Radzen's single-class `.rz-layout` default
   (this sheet also loads after material-base.css). The per-layout @media drawer rules
   set `grid-template-columns: 1fr !important`, which still wins below their breakpoint —
   the :has() rule only flips a CUSTOM PROPERTY, so it can't leak into the drawer. The
   expanded width is the DEFAULT, so a browser without :has() degrades to an always-
   expanded rail (harmless), never a broken collapsed state.
   ───────────────────────────────────────────────────────────────────────── */
.rz-layout.layout-no-rz-chrome.rently-rail-grid {
    grid-template-columns: var(--rently-rail-track, var(--rently-sidebar-w, 264px)) minmax(0, 1fr);
    /* Gate C (2026-07-23): the :has() flip below swaps the track var INSTANTLY while the rail's own
       width animates — the "background lags behind" jank. grid-template-columns interpolates for
       same-structure track lists (both states resolve px + minmax(0,1fr)), and the shared
       --rently-transition-base keeps rail + track in lockstep. Verified by per-frame QA capture,
       not trusted from the spec. */
    /* S7-06 verdict — KEEP as-is. grid-template-columns is a layout property, so this relayouts the
       whole dashboard grid every frame for 200ms, and the alternative was considered: transition the
       rail's own `width` with the grid track set to `auto`. Rejected. The Gate C note above is the
       reason this rule exists at all — animating only the rail is exactly the "background lags behind"
       jank it was written to fix — and swapping to `auto` would re-open the scrollbar-gutter
       interaction that sizing this track explicitly was meant to settle. It is also a deliberate,
       infrequent, user-initiated toggle, not something that fires during scroll or typing. */
    transition: grid-template-columns var(--rently-transition-base);
}

@media (prefers-reduced-motion: reduce) {
    .rz-layout.layout-no-rz-chrome.rently-rail-grid {
        transition: none;
    }
}

/* The :has() match is intentionally broad — section sidebars are layout-rail-only chrome (none render in
   @Body today) and a broad match auto-covers any future section layout. If a page ever hosts a collapsible
   section sidebar in its BODY, scope this to the rail slot: :has(> [class$="-sidebar-wrapper"] .rently-sidebar--collapsed). */
.rz-layout.layout-no-rz-chrome.rently-rail-grid:has(.rently-sidebar--collapsed) {
    --rently-rail-track: var(--rently-sidebar-w-collapsed, 76px);
}

/* ─────────────────────────────────────────────────────────────────────────
   WELDED TAB KIT (Gate E1, 2026-07-23) — the shared "unmistakably tabs" vocabulary:
   a frost tab strip whose ACTIVE tab is white, carries an inset accent top rule, and
   overhangs the panel border by 1px so tab + panel read as ONE surface (the SearchNav
   G7 weld doctrine: active styling is a STATE class, never a focus pseudo). Promoted
   here (not page-scoped) because ManageAccount and the merged Addresses page share it,
   and future tabbed pages should too. The bar scrolls horizontally when tabs overflow
   (wrapped tabs cannot weld). Mechanics stay the host's (buttons + aria-pressed or
   links — the kit is presentation only).
   ───────────────────────────────────────────────────────────────────────── */
.rently-tabs {
    display: flex;
    flex-direction: column;   /* gapless — the weld needs bar and panel adjacent */
    width: 100%;
    min-width: 0;
}

/* The bar/panel divider is an INSET box-shadow hairline, not a border, and the active tab does
   NOT overhang: a scrollable bar (overflow-x: auto) forces overflow-y to auto too, so a -1px
   overhanging tab spawned a phantom vertical scrollbar (QA screenshot-caught). The inset shadow
   paints under the tabs' content, the opaque active tab covers it where it stands, and the panel
   drops its own top border — same weld, zero overflow. */
.rently-tabbar {
    display: flex;
    align-items: flex-end;
    gap: var(--rently-space-1);
    padding: var(--rently-space-2) var(--rently-space-2) 0;
    background: var(--rently-subtle-bg);
    border: 1px solid var(--rently-border);
    border-bottom: 0;
    border-radius: var(--rently-radius-lg) var(--rently-radius-lg) 0 0;
    box-shadow: inset 0 -1px 0 var(--rently-border);
    overflow-x: auto;
    /* Scrollbar hidden, scrolling kept: a classic scrollbar's gutter opens a gap between
       the active tab's bottom edge and the panel on narrow screens, breaking the weld.
       The hidden scrollbar is exactly why the S8-08 edge fades below exist. */
    scrollbar-width: none;
    /* Keyboard focus moving along the strip calls scrollIntoView; without this the focused tab
       lands flush against the edge and the strip reads as if it ended there. 48px leaves the
       neighbour peeking (the "peek" ask) — no engineered half-tab needed, since nowrap tabs
       already cut mid-tab at almost every width and the fade makes that cut explicit. */
    scroll-padding-inline: 48px;
}

.rently-tabbar::-webkit-scrollbar {
    display: none;
}

.rently-tab {
    display: inline-flex;
    align-items: center;
    gap: var(--rently-space-2);
    padding: 10px 16px;
    border: 1px solid transparent;
    border-bottom: 0;
    border-radius: var(--rently-radius-md) var(--rently-radius-md) 0 0;
    background: transparent;
    font-family: var(--rently-font-display);
    font-size: 0.86rem;
    font-weight: 600;
    color: var(--rently-text-secondary);
    cursor: pointer;
    white-space: nowrap;
    flex-shrink: 0;
    transition: background var(--rently-transition-fast), color var(--rently-transition-fast);
}

.rently-tab:hover {
    color: var(--rently-text-strong);
    background: color-mix(in srgb, var(--section-accent, var(--rently-primary)) 6%, transparent);
}

.rently-tab:focus-visible {
    outline: 2px solid var(--section-accent-text, var(--rently-primary-dark));
    outline-offset: -2px;
}

.rently-tab--active {
    background: var(--rently-card-bg);
    border-color: var(--rently-border);
    box-shadow: inset 0 2px 0 var(--section-accent, var(--rently-primary));   /* the accent top rule */
    color: var(--section-accent-text, var(--rently-primary-dark));
}

.rently-tabpanel {
    background: var(--rently-card-bg);
    border: 1px solid var(--rently-border);
    border-top: 0;                          /* the bar's inset hairline IS the divider — see above */
    border-radius: 0 0 var(--rently-radius-lg) var(--rently-radius-lg);
    padding: var(--rently-space-5);
    min-width: 0;
}

@media (prefers-reduced-motion: reduce) {
    .rently-tab {
        transition: none;
    }
}

/* ─────────────────────────────────────────────────────────────────────────
   SCROLL AFFORDANCE (Gate S8-08) — the counterpart to the hidden scrollbar above.
   js/scroll-affordance.js sets data-can-scroll-left / data-can-scroll-right on every
   .rently-tabbar, .rently-table-wrap and opt-in [data-scroll-affordance] element; each
   flag opens a 36px edge fade on ITS side by raising that side's stop from the 0px
   default. No JS (or no flag) → both stops stay 0px → the mask is a hard edge on both
   sides, i.e. visually identical to no mask at all, so this degrades to today's look.

   Everything here is static paint, not motion — no transitions anywhere by design, so
   there is nothing for prefers-reduced-motion to suppress.

   Weld safety: the mask fades the SCROLLER's own painted box (its background, border and
   the inset hairline that welds bar to panel) over the outer 36px, but only on a side that
   actually has hidden content — so a non-overflowing tab strip's weld is never touched.
   ───────────────────────────────────────────────────────────────────────── */
.rently-tabbar[data-can-scroll-left],
.rently-table-wrap[data-can-scroll-left],
[data-scroll-affordance][data-can-scroll-left] {
    --rently-fade-l: 36px;
}

.rently-tabbar[data-can-scroll-right],
.rently-table-wrap[data-can-scroll-right],
[data-scroll-affordance][data-can-scroll-right] {
    --rently-fade-r: 36px;
}

.rently-tabbar[data-can-scroll-left],
.rently-tabbar[data-can-scroll-right],
.rently-table-wrap[data-can-scroll-left],
.rently-table-wrap[data-can-scroll-right],
[data-scroll-affordance][data-can-scroll-left],
[data-scroll-affordance][data-can-scroll-right] {
    -webkit-mask-image: linear-gradient(to right,
        transparent, #000 var(--rently-fade-l, 0px),
        #000 calc(100% - var(--rently-fade-r, 0px)), transparent);
    mask-image: linear-gradient(to right,
        transparent, #000 var(--rently-fade-l, 0px),
        #000 calc(100% - var(--rently-fade-r, 0px)), transparent);
}

/* ─────────────────────────────────────────────────────────────────────────
   KPI band — a full-bleed white Nordic strip of flattened DashboardKpiCards
   (the stat strip lifts OFF the hero into its own band). Promoted from the
   locked Account OrderHistory / Addresses recipe (was duplicated per-page as
   .aoh-/.aae-kpi-band). Matches the child-rendered .rently-kpi directly — no
   ::deep (this is the global sheet, not a scoped file). Full-width by default;
   a console page opts into a reading cap by setting --rently-kpi-band-cap on
   its shell (keeps the cells aligned to a capped main column, e.g. OrderHistory).
   Responsive contract lives in the @media blocks at the end of this section —
   note especially that KPI CAPTIONS ARE HIDDEN inside a band below 600px (S8-07).
   ───────────────────────────────────────────────────────────────────────── */
.rently-kpi-band {
    background: var(--rently-card-bg);
    border-bottom: 1px solid var(--rently-border);
}

.rently-kpi-band__inner {
    display: grid;
    grid-template-columns: repeat(var(--rently-kpi-cols, 3), minmax(0, 1fr));
    width: 100%;
    max-width: var(--rently-kpi-band-cap, none);
    /* full-bleed: cells span edge-to-edge so each KPI's outer border touches the band/hero edges
       (user directive 2026-06-24). Cells keep their own internal padding, so content stays readable;
       this intentionally trades the prior body-content inset alignment for the edge-to-edge look. */
    padding-inline: 0;
}

/* Flatten the cards into the Nordic strip. The 3-class chain (specificity 0,3,0) is deliberate: the cards'
   own DashboardKpiCard.razor.css rules are SCOPED → `.rently-kpi[b-xxx]` (0,2,0), and the scoped bundle loads
   AFTER this global sheet, so a plain `.rently-kpi-band .rently-kpi` (0,2,0) LOSES the tie and the cards keep
   their standalone border/radius/shadow + 240px cap. This chain out-specifies the scoped rule so the band wins. */
.rently-kpi-band .rently-kpi-band__inner .rently-kpi {
    border: 0;
    border-right: 1px solid var(--rently-border-subtle);
    border-radius: 0;
    box-shadow: none;
    background: transparent;
    max-width: none;   /* cells fill their grid columns edge-to-edge (override the standalone 240px cap) */
}

.rently-kpi-band .rently-kpi-band__inner .rently-kpi:hover {
    box-shadow: none;
    transform: none;
}

.rently-kpi-band .rently-kpi-band__inner .rently-kpi:last-child {
    border-right: 0;
}

/* 4-KPI variant — a page with four metrics adds .rently-kpi-band--4 to the band
   wrapper for a 4-up desktop grid (tablet steps to 2-up via the @960 rule below;
   mobile is 1-up via the @600 rule). Replaces the per-page local .xxx-kpi-band
   4-col overrides — the band is now ONE global implementation. 3-KPI pages need
   no modifier (the --rently-kpi-cols default is 3). */
.rently-kpi-band--4 .rently-kpi-band__inner {
    --rently-kpi-cols: 4;
}

/* ─────────────────────────────────────────────────────────────────────────
   Reading-width container (Initiative C · C3) — caps text-heavy / form
   surfaces for readability under the full-bleed layout default, while
   data-dense surfaces (dashboards / tables / card grids) stay full width.
   The token is server-driven + FOUC-safe: declared in App.razor's critical
   head and overridden from SiteConfig.ReadingMaxWidthPx; 820px is the
   fallback (the C0 lock). DEFINED in C3 Pt1; APPLIED to form / checkout /
   long-text surfaces in C3 Pt2.
   ───────────────────────────────────────────────────────────────────────── */
.rently-reading-width {
    max-width: var(--rently-reading-max-width, 820px);
    margin-inline: auto;
}

/* ─────────────────────────────────────────────────────────────────────────
   Page gutter (S8-05) — standalone pages that render OUTSIDE a console or a
   DashboardShell (the 2FA/security suite, the review + template forms) used
   to inherit their gutter from the retired UserDashboardLayout, whose body
   column carried a hard-coded 15px pad. UserDashboardLayoutNoMaxWidth is
   full-bleed by design, so those pages now opt in here and would otherwise
   sit flush against the viewport edge at mobile.

   Inline axis is --rently-space-6 (16px), NOT space-5 (14px): 16px is the
   mobile gutter floor for this pass, and it also keeps every migrated page
   at or above the 15px it had under the old layout. Deeper bottom pad gives
   the last card room to clear the footer seam.
   Pages whose root already pads itself (.review-page-container, .car-body,
   ConfirmEmailPopup's self-margining cards) must NOT take this class.
   ───────────────────────────────────────────────────────────────────────── */
.rently-page-pad {
    padding: var(--rently-space-6) var(--rently-space-6) var(--rently-space-8);
}

/* ─────────────────────────────────────────────────────────────────────────
   Status-grouped sections — a labelled <section> (h2 title + count caption)
   wrapping a card grid. The "Status-grouped" archetype: Default/Other,
   Verified/Pending, Public/Private. A one-card group still reads as
   intentional IA.
   ───────────────────────────────────────────────────────────────────────── */
.rently-group {
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-4);
}

.rently-group + .rently-group {
    margin-top: var(--rently-space-7);
}

.rently-group__head {
    display: flex;
    align-items: baseline;
    gap: var(--rently-space-3);
    flex-wrap: wrap;
    padding-bottom: var(--rently-space-2);
    border-bottom: 1px solid var(--rently-border);
}

.rently-group__title {
    margin: 0;
    font-family: var(--rently-font-display);
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--rently-text-strong);
}

.rently-group__caption {
    font-size: 0.8rem;
    color: var(--rently-text-tertiary);
}

/* ─────────────────────────────────────────────────────────────────────────
   Entity grid + card — the dashboard "list of saved things" surface (saved
   addresses, bank accounts, meeting spots). A responsive auto-fill grid of
   frost cards (avatar + name + body + foot). DISTINCT from the storefront
   .rently-card-grid (rental cards) — do not conflate the two grids.
   ───────────────────────────────────────────────────────────────────────── */
.rently-entity-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--rently-space-5);
}

/* Composes with .rently-card (base surface): adds the flex body, a slightly
   tighter padding, and a lift-free accent hover. Markup: class="rently-card
   rently-entity-card". */
.rently-entity-card {
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-3);
    padding: var(--rently-space-5);
    transition: box-shadow var(--rently-transition-base), border-color var(--rently-transition-base);
}

@media (hover: hover) {
    .rently-entity-card:not(.rently-entity-card--skeleton):hover {
        box-shadow: var(--rently-shadow-3);
        border-color: color-mix(in srgb, var(--section-accent, var(--rently-primary)) 22%, var(--rently-border));
    }
}

.rently-entity-card__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--rently-space-3);
}

.rently-entity-card__identity {
    display: flex;
    align-items: center;
    gap: var(--rently-space-3);
    min-width: 0;
}

.rently-entity-card__avatar {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: var(--rently-radius-md);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--section-accent-text, var(--rently-primary-dark));
    background: color-mix(in srgb, var(--section-accent, var(--rently-primary)) 12%, var(--rently-card-bg));
}

/* default item's avatar is filled with the accent (white glyph) — a clear
   at-a-glance anchor */
.rently-entity-card__avatar--default {
    color: var(--rently-card-bg);
    background: var(--section-accent, var(--rently-primary));
}

.rently-entity-card__name-block {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.rently-entity-card__name {
    margin: 0;
    font-family: var(--rently-font-display);
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--rently-text-strong);
    line-height: var(--rently-leading-snug);
    overflow-wrap: anywhere;
}

.rently-entity-card__default-chip {
    align-self: flex-start;
}

.rently-entity-card__address {
    margin: 0;
    font-size: 0.83rem;
    line-height: var(--rently-leading-snug);
    color: var(--rently-text-secondary);
    overflow-wrap: anywhere;
}

.rently-entity-card__foot {
    margin-top: auto;
    padding-top: var(--rently-space-3);
    border-top: 1px solid var(--rently-border-subtle);
    display: flex;
    align-items: center;
}

/* small accent text (e.g. "Active across Rently") → accent-TEXT (#256f7a, AA),
   never the 3.09:1 raw accent on small text */
.rently-entity-card__foot-note {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--section-accent-text, var(--rently-primary-dark));
}

/* The icon-only MudMenu activator is sub-44px by default in MudBlazor 9.4 —
   guarantee the touch target. Global (not ::deep) because this sheet matches
   the Mud-rendered .mud-icon-button directly; only activators inside our entity
   card are affected. The popover is portaled out and is left stock. */
.rently-entity-card .mud-menu .mud-icon-button {
    min-width: 44px;
    min-height: 44px;
}

/* ─────────────────────────────────────────────────────────────────────────
   Entity-card skeleton — mirrors the card silhouette (title line + 2 body
   lines) for the loading state. Reduced-motion neutralizes the shimmer.
   ───────────────────────────────────────────────────────────────────────── */
.rently-entity-card--skeleton {
    pointer-events: none;
}

.rently-skel-line {
    height: 12px;
    border-radius: var(--rently-radius-sm, 6px);
    background: linear-gradient(90deg, var(--rently-border-subtle) 25%, var(--rently-border) 37%, var(--rently-border-subtle) 63%);
    background-size: 400% 100%;
    animation: rently-skel-shimmer 1.4s ease infinite;
}

.rently-skel-line--title {
    height: 16px;
    width: 55%;
}

.rently-skel-line--short {
    width: 40%;
}

@keyframes rently-skel-shimmer {
    0% { background-position: 100% 0; }
    100% { background-position: 0 0; }
}

@media (prefers-reduced-motion: reduce) {
    .rently-skel-line {
        animation: none;
    }
}

/* KPI band responsive — stays full-bleed (zero inline padding) at every width; 4-up bands step to
   2-up at tablet, and every band lands on a compact 2×2 at mobile (S8-07 — was a 1-up stack, which
   on a 4-KPI console spent most of a phone's first screen on the stat strip before any real
   content appeared). */
@media (max-width: 960px) {
    /* 4-up bands step to 2-up at tablet (cells stay legible); 3-up bands keep
       three columns down to the @600 two-column break. */
    .rently-kpi-band--4 .rently-kpi-band__inner {
        --rently-kpi-cols: 2;
    }
}

@media (max-width: 600px) {
    /* S8-07 — compact 2×2 (was 1-up). Odd counts: the final KPI spans the full row (2+1, no hole). */
    .rently-kpi-band__inner {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .rently-kpi-band__inner > :last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }

    /* Seams for a 2-col grid: vertical seam on left-column cells; horizontal seam between rows;
       nothing on the outer edges. Two cells must drop the bottom seam — the last one, and (on an
       EVEN count only) the one beside it. `:nth-last-child(2):nth-child(odd)` says exactly that:
       second-from-last AND in the left column, which can only be true when the final row is full.
       On an odd count the second-from-last cell is in the RIGHT column, so it fails the test and
       correctly keeps its seam — the full-width last cell sits on a row below it. */
    .rently-kpi-band .rently-kpi-band__inner .rently-kpi {
        border-right: 0;
        border-bottom: 1px solid var(--rently-border-subtle);
    }

    .rently-kpi-band .rently-kpi-band__inner .rently-kpi:nth-child(odd):not(:last-child) {
        border-right: 1px solid var(--rently-border-subtle);
    }

    .rently-kpi-band .rently-kpi-band__inner .rently-kpi:last-child,
    .rently-kpi-band .rently-kpi-band__inner .rently-kpi:nth-last-child(2):nth-child(odd) {
        border-bottom: 0;
    }

    /* The icon step-down has to live HERE, in the global sheet, not in DashboardKpiCard.razor.css: that
       file's `.rently-kpi__icon-wrap .mud-icon-root` rules are scoped, and a scope attribute never reaches
       a CHILD component's root — MudIcon renders the .mud-icon-root, so the scoped copies (base 1.5rem,
       @960 1.25rem) have always been inert. Matching the class directly from the global sheet is the same
       technique the band uses for .rently-kpi itself. Band context only, to match the padding step-down. */
    .rently-kpi-band .rently-kpi__icon-wrap .mud-icon-root {
        font-size: 1.1rem;
    }

    /* KIT CONTRACT (S8-07): captions ("vs last month") are SUPPRESSED inside a band below 600px —
       visually AND for AT — because at 2-up density they wrap into three lines and swamp the value.
       Every caption in the current census is supplementary. A page whose caption is load-bearing
       must surface that fact somewhere else at mobile; do not rely on the band to show it. Band
       context only — a standalone .rently-kpi outside a band keeps its caption at every width. */
    .rently-kpi-band .rently-kpi__caption {
        display: none;
    }
}

/* ─────────────────────────────────────────────────────────────────────────
   Responsive — Nordic breakpoints. Touch-target (44px ≤960) and reduced-motion
   are provided by `.rently-touch-target` / `.rently-respects-motion` in the
   tokens file — reuse them, do NOT redefine here.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 1280px) {
    .rently-grid--4 { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 960px) {
    .rently-grid--3,
    .rently-grid--4 { grid-template-columns: repeat(2, 1fr); }

    .rently-page-header {
        flex-direction: column;
        align-items: flex-start;
    }

    .rently-page-header__tools {
        margin-left: 0;
        width: 100%;
    }

    /* Touch-target enforcement baked into the button itself (contract C-8, SC 2.5.5):
       a button is always interactive, so 44px at tablet-and-below should not depend on a
       consumer remembering to add .rently-touch-target. Desktop keeps the compact 36px
       Nordic height. .rently-touch-target remains for icon-only buttons / action chips. */
    .rently-btn {
        min-height: 44px;
    }
}

@media (max-width: 600px) {
    .rently-grid--2,
    .rently-grid--3,
    .rently-grid--4 { grid-template-columns: 1fr; }

    .rently-actionbar,
    .rently-page-header,
    .rently-content-header {
        padding-left: var(--rently-space-5);
        padding-right: var(--rently-space-5);
    }
}

/* Reduced-motion: MudBlazor's skeleton "wave" shimmer carries no prefers-reduced-motion guard of its own.
   The dashboard loading states use it, so neutralise it globally here (the CountUp + ContentReveal kits
   already self-guard). SC 2.3.3 / repo motion contract — applies to every batch's loaders. */
@media (prefers-reduced-motion: reduce) {
    .mud-skeleton {
        animation: none !important;
    }
}

/* ═════════════════════════════════════════════════════════════════════════
   GUIDED CONSOLE — the "filterable user-content list" layout vocabulary
   ─────────────────────────────────────────────────────────────────────────
   Promoted ONCE from the 4 Account Group-B pages (MyRentables / MyRentalTemplates
   / UserLists / UserList), which each carried a byte-identical copy as page-scoped
   .amr-/.amt-/.aul-* rules ("prove across 4, promote once"). Section-agnostic +
   token-driven, so every later console page (Batches 3–5) inherits it.

   THE LAYOUT: a fluid main column + a bounded sticky "Actions" rail (the locked
   OrderHistory two-column model); a page-level SEGMENTED control (status/source
   switcher — NOT MudTabs); a Table/Cards VIEW TOGGLE ("view switcher" idiom —
   muted track + raised white active pill, deliberately distinct from the solid
   segments); a framed search/sort filter row; a white toolbar card; rail cards +
   a stat list; loading skeletons.

   NO ::deep (illegal here): the MudInput / breadcrumb / icon rules use plain
   descendant selectors — Mud's .mud-* are global unscoped classes reachable
   directly from this sheet (same technique as the FORM VOCABULARY below and the
   .rently-entity-card .mud-menu rule above). Composes with .rently-card /
   .rently-entity-grid / .rently-table-wrap — markup carries both classes.

   COLLISION-SAFE: .rently-console* / .rently-segment* / .rently-segmented /
   .rently-view-toggle* are unused elsewhere and are NOT the reserved primitive
   stems (.rently-section-header* / .rently-pill*).

   PAGE-SPECIFIC (stays in each page's .razor.css): the domain card/row/thumb
   vocabulary, category/system/about content, the local 4-col KPI band, the rail
   stat-dot COLOUR modifiers (data-semantic), the per-page MudMenu 44px ::deep
   touch-target rule, and the --rently-table-wide-min override.
   ═════════════════════════════════════════════════════════════════════════ */

/* Page scaffold (frost shell bg; the breadcrumb reset + the table-wide var also live here). */
.rently-console-page {
    background: var(--rently-shell-bg);
}

.rently-console-page .mud-breadcrumbs {
    padding: 0;
    margin: 0;
}

/* Body — full-width; inline padding matches the KPI band inner (alignDelta = 0). */
.rently-console-body {
    padding: var(--rently-space-8);
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-7);
    width: 100%;
}

.rently-console__stack {
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-6);
    width: 100%;
    min-width: 0;
}

/* Actionbar — breadcrumbs + the Table/Cards view toggle (Create lives in the rail "Actions"). */
.rently-console-actionbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--rently-space-4);
    flex-wrap: wrap;
    width: 100%;
}

/* View toggle — the "view switcher" idiom: a grey track with a raised WHITE active pill
   (accent-text label + soft shadow). Deliberately DISTINCT from the solid-fill segments so
   the two segmented controls never blur. 44px at all widths. */
.rently-view-toggle {
    display: inline-flex;
    background: var(--rently-muted-bg);
    border: 1px solid var(--rently-border);
    border-radius: var(--rently-radius-md);
    padding: 3px;
    gap: 2px;
    flex-shrink: 0;
}

.rently-view-toggle__btn {
    display: inline-flex;
    align-items: center;
    gap: var(--rently-space-2);
    font-family: var(--rently-font-display);
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--rently-text-secondary);
    background: transparent;
    border: 0;
    border-radius: calc(var(--rently-radius-md) - 3px);
    padding: 0 var(--rently-space-4);
    min-height: 44px;
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--rently-transition-fast), color var(--rently-transition-fast), box-shadow var(--rently-transition-fast);
}

.rently-view-toggle__btn:hover {
    color: var(--rently-text-strong);
}

.rently-view-toggle__btn--active {
    background: var(--rently-card-bg);
    color: var(--section-accent-text, var(--rently-primary-dark));
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10);
}

.rently-view-toggle__btn:focus-visible {
    outline: 2px solid var(--section-accent-text, var(--rently-primary-dark));
    outline-offset: 2px;
}

.rently-view-toggle__btn .mud-icon-root {
    font-size: 1.1rem;
}

/* Guided console — fluid main column + bounded sticky rail (the locked OrderHistory model). */
.rently-console {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(300px, 360px);
    gap: var(--rently-space-7);
    align-items: start;
    width: 100%;
}

.rently-console__main {
    min-width: 0;
}

.rently-console-rail {
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-5);
    min-width: 0;
    position: sticky;
    top: var(--rently-space-6);
    align-self: start;
}

.rently-console-rail > * {
    min-width: 0;
}

/* Toolbar — the white card (.rently-card) holding the segments + framed filters. */
.rently-console-toolbar {
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-5);
}

/* Non-interactive container — suppress the .rently-card hover lift. */
.rently-console-toolbar:hover {
    box-shadow: none;
}

/* Segmented control — the status/source filter. Solid-fill active pill. */
.rently-segmented {
    display: flex;
    flex-wrap: wrap;
    gap: var(--rently-space-2);
}

.rently-segment {
    display: inline-flex;
    align-items: center;
    gap: var(--rently-space-2);
    min-height: 44px;
    padding: 0 var(--rently-space-5);
    border: 1px solid var(--rently-border);
    border-radius: var(--rently-radius-md);
    background: var(--rently-card-bg);
    font-family: var(--rently-font-display);
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--rently-text-secondary);
    cursor: pointer;
    transition: background var(--rently-transition-fast), color var(--rently-transition-fast), border-color var(--rently-transition-fast);
}

.rently-segment:hover {
    color: var(--rently-text-strong);
    border-color: var(--rently-border-strong);
}

.rently-segment--active {
    background: var(--section-accent-fill, var(--rently-primary-dark));
    border-color: var(--section-accent-text, var(--rently-primary-dark));
    color: #ffffff;
}

.rently-segment:focus-visible {
    outline: 2px solid var(--section-accent-text, var(--rently-primary-dark));
    outline-offset: 2px;
}

.rently-segment__count {
    font-weight: 700;
    font-size: 0.72rem;
    padding: 1px 6px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--section-accent) 12%, var(--rently-card-bg));
    color: var(--section-accent-text, var(--rently-primary-dark));
}

.rently-segment--active .rently-segment__count {
    /* Darken (black wash) rather than lighten — white text on a black-washed accent-text fill keeps ≥4.5:1 in
       BOTH flavours. A WHITE wash would lighten the fill and DROP the white-digit contrast (a11y/ui gate). */
    background: rgba(0, 0, 0, 0.16);
    color: #ffffff;
}

/* Filters — framed search (wider) + sort on the white toolbar card. */
.rently-console-filters {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: var(--rently-space-5);
    align-items: start;
}

/* MudBlazor filter-control theming → Nordic white well. Plain descendants (NO ::deep) — .mud-* are
   global unscoped classes; anchored on .rently-console-filters (the only outlined inputs in a console
   body), mirroring the FORM VOCABULARY .rz-* technique below. Specificity is (0,4,0): it intentionally
   trades away the old scoped (0,5,0) [b-xxx] weight, still beats MudBlazor's defaults — same nodes, same paint.
   KNOWN CARRY-FORWARD (preserved verbatim from the shipped Group B recipe to keep this consolidation a pure
   parity no-op; both deferred to the coordinated console-filter fix — with the framed-MudSelect visible-name
   a11y — so they land across ALL console pages incl. StoreOrderHistory at once): (1) the :focus rule below
   keys on `.mud-focused`, which Mud 9.4 does NOT render on an outlined input (it uses :focus-within), so the
   section-accent focus border silently falls back to Mud's default primary; (2) `:not(.mud-error)` should be
   `:not(.mud-input-error)` (the real class), so the guard is currently inert. */
.rently-console-filters .mud-input.mud-input-outlined {
    background: var(--rently-card-bg);
    border-radius: var(--rently-radius-md);
}

.rently-console-filters .mud-input.mud-input-outlined .mud-input-outlined-border {
    border-color: var(--rently-border);
    border-radius: var(--rently-radius-md);
    transition: border-color var(--rently-transition-fast);
}

.rently-console-filters .mud-input.mud-input-outlined:hover:not(.mud-disabled):not(.mud-error) .mud-input-outlined-border {
    border-color: var(--rently-border-strong);
}

.rently-console-filters .mud-input.mud-input-outlined.mud-focused:not(.mud-error) .mud-input-outlined-border {
    border-color: var(--section-accent);
    border-width: 2px;
}

.rently-console-filters .mud-input-adornment-icon {
    color: var(--rently-text-tertiary);
}

/* Cards container (composes .rently-entity-grid in markup for the responsive grid). */
.rently-console-cards {
    width: 100%;
}

/* Table-wrap (composes the global .rently-table-wrap for overflow scroll). */
.rently-console-table-wrap {
    width: 100%;
}

/* Wide-table opt-in — a console table with ≥5 columns needs more than the 460px global floor so its
   first text column doesn't crush to a vertical character stack. Per-page value via
   --rently-table-wide-min (default 600px; MyRentables sets 640, UserList 560). Leaves the global 460
   floor untouched for every other .rently-table consumer (StoreOrderHistory/Details/Dashboard). */
.rently-table-wrap > .rently-table--wide {
    min-width: var(--rently-table-wide-min, 600px);
}

/* Empty state. */
.rently-console-empty {
    padding: var(--rently-space-8) var(--rently-space-6);
    width: 100%;
}

/* Rail cards (compose .rently-card). Prefix-coherent under .rently-console-rail so a consumer renames its
   whole rail subtree with one amr/amt/aul-rail → rently-console-rail swap. */
.rently-console-rail-card {
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-3);
    padding: var(--rently-space-5);
    align-items: flex-start;
}

.rently-console-rail-card__title {
    display: inline-flex;
    align-items: center;
    gap: var(--rently-space-2);
    font-family: var(--rently-font-display);
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--rently-text-strong);
}

.rently-console-rail-card__title .mud-icon-root {
    color: var(--section-accent-text, var(--rently-primary-dark));
}

.rently-console-rail-card__body {
    margin: 0;
    font-size: 0.8rem;
    line-height: var(--rently-leading-snug);
    color: var(--rently-text-secondary);
}

.rently-console-rail-card__body strong {
    color: var(--rently-text-strong);
    font-weight: 700;
}

.rently-console-rail-btn {
    align-self: stretch;
}

/* At-a-glance stat list (the dot COLOUR modifiers stay page-local — data-semantic). */
.rently-console-rail-stats {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-3);
    width: 100%;
}

.rently-console-rail-stats li {
    display: flex;
    align-items: center;
    gap: var(--rently-space-2);
    font-size: 0.82rem;
    color: var(--rently-text-body);
}

.rently-console-rail-stats strong {
    font-family: var(--rently-font-display);
    color: var(--rently-text-strong);
}

.rently-console-rail-stats__sub {
    margin-left: auto;
    font-size: 0.72rem;
    color: var(--rently-text-tertiary);
}

.rently-console-rail-stats__dot {
    flex-shrink: 0;
    width: 8px;
    height: 8px;
    border-radius: 999px;
}

/* Loading skeleton — reuses the global @keyframes rently-skel-shimmer (declared above). */
.rently-skel-box {
    background: linear-gradient(90deg, var(--rently-border-subtle) 25%, var(--rently-border) 37%, var(--rently-border-subtle) 63%);
    background-size: 400% 100%;
    animation: rently-skel-shimmer 1.4s ease infinite;
}

.rently-skel-grow {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.rently-skel-name {
    width: 60%;
}

.rently-skel-chip {
    width: 52px;
    height: 18px;
}

@media (prefers-reduced-motion: reduce) {
    .rently-skel-box {
        animation: none;
    }
}

/* Console responsive — rail drops below the main ≤1100; segments/filters/toggle go full-width ≤600. */
@media (max-width: 1100px) {
    .rently-console {
        grid-template-columns: 1fr;
    }

    .rently-console-rail {
        position: static;
    }
}

@media (max-width: 960px) {
    .rently-console-body {
        padding: var(--rently-space-6);
        gap: var(--rently-space-6);
    }
}

@media (max-width: 600px) {
    .rently-segmented {
        width: 100%;
    }

    .rently-segment {
        flex: 1 1 auto;
        justify-content: center;
    }

    .rently-console-filters {
        grid-template-columns: 1fr;
    }

    .rently-view-toggle {
        width: 100%;
    }

    .rently-view-toggle__btn {
        flex: 1 1 auto;
        justify-content: center;
    }
}

/* ═════════════════════════════════════════════════════════════════════════
   FORM VOCABULARY — Nordic Radzen form treatment (the "forms crucible")
   ─────────────────────────────────────────────────────────────────────────
   First folded for MyStore (Batch 1 Store rollout); section-agnostic so every
   later form page (Account / Organization / Success Ambassador) inherits it.

   VARIABLES-FIRST (Radzen 10.4.4): Radzen styles inputs via .rz-* CLASS
   selectors that READ --rz-* variables, so setting those variables on the
   .rently-form scope wins the cascade without a specificity fight — and WITHOUT
   ::deep (which is illegal in this global sheet): Radzen's .rz-* are GLOBAL,
   unscoped classes, reachable by a plain descendant selector from here. The
   retint lives on .rently-form (the form SCOPE) rather than .rently-field so it
   also reaches the save RadzenButton, which sits outside any field cell.

   COLLISION-SAFE: .rently-form* / .rently-field* are unused elsewhere and are
   NOT the reserved primitive stems (.rently-section-header* / .rently-pill*).
   ═════════════════════════════════════════════════════════════════════════ */
.rently-form {
    --rz-primary: var(--section-accent, var(--rently-primary));
    --rz-primary-lighter: color-mix(in srgb, var(--section-accent, var(--rently-primary)) 12%, transparent);
    --rz-input-border: 1px solid var(--rently-border);
    --rz-input-hover-border: 1px solid var(--rently-border-strong);
    --rz-input-border-radius: var(--rently-radius-md);   /* Radzen default is 4px */
    --rz-input-background-color: var(--rently-card-bg);
    --rz-form-field-label-color: var(--rently-text-secondary);
    /* NOTE the -color suffix — Radzen 10.4.4's token is --rz-switch-checked-background-COLOR; the
       suffix-less name (which several legacy pages set inline) is dead → a no-op. The STOCK theme
       default is --rz-primary-LIGHTER, a TRANSLUCENT 12% wash (stock: rgba(67, 64, 210, 0.12)).
       This override rebinds the checked track to a SOLID section accent so an "on" switch wears
       the section colour, not the global primary — i.e. it changes both the hue AND the opacity
       of the STOCK default. (Anchored on stock: inside .rently-form the hue has already moved
       before this line runs — the --rz-primary-lighter rebind above re-mixes it to 12% of the
       section accent — so this declaration's MARGINAL effect in that scope is the opacity.)
       ⚠ CORRECTED AT D45 (2026-07-15). This note previously asserted the stock default was a SOLID
       --rz-primary and cited "material3-base.css:12945" while claiming verification "against the
       bundled 10.4.4 theme" — it was BACKWARDS, and the "earlier note" it overruled was right. Root
       cause: wwwroot/css/material3-*.css were ORPHAN DECOYS that no <link> ever loaded (App.razor
       loads the Radzen PACKAGE sheet _content/Radzen.Blazor/css/material-base.css), and the decoy
       disagreed with the real sheet on this very token. The decoys are DELETED at D45. Re-verified
       both directly and by radzen-expert against the bundled 10.4.4 material-base.css :root defaults
       block (sibling --rz-switch-background-color: var(--rz-base-400) confirms the block).
       Behaviour was never affected — the declaration below overrides the default either way. */
    --rz-switch-checked-background-color: var(--section-accent, var(--rently-primary));
    --rz-switch-checked-circle-background-color: #ffffff;
    --rz-button-base-background-color: var(--section-accent, var(--rently-primary));
}

/* Radzen inputs fill their grid cell (plain descendant — .rz-* are global classes, no ::deep) */
.rently-form .rz-form-field,
.rently-form .rz-textbox,
.rently-form .rz-textarea,
.rently-form .rz-dropdown,
.rently-form .rz-numeric {
    width: 100%;
}

/* RadzenButton → Nordic vocabulary (8px radius, Montserrat, no uppercase). The accent FILL comes
   from --rz-primary / --rz-button-base-background-color above; this only shapes the chrome. */
.rently-form .rz-button {
    border-radius: var(--rently-radius-md);
    font-family: var(--rently-font-display);
    font-weight: 600;
    text-transform: none;
    min-height: 40px;
}

/* Field cell — the locked "Framed" enclosure (Form System v2, user pick): a frost card with a white
   input well, so every field reads as a clearly-bounded module. Default form style for every section —
   any page that uses .rently-field inherits it. Ported faithfully from the showcase .rfx--framed.
   INVARIANT: assumes a WHITE (--rently-card-bg) parent surface. --rently-subtle-bg == --rently-shell-bg,
   so a .rently-field placed directly on the dashboard shell reads invisible (frost-on-frost) — wrap such
   fields in a .rently-card first. And do NOT darken --rently-subtle-bg without re-checking the hint
   #64748b contrast (4.52:1 on it — only ~0.02 above the 4.5:1 AA bar). */
.rently-field {
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-2);
    min-width: 0;                                        /* let inputs shrink inside a grid cell */
    background: var(--rently-subtle-bg);                 /* frost card */
    border: 1px solid var(--rently-border);
    border-radius: var(--rently-radius-lg);
    padding: var(--rently-space-4) var(--rently-space-5);
    --rz-input-height: 2.75rem;                          /* 44px — the input is its own touch target (SC 2.5.5) */
    --rz-input-background-color: var(--rently-card-bg);  /* white well inside the frost frame */
    transition: border-color var(--rently-transition-fast), box-shadow var(--rently-transition-fast);
}

.rently-field:focus-within {
    border-color: var(--section-accent, var(--rently-primary));
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--section-accent, var(--rently-primary)) 14%, transparent);
}

.rently-field--error {
    border-color: var(--rently-critical-text);
}

/* Error must beat :focus-within (equal specificity → guarantee it) so the red boundary stays while the
   user focuses the invalid field to fix it. */
.rently-field--error:focus-within {
    border-color: var(--rently-critical-text);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--rently-critical-text) 14%, transparent);
}

@media (prefers-reduced-motion: reduce) {
    .rently-field {
        transition: none;
    }
}

.rently-field--full {
    grid-column: 1 / -1;
}

/* ── Flat mode — for fields that already sit inside a card the caller owns ──────────────────────
   The per-day schedule tiles in Collection / Delivery / Pricing are themselves .rently-card-style
   tiles, so the default frost card stacks a card inside a card. Measured cost: a 40px time input
   rendered a 148px-tall field (24px padding + 2px border + 26px label head + 16px gaps + 52px body
   + 24px meta), ×40 pickers across the three tabs.

   This does NOT simply delete the enclosure the way .rently-field--switch does. A MudSwitch is
   self-contained, but Radzen's inputs are not: .rz-form-field.rz-variant-outlined and .rz-inputtext
   both compute to `border: 0px none` on a transparent background (measured live), so the frost card
   IS the input's only visual boundary. Deleting it would leave a bare input floating on white.
   So the border / background / focus ring / error ring all move DOWN onto .rently-field__body — our
   own element, present in every control mode — and the outer card goes away. Net: one less nesting
   level, ~26px saved per field, and identical affordance. ── */
.rently-field--flat {
    background: none;
    border: 0;
    border-radius: 0;
    padding: 0;
    box-shadow: none;
}

.rently-field--flat .rently-field__body {
    background: var(--rently-card-bg);
    border: 1px solid var(--rently-border);
    border-radius: var(--rently-radius-md);
    transition: border-color var(--rently-transition-fast), box-shadow var(--rently-transition-fast);
}

/* Suppress the outer ring (it would now halo the label too) and re-home it on the well. */
.rently-field--flat:focus-within {
    border-color: transparent;
    box-shadow: none;
}

.rently-field--flat:focus-within .rently-field__body {
    border-color: var(--section-accent, var(--rently-primary));
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--section-accent, var(--rently-primary)) 14%, transparent);
}

/* Error still beats focus, same guarantee as the un-flattened field. */
.rently-field--flat.rently-field--error {
    border-color: transparent;
}

.rently-field--flat.rently-field--error .rently-field__body,
.rently-field--flat.rently-field--error:focus-within .rently-field__body {
    border-color: var(--rently-critical-text);
}

.rently-field--flat.rently-field--error:focus-within .rently-field__body {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--rently-critical-text) 14%, transparent);
}

@media (prefers-reduced-motion: reduce) {
    .rently-field--flat .rently-field__body {
        transition: none;
    }
}

/* ── Flat section groups (opt-in) — de-cards MudExpansionPanels so sections read as flat groups
   with a heading row + hairline dividers instead of stacked cards. Pair with Elevation="0"
   Outlined="false" Gutters="false" on the MudExpansionPanels. The geometry rules are ≥(0,3,0)
   and beat the stock (0,2,0) Mud rules regardless of stylesheet order; the background override
   below is (0,2,0) vs a stock (0,1,0) — it wins on specificity today, but a future (0,2,0)
   panel-background rule in a later sheet would tie-and-beat it by order. First consumers: the
   catalogue filter panels (desktop drawer + mobile sheet). ── */
.rently-panels-flat .mud-expand-panel {
    background: transparent;
}

/* The stock expanded-panel 16px pop-out margin is the "detached card" look — kill it. */
.rently-panels-flat .mud-expand-panel.mud-panel-expanded {
    margin: 0;
}

.rently-panels-flat .mud-expand-panel + .mud-expand-panel {
    border-top: 1px solid var(--rently-border);
}

/* One shared 16px inset for header text and section content (stock gutters were 24px). */
.rently-panels-flat .mud-expand-panel .mud-expand-panel-header {
    padding: 12px 16px;
}

.rently-panels-flat .mud-expand-panel .mud-expand-panel-content {
    padding: 0 16px 14px;
}

/* Flat mode + Mud outlined input: __body carries the well border, so the Mud input's own outlined
   border would double it. border:none also zeroes border-STYLE, so the Mud-bridge focus/hover rules
   above (they set color/width only) cannot resurrect it — the focus affordance is the __body ring. */
.rently-field--flat .rently-field__body .mud-input.mud-input-outlined .mud-input-outlined-border {
    border: none;
}

/* Same guarantee for BARE Radzen inputs (adversarial-review catch, session 6): the catalogue
   filter panel puts RadzenTextBox / RadzenNumeric / date inputs directly in the well with NO
   RadzenFormField wrapper, and material-base.css borders .rz-textbox/.rz-numeric/.rz-inputtext
   directly (re-tinted by .rently-form's --rz-input-border) — a second frame flush inside the
   __body well border. (0,3,0) beats Radzen's (0,2,0) rest/hover/focus border swaps for the
   border property in EVERY state, and border:none also kills the material underline
   (border-block-end). RadzenFormField-WRAPPED controls already compute border:0 (session-3 V4
   measurement) — this is a no-op for them. */
.rently-field--flat .rently-field__body .rz-textbox,
.rently-field--flat .rently-field__body .rz-numeric,
.rently-field--flat .rently-field__body .rz-inputtext {
    border: none;
}

/* ── Field envelope (Form System v2) — a fixed-height head / body / meta stack so 2-column grid cells
   bottom-align by construction (the core "ragged form" fix). The head reserves the label + "?" line;
   the meta reserves the hint / error / counter line even when empty. ── */
.rently-field__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--rently-space-2);
    min-height: 1.6rem;                  /* reserves the label / "?" line so field heights match */
    margin-bottom: var(--rently-space-1);
}

/* The field label — uppercase Nordic micro-label (7.5:1). Used by the head row AND by the controls
   that carry no RadzenFormField (switch rows, the trust radio / slider spans). */
.rently-field__label {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--rently-tracking-wide);
    color: var(--rently-text-secondary);   /* #475569 — 7.5:1, never low-contrast (S7) */
    font-family: var(--rently-font-display);
    display: inline-flex;
    align-items: center;
}

/* Required marker — __req (v2 head) + __required (back-compat), both critical-text. */
.rently-field__req,
.rently-field__required {
    color: var(--rently-critical-text);
    margin-inline-start: 3px;
}

/* Inert wrapper around the control (parity with the showcase .rfx__body). */
.rently-field__body {
    min-width: 0;
}

/* Meta row — fixed reserved height; the always-visible hint + the live ValidationMessage sit in __msg,
   the supplementary counter sits right. The reserved min-height never collapses, even when empty. */
.rently-field__meta {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--rently-space-3);
    min-height: 1.15rem;
}

.rently-field__msg {
    min-width: 0;
}

.rently-field__hint {
    font-size: 0.78rem;
    color: var(--rently-text-tertiary);   /* #64748b — 4.52:1 on the #f8f9fb frost card (4.76:1 on white) */
    margin: 0;
}

/* Validation surface — ALWAYS visible (no display toggle): pages render a live Blazor ValidationMessage
   here, which must show whenever the field is invalid without per-field plumbing. */
.rently-field__error {
    font-size: 0.78rem;
    font-weight: 500;
    color: var(--rently-critical-text);   /* #dc2626 — 4.83:1 on white */
    margin: 0;
}

/* Char counter — supplementary (aria-hidden in markup), tabular so digits don't jitter. NOT
   --rently-text-muted (2.56:1, fails AA); tertiary 4.76:1 holds the bar (S4 / S7). */
.rently-field__counter {
    margin-left: auto;
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--rently-text-tertiary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.rently-field__counter--warn {
    color: var(--rently-warning-text);
}

.rently-field__counter--full {
    color: var(--rently-critical-text);
}

/* ── Radzen-internals fixes (Form System v2) — graduated from page-scope to global. Radzen .rz-* are
   global classes, so a plain descendant from .rently-field reaches them (no ::deep in this sheet). The
   row has no intrinsic height in Radzen 10.4.4, and the dropdown host clips a 2-line value. ── */
/* RadzenFormField renders display:inline-flex, so it SHRINK-WRAPS to its content instead of filling
   .rently-field__body — measured live at 233px inside a 1213px body, which reads as an unfinished
   half-width input. The inner input's own width:100% is innocent: it faithfully fills the 233px
   wrapper. Fixing it here rather than in 26 scoped sheets, because it affects every Radzen-mode
   field platform-wide (including pre-R3 consumers like AddAddress). Scoped to .rently-field, so
   RadzenFormFields outside the field system keep their intrinsic sizing. */
.rently-field .rz-form-field {
    display: flex;
    width: 100%;
}

.rently-field .rz-form-field-content {
    min-height: 2.75rem;                  /* row floor — independent of how tall the input computes */
}

.rently-field .rz-dropdown {
    height: auto;
    min-height: var(--rz-input-height);   /* one-line floor; grows for a 2-line value */
    overflow: visible;                    /* the real un-clip — host overflow:hidden was clipping line 2 */
}

.rently-field .rz-dropdown .rz-dropdown-label {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    height: auto;
    display: block;
    padding-block: 0.375rem;
}

/* Error-state input border ≥3:1 — for future pure-.rently-field forms that toggle .rently-field--error. */
.rently-field--error .rz-form-field-content {
    border-color: var(--rently-critical-text);
}

/* RadzenFormField renders an always-on empty <label for=""> when no Text/Component is set
   (AllowFloatingLabel="false" does NOT suppress it). We label externally via .rently-field__head, so
   hide the stray empty one. :empty guards against ever hiding a label that legitimately has text. */
.rently-field .rz-form-field .rz-form-field-label:empty {
    display: none;
}

/* ── MudBlazor outlined inputs inside .rently-field → the SAME Nordic white well the --rz-* vars give
   Radzen inputs (MudBlazor ignores --rz-*). Consolidated here from the per-page copies
   (StoreRequestWithdraw / StoreOrderDetails) so every Mud-in-field surface — INCLUDING dialogs that have
   no companion .razor.css (CancelOrderDialog / RejectOrderDialog) — reads identically. These .mud-* are
   global classes (no ::deep in this sheet). Focus uses :focus-within because Mud 9.4 does NOT render
   .mud-focused on an outlined input; the error guard is .mud-input-error (the real 9.4 class — .mud-error
   is inert) so a validated red border is never overridden by the accent. Pages that still carry a higher-
   specificity scoped copy win unchanged; this only lifts the un-bridged surfaces to the standard. ── */
.rently-field .mud-input.mud-input-outlined {
    background: var(--rently-card-bg);
    border-radius: var(--rently-radius-md);
    /* Gate A 2026-07-23: the 2.75rem floor Radzen inputs get from --rz-input-height /
       .rz-form-field-content — the visible height drift between Mud and Radzen filter cells. */
    min-height: 2.75rem;
}

.rently-field .mud-input.mud-input-outlined .mud-input-outlined-border {
    border-color: var(--rently-border);
    border-radius: var(--rently-radius-md);
    transition: border-color var(--rently-transition-fast);
}

.rently-field .mud-input.mud-input-outlined:hover:not(.mud-disabled):not(.mud-input-error) .mud-input-outlined-border {
    border-color: var(--rently-border-strong);
}

.rently-field .mud-input.mud-input-outlined:focus-within:not(.mud-input-error) .mud-input-outlined-border {
    border-color: var(--section-accent, var(--rently-primary));
    border-width: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .rently-field .mud-input.mud-input-outlined .mud-input-outlined-border {
        transition: none;
    }
}

/* Legacy direct switch rows remain flat and inline. Several older forms compose this class without
   RentlyField, so its contract cannot be repurposed by the framed component variant below. */
.rently-field--switch {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--rently-space-3);
    min-height: 44px;
    background: none;
    border: 0;
    padding: 0;
    box-shadow: none;
}

/* The shared RentlyField switch gets the polished field enclosure and a dedicated inner row.
   Keeping this as a modifier protects every legacy direct .rently-field--switch call site. */
.rently-field--switch-framed {
    flex-direction: column;
    align-items: stretch;
    min-height: 0;
    background: var(--rently-subtle-bg);
    border: 1px solid var(--rently-border);
    padding: var(--rently-space-4) var(--rently-space-5);
}

.rently-field__switch-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--rently-space-4);
    min-height: 44px;
}

.rently-field__switch-copy {
    display: flex;
    align-items: center;
    gap: var(--rently-space-2);
    min-width: 0;
}

.rently-field__switch-control {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
}

.rently-field--switch-framed.rently-field--switch-compact {
    flex-direction: row;
    align-items: center;
    min-height: 44px;
    background: none;
    border: 0;
    padding: 0;
    box-shadow: none;
}

.rently-field--switch-framed.rently-field--switch-compact .rently-field__switch-row {
    width: 100%;
}

.rently-field__switch-label {
    display: flex;
    align-items: center;
    min-height: 44px;
    margin: 0;
    cursor: pointer;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--rently-text-body);
    font-family: var(--rently-font-display);
}

/* Two-column responsive form grid + right-aligned action row */
.rently-form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--rently-space-6);
}

.rently-form-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: var(--rently-space-2);
}

@media (max-width: 960px) {
    .rently-form-grid {
        grid-template-columns: 1fr;
    }

    /* Touch-target parity with .rently-btn — Radzen form buttons reach 44px at tablet-and-below */
    .rently-form .rz-button {
        min-height: 44px;
    }
}

/* ═════════════════════════════════════════════════════════════════════════
   FORM SUCCESS ALERT — accessible Radzen success popup (Form System v2)
   ─────────────────────────────────────────────────────────────────────────
   Radzen's lighter-flat success alert paints its message, leading icon and close glyph in mid-green
   (~#4caf50) over a 16%-green wash → ~2.39:1, failing SC 1.4.3 (text) / 1.4.11 (icons). Retint the
   foreground to --rently-ok-text-strong (#146c37 ≈ 5.59:1 on the wash) so the popup stays crisp while
   keeping its light-green success identity. Reusable: any form sets Class="rently-form-alert" on a
   RadzenAlert and wraps its content in .rently-form-alert__content. The .rz-* part names are global
   Radzen classes — plain descendants reach them (no ::deep in this sheet).
   ═════════════════════════════════════════════════════════════════════════ */
.rently-form-alert {
    margin-bottom: 0;
}

.rently-form-alert__content {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--rently-space-2);
    width: 100%;
    color: var(--rently-ok-text-strong);   /* the message <span> inherits this */
}

.rently-form-alert .rz-alert-icon,
.rently-form-alert .rz-button {
    /* leading status icon + the custom dismiss button. !important pins the colour across rest/hover/
       focus — Radzen's text-variant success :hover rule out-specifies a plain override and would revert
       the close × to the failing ~2.39:1 mid-green. */
    color: var(--rently-ok-text-strong) !important;
}

/* ═════════════════════════════════════════════════════════════════════════
   FORM DANGER ALERT — accessible Radzen danger popup (the danger mirror of
   .rently-form-alert above)
   ─────────────────────────────────────────────────────────────────────────
   Radzen's lighter-flat Danger alert paints its message + leading icon ~#f44336
   over a 20%-red wash → ~3.15:1, failing SC 1.4.3 (text) / 1.4.11 (icons).
   Retint the foreground to --rently-critical-text-strong (#b91c1c, ≈5:1 on the
   wash) so the banner stays crisp while keeping its red danger identity. The token
   flips LIGHT (#fca5a5, red-300) under [data-theme="dark"], so the danger alert
   stays AA on the dark danger wash (≈6.56:1 card / ≈8.18:1 page, accessibility-expert
   verified) — a bare #b91c1c here could not flip and went dark-on-dark (C5 dark
   spot-check, G1). Reusable: set
   Class="rently-form-alert rently-form-alert--danger" on a RadzenAlert
   (AlertStyle.Danger, Shade.Lighter — the translucent-wash shade this retint targets).
   The part names are the verified Radzen 10.4.4 alert parts (.rz-alert-message /
   -title / -icon) — global classes reached by plain descendants (no ::deep in this
   sheet). Promoted from the locked AddressForms example (item 12a Pt3).
   ═════════════════════════════════════════════════════════════════════════ */
.rently-form-alert--danger,
.rently-form-alert--danger .rz-alert-message,
.rently-form-alert--danger .rz-alert-title,
.rently-form-alert--danger .rz-alert-icon,
.rently-form-alert--danger .rzi,
.rently-form-alert--danger i {
    color: var(--rently-critical-text-strong) !important;
}

/* ═════════════════════════════════════════════════════════════════════════
   FIELD-HELP "?" AFFORDANCE — global skin for RentlyFieldHelp (Form System v2)
   ─────────────────────────────────────────────────────────────────────────
   GLOBAL (not scoped): the MudTooltip surface is portaled out of the consuming
   component via MudPopoverProvider, so a scoped *.razor.css rule can never reach
   it. The trigger button is also styled here so every form across the platform
   gets the same 44px, accent-on-hover help control.

   The "?" glyph rests neutral (--rently-text-tertiary, 4.76:1) and goes section-
   accent on hover/focus (--section-accent-text, resolved from the wrapping shell);
   the 44px transparent button reads visually as just the glyph until interacted.
   ═════════════════════════════════════════════════════════════════════════ */
.rently-help-trigger-wrap {
    display: inline-flex;
    align-items: center;
    line-height: 0;
}

.rently-help-trigger.mud-icon-button {
    width: 44px;                       /* SC 2.5.5 / house C-8 hit area */
    height: 44px;
    padding: 0;
    color: var(--rently-text-tertiary);
    background-color: transparent;
}

.rently-help-trigger .mud-icon-root {
    font-size: 20px;                   /* small glyph inside the generous hit area */
    color: inherit;
}

.rently-help-trigger.mud-icon-button:hover,
.rently-help-trigger.mud-icon-button:focus-visible {
    color: var(--section-accent-text, var(--rently-primary-dark));
    background-color: color-mix(in srgb, var(--section-accent, var(--rently-primary)) 8%, transparent);
}

.rently-help-trigger.mud-icon-button:focus-visible {
    outline: 2px solid var(--section-accent-text, var(--rently-primary-dark));
    outline-offset: 2px;
}

/* Nordic tooltip surface (white card, hairline border, Montserrat). max-width caps rich content —
   MudTooltip 9.4 has no MaxWidth param. text-align:left because help is a sentence, not a label. */
.mud-tooltip.rently-help-tip {
    background-color: var(--rently-card-bg);
    color: var(--rently-text-body);
    border: 1px solid var(--rently-border);
    border-radius: var(--rently-radius-md);
    box-shadow: var(--rently-shadow-2);
    font-family: var(--rently-font-display);
    font-size: 0.78rem;
    line-height: 1.45;
    text-align: left;
    padding: var(--rently-space-3) var(--rently-space-4);
    max-width: 280px;
}

.rently-help-body__title {
    font-weight: 700;
    color: var(--rently-text-strong);
    margin-bottom: 2px;
}

.rently-help-body__text {
    color: var(--rently-text-secondary);
}

/* ═════════════════════════════════════════════════════════════════════════
   HANDOVER-LOCATION DROPDOWN ROWS (F6, 2026-07-25) — GLOBAL BY NECESSITY
   ─────────────────────────────────────────────────────────────────────────
   HandoverLocationPicker (store side) and HandoverLocationSelector (renter side)
   both render a two-line meeting-spot row inside their MudSelect items. Those rows
   CANNOT be styled from the components' own *.razor.css: MudSelect renders its
   popover through MudPopoverProvider, which lives at the app root
   (Layout/Shared/MudRadzenHeaders.razor) — the markup is portaled clean out of the
   component subtree, so neither a scoped selector nor ::deep can reach it. The hook
   is PopoverClass, which MudSelect 9.7 puts on the .mud-popover ROOT.

   Verified chain (mudblazor-expert, 9.7.0):
     .mud-popover.<PopoverClass>
       > .mud-list
         > .mud-list-item[role="option"]
           > .mud-list-item-text
             > p.mud-typography-body1     ← unavoidable; MudSelectItem always wraps
               > .hlp-option / .hls-option

   That <p> is why the row markup is built from SPANS: a block element inside a <p>
   is re-parented by the HTML parser during prerender. It is also why the type scale
   is restated below — the row inherits body1 (1rem) from the wrapper, not the
   body2/caption the old MudText nodes carried.
   ═════════════════════════════════════════════════════════════════════════ */
/* S11-03 c2 — moved here from CreateOrderPage's inline style element. It caps the
   address MudSelect's popover so a long address book cannot run off-screen.
   It has to be GLOBAL: HandoverLocationSelector owns the control (that file,
   :143, PopoverClass="address-select-popover hls-popover") and
   MudPopoverProvider PORTALS the panel out of the consuming page's subtree, so
   no scoped sheet can reach it. Living in CreateOrderPage also meant the rule
   only existed while that page happened to be rendered; here it travels with
   the component, which is where it belonged. */
.address-select-popover {
    max-height: 400px !important;
    overflow-y: auto !important;
}

.hlp-popover .hlp-option,
.hls-popover .hls-option {
    display: flex;
    align-items: flex-start;
    gap: var(--rently-space-2);
    min-width: 0;
}

.hlp-popover .hlp-option__icon,
.hls-popover .hls-option__icon {
    flex: none;
    margin-top: 2px;
}

.hlp-popover .hlp-option__icon--public,
.hls-popover .hls-option__icon--public {
    color: var(--rently-ok-text-strong);
}

.hlp-popover .hlp-option__icon--private,
.hls-popover .hls-option__icon--private {
    color: var(--rently-primary);
}

/* Was MudStack Spacing="0": the spot name and its address were welded together with no
   gap at all, which is the "squished" half of the reported defect. */
.hlp-popover .hlp-option__body,
.hls-popover .hls-option__body {
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-1);
    min-width: 0;
}

.hlp-popover .hlp-option__head,
.hls-popover .hls-option__head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--rently-space-2);
    min-width: 0;
}

.hlp-popover .hlp-option__name,
.hls-popover .hls-option__name {
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1.4;
    color: var(--rently-text-strong);
}

.hlp-popover .hlp-option__address,
.hls-popover .hls-option__address {
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--rently-text-body);
    /* .mud-list-item forces nowrap on its text; an address is the one thing in the row
       that should wrap rather than be truncated mid-suburb. */
    white-space: normal;
}

/* The hard height: 18px these chips carried sat BELOW their own line box, so the label
   was clipped by its own container. Only the type scale is ours now; the box comes from
   Mud's .mud-chip-size-small. The margin reset hands spacing to the flex gap above,
   replacing .mud-chip's stock 4px margin. */
.hlp-popover .hlp-option__chip,
.hls-popover .hls-option__chip {
    flex: none;
    margin: 0;
    font-size: 0.65rem;
}

/* Rows are now two-line with a real gap, so the item box has to align to the top and
   give the taller content room instead of vertically centring a clipped single line. */
.hlp-popover .mud-list-item[role="option"],
.hls-popover .mud-list-item[role="option"] {
    align-items: flex-start;
}

/* ============================================================
   Security-page kit (S7-03) — the note / card / section
   vocabulary the 2FA suite shares with the ManageAccount
   Security fragment.

   GLOBAL on purpose. The originals are `.ama-*` inside
   ManageAccount.razor.css, and Blazor scoped CSS does not
   cascade across components, so the seven 2FA pages could only
   reuse that look by each carrying its own copy — seven places
   to update, which is exactly how a design standard rots. These
   live beside the existing global .rently-field / .rently-btn /
   .rently-card kit that the same pages already use.

   Status is never colour-only: every note pairs a colour with an
   icon and a role (note / status / alert).
   ============================================================ */

.rently-sec-section {
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-4);
}

.rently-sec-section + .rently-sec-section {
    margin-top: var(--rently-space-7);
}

.rently-sec-section__title {
    margin: 0;
    font-family: var(--rently-font-display);
    font-weight: 700;
    font-size: 1rem;
    color: var(--rently-text-strong);
}

.rently-sec-section__lead {
    margin: 0;
    font-size: 0.85rem;
    line-height: var(--rently-leading-relaxed);
    color: var(--rently-text-secondary);
}

/* Flat card — single depth, hover lift suppressed (the ManageAccount decision: a raised inner card
   on an already-white settings surface reads as a faint double frame). */
.rently-sec-card {
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-3);
    padding: var(--rently-space-5);
    border: 1px solid var(--rently-border);
    border-radius: var(--rently-radius-lg);
    background: var(--rently-card-bg);
}

.rently-sec-card:hover {
    box-shadow: none;
}

.rently-sec-card__title {
    display: inline-flex;
    align-items: center;
    gap: var(--rently-space-2);
    font-family: var(--rently-font-display);
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--rently-text-strong);
}

.rently-sec-card__title .mud-icon-root {
    color: var(--rently-text-strong);
}

.rently-sec-card__body {
    margin: 0;
    font-size: 0.82rem;
    line-height: var(--rently-leading-relaxed);
    color: var(--rently-text-secondary);
}

.rently-sec-card__body strong {
    color: var(--rently-text-strong);
    font-weight: 700;
}

.rently-sec-card__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--rently-space-2);
}

/* Consequence lists on the destructive flows — "here is exactly what happens if you continue". */
.rently-sec-consequences {
    margin: 0;
    padding-left: var(--rently-space-6);
    display: flex;
    flex-direction: column;
    gap: var(--rently-space-2);
}

.rently-sec-consequences li {
    font-size: 0.82rem;
    line-height: var(--rently-leading-relaxed);
    color: var(--rently-text-secondary);
}

.rently-sec-consequences strong {
    color: var(--rently-text-strong);
    font-weight: 700;
}

/* Inline note rows. */
.rently-note {
    display: flex;
    align-items: flex-start;
    gap: var(--rently-space-2);
    padding: var(--rently-space-3) var(--rently-space-4);
    border-radius: var(--rently-radius-md);
    font-size: 0.82rem;
    line-height: var(--rently-leading-snug);
}

.rently-note .mud-icon-root {
    flex-shrink: 0;
}

.rently-note--info {
    background: var(--rently-info-bg, rgba(59, 130, 246, 0.08));
    border: 1px solid color-mix(in srgb, var(--rently-info, #3b82f6) 30%, var(--rently-border));
    color: var(--rently-info-text, #1d4ed8);
}

.rently-note--info .mud-icon-root {
    color: var(--rently-info-text, #1d4ed8);
}

/* Dark-mode info ink is pinned to a literal rather than --rently-info-text.
   A note's contrast depends on the surface it is NESTED ON, not just its own translucent fill: the
   token ink measured 5.24:1 on the page background but only 4.26:1 once the same note sat inside a
   .rently-sec-card / .ea-step (a lighter surface), which is below AA. This literal clears 4.5:1 on the
   lightest surface these notes are used on, so the kit is safe wherever it is dropped. */
[data-theme="dark"] .rently-note--info,
[data-theme="dark"] .rently-note--info .mud-icon-root {
    color: #7ba9f9;
}

.rently-note--warning {
    background: var(--rently-warning-bg, rgba(245, 158, 11, 0.08));
    border: 1px solid color-mix(in srgb, var(--rently-warning, #f59e0b) 30%, var(--rently-border));
    color: var(--rently-warning-text, #b45309);
}

.rently-note--warning .mud-icon-root {
    color: var(--rently-warning-text, #b45309);
}

.rently-note--error {
    background: var(--rently-critical-bg, rgba(239, 68, 68, 0.08));
    border: 1px solid color-mix(in srgb, var(--rently-critical, #ef4444) 30%, var(--rently-border));
    color: var(--rently-critical-text, #b91c1c);
}

.rently-note--error .mud-icon-root {
    color: var(--rently-critical-text, #b91c1c);
}

.rently-note--ok {
    background: var(--rently-ok-bg, rgba(22, 163, 74, 0.08));
    border: 1px solid color-mix(in srgb, var(--rently-ok, #16a34a) 30%, var(--rently-border));
    color: var(--rently-ok-text-strong, #146c37);
}

.rently-note--ok .mud-icon-root {
    color: var(--rently-ok-text-strong, #146c37);
}

/* ── Empty values (S11-04) ───────────────────────────────────────────────────────────────────────
   The styling half of <RentlyEmptyValue>, which replaced the em dash that used to stand in for a
   missing value in ~88 places. GLOBAL rather than a *.razor.css, for the ordinary reason: the
   component renders inside dozens of other components' scopes, and scoped CSS does not cascade
   across components.

   Two properties carry the whole idea and neither is decorative:

   · TERTIARY ink, so an absent value recedes behind values that actually exist. It must still clear
     AA — this is real content a member has to read, not a decorative glyph — which is why it uses
     the tertiary TOKEN rather than a lighter one-off grey.
   · font-weight 400 and the SAME font-size as its host, inherited. The dash's real sin was being
     rendered at display weight inside stat tiles and KPI cards, where "—" read as a broken value
     rather than an empty one. An empty value must never look like a headline.

   Deliberately NOT italic: italic at small sizes hurts legibility for dyslexic readers and buys
   nothing here — the wording already says it is empty. */
.rently-empty-value {
    color: var(--rently-text-tertiary);
    font-weight: 400;
    font-style: normal;
}

/* Stat tiles and KPI cards set a large display size on the value slot. Inherit that box but not the
   type scale, so the empty state sits on the same baseline without shouting. */
.rently-kpi__value .rently-empty-value,
.rently-stat__value .rently-empty-value,
.adm-kpi__value .rently-empty-value {
    font-size: 0.875rem;
    letter-spacing: normal;
}

/* Inline links inside security copy. Literal inks, not --rently-primary: the palette engine re-projects
   that token at runtime (live-measured #35a0ae = 3.09:1), which fails AA for body-size text. These two
   are the house-locked pair — #256f7a is 5.78:1 on white, #74d0dc is the dark lift. */
.rently-link {
    color: #256f7a;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.rently-link:hover {
    text-decoration-thickness: 2px;
}

[data-theme="dark"] .rently-link {
    color: #74d0dc;
}

/* ═════════════════════════════════════════════════════════════════════════
   FACT VOCABULARY — the read-only name/value pair (S12-04c)
   ─────────────────────────────────────────────────────────────────────────
   A "fact" is the read-only twin of a form field: a short name and the value
   it belongs to, with no control and nothing to submit. The field vocabulary
   above already owns the WRITE side of that shape; this owns the READ side,
   and the two are deliberately built to the same rhythm (uppercase micro-label
   over a heavier value) so a page that shows a value and a page that edits it
   do not look like two different products.

   WHY THIS IS GLOBAL, and why it exists at all. The recipe was authored three
   times inside three scoped sheets: `.rops-fact` in RentalOptionsPoliciesSection,
   `.rd-fact` in RentalSpecificationsSection, and a third copy was about to be
   written on RentalDetailsPage. Two of those carried a written "change one,
   change both" contract in their comments — which is the honest admission that
   the abstraction was missing, because a contract a human has to remember is
   not a contract. Scoped CSS cannot cascade across components, so the ONLY
   place one shared recipe can live is here.

   TWO SHAPES, not one:
     .rently-fact       — the bare pair. No enclosure. For a dense grid of many
                          facts (a specification list, a policy card body) where
                          boxing each one would out-shout the content.
     .rently-fact-tile  — the frost WELL. For a small set of headline numbers
                          (rates, totals, counts) that should read as figures.
   Reach for the tile when the value is a number the user came to find, and the
   bare pair when the value is prose they will scan.

   ⚠ SURFACE INVARIANT — the same one .rently-field carries, for the same
   reason. --rently-subtle-bg (#f8f9fb) is one hair off --rently-shell-bg
   (#f5f5f5), so a frost tile dropped straight onto a page shell is invisible.
   .rently-fact-tile is for NESTING inside a WHITE (--rently-card-bg) surface —
   a .rently-card, a MudTabs outlined panel, a policy card. The bare
   .rently-fact has no surface of its own and is safe anywhere.

   GEOMETRY IS LITERAL px, INK IS TOKENIZED. Every colour below names a
   --rently-* token, so dark mode is correct by construction with no mirrored
   override block. The lengths stayed literal on purpose: this promotion has to
   compute IDENTICALLY to the copies it replaces, and the --rently-space-*
   tokens are rem-based, so swapping 12px for var(--rently-space-4) would
   silently rescale every consumer under a non-16px root font size. That is a
   change worth making deliberately one day; it is not one to smuggle in under
   a de-duplication.

   ALIASED, NOT COPIED. `.rd-facts` and friends ride along on the selector
   lists below rather than being restyled in place, because
   RentalSpecificationsSection.razor's markup is owned elsewhere and could not
   be renamed in this change. They are aliases on the one rule, not a second
   copy of it — the whole point. RentalOptionsPoliciesSection took the clean
   route and renamed its markup, so it carries no aliases here.
   ═════════════════════════════════════════════════════════════════════════ */

/* The <dl>. auto-fit rather than a fixed column count: a card with two facts
   should not render two-thirds of an empty row, and the same rule has to serve
   both a 2-fact policy card and a 30-row specification list. */
.rently-facts,
.rd-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 12px 24px;
    margin: 0;                  /* reset the UA <dl> margin */
}

/* min-width:0 is load-bearing, not defensive: a grid item's default min-width
   is auto, so one unbreakable value (a long URL, a 30-character SKU) would
   otherwise widen its track and drag every sibling column out of alignment. */
.rently-fact,
.rd-fact {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.rently-fact__label,
.rd-fact__label {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
    color: var(--rently-text-tertiary);   /* #64748b — 4.76:1 on white, 4.52:1 on frost */
}

/* overflow-wrap:anywhere is the other half of the min-width:0 pair — that one
   lets the track stay narrow, this one lets the text inside it break. */
.rently-fact__value,
.rd-fact__value {
    margin: 0;                  /* reset the UA <dd> indent */
    font-weight: 600;
    color: var(--rently-text-primary);
    overflow-wrap: anywhere;
}

/* ── The tile variant ────────────────────────────────────────────────────
   A tighter 160px minimum than the bare .rently-facts grid, because tiles hold
   short figures rather than prose and a 200px track would leave a money value
   swimming in its own box. */
.rently-fact-tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 12px;
}

.rently-fact-tile {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 14px 16px;
    border: 1px solid var(--rently-border);
    border-radius: 12px;
    background: var(--rently-subtle-bg);   /* frost — see the surface invariant above */
}

/* Wider tracking than .rently-fact__label (0.08em vs 0.06em). The tile label
   sits above a 1.25rem value rather than a 1rem one, and the heavier optical
   weight below it needs the extra air to stay legible as a caption. */
.rently-fact-tile__label {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
    color: var(--rently-text-tertiary);
}

/* tabular-nums so a column of money aligns on the decimal. Without it the
   proportional digits in Montserrat make R 1 199,00 and R 250,00 ragged. */
.rently-fact-tile__value {
    font-size: 1.25rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--rently-text-primary);
}

/* The trailing qualifier on a figure — "per day", "km", "incl. VAT". Sized and
   inked to recede so the number, not its unit, is what the eye lands on. */
.rently-fact-tile__unit {
    font-size: 0.85rem;
    color: var(--rently-text-tertiary);
}
