/* Money journey — the shared visual system for /credits, /wallet and /subscriptions.
 *
 * IMP-0622. These three routes are one journey (top up, see where the money went,
 * change what you pay for) and used to be three unrelated products: a promotional
 * storefront with gradient hero numerals, an administrative key/value dashboard, and a
 * 600px-wide compact plan list. Each invented its own card border weight, radius, badge
 * shape, big-number scale, hover behaviour, spinner and empty state.
 *
 * Everything visual that is NOT specific to one route lives here, so the three route
 * stylesheets hold only what genuinely differs (a ledger needs filters; a plan list does
 * not). The rule for adding to a route stylesheet: if the same thing could appear on
 * another money page, it belongs in this file.
 *
 * Design language: docs/design/MYSTRIX_DESIGN_LANGUAGE.md. The brief's palette,
 * typography roles and radii are resolved once in the token block below.
 */

/* ---------------------------------------------------------------------------
 * Tokens
 *
 * Scoped to .money-page rather than :root on purpose: root.css is the single source
 * of truth for global variables, and the general reader-page token system (IMP-0619)
 * owns the job of putting the design language's palette there. Each token below reads
 * the shared name first and falls back to the brief's own hex, so these pages render
 * the language's colours today and inherit the shared definitions the moment IMP-0619
 * lands them — no duplicate declaration, no "just in case" second palette.
 * ------------------------------------------------------------------------- */

/* The token scope. `.toast-container` is listed alongside `.money-page` because dom.js
   injects the toast stack straight into <body>, outside the page wrapper — without this
   it would be the one money component that could not read the money tokens. */
.money-page,
.toast-container {
    /* Palette — docs/design/MYSTRIX_DESIGN_LANGUAGE.md § Color. */
    /* --parchment is deliberately absent: the brief reserves it for cinematic hero
       moments and printed/export views, and a money page is neither. A token declared
       "just in case" is the grab-bag habit the brief is retiring. */
    --money-ink: var(--ink, #0b0a10);
    --money-amethyst: var(--amethyst, #9b7ef5);
    --money-amethyst-deep: var(--amethyst-deep, #5b3fb0);
    --money-ember: var(--ember, #e8935f);
    --money-verdigris: var(--verdigris, #4fae94);
    --money-danger: var(--error);

    /* Tints of the five above. Declared once here so no money stylesheet ever
       hand-mixes an alpha, and so the retired grab-bag accents (--accent-blue,
       --accent-yellow, --accent-pink, --accent-orange, --accent-green) have no
       reason to appear on a money page at all. */
    --money-amethyst-wash: rgba(155, 126, 245, 0.09);
    --money-amethyst-edge: rgba(155, 126, 245, 0.42);
    --money-amethyst-glow: rgba(155, 126, 245, 0.16);
    --money-ember-wash: rgba(232, 147, 95, 0.12);
    --money-ember-edge: rgba(232, 147, 95, 0.4);
    --money-verdigris-wash: rgba(79, 174, 148, 0.1);
    --money-verdigris-edge: rgba(79, 174, 148, 0.42);
    --money-danger-wash: var(--tint-error-100);
    --money-danger-edge: var(--tint-error-300);

    /* Surfaces. One raised colour, one recessed colour, one edge. The recessed surface
       is --ink itself: near-black with a violet cast rather than the neutral gray-black
       these pages used, which is the whole point of the brief naming the colour. The
       raised surface stays the product-wide card colour so IMP-0619's retone reaches
       these pages instead of being forked here. */
    --money-surface: var(--bg-card);
    --money-surface-sunken: var(--money-ink);
    --money-line: var(--border);

    /* Typography — § Typography. Display for figures and page/plan names, UI for
       everything else. The shared --font-display / --font-ui names are read first so
       self-hosted Fraunces and Inter apply here automatically once they ship; until
       then the fallback chain still keeps figures in a serif and chrome in a sans, which
       is the distinction the brief is actually making. */
    --money-font-display: var(--font-display, 'Fraunces', 'Source Serif 4', Georgia, 'Times New Roman', serif);
    --money-font-ui: var(--font-ui, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);

    /* One figure ramp for all three routes. Before this, the same class of number was
       3.5rem on /credits, 2.25rem on /wallet and 1.5rem on /subscriptions. */
    --money-figure-xl: 3.25rem;
    --money-figure-lg: 2rem;
    --money-figure-sm: 1.5rem;

    /* One spacing ramp. § Layout principles: reader-facing surfaces earn generous
       whitespace and a single clear focal column. */
    --money-pad: 1.5rem;
    --money-pad-tight: 1.125rem;
    --money-gap: 1rem;
    --money-gap-section: 2.5rem;
}

/* One column, one width, one reading rhythm on all three routes. /credits used to be a
   full-bleed two-column storefront with a promotional rail, /wallet a full-bleed 2x2
   dashboard, and /subscriptions a 600px strip. */
.money-page {
    max-width: 76rem;
    margin-inline: auto;
    font-family: var(--money-font-ui);
}

/* ---------------------------------------------------------------------------
 * Actions
 *
 * main.css paints every .btn-primary with a violet-to-pink gradient and a coloured
 * shadow. Pink is one of the accents § Color retires, and on a money page the primary
 * action is the one place amethyst most needs to mean "this is the thing that costs
 * money" — so on these routes the CTA is the brand colour, flat, with no second hue.
 * ------------------------------------------------------------------------- */

.money-page .btn-primary {
    background: var(--money-amethyst);
    color: var(--money-ink);
    box-shadow: none;
    font-weight: 600;
}

.money-page .btn-primary:hover {
    background: var(--money-amethyst-deep);
    color: var(--text);
    box-shadow: none;
    transform: none;
}

.money-page .btn-primary:active {
    background: var(--money-amethyst-deep);
    color: var(--text);
}

.money-page .btn-primary:focus-visible,
.money-page .btn-secondary:focus-visible {
    outline: 2px solid var(--money-amethyst);
    outline-offset: 2px;
}

.money-page .btn-secondary {
    background: var(--money-surface-sunken);
    border: 1px solid var(--money-line);
    color: var(--text);
}

.money-page .btn-secondary:hover {
    background: var(--money-amethyst-wash);
    border-color: var(--money-amethyst-edge);
}

/* ---------------------------------------------------------------------------
 * The journey strip
 *
 * The single clearest statement that these are one place. Present on all three routes
 * with the same three destinations in the same order, so moving between them is a
 * lateral step rather than arriving somewhere new.
 * ------------------------------------------------------------------------- */

.money-journey {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    padding: 0.25rem;
    margin-bottom: var(--money-gap);
    background: var(--money-surface-sunken);
    border: 1px solid var(--money-line);
    border-radius: var(--radius);
}

.money-journey-step {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.9rem;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    font-size: 0.875rem;
    text-decoration: none;
    transition: background var(--transition-fast), color var(--transition-fast);
}

.money-journey-step i {
    font-size: 0.9em;
    opacity: 0.85;
}

.money-journey-step:hover {
    background: var(--money-amethyst-wash);
    color: var(--text);
}

.money-journey-step[aria-current="page"] {
    background: var(--money-amethyst-wash);
    border: 1px solid var(--money-amethyst-edge);
    color: var(--text);
    font-weight: 600;
}

.money-journey-step:focus-visible {
    outline: 2px solid var(--money-amethyst);
    outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * Page header and section rhythm
 * ------------------------------------------------------------------------- */

.money-lede {
    margin-bottom: var(--money-gap-section);
}

.money-lede .page-title {
    font-family: var(--money-font-display);
    font-weight: 600;
    letter-spacing: -0.01em;
    margin-bottom: 0.35rem;
}

/* main.css clips the page-title icon to a --primary/--secondary (violet-to-pink)
   gradient. Pink is one of the accents the design language retires, and a money page
   should open on the brand colour it then uses for every CTA below. */
.money-lede .page-title i {
    background: none;
    -webkit-text-fill-color: currentColor;
    color: var(--money-amethyst);
}

.money-lede-note {
    color: var(--text-secondary);
    font-size: 0.95rem;
    max-width: 46ch;
}

.money-section {
    margin-bottom: var(--money-gap-section);
}

.money-section:last-child {
    margin-bottom: 0;
}

.money-section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: var(--money-gap);
}

.money-section-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--money-font-display);
    font-size: 1.125rem;
    font-weight: 600;
    letter-spacing: -0.005em;
}

.money-section-title i {
    color: var(--money-amethyst);
    font-size: 0.85em;
}

.money-section-note {
    color: var(--text-muted);
    font-size: 0.85rem;
}

/* ---------------------------------------------------------------------------
 * The card
 *
 * One treatment for "something a reader can buy or manage": a top-up package, a
 * subscription plan, a wallet account panel. Same surface, same 1px edge, same 16px
 * radius, same internal rhythm. What differs between routes is the CONTENT slotted
 * into it, which is the difference that should be visible.
 * ------------------------------------------------------------------------- */

.money-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: var(--money-gap);
}

.money-grid-wide {
    grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
}

.money-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: var(--money-pad);
    background: var(--money-surface);
    border: 1px solid var(--money-line);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

/* The state rule. A 3px inline-start bar marking a card the reader has chosen or is
   already paying for — deliberately a quiet, static echo of the product's forking rule,
   not the rule itself: the design language spends that motion in exactly one place, the
   live choice moment, and money chrome stays disciplined by contrast. */
.money-card::before {
    content: '';
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: 3px;
    background: transparent;
}

/* min-height keeps the figure below it on the same baseline whether or not the card
   carries a tag, so a row of packages reads as a comparable set. */
.money-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    min-height: 1.6rem;
}

.money-card-name {
    font-family: var(--money-font-display);
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--text);
}

.money-card-note {
    color: var(--text-muted);
    font-size: 0.85rem;
    line-height: 1.5;
}

.money-card-list {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0;
    margin: 0;
}

.money-card-list li {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    color: var(--text-secondary);
    font-size: 0.85rem;
}

.money-card-list li i {
    width: 1rem;
    color: var(--money-verdigris);
    font-size: 0.8em;
    text-align: center;
}

/* Push the action to the bottom so cards of unequal content still line their
   buttons up across a row. */
.money-card-action {
    margin-top: auto;
    padding-top: 0.25rem;
}

.money-card-action .btn {
    width: 100%;
}

/* Selectable: a top-up package, a subscription plan. The two routes reach the purchase
   differently on purpose — a package IS the button (picking one loads the checkout
   summary below it), a plan carries its own action because choosing one commits
   immediately — so the pointer cursor is claimed only by the card that is itself
   clickable. The visual treatment is identical either way. */
.money-card--offer {
    width: 100%;
    text-align: start;
    color: inherit;
    font: inherit;
    font-family: var(--money-font-ui);
    appearance: none;
    transition: border-color var(--transition-base), transform var(--transition-base), box-shadow var(--transition-base);
}

button.money-card--offer {
    cursor: pointer;
}

/* Pressed. --amethyst-deep is the brief's dark variant of the brand colour, and this is
   what it is for: the moment a reader's finger is down on something that costs money. */
button.money-card--offer:active {
    border-color: var(--money-amethyst-deep);
    transform: translateY(0);
    box-shadow: none;
}

.money-card--offer:hover {
    border-color: var(--money-amethyst-edge);
    transform: translateY(-2px);
    box-shadow: 0 10px 28px var(--money-amethyst-glow);
}

.money-card--offer:focus-visible {
    outline: 2px solid var(--money-amethyst);
    outline-offset: 3px;
}

.money-card--offer[aria-pressed="true"],
.money-card--offer.is-selected {
    border-color: var(--money-amethyst-edge);
    background: var(--money-amethyst-wash);
}

.money-card--offer[aria-pressed="true"]::before,
.money-card--offer.is-selected::before {
    background: var(--money-amethyst);
}

/* Already yours: the active plan, the funded balance. Verdigris is the language's one
   cool accent, reserved for positive state — it is what "this is working" looks like. */
.money-card--current {
    border-color: var(--money-verdigris-edge);
    background: var(--money-verdigris-wash);
}

.money-card--current::before {
    background: var(--money-verdigris);
}

.money-card--current:hover {
    transform: none;
    box-shadow: none;
}

/* Not selectable right now: a scheduled downgrade, a plan you already left. */
.money-card--muted {
    opacity: 0.72;
}

/* The one page-level summary card: the balance or the current subscription. Spans the
   grid and carries the xl figure. One per page. */
.money-card--headline {
    grid-column: 1 / -1;
    padding: var(--money-pad) var(--money-pad) calc(var(--money-pad) + 0.25rem);
    background: var(--money-surface);
    border-color: var(--money-amethyst-edge);
}

.money-card--headline::after {
    content: '';
    position: absolute;
    inset-block-start: -55%;
    inset-inline-end: -12%;
    width: 20rem;
    height: 20rem;
    background: radial-gradient(circle, var(--money-amethyst-glow) 0%, transparent 68%);
    pointer-events: none;
}

.money-card--headline > * {
    position: relative;
}

/* ---------------------------------------------------------------------------
 * Figures
 *
 * The number a money page exists to show. Display face, tabular numerals so digits do
 * not jitter when a balance updates, and a unit that never competes with the value.
 * ------------------------------------------------------------------------- */

.money-figure {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.money-figure-value {
    font-family: var(--money-font-display);
    font-size: var(--money-figure-lg);
    font-weight: 600;
    line-height: 1.05;
    letter-spacing: -0.02em;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.money-figure-xl .money-figure-value {
    font-size: var(--money-figure-xl);
}

.money-figure-sm .money-figure-value {
    font-size: var(--money-figure-sm);
}

.money-figure-unit {
    color: var(--text-muted);
    font-size: 0.9rem;
}

.money-figure-note {
    color: var(--text-muted);
    font-size: 0.8rem;
}

/* A label above a figure. Small, wide-tracked, quiet — it names the number without
   arguing with it. */
.money-eyebrow {
    display: block;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* Key/value pairs: wallet's account facts, a checkout summary line. */
.money-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
    gap: var(--money-gap);
}

.money-fact-k {
    display: block;
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-bottom: 0.2rem;
}

.money-fact-v {
    display: block;
    font-family: var(--money-font-display);
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
 * Tags
 *
 * One badge shape for every "what is special about this card" marker across the three
 * routes: best value, your current plan, an upgrade, a scheduled change.
 * ------------------------------------------------------------------------- */

.money-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.55rem;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
}

.money-tag--best {
    background: var(--money-ember-wash);
    border-color: var(--money-ember-edge);
    color: var(--money-ember);
}

.money-tag--current {
    background: var(--money-verdigris-wash);
    border-color: var(--money-verdigris-edge);
    color: var(--money-verdigris);
}

.money-tag--upgrade {
    background: var(--money-amethyst-wash);
    border-color: var(--money-amethyst-edge);
    color: var(--money-amethyst);
}

.money-tag--pending {
    background: transparent;
    border-color: var(--money-line);
    color: var(--text-muted);
}

/* ---------------------------------------------------------------------------
 * Notes and alerts
 *
 * One shape for every inline message on a money page, tinted by meaning. Replaces four
 * separate banner treatments (low balance, daily free credits, checkout return,
 * cancellation notice) that shared nothing but intent.
 * ------------------------------------------------------------------------- */

.money-note {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    margin-bottom: var(--money-gap);
    background: var(--money-surface-sunken);
    border: 1px solid var(--money-line);
    border-inline-start: 3px solid var(--money-line);
    border-radius: var(--radius);
    color: var(--text-secondary);
    font-size: 0.875rem;
    line-height: 1.5;
}

.money-note-text {
    flex: 1;
}

.money-note i {
    font-size: 1.1rem;
    color: var(--text-muted);
}

.money-note--good {
    background: var(--money-verdigris-wash);
    border-color: var(--money-verdigris-edge);
    border-inline-start-color: var(--money-verdigris);
}

.money-note--good i {
    color: var(--money-verdigris);
}

.money-note--warn {
    background: var(--money-ember-wash);
    border-color: var(--money-ember-edge);
    border-inline-start-color: var(--money-ember);
}

.money-note--warn i,
.money-note--warn strong {
    color: var(--money-ember);
}

.money-note--bad {
    background: var(--money-danger-wash);
    border-color: var(--money-danger-edge);
    border-inline-start-color: var(--money-danger);
}

.money-note--bad i {
    color: var(--money-danger);
}

/* Checkout return banners set their state from the query string rather than a class.
 *
 * Audit #3511 fixes BUG-2836: the neutral/pending case above used to be styled with
 * `border-inline-start: 3px solid var(--info)`, and root.css -- the declared single
 * source of truth for globals -- has never defined --info. An unresolvable var() voids
 * the whole declaration, so the banner that tells a reader whether the payment they just
 * made went through had no accent stripe at all. The same undefined token silently
 * blanked .status-trialing on /credits and the confirmation note icon on
 * /subscription/success. All three now resolve to real tokens. */
.money-note[data-state="confirmed"] {
    background: var(--money-verdigris-wash);
    border-color: var(--money-verdigris-edge);
    border-inline-start-color: var(--money-verdigris);
}

.money-note[data-state="cancelled"],
.money-note[data-state="failed"] {
    background: var(--money-danger-wash);
    border-color: var(--money-danger-edge);
    border-inline-start-color: var(--money-danger);
}

/* ---------------------------------------------------------------------------
 * Ledger
 *
 * /credits and /wallet both list money movements. They used to be two tables with
 * different type scales, borders, alignment and number fonts; now they are one, and the
 * only difference is how much of it each route shows.
 * ------------------------------------------------------------------------- */

.money-ledger-shell {
    background: var(--money-surface);
    border: 1px solid var(--money-line);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.money-ledger-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem;
    padding: var(--money-pad-tight);
    border-bottom: 1px solid var(--money-line);
}

.money-ledger-scroll {
    overflow-x: auto;
}

.money-ledger {
    width: 100%;
    border-collapse: collapse;
}

.money-ledger th {
    padding: 0.7rem var(--money-pad-tight);
    background: var(--money-surface-sunken);
    border-bottom: 1px solid var(--money-line);
    color: var(--text-muted);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.07em;
    text-align: start;
    text-transform: uppercase;
    white-space: nowrap;
}

.money-ledger td {
    padding: 0.85rem var(--money-pad-tight);
    border-bottom: 1px solid var(--money-line);
    font-size: 0.875rem;
    text-align: start;
    vertical-align: top;
}

.money-ledger tbody tr:last-child td {
    border-bottom: none;
}

.money-ledger tbody tr:hover {
    background: var(--money-amethyst-wash);
}

.money-ledger-desc {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.money-ledger-desc-sub {
    color: var(--text-muted);
    font-size: 0.8rem;
}

/* Amounts across both routes: one face, tabular so columns of digits align, and the two
   accents that mean gained/spent — never a fourth typeface for "numeric". */
.money-amount {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.money-amount.positive {
    color: var(--money-verdigris);
}

.money-amount.negative {
    color: var(--money-danger);
}

.money-ledger-balance {
    color: var(--text-muted);
    font-size: 0.85rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* A column each ledger nominates as the first thing to drop on a narrow screen. Which
   column that is differs per route -- /credits can lose its running balance because the
   headline card above states the current one, /wallet cannot lose the same column
   because its ledger sits in a different order -- so the choice is markup's, and the
   breakpoint is shared. */
@media (max-width: 576px) {
    .money-ledger .money-ledger-optional {
        display: none;
    }
}

.money-ledger-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem;
    padding: 0.7rem var(--money-pad-tight);
    background: var(--money-surface-sunken);
    border-top: 1px solid var(--money-line);
    color: var(--text-muted);
    font-size: 0.85rem;
}

/* Small quiet controls: ledger filters, pagination, and the "go look at the detail"
   links each money page offers for the surface it summarises. Used as both a <button>
   and an <a>, so it declares its own box rather than inheriting one. */
.money-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.7rem;
    text-decoration: none;
    white-space: nowrap;
    background: var(--money-surface-sunken);
    border: 1px solid var(--money-line);
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    font-family: inherit;
    font-size: 0.8rem;
    cursor: pointer;
    transition: color var(--transition-fast), border-color var(--transition-fast), background var(--transition-fast);
}

.money-chip:hover:not(:disabled) {
    border-color: var(--money-amethyst-edge);
    color: var(--text);
}

.money-chip:focus-visible {
    outline: 2px solid var(--money-amethyst);
    outline-offset: 2px;
}

.money-chip:active:not(:disabled) {
    border-color: var(--money-amethyst-deep);
}

.money-chip:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.money-chip.active {
    background: var(--money-amethyst-wash);
    border-color: var(--money-amethyst-edge);
    color: var(--text);
}

.money-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.money-link-action {
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--money-amethyst);
    font-family: inherit;
    font-size: 0.8rem;
    cursor: pointer;
    white-space: nowrap;
}

.money-link-action:hover {
    text-decoration: underline;
}

.money-link-action:focus-visible {
    outline: 2px solid var(--money-amethyst);
    outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * States
 *
 * Logged out, loading, empty, failed. § Signature element: state screens are
 * deliberately UNDECORATED relative to the product's one signature moment. One shape,
 * no gradient, no oversized icon.
 * ------------------------------------------------------------------------- */

.money-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 3.5rem 1.5rem;
    text-align: center;
    color: var(--text-muted);
}

.money-state > i {
    font-size: 1.75rem;
    color: var(--text-muted);
    opacity: 0.6;
}

.money-state h2 {
    font-family: var(--money-font-display);
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--text);
}

.money-state p {
    max-width: 40ch;
}

.money-state .btn {
    margin-top: 0.5rem;
}

.money-spinner {
    width: 2rem;
    height: 2rem;
    border: 2px solid var(--money-line);
    border-top-color: var(--money-amethyst);
    border-radius: 50%;
    animation: money-spin 0.8s linear infinite;
}

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

/* ---------------------------------------------------------------------------
 * Toasts
 *
 * dom.js injects one shared toast stack (#global-toast-container) into <body> on every
 * page and styles it from whatever stylesheet that page happens to load. /wallet was the
 * only money route that shipped rules for it, so an identical purchase-failed or
 * settings-saved message rendered as a positioned card there and as unstyled body text on
 * /credits and /subscriptions. One definition, all three routes.
 * ------------------------------------------------------------------------- */

.toast-container {
    position: fixed;
    inset-block-end: 2rem;
    inset-inline-start: 50%;
    transform: translateX(-50%);
    z-index: 2000;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    pointer-events: none;
}

.toast {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1.25rem;
    background: var(--money-surface);
    border: 1px solid var(--money-line);
    border-radius: var(--radius);
    box-shadow: 0 4px 12px var(--tint-black-400);
    font-size: 0.9rem;
    opacity: 0;
    transform: translateY(1.25rem);
    transition: opacity var(--transition-slow), transform var(--transition-slow);
    pointer-events: auto;
}

.toast-visible {
    opacity: 1;
    transform: translateY(0);
}

.toast-success {
    border-color: var(--money-verdigris-edge);
}

.toast-success i {
    color: var(--money-verdigris);
}

.toast-error {
    border-color: var(--money-danger-edge);
}

.toast-error i {
    color: var(--money-danger);
}

.toast-warning {
    border-color: var(--money-ember-edge);
}

.toast-warning i {
    color: var(--money-ember);
}

.toast-info {
    border-color: var(--money-amethyst-edge);
}

.toast-info i {
    color: var(--money-amethyst);
}

.toast-close {
    padding: 0;
    background: transparent;
    border: 0;
    color: var(--text-muted);
    cursor: pointer;
}

/* ---------------------------------------------------------------------------
 * Responsive
 * ------------------------------------------------------------------------- */

@media (max-width: 768px) {
    .money-page {
        --money-pad: 1.25rem;
        --money-gap-section: 1.75rem;
        --money-figure-xl: 2.5rem;
    }

    .money-grid,
    .money-grid-wide {
        grid-template-columns: 1fr;
    }

    .money-journey {
        overflow-x: auto;
        flex-wrap: nowrap;
    }

    .money-journey-step {
        white-space: nowrap;
    }
}
