/* =======================================================================
   v2-checkout.css — Shared styles for the v2.1 checkout flow.

   Consolidates the patterns that were previously duplicated across the 9
   checkout views (GS × 3, DS × 3, SA × 3). Each view links this file from
   its @section Styles block and inlines only the view-specific one-offs
   (product-specific tier / region / addon card markup, etc).

   Depends on v2.css being loaded first (this file uses `--v2-*` tokens).

   Organization:
     1. Body backdrop
     2. Aurora hero + gamebar + progress stepper
     3. Dark-chrome card re-skin  (`.v2-static .card` family)
     4. Text + utility color overrides
     5. Form controls
     6. Buttons
     7. Alerts
     8. Modal re-skin
     9. Order-summary sidebar + price breakdown
    10. Review-item tiles (Review pages)
    11. Addon-review tiles (Review pages)
    12. Account-option tiles (Complete pages)
    13. Payment-method tiles (Complete pages)
    14. Choices.js dark-mode overrides
   ======================================================================= */


/* ============================================================
   1. Body backdrop
   ============================================================ */

body.v2-chrome:has(.v2-static.v2-mode-dark) {
    /* Belt-and-suspenders: ensures the page base is the v5 ink color even
       if the layout's own body styles haven't set it. Safe no-op if they
       have. */
    background: var(--v2-ink);
}

/* theme.css hides the reCAPTCHA badge by default (the Dashboard doesn't
   want it visible on admin screens). Complete pages DO use reCAPTCHA v3
   so we need the badge to render for Google's TOS compliance. Unhide. */
.grecaptcha-badge {
    display: block !important;
    visibility: visible !important;
}


/* ============================================================
   2. Aurora hero + gamebar + progress stepper
   ============================================================ */

.v2-checkout-hero {
    position: relative;
    padding: 3.25rem 0 2.5rem;
    overflow: hidden;
    border-bottom: 1px solid var(--v2-line-2);
}
.v2-checkout-hero .v2-aurora {
    position: absolute;
    border-radius: 50%;
    filter: blur(120px);
    opacity: .35;
    pointer-events: none;
    z-index: 0;
}
.v2-checkout-hero .v2-aurora--left {
    width: 520px; height: 520px;
    background: radial-gradient(circle, #976CE6 0%, transparent 65%);
    top: -180px; left: -160px;
}
.v2-checkout-hero .v2-aurora--right {
    width: 480px; height: 480px;
    background: radial-gradient(circle, #6AF2E5 0%, transparent 65%);
    top: -120px; right: -120px;
}
.v2-checkout-hero .position-relative { z-index: 1; }
.v2-checkout-hero .v2-eyebrow {
    display: inline-flex;
    align-items: center;
    font-family: var(--v2-mono);
    font-size: .72rem;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--v2-accent);
    padding: .35rem .9rem;
    border-radius: 999px;
    background: rgba(106, 242, 229, .08);
    border: 1px solid rgba(106, 242, 229, .3);
    margin-bottom: 1rem;
}
.v2-checkout-hero__title {
    font-size: clamp(1.75rem, 2.8vw, 2.4rem);
    font-weight: 700;
    letter-spacing: -.02em;
    line-height: 1.1;
    margin-bottom: .75rem;
    background: var(--v2-grad);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}
.v2-checkout-hero__subtitle {
    color: var(--v2-text-dim);
    font-size: 1rem;
    max-width: 620px;
    margin: 0 auto;
}


/* ---- Slim "you are ordering" gamebar below the hero ---- */

.v2-checkout-gamebar {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: .9rem 1.1rem;
    background: linear-gradient(180deg, rgba(21, 26, 56, .55) 0%, rgba(14, 18, 48, .55) 100%);
    border: 1px solid var(--v2-line-2);
    border-radius: var(--v2-radius-lg);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}
.v2-checkout-gamebar__icon {
    width: 48px; height: 48px;
    border-radius: 10px;
    object-fit: cover;
    flex-shrink: 0;
    /* Default icon-chip styling for icon-font variants (DS / SA use an
       <i class="mdi ..."> instead of a game thumbnail). Harmless on <img>
       since backgrounds don't apply to img content. */
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(106, 242, 229, .08);
    border: 1px solid rgba(106, 242, 229, .25);
    color: var(--v2-accent);
    font-size: 1.4rem;
}
.v2-checkout-gamebar__meta {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    flex: 1;
    min-width: 0;
}
.v2-checkout-gamebar__eyebrow {
    font-family: var(--v2-mono);
    font-size: .62rem;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--v2-text-dim);
}
.v2-checkout-gamebar__title {
    font-weight: 600;
    font-size: 1.05rem;
    color: var(--v2-text-invert);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.v2-checkout-gamebar__step {
    font-family: var(--v2-mono);
    font-size: .68rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--v2-accent);
    padding: .35rem .7rem;
    border-radius: 999px;
    background: rgba(106, 242, 229, .08);
    border: 1px solid rgba(106, 242, 229, .3);
    flex-shrink: 0;
}
@media (max-width: 575.98px) {
    .v2-checkout-gamebar__step { display: none; }
}


/* ---- Progress stepper (1 · Configure → 2 · Review → 3 · Complete) ---- */

.checkout-progress {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .75rem;
    padding: .25rem 0;
}
.checkout-step {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .45rem;
    color: var(--v2-text-dim);
    min-width: 6rem;
}
.checkout-step .step-icon {
    width: 36px; height: 36px;
    border-radius: 50%;
    background: rgba(10, 14, 31, .65);
    border: 1px solid var(--v2-line-2);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--v2-mono);
    font-size: .82rem;
    font-weight: 600;
    color: var(--v2-text-dim);
    transition: background .2s, border-color .2s, color .2s;
}
.checkout-step .step-label {
    font-family: var(--v2-mono);
    font-size: .66rem;
    letter-spacing: .16em;
    text-transform: uppercase;
}
.checkout-step.completed .step-icon {
    background: rgba(49, 217, 165, .18);
    border-color: rgba(49, 217, 165, .45);
    color: var(--v2-success);
}
.checkout-step.completed { color: var(--v2-success); }
.checkout-step.active .step-icon {
    /* -2%/102% stops + padding-box clip follow the same pattern we use on
       `.v2-btn--grad` to keep the raw endpoint colors off the curved edge. */
    background: linear-gradient(90deg, #6AF2E5 -2%, #8A92E6 50%, #976CE6 102%);
    background-clip: padding-box;
    border-color: transparent;
    color: #0A0E1F;
    box-shadow: 0 0 0 4px rgba(106, 242, 229, .12);
}
.checkout-step.active { color: var(--v2-text-invert); }
.progress-line {
    flex: 1 1 auto;
    max-width: 6rem;
    height: 1px;
    background: var(--v2-line-2);
}
.progress-line.completed { background: var(--v2-success); }


/* ============================================================
   3. Dark-chrome card re-skin
   ============================================================ */

.v2-static .card {
    background: linear-gradient(180deg, var(--v2-ink-2) 0%, #0E1226 100%);
    border: 1px solid var(--v2-line-2);
    border-radius: var(--v2-radius-lg);
    color: var(--v2-text-invert);
    box-shadow: none;
}
.v2-static .card-header {
    background: transparent;
    border-bottom: 1px solid var(--v2-line-2);
    padding: 1.1rem 1.5rem;
    color: var(--v2-text-invert);
}
.v2-static .card-header h5 {
    color: var(--v2-text-invert);
    font-weight: 600;
    font-size: 1.05rem;
    letter-spacing: -.01em;
    margin: 0;
}
.v2-static .card-header h5 i { color: var(--v2-accent); }
.v2-static .card-body { padding: 1.5rem; }
.v2-static hr { border-top-color: var(--v2-line-2); }

/* Card-header variants used on Complete pages (Review card-header flex row,
   bg-primary / bg-success header variants). Kept minimal — just neutralize
   the bootstrap backgrounds and recolor the h5 + icon. */
.v2-static .card-header.d-flex { display: flex; align-items: center; justify-content: space-between; }
.v2-static .bg-primary-alt,
.v2-static .bg-primary,
.v2-static .bg-success { background: transparent !important; }
.v2-static .card-header.bg-primary,
.v2-static .card-header.bg-success { background: transparent !important; }
.v2-static .card-header.bg-primary h5,
.v2-static .card-header.bg-primary h5 i,
.v2-static .card-header.bg-primary h5.text-white,
.v2-static .card-header.bg-success h5 { color: var(--v2-text-invert); }
.v2-static .card-header.bg-primary h5 i { color: var(--v2-accent); }
.v2-static .card-header.bg-success h5 i { color: var(--v2-success); }

/* Review / Complete pages sometimes use `.card.border-success` for the
   money-back guarantee card (GS + DS + SA review all do). */
.v2-static .card.border-success {
    border: 1px solid rgba(49, 217, 165, .45) !important;
    background: linear-gradient(180deg, rgba(49, 217, 165, .08) 0%, rgba(14, 18, 48, .4) 100%);
}
.v2-static .card.border-success .text-success { color: var(--v2-success) !important; }

/* Headings inside .v2-static should render on dark by default. */
.v2-static h2, .v2-static h4 {
    color: var(--v2-text-invert);
    font-weight: 700;
    letter-spacing: -.01em;
}


/* ============================================================
   4. Text + utility color overrides (Bootstrap utility compat)
   ============================================================ */

.v2-static .text-muted { color: var(--v2-text-dim) !important; }
.v2-static .text-primary { color: var(--v2-accent) !important; }
.v2-static .text-success { color: var(--v2-success) !important; }
.v2-static .text-info { color: var(--v2-accent) !important; }
.v2-static .text-warning { color: #EAB96C !important; }
.v2-static .text-danger { color: #ff9aa4 !important; }
.v2-static .text-white { color: var(--v2-text-invert) !important; }


/* ============================================================
   5. Form controls
   ============================================================ */

.v2-static .form-group { margin-bottom: 1rem; }
.v2-static .form-group label,
.v2-static .form-check-label,
.v2-static label {
    color: var(--v2-text-dim);
    font-size: .85rem;
}
.v2-static .form-label,
.v2-static .font-weight-bold { color: var(--v2-text-invert); }

.v2-static .form-control,
.v2-static .form-control-lg,
.v2-static select.form-control,
.v2-static select.form-control-lg {
    background: rgba(10, 14, 31, .55);
    border: 1px solid var(--v2-line-2);
    color: var(--v2-text-invert);
    border-radius: var(--v2-radius-sm);
}
.v2-static .form-control:focus,
.v2-static .form-control-lg:focus,
.v2-static select.form-control:focus,
.v2-static select.form-control-lg:focus {
    background: rgba(10, 14, 31, .7);
    border-color: rgba(106, 242, 229, .55);
    box-shadow: none;
    color: var(--v2-text-invert);
}
.v2-static .form-control::placeholder { color: var(--v2-text-dim); opacity: .55; }

.v2-static .form-check-input {
    accent-color: var(--v2-accent);
}
.v2-static .form-check-input:checked {
    background-color: var(--v2-accent);
    border-color: var(--v2-accent);
}
.v2-static .input-group-append .btn {
    border-radius: 0 var(--v2-radius-sm) var(--v2-radius-sm) 0;
}

/* The .btn-outline-* base padding override below (.75rem 1.25rem) makes
   any outline button taller than a default-sized .form-control. When the
   button sits inside an input-group-append (e.g. the password-reveal eye
   on the Complete-step "I have an account" form), the height mismatch is
   visible — the button towers over the input it pairs with. Restore the
   Bootstrap 4 default .btn padding inside input-groups so the heights
   line up. Skip btn-lg / btn-sm so paired sizing (promo-code Apply, etc.)
   keeps working. */
.v2-static .input-group-append .btn:not(.btn-lg):not(.btn-sm),
.v2-static .input-group-prepend .btn:not(.btn-lg):not(.btn-sm) {
    padding: .375rem .75rem;
}

/* Microsoft Edge (legacy + Chromium) renders its own password-reveal eye
   inside <input type="password"> via the ::-ms-reveal pseudo-element. On
   our checkout login form we render our own eye-icon toggle in an
   input-group-append, so the native one shows up as a duplicate sitting
   inside the input next to ours. Hide the native pseudo-element on
   v2-static password inputs so only our toggle is visible. */
.v2-static input[type="password"]::-ms-reveal,
.v2-static input[type="password"]::-ms-clear {
    display: none;
}

.v2-static a { color: var(--v2-accent); }
.v2-static a:hover { color: #9bf6ea; }


/* ============================================================
   6. Buttons
   ============================================================ */

.v2-static .btn-primary {
    background: var(--v2-grad);
    background-clip: padding-box;   /* matches .v2-btn--grad fix */
    color: #0A0E1F;
    /* 1px transparent border (not `border: 0`) so the box-model
       matches the .btn-outline-* variants — without this, a paired
       primary + outline-primary button rendered 2px shorter on
       the primary side, visibly off when sat side-by-side. */
    border: 1px solid transparent;
    font-weight: 600;
    padding: .75rem 1.25rem;
    border-radius: var(--v2-radius-sm);
    transition: transform .15s, filter .15s;
}
.v2-static .btn-primary:hover {
    transform: translateY(-1px);
    filter: brightness(1.08);
    color: #0A0E1F;
}
.v2-static .btn-primary.btn-lg { padding: .9rem 1.4rem; font-size: 1rem; }
.v2-static .btn-primary:disabled,
.v2-static .btn-primary.disabled {
    opacity: .45;
    filter: grayscale(.3);
    cursor: not-allowed;
}
.v2-static .btn-block { display: block; width: 100%; }

/* Sizing parity for outline-* button variants. The .btn-primary
   override above sets v2-tuned padding / radius / font-weight /
   transition + a separate .btn-lg sub-rule with bigger padding;
   the outline variants previously only overrode bg / color /
   border, so a `<a class="btn btn-outline-primary btn-lg">` next
   to a `<a class="btn btn-primary btn-lg">` rendered with
   Bootstrap's default sizing — different padding, different
   radius, different font-size, different visual weight. The
   chained selector below pulls outline-{primary,secondary,
   success} onto the same sizing scale as .btn-primary so a paired
   "Go to Dashboard" + "Browse More Games" CTA reads as a matched
   set instead of two-buttons-cobbled-together. */
.v2-static .btn-outline-primary,
.v2-static .btn-outline-secondary,
.v2-static .btn-outline-success {
    padding: .75rem 1.25rem;
    border-radius: var(--v2-radius-sm);
    font-weight: 600;
    transition: transform .15s, filter .15s, background .15s, color .15s, border-color .15s;
}
.v2-static .btn-outline-primary.btn-lg,
.v2-static .btn-outline-secondary.btn-lg,
.v2-static .btn-outline-success.btn-lg {
    padding: .9rem 1.4rem;
    font-size: 1rem;
}
/* btn-sm override for the v2-styled outlines + the matching primary
   variant. Without this, the new outline-* base padding (.75rem
   1.25rem) is more specific than Bootstrap's `.btn-sm` (.25rem
   .5rem) and the small "Edit" / "Cancel" / "Validate" buttons that
   use `.btn-sm` lose their compact size and end up dominating
   surfaces they were meant to live quietly on (Review-page card
   header Edit links being the canonical example). Same value pair
   is set on `.btn-primary.btn-sm` for parity. */
.v2-static .btn-primary.btn-sm,
.v2-static .btn-outline-primary.btn-sm,
.v2-static .btn-outline-secondary.btn-sm,
.v2-static .btn-outline-success.btn-sm {
    padding: .35rem .85rem;
    font-size: .82rem;
}

.v2-static .btn-outline-primary {
    background: rgba(106, 242, 229, .06);
    color: var(--v2-accent);
    border: 1px solid rgba(106, 242, 229, .45);
}
.v2-static .btn-outline-primary:hover {
    background: rgba(106, 242, 229, .12);
    color: var(--v2-text-invert);
}

.v2-static .btn-outline-secondary {
    background: rgba(255, 255, 255, .04);
    color: var(--v2-text-dim);
    border: 1px solid var(--v2-line-2);
}
.v2-static .btn-outline-secondary:hover {
    background: rgba(255, 255, 255, .08);
    color: var(--v2-text-invert);
    border-color: rgba(106, 242, 229, .45);
}

.v2-static .btn-outline-success {
    background: rgba(49, 217, 165, .06);
    color: var(--v2-success);
    border: 1px solid rgba(49, 217, 165, .45);
}
.v2-static .btn-outline-success:hover {
    background: rgba(49, 217, 165, .14);
    color: var(--v2-text-invert);
}

/* Solid-secondary variant — used by the GS Configure tier-info modal's
   "Got it!" dismiss button. Mirrors the v2 sizing scale so it isn't
   visually adrift from the rest of the v2-themed buttons that share
   the modal's surface. Less common than the outline variants but
   still surfaces, so worth normalizing. */
.v2-static .btn-secondary {
    background: var(--v2-ink-2);
    color: var(--v2-text-invert);
    border: 1px solid var(--v2-line-2);
    font-weight: 600;
    padding: .75rem 1.25rem;
    border-radius: var(--v2-radius-sm);
    transition: transform .15s, filter .15s, background .15s, color .15s, border-color .15s;
}
.v2-static .btn-secondary:hover {
    background: rgba(255, 255, 255, .08);
    color: var(--v2-text-invert);
    border-color: rgba(106, 242, 229, .45);
}
.v2-static .btn-secondary.btn-lg { padding: .9rem 1.4rem; font-size: 1rem; }
.v2-static .btn-secondary.btn-sm { padding: .35rem .85rem; font-size: .82rem; }


/* ============================================================
   7. Alerts
   ============================================================ */

.v2-static .alert-danger {
    background: rgba(255, 107, 122, .12);
    border: 1px solid rgba(255, 107, 122, .35);
    color: #ff9aa4;
}
.v2-static .alert-warning {
    background: rgba(234, 185, 108, .12);
    border: 1px solid rgba(234, 185, 108, .35);
    color: #f4d393;
}
.v2-static .alert-success {
    background: rgba(49, 217, 165, .12);
    border: 1px solid rgba(49, 217, 165, .35);
    color: var(--v2-success);
}
.v2-static .alert-info {
    background: rgba(106, 242, 229, .12);
    border: 1px solid rgba(106, 242, 229, .35);
    color: var(--v2-accent);
}


/* ============================================================
   8. Modal re-skin
   ============================================================ */

.v2-static .modal-content {
    background: linear-gradient(180deg, var(--v2-ink-2) 0%, #0E1226 100%);
    border: 1px solid var(--v2-line-2);
    color: var(--v2-text-invert);
    border-radius: var(--v2-radius-lg);
}
.v2-static .modal-header { border-bottom-color: var(--v2-line-2); }
.v2-static .modal-footer { border-top-color: var(--v2-line-2); }
.v2-static .modal .close {
    color: var(--v2-text-invert);
    text-shadow: none;
    opacity: .7;
}
.v2-static .modal .spinner-border.text-primary {
    color: var(--v2-accent) !important;
}


/* ============================================================
   9. Order-summary sidebar + price breakdown
   ============================================================ */

.order-summary-card {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.order-summary-card hr {
    border: 0;
    border-top: 1px dashed var(--v2-line-2);
    margin: 1rem 0;
}

/* F-GS-L4 — keep the sticky order-summary sidebar inside the viewport when
   many addons have been selected. Every checkout view renders this block
   as `<div class="order-summary-card sticky-top" style="top: 100px;">`
   (see GS / DS / SA Configure + Review + Complete). At tall viewports the
   sidebar fits naturally; at ≤800px heights it was clipping below the
   fold because the card itself had no max-height — the sticky-top kept it
   pinned but any content past the fold was unreachable. Constrain to
   viewport-minus-header-offset with overflow-y:auto + stable scrollbar
   gutter so the card scrolls internally without layout shift when its
   content overflows. The 100px header offset matches the inline
   `top: 100px;` already applied by every checkout view; the extra
   1.5rem leaves breathing room at the bottom of the viewport.

   Scope to lg+ (≥ 992px) only. On mobile the .col-lg-4 stacks below
   .col-lg-8 as a full-width row and the sticky behavior is no longer
   useful — the user scrolls through everything in natural document
   order. Worse, leaving the max-height/overflow rules in place at
   mobile widths capped the stacked sidebar at ~691px and pushed the
   Order Summary card + final Continue button into an unreachable inner
   scrollbox. The lg breakpoint (992px) matches col-lg-* — at that
   width the sidebar becomes a real right rail again and the constraint
   matters. */
@media (min-width: 992px) {
    .order-summary-card.sticky-top {
        max-height: calc(100vh - 100px - 1.5rem);
        overflow-y: auto;
        scrollbar-gutter: stable;
    }
}

/* Mobile / tablet: kill the sticky pin entirely. Bootstrap's .sticky-top
   utility applies position:sticky at every breakpoint, but at < lg the
   sidebar is just a stacked row and sticky has no meaningful sibling to
   stick relative to. Resetting to static lets the column flow naturally
   so the Continue button lands at the very bottom of the page. */
@media (max-width: 991.98px) {
    .order-summary-card.sticky-top {
        position: static;
    }
}

.summary-item {
    display: flex;
    align-items: center;
    gap: .75rem;
}
.summary-item__icon {
    width: 48px; height: 48px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(106, 242, 229, .08);
    border: 1px solid rgba(106, 242, 229, .25);
    color: var(--v2-accent);
    font-size: 1.25rem;
    flex-shrink: 0;
}
.summary-game-icon {
    width: 48px; height: 48px;
    border-radius: 10px;
    object-fit: cover;
    flex-shrink: 0;
}
.summary-item-details,
.summary-item__details {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.summary-game-title,
.summary-item__title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--v2-text-invert);
    letter-spacing: -.01em;
}
.summary-size,
.summary-item__sub {
    font-family: var(--v2-mono);
    font-size: .7rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--v2-text-dim);
}

.price-breakdown {
    display: flex;
    flex-direction: column;
    gap: .5rem;
}
.price-row {
    display: flex;
    justify-content: space-between;
    font-family: var(--v2-mono);
    font-size: .85rem;
    color: var(--v2-text-invert);
}
.price-row span:first-child { color: var(--v2-text-dim); }
.price-row.subtotal {
    font-size: .9rem;
    color: var(--v2-text-invert);
    font-weight: 600;
}
.price-row.subtotal span:first-child { color: var(--v2-text-invert); }
.price-row.total {
    font-family: var(--v2-font);
    font-size: 1.1rem;
    padding-top: .5rem;
}
.price-row.total span:first-child {
    color: var(--v2-text-invert);
    font-weight: 600;
}
.price-row.total .total-price {
    display: flex;
    align-items: baseline;
    gap: .15rem;
    flex-wrap: wrap;
    justify-content: flex-end;
}

.discount-row {
    display: flex;
    justify-content: space-between;
    font-family: var(--v2-mono);
    font-size: .85rem;
    color: var(--v2-success);
}
.discount-row .text-success { color: var(--v2-success) !important; }

.total-amount {
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: -.02em;
    background: var(--v2-grad);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}
.total-amount.text-success {
    background: none !important;
    color: var(--v2-success) !important;
    -webkit-text-fill-color: var(--v2-success);
}
.billing-period {
    font-family: var(--v2-mono);
    font-size: .75rem;
    color: var(--v2-text-dim);
}


/* ============================================================
   10. Review-item tiles (Review pages — Server Configuration summary)
   ============================================================ */

.review-item {
    display: flex;
    align-items: flex-start;
    gap: .9rem;
    padding: .75rem;
    border-radius: var(--v2-radius-sm);
    background: rgba(10, 14, 31, .4);
    border: 1px solid var(--v2-line-2);
    height: 100%;
}
.review-item-icon {
    flex-shrink: 0;
    width: 48px; height: 48px;
    border-radius: 10px;
    background: rgba(106, 242, 229, .08);
    border: 1px solid rgba(106, 242, 229, .25);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--v2-accent);
    font-size: 1.4rem;
    overflow: hidden;
    line-height: 0;
}
.review-item-icon img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
.review-item-content {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    flex: 1;
    min-width: 0;
}
.review-label {
    font-family: var(--v2-mono);
    font-size: .62rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--v2-text-dim);
    display: block;
}
.review-value {
    font-size: 1rem;
    font-weight: 600;
    color: var(--v2-text-invert);
    letter-spacing: -.01em;
    display: block;
}
.review-item small {
    font-family: var(--v2-mono);
    font-size: .72rem;
    letter-spacing: .04em;
    color: var(--v2-text-dim);
}
.review-item .badge {
    font-family: var(--v2-mono);
    font-size: .62rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    font-weight: 700;
    padding: .22rem .55rem;
    border-radius: 999px;
    white-space: nowrap;
    align-self: flex-start;
    margin-top: .25rem;
}
.review-item .badge.badge-success {
    background: rgba(49, 217, 165, .14);
    color: var(--v2-success);
    border: 1px solid rgba(49, 217, 165, .35);
}


/* ============================================================
   11. Addon-review tiles (Review pages — Selected Add-ons strip)
   ============================================================ */

.addon-review-item,
.ds-addon-review,
.sa-addon-review {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .35rem;
    padding: 1.1rem .9rem;
    border-radius: var(--v2-radius-sm);
    background: rgba(10, 14, 31, .4);
    border: 1px solid var(--v2-line-2);
    text-align: center;
    height: 100%;
}
.addon-review-item > i,
.ds-addon-review > i,
.sa-addon-review > i {
    color: var(--v2-accent) !important;
    font-size: 1.5rem;
    margin-bottom: .2rem;
}
.addon-review-label,
.ds-addon-review-label,
.sa-addon-review-label {
    font-family: var(--v2-mono);
    font-size: .62rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--v2-text-dim);
}
.addon-review-value,
.ds-addon-review-value,
.sa-addon-review-value {
    font-size: .9rem;
    font-weight: 600;
    color: var(--v2-text-invert);
}
.addon-review-price,
.ds-addon-review-price,
.sa-addon-review-price {
    font-family: var(--v2-mono);
    font-size: .72rem;
    color: var(--v2-text-dim);
    margin-top: .15rem;
}
.addon-review-price .text-success { color: var(--v2-success) !important; }
.addon-review-price .text-primary { color: var(--v2-accent) !important; }
.addon-review-price.included,
.ds-addon-review-price.included,
.sa-addon-review-price.included { color: var(--v2-success); }


/* ============================================================
   12. Account-option tiles (Complete pages — Login / Create Account)
   ============================================================ */

.account-option {
    padding: 1rem 1.1rem;
    border-radius: var(--v2-radius);
    background: rgba(10, 14, 31, .4);
    border: 1px solid var(--v2-line-2);
    cursor: pointer;
    transition: border-color .2s, transform .2s;
    height: 100%;
}
.account-option:hover { border-color: rgba(106, 242, 229, .45); }
.account-option.selected {
    background: linear-gradient(rgba(10, 14, 31, .85), rgba(10, 14, 31, .85)) padding-box,
                var(--v2-grad) border-box;
    border: 1px solid transparent;
}
.account-option-header {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
}
.account-option-header input[type="radio"] {
    margin-top: .4rem;
    accent-color: var(--v2-accent);
}
.account-option-header label {
    cursor: pointer;
    margin-bottom: 0;
    color: var(--v2-text-invert);
}
.account-option-header label strong {
    display: block;
    font-weight: 600;
    color: var(--v2-text-invert);
}
.account-option-header label small { color: var(--v2-text-dim); }
.account-form-container { margin-top: 0; }
.account-form { padding-top: .5rem; }


/* ============================================================
   13. Payment-method tiles (Complete pages)
   ============================================================ */

.payment-methods {
    display: flex;
    gap: .75rem;
    flex-wrap: wrap;
}
.payment-method {
    flex: 1 1 180px;
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .9rem 1rem;
    border-radius: var(--v2-radius);
    background: rgba(10, 14, 31, .4);
    border: 1px solid var(--v2-line-2);
    cursor: pointer;
    transition: border-color .2s, transform .2s;
    color: var(--v2-text-invert);
}
.payment-method:hover {
    border-color: rgba(106, 242, 229, .45);
    transform: translateY(-1px);
}
.payment-method.selected {
    background: linear-gradient(rgba(10, 14, 31, .85), rgba(10, 14, 31, .85)) padding-box,
                var(--v2-grad) border-box;
    border: 1px solid transparent;
}
.payment-method span { font-weight: 600; }
.payment-method i { color: var(--v2-accent); }
#card-element {
    min-height: 42px;
    padding: 10px 12px !important;
}

/* Password strength indicator bar (Complete pages) */
.password-strength {
    height: 4px;
    border-radius: 2px;
    background: rgba(255, 255, 255, .06);
    overflow: hidden;
    position: relative;
}
.password-strength::after {
    content: attr(data-strength);
    position: absolute;
    left: 0; bottom: -1.2em;
    font-family: var(--v2-mono);
    font-size: .7rem;
    color: var(--v2-text-dim);
}
#passwordMatch { font-family: var(--v2-mono); font-size: .72rem; }


/* ============================================================
   14. Billing toggle + save badge (Configure pages)

   Same Monthly / Yearly switch shape used on all three Configure pages.
   Slider active state uses the same `-2%/102%` gradient stop offset
   trick as the progress stepper to avoid the raw teal/purple endpoint
   colors showing as a 1-px band on the pill's curved edge.
   ============================================================ */

.billing-toggle-container {
    display: flex;
    align-items: center;
    gap: .75rem;
}
.billing-toggle {
    position: relative;
    display: inline-block;
    width: 46px; height: 26px;
    /* GS Checkout's original rule used a `label`-tag-wrapped structure; the
       `.mb-0` utility class is kept in the markup for Bootstrap form-
       alignment compat but the actual sizing is here. */
}
.billing-toggle input {
    opacity: 0;
    width: 0; height: 0;
}
.billing-slider {
    position: absolute;
    inset: 0;
    background: rgba(10, 14, 31, .65);
    border: 1px solid var(--v2-line-2);
    border-radius: 999px;
    cursor: pointer;
    transition: background .2s;
}
.billing-slider::before {
    content: "";
    position: absolute;
    left: 2px; top: 50%;
    transform: translateY(-50%);
    width: 16px; height: 16px;
    border-radius: 50%;
    background: var(--v2-text-dim);
    transition: transform .2s, background .2s;
}
.billing-toggle input:checked + .billing-slider {
    background: linear-gradient(90deg, #6AF2E5 -2%, #8A92E6 50%, #976CE6 102%);
    background-clip: padding-box;
    border-color: transparent;
}
.billing-toggle input:checked + .billing-slider::before {
    transform: translate(22px, -50%);
    background: #0A0E1F;
}
.billing-label {
    font-family: var(--v2-mono);
    font-size: .78rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--v2-text-dim);
}
.billing-label.active { color: var(--v2-text-invert); }

.save-badge {
    font-family: var(--v2-mono);
    font-size: .62rem;
    letter-spacing: .14em;
    font-weight: 700;
    padding: .22rem .55rem;
    border-radius: 999px;
    background: rgba(49, 217, 165, .14);
    color: var(--v2-success);
    border: 1px solid rgba(49, 217, 165, .35);
}


/* ============================================================
   15. Choices.js dark-mode overrides (Minecraft Version picker etc.)

   The shared mod-loader-build-picker.css assumes a light page. Repaint
   the dropdown chrome (closed box, open panel, search input, row hover)
   with v5 tokens so selects match the rest of the checkout instead of
   flashing white.
   ============================================================ */

.v2-static .choices { margin-bottom: 0; }
.v2-static .choices[data-type*="select-one"] .choices__inner {
    background: rgba(10, 14, 31, .55);
    border: 1px solid var(--v2-line-2);
    border-radius: var(--v2-radius-sm);
    color: var(--v2-text-invert);
    min-height: 42px;
}
.v2-static .choices__list--single .choices__item { color: var(--v2-text-invert); }
.v2-static .choices[data-type*="select-one"]::after {
    border-color: var(--v2-text-dim) transparent transparent;
}
.v2-static .choices.is-open[data-type*="select-one"]::after {
    border-color: transparent transparent var(--v2-text-dim);
}
.v2-static .choices__list--dropdown,
.v2-static .choices__list[aria-expanded] {
    background: linear-gradient(180deg, var(--v2-ink-2) 0%, #0E1226 100%);
    border: 1px solid var(--v2-line-2);
    border-radius: var(--v2-radius-sm);
    box-shadow: 0 12px 32px rgba(0, 0, 0, .55);
    color: var(--v2-text-invert);
}
.v2-static .choices__list--dropdown .choices__input,
.v2-static .choices__list[aria-expanded] .choices__input {
    background: rgba(10, 14, 31, .65);
    color: var(--v2-text-invert);
    border: 1px solid var(--v2-line-2);
    border-radius: var(--v2-radius-sm);
}
.v2-static .choices__list--dropdown .choices__item,
.v2-static .choices__list[aria-expanded] .choices__item {
    color: var(--v2-text-invert);
}
.v2-static .choices__list--dropdown .choices__item--selectable.is-highlighted,
.v2-static .choices__list[aria-expanded] .choices__item--selectable.is-highlighted,
.v2-static .choices__list--dropdown .choices__item--selectable:hover,
.v2-static .choices__list[aria-expanded] .choices__item--selectable:hover {
    background: rgba(106, 242, 229, .12);
    color: var(--v2-text-invert);
}
.v2-static .choices[data-type*="select-one"].is-focused .choices__inner,
.v2-static .choices[data-type*="select-one"].is-open .choices__inner {
    border-color: rgba(106, 242, 229, .55);
    background: rgba(10, 14, 31, .7);
}
.v2-static .choices__placeholder { color: var(--v2-text-dim); opacity: .8; }


/* ============================================================
   16. PayPal SDK iframe — color-scheme handoff

   PayPal's Smart Buttons render inside a cross-origin iframe (zoid).
   When the parent page declares `color-scheme: light` (or the browser
   inherits one), the iframe inherits that preference and PayPal paints
   its alternate-funding rows + the gap between buttons in white.

   The Dashboard never had this problem because it always served a
   light-themed billing tab; the Static project was originally light-
   mode-only too, so the issue only surfaces now that v2 checkout
   pages run under v2-static v2-mode-dark. Fix is to declare
   `color-scheme: none` on the PayPal button container so the iframe
   stops inheriting a light preference and falls back to transparent
   for surfaces it would otherwise have painted white.

   Reference: stackoverflow.com/a/78061080 (PayPal SDK + dark mode).
   Same selector covers both Static checkout flows (#paypal-button-container
   in Order/Complete + StorageAccountCheckout/Complete + DedicatedServerCheckout/Complete)
   and any future PayPal mount points by class.
   ============================================================ */
#paypal-button-container,
.paypal-buttons {
    color-scheme: none;
}

/* ============================================================
   "What's Next?" timeline (Confirmation pages)
   ============================================================
   Vertical step rail used by Checkout/Confirmation +
   DedicatedServerCheckout/Confirmation +
   StorageAccountCheckout/Confirmation. The legacy site-wide CSS
   that styled `.timeline` / `.timeline-item` / `.timeline-icon`
   stopped shipping when the Bootstrap theme bundle was retired
   for v2.1 — so the markup was rendering as raw inline icons +
   labels with no circles, no connector line, and no state
   coloring. Rebuilt here on the v2.1 token palette.

   Single-gradient model: ONE logical 180deg teal-to-purple
   gradient runs from the top of the first chip to the bottom of
   the last chip. Each chip + connector slices its visible portion
   from that shared gradient via `background-size: ... var(--tl-h)`
   + per-element `background-position-y: var(--bg-y)`. With both
   driven by JS-measured offsets (see the small init script
   inlined into each Confirmation view), the colors flow correctly
   regardless of how many items the page has or how tall each
   item ends up — so a 4-step Confirmation with 81px-tall items
   works as cleanly as a 3-step with 68px items.

   Two ROOT bugs were fixed when this rebuild landed; both worth
   knowing about because they're easy to reintroduce:

   1. The original implementation hardcoded `--tl-h: 176px`
      (3 chips × 40 + 2 × 28 connector) and used per-`nth-child`
      `background-position-y` slices. With 4 items and 81px-tall
      content, the math drifted and produced a visible 13px color
      step at every connector→chip seam. JS-measured slicing
      replaces both — `--tl-h` is the timeline's actual offsetHeight
      and `--bg-y` per element is `-(item.offsetTop + chip-top)`.

   2. The in-progress chip uses a multi-layer background:
      a solid ink-2 clipped to `padding-box` on top of the gradient
      clipped to `border-box`. WITHOUT `background-origin: border-box`
      on both layers, both layers' (0,0) defaults to the padding-box
      origin (which is INSIDE the border by border-width). For a
      40px chip with 2px transparent border, the gradient image
      then renders from x=2 to x=42 of the border-box — the
      LEFTMOST 2px (which IS where the visible ring is, because
      the curved padding-box dips inward there) shows NO gradient
      at all. The user reported this as "the ring cuts off at a
      left-side pixel limit." Setting `background-origin: border-box`
      slides the gradient image left by exactly the border width
      so it covers x=0..40 cleanly. This is the same "render into
      negative pixels" pattern we used on `.v2-btn--grad` for the
      same family of edge-banding issues.

   If you ever need to refactor: keep both `--bg-y` parameterization
   AND `background-origin: border-box` on the in-progress chip.
   Dropping either reintroduces a visible regression.
   ============================================================ */
.v2-static .timeline {
    position: relative;
    padding: .25rem 0;
    /* `--tl-h` and per-element `--bg-y` are set by the small init
       script in each Confirmation view. The 100% / 0 fallbacks
       below mean the timeline still renders something sensible
       (gradient sized to its own element, no slice offset) if the
       JS hasn't run yet. */
    --tl-grad: linear-gradient(180deg, #6AF2E5 0%, #8A92E6 50%, #976CE6 100%);
}
.v2-static .timeline-item {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    padding-bottom: 1.75rem;
}
.v2-static .timeline-item:last-child { padding-bottom: 0; }

/* Vertical connector — drawn from the bottom of each icon to the
   top of the next item's icon. Anchored at the icon's vertical
   center (40px circle / 2 = 20px) and extends downward. Last
   item suppresses its connector since there's no next icon. */
.v2-static .timeline-item::before {
    content: "";
    position: absolute;
    left: 19px;                /* 40px icon / 2 = 20, minus half of the 2px line */
    top: 40px;                 /* below the 40px icon circle */
    bottom: 0;
    width: 2px;
    background: var(--v2-line-2);
}
.v2-static .timeline-item:last-child::before { display: none; }

/* Completed connector — slice of the shared gradient. Both the
   total height (`--tl-h`) and the per-connector y-offset
   (`--bg-y`) are JS-measured per the init script in the
   Confirmation views. */
.v2-static .timeline-item.completed::before {
    background-image: var(--tl-grad);
    background-size: 2px var(--tl-h, 100%);
    background-position-y: var(--bg-y, 0);
    background-repeat: no-repeat;
}

/* Icon chip — fixed 40px circle, defaults to a muted ring with a
   dim glyph (future / not-yet-reached steps). */
.v2-static .timeline-item .timeline-icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--v2-ink-2);
    border: 2px solid var(--v2-line-2);
    color: var(--v2-text-dim);
    font-size: .9rem;
    position: relative;
    z-index: 1;                /* sit above the connector line */
    transition: background .2s, border-color .2s, color .2s;
}

/* In-progress: gradient ring + accent-colored glyph + soft glow
   so the user's eye lands on the active step. The two-layer
   trick — solid ink clipped to padding-box on top of the
   timeline-shared gradient clipped to border-box — gives a clean
   gradient ring without the edge banding we hit with a plain
   transparent border.

   `background-origin: border-box, border-box` is load-bearing —
   without it the gradient image's (0,0) lands at the padding-box
   edge and the leftmost 2px ring sliver renders empty. See the
   block comment above this rule for the full explanation. */
.v2-static .timeline-item.in-progress .timeline-icon {
    background-image:
        linear-gradient(var(--v2-ink-2), var(--v2-ink-2)),
        var(--tl-grad);
    background-clip: padding-box, border-box;
    background-origin: border-box, border-box;
    background-size: auto, 40px var(--tl-h, 100%);
    background-position: 0 0, 0 var(--bg-y, 0);
    background-repeat: no-repeat, no-repeat;
    border-color: transparent;
    color: var(--v2-accent);
    box-shadow: 0 0 0 4px rgba(106, 242, 229, .08);
}

/* Completed: filled gradient circle, dark glyph for contrast.
   `border: 0` (not just transparent) prevents the inherited 2px
   transparent border from leaking the gradient through its anti-
   aliased edge — same edge-banding artifact the old
   `/GradientDebug` page was set up to track on `.v2-btn--grad`.
   `background-clip: padding-box` is belt-and-suspenders. */
.v2-static .timeline-item.completed .timeline-icon {
    background-image: var(--tl-grad);
    background-size: 40px var(--tl-h, 100%);
    background-position-y: var(--bg-y, 0);
    background-repeat: no-repeat;
    background-clip: padding-box;
    border: 0;
    color: #0A0E1F;
}

/* Content column — heading + description sit beside the icon. */
.v2-static .timeline-item .timeline-content {
    flex: 1;
    padding-top: .35rem;
}
.v2-static .timeline-item .timeline-content h6 {
    color: var(--v2-text-invert);
    margin: 0 0 .25rem;
    font-weight: 600;
    font-size: 1rem;
}
.v2-static .timeline-item .timeline-content p {
    color: var(--v2-text-dim);
    margin: 0;
    line-height: 1.5;
    font-size: .9rem;
}
