/* PinGrim custom styles */

/* Fade-in animation */
@keyframes fadeIn {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}

/* Admin-toggleable uppercase style for the marketplace action buttons
   (Deposit + whichever of Withdraw/Unlock Premium/Membership/Benefits/Cash
   Out is currently active) — admin/button-tracking.php, site_setting
   action_button_uppercase. Purely visual: the underlying label text/markup
   is untouched, so this is a zero-risk, instantly-reversible toggle. */
.action-btns-uppercase span {
    text-transform: uppercase;
    letter-spacing: .02em;
}

.fade-in {
    animation: fadeIn 0.4s ease-out;
}

/* Form input focus ring */
input:focus {
    outline: none;
    box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.2);
}

/* Button hover transition */
button {
    transition: all 0.2s ease;
}

/* Message container */
#message {
    transition: opacity 0.3s ease;
}

/* ===== Promo Modal Styles ===== */

/* Modal container - override Tailwind hidden */
#promoModal {
    display: none;
}

#promoModal.hidden {
    display: none !important;
}

/* Modal content animation */
#promoModalContent {
    transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease;
}

/* Shake animation for empty promo input */
@keyframes shake {
    0%, 100% { transform: translateX(0); }
    10%, 30%, 50%, 70%, 90% { transform: translateX(-6px); }
    20%, 40%, 60%, 80% { transform: translateX(6px); }
}

.shake-input {
    animation: shake 0.5s ease-in-out;
    border-color: #ff0000 !important;
}

/* Modal input focus state */
#modalPromoInput:focus {
    outline: none;
    box-shadow: 0 0 0 3px rgba(0, 255, 159, 0.25);
    border-color: #00ff9f;
}

/* ===== Modal Overlay Animations ===== */

/* Modal overlay fade-in */
#modal-overlay {
    opacity: 0;
    transition: opacity 0.3s ease;
}

#modal-overlay.flex {
    opacity: 1;
}

/* Modal content slide-up animation */
/* max-height/overflow enforced here because the Tailwind arbitrary class
   max-h-[90vh] used inline across the site was purged from the compiled
   build — without a cap, tall modal content overflows above/below a
   viewport-sized fixed overlay with no way to scroll to it. */
#modal-content {
    transform: translateY(20px) scale(0.95);
    opacity: 0;
    transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease;
    max-height: 90vh;
    overflow-y: auto;
}

#modal-overlay.flex #modal-content {
    transform: translateY(0) scale(1);
    opacity: 1;
}


/* Exit intent modal specific styles */
#exit-intent-modal {
    display: none;
}

#exit-intent-modal.show {
    display: flex;
}

/* Bounce-in animation for modals */
@keyframes bounceIn {
    0% {
        opacity: 0;
        transform: scale(0.8) translateY(20px);
    }
    50% {
        transform: scale(1.02) translateY(-5px);
    }
    100% {
        opacity: 1;
        transform: scale(1) translateY(0);
    }
}

.animate-bounce-in {
    animation: bounceIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Urgent CTA pulse animation */
.urgent-cta {
    animation: pulse-urgent 2s ease-in-out infinite;
}

@keyframes pulse-urgent {
    0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(255, 215, 0, 0.4); }
    50% { transform: scale(1.02); box-shadow: 0 0 0 10px rgba(255, 215, 0, 0); }
}

/* ===== Withdraw Button Glow Animation ===== */
@keyframes withdraw-glow {
    0%, 100% {
        box-shadow:
            0 0 5px rgba(251, 191, 36, 0.5),
            0 0 10px rgba(251, 191, 36, 0.3),
            0 0 15px rgba(251, 191, 36, 0.2),
            0 0 20px rgba(251, 191, 36, 0.1);
    }
    50% {
        box-shadow:
            0 0 10px rgba(251, 191, 36, 0.8),
            0 0 20px rgba(251, 191, 36, 0.6),
            0 0 30px rgba(251, 191, 36, 0.4),
            0 0 40px rgba(251, 191, 36, 0.2);
    }
}

.withdraw-glow {
    animation: withdraw-glow 1.5s ease-in-out infinite;
    position: relative;
}

.withdraw-glow::before {
    content: '';
    position: absolute;
    inset: -2px;
    background: linear-gradient(45deg, #fbbf24, #f97316, #fbbf24, #f97316);
    border-radius: 14px;
    z-index: -1;
    opacity: 0;
    animation: border-glow 1.5s ease-in-out infinite;
}

@keyframes border-glow {
    0%, 100% { opacity: 0.3; }
    50% { opacity: 0.7; }
}

/* ===== Action Button Glow Variants ===== */
/* Uses inline style injection via PHP to guarantee glow works regardless of Tailwind */

/* ===== Tab Section Transitions ===== */
.tab-section {
    transition: opacity 150ms ease, transform 150ms ease;
}

.tab-section.hidden {
    display: none;
}

/* Input shake animation for validation */
.shake {
    animation: shake 0.5s ease-in-out;
}

/* Account card hover effects */
.account-card {
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.account-card:hover {
    transform: translateY(-2px);
}

/* Tab button active state border */
.border-b-3 {
    border-bottom-width: 3px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   NATIVE APP FEEL
   ═══════════════════════════════════════════════════════════════════════════ */

/* Page entrance fade-in — opacity ONLY on body.
   IMPORTANT: Never use transform on body/html — it breaks position:fixed elements
   (bottom nav, modals, overlays) by creating a new stacking context.
   The slide-up effect is applied only to non-fixed page content via .pg-content. */
body {
    animation: pgFadeIn 0.18s ease-out both;
}
@keyframes pgFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Slide-up applied to scrollable page content containers.
   IMPORTANT: opacity ONLY here too — no transform. A transform on main/.pg-content/
   .fade-in doesn't need to be non-identity to break things: ANY non-none transform value
   (even the resting translateY(0) this animation settles on, via animation-fill-mode:
   both) makes the element a new containing block for position:fixed DESCENDANTS. #p9-modal-overlay
   (VIP Tools/Scripts purchase modal, includes/p9_sections.php) is rendered inside <main>
   on marketplace.php, so it was being positioned relative to <main>'s box instead of the
   viewport — not fixed to the screen at all, hence drifting/clipping on scroll. Confirmed
   via getBoundingClientRect() on the live element: with this transform present, top was
   -475px instead of 0. #modal-overlay (Form Tools/Accounts) escaped this only because it
   happens to be markup'd as a sibling AFTER </main> closes, not a structural fix. */
main, .pg-content, .fade-in {
    animation: pgSlideUp 0.22s ease-out both;
}
@keyframes pgSlideUp {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Remove the 300ms tap delay on all interactive elements.
   This is the single biggest mobile responsiveness improvement — taps feel instant. */
a, button, [role="button"],
input[type="button"], input[type="submit"], input[type="reset"],
label, select {
    touch-action: manipulation;
}

/* Remove the blue/grey flash that appears on tap in mobile browsers */
* {
    -webkit-tap-highlight-color: transparent;
}

/* Smooth scroll throughout */
html {
    scroll-behavior: smooth;
}

/* Prevent accidental text selection when tapping buttons and links */
a, button, [role="button"], .toggle-switch, label {
    -webkit-user-select: none;
    user-select: none;
}

/* ===== Notifications Modal ===== */
#notifications-modal > div {
    max-height: 80vh;
    overflow: hidden;
}

#notifications-modal .notif-scroll {
    max-height: 60vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* ═══════════════════════════════════════════════════════════════════════
   USER-FACING DARK MODE — v2 rebuild
   Light mode (the existing hardcoded Tailwind classes below) stays the
   default with zero markup changes. html.dark-mode is the opt-in override,
   toggled by assets/js/theme-toggle.js and set server-side (before first
   byte, no flash) by get_user_theme_mode() in includes/functions.php.

   v2 rebuild reasons (2026-08-11): v1 used a mid-gray palette (#0a0a0a
   page / #161616 cards) that read as washed-out grey rather than the true
   OLED black in the user's reference screenshots, and only covered
   Tailwind CLASS-based color usage — it silently missed (a) JS-injected
   inline-styled markup (assets/js/pwa.js install sheet), (b) inline
   `style="..."` attributes on PHP pages built without Tailwind classes
   at all (gift-cards.php / crypto-wallet.php are ~95% inline styles),
   and (c) Tailwind gradient-STOP utilities (from-yellow-50/to-orange-50
   etc.) which are separate classes from bg-yellow-50 and set different
   CSS custom properties (--tw-gradient-from/--tw-gradient-to).

   Technique, extended: still override the specific escaped Tailwind
   arbitrary-value/utility classes already compiled into
   assets/css/tailwind.min.css (never regenerate, only override what's
   already there — a brand-new class would be silently purged). PLUS: every
   inline `style="color:#1a1a1a"` etc. across the codebase has been
   rewritten to `style="color:var(--pg-text-heading,#1a1a1a)"` — the
   hardcoded hex stays as the fallback (so light mode is byte-for-byte
   unaffected), and the CSS variable (only defined under html.dark-mode)
   takes over the moment dark mode is active, with zero markup risk.

   Deliberately NOT touched (verified against the reference screenshots —
   these read correctly on dark with zero changes): brand red (#ff0000 and
   friends), the #00ff9f/#00d68f/#00c278 green accents, gold/amber
   (#FFD700, #f59e0b), purple/orange accents, social brand colors (WhatsApp
   Facebook TikTok), white text sitting on a colored button/badge, and any
   component that's already hand-built dark regardless of theme (e.g.
   marketplace.php's balance hero card gradient).
   ═══════════════════════════════════════════════════════════════════════ */
html.dark-mode {
    /* True-black surface scale, calibrated against the user's reference
       screenshots: the page is near-pure black, cards are only barely
       lighter than the page (a subtle presence, not a grey block), and
       borders — not fill contrast — are what separates an input/card
       from the page behind it. */
    --pg-bg-page:      #000000;
    --pg-bg-card:      #0d0d0d;
    --pg-bg-card-2:    #141414;
    --pg-bg-well:      #0a0a0a;
    --pg-bg-well-2:    #1a1a1a;
    --pg-bg-well-3:    #242424;
    --pg-border:       #2a2a2a;
    --pg-border-2:     #3a3a3a;
    --pg-border-3:     #1a1a1a;
    --pg-text-primary: #e5e5e5;
    --pg-text-heading: #ffffff;
    --pg-text-muted:   #9ca3af;
    --pg-text-dim:     #8b8b93;
    --pg-text-dimmer:  #b8b8bd;
    --pg-text-faint:   #e5e5e5;
    /* Frosted/glass floating pills (e.g. a "back to home" button floating
       over page content) — light mode uses translucent WHITE glass, dark
       mode swaps to translucent dark glass so it doesn't sit as a bright
       white patch on a black page. */
    --pg-glass-bg:     rgba(20,20,20,.88);
    --pg-glass-border: rgba(255,255,255,.10);
    --pg-glass-text:   #f5f5f5;
    /* "Premium gate" fade veils — a blurred preview grid with a white
       fade-to-solid overlay on top, used to tease locked content. Dark
       mode fades to the card's own near-black instead of white. */
    --pg-gate-overlay: linear-gradient(180deg,rgba(0,0,0,.55) 0%,rgba(13,13,13,.94) 35%,rgba(13,13,13,.99) 100%);
    /* Modal/dialog elevation — a modal at the same near-black value as an
       ordinary page card (#0d0d0d) gives almost no visual "pop" against the
       true-black page when it appears; users couldn't tell a modal had
       opened at all. Standard dark-theme fix (Material/iOS use the same
       idea): elevated surfaces get LIGHTER, not shadowed — box-shadow is
       close to invisible on black. This is deliberately reserved for real
       modal/dialog/bottom-sheet SURFACES only (not ordinary in-page cards,
       which stay --pg-bg-card) — see the selector list below. */
    --pg-bg-modal:     #1c1c1e;
    --pg-modal-border: rgba(255,255,255,.14);

    /* Soft tinted "callout" banners/badges (amber/green/blue/red/purple/
       orange) — light mode uses a pale-50 fill + saturated-700 text; dark
       mode swaps to a translucent glow of the same hue with brightened
       text, so it reads as an accent against the dark page instead of a
       bright, clashing patch. One variable trio per hue, reused by both
       the Tailwind class overrides below AND every inline-style
       substitution site-wide — single source of truth. */
    --pg-red-bg:     rgba(239,68,68,.14);
    --pg-red-border: rgba(239,68,68,.4);
    --pg-red-text:   #f87171;
    --pg-orange-bg:     rgba(249,115,22,.15);
    --pg-orange-border: rgba(249,115,22,.4);
    --pg-orange-text:   #fb923c;
    --pg-amber-bg:     linear-gradient(135deg,rgba(217,119,6,.18) 0%,rgba(180,83,9,.10) 60%,rgba(217,119,6,.18) 100%);
    --pg-amber-bg-flat: rgba(217,119,6,.16);
    --pg-amber-border: rgba(217,119,6,.45);
    --pg-amber-text:   #fbbf24;
    --pg-yellow-bg:     rgba(234,179,8,.14);
    --pg-yellow-border: rgba(234,179,8,.4);
    --pg-yellow-text:   #facc15;
    --pg-green-bg:     rgba(34,197,94,.14);
    --pg-green-border: rgba(34,197,94,.4);
    --pg-green-text:   #4ade80;
    --pg-emerald-bg:     rgba(16,185,129,.14);
    --pg-emerald-border: rgba(16,185,129,.4);
    --pg-emerald-text:   #34d399;
    --pg-blue-bg:     rgba(59,130,246,.14);
    --pg-blue-border: rgba(59,130,246,.4);
    --pg-blue-text:   #60a5fa;
    --pg-purple-bg:     rgba(168,85,247,.14);
    --pg-purple-border: rgba(168,85,247,.4);
    --pg-purple-text:   #c084fc;
    --pg-pink-bg:     rgba(236,72,153,.14);
    --pg-pink-border: rgba(236,72,153,.4);
    --pg-pink-text:   #f472b6;
    --pg-indigo-bg:     rgba(99,102,241,.14);
    --pg-indigo-border: rgba(99,102,241,.4);
    --pg-indigo-text:   #818cf8;
    color-scheme: dark;
}

/* Page background */
html.dark-mode body { background: var(--pg-bg-page) !important; }
html.dark-mode .bg-\[\#f8f9fa\] { background: var(--pg-bg-page) !important; }
html.dark-mode .bg-\[\#fafafa\] { background: var(--pg-bg-well) !important; }

/* Cards, headers, nav, inputs — every plain white surface */
html.dark-mode .bg-white { background: var(--pg-bg-card) !important; }
html.dark-mode .bg-gray-50 { background: var(--pg-bg-well) !important; }
html.dark-mode .bg-gray-100 { background: var(--pg-bg-card-2) !important; }
html.dark-mode .bg-gray-200 { background: var(--pg-bg-well-2) !important; }
html.dark-mode .bg-gray-300 { background: var(--pg-bg-well-3) !important; }
html.dark-mode .bg-\[\#e5e7eb\] { background: var(--pg-bg-well-2) !important; }
html.dark-mode .bg-\[\#f3f4f6\] { background: var(--pg-bg-card-2) !important; }

/* Hover states on the same surfaces */
html.dark-mode .hover\:bg-\[\#f8f9fa\]:hover { background: var(--pg-bg-card-2) !important; }
html.dark-mode .hover\:bg-gray-50:hover { background: var(--pg-bg-well) !important; }
html.dark-mode .hover\:bg-gray-100:hover { background: var(--pg-bg-card-2) !important; }

/* Borders */
html.dark-mode .border-\[\#e5e7eb\] { border-color: var(--pg-border) !important; }
html.dark-mode .border-gray-100 { border-color: var(--pg-border-3) !important; }
html.dark-mode .border-gray-200 { border-color: var(--pg-border) !important; }
html.dark-mode .border-gray-300 { border-color: var(--pg-border-2) !important; }
html.dark-mode .border-\[\#f0f0f0\] { border-color: var(--pg-border-3) !important; }
html.dark-mode .border-\[\#f3f4f6\] { border-color: var(--pg-border-3) !important; }
html.dark-mode .border-\[\#f9fafb\] { border-color: var(--pg-border-3) !important; }
html.dark-mode .divide-\[\#e5e7eb\] > :not([hidden]) ~ :not([hidden]) { border-color: var(--pg-border) !important; }

/* Text */
html.dark-mode .text-\[\#1a1a1a\] { color: var(--pg-text-heading) !important; }
html.dark-mode .text-\[\#6b7280\] { color: var(--pg-text-muted) !important; }
html.dark-mode .text-\[\#9ca3af\] { color: var(--pg-text-muted) !important; }
html.dark-mode .text-\[\#374151\] { color: var(--pg-text-dimmer) !important; }
html.dark-mode .text-\[\#4b5563\] { color: var(--pg-text-dim) !important; }
html.dark-mode .text-\[\#e5e7eb\] { color: var(--pg-text-dim) !important; }
html.dark-mode .text-black { color: var(--pg-text-heading) !important; }
html.dark-mode .text-gray-400 { color: var(--pg-text-muted) !important; }
html.dark-mode .text-gray-500 { color: var(--pg-text-muted) !important; }
html.dark-mode .text-gray-600 { color: var(--pg-text-dim) !important; }
html.dark-mode .text-gray-700 { color: var(--pg-text-dimmer) !important; }
html.dark-mode .text-gray-800 { color: var(--pg-text-faint) !important; }
html.dark-mode .text-gray-900 { color: var(--pg-text-heading) !important; }

/* Form fields — inherit bg-white/border/text overrides above automatically
   (inputs use those exact classes), this just handles native browser
   chrome + placeholder color that isn't driven by a Tailwind class */
html.dark-mode input,
html.dark-mode select,
html.dark-mode textarea {
    color-scheme: dark;
}
html.dark-mode input::placeholder,
html.dark-mode textarea::placeholder {
    color: #6b7280 !important;
    opacity: 1;
}
html.dark-mode input:-webkit-autofill,
html.dark-mode input:-webkit-autofill:hover,
html.dark-mode input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--pg-text-heading) !important;
    -webkit-box-shadow: 0 0 0px 1000px var(--pg-bg-card) inset !important;
    transition: background-color 9999s ease-in-out 0s;
}

/* Shadows read as near-invisible on a black background (they're black by
   default) — drop them in favor of the border contrast already in place,
   matches the flat-card look in the reference screenshots */
html.dark-mode .shadow-sm,
html.dark-mode .shadow-md,
html.dark-mode .shadow-lg,
html.dark-mode .shadow-xl,
html.dark-mode .shadow-2xl {
    box-shadow: 0 1px 2px rgba(0,0,0,.6) !important;
}

/* Soft "callout" banners — pale-bg-50 + border-200/300 + text-600/700/800 is
   the dominant pattern for info/success/warning/error boxes site-wide
   (100+ uses each color). Pale backgrounds read as harsh bright patches on
   a black page, so dark mode swaps each to a translucent glow of the same
   hue with brightened text — same visual language, no clashing. Every hue
   pulls from the single --pg-{hue}-{bg,border,text} trio defined above. */
html.dark-mode .bg-red-50     { background: var(--pg-red-bg) !important; }
html.dark-mode .bg-blue-50    { background: var(--pg-blue-bg) !important; }
html.dark-mode .bg-green-50   { background: var(--pg-green-bg) !important; }
html.dark-mode .bg-emerald-50 { background: var(--pg-emerald-bg) !important; }
html.dark-mode .bg-orange-50  { background: var(--pg-orange-bg) !important; }
html.dark-mode .bg-amber-50   { background: var(--pg-amber-bg-flat) !important; }
html.dark-mode .bg-yellow-50  { background: var(--pg-yellow-bg) !important; }
html.dark-mode .bg-purple-50  { background: var(--pg-purple-bg) !important; }
html.dark-mode .bg-pink-50    { background: var(--pg-pink-bg) !important; }
html.dark-mode .bg-indigo-50  { background: var(--pg-indigo-bg) !important; }
html.dark-mode .bg-gray-50    { background: var(--pg-bg-well) !important; }

/* -100 shade — same family, used mostly for small icon-circle backdrops
   (e.g. a question-mark icon in a confirm modal) rather than full banners. */
html.dark-mode .bg-red-100    { background: var(--pg-red-bg) !important; }
html.dark-mode .bg-blue-100   { background: var(--pg-blue-bg) !important; }
html.dark-mode .bg-green-100  { background: var(--pg-green-bg) !important; }
html.dark-mode .bg-emerald-100{ background: var(--pg-emerald-bg) !important; }
html.dark-mode .bg-orange-100 { background: var(--pg-orange-bg) !important; }
html.dark-mode .bg-amber-100  { background: var(--pg-amber-bg-flat) !important; }
html.dark-mode .bg-yellow-100 { background: var(--pg-yellow-bg) !important; }
html.dark-mode .bg-purple-100 { background: var(--pg-purple-bg) !important; }
html.dark-mode .bg-pink-100   { background: var(--pg-pink-bg) !important; }
html.dark-mode .bg-indigo-100 { background: var(--pg-indigo-bg) !important; }

html.dark-mode .border-red-200,     html.dark-mode .border-red-300     { border-color: var(--pg-red-border) !important; }
html.dark-mode .border-blue-200,    html.dark-mode .border-blue-300    { border-color: var(--pg-blue-border) !important; }
html.dark-mode .border-green-200,   html.dark-mode .border-green-300   { border-color: var(--pg-green-border) !important; }
html.dark-mode .border-emerald-200, html.dark-mode .border-emerald-300 { border-color: var(--pg-emerald-border) !important; }
html.dark-mode .border-orange-200,  html.dark-mode .border-orange-300  { border-color: var(--pg-orange-border) !important; }
html.dark-mode .border-amber-200,   html.dark-mode .border-amber-300   { border-color: var(--pg-amber-border) !important; }
html.dark-mode .border-yellow-200,  html.dark-mode .border-yellow-300  { border-color: var(--pg-yellow-border) !important; }
html.dark-mode .border-purple-200,  html.dark-mode .border-purple-300  { border-color: var(--pg-purple-border) !important; }
html.dark-mode .border-pink-200,    html.dark-mode .border-pink-300    { border-color: var(--pg-pink-border) !important; }
html.dark-mode .border-indigo-200,  html.dark-mode .border-indigo-300  { border-color: var(--pg-indigo-border) !important; }
html.dark-mode .border-red-100     { border-color: var(--pg-red-border) !important; }
html.dark-mode .border-amber-100,   html.dark-mode .border-orange-100  { border-color: var(--pg-amber-border) !important; }

html.dark-mode .text-red-600,     html.dark-mode .text-red-700,     html.dark-mode .text-red-800,     html.dark-mode .text-red-900     { color: var(--pg-red-text) !important; }
html.dark-mode .text-blue-600,    html.dark-mode .text-blue-700,    html.dark-mode .text-blue-800     { color: var(--pg-blue-text) !important; }
html.dark-mode .text-green-600,   html.dark-mode .text-green-700,   html.dark-mode .text-green-800    { color: var(--pg-green-text) !important; }
html.dark-mode .text-emerald-600, html.dark-mode .text-emerald-700  { color: var(--pg-emerald-text) !important; }
html.dark-mode .text-orange-600,  html.dark-mode .text-orange-700,  html.dark-mode .text-orange-800   { color: var(--pg-orange-text) !important; }
html.dark-mode .text-amber-600,   html.dark-mode .text-amber-700,   html.dark-mode .text-amber-800    { color: var(--pg-amber-text) !important; }
html.dark-mode .text-yellow-600,  html.dark-mode .text-yellow-700   { color: var(--pg-yellow-text) !important; }
html.dark-mode .text-purple-600,  html.dark-mode .text-purple-700,  html.dark-mode .text-purple-800   { color: var(--pg-purple-text) !important; }
html.dark-mode .text-pink-600,    html.dark-mode .text-pink-700     { color: var(--pg-pink-text) !important; }
html.dark-mode .text-indigo-600,  html.dark-mode .text-indigo-700   { color: var(--pg-indigo-text) !important; }

/* Tailwind gradient-STOP utilities (from-*/via-*/to-*) are a SEPARATE
   class family from bg-*-50 — they set --tw-gradient-from/--tw-gradient-to
   custom properties that bg-gradient-to-* then composes into a
   background-image. Missing this family was the single biggest visual gap
   in v1: every "from-yellow-50 to-orange-50" soft banner (payment page
   amount-to-transfer box, profile premium banners, etc.) stayed pale
   cream/yellow in dark mode because only flat bg-*-50 was overridden.
   Overriding the custom property per-class works regardless of which
   from/via/to combination a given element uses. */
html.dark-mode .from-red-50     { --tw-gradient-from: var(--pg-red-bg) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(239,68,68,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }
html.dark-mode .from-orange-50  { --tw-gradient-from: var(--pg-orange-bg) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(249,115,22,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }
html.dark-mode .from-amber-50   { --tw-gradient-from: var(--pg-amber-bg-flat) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(217,119,6,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }
html.dark-mode .from-yellow-50  { --tw-gradient-from: var(--pg-yellow-bg) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(234,179,8,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }
html.dark-mode .from-green-50   { --tw-gradient-from: var(--pg-green-bg) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(34,197,94,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }
html.dark-mode .from-emerald-50 { --tw-gradient-from: var(--pg-emerald-bg) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(16,185,129,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }
html.dark-mode .from-blue-50    { --tw-gradient-from: var(--pg-blue-bg) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(59,130,246,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }
html.dark-mode .from-purple-50  { --tw-gradient-from: var(--pg-purple-bg) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(168,85,247,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }
html.dark-mode .from-purple-100 { --tw-gradient-from: var(--pg-purple-bg) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(168,85,247,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }
html.dark-mode .from-pink-50    { --tw-gradient-from: var(--pg-pink-bg) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(236,72,153,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }
html.dark-mode .from-indigo-50  { --tw-gradient-from: var(--pg-indigo-bg) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(99,102,241,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }
html.dark-mode .from-gray-100   { --tw-gradient-from: var(--pg-bg-card-2) var(--tw-gradient-from-position) !important; --tw-gradient-to: rgba(20,20,20,0) var(--tw-gradient-to-position) !important; --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to) !important; }

html.dark-mode .to-red-50     { --tw-gradient-to: var(--pg-red-bg) var(--tw-gradient-to-position) !important; }
html.dark-mode .to-orange-50  { --tw-gradient-to: var(--pg-orange-bg) var(--tw-gradient-to-position) !important; }
html.dark-mode .to-amber-50   { --tw-gradient-to: var(--pg-amber-bg-flat) var(--tw-gradient-to-position) !important; }
html.dark-mode .to-yellow-50  { --tw-gradient-to: var(--pg-yellow-bg) var(--tw-gradient-to-position) !important; }
html.dark-mode .to-green-50   { --tw-gradient-to: var(--pg-green-bg) var(--tw-gradient-to-position) !important; }
html.dark-mode .to-emerald-50 { --tw-gradient-to: var(--pg-emerald-bg) var(--tw-gradient-to-position) !important; }
html.dark-mode .to-blue-50    { --tw-gradient-to: var(--pg-blue-bg) var(--tw-gradient-to-position) !important; }
html.dark-mode .to-purple-50  { --tw-gradient-to: var(--pg-purple-bg) var(--tw-gradient-to-position) !important; }
html.dark-mode .to-pink-50    { --tw-gradient-to: var(--pg-pink-bg) var(--tw-gradient-to-position) !important; }
html.dark-mode .to-pink-100   { --tw-gradient-to: var(--pg-pink-bg) var(--tw-gradient-to-position) !important; }
html.dark-mode .to-indigo-50  { --tw-gradient-to: var(--pg-indigo-bg) var(--tw-gradient-to-position) !important; }
html.dark-mode .to-gray-200   { --tw-gradient-to: var(--pg-bg-well-2) var(--tw-gradient-to-position) !important; }

/* ═══════════════════════════════════════════════════════════════════════
   MODAL / DIALOG ELEVATION
   Every real modal, bottom-sheet, and dialog surface site-wide, lifted to
   --pg-bg-modal (see variable comment above) instead of the flat
   --pg-bg-card ordinary page cards use, plus a thin light rim (box-shadow,
   not border — border shifts box-sizing on elements without
   box-sizing:border-box; box-shadow doesn't, and still reads as a crisp
   1px outline). Uses !important so it wins over each element's own inline
   var(--pg-bg-card,#fff)/box-shadow regardless of source order. Listed by
   file so a newly-added modal is easy to slot in:
     - generic showModal() system: payment.php/_main, transaction.php/_main
     - abandoned_payment_popup.php, onboarding_v2.php, onboarding_modal.php,
       onboarding_checklist.php, p9_sections.php, invite_campaign_modal.php,
       promo_reward_modal.php, verification_modal.php, sidebar.php (upsell +
       gender-retention), signup.php (trust modal + gender modal),
       ai_chat_widget.php, balance_transfer_globals.php
     - JS-injected (no server-rendered wrapper to add a class to):
       assets/js/{fcm-init,realtime,pwa}.js, marketplace.php/marketplace-old.php
       reupload modal, payment.php/transaction.php/index.php exit-intent,
       index-new.php's own exit-intent (different id), ai-chat premium upsell
   ═══════════════════════════════════════════════════════════════════════ */
html.dark-mode #modal-content,
html.dark-mode #aba-sheet,
html.dark-mode #obv2-sheet,
html.dark-mode #pgob-modal,
html.dark-mode #p9-modal,
html.dark-mode #acct-modal,
html.dark-mode #icm-sheet,
html.dark-mode #prm-sheet,
html.dark-mode #pg-upsell-card,
html.dark-mode #pg-verify-modal,
html.dark-mode #pg-stm-card,
html.dark-mode #pg-sheet-content,
html.dark-mode #ai-chat-sheet,
html.dark-mode #pg-gc-card,
html.dark-mode #pg-push-sheet,
html.dark-mode #ps-card,
html.dark-mode #pw-card,
html.dark-mode #pg-card,
html.dark-mode #pg-gender-ret-card,
html.dark-mode #pg-gender-card,
html.dark-mode #abandoned-cart-modal > div,
html.dark-mode #ai-chat-upsell > div,
html.dark-mode #exit-intent-overlay > div,
html.dark-mode #pg-ei > div,
html.dark-mode #reupload-modal > div,
html.dark-mode #pg-a2hs-banner > div:not(#pg-a2hs-backdrop) {
    background: var(--pg-bg-modal, #fff) !important;
    box-shadow: 0 0 0 1px var(--pg-modal-border, transparent), 0 20px 60px rgba(0,0,0,.65) !important;
}

/* Backdrops behind the modals above — strengthened + blurred uniformly so
   the page content genuinely recedes instead of just going a bit darker,
   giving the (now lighter) modal surface more to contrast against. */
html.dark-mode #modal-overlay,
html.dark-mode #aba-overlay,
html.dark-mode #obv2-overlay,
html.dark-mode #pgob-overlay,
html.dark-mode #p9-modal-overlay,
html.dark-mode #acct-modal-overlay,
html.dark-mode #icm-overlay,
html.dark-mode #prm-overlay,
html.dark-mode #pg-upsell-overlay,
html.dark-mode #ai-chat-upsell,
html.dark-mode #exit-intent-overlay,
html.dark-mode #reupload-modal,
html.dark-mode #abandoned-cart-modal,
html.dark-mode #payment-status-modal,
html.dark-mode #premium-welcome-modal,
html.dark-mode #promo-grant-modal,
html.dark-mode #pg-sheet-overlay,
html.dark-mode #pg-push-bd {
    background: rgba(0,0,0,.8) !important;
    backdrop-filter: blur(6px) !important;
    -webkit-backdrop-filter: blur(6px) !important;
}

/* "Already dark" UI elements (a solid near-black button/pill that's meant
   to read as a deliberate dark accent even in LIGHT mode, e.g. a "selected
   currency" pill or a black CTA button) go invisible against a true-black
   PAGE once dark mode is active — lift them one step so they still read as
   a raised, tappable surface. */
html.dark-mode .btn-dark,
html.dark-mode .pill.sel,
html.dark-mode .pill:hover {
    background: var(--pg-bg-well-3) !important;
    border-color: var(--pg-bg-well-3) !important;
}

/* Scrollbar */
html.dark-mode ::-webkit-scrollbar-track { background: var(--pg-bg-page); }
html.dark-mode ::-webkit-scrollbar-thumb { background: var(--pg-border-2); }

/* Onboarding V2 bottom-sheet (includes/onboarding_v2.php) — the "STEP 1 OF 3"
   badge pill's background/text come from a per-type PHP color pair
   ($_c/$_cl) that's a saturated-on-pale-tint combo designed for a white
   card. On the new true-black card the pale tint reads as a bright patch,
   so dark mode swaps each type's badge to the matching translucent glow
   (same hue mapping as the rest of the site's soft-callout system). */
html.dark-mode .obv2-badge-premium         { background: var(--pg-red-bg)    !important; color: var(--pg-red-text)    !important; }
html.dark-mode .obv2-badge-deposit         { background: var(--pg-green-bg)  !important; color: var(--pg-green-text)  !important; }
html.dark-mode .obv2-badge-gift_card       { background: var(--pg-orange-bg) !important; color: var(--pg-orange-text) !important; }
html.dark-mode .obv2-badge-crypto          { background: var(--pg-purple-bg) !important; color: var(--pg-purple-text) !important; }
html.dark-mode .obv2-badge-vip_tools       { background: var(--pg-blue-bg)   !important; color: var(--pg-blue-text)   !important; }
html.dark-mode .obv2-badge-social_accounts { background: var(--pg-blue-bg)   !important; color: var(--pg-blue-text)   !important; }

/* Theme toggle switch (sidebar) */
.pg-switch-track {
    width: 44px; height: 24px; background: #d1d5db; border-radius: 12px;
    position: relative; transition: background 0.2s; display: block;
}
.pg-switch-knob {
    position: absolute; top: 2px; left: 2px; width: 20px; height: 20px;
    background: #fff; border-radius: 50%; transition: left 0.2s;
    box-shadow: 0 1px 4px rgba(0,0,0,0.3);
}
.pg-switch-input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; z-index: 1; }
.pg-switch-input:checked ~ .pg-switch-track { background: #ff0000; }
.pg-switch-input:checked ~ .pg-switch-track .pg-switch-knob { left: 22px; }
html.dark-mode .pg-switch-track { background: #333333; }

/* ===== Amount Modal — Add Funds Continue button =====
   _buildAmountModalHtml() (assets/js/payments.js) used an INLINE
   background style for the green (Add Funds) theme's Continue button so it
   could show a gradient. Inline styles always beat class-based CSS by
   specificity, which silently defeated the button's own
   "disabled:bg-gray-300" Tailwind class — the button stayed bright green
   even while genuinely disabled (amount below minimum), unlike the
   red/purple Deposit theme's Continue button, which never used an inline
   style and greyed out correctly. Moving the gradient into a real class
   here (with an !important disabled override) restores the same visual
   feedback for both themes without touching the JS disable logic itself,
   which was already correct. */
.pg-amount-cta-green { background: linear-gradient(to right,#16a34a,#059669); }
.pg-amount-cta-green:disabled { background: #d1d5db !important; color: #6b7280 !important; }

/* ===== Responsive overhaul — desktop/tablet enlargement + small-screen fixes ===== */
@media (min-width: 768px) {
    .max-w-sm { max-width: 460px; }
    .max-w-md { max-width: 520px; }
    .max-w-lg { max-width: 600px; }
}
@media (min-width: 1024px) {
    .max-w-sm { max-width: 480px; }
    .max-w-md { max-width: 560px; }
    .max-w-lg { max-width: 680px; }
}

/* Marketplace shell (header + main) needs far more room than a form/profile
   page so more product cards fit per row — wins over the general .max-w-lg
   rule above since it's declared later at equal specificity. */
@media (min-width: 768px) { .mp-shell { max-width: 720px; } }
@media (min-width: 1024px) { .mp-shell { max-width: 960px; } }
@media (min-width: 1280px) { .mp-shell { max-width: 1140px; } }

/* Product grids: 2 cols on mobile (unchanged) -> 3 -> 4 as room allows. ID
   selectors already beat Tailwind's .grid-cols-2 class, no !important needed. */
@media (min-width: 768px) {
    #tool-cards-grid, #tool-skeleton-grid, #account-cards-grid,
    #vip-tools-cards-grid, #scripts-cards-grid { grid-template-columns: repeat(3, minmax(0,1fr)); }
}
@media (min-width: 1024px) {
    #tool-cards-grid, #tool-skeleton-grid, #account-cards-grid,
    #vip-tools-cards-grid, #scripts-cards-grid { grid-template-columns: repeat(4, minmax(0,1fr)); }
}

/* Rates ticker (marketplace-old.php / marketplace.php) was clipping its last
   pill off-screen on narrow phones — its items already have flex-shrink:0
   but the row itself never scrolled. */
.mp-rate-ticker { overflow-x: auto; scrollbar-width: none; }
.mp-rate-ticker::-webkit-scrollbar { display: none; }

/* AI chat FAB overlapped the 2nd-column product card's tap target on very
   narrow phones (~360px) — shrink and pull it in from the edge there. */
@media (max-width: 400px) {
    #ai-chat-fab { width: 48px !important; height: 48px !important; right: 10px !important; }
    #ai-chat-fab svg { width: 20px; height: 20px; }
}
/* The button element's real clickable box is a square even though it looks
   circular, so its invisible corners were swallowing taps meant for
   whatever card sits underneath it. Clipping the hit-area to match the
   visible circle lets those taps pass through instead. */
#ai-chat-fab { clip-path: circle(50%); }

/* ===== UI Theme system (Regal Red / Jewel Navy+Gold) =====
   Class applied via get_user_theme_class() -> html.theme-regal /
   html.theme-jewel, resolved server-side by get_active_ui_theme()
   (includes/functions.php), same mechanism as html.dark-mode. Admin
   control: admin/ui-theme.php.

   SITE-WIDE layer: --pg-brand-400/500/600 map the site's 3 hardcoded brand
   hex values (#ef4444/#ff0000/#dc2626) to theme-appropriate colors. Every
   occurrence of those 3 hex codes inside an actual CSS context (style=""
   attributes, <style> blocks, fill=/stroke= — everywhere EXCEPT admin/,
   which has its own separate tool chrome) was mechanically rewritten to
   var(--pg-brand-*, original-hex) by _migrate_brand_red_tokens.js, so this
   one token block re-themes buttons/badges/links/gradients on every public
   page at once, not just the marketplace balance card.

   Deliberately NOT touched: Tailwind's semantic red-* utility classes
   (bg-red-600, text-red-500, border-red-500, from-red-500, etc. — 600+
   occurrences across 60 files). Unlike this codebase's bespoke brand
   buttons (which consistently use inline gradient styles, all migrated
   above), the red-* utility classes are overwhelmingly used for universal
   error/danger/rejected semantics (form validation, alert banners, status
   badges) mixed in with the occasional brand touch, with no reliable way
   to tell them apart at the CSS-selector level. Recoloring those sitewide
   would risk turning genuine error states gold/oxblood, which reads as
   broken, not premium — so semantic red stays red in every theme.

   Marketplace balance card layer (--mp-*): a bespoke, hand-tuned treatment
   for the single highest-visibility surface (card background, pill, amount
   font, decorative orbs, the Unlock Benefits button's glow) — kept as its
   own richer layer on top of the general brand tokens below, not replaced
   by them. See .mp-balance-card etc. further down. */
html.theme-regal {
    --pg-brand-500: #8a1030;
    --pg-brand-400: #a51d3f;
    --pg-brand-600: #5c0c20;

    --mp-card-bg: linear-gradient(160deg,#2a0d13 0%,#170708 70%,#0f0505 100%);
    --mp-card-border: rgba(201,162,77,.35);
    --mp-pill-bg: rgba(201,162,77,.14);
    --mp-pill-border: rgba(201,162,77,.4);
    --mp-pill-ink: #d9b96a;
    --mp-amount-ink: #f6ecd9;
    --mp-amount-font: 'Palatino Linotype', Palatino, 'Iowan Old Style', Georgia, 'Times New Roman', serif;
    --mp-brand-btn-bg: linear-gradient(to right,#8a1030,#5c0c20);
    --mp-brand-btn-ring: rgba(201,162,77,.5);
}
html.theme-jewel {
    /* Deeper bronze-gold than the balance card's --mp-* tones below — this
       set has to stay legible as plain text/links on ordinary white-page
       backgrounds sitewide, not just look good against the dark navy card
       where a brighter gold works fine. */
    --pg-brand-500: #a9862a;
    --pg-brand-400: #c9a24d;
    --pg-brand-600: #7a5e1c;

    --mp-card-bg: linear-gradient(160deg,#132a44 0%,#0c1a2c 65%,#08131f 100%);
    --mp-card-border: rgba(212,175,55,.28);
    --mp-pill-bg: rgba(212,175,55,.14);
    --mp-pill-border: rgba(212,175,55,.4);
    --mp-pill-ink: #d4af37;
    --mp-amount-ink: #f2f5fa;
    --mp-amount-font: inherit;
    --mp-brand-btn-bg: linear-gradient(to right,#d4af37,#a9862a);
    --mp-brand-btn-ring: rgba(212,175,55,.6);
}

html.theme-regal .mp-balance-card, html.theme-jewel .mp-balance-card {
    background: var(--mp-card-bg) !important;
    border-color: var(--mp-card-border) !important;
}
html.theme-regal .mp-balance-decor, html.theme-jewel .mp-balance-decor { display: none !important; }
html.theme-regal .mp-balance-pill, html.theme-jewel .mp-balance-pill {
    background: var(--mp-pill-bg) !important;
    border-color: var(--mp-pill-border) !important;
}
html.theme-regal .mp-balance-pill i, html.theme-regal .mp-balance-pill span,
html.theme-jewel .mp-balance-pill i, html.theme-jewel .mp-balance-pill span { color: var(--mp-pill-ink) !important; }
html.theme-regal .mp-balance-amount, html.theme-jewel .mp-balance-amount {
    color: var(--mp-amount-ink) !important;
    font-family: var(--mp-amount-font);
}
html.theme-regal .mp-btn-brand-red, html.theme-jewel .mp-btn-brand-red {
    background: var(--mp-brand-btn-bg) !important;
    box-shadow: 0 0 0 1px var(--mp-brand-btn-ring) inset !important;
    animation: mpBrandGlow 1.8s ease-in-out infinite !important;
}
html.theme-jewel .mp-btn-brand-red { color: #0a1220 !important; }
@keyframes mpBrandGlow {
    0%, 100% { filter: brightness(1); }
    50% { filter: brightness(1.16); }
}
@media (prefers-reduced-motion: reduce) {
    html.theme-regal .mp-btn-brand-red, html.theme-jewel .mp-btn-brand-red { animation: none !important; }
}

/* Tailwind arbitrary-value classes hardcoding the exact brand hex (bg-[#ff0000]
   etc.) — a DIFFERENT mechanism from the inline style="" attributes the
   migration script above handles, so they need their own override here, same
   technique html.dark-mode already uses for its own arbitrary-value classes
   (see e.g. html.dark-mode .bg-\[#f8f9fa\] further up). Deliberately only the
   exact-hex bracket form, not Tailwind's semantic red-500/600/etc scale
   classes (bg-red-600 etc.) — those are overwhelmingly error/danger/rejected
   semantics mixed with the occasional brand touch, with no reliable way to
   tell them apart; typing the literal brand hex instead of the semantic
   class name is itself a strong signal "this one really is brand", found via
   an actual sitewide scan of every distinct variant in use (signup.php's
   Sign Up button was the one that surfaced this gap during verification). */
html.theme-regal .bg-\[\#ff0000\], html.theme-jewel .bg-\[\#ff0000\] { background-color: var(--pg-brand-500) !important; }
html.theme-regal .text-\[\#ff0000\], html.theme-jewel .text-\[\#ff0000\] { color: var(--pg-brand-500) !important; }
html.theme-regal .border-\[\#ff0000\], html.theme-jewel .border-\[\#ff0000\] { border-color: var(--pg-brand-500) !important; }
html.theme-regal .hover\:text-\[\#ff0000\]:hover, html.theme-jewel .hover\:text-\[\#ff0000\]:hover { color: var(--pg-brand-500) !important; }
html.theme-regal .hover\:border-\[\#ff0000\]:hover, html.theme-jewel .hover\:border-\[\#ff0000\]:hover { border-color: var(--pg-brand-500) !important; }
html.theme-regal .focus\:border-\[\#ff0000\]:focus, html.theme-jewel .focus\:border-\[\#ff0000\]:focus { border-color: var(--pg-brand-500) !important; }
html.theme-regal .ring-\[\#ff0000\], html.theme-jewel .ring-\[\#ff0000\],
html.theme-regal .focus\:ring-\[\#ff0000\]:focus, html.theme-jewel .focus\:ring-\[\#ff0000\]:focus { --tw-ring-color: var(--pg-brand-500) !important; }
html.theme-regal .from-\[\#ff0000\], html.theme-jewel .from-\[\#ff0000\] { --tw-gradient-from: var(--pg-brand-500) !important; }
html.theme-regal .to-\[\#dc2626\], html.theme-jewel .to-\[\#dc2626\] { --tw-gradient-to: var(--pg-brand-600) !important; }
html.theme-regal .to-\[\#cc0000\], html.theme-jewel .to-\[\#cc0000\] { --tw-gradient-to: var(--pg-brand-600) !important; }
html.theme-regal .hover\:bg-\[\#cc0000\]:hover, html.theme-jewel .hover\:bg-\[\#cc0000\]:hover { background-color: var(--pg-brand-600) !important; }
html.theme-regal .hover\:from-\[\#cc0000\]:hover, html.theme-jewel .hover\:from-\[\#cc0000\]:hover { --tw-gradient-from: var(--pg-brand-600) !important; }

/* Modal urgency/discount banners (payments.js) use Tailwind's semantic
   bg-red-50/border-red-200/text-red-600 classes, which stay untouched
   everywhere ELSE on purpose (they're the same classes real error/danger
   messages use, and recoloring those sitewide would be wrong). These two
   specific banners are genuine urgency/persuasion copy, not errors, so they
   get their own targeted hook classes instead of touching the shared
   Tailwind classes. */
html.theme-regal .pg-urgency-banner, html.theme-jewel .pg-urgency-banner { background-color: color-mix(in srgb, var(--pg-brand-500) 8%, transparent) !important; border-color: color-mix(in srgb, var(--pg-brand-500) 30%, transparent) !important; }
html.theme-regal .pg-urgency-text, html.theme-jewel .pg-urgency-text { color: var(--pg-brand-600) !important; }

/* Product card borders now follow whichever theme is active (subtle, not
   bold) instead of a flat neutral gray — uses the same var(--pg-brand-500,
   #ff0000) + color-mix(...,transparent) pattern as .pg-urgency-banner above,
   but UNSCOPED (no html.theme-* prefix) so it also applies in today's
   default state, where plain red already IS the "active theme". !important
   is needed since each card's own inline style sets border-color directly
   (an admin-configurable per-product color that, being a static hex, can
   never itself "follow the active theme" the way a CSS variable can). */
.tool-card, .account-card, .p9-card, .upd-card { border-color: color-mix(in srgb, var(--pg-brand-500,#ff0000) 26%, transparent) !important; }
