/* ==================== ОСНОВНЫЕ СТИЛИ (iOS-style) ==================== */

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    -webkit-tap-highlight-color: transparent;
}

/* === Theming ===
   Default = LIGHT (per latest brief). Dark is opt-in via the toggle in
   profile (sets `<html data-theme="dark">`). All themable colours come
   from CSS variables; the `--overlay-N` set replaces the
   rgba(255,255,255,0.0X) tints that used to be hard-coded for the dark
   theme — on light theme they become near-black tints, so hover states
   and subtle dividers survive the flip without a white-on-white mess. */
:root {
    --primary-bg:        #F2F2F7;
    --secondary-bg:      #FFFFFF;
    --card-bg:           #FFFFFF;
    --accent-blue:       #007AFF;
    --accent-light-blue: #5AC8FA;
    --text-primary:      #000000;
    --text-secondary:    #6E6E73;
    --border-color:      rgba(0,0,0,0.10);

    /* Overlays — stronger than 0.03 on white otherwise balance rows
       and chips become near-invisible. */
    --overlay-1: rgba(0,0,0,0.06);
    --overlay-2: rgba(0,0,0,0.10);
    --overlay-3: rgba(0,0,0,0.16);
    --overlay-fade: rgba(0,0,0,0.05);

    /* Hover/pressed surfaces on top of card-bg */
    --surface-elevated: #FFFFFF;
    --surface-pressed:  rgba(0,0,0,0.05);
    --tabbar-bg:        rgba(255,255,255,0.92);
    --tabbar-shadow:    0 8px 28px rgba(0,0,0,0.12);
    --progress-shell-from: rgba(245,245,247,0.98);
    --progress-shell-to:   rgba(230,230,235,0.98);
    --progress-inner-bg:   rgba(245,245,247,0.92);
    --progress-track-bg:   rgba(0,0,0,0.06);
    /* Text inside the lg progress shell — needs to flip per theme so the
       shell isn't a "white-on-white" wash on light. */
    --progress-text:           #1C1C1E;
    --progress-text-muted:     rgba(60,60,67,0.55);
    --progress-caption-text:   #FFFFFF;
    --progress-caption-bg:     rgba(110,110,120,0.78);

    /* Per-theme shadow stack so cards lift off the light background;
       keeps the same vertical hierarchy users got used to in dark. */
    --shadow-small:  0 1px 2px rgba(0,0,0,0.04), 0 4px 12px rgba(0,0,0,0.06);
    --shadow-medium: 0 2px 6px rgba(0,0,0,0.06), 0 12px 28px rgba(0,0,0,0.10);
    --shadow-large:  0 4px 12px rgba(0,0,0,0.10), 0 24px 48px rgba(0,0,0,0.14);

    /* Brand / status palette. Pulled out of inline hex colours so the
       dark theme can adjust contrast against its darker surfaces. The
       light values stay close to the iOS HIG palette since most users
       open the app in Telegram's light theme on iPhone. */
    --color-success:       #34C759;
    --color-warning:       #FF9500;
    --color-danger:        #FF3B30;
    --color-info:          #007AFF;
    --color-ton:           #0088CC;
    --color-ton-dark:      #005F99;
    --color-usdt:          #26A17B;
    --color-stars:         #FFD700;

    /* Secondary-button surface: needs to be visibly different from
       card-bg AND from the modal sheet, otherwise the button blends
       into white. F2F2F7 matches Apple HIG's "fill" surface and
       reads clearly on every screen. */
    --btn-secondary-bg:        #F2F2F7;
    --btn-secondary-bg-hover:  #E5E5EA;
    --btn-secondary-border:    rgba(0,0,0,0.16);
}
:root[data-theme="dark"] {
    --primary-bg:        #000000;
    --secondary-bg:      #1C1C1E;
    --card-bg:           #2C2C2E;
    --accent-blue:       #0A84FF;
    --accent-light-blue: #64D2FF;
    --text-primary:      #FFFFFF;
    --text-secondary:    #8E8E93;
    --border-color:      #38383A;

    --overlay-1: rgba(255,255,255,0.04);
    --overlay-2: rgba(255,255,255,0.08);
    --overlay-3: rgba(255,255,255,0.14);
    --overlay-fade: rgba(255,255,255,0.04);

    --surface-elevated: #2C2C2E;
    --surface-pressed:  rgba(255,255,255,0.06);
    --tabbar-bg:        rgba(28,28,30,0.72);
    --tabbar-shadow:    0 8px 32px rgba(0,0,0,0.6);
    --progress-shell-from: rgba(37,39,40,0.98);
    --progress-shell-to:   rgba(26,27,28,0.98);
    --progress-inner-bg:   rgba(40,40,39,0.94);
    --progress-track-bg:   rgba(255,255,255,0.08);
    --progress-text:           #FFFFFF;
    --progress-text-muted:     rgba(255,255,255,0.46);
    --progress-caption-text:   #FFFFFF;
    --progress-caption-bg:     rgba(110,110,120,0.55);

    --shadow-small:  0 2px 8px rgba(0,0,0,0.30);
    --shadow-medium: 0 4px 16px rgba(0,0,0,0.40);
    --shadow-large:  0 8px 32px rgba(0,0,0,0.50);

    /* Slightly brighter status colours on dark — iOS uses the lighter
       variants (e.g. #30D158 vs #34C759) for better contrast on near-
       black surfaces. */
    --color-success:       #30D158;
    --color-warning:       #FFD60A;
    --color-danger:        #FF453A;
    --color-info:          #0A84FF;
    --color-ton:           #38B6FF;
    --color-ton-dark:      #1A8AC9;
    --color-usdt:          #26A17B;
    --color-stars:         #FFD700;

    /* Dark theme — secondary button needs to sit above card-bg too.
       3A3A3C is iOS HIG "tertiary fill" on dark. */
    --btn-secondary-bg:        #3A3A3C;
    --btn-secondary-bg-hover:  #48484A;
    --btn-secondary-border:    rgba(255,255,255,0.10);
}
/* Layout-only vars stay in :root so they don't need to be redeclared. */
:root {
    
    /* Safe-area — these vars are owned by tg.js (set from Telegram WebApp SDK).
       The env() values are only a *fallback* applied via :root selector below
       in case tg.js can't run (e.g. project preview in plain browser). */
    --safe-area-top:    0px;
    --safe-area-bottom: 0px;
    --safe-area-left:   0px;
    --safe-area-right:  0px;
    --content-safe-top:    0px;
    --content-safe-bottom: 0px;
    --content-safe-left:   0px;
    --content-safe-right:  0px;
    --tg-viewport-height: 100vh;
    --tabbar-height: 64px;
    
    /* Скругления */
    --radius-small: 10px;
    --radius-medium: 16px;
    --radius-large: 24px;
    --border-radius: 12px; /* iOS-style закругление по умолчанию */
    
    /* Тени */
    --shadow-small: 0 2px 8px rgba(0, 0, 0, 0.3);
    --shadow-medium: 0 4px 16px rgba(0, 0, 0, 0.4);
    --shadow-large: 0 8px 32px rgba(0, 0, 0, 0.5);
}

/* Fallback when tg.js can't set safe-area (plain browser preview).
   Inside Telegram WebApp tg.js overwrites these immediately. */
@supports (padding: env(safe-area-inset-top)) {
    :root:not(:has(.has-tg-safe-area)) {
        --safe-area-top:    env(safe-area-inset-top, 0px);
        --safe-area-bottom: env(safe-area-inset-bottom, 0px);
        --safe-area-left:   env(safe-area-inset-left, 0px);
        --safe-area-right:  env(safe-area-inset-right, 0px);
    }
}

body {
    font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif;
    background: var(--primary-bg);
    color: var(--text-primary);
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* outer device safe-area (notch / Dynamic Island) */
    padding-left: var(--safe-area-left);
    padding-right: var(--safe-area-right);
}

#app {
    min-height: var(--tg-viewport-height, 100vh);
    display: flex;
    flex-direction: column;
}

#page-container {
    flex: 1;
    /* `content-safe-top` is what Telegram says is *non-overlapped* by its own
       header chrome. We add a generous gap on top of it so the big page
       title ("Мои кошельки", "История транзакций") never gets clipped by
       the close/expand chrome — even when Telegram reports 0. */
    padding-top:    calc(var(--content-safe-top, 0px) + var(--safe-area-top, 0px) + 32px);
    padding-bottom: calc(var(--tabbar-height) + var(--safe-area-bottom) + 16px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    transition: opacity 0.08s ease;
    will-change: opacity;
}

/* ==================== НИЖНИЙ ТАББАР (iOS-style) ==================== */

.bottom-tabbar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 0 calc(12px + var(--safe-area-left)) calc(var(--safe-area-bottom) + 16px) calc(12px + var(--safe-area-right));
    z-index: 1000;
    pointer-events: none;
}

.tabbar-wrapper {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-around;
    background: var(--tabbar-bg);
    /* Half the blur radius — saturate(180%) on top of blur(40px) was the
       biggest GPU cost on low-end phones. blur(18px) reads identical in
       practice and the tabbar paint stays under 4ms. */
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    /* Promote to its own layer so scrolling the page doesn't repaint
       the tabbar every frame. */
    transform: translateZ(0);
    contain: layout paint style;
    border-radius: 28px;
    padding: 8px 12px 8px;
    box-shadow: var(--tabbar-shadow),
                0 0 0 1px var(--overlay-2) inset;
    pointer-events: auto;
}

.tab-button {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 8px 16px;
    background: none;
    border: none;
    color: var(--text-secondary);
    cursor: pointer;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    z-index: 2;
}

.tab-icon {
    width: 24px;
    height: 24px;
    stroke-width: 2;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.tab-label {
    font-size: 10px;
    font-weight: 500;
    letter-spacing: -0.2px;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.tab-button.active {
    color: var(--accent-blue);
}

.tab-button.active .tab-icon {
    transform: scale(1.1);
}

.tab-button:active {
    transform: scale(0.95);
}

/* Индикатор активной вкладки */
.tab-indicator {
    position: absolute;
    bottom: 8px;
    height: calc(100% - 16px);
    background: rgba(10, 132, 255, 0.15);
    border-radius: 18px;
    transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
    z-index: 1;
    pointer-events: none;
}

/* ==================== СТРАНИЦЫ ==================== */

.page {
    min-height: 100vh;
    animation: fadeIn 0.3s ease-out;
}

@keyframes fadeIn {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

@keyframes fadeOut {
    from {
        opacity: 1;
    }
    to {
        opacity: 0;
    }
}

@keyframes slideUpFade {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes slideDown {
    from {
        transform: translateY(0);
    }
    to {
        transform: translateY(100%);
    }
}

.page-header {
    /* Top safe-area is already handled by #page-container (it adds
       --content-safe-top + 16px). Don't double-pad: just give the header
       its own breathing room within the page. */
    padding: 8px 20px 16px;
    background: transparent;
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
}

.page-header .btn-back {
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 10;
    margin: 0;
}

.page-header:has(.btn-back) .page-title {
    padding-left: 48px;
}

.page-title {
    font-size: 28px;          /* 34 was clipping under TG header on small phones */
    line-height: 1.15;
    font-weight: 700;
    letter-spacing: -0.5px;
    flex: 1;
    min-width: 0;             /* allow flex item to shrink for ellipsis if needed */
    overflow-wrap: anywhere;
}

.page-content {
    padding: 0 20px 20px;
}

/* ==================== КАРТОЧКИ ==================== */

.info-card {
    background: var(--card-bg);
    border-radius: var(--radius-medium);
    padding: 20px;
    margin-bottom: 16px;
    box-shadow: var(--shadow-small);
    /* Each card is its own layout/paint island — text reflows inside a
       card don't kick the rest of the page. Big perf win on profile
       pages with 5-6 cards stacked. */
    contain: layout paint style;
}

/* ═══════════════════════════════════════════════════════════════════
 * Лидерборд (страница «Лидеры»)
 *
 * 1:1 replica of the TopGift leaderboard design:
 *   - Dark-themed page (forced black bg regardless of app theme)
 *   - Full-width background image with per-place glow overlays
 *   - Top-3 avatars positioned absolutely on the background
 *   - Small numbered medal circles with gold/silver/bronze gradients
 *   - Flat dark-pill list rows for places 4+
 *   - Scale-bounce medal animation + avatar fade-in
 * ═══════════════════════════════════════════════════════════════════ */

/* Leaderboard page — theme-aware (light/dark). The podium SHOWCASE
 * area uses a dark backdrop because the decorative bg image is dark,
 * but the rest of the page (header, list rows, "your place") follows
 * the app's active theme.
 *
 * Per-theme variable defaults:
 *   --leaders-pill-bg     = pill row background (#191919 dark / light)
 *   --leaders-pill-text   = pill row primary text
 *   --leaders-pill-muted  = pill row secondary text
 *   --leaders-page-bg     = page background
 * Falls back to global tokens if unset. */
.leaders-page {
    --leaders-page-bg:    var(--primary-bg);
    --leaders-pill-bg:    var(--card-bg);
    --leaders-pill-text:  var(--text-primary);
    --leaders-pill-muted: var(--text-secondary);
    --leaders-separator:  var(--border-color);
    /* Showcase area always reads dark since the bg image is dark */
    --leaders-showcase-bg: linear-gradient(180deg, #0c0c14 0%, #1a1a26 100%);
    --leaders-showcase-text: #fff;
    --leaders-showcase-muted: rgba(255,255,255,0.55);
    background: var(--leaders-page-bg);
    color: var(--text-primary);
    min-height: 100vh;
}
.leaders-page .page-header {
    background: transparent;
    padding-bottom: 0;
}
.leaders-page .page-title {
    color: var(--text-primary);
}
.leaders-page .page-subtitle {
    color: var(--text-secondary);
    font-size: 14px;
    margin: 6px 0 0;
    line-height: 1.4;
}

/* ═══════════════════════════════════════════════════════════════════
 * 3D FROSTED-GLASS PODIUM STAGE
 * ─────────────────────────────────────────────────────────────────
 * Pure SVG + CSS implementation. No external image assets. Three
 * isometric blocks (front + top + side faces) rendered via SVG
 * polygons share exact corner points so the staircase reads as a
 * single rostrum without edge drift.
 *
 * Visual order left → right: 2nd · 1st · 3rd (1st crowns the row).
 * Entry sequence:
 *   1. Stage halo fades in
 *   2. 3rd block rises (scaleY 0 → 1)
 *   3. 2nd block rises
 *   4. 1st block rises
 *   5. Avatars pop on top of each block (3rd → 2nd → 1st)
 *   6. Medals bounce in
 *   7. Names + amounts fade up
 * ═══════════════════════════════════════════════════════════════════ */

.leaders-stage {
    position: relative;
    width: 100%;
    margin: 16px 0 24px;
    padding: 36px 12px 22px;
    background: var(--leaders-showcase-bg);
    border-radius: 24px;
    overflow: hidden;
    box-shadow: var(--shadow-medium);
    isolation: isolate;
}

/* Soft gold radial halo behind the centre slot, drawing the eye to
 * the winner. Sits at z-index 0 (everything else is z-index 1+). */
.leaders-stage__halo {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(45% 55% at 50% 38%,
            rgba(255,200,80,0.22), transparent 70%),
        radial-gradient(80% 70% at 50% 100%,
            rgba(60,80,160,0.18), transparent 65%);
    opacity: 0;
    animation: leadersHaloIn 0.6s ease-out forwards;
}
@keyframes leadersHaloIn {
    to { opacity: 1; }
}

/* Floor shadow line under all three blocks — gives the stage a
 * "ground plane" feel so the blocks read as standing on something. */
.leaders-stage__floor {
    position: absolute;
    left: 6%;
    right: 6%;
    bottom: 14px;
    height: 12px;
    z-index: 0;
    background: radial-gradient(50% 100% at 50% 0%,
        rgba(0,0,0,0.50), transparent 70%);
    filter: blur(6px);
    pointer-events: none;
}

/* Decorative sparkles drifting behind the blocks — six dots scattered
 * across the stage, each twinkling at a different cadence. */
.leaders-stage__sparkles {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}
.leaders-stage__sparkles span {
    position: absolute;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: radial-gradient(circle, #fff 0%, rgba(255,255,255,0.4) 50%, transparent 100%);
    opacity: 0;
    animation: leadersSparkle 3.2s ease-in-out infinite;
    box-shadow: 0 0 8px rgba(255,255,255,0.6);
}
.leaders-stage__sparkles span:nth-child(1) { top: 18%; left: 12%; animation-delay: 1.2s; }
.leaders-stage__sparkles span:nth-child(2) { top: 28%; left: 78%; animation-delay: 1.9s; }
.leaders-stage__sparkles span:nth-child(3) { top: 12%; left: 56%; animation-delay: 2.4s; width: 3px; height: 3px; }
.leaders-stage__sparkles span:nth-child(4) { top: 42%; left: 30%; animation-delay: 2.8s; width: 3px; height: 3px; }
.leaders-stage__sparkles span:nth-child(5) { top: 22%; left: 90%; animation-delay: 3.1s; width: 5px; height: 5px; }
.leaders-stage__sparkles span:nth-child(6) { top: 36%; left: 6%;  animation-delay: 3.6s; }
@keyframes leadersSparkle {
    0%, 100% { opacity: 0; transform: scale(0.6); }
    50%      { opacity: 1; transform: scale(1.2); }
}

/* Slots container — flex row, bottom-aligned so 1st (with tallest
 * block) sits visually higher than 2nd / 3rd. */
.leaders-stage__slots {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 6px;
    min-height: 280px;
}

/* Individual slot — vertical stack: avatar (top), label, block (bottom).
 * Bottom-aligned within the flex so all three rest on the same
 * "floor" regardless of block height. */
.leaders-slot {
    flex: 1 1 0;
    max-width: 36%;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
}
.leaders-slot--1st { order: 2; }
.leaders-slot--2nd { order: 1; }
.leaders-slot--3rd { order: 3; }

/* Avatar — sits at the top of the slot, close to the block top so it
 * visually "rests on" the podium. Bottom-margin tightened so it
 * connects to the label/block beneath. */
.leaders-slot__avatar {
    width: 72%;
    aspect-ratio: 1 / 1;
    max-width: 76px;
    border-radius: 50%;
    overflow: hidden;
    background-color: rgba(255,255,255,0.14);
    box-shadow: 0 8px 22px rgba(0,0,0,0.45),
                inset 0 0 0 2px rgba(255,255,255,0.22);
    position: relative;
    z-index: 3;
    margin-bottom: 6px;
    opacity: 0;
    transform: translateY(8px) scale(0.6);
    animation: leadersAvatarPop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
.leaders-slot--1st .leaders-slot__avatar {
    width: 78%;
    max-width: 92px;
    animation-delay: 1.10s;
}
.leaders-slot--2nd .leaders-slot__avatar { animation-delay: 0.95s; }
.leaders-slot--3rd .leaders-slot__avatar { animation-delay: 0.80s; }
@keyframes leadersAvatarPop {
    to { opacity: 1; transform: translateY(0) scale(1); }
}
.leaders-slot__avatar img,
.leaders-slot__avatar .leaders-avatar-fallback {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
    display: block;
}

/* Fallback avatar (no photo) */
.leaders-avatar-fallback {
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-weight: 700;
    line-height: 1;
    border-radius: 50%;
}

/* Label stack — name + amount only (medal moved onto the block).
 * Sits tightly between avatar and block, so the three feel grouped. */
.leaders-slot__label {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    margin-bottom: 4px;
    position: relative;
    z-index: 4;
    max-width: 100%;
    min-width: 0;
    text-align: center;
}

/* Medal — now positioned on the block's top face, sitting like a
 * plaque on the podium step. Wrapper centres the medal horizontally
 * across the block's width. */
.leaders-slot__medal-wrap {
    position: absolute;
    left: 50%;
    top: 0;
    transform: translate(-50%, -50%);
    z-index: 5;
    pointer-events: none;
}
.leaders-medal-wrapper {
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transform: scale(0);
    animation: leadersMedalBounce 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
.leaders-slot--1st .leaders-medal-wrapper { animation-delay: 1.25s; }
.leaders-slot--2nd .leaders-medal-wrapper { animation-delay: 1.10s; }
.leaders-slot--3rd .leaders-medal-wrapper { animation-delay: 0.95s; }
@keyframes leadersMedalBounce {
    0%   { opacity: 0; transform: scale(0); }
    60%  { opacity: 1; transform: scale(1.4); }
    100% { opacity: 1; transform: scale(1); }
}

/* ── Iridescent place medals (gold / silver / bronze) ───────────────
 * Each medal is a coin with:
 *   1. A conic-gradient base for the metallic colour wheel that
 *      catches light from multiple angles (the "iridescent" feel)
 *   2. A radial highlight on the upper-left for the 3D sphere look
 *   3. An animated shine bar swept diagonally across — sells the
 *      polished metal feel
 *   4. An inset shadow at the bottom for depth
 *   5. A glow box-shadow in the tier colour for ambient light
 * Numbers are italic + bold + drop-shadowed for that engraved feel. */
.leaders_first-place-medal span,
.leaders_second-place-medal span,
.leaders_third-place-medal span {
    font-style: italic;
    font-size: 15px;
    font-weight: 800;
    line-height: 1;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 28px;
    height: 28px;
    border-radius: 99px;
    position: relative;
    overflow: hidden;
    isolation: isolate;
    letter-spacing: -0.02em;
    -webkit-text-stroke: 0;
}

/* 1st — pure rich gold: warm yellows with bright highlights and
 * deep amber shadows. Animated shine sweep. */
.leaders_first-place-medal span {
    color: #5a3a00;
    background:
        radial-gradient(circle at 30% 25%, rgba(255,255,255,0.85) 0%, transparent 45%),
        conic-gradient(from 215deg at 50% 50%,
            #fff5c2 0deg,
            #ffd84a 60deg,
            #ffb300 120deg,
            #c98300 180deg,
            #ffb300 240deg,
            #ffd84a 300deg,
            #fff5c2 360deg);
    border: 1.5px solid #ffc940;
    box-shadow:
        inset 0 -3px 6px rgba(120,60,0,0.55),
        inset 0 2px 3px rgba(255,255,255,0.55),
        0 0 14px rgba(255,180,30,0.55),
        0 4px 10px rgba(0,0,0,0.45);
    text-shadow: 0 1px 0 rgba(255,240,180,0.65);
}
.leaders_first-place-medal span::before {
    content: "";
    position: absolute;
    inset: -2px;
    background: linear-gradient(115deg,
        transparent 30%,
        rgba(255,255,255,0.65) 48%,
        rgba(255,255,255,0.85) 50%,
        rgba(255,255,255,0.65) 52%,
        transparent 70%);
    transform: translateX(-130%);
    animation: medalShineGold 3s ease-in-out 1.4s infinite;
    pointer-events: none;
    z-index: 2;
    mix-blend-mode: overlay;
}
@keyframes medalShineGold {
    0%   { transform: translateX(-130%); }
    50%  { transform: translateX(130%); }
    100% { transform: translateX(130%); }
}

/* 2nd — bright platinum silver: cool whites with steel-blue accents
 * for that polished mirror-silver feel. Subtler shine. */
.leaders_second-place-medal span {
    color: #2a2a30;
    background:
        radial-gradient(circle at 30% 25%, rgba(255,255,255,0.95) 0%, transparent 50%),
        conic-gradient(from 215deg at 50% 50%,
            #ffffff 0deg,
            #e0e4ec 60deg,
            #b4bbc8 120deg,
            #7e8694 180deg,
            #b4bbc8 240deg,
            #e0e4ec 300deg,
            #ffffff 360deg);
    border: 1.5px solid #d8dde6;
    box-shadow:
        inset 0 -3px 6px rgba(60,70,90,0.50),
        inset 0 2px 3px rgba(255,255,255,0.75),
        0 0 12px rgba(200,210,225,0.50),
        0 4px 10px rgba(0,0,0,0.40);
    text-shadow: 0 1px 0 rgba(255,255,255,0.70);
}
.leaders_second-place-medal span::before {
    content: "";
    position: absolute;
    inset: -2px;
    background: linear-gradient(115deg,
        transparent 30%,
        rgba(255,255,255,0.55) 48%,
        rgba(255,255,255,0.85) 50%,
        rgba(255,255,255,0.55) 52%,
        transparent 70%);
    transform: translateX(-130%);
    animation: medalShineSilver 3.4s ease-in-out 1.8s infinite;
    pointer-events: none;
    z-index: 2;
    mix-blend-mode: overlay;
}
@keyframes medalShineSilver {
    0%   { transform: translateX(-130%); }
    55%  { transform: translateX(130%); }
    100% { transform: translateX(130%); }
}

/* 3rd — rich bronze/copper: warm browns with copper highlights and
 * deep auburn shadows. Patina-like depth. */
.leaders_third-place-medal span {
    color: #4a1f00;
    background:
        radial-gradient(circle at 30% 25%, rgba(255,220,180,0.85) 0%, transparent 45%),
        conic-gradient(from 215deg at 50% 50%,
            #ffd0a0 0deg,
            #e89055 60deg,
            #c46818 120deg,
            #7a3a00 180deg,
            #c46818 240deg,
            #e89055 300deg,
            #ffd0a0 360deg);
    border: 1.5px solid #d47730;
    box-shadow:
        inset 0 -3px 6px rgba(70,30,0,0.60),
        inset 0 2px 3px rgba(255,220,180,0.55),
        0 0 12px rgba(196,104,24,0.55),
        0 4px 10px rgba(0,0,0,0.45);
    text-shadow: 0 1px 0 rgba(255,200,150,0.55);
}
.leaders_third-place-medal span::before {
    content: "";
    position: absolute;
    inset: -2px;
    background: linear-gradient(115deg,
        transparent 30%,
        rgba(255,235,200,0.55) 48%,
        rgba(255,235,200,0.85) 50%,
        rgba(255,235,200,0.55) 52%,
        transparent 70%);
    transform: translateX(-130%);
    animation: medalShineBronze 3.6s ease-in-out 2.2s infinite;
    pointer-events: none;
    z-index: 2;
    mix-blend-mode: overlay;
}
@keyframes medalShineBronze {
    0%   { transform: translateX(-130%); }
    55%  { transform: translateX(130%); }
    100% { transform: translateX(130%); }
}

/* Nickname — fades up after the medal bounces in. SF Pro / system
 * font with semi-condensed letter-spacing for that polished feel. */
.leaders-slot__name {
    font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display',
                 'Inter', 'Segoe UI', system-ui, sans-serif;
    font-size: 13.5px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 120px;
    text-shadow: 0 1px 4px rgba(0,0,0,0.75),
                 0 0 12px rgba(0,0,0,0.40);
    opacity: 0;
    transform: translateY(4px);
    animation: leadersNameIn 0.35s ease-out forwards;
}
.leaders-slot--1st .leaders-slot__name {
    animation-delay: 1.40s;
    font-size: 15px;
    background: linear-gradient(180deg, #fff 0%, #ffe9a8 100%);
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
    /* Fallback text colour for browsers without text-fill-color */
    color: #ffe9a8;
}
.leaders-slot--2nd .leaders-slot__name { animation-delay: 1.25s; }
.leaders-slot--3rd .leaders-slot__name { animation-delay: 1.10s; }
@keyframes leadersNameIn {
    to { opacity: 1; transform: translateY(0); }
}

/* Amount — same fade-up. Tabular numbers + tighter tracking + a
 * subtle metallic gradient for the winner's number. */
.leaders-slot__amount {
    font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display',
                 'Inter', 'Segoe UI', system-ui, sans-serif;
    font-size: 12.5px;
    font-weight: 700;
    color: rgba(255,255,255,0.92);
    white-space: nowrap;
    letter-spacing: -0.01em;
    text-shadow: 0 1px 3px rgba(0,0,0,0.65);
    font-variant-numeric: tabular-nums;
    opacity: 0;
    transform: translateY(4px);
    animation: leadersNameIn 0.35s ease-out forwards;
}
.leaders-slot--1st .leaders-slot__amount {
    animation-delay: 1.50s;
    font-size: 14px;
    font-weight: 800;
    color: #ffd45a;
    text-shadow: 0 1px 3px rgba(0,0,0,0.75),
                 0 0 10px rgba(255,180,30,0.40);
}
.leaders-slot--2nd .leaders-slot__amount {
    animation-delay: 1.35s;
    color: #e6ebf3;
}
.leaders-slot--3rd .leaders-slot__amount {
    animation-delay: 1.20s;
    color: #ffc090;
}

/* ── 3D frosted-glass block — HTML divs with backdrop-filter for a
 *    real frosted-glass refraction (blurs the halo + sparkles behind).
 *    Block heights set per-place via custom property --block-h. Block
 *    rises from below (scaleY 0 → 1) on entry. */
.leaders-slot__block {
    width: 100%;
    max-width: 130px;
    height: var(--block-h, 80px);
    position: relative;
    transform-origin: bottom center;
    transform: scaleY(0);
    opacity: 0;
    animation: leadersBlockRise 0.55s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
    filter: drop-shadow(0 10px 22px rgba(0,0,0,0.55));
}
.leaders-slot--1st .leaders-slot__block { --block-h: 124px; animation-delay: 0.60s; }
.leaders-slot--2nd .leaders-slot__block { --block-h: 96px;  animation-delay: 0.35s; }
.leaders-slot--3rd .leaders-slot__block { --block-h: 74px;  animation-delay: 0.10s; }
@keyframes leadersBlockRise {
    0%   { transform: scaleY(0); opacity: 0; }
    100% { transform: scaleY(1); opacity: 1; }
}

/* The glass container — relative parent for all three faces. The
 * top-of-block visual is the top face (parallelogram), the depth
 * is the right side face, and the main viewer-facing surface is
 * the front face (rectangle). Top depth + side depth via vars so
 * geometry stays consistent across pieces. */
.leaders-glass {
    --top-depth: 14px;
    --side-depth: 12px;
    position: absolute;
    inset: 0;
}

/* FRONT face — the main viewer-facing glass rectangle. Uses
 * backdrop-filter to actually blur whatever sits behind it (the
 * stage halo + sparkles + gradient), giving a real glass refraction
 * feel rather than a flat tinted overlay. */
.leaders-glass__face {
    position: absolute;
    top: var(--top-depth);
    left: 0;
    right: var(--side-depth);
    bottom: 0;
    -webkit-backdrop-filter: blur(14px) saturate(180%);
            backdrop-filter: blur(14px) saturate(180%);
    background:
        linear-gradient(180deg,
            rgba(255,255,255,0.22) 0%,
            rgba(255,255,255,0.10) 38%,
            rgba(255,255,255,0.04) 100%);
    border: 1px solid rgba(255,255,255,0.22);
    border-top-color: rgba(255,255,255,0.42);
    border-radius: 6px 6px 3px 3px;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.30),
        inset 0 -8px 16px rgba(0,0,0,0.22),
        inset 6px 0 12px rgba(255,255,255,0.05);
    overflow: hidden;
}

/* Vertical shine stripe down the centre of the front face. Lives
 * inside the face so it gets clipped by overflow:hidden and never
 * leaks past the corners. */
.leaders-glass__shine {
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg,
        transparent 35%,
        rgba(255,255,255,0.10) 48%,
        rgba(255,255,255,0.20) 50%,
        rgba(255,255,255,0.10) 52%,
        transparent 65%);
    pointer-events: none;
}

/* TOP face — parallelogram lid, brightest face (catches light) */
.leaders-glass__top {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: var(--top-depth);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
            backdrop-filter: blur(16px) saturate(180%);
    background: linear-gradient(135deg,
        rgba(255,255,255,0.38) 0%,
        rgba(255,255,255,0.20) 60%,
        rgba(255,255,255,0.10) 100%);
    clip-path: polygon(
        0 100%,
        calc(100% - var(--side-depth)) 100%,
        100% 0,
        var(--side-depth) 0
    );
    border-top: 1px solid rgba(255,255,255,0.42);
}

/* SIDE face — right-edge depth, darkest face (in shadow) */
.leaders-glass__side {
    position: absolute;
    top: 0;
    right: 0;
    width: var(--side-depth);
    bottom: 0;
    -webkit-backdrop-filter: blur(10px) saturate(140%);
            backdrop-filter: blur(10px) saturate(140%);
    background: linear-gradient(90deg,
        rgba(0,0,0,0.30) 0%,
        rgba(0,0,0,0.55) 100%);
    clip-path: polygon(
        0 var(--top-depth),
        100% 0,
        100% 100%,
        0 100%
    );
}

/* Winner-tier glass tint — warm gold layered on top of the cool
 * neutral glass. Higher saturation, golden edge. */
.leaders-slot--1st .leaders-glass__face {
    background:
        linear-gradient(180deg,
            rgba(255,215,90,0.32) 0%,
            rgba(255,175,40,0.18) 45%,
            rgba(120,75,15,0.10) 100%);
    border-color: rgba(255,225,140,0.45);
    border-top-color: rgba(255,240,180,0.65);
    box-shadow:
        inset 0 1px 0 rgba(255,240,180,0.55),
        inset 0 -8px 16px rgba(80,40,0,0.30),
        inset 6px 0 12px rgba(255,210,100,0.10);
}
.leaders-slot--1st .leaders-glass__top {
    background: linear-gradient(135deg,
        rgba(255,235,160,0.55) 0%,
        rgba(255,200,80,0.30) 60%,
        rgba(200,140,40,0.15) 100%);
    border-top-color: rgba(255,240,180,0.70);
}
.leaders-slot--1st .leaders-glass__side {
    background: linear-gradient(90deg,
        rgba(80,40,0,0.40) 0%,
        rgba(40,20,0,0.65) 100%);
}

/* Silver tint for 2nd place — cool platinum cast */
.leaders-slot--2nd .leaders-glass__face {
    background:
        linear-gradient(180deg,
            rgba(230,235,245,0.30) 0%,
            rgba(180,190,210,0.15) 45%,
            rgba(60,70,90,0.08) 100%);
    border-color: rgba(230,235,245,0.42);
    border-top-color: rgba(255,255,255,0.60);
}
.leaders-slot--2nd .leaders-glass__top {
    background: linear-gradient(135deg,
        rgba(255,255,255,0.50) 0%,
        rgba(210,215,230,0.30) 60%,
        rgba(140,150,170,0.15) 100%);
    border-top-color: rgba(255,255,255,0.65);
}

/* Bronze tint for 3rd place — warm copper cast */
.leaders-slot--3rd .leaders-glass__face {
    background:
        linear-gradient(180deg,
            rgba(220,140,80,0.28) 0%,
            rgba(180,100,40,0.15) 45%,
            rgba(80,40,10,0.08) 100%);
    border-color: rgba(230,160,100,0.42);
    border-top-color: rgba(255,200,150,0.60);
}
.leaders-slot--3rd .leaders-glass__top {
    background: linear-gradient(135deg,
        rgba(255,200,150,0.50) 0%,
        rgba(210,140,80,0.30) 60%,
        rgba(140,80,30,0.15) 100%);
    border-top-color: rgba(255,210,160,0.60);
}

/* Winner's avatar gets a subtle continuous bob after entry settles */
.leaders-slot--1st .leaders-slot__avatar {
    animation: leadersAvatarPop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) 1.10s forwards,
               leadersWinnerBob 3.6s ease-in-out 2.0s infinite;
}
@keyframes leadersWinnerBob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-3px); }
}

/* ── "Your place" row — sits above the list, follows page theme. ── */
.leaders-you-row {
    display: flex;
    align-items: center;
    padding: 12px 14px;
    margin: 0 0 10px;
    background: linear-gradient(135deg,
        rgba(10,132,255,0.10), rgba(10,132,255,0.04));
    border: 1px solid rgba(10,132,255,0.20);
    border-radius: var(--radius-medium);
}
.leaders-you-row__place {
    font-weight: 600;
    color: var(--text-secondary);
    font-size: 14px;
    margin-right: 14px;
    min-width: 22px;
    text-align: center;
}
.leaders-you-row__avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    margin-right: 10px;
    object-fit: cover;
    flex-shrink: 0;
    background: var(--card-bg);
}
.leaders-you-row__name {
    font-weight: 600;
    color: var(--text-primary);
    font-size: 14px;
    margin-right: 8px;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.leaders-you-row__metric {
    font-weight: 600;
    color: var(--accent-blue);
    font-size: 14px;
    white-space: nowrap;
}

/* ── List rows for places 4+ — dark rounded pills ── */
.leaders-list {
    display: flex;
    flex-direction: column;
    padding: 0 2px;
    padding-bottom: 50px;
}
.leaders-list__separator {
    width: 100%;
    height: 1px;
    background: var(--leaders-separator);
    margin-bottom: 10px;
}

.leaders-row {
    display: block;
    margin-bottom: 8px;
    opacity: 0;
    transform: translateY(8px);
    animation: leadersRowIn 0.32s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
@keyframes leadersRowIn {
    to { opacity: 1; transform: translateY(0); }
}
/* Stagger rows */
.leaders-row:nth-child(1)  { animation-delay: 0.40s; }
.leaders-row:nth-child(2)  { animation-delay: 0.44s; }
.leaders-row:nth-child(3)  { animation-delay: 0.48s; }
.leaders-row:nth-child(4)  { animation-delay: 0.52s; }
.leaders-row:nth-child(5)  { animation-delay: 0.56s; }
.leaders-row:nth-child(6)  { animation-delay: 0.60s; }
.leaders-row:nth-child(7)  { animation-delay: 0.64s; }
.leaders-row:nth-child(8)  { animation-delay: 0.68s; }
.leaders-row:nth-child(9)  { animation-delay: 0.72s; }
.leaders-row:nth-child(10) { animation-delay: 0.76s; }
.leaders-row:nth-child(n+11) { animation-delay: 0.80s; }

/* Row pill — self-contained. Place number sits inline on the left,
 * then avatar, name+metric, with the amount as the rightmost cell.
 * Uses card-bg so it flips with the theme. */
.leaders-row__pill {
    background: var(--leaders-pill-bg);
    padding: 8px 14px;
    border-radius: 32px;
    flex: 1;
    display: grid;
    grid-template-columns: 28px 36px 1fr auto;
    align-items: center;
    gap: 10px;
    min-width: 0;
    box-shadow: var(--shadow-small);
    border: 1px solid var(--border-color);
}
.leaders-row__place {
    font-size: 14px;
    font-weight: 700;
    color: var(--leaders-pill-muted);
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.leaders-row__avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    flex-shrink: 0;
    overflow: hidden;
    background: var(--overlay-1);
}
.leaders-row__avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
}
.leaders-row__avatar .leaders-avatar-fallback {
    width: 36px;
    height: 36px;
    font-size: 15px;
}
.leaders-row__info {
    display: flex;
    flex-direction: column;
    min-width: 0;
    gap: 2px;
}
.leaders-row__name {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--leaders-pill-text);
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.leaders-row__name a.tg-user-link {
    color: var(--leaders-pill-text);
    text-decoration: none;
}
.leaders-row__metric {
    font-size: 11px;
    font-weight: 500;
    color: var(--leaders-pill-muted);
    line-height: 1.2;
}
.leaders-row__amount {
    font-size: 14px;
    font-weight: 700;
    color: var(--leaders-pill-text);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.leaders-empty {
    text-align: center;
    padding: 60px 20px;
    color: var(--text-secondary);
    font-size: 14px;
}
.leaders-empty p { margin: 0; }

/* ═══════════════════════════════════════════════════════════════════
 * COMING-SOON SPLASH — pre-launch countdown screen
 * ─────────────────────────────────────────────────────────────────
 * Pure brand palette: blue + white on light, blue + black on dark.
 * Theme-aware via local CSS variables that flip on data-theme="dark".
 *
 * Layout (top → bottom):
 *   1. Trophy + title + subtitle
 *   2. "Launches in" small label
 *   3. Four glass digit cards (DD HH MM SS)
 *   4. Prize pool callout ($50,000)
 *   5. Three medal cards for places 1, 2, 3 (blue-tonal hierarchy)
 *   6. Tier rows for 4-10 / 11-100
 *   7. Winners total note
 *
 * Animations: clean ease-out fade-ups only, no overshoot bouncing.
 * Sparse ambient effects (one soft halo, four small sparkles).
 * ═══════════════════════════════════════════════════════════════════ */

/* Theme tokens for the splash. Default = light theme; dark theme
 * overrides below. Palette uses lighter sky-blue tones (--splash-
 * accent = #5AC8FA family) instead of the deeper iOS systemBlue, so
 * the splash reads as airy / soft rather than corporate. */
.leaders-page {
    --splash-bg:           linear-gradient(180deg, #eef6ff 0%, #d6e9ff 100%);
    --splash-border:       rgba(90,200,250,0.18);
    --splash-shadow:       0 24px 60px -28px rgba(20,80,160,0.20);
    --splash-text:         #0a0e1a;
    --splash-text-muted:   rgba(28,28,30,0.60);
    --splash-cap-text:     rgba(28,28,30,0.45);
    --splash-glass-bg:     rgba(255,255,255,0.78);
    --splash-glass-border: rgba(90,200,250,0.28);
    --splash-glass-shadow: 0 2px 12px rgba(20,80,160,0.10);
    --splash-halo:         radial-gradient(70% 60% at 50% 0%,
                              rgba(90,200,250,0.32), transparent 70%);
    --splash-sparkle:      #5AC8FA;
    /* Main brand accent — lighter sky blue */
    --splash-accent:       #5AC8FA;
    --splash-accent-deep:  #2BAEEC;   /* slightly deeper for readable numbers */
    --splash-accent-soft:  #91DCFF;
    --splash-accent-pale:  #d0eaff;
}
:root[data-theme="dark"] .leaders-page {
    --splash-bg:           linear-gradient(180deg, #102246 0%, #050a18 100%);
    --splash-border:       rgba(120,200,255,0.18);
    --splash-shadow:       0 24px 60px -20px rgba(0,0,0,0.65);
    --splash-text:         #ffffff;
    --splash-text-muted:   rgba(255,255,255,0.68);
    --splash-cap-text:     rgba(255,255,255,0.48);
    --splash-glass-bg:     rgba(120,200,255,0.10);
    --splash-glass-border: rgba(120,200,255,0.25);
    --splash-glass-shadow: 0 4px 14px rgba(0,30,80,0.45);
    --splash-halo:         radial-gradient(70% 60% at 50% 0%,
                              rgba(100,210,255,0.38), transparent 70%);
    --splash-sparkle:      #91DCFF;
    --splash-accent:       #64D2FF;
    --splash-accent-deep:  #5AC8FA;
    --splash-accent-soft:  #91DCFF;
    --splash-accent-pale:  #2e4d80;
}

.leaders-splash {
    position: relative;
    margin: 16px 0 24px;
    padding: 28px 18px 22px;
    background: var(--splash-bg);
    border-radius: 24px;
    overflow: hidden;
    box-shadow: var(--splash-shadow),
                inset 0 0 0 1px var(--splash-border);
    isolation: isolate;
    text-align: center;
    color: var(--splash-text);
}

/* Ambient background — single soft blue halo at the top + four
 * small twinkling sparkles. No rotating ring (kept subtle). */
.leaders-splash__bg {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}
.leaders-splash__rings { display: none; }
.leaders-splash__halo {
    position: absolute;
    inset: 0;
    background: var(--splash-halo);
    opacity: 0;
    animation: leadersSplashFade 0.7s ease-out forwards;
}
@keyframes leadersSplashFade {
    to { opacity: 1; }
}

.leaders-splash__sparkles { position: absolute; inset: 0; }
.leaders-splash__sparkles span {
    position: absolute;
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: var(--splash-sparkle);
    box-shadow: 0 0 8px currentColor;
    color: var(--splash-sparkle);
    opacity: 0;
    animation: leadersSparkle 3.6s ease-in-out infinite;
}
.leaders-splash__sparkles span:nth-child(1) { top: 14%; left: 14%; animation-delay: 0.6s; }
.leaders-splash__sparkles span:nth-child(2) { top: 22%; right: 16%; animation-delay: 1.9s; }
.leaders-splash__sparkles span:nth-child(3) { top: 58%; left: 8%;   animation-delay: 2.4s; }
.leaders-splash__sparkles span:nth-child(4) { top: 70%; right: 10%; animation-delay: 1.2s; }
/* Extra sparkles hidden to keep the screen calm */
.leaders-splash__sparkles span:nth-child(n+5) { display: none; }
@keyframes leadersSparkle {
    0%, 100% { opacity: 0; transform: scale(0.5); }
    50%      { opacity: 0.75; transform: scale(1); }
}

/* ── Hero: trophy + title stack ─────────────────────────────────── */
.leaders-splash__hero {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    margin-bottom: 22px;
}
.leaders-splash__trophy {
    width: 72px;
    height: 72px;
    filter: drop-shadow(0 0 22px rgba(0,122,255,0.45))
            drop-shadow(0 6px 14px rgba(0,40,120,0.30));
    opacity: 0;
    transform: translateY(-8px);
    animation: leadersTrophyIn 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards,
               leadersTrophyFloat 5s ease-in-out 0.6s infinite;
}
.leaders-splash__trophy svg { width: 100%; height: 100%; display: block; }
@keyframes leadersTrophyIn {
    to { opacity: 1; transform: translateY(0); }
}
@keyframes leadersTrophyFloat {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-4px); }
}

.leaders-splash__title-row {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    max-width: 320px;
}
.leaders-splash__title {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display',
                 'Inter', 'Segoe UI', system-ui, sans-serif;
    font-size: 23px;
    font-weight: 800;
    letter-spacing: -0.025em;
    line-height: 1.18;
    color: var(--splash-text);
    opacity: 0;
    transform: translateY(6px);
    animation: leadersSplashFadeUp 0.5s cubic-bezier(0.16, 1, 0.3, 1) 0.20s forwards;
}
.leaders-splash__subtitle {
    margin: 0;
    font-size: 14px;
    line-height: 1.45;
    color: var(--splash-text-muted);
    max-width: 300px;
    opacity: 0;
    transform: translateY(6px);
    animation: leadersSplashFadeUp 0.5s cubic-bezier(0.16, 1, 0.3, 1) 0.30s forwards;
}
@keyframes leadersSplashFadeUp {
    to { opacity: 1; transform: translateY(0); }
}

/* "Launches in" small caps label */
.leaders-splash__cd-label {
    position: relative;
    z-index: 1;
    margin: 0 0 12px;
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.18em;
    color: var(--splash-cap-text);
    opacity: 0;
    animation: leadersSplashFadeUp 0.4s ease-out 0.40s forwards;
}

/* ── Countdown timer — 4 wide glass cards ──────────────────────── */
.leaders-cd {
    position: relative;
    z-index: 1;
    display: flex;
    justify-content: center;
    gap: 8px;
    margin: 0 0 28px;
    opacity: 0;
    transform: translateY(6px);
    animation: leadersSplashFadeUp 0.5s cubic-bezier(0.16, 1, 0.3, 1) 0.48s forwards;
}
.leaders-cd__unit {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    flex: 1 1 0;
    max-width: 78px;
}
.leaders-cd__card {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1.1;
    min-height: 64px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1px;
    border-radius: 14px;
    background: var(--splash-glass-bg);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
            backdrop-filter: blur(14px) saturate(160%);
    border: 1px solid var(--splash-glass-border);
    box-shadow: var(--splash-glass-shadow),
                inset 0 1px 0 rgba(255,255,255,0.08);
    overflow: hidden;
    isolation: isolate;
}
.leaders-cd__card::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 8%;
    right: 8%;
    height: 1px;
    background: var(--splash-glass-border);
    z-index: 2;
    pointer-events: none;
}
.leaders-cd__num {
    font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display',
                 'Inter', 'Segoe UI', system-ui, sans-serif;
    font-size: 34px;
    font-weight: 800;
    line-height: 1;
    /* Slightly deeper than the base accent so the number stays
     * readable against the light glass card on white themes. */
    color: var(--splash-accent-deep);
    letter-spacing: -0.04em;
    font-variant-numeric: tabular-nums;
    position: relative;
    z-index: 3;
}
.leaders-cd__num--tick { animation: leadersCdTick 0.4s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes leadersCdTick {
    0%   { opacity: 0.4; transform: translateY(-4px); }
    100% { opacity: 1;   transform: translateY(0); }
}
.leaders-cd__cap {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--splash-cap-text);
}

/* ── Prize pool callout ────────────────────────────────────────── */
.leaders-prize-pool {
    position: relative;
    z-index: 1;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    margin: 0 auto 16px;
    padding: 14px 28px;
    background: var(--splash-glass-bg);
    border: 1px solid var(--splash-glass-border);
    border-radius: 20px;
    -webkit-backdrop-filter: blur(12px) saturate(160%);
            backdrop-filter: blur(12px) saturate(160%);
    box-shadow: var(--splash-glass-shadow);
    opacity: 0;
    transform: translateY(6px);
    animation: leadersSplashFadeUp 0.5s cubic-bezier(0.16, 1, 0.3, 1) 0.58s forwards;
}
.leaders-prize-pool__label {
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--splash-cap-text);
}
.leaders-prize-pool__amount {
    font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display',
                 'Inter', 'Segoe UI', system-ui, sans-serif;
    font-size: 30px;
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1;
    color: var(--splash-accent-deep);
    font-variant-numeric: tabular-nums;
}

/* ── Prize cards 1 / 2 / 3 — blue tonal hierarchy ────────────────
 * 1st = brand --splash-accent (deepest blue)
 * 2nd = --splash-accent-soft (cyan)
 * 3rd = --splash-accent-pale (light blue)
 * No gold / silver / bronze anywhere. */
.leaders-prize-grid {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 8px;
    margin: 0 0 14px;
}
.leaders-prize-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    padding: 14px 8px 12px;
    border-radius: 16px;
    background: var(--splash-glass-bg);
    border: 1px solid var(--splash-glass-border);
    -webkit-backdrop-filter: blur(10px) saturate(160%);
            backdrop-filter: blur(10px) saturate(160%);
    box-shadow: var(--splash-glass-shadow);
    overflow: hidden;
    opacity: 0;
    transform: translateY(6px);
    animation: leadersSplashFadeUp 0.45s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.leaders-prize-card:nth-child(1) { animation-delay: 0.66s; }
.leaders-prize-card:nth-child(2) { animation-delay: 0.74s; }
.leaders-prize-card:nth-child(3) { animation-delay: 0.82s; }

.leaders-prize-card__medal {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 800;
    line-height: 1;
    color: #ffffff;
    margin-bottom: 2px;
}
.leaders-prize-card__amount {
    font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display',
                 'Inter', 'Segoe UI', system-ui, sans-serif;
    font-size: 21px;
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--splash-text);
}
.leaders-prize-card__label {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--splash-cap-text);
}

/* 1st place — winner card: deeper sky-blue medal + stronger border/glow */
.leaders-prize-card--gold {
    border-color: var(--splash-accent-deep);
    box-shadow:
        0 4px 20px rgba(90,200,250,0.30),
        inset 0 1px 0 rgba(255,255,255,0.18);
}
.leaders-prize-card--gold .leaders-prize-card__medal {
    background: var(--splash-accent-deep);
    box-shadow: 0 0 16px rgba(90,200,250,0.55),
                inset 0 -2px 4px rgba(0,60,120,0.25);
}
.leaders-prize-card--gold .leaders-prize-card__amount { color: var(--splash-accent-deep); }

/* 2nd place — cyan medal */
.leaders-prize-card--silver .leaders-prize-card__medal {
    background: var(--splash-accent-soft);
    box-shadow: 0 0 10px rgba(90,200,250,0.40),
                inset 0 -2px 4px rgba(0,80,160,0.25);
}

/* 3rd place — pale blue medal */
.leaders-prize-card--bronze .leaders-prize-card__medal {
    background: var(--splash-accent-pale);
    box-shadow: 0 0 8px rgba(120,170,230,0.30),
                inset 0 -2px 4px rgba(40,80,140,0.20);
}

/* ═══════════════════════════════════════════════════════════════
 * FIRST-DEAL BONUS BLOCK — separate prominent CTA card
 * ─────────────────────────────────────────────────────────────
 * Highlights a SECONDARY pot ($5K) distributed equally among
 * everyone who closes at least one deal. Sits outside the main
 * 50K leaderboard pool — its job is to convert "haven't tried
 * yet" users by promising a guaranteed slice for participation.
 *
 * Visual: horizontal hero card with sparkle icon on the left and
 * amount + title + body + checkmark CTA on the right. Stronger
 * blue accent + shimmer sweep than the regular cards so it pops
 * without screaming.
 * ═══════════════════════════════════════════════════════════ */
.leaders-bonus {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 16px;
    margin: 0 0 14px;
    padding: 16px 18px;
    border-radius: 20px;
    background: linear-gradient(135deg,
        rgba(90,200,250,0.32) 0%,
        rgba(0,122,255,0.18)  55%,
        rgba(145,220,255,0.10) 100%);
    border: 1px solid var(--splash-accent);
    box-shadow:
        0 6px 22px rgba(90,200,250,0.30),
        inset 0 1px 0 rgba(255,255,255,0.20),
        inset 0 0 0 1px rgba(255,255,255,0.06);
    -webkit-backdrop-filter: blur(14px) saturate(180%);
            backdrop-filter: blur(14px) saturate(180%);
    overflow: hidden;
    isolation: isolate;
    text-align: left;
    opacity: 0;
    transform: translateY(8px);
    animation: leadersSplashFadeUp 0.55s cubic-bezier(0.16, 1, 0.3, 1) 0.86s forwards;
}

/* Soft pulsing halo behind the icon — draws the eye */
.leaders-bonus__halo {
    position: absolute;
    width: 140px;
    height: 140px;
    top: 50%;
    left: 0;
    transform: translate(-30%, -50%);
    background: radial-gradient(circle, rgba(90,200,250,0.35), transparent 65%);
    filter: blur(8px);
    pointer-events: none;
    z-index: 0;
    animation: leadersBonusHalo 3.5s ease-in-out infinite;
}
@keyframes leadersBonusHalo {
    0%, 100% { opacity: 0.7; transform: translate(-30%, -50%) scale(1); }
    50%      { opacity: 1;   transform: translate(-30%, -50%) scale(1.08); }
}

/* Diagonal shine that sweeps across every few seconds */
.leaders-bonus__shine {
    position: absolute;
    inset: 0;
    background: linear-gradient(110deg,
        transparent 35%,
        rgba(255,255,255,0.20) 48%,
        rgba(255,255,255,0.35) 50%,
        rgba(255,255,255,0.20) 52%,
        transparent 65%);
    transform: translateX(-100%);
    animation: leadersBonusShine 5s ease-in-out 2s infinite;
    pointer-events: none;
    z-index: 1;
    mix-blend-mode: overlay;
}
@keyframes leadersBonusShine {
    0%   { transform: translateX(-100%); }
    50%  { transform: translateX(120%); }
    100% { transform: translateX(120%); }
}

/* Sparkle icon on the left — big, glowing */
.leaders-bonus__icon {
    position: relative;
    z-index: 2;
    flex-shrink: 0;
    width: 56px;
    height: 56px;
    border-radius: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    background:
        radial-gradient(circle at 30% 25%, rgba(255,255,255,0.30), transparent 60%),
        linear-gradient(135deg, var(--splash-accent), var(--splash-accent-deep));
    box-shadow:
        0 0 18px rgba(90,200,250,0.55),
        inset 0 1px 0 rgba(255,255,255,0.30),
        inset 0 -2px 4px rgba(0,60,120,0.25);
    animation: leadersBonusIconPulse 2.4s ease-in-out infinite;
}
.leaders-bonus__icon svg {
    width: 38px;
    height: 38px;
    filter: drop-shadow(0 1px 2px rgba(0,40,120,0.40));
}
@keyframes leadersBonusIconPulse {
    0%, 100% { transform: scale(1)   rotate(0deg); }
    50%      { transform: scale(1.06) rotate(2deg); }
}

/* Content column on the right */
.leaders-bonus__content {
    position: relative;
    z-index: 2;
    min-width: 0;
    flex: 1;
}
.leaders-bonus__top {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 4px;
}
.leaders-bonus__amount {
    font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display',
                 'Inter', 'Segoe UI', system-ui, sans-serif;
    font-size: 26px;
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1;
    color: var(--splash-text);
    font-variant-numeric: tabular-nums;
    text-shadow: 0 1px 8px rgba(90,200,250,0.30);
}
.leaders-bonus__badge {
    display: inline-flex;
    align-items: center;
    padding: 3px 9px;
    font-size: 9.5px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: #fff;
    background: var(--splash-accent-deep);
    border-radius: 99px;
    box-shadow: 0 0 8px rgba(90,200,250,0.45);
    line-height: 1;
    white-space: nowrap;
}
.leaders-bonus__title {
    margin: 0 0 4px;
    font-size: 14px;
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -0.01em;
    color: var(--splash-text);
}
.leaders-bonus__body {
    margin: 0 0 6px;
    font-size: 12.5px;
    line-height: 1.4;
    color: var(--splash-text-muted);
}

/* Small reassurance tag at the bottom — "Anyone can win" */
.leaders-bonus__cta {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px 4px 7px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: -0.005em;
    color: var(--splash-accent-deep);
    background: rgba(255,255,255,0.65);
    border: 1px solid var(--splash-glass-border);
    border-radius: 99px;
    line-height: 1;
}
.leaders-bonus__cta svg { width: 11px; height: 11px; }

/* Dark theme: the white-ish CTA tag needs less luminance */
:root[data-theme="dark"] .leaders-bonus__cta {
    background: rgba(120,200,255,0.20);
    color: #fff;
}

/* Narrow screens — keep the icon big but allow content to wrap */
@media (max-width: 360px) {
    .leaders-bonus { gap: 12px; padding: 14px 14px; }
    .leaders-bonus__icon { width: 48px; height: 48px; }
    .leaders-bonus__icon svg { width: 32px; height: 32px; }
    .leaders-bonus__amount { font-size: 24px; }
}

/* ── Shared tier rows ──────────────────────────────────────────── */
.leaders-tiers {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0 0 10px;
}
.leaders-tier-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    background: var(--splash-glass-bg);
    border: 1px solid var(--splash-glass-border);
    border-radius: 12px;
    -webkit-backdrop-filter: blur(8px);
            backdrop-filter: blur(8px);
    box-shadow: var(--splash-glass-shadow);
    opacity: 0;
    transform: translateY(6px);
    animation: leadersSplashFadeUp 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.leaders-tier-row:nth-child(1) { animation-delay: 0.90s; }
.leaders-tier-row:nth-child(2) { animation-delay: 0.98s; }
.leaders-tier-row__range {
    font-size: 13px;
    font-weight: 700;
    color: var(--splash-text);
    letter-spacing: -0.01em;
    min-width: 56px;
    text-align: left;
}
.leaders-tier-row__range::before {
    content: "#";
    color: var(--splash-text-muted);
    margin-right: 1px;
    font-weight: 600;
}
.leaders-tier-row__sep {
    flex: 1;
    height: 1px;
    background: var(--splash-glass-border);
}
.leaders-tier-row__amount {
    font-size: 14px;
    font-weight: 800;
    color: var(--splash-accent-deep);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
}

/* Random-tier variant: replaces the plain separator with a small
 * "Розыгрыш" pill carrying a dice-dots icon. Lets the user see at a
 * glance that this tier is a lottery, not a ranking. */
.leaders-tier-row--random {
    background:
        linear-gradient(135deg,
            rgba(90,200,250,0.18) 0%,
            rgba(145,220,255,0.06) 100%);
    border-color: var(--splash-accent-deep);
}
.leaders-tier-row__badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin: 0 8px;
    padding: 4px 10px 4px 8px;
    font-size: 10.5px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.10em;
    color: #fff;
    background: var(--splash-accent-deep);
    border-radius: 99px;
    box-shadow: 0 0 10px rgba(90,200,250,0.50),
                inset 0 -1px 2px rgba(0,60,120,0.30);
    line-height: 1;
    white-space: nowrap;
}
.leaders-tier-row__badge svg {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
}

/* ── Raffle callout — explains that places 51-100 are random ──── */
.leaders-raffle {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 12px 0 18px;
    padding: 14px 16px;
    border-radius: 16px;
    text-align: left;
    background: linear-gradient(135deg,
        rgba(90,200,250,0.16) 0%,
        rgba(145,220,255,0.04) 100%);
    border: 1px dashed var(--splash-accent-deep);
    box-shadow: var(--splash-glass-shadow);
    -webkit-backdrop-filter: blur(8px);
            backdrop-filter: blur(8px);
    opacity: 0;
    transform: translateY(6px);
    animation: leadersSplashFadeUp 0.5s cubic-bezier(0.16, 1, 0.3, 1) 1.10s forwards;
}
.leaders-raffle__icon {
    flex-shrink: 0;
    width: 42px;
    height: 42px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--splash-glass-bg);
    border: 1px solid var(--splash-glass-border);
    color: var(--splash-accent-deep);
    /* Gentle wobble — sells the "random / dice rolling" feel */
    animation: leadersRaffleShake 5s ease-in-out 2s infinite;
}
.leaders-raffle__icon svg { width: 22px; height: 22px; }
@keyframes leadersRaffleShake {
    0%, 88%, 100% { transform: rotate(0deg); }
    91% { transform: rotate(-6deg); }
    94% { transform: rotate(6deg); }
    97% { transform: rotate(-3deg); }
}
.leaders-raffle__text { min-width: 0; }
.leaders-raffle__title {
    margin: 0 0 2px;
    font-size: 13.5px;
    font-weight: 800;
    letter-spacing: -0.01em;
    color: var(--splash-text);
    line-height: 1.3;
}
.leaders-raffle__body {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.4;
    color: var(--splash-text-muted);
}

/* Total winners footnote */
.leaders-winners-note {
    position: relative;
    z-index: 1;
    margin: 6px auto 18px;
    font-size: 12px;
    line-height: 1.4;
    color: var(--splash-text-muted);
    max-width: 280px;
    opacity: 0;
    animation: leadersSplashFadeUp 0.4s ease-out 1.06s forwards;
}

/* ── Participants count chip — social proof under the title ──────── */
.leaders-participants {
    position: relative;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: -4px auto 18px;
    padding: 7px 14px 7px 11px;
    background: var(--splash-glass-bg);
    border: 1px solid var(--splash-glass-border);
    border-radius: 99px;
    -webkit-backdrop-filter: blur(10px) saturate(160%);
            backdrop-filter: blur(10px) saturate(160%);
    box-shadow: var(--splash-glass-shadow);
    color: var(--splash-text-muted);
    font-size: 12.5px;
    line-height: 1.2;
    opacity: 0;
    transform: translateY(6px);
    animation: leadersSplashFadeUp 0.5s cubic-bezier(0.16, 1, 0.3, 1) 0.38s forwards;
}
.leaders-participants__icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    color: var(--splash-accent-deep);
}
.leaders-participants__text {
    font-weight: 500;
    color: var(--splash-text-muted);
}
.leaders-participants__text b {
    color: var(--splash-text);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
    margin: 0 1px;
}

/* ── "How it works" 3-step section ─────────────────────────────── */
.leaders-how {
    position: relative;
    z-index: 1;
    margin: 0 0 18px;
    text-align: left;
}
.leaders-how__title {
    margin: 0 0 10px;
    font-size: 15px;
    font-weight: 800;
    letter-spacing: -0.01em;
    color: var(--splash-text);
    text-align: center;
    opacity: 0;
    animation: leadersSplashFadeUp 0.4s ease-out 1.14s forwards;
}
.leaders-how__steps {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.leaders-how__step {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 14px;
    background: var(--splash-glass-bg);
    border: 1px solid var(--splash-glass-border);
    border-radius: 14px;
    -webkit-backdrop-filter: blur(8px);
            backdrop-filter: blur(8px);
    box-shadow: var(--splash-glass-shadow);
    opacity: 0;
    transform: translateY(6px);
    animation: leadersSplashFadeUp 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.leaders-how__step:nth-child(1) { animation-delay: 1.22s; }
.leaders-how__step:nth-child(2) { animation-delay: 1.30s; }
.leaders-how__step:nth-child(3) { animation-delay: 1.38s; }
.leaders-how__num {
    flex-shrink: 0;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--splash-accent);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 800;
    line-height: 1;
    box-shadow: 0 0 10px rgba(90,200,250,0.35),
                inset 0 -2px 3px rgba(0,60,120,0.20);
    margin-top: 1px;
}
.leaders-how__text {
    min-width: 0;
}
.leaders-how__step-title {
    margin: 0 0 2px;
    font-size: 13.5px;
    font-weight: 700;
    color: var(--splash-text);
    letter-spacing: -0.01em;
    line-height: 1.3;
}
.leaders-how__step-body {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.4;
    color: var(--splash-text-muted);
}

/* ── Reminder callout — "Make deals now, you might win" ──────────── */
.leaders-reminder {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 0;
    padding: 14px 16px;
    border-radius: 16px;
    text-align: left;
    /* Slightly stronger blue tint than the regular glass — calls
     * attention without being noisy. */
    background: linear-gradient(135deg,
        rgba(90,200,250,0.18) 0%,
        rgba(145,220,255,0.08) 100%);
    border: 1px solid var(--splash-accent-deep);
    box-shadow: 0 4px 18px rgba(90,200,250,0.18),
                inset 0 1px 0 rgba(255,255,255,0.10);
    -webkit-backdrop-filter: blur(8px);
            backdrop-filter: blur(8px);
    opacity: 0;
    transform: translateY(6px);
    animation: leadersSplashFadeUp 0.5s cubic-bezier(0.16, 1, 0.3, 1) 1.50s forwards;
}
.leaders-reminder__icon {
    flex-shrink: 0;
    width: 42px;
    height: 42px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--splash-accent-deep);
    color: #fff;
    box-shadow: 0 0 14px rgba(90,200,250,0.45),
                inset 0 -2px 4px rgba(0,60,120,0.25);
}
.leaders-reminder__icon svg { width: 22px; height: 22px; }
.leaders-reminder__text {
    min-width: 0;
}
.leaders-reminder__title {
    margin: 0 0 2px;
    font-size: 14px;
    font-weight: 800;
    letter-spacing: -0.01em;
    color: var(--splash-text);
}
.leaders-reminder__body {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.4;
    color: var(--splash-text-muted);
}

/* Reduce motion — drop all entrance + ambient animations */
@media (prefers-reduced-motion: reduce) {
    .leaders-stage__halo,
    .leaders-stage__sparkles span,
    .leaders-slot__block,
    .leaders-slot__avatar,
    .leaders-medal-wrapper,
    .leaders-slot__name,
    .leaders-slot__amount,
    .leaders-row,
    .leaders-splash__halo,
    .leaders-splash__sparkles span,
    .leaders-splash__trophy,
    .leaders-splash__title,
    .leaders-splash__subtitle,
    .leaders-splash__cd-label,
    .leaders-cd,
    .leaders-cd__num--tick,
    .leaders-prize-pool,
    .leaders-prize-card,
    .leaders-tier-row,
    .leaders-winners-note,
    .leaders-participants,
    .leaders-how__title,
    .leaders-how__step,
    .leaders-reminder,
    .leaders-raffle,
    .leaders-raffle__icon,
    .leaders-bonus,
    .leaders-bonus__halo,
    .leaders-bonus__shine,
    .leaders-bonus__icon {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
    }
}

/* Skeleton while data loads */
.leaders-skeleton { padding: 16px 0; }
.leaders-skel-podium {
    display: flex;
    justify-content: center;
    align-items: flex-end;
    gap: 14px;
    padding: 60px 14px 18px;
    margin: 16px 0 24px;
    background: var(--leaders-showcase-bg);
    border-radius: 24px;
    box-shadow: var(--shadow-medium);
    min-height: 260px;
}
/* Each skel column shows an avatar circle on top of a block. */
.leaders-skel-col {
    flex: 1 1 0;
    max-width: 36%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
}
.leaders-skel-circle {
    border-radius: 50%;
    background: rgba(255,255,255,0.08);
    animation: leadersSkelPulse 1.3s ease-in-out infinite;
}
.leaders-skel-circle.big   { width: 88px; height: 88px; }
.leaders-skel-circle.small { width: 68px; height: 68px; }
.leaders-skel-block {
    width: 100%;
    max-width: 130px;
    background: rgba(255,255,255,0.06);
    border-radius: 8px 8px 4px 4px;
    animation: leadersSkelPulse 1.3s ease-in-out infinite;
}
.leaders-skel-block.tall   { height: 150px; }
.leaders-skel-block.medium { height: 110px; }
.leaders-skel-block.short  { height: 80px;  }
.leaders-skel-list { display: flex; flex-direction: column; gap: 8px; padding: 0 2px; }
.leaders-skel-row {
    height: 56px;
    background: var(--overlay-1);
    border-radius: 32px;
    animation: leadersSkelPulse 1.3s ease-in-out infinite;
}
@keyframes leadersSkelPulse {
    0%, 100% { opacity: 0.55; }
    50%      { opacity: 0.85; }
}

/* Polished "Доступно: N CURRENCY" callout that sits at the top of
 * every withdraw modal. Earlier this was just an .info-card with
 * inline plain text ("Доступно: 32.33 ⭐") — readable but visually
 * unremarkable. The variant below promotes the balance to a proper
 * stat card: tiny uppercase label, bold amount, currency badge on
 * the right. Same component used by all 4 withdraw flows (TON,
 * STARS, USDT, fiat) so they look consistent.
 *
 * Markup pattern:
 *   <div class="info-card balance-callout">
 *     <div class="balance-callout__text">
 *       <p class="balance-callout__label">Доступно</p>
 *       <p class="balance-callout__amount">32.33</p>
 *     </div>
 *     <div class="balance-callout__badge">⭐</div>
 *   </div>
 */
.info-card.balance-callout {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 14px 18px;
    background: linear-gradient(135deg,
        rgba(10,132,255,0.07) 0%,
        rgba(73,223,100,0.05) 100%);
    border: 1px solid rgba(10,132,255,0.12);
}
.balance-callout__text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.balance-callout__label {
    margin: 0;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.balance-callout__amount {
    margin: 0;
    font-size: 22px;
    font-weight: 700;
    color: var(--text-primary);
    letter-spacing: -0.02em;
    line-height: 1.15;
    /* Long numbers (e.g. "1 250 000 ⭐" in formatted form) stay on one
     * line and ellipse rather than wrapping under the badge. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.balance-callout__badge {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    height: 44px;
    padding: 0 12px;
    border-radius: 14px;
    background: rgba(255,255,255,0.7);
    color: var(--accent-blue);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.02em;
    box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
:root[data-theme="dark"] .balance-callout__badge {
    background: rgba(255,255,255,0.08);
    color: #fff;
}

.card-title {
    font-size: 18px;
    font-weight: 600;
    margin-bottom: 16px;
    color: var(--text-primary);
}

/* ==================== ПРОФИЛЬ ==================== */

.profile-header {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 20px 0 30px;
}

.profile-avatar {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--accent-blue), var(--accent-light-blue));
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 32px;
    font-weight: 600;
    margin-bottom: 12px;
    box-shadow: 0 4px 20px rgba(10, 132, 255, 0.4);
    position: relative;
    overflow: hidden;
    color: #fff;
}
/* <img> sits on top of the initial letter once loaded; transparent
   until JS gives it a src + the 'loaded' class. Errors (broken TG CDN
   link) leave the img invisible so the initial letter shows through.
   ⚠ z-index matters: BOTH img and initial create stacking context
   (img via position:absolute, initial via position:relative+z-index).
   Without an explicit z-index on the img, the initial — which comes
   LATER in DOM order — paints ON TOP of the loaded image. That's the
   "вопросительный знак поверх аватарки" bug. Pin img to z-index:2
   and initial to z-index:1 so the image always wins when loaded. */
.profile-avatar img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity .15s ease;
    z-index: 2;
}
.profile-avatar img.loaded {
    opacity: 1;
}
.profile-avatar #profile-avatar-initial {
    position: relative;
    z-index: 1;
    line-height: 1;
}

.profile-name {
    font-size: 24px;
    font-weight: 700;
    margin-bottom: 4px;
    /* Long names (e.g. "Александр Александрович" or a 24-char latin
       handle) used to push the layout out and break the rounded
       header card. Constrain to the viewport with a comfortable
       inset and let the browser clip with an ellipsis. */
    max-width: min(92vw, 360px);
    padding: 0 8px;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.profile-username {
    font-size: 15px;
    color: var(--text-secondary);
    max-width: min(92vw, 360px);
    padding: 0 8px;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Заголовок карточки с переключателем */
.card-header-with-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
    gap: 12px;
}

/* iOS-style переключатель */
.toggle-switch {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    user-select: none;
}

.toggle-switch input[type="checkbox"] {
    display: none;
}

.toggle-slider {
    position: relative;
    width: 51px;
    height: 31px;
    background: var(--overlay-2);
    border: 1px solid var(--border-color);
    border-radius: 31px;
    transition: background 0.3s ease, border-color 0.3s ease;
    flex-shrink: 0;
    /* Inset so the track is clearly visible against white card. */
    box-shadow: inset 0 1px 2px rgba(0,0,0,0.06);
}

.toggle-slider::before {
    content: '';
    position: absolute;
    width: 25px;
    height: 25px;
    border-radius: 50%;
    background: #FFFFFF;
    top: 2px;
    left: 2px;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow:
        0 1px 1px rgba(0,0,0,0.10),
        0 3px 8px rgba(0,0,0,0.18);
}

.toggle-switch input[type="checkbox"]:checked + .toggle-slider {
    background: var(--accent-blue);
}

.toggle-switch input[type="checkbox"]:checked + .toggle-slider::before {
    transform: translateX(20px);
}

.toggle-label {
    font-size: 13px;
    color: var(--text-secondary);
    white-space: nowrap;
}

/* Балансы */
.balances-list {
    display: grid;
    gap: 12px;
}

/* Balance row sits inside an info-card (.card-bg). Using --secondary-bg
   on light theme made the row identical to the card it's nested in
   (both #FFFFFF) so taps "blended with the background". An overlay tint
   keeps the row subtly distinct on both themes; press feedback is just
   a brief scale + slightly darker overlay, not opacity. */
.balance-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    background: var(--overlay-1);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-small);
    transition: transform 0.15s ease, background 0.15s ease;
    gap: 12px;
    /* Hardware-accelerate the press animation so it doesn't twitch on
       layout reflow when the modal opens. */
    will-change: transform;
}
.balance-item.hidden { display: none; }
.balance-item:active {
    transform: scale(0.985);
    background: var(--overlay-2);
}
@media (hover: hover) {
    .balance-item:hover { background: var(--overlay-2); }
}

.balance-currency {
    display: flex;
    align-items: center;
    gap: 10px;
    /* `flex: 1 1 auto` (was `0 0 auto`) lets the wrapper share the
       available row width with `.balance-amount` and shrink when the
       sum is fat. Combined with `min-width: 0` on both sides, ellipsis
       on `.currency-name` actually triggers — `0 0 auto` would have
       kept it at intrinsic width and pushed the balance off-screen. */
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
}

/* === Currency icons (unified) ===
   All currency icons render at the same size for a given context.
   Use FunpayIcons.currencyIcon(code, size) from icons.js to inject. */
.currency-icon,
.currency-icon-img,
.currency-icon-svg,
.cur-icon {
    width: 40px;
    height: 40px;
    min-width: 40px;
    min-height: 40px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    flex-shrink: 0;
}

.currency-icon-svg svg,
.cur-icon {
    display: block;
}

/* small variant for chips/inline labels — was 9px which made text invisible.
   Restored to a readable size and aligned with .tx-currency-icon. */
.currency-icon.small,
.currency-icon-img.small,
.currency-icon-svg.small,
.cur-icon.cur-icon-sm {
    width: 24px;
    height: 24px;
    min-width: 24px;
    min-height: 24px;
}

/* Иконки валют в транзакциях */
.tx-currency-icon {
    width: 24px;
    height: 24px;
    min-width: 24px;
    min-height: 24px;
    border-radius: 50%;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: var(--text-primary);
}

.tx-currency-icon svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* Цвета для конкретных валют — берутся из CSS-переменных, чтобы
   тёмная тема могла поднять контраст. */
.balance-item[data-currency="TON"] .tx-currency-icon,
.transaction-item[data-currency="TON"] .tx-currency-icon {
    color: var(--color-ton);
}

.balance-item[data-currency="USDT"] .tx-currency-icon,
.transaction-item[data-currency="USDT"] .tx-currency-icon {
    color: var(--color-usdt);
}

.balance-item[data-currency="STARS"] .tx-currency-icon,
.transaction-item[data-currency="STARS"] .tx-currency-icon {
    color: var(--color-stars);
}

.balance-item[data-currency="RUB"] .tx-currency-icon,
.transaction-item[data-currency="RUB"] .tx-currency-icon {
    color: #0039A6;
}

.balance-item[data-currency="USD"] .tx-currency-icon,
.transaction-item[data-currency="USD"] .tx-currency-icon {
    color: #85BB65;
}

.balance-item[data-currency="EUR"] .tx-currency-icon,
.transaction-item[data-currency="EUR"] .tx-currency-icon {
    color: #0051D5;
}

.balance-item[data-currency="GBP"] .tx-currency-icon,
.transaction-item[data-currency="GBP"] .tx-currency-icon {
    color: #C8102E;
}

.balance-item[data-currency="CNY"] .tx-currency-icon,
.transaction-item[data-currency="CNY"] .tx-currency-icon {
    color: #DE2910;
}

.balance-item[data-currency="JPY"] .tx-currency-icon,
.transaction-item[data-currency="JPY"] .tx-currency-icon {
    color: #BC002D;
}

.tx-currency-icon img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Currency / amount labels stay on one line (codes like "USDT" and
   numerics never look right wrapped) but we add ellipsis + min-width:0
   so a long localised currency name OR a fat balance like
   "1234567.89 USDT" can shrink the row instead of pushing siblings off
   the right edge of the screen. */
.currency-name {
    font-size: 15px;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.balance-amount {
    font-size: 15px;
    font-weight: 600;
    color: var(--accent-blue);
    white-space: nowrap;
    text-align: right;
    margin-left: auto;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* Статистика */
.stats-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
}

.stat-item {
    display: flex;
    flex-direction: column;
    padding: 16px;
    background: var(--overlay-1);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-small);
    text-align: center;
    /* Same outline + tiny shadow as the balance row so the stat tiles
       stand off the card surface on light theme. */
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}

.stat-item.stat-highlight {
    grid-column: 1 / -1;
    background: linear-gradient(135deg, rgba(10, 132, 255, 0.20), rgba(100, 210, 255, 0.10));
    border-color: rgba(10, 132, 255, 0.45);
    box-shadow: 0 2px 8px rgba(10,132,255,0.18);
}

.stat-label {
    font-size: 13px;
    color: var(--text-secondary);
    margin-bottom: 8px;
}

.stat-value {
    font-size: 22px;
    font-weight: 700;
    color: var(--text-primary);
}

.stat-highlight .stat-value {
    color: var(--accent-blue);
}

/* Курсы валют */
.rates-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.rate-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    background: var(--overlay-1);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-small);
    gap: 12px;
    /* Same lift as balance/stat tiles so the rate rows are visible on
       a white card surface. */
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}

.rate-pair {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1;
}

.rate-info {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex: 1;
    gap: 12px;
    /* min-width: 0 is the magic value that lets a flex child actually
       shrink below its content's intrinsic width — without it,
       text-overflow: ellipsis on the children doesn't trigger because
       the parent stays at intrinsic size and overflows the row. */
    min-width: 0;
}

.rate-currency {
    font-size: 15px;
    font-weight: 500;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    /* Allow the rate row to truncate the currency code if the rate
       value next to it pushes layout out of bounds (rare, but happens
       with very large rates like JPY where the value plus the
       currency code crosses the viewport on 320px screens). */
}

.rate-icons {
    display: flex;
    align-items: center;
}

.rate-icon {
    width: 28px;
    height: 28px;
    min-width: 28px;
    min-height: 28px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 600;
    background: var(--card-bg);
    flex-shrink: 0;
}

.rate-icon-img {
    width: 28px !important;
    height: 28px !important;
    min-width: 28px !important;
    min-height: 28px !important;
    max-width: 28px !important;
    max-height: 28px !important;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    display: block;
}

.rate-icon + .rate-icon {
    margin-left: -10px;
}

.rate-name {
    font-size: 15px;
    font-weight: 500;
}

.rate-value {
    font-size: 16px;
    font-weight: 600;
    color: var(--accent-blue);
    white-space: nowrap;
    text-align: right;
}

/* ==================== КНОПКИ ==================== */

.action-buttons {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 24px;
}

.btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 16px 24px;
    border: none;
    border-radius: var(--radius-medium);
    font-size: 17px;
    font-weight: 600;
    cursor: pointer;
    /* Earlier this was `transition: all 0.2s ease` which animated
       transform, box-shadow, color, padding — everything. When the
       JS toggled `.active` while the user's tap was still triggering
       `:active` (scale(.96)), the simultaneous transform + bg-color
       transitions clashed → "залития голубым мигает и дергает" (blue
       fill flashing/jerking on STARS recipient switch). Scoping the
       transition to only the colour properties keeps the press feel
       crisp while the colour swap stays smooth. */
    transition: background-color 0.18s ease,
                border-color 0.18s ease,
                color 0.18s ease,
                box-shadow 0.18s ease;
    -webkit-tap-highlight-color: transparent;
}

.btn:active {
    transform: scale(0.96);
    /* The press transform is INSTANT — separate from the colour
       transition above so the two never compete on the same axis. */
    transition: transform 0.08s ease, background-color 0.18s ease,
                border-color 0.18s ease, color 0.18s ease;
}

.btn-primary {
    background: var(--accent-blue);
    color: white;
    box-shadow: 0 4px 16px rgba(10, 132, 255, 0.4);
}

.btn-primary:hover {
    background: var(--accent-light-blue);
}

.btn-secondary {
    /* Use a TINTED surface (not pure card-bg) so the button is
       visibly different from the modal/card behind it. In the
       light theme card-bg, secondary-bg AND the surrounding card
       are ALL #FFFFFF, so a button using `--card-bg` literally
       blended into the background and looked like text floating
       on white — exactly the "кнопки сливаются" bug. The new
       `--btn-secondary-bg` resolves to #F2F2F7 on light (matches
       iOS HIG secondary surface) and a slightly raised mid-gray
       on dark; either way the button is clearly a button. */
    background: var(--btn-secondary-bg, #F2F2F7);
    color: var(--text-primary);
    border: 1px solid var(--btn-secondary-border, rgba(0,0,0,0.18));
}

/* Desktop-only hover. On touch devices the OS reports hover briefly
   on tap, which can flash a colour change just before .active lands —
   suppressing it eliminates the "blink" on STARS recipient switch. */
@media (hover: hover) and (pointer: fine) {
    .btn-secondary:hover {
        background: var(--btn-secondary-bg-hover, #E5E5EA);
    }
}

.btn-secondary.active {
    background: var(--accent-blue);
    color: white;
    border-color: var(--accent-blue);
    /* Matching shadow so the colour swap doesn't include a
       "shadow appears" jump on top of the bg change. */
    box-shadow: 0 4px 16px rgba(10, 132, 255, 0.25);
}

.btn svg {
    flex-shrink: 0;
}

/* Иконочная кнопка для копирования */
.btn-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--text-primary);
    cursor: pointer;
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.btn-icon:hover {
    background: var(--secondary-bg);
    transform: scale(1.05);
}

.btn-icon:active {
    transform: scale(0.95);
}

/* ==================== АДАПТИВНОСТЬ ==================== */

@media (min-width: 768px) {
    .tabbar-wrapper {
        max-width: 500px;
        margin: 0 auto;
    }
    
    .page-content {
        max-width: 600px;
        margin: 0 auto;
    }
}

/* ==================== АНИМАЦИИ ==================== */

@keyframes slideUp {
    from {
        transform: translateY(100%);
        opacity: 0;
    }
    to {
        transform: translateY(0);
        opacity: 1;
    }
}

@keyframes slideDownIn {
    /* unused — kept for future top-dropdown animations. Renamed to avoid
       colliding with the modal-overlay close keyframe of the same name. */
    from {
        transform: translateY(-100%);
        opacity: 0;
    }
    to {
        transform: translateY(0);
        opacity: 1;
    }
}

/* ==================== МОДАЛЬНЫЕ ОКНА ==================== */

.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    /* Above the order-detail-overlay (3500) and transactions-overlay
       (3000) so a modal opened from inside one of those overlays sits
       on top — otherwise the share/confirm modal appeared behind and
       seemed "below the screen". */
    z-index: 4000;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    opacity: 0;
    animation: fadeIn 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
    will-change: opacity;
}

.modal-overlay.closing {
    animation: fadeOut 0.15s cubic-bezier(0.4, 0, 1, 1) forwards;
}

/* The bottom-sheet container.
   Two patterns coexist in the JS:
     A. modals.js: <overlay><modal><modal-content>...</></></>
     B. dashboard.js: <overlay><modal-content>...</></>
   The styles below apply to whichever element is the *direct* child of
   the overlay so both patterns render identically. */
.modal,
.modal-overlay > .modal-content {
    width: 100%;
    max-height: 90vh;
    background: var(--secondary-bg);
    border-radius: 24px 24px 0 0;
    padding: 24px 20px calc(var(--safe-area-bottom) + 20px);
    transform: translateY(100%);
    animation: slideUp 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
    overflow-y: auto;
    will-change: transform;
    box-sizing: border-box;
}

.modal-overlay.closing .modal,
.modal-overlay.closing > .modal-content {
    animation: slideDown 0.2s cubic-bezier(0.4, 0, 1, 1) forwards;
}

/* ── Wide-screen modal layout ───────────────────────────────────────
 * Without this block, the bottom-sheet pattern (width:100% + rounded
 * top corners only) stretched edge-to-edge on iPad and landscape
 * phones, leaving acres of whitespace beside the form. The result
 * looked like a thin form floating in a giant white panel (see the
 * "Вывести Stars" screenshot from a 1200-pixel-wide device).
 *
 * On screens ≥ 560px we:
 *   - cap the modal at 480px wide (comfortable form size on tablet)
 *   - centre it vertically as well as horizontally
 *   - round all four corners (no longer a bottom-sheet visually)
 *   - swap the slide-up-from-bottom animation for a soft scale-fade
 *     so it doesn't try to fly in from off-screen on a centred sheet
 */
@media (min-width: 560px) {
    .modal-overlay {
        align-items: center;
        padding: 24px;
    }
    .modal,
    .modal-overlay > .modal-content {
        max-width: 480px;
        width: 100%;
        max-height: calc(100vh - 48px);
        border-radius: 24px;
        animation: modalScaleIn 0.22s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
        transform: scale(0.96);
    }
    @keyframes modalScaleIn {
        from { opacity: 0; transform: scale(0.96) translateY(8px); }
        to   { opacity: 1; transform: scale(1)    translateY(0); }
    }
}

/* In pattern A the inner .modal-content fades up; in pattern B it IS the
   sheet, no extra animation. */
.modal > .modal-content {
    transform: translateY(20px);
    opacity: 0;
    animation: slideUpFade 0.25s cubic-bezier(0.4, 0, 0.2, 1) 0.05s forwards;
    will-change: transform, opacity;
}

.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 24px;
}

.modal-title {
    font-size: 22px;
    font-weight: 700;
}

.modal-close,
.btn-close {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--overlay-1);
    border: 1.5px solid var(--overlay-2);
    color: var(--text-secondary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    flex-shrink: 0;
}

.modal-close:hover,
.btn-close:hover {
    background: var(--overlay-2);
    border-color: rgba(255, 255, 255, 0.2);
    transform: scale(1.05);
}

.modal-close:active,
.btn-close:active {
    transform: scale(0.95);
}

.modal-close svg,
.btn-close svg {
    width: 18px;
    height: 18px;
    stroke-width: 2.5;
}

/* ==================== ОРДЕРА ==================== */

.orders-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.order-card {
    background: var(--card-bg);
    border-radius: var(--radius-medium);
    padding: 16px;
    cursor: pointer;
    transition: all 0.2s ease;
    border: 1px solid transparent;
}

.order-card:active {
    transform: scale(0.98);
    border-color: var(--accent-blue);
}

.order-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}

.order-tag {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-secondary);
}

.order-status {
    padding: 4px 12px;
    border-radius: 12px;
    font-size: 12px;
    font-weight: 600;
}

.status-wait_payment {
    background: rgba(255, 159, 10, 0.2);
    color: var(--color-warning);
}

.status-paid {
    background: rgba(10, 132, 255, 0.2);
    color: var(--accent-blue);
}

.status-completed {
    background: rgba(48, 209, 88, 0.2);
    color: #30D158;
}

.status-cancelled {
    background: rgba(255, 69, 58, 0.2);
    color: #FF453A;
}

.order-amount {
    font-size: 22px;
    font-weight: 700;
    margin-bottom: 8px;
    color: var(--accent-blue);
}

.order-description {
    font-size: 14px;
    color: var(--text-secondary);
    line-height: 1.4;
}

.empty-state,
.loading,
.error {
    text-align: center;
    padding: 40px 20px;
    color: var(--text-secondary);
    font-size: 16px;
}

/* === Skeleton loaders ===
   Used as initial markup so a page never appears empty while data loads. */
@keyframes skel-shimmer {
    0%   { background-position: -200% 0; }
    100% { background-position:  200% 0; }
}
.skeleton-line,
.skeleton-block {
    border-radius: 8px;
    background: linear-gradient(90deg,
        rgba(255,255,255,.04) 0%,
        rgba(255,255,255,.10) 40%,
        rgba(255,255,255,.04) 80%);
    background-size: 200% 100%;
    animation: skel-shimmer 1.4s linear infinite;
}
.skeleton-line { height: 14px; margin: 6px 0; }
.skeleton-block { width: 100%; }
.skeleton-h-44 { height: 44px; }
.skeleton-h-72 { height: 72px; }
.skeleton-w-30 { width: 30%; }
.skeleton-w-50 { width: 50%; }
.skeleton-w-70 { width: 70%; }
.skeleton-card {
    /* same paddings/style as .info-card so swap is invisible */
    background: var(--card-bg);
    border-radius: var(--radius-medium);
    padding: 16px;
    margin-bottom: 12px;
}
.skeleton-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 0;
}
.skeleton-circle-40 {
    width: 40px; height: 40px; border-radius: 50%;
    background: linear-gradient(90deg,
        rgba(255,255,255,.04) 0%,
        rgba(255,255,255,.10) 40%,
        rgba(255,255,255,.04) 80%);
    background-size: 200% 100%;
    animation: skel-shimmer 1.4s linear infinite;
    flex-shrink: 0;
}

/* ==================== РЕКВИЗИТЫ ==================== */

.wallet-section {
    margin-bottom: 24px;
}

.wallet-section h3 {
    font-size: 20px;
    font-weight: 600;
    margin-bottom: 16px;
}

.requisite-item {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px 0;
    border-bottom: 1px solid var(--border-color);
}

.requisite-item:last-of-type {
    border-bottom: none;
}

.requisite-label {
    font-size: 13px;
    color: var(--text-secondary);
}

.requisite-value {
    font-size: 16px;
    font-weight: 500;
    color: var(--text-primary);
    word-break: break-all;
}



/* (Old duplicate of .modal-close/.btn-close was here; rules already exist
   at line ~828 with proper border styles. Removed.) */
.modal-body {
    padding-top: 4px;
}

/* Utility classes referenced by inline templates throughout the JS — the
   audit caught that none of these had rules, leaving widths / spacing
   unstyled in deposit/withdraw modals. */
.btn-block { width: 100%; }
.btn-sm    { padding: 8px 16px; font-size: 14px; min-height: 36px; }
.form-text {
    display: block;
    font-size: 12px;
    color: var(--text-secondary);
    margin-top: 6px;
    line-height: 1.4;
}
/* Cancel/Confirm pair at the bottom of every modal. Replaces the dozen
   inline `style="flex:1; margin-top:8px"` snippets — kept compatible with
   them by also matching that pattern. */
.modal-actions,
.modal-footer {
    display: flex;
    gap: 8px;
    margin-top: 20px;
}
.modal-actions > .btn,
.modal-footer  > .btn {
    flex: 1;
}

/* ========== ФОРМЫ ========== */
.form {
    width: 100%;
}

.form-step {
    animation: fadeIn 0.3s ease;
}

.form-step.hidden {
    display: none;
}

.form-step-title {
    font-size: 18px;
    font-weight: 600;
    color: var(--text-primary);
    margin: 0 0 20px 0;
    text-align: center;
}

.back-btn {
    display: flex;
    align-items: center;
    gap: 8px;
    background: none;
    border: none;
    color: var(--accent-blue);
    font-size: 16px;
    cursor: pointer;
    padding: 8px 0;
    margin-bottom: 16px;
    transition: opacity 0.2s ease;
}

.back-btn:hover {
    opacity: 0.7;
}

.button-group {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.choice-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 16px 24px;
    background: var(--overlay-1);
    border: 2px solid var(--overlay-2);
    border-radius: var(--border-radius);
    color: var(--text-primary);
    font-size: 16px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
}

.choice-btn:hover {
    background: var(--overlay-2);
    border-color: var(--accent-blue);
    transform: translateY(-2px);
}

.choice-btn svg {
    width: 24px;
    height: 24px;
}

.currency-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
}

.currency-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 20px;
    background: var(--overlay-1);
    border: 2px solid var(--overlay-2);
    border-radius: var(--border-radius);
    color: var(--text-primary);
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
}

.currency-btn:hover {
    background: var(--overlay-2);
    border-color: var(--accent-blue);
    transform: translateY(-2px);
}

/* (Removed: legacy .currency-icon override that pasted a blue gradient on
   top of every icon, including the SVG-circle ones from icons.js. The
   unified .currency-icon rule at the top of this file already sets size
   + flex centering and the SVG carries its own brand-coloured fill.) */

.form-group {
    margin-bottom: 20px;
    position: relative;
}

.form-label {
    display: block;
    font-size: 14px;
    color: var(--text-secondary);
    margin-bottom: 8px;
}

/* Bare <label> inside a .form-group (the pattern every withdraw /
 * deposit / deal-create modal uses in dashboard.js) had NO CSS rule
 * attached — labels rendered with browser defaults: thin weight,
 * no spacing under them, slightly off-baseline relative to the input.
 * The user described it as "тонкие шрифты и нет отступа" on the
 * Stars withdraw modal screenshot.
 *
 * This rule promotes bare labels to the proper form-label treatment
 * automatically: medium weight, breathing margin, primary text colour
 * so they read as section headings rather than tiny grey strings. */
.form-group > label {
    display: block;
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 8px;
    letter-spacing: -0.005em;
    line-height: 1.3;
}

.form-input,
.form-select,
.form-textarea,
.form-control,
input[type="text"],
input[type="number"],
input[type="email"],
select {
    width: 100%;
    padding: 14px 16px;
    background: var(--secondary-bg);
    border: 1.5px solid var(--border-color);
    border-radius: 12px;
    color: var(--text-primary);
    font-size: 16px;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
    transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    -webkit-appearance: none;
    appearance: none;
}

.form-input:focus,
.form-select:focus,
.form-textarea:focus,
.form-control:focus,
input[type="text"]:focus,
input[type="number"]:focus,
input[type="email"]:focus,
select:focus {
    outline: none;
    border-color: var(--accent-blue);
    background: var(--card-bg);
    box-shadow: 0 0 0 4px rgba(10, 132, 255, 0.1);
}

.form-input::placeholder,
.form-control::placeholder,
input::placeholder {
    color: var(--text-tertiary);
    opacity: 0.6;
}

.form-textarea {
    resize: vertical;
    min-height: 100px;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
}

.input-currency {
    position: absolute;
    right: 16px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-secondary);
    font-size: 14px;
    font-weight: 500;
}

.info-box {
    padding: 16px;
    background: rgba(10, 132, 255, 0.1);
    border-left: 4px solid var(--accent-blue);
    border-radius: var(--border-radius);
    margin-bottom: 20px;
}

.info-box.warning {
    background: rgba(255, 159, 10, 0.1);
    border-left-color: var(--color-warning);
}

.info-box p {
    margin: 0;
    color: var(--text-secondary);
    font-size: 14px;
    line-height: 1.5;
}

/* ========== ORDER SUMMARY ========== */
.order-summary {
    background: var(--overlay-1);
    border-radius: var(--border-radius);
    padding: 16px;
    margin-bottom: 20px;
}

.summary-item {
    display: flex;
    justify-content: space-between;
    padding: 12px 0;
    border-bottom: 1px solid var(--overlay-2);
}

.summary-item:last-child {
    border-bottom: none;
}

.summary-item span:first-child {
    color: var(--text-secondary);
}

.summary-item span:last-child {
    color: var(--text-primary);
    font-weight: 500;
}

/* ========== ORDER DETAILS ========== */
.order-details {
    color: var(--text-primary);
}

.detail-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 24px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--overlay-2);
}

.order-tag {
    font-size: 18px;
    font-weight: 600;
    color: var(--text-primary);
}

.detail-section {
    margin-bottom: 24px;
}

.detail-section h4 {
    font-size: 14px;
    color: var(--text-secondary);
    margin: 0 0 12px 0;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.detail-item {
    display: flex;
    justify-content: space-between;
    padding: 12px 0;
    border-bottom: 1px solid var(--overlay-1);
}

.detail-item:last-child {
    border-bottom: none;
}

.detail-label {
    color: var(--text-secondary);
    font-size: 14px;
}

.detail-value {
    color: var(--text-primary);
    font-weight: 500;
}

.detail-value.highlight {
    color: var(--accent-blue);
    font-weight: 600;
}

.detail-description {
    color: var(--text-primary);
    line-height: 1.6;
    margin: 0;
}

.detail-requisites {
    display: flex;
    flex-direction: column;
    gap: 8px;
    background: var(--overlay-1);
    padding: 16px;
    border-radius: var(--border-radius);
}

.requisite-label {
    color: var(--text-secondary);
    font-size: 12px;
}

.requisite-value {
    color: var(--text-primary);
    font-size: 14px;
    font-family: monospace;
    word-break: break-all;
}

.detail-actions {
    display: flex;
    gap: 12px;
    margin-top: 24px;
}

/* ========== NOTIFICATIONS ========== */
.notification {
    position: fixed;
    /* Anchor BELOW the Telegram WebApp chrome / iOS notch / Dynamic
       Island — earlier we used a flat 100px, which on iPhone 14 Pro+
       and recent Androids tucked the toast UNDER the title bar so
       users never saw it. `safe-area-top` plus a comfortable 16px
       breathing space keeps it visible on every device. */
    top: calc(env(safe-area-inset-top, 0px) + var(--content-safe-top, 60px) + 12px);
    left: 50%;
    transform: translateX(-50%) translateY(-100px);
    background: var(--card-bg);
    color: var(--text-primary);
    padding: 16px 24px;
    border-radius: 12px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
    z-index: 10000;
    opacity: 0;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    max-width: 90%;
    text-align: center;
}

.notification.show {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

.notification-success {
    border-left: 4px solid var(--color-success);
}

.notification-error {
    border-left: 4px solid var(--color-danger);
}

.notification-warning {
    border-left: 4px solid var(--color-warning);
}

.notification-info {
    border-left: 4px solid var(--accent-blue);
}

/* ========== TON CONNECT ========== */
/* ========== TON CONNECT ========== */
#ton-wallet-container {
    width: 100%;
}

.connected-wallet {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: var(--secondary-bg);
    border-radius: 10px;
    gap: 12px;
}

.wallet-info {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 4px;
    width: 100%;
}

.wallet-icon {
    width: 40px;
    height: 40px;
    min-width: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    background: linear-gradient(135deg, var(--color-ton), var(--color-ton-dark));
    border-radius: 50%;
}

.wallet-details {
    display: flex;
    flex-direction: column;
    gap: 4px;
    align-items: center;
}

.wallet-label {
    font-size: 13px;
    color: var(--text-secondary);
    text-align: center;
}

.wallet-address {
    font-size: 15px;
    font-weight: 600;
    color: var(--text-primary);
    font-family: 'Courier New', monospace;
    text-align: center;
}

.btn-disconnect {
    width: 100%;
    padding: 10px 16px;
    background: rgba(255, 59, 48, 0.15);
    color: var(--color-danger);
    border: none;
    border-radius: 10px;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s ease;
}

.btn-disconnect:hover {
    background: rgba(255, 59, 48, 0.25);
}

.btn-disconnect:active {
    transform: scale(0.96);
}

/* ========== TON CONNECT КНОПКА ========== */
#ton-connect-button {
    width: 100% !important;
}

#ton-connect-button button {
    width: 100% !important;
    height: 44px !important;
    border-radius: 10px !important;
    font-size: 15px !important;
    font-weight: 600 !important;
    background: #0A84FF !important;
    color: white !important;
    border: none !important;
    cursor: pointer !important;
    transition: all 0.2s ease !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}

#ton-connect-button button:hover {
    opacity: 0.85 !important;
}

#ton-connect-button button:active {
    transform: scale(0.96) !important;
}

/* ========== РЕДАКТИРОВАНИЕ РЕКВИЗИТОВ ========== */
.requisite-group {
    margin-bottom: 14px;
    padding: 14px 16px;
    background: var(--overlay-1);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius);
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}
.requisite-group:last-child { margin-bottom: 0; }

.requisite-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}

.requisite-label {
    font-size: 14px;
    color: var(--text-secondary);
    font-weight: 500;
}

.requisite-value {
    font-size: 16px;
    color: var(--text-primary);
    word-break: break-all;
    font-family: monospace;
}

.requisite-value.warning {
    color: var(--color-warning);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.btn-icon {
    width: 40px;
    height: 40px;
    min-width: 40px;
    min-height: 40px;
    border-radius: 50%;
    background: rgba(10, 132, 255, 0.15);
    border: none;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s ease;
    color: var(--accent-blue);
    flex-shrink: 0;
}

.btn-icon:hover {
    background: rgba(10, 132, 255, 0.25);
    transform: scale(1.1);
}

.btn-icon svg {
    width: 20px;
    height: 20px;
}

.form-hint {
    margin-top: 8px;
    font-size: 12px;
    color: var(--text-secondary);
}

.info-box ol {
    margin: 10px 0;
    padding-left: 20px;
    color: var(--text-primary);
}

.info-box ol li {
    margin: 6px 0;
    font-size: 14px;
}

/* История транзакций */
.transactions-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.transaction-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px;
    background: var(--card-bg);
    border-radius: 12px;
    border: 1px solid var(--border-color);
    transition: all 0.2s ease;
}

.transaction-item:active {
    transform: scale(0.98);
    opacity: 0.8;
}

.tx-icon-wrapper {
    position: relative;
    flex-shrink: 0;
}

/* Glass-style direction badge — translucent blur circle, no border, with
   the arrow icon on top. Reads as a stack of stained glass coins.
   Per-direction colour is applied via CSS var below so the same rule
   covers credit/debit/refund. */
.tx-arrow {
    --tx-tint: 110, 110, 120;
    position: absolute;
    bottom: -4px;
    right: -4px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--tx-tint), 0.55);
    backdrop-filter: blur(8px) saturate(150%);
    -webkit-backdrop-filter: blur(8px) saturate(150%);
    box-shadow:
        inset 0 0 0 1px rgba(255,255,255,0.10),
        0 1px 2px rgba(0,0,0,0.10);
    color: #fff;
}

.tx-arrow svg {
    width: 12px;
    height: 12px;
    display: block;
}

/* Tints set the glass colour via the --tx-tint CSS variable so the
   single .tx-arrow rule above renders all variants. */
.tx-deposit    .tx-arrow,
.tx-arrow.tx-deposit    { --tx-tint:  32,160, 80; }   /* green */
.tx-withdrawal .tx-arrow,
.tx-arrow.tx-withdrawal { --tx-tint: 200, 40, 40; }   /* red   */
.tx-deal-in    .tx-arrow,
.tx-arrow.tx-deal-in    { --tx-tint:  30,110,210; }   /* blue  */
.tx-deal-out   .tx-arrow,
.tx-arrow.tx-deal-out   { --tx-tint: 220,140, 40; }   /* amber */

.tx-details {
    flex: 1;
    min-width: 0;
}

.tx-type {
    font-size: 15px;
    font-weight: 500;
    color: var(--text-primary);
    margin-bottom: 4px;
    display: flex;
    align-items: center;
    gap: 8px;
}

.tx-date {
    font-size: 13px;
    color: var(--text-secondary);
    margin-bottom: 2px;
}

.tx-hash {
    font-size: 11px;
    color: var(--text-tertiary);
    font-family: 'SF Mono', 'Monaco', 'Courier New', monospace;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tx-partner {
    font-size: 12px;
    color: var(--accent-blue);
    margin-top: 2px;
}

.tx-status {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
}

.tx-status-pending {
    background: rgba(255, 149, 0, 0.15);
    color: var(--color-warning);
}

.tx-status-completed {
    background: rgba(52, 199, 89, 0.15);
    color: var(--color-success);
}

.tx-status-failed {
    background: rgba(255, 59, 48, 0.15);
    color: var(--color-danger);
}

.tx-amount {
    font-size: 16px;
    font-weight: 600;
    white-space: nowrap;
}

.tx-amount.tx-deposit {
    color: var(--color-success);
}

.tx-amount.tx-withdrawal {
    color: var(--color-danger);
}

.tx-amount.tx-deal-in {
    color: var(--color-info);
}

.tx-amount.tx-deal-out {
    color: #FF9500;
}

.btn-back {
    width: 36px;
    height: 36px;
    background: rgba(10, 132, 255, 0.1);
    border: 1.5px solid rgba(10, 132, 255, 0.2);
    border-radius: 12px;
    padding: 0;
    margin-right: 12px;
    cursor: pointer;
    color: var(--accent-blue);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    flex-shrink: 0;
}

.btn-back:hover {
    background: rgba(10, 132, 255, 0.15);
    border-color: rgba(10, 132, 255, 0.3);
    transform: translateX(-2px);
}

.btn-back:active {
    transform: translateX(-2px) scale(0.95);
}

.btn-back svg {
    width: 20px;
    height: 20px;
    stroke-width: 2.5;
}

/* Выбор языка */
.language-modal .modal-content {
    max-width: 400px;
}

.language-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 60vh;
    overflow-y: auto;
}

.language-item {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    padding: 20px 24px;
    background: var(--card-bg);
    border-radius: 12px;
    border: 2px solid var(--border-color);
    cursor: pointer;
    transition: all 0.2s ease;
    min-height: 60px;
    font-size: 17px;
    width: 100%;
}

.language-item:hover {
    background: rgba(44, 44, 46, 0.9);
    border-color: rgba(10, 132, 255, 0.3);
}

.language-item:active {
    transform: scale(0.98);
    background: rgba(10, 132, 255, 0.15);
}

.language-item.active {
    border-color: #0A84FF;
    background: rgba(10, 132, 255, 0.15);
    box-shadow: 0 0 0 1px rgba(10, 132, 255, 0.2);
}

.language-name-centered {
    font-size: 18px;
    font-weight: 500;
    color: var(--text-primary);
    text-align: center;
}

.language-check {
    position: absolute;
    right: 20px;
    color: #0A84FF;
}

.language-flag {
    font-size: 32px;
    line-height: 1;
    flex-shrink: 0;
}

.language-name {
    font-size: 18px;
    font-weight: 500;
    color: var(--text-primary);
    flex: 1;
}

.language-icon {
    transition: transform 0.3s ease;
}

#language-btn:active .language-icon {
    transform: rotate(180deg);
}

/* TonConnect UI поверх всех модалов */
tc-root,
[class*="ton-connect"],
[class*="tonconnect"] {
    z-index: 999999 !important;
}

tc-root > div,
[class*="ton-connect"] > div,
[class*="tonconnect"] > div {
    z-index: 999999 !important;
}

/* Закругления для всех элементов TonConnect */
tc-root *,
[class*="ton-connect"] *,
[class*="tonconnect"] * {
    border-radius: 12px !important;
}

tc-root button,
[class*="ton-connect"] button,
[class*="tonconnect"] button {
    border-radius: 12px !important;
}

tc-root [role="dialog"],
tc-root [class*="modal"],
[class*="ton-connect"] [role="dialog"],
[class*="ton-connect"] [class*="modal"] {
    border-radius: 16px !important;
}

/* Скрываем ВСЕ уведомления TonConnect */
tc-root [class*="notification"],
tc-root [class*="toast"],
tc-root [class*="snackbar"],
tc-root [class*="alert"],
tc-root [class*="message"],
[class*="ton-connect-notification"],
[class*="tonconnect-notification"],
[class*="tc-notification"],
div[style*="position: fixed"][style*="z-index"] > div[class*="notification"],
div[style*="position: fixed"][style*="z-index"] > div[class*="toast"] {
    display: none !important;
    visibility: hidden !important;
    opacity: 0 !important;
}

/* Модальное окно транзакций */
.transactions-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--primary-bg);
    z-index: 3000;
    opacity: 0;
    transform: translateX(100%);
    transition: opacity 0.3s ease, transform 0.3s ease;
}

.transactions-overlay.active {
    opacity: 1;
    transform: translateX(0);
}

.transactions-overlay .page {
    height: 100%;
    overflow-y: auto;
    /* Mirror the exact same safe-area treatment as #page-container so the
       transactions screen looks like every other page. There's no tabbar
       on this overlay, so we drop --tabbar-height from the bottom inset. */
    padding-top:    calc(var(--content-safe-top, 0px) + var(--safe-area-top, 0px) + 32px);
    padding-bottom: calc(var(--safe-area-bottom, 0px) + 16px);
    padding-left:   var(--safe-area-left, 0px);
    padding-right:  var(--safe-area-right, 0px);
}

/* === Theme toggle ===
   Floating pill in the top-right of the profile page. Sun on the left,
   moon on the right, sliding circle indicator. Safe-area aware so it
   never collides with the iOS status bar / Telegram chrome. */
.theme-toggle {
    position: fixed;
    top: calc(var(--content-safe-top, 0px) + var(--safe-area-top, 0px) + 14px);
    right: calc(var(--safe-area-right, 0px) + 14px);
    z-index: 200;
    display: inline-flex;
    align-items: center;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    padding: 4px;
    gap: 0;
    cursor: pointer;
    user-select: none;
    transition: background 0.2s ease, border-color 0.2s ease;
    box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
.theme-toggle__track {
    position: relative;
    width: 60px;
    height: 28px;
    border-radius: 999px;
    background: var(--overlay-1);
}
.theme-toggle__thumb {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--accent-blue);
    box-shadow:
        0 2px 6px rgba(10,132,255,0.45),
        inset 0 1px 0 rgba(255,255,255,0.3);
    transition: transform 0.32s cubic-bezier(0.34, 1.34, 0.5, 1), background 0.2s ease;
    display: flex;
    align-items: center;
    justify-content: center;
}
.theme-toggle__thumb svg { width: 14px; height: 14px; color: #fff; }
.theme-toggle__sun, .theme-toggle__moon {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-secondary);
    width: 14px;
    height: 14px;
    pointer-events: none;
}
.theme-toggle__sun  { left: 7px; }
.theme-toggle__moon { right: 7px; }

:root[data-theme="dark"] .theme-toggle__thumb {
    transform: translateX(32px);
}

/* Hide the toggle on every page except profile — it's mounted globally
   for safe-area positioning, but conceptually a profile-page setting. */
.theme-toggle.hidden { display: none; }

/* === Touch fix ===
   On no-hover (touch-only) devices the :hover state can stick after a tap
   and the button stays in its bright "pressed" look until the user taps
   somewhere else — exactly the bug the user reported. We re-assert the
   non-hover values for these elements when hover isn't real, so :hover
   only paints on actual mouse devices.

   :focus is also auto-cleared visually: we keep it only for keyboard
   navigation via :focus-visible. */
@media (hover: none) {
    .btn-primary:hover    { background: var(--accent-blue); }
    /* Two fixes packed into one selector:
     *   1. `:not(.active)` — without this, when a .btn-secondary is in
     *      its .active state (blue bg + white text), the touch-tap
     *      briefly triggers :hover, this rule wins by specificity
     *      ordering, the bg flashes to var(--card-bg)=#FFFFFF on light
     *      theme, and the white text becomes invisible (only the blue
     *      border remained → user-reported "пустая кнопка Другому" on
     *      Stars withdraw). The active rule must STAY in charge while
     *      .active is set.
     *   2. Fallback target changed from var(--card-bg) → var(--btn-
     *      secondary-bg). On the light theme card-bg is pure white,
     *      same as the modal underneath, so an inactive secondary
     *      button briefly flashed invisible on tap too. The tinted
     *      btn-secondary-bg (#F2F2F7) keeps the button shape visible
     *      throughout the tap. */
    .btn-secondary:not(.active):hover  { background: var(--btn-secondary-bg, var(--card-bg)); }
    .btn-icon:hover       { background: var(--card-bg); transform: none; }
    .modal-close:hover,
    .btn-close:hover      { background: var(--overlay-1); }
    .back-btn:hover       { background: transparent; }
    .choice-btn:hover     { background: var(--overlay-1); border-color: var(--overlay-2); }
    .currency-btn:hover   { background: var(--overlay-1); border-color: var(--overlay-2); transform: none; }
    .btn-disconnect:hover { background: var(--card-bg); }
    .order-card:hover,
    .balance-item:hover   { background: var(--card-bg); }
    /* tabbar buttons too — hover stuck after tap was making the previous
       tab still look "selected" momentarily. */
    .tab-button:hover     { color: inherit; }
}

/* Focus ring only when focused via keyboard, not after a mouse/tap click. */
button:focus,
.btn:focus,
.tab-button:focus {
    outline: none;
}
button:focus-visible,
.btn:focus-visible,
.tab-button:focus-visible {
    outline: 2px solid var(--accent-blue);
    outline-offset: 2px;
}

/* === Segmented control (To Telegram / To Wallet) ===
   Two-button switch with a sliding pill background. The pill's transform
   is driven by the parent's `data-active="0|1"` attribute so the JS only
   has to set one flag to trigger the animation. */
.seg-control {
    position: relative;
    display: flex;
    background: var(--card-bg);
    border-radius: 14px;
    padding: 4px;
    margin-bottom: 8px;
    user-select: none;
}
.seg-pill {
    position: absolute;
    top: 4px;
    bottom: 4px;
    left: 4px;
    width: calc(50% - 4px);
    background: linear-gradient(180deg, #2A93FF 0%, #0A84FF 100%);
    border-radius: 11px;
    box-shadow:
        0 4px 14px rgba(10,132,255,0.45),
        inset 0 1px 0 rgba(255,255,255,0.3);
    transition: transform 0.4s cubic-bezier(0.34, 1.34, 0.5, 1);
    pointer-events: none;
    z-index: 0;
}
.seg-control[data-active="1"] .seg-pill {
    transform: translateX(100%);
}
.seg-btn {
    flex: 1;
    position: relative;
    z-index: 1;
    background: transparent;
    border: none;
    padding: 11px 8px;
    color: var(--text-secondary);
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    transition: color 0.25s ease;
}
.seg-btn svg { transition: transform 0.3s ease; }
.seg-control[data-active="0"] .seg-btn:nth-of-type(1),
.seg-control[data-active="1"] .seg-btn:nth-of-type(2) {
    color: #fff;
}
.seg-control[data-active="0"] .seg-btn:nth-of-type(1) svg,
.seg-control[data-active="1"] .seg-btn:nth-of-type(2) svg {
    transform: scale(1.05);
}

.seg-hint {
    font-size: 12.5px;
    color: var(--text-secondary);
    line-height: 1.45;
    margin: 0 4px 14px;
}

/* Pane fade — invisible flicker-free swap when toggling segments. */
.seg-pane { animation: seg-fade 0.3s ease both; }
@keyframes seg-fade {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* USDT network selector — chip strip with active fill + fee subtitle. */
.net-strip {
    display: flex;
    gap: 8px;
    margin-bottom: 6px;
}
.net-chip {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 10px 8px;
    background: var(--overlay-1);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    color: var(--text-primary);
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
}
.net-chip:active { transform: scale(0.97); }
.net-chip.active {
    background: var(--accent-blue);
    border-color: var(--accent-blue);
    color: #fff;
}
.net-chip .net-name { font-size: 13px; font-weight: 700; letter-spacing: -0.1px; }
.net-chip .net-fee  { font-size: 10.5px; opacity: 0.75; }

/* Recipient self/other quick toggle inside the Telegram-mode pane. */
.recip-toggle {
    display: flex;
    gap: 6px;
    background: var(--overlay-1);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: 4px;
}
.recip-btn {
    flex: 1;
    padding: 9px 10px;
    background: transparent;
    border: none;
    border-radius: 7px;
    color: var(--text-secondary);
    font-family: inherit;
    font-size: 13.5px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease;
}
.recip-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.recip-btn.active {
    background: var(--accent-blue);
    color: #fff;
    box-shadow: 0 2px 8px rgba(10,132,255,0.35);
}

/* Multi-step form: helper text shown above the description input */
.form-step-help {
    background: rgba(10,132,255,0.06);
    border: 1px solid rgba(10,132,255,0.18);
    border-radius: 12px;
    padding: 12px 14px;
    margin-bottom: 14px;
    color: var(--text-secondary);
    font-size: 13px;
    line-height: 1.5;
}
.form-step-help p { margin: 0 0 8px; }
.form-step-help p:last-child { margin-bottom: 0; }
.form-step-help b { color: var(--text-primary); }
.form-step-help code,
.form-step-help pre {
    background: var(--overlay-1);
    padding: 2px 6px;
    border-radius: 4px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px;
    color: var(--accent-light-blue, #5DC0FF);
}
.form-step-help pre {
    display: block;
    padding: 8px 10px;
    margin: 6px 0;
    overflow-x: auto;
    white-space: pre;
    line-height: 1.6;
}

/* === Order detail overlay ===
   Slides up over the dashboard, mirrors transactions overlay layout. */
.order-detail-overlay {
    position: fixed;
    inset: 0;
    background: var(--primary-bg);
    z-index: 3500;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.25s ease, transform 0.25s ease;
}
.order-detail-overlay.active {
    opacity: 1;
    transform: translateY(0);
}
.order-detail-page {
    height: 100%;
    overflow-y: auto;
    /* Scroll isolation — when the user reaches the top/bottom of this
     * scroller, the touch must NOT bubble up to the deals list under
     * the overlay. Without this, the page beneath silently scrolled
     * (especially noticeable after a real-time status update shortened
     * the visible content: with little left to scroll inside the deal,
     * the next swipe handed control to the background page).
     *   - overscroll-behavior: contain — Chromium/Firefox stop chaining
     *   - touch-action: pan-y          — sideways gestures don't get
     *                                    intercepted as horizontal scroll
     *   - -webkit-overflow-scrolling   — keep iOS momentum smooth
     * iOS Safari additionally needs a JS body-lock (see _lockBodyScroll
     * in dashboard.js) because overscroll-behavior alone doesn't stop
     * the rubber-band from reaching the document body. */
    overscroll-behavior: contain;
    touch-action: pan-y;
    -webkit-overflow-scrolling: touch;
    padding-top:    calc(var(--content-safe-top, 0px) + var(--safe-area-top, 0px) + 32px);
    padding-bottom: calc(var(--safe-area-bottom, 0px) + 16px);
    padding-left:   var(--safe-area-left, 0px);
    padding-right:  var(--safe-area-right, 0px);
}
/* When ANY full-screen overlay locks the document, freeze the body so
 * the page underneath can't be scrolled through the overlay. We save
 * the scroll offset to `top: -Ypx` and restore it on unlock — without
 * this the user's place in the deals list gets lost when they close
 * the overlay. */
body.body-scroll-locked {
    position: fixed;
    left: 0;
    right: 0;
    width: 100%;
    overflow: hidden;
    overscroll-behavior: none;
}

/* TonConnect renders an iframe-button into #ton-connect-button. Clamp it
   to the parent width so it doesn't drift to the screen edge on phones,
   and centre any internal floating elements. */
#ton-connect-button {
    width: 100%;
    display: flex;
    justify-content: center;
    min-height: 48px;
}
#ton-connect-button > * {
    width: 100% !important;
    max-width: 100% !important;
    box-sizing: border-box;
}
/* TonConnect's portal-rendered modal — anchor it inside the viewport. */
#tc-widget-root,
[id^="tc-widget"] {
    z-index: 5000 !important;
}

/* Loading skeleton shown WHILE the TON Connect SDK is being fetched
   so the user has visible feedback instead of an empty wallet card. */
.ton-connect-skel {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 48px;
    background: linear-gradient(110deg,
                                rgba(127,127,127,0.10) 30%,
                                rgba(127,127,127,0.20) 50%,
                                rgba(127,127,127,0.10) 70%);
    background-size: 200% 100%;
    animation: ton-connect-shimmer 1.4s ease-in-out infinite;
    border-radius: 12px;
    gap: 10px;
    color: var(--text-secondary);
    font-size: 14px;
    font-weight: 500;
}
@keyframes ton-connect-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}
.ton-connect-skel__bar {
    width: 18px;
    height: 18px;
    border: 2px solid var(--text-secondary);
    border-top-color: transparent;
    border-radius: 50%;
    animation: ton-connect-spin 0.9s linear infinite;
    opacity: 0.7;
}
@keyframes ton-connect-spin {
    to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
    .ton-connect-skel { animation: none; }
    .ton-connect-skel__bar { animation: none; }
}

/* Retry view when SDK fetch fails — clear message + big retry CTA. */
.ton-connect-failed {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 12px 8px;
    width: 100%;
}
.ton-connect-failed__msg {
    color: var(--text-secondary);
    font-size: 14px;
    text-align: center;
}
.ton-connect-failed__retry {
    width: 100%;
}

/* Custom Connect button that replaces the SDK's iframe button. We
   own this element so it never disappears on tab re-render — the
   previous iframe-based approach lost its DOM anchor on the second
   visit to the wallets page. */
.ton-connect-btn {
    width: 100%;
    min-height: 48px;
}
.ton-connect-btn:disabled {
    opacity: 0.7;
    cursor: progress;
}
.ton-connect-btn .ton-connect-btn__label {
    line-height: 1;
}

/* Stage-by-stage instruction card inside the deal detail screen.
   Sits between the key/value info block and the action buttons —
   tells the user "you are here / next step" in plain language.
   Background tints subtly by status so the colour itself signals
   "calm / action needed / done". */
.stage-guide {
    background: var(--overlay-1);
    border-left: 3px solid var(--accent-blue);
    padding: 14px 16px !important;
    border-radius: 14px;
    margin: 14px 0;
}
[dir="rtl"] .stage-guide {
    border-left: none;
    border-right: 3px solid var(--accent-blue);
}
.stage-guide__title {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 6px;
}
.stage-guide__body {
    color: var(--text-primary);
    font-size: 14px;
    line-height: 1.55;
    overflow-wrap: break-word;
    word-wrap: break-word;
}
/* Status-specific accent so the card reinforces the stage at a glance. */
.stage-guide--paid       { border-left-color: #FF9500; }
[dir="rtl"] .stage-guide--paid       { border-right-color: #FF9500; }
.stage-guide--sent       { border-left-color: var(--accent-blue); }
.stage-guide--completed  { border-left-color: #34C759; }
[dir="rtl"] .stage-guide--completed  { border-right-color: #34C759; }
.stage-guide--cancelled  { border-left-color: #FF3B30; opacity: 0.85; }
[dir="rtl"] .stage-guide--cancelled  { border-right-color: #FF3B30; }

/* Order detail body — cross-fade animation when the deal updates in
   place. The status flag is added before innerHTML is set then removed
   on the next frame so the transition runs forwards. */
#order-detail-body {
    transition: opacity 0.18s ease;
    will-change: opacity;
}
#order-detail-body.detail-fading {
    opacity: 0;
}

/* Order summary card */
.order-summary__row {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 8px;
}
.order-summary__amount {
    font-size: 28px;
    font-weight: 700;
    letter-spacing: -0.4px;
}
.order-summary__desc {
    color: var(--text-secondary);
    line-height: 1.4;
    font-size: 15px;
    word-break: break-word;
}

/* Key/value rows in info cards */
.kv {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 0;
    border-bottom: 1px solid var(--border-color);
    gap: 12px;
    min-width: 0;
}
.kv:last-child { border-bottom: none; }
.kv-key {
    color: var(--text-secondary);
    font-size: 14px;
    /* Keep the key column at its natural width so the long value
       (e.g. a 32-char @username) gets the available space and not
       the label. */
    flex: 0 0 auto;
    white-space: nowrap;
}
.kv-val {
    color: var(--text-primary);
    font-size: 15px;
    font-weight: 500;
    /* Allow the right-hand value to shrink and ellipsize. Without
       min-width:0 a flex item refuses to shrink below its content,
       which is what makes long usernames spill out of the card and
       break the rounded edge. */
    min-width: 0;
    text-align: right;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.success-card,
.cancel-card,
.warn-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    text-align: center;
    font-weight: 600;
    padding: 22px 20px;
}
.success-card { color: #34D399; }
.cancel-card  { color: #FF6961; }
.warn-card    { color: #F4A33D; }
.result-icon  { width: 36px; height: 36px; }

/* Buyer pay summary — clear breakdown of amount + fee + total + balance. */
.pay-summary .kv:last-of-type { border-bottom: none; }

/* Citation-style warning block, used by the "deal already taken" modal
   and similar notice surfaces. Mirrors the chat blockquote look. */
.quote-warning blockquote {
    background: var(--overlay-1);
    border-left: 3px solid var(--accent-blue);
    border-radius: 4px;
    padding: 10px 14px;
    margin: 0 0 8px;
    color: var(--text-primary);
    font-size: 14.5px;
    line-height: 1.45;
}
.quote-warning blockquote:last-child { margin-bottom: 0; }
.kv-warn  { color: #FF6961 !important; }
.pay-total { font-size: 17px; }

/* Cross-currency pay picker — list of currency rows with rate + balance.
   Each row tappable like a button; the chosen currency drills into a
   confirmation modal that quotes the precise debit. */
.cross-pay-help {
    font-size: 13px;
    color: var(--text-secondary);
    line-height: 1.45;
    margin: -4px 0 14px;
}
.cross-pay-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.cross-pay-loading {
    color: var(--text-secondary);
    font-size: 13px;
    text-align: center;
    padding: 18px 0;
}
.cross-pay-row {
    width: 100%;
    background: var(--overlay-1);
    border: 1px solid var(--overlay-2);
    border-radius: 14px;
    padding: 12px 14px;
    text-align: left;
    cursor: pointer;
    color: var(--text-primary);
    transition: background-color .15s ease, transform .12s ease;
    font: inherit;
}
.cross-pay-row:hover { background: var(--overlay-2); }
.cross-pay-row:active { transform: scale(.985); }
.cross-pay-row-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 4px;
}
.cross-pay-cur {
    font-weight: 700;
    font-size: 15px;
}
.cross-pay-amount {
    font-size: 14px;
}
.cross-pay-row-meta {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    font-size: 12px;
    color: var(--text-secondary);
}
[dir="rtl"] .cross-pay-row { text-align: right; }

/* Hand-over confirm modal — destructive step the seller takes when the
   gift has actually changed hands. Visually reinforced with a yellow
   warning glyph and the live manager handle so they can sanity-check
   before tapping the heavy "Yes" button. */
.handover-confirm .modal-content,
.handover-confirm {
    max-width: 420px;
}
.handover-question {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin-bottom: 14px;
}
.handover-question .result-icon {
    width: 32px;
    height: 32px;
    color: #F4A33D;
    flex: 0 0 32px;
}
.handover-question p {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--text-primary);
}
.handover-mgr {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--overlay-1);
    border-radius: 12px;
    padding: 10px 14px;
    margin-bottom: 14px;
}
.handover-mgr span {
    font-size: 13px;
    color: var(--text-secondary);
}
.handover-mgr code,
.handover-mgr a.handover-mgr-link {
    font-size: 14px;
    font-weight: 600;
    color: var(--accent-blue);
    font-family: -apple-system, BlinkMacSystemFont, 'SF Mono', Menlo, monospace;
    text-decoration: none;
}
.handover-mgr a.handover-mgr-link:hover,
.handover-mgr a.handover-mgr-link:focus { text-decoration: underline; }
.handover-mgr a.handover-mgr-link:active { opacity: 0.7; }
.handover-warn {
    background: rgba(244, 163, 61, 0.12);
    border: 1px solid rgba(244, 163, 61, 0.32);
    border-radius: 12px;
    padding: 10px 14px;
    margin: 0 0 16px;
    font-size: 13px;
    line-height: 1.45;
    color: var(--text-primary);
}
.handover-yes {
    background: linear-gradient(135deg, #F4A33D, #E07B00);
    color: #fff !important;
}
.handover-yes:hover {
    filter: brightness(1.05);
}

/* "(You)" suffix shown next to a counterparty's name when the viewer is
   that party. Keeps the colour subtle so it doesn't shout. */
.kv-you {
    color: var(--accent-blue);
    font-weight: 600;
    font-size: 12px;
    margin-left: 4px;
    opacity: 0.9;
}

/* Admin card mini-list */
.kv-list  { display: flex; flex-direction: column; }
.kv-list .kv:last-child { border-bottom: none; }
.kv-empty {
    color: var(--text-secondary);
    font-size: 13px;
    margin: 6px 0;
    text-align: center;
}
.kv-section-title {
    margin: 14px 0 8px;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
}

/* Requisite "Not bound" placeholder dim style */
.requisite-value.placeholder {
    color: var(--text-secondary);
    font-style: italic;
}

/* Stacked action buttons in the order detail — give every button air,
   never let two CTAs sit flush against each other. */
.action-stack {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 4px;
}
.action-stack > .btn { margin: 0; }
.action-stack > .info-card { margin: 0; }

.pay-instructions__body { color: var(--text-secondary); font-size: 14px; line-height: 1.5; margin-top: 6px; }

/* Mini progress bar inside list cards */
.order-progress-mini { margin-top: 14px; }

/* Order list cards — consistent spacing. Slightly bigger padding so
   the status pill + amount + description stack with proper breathing
   room, and the mini progress bar at the bottom doesn't overflow. */
.orders-list { display: flex; flex-direction: column; gap: 14px; }
.order-card {
    padding: 18px 18px 16px;
    border-radius: 18px;
    background: var(--card-bg);
    box-shadow: var(--shadow-small);
    transition: transform 0.12s ease, box-shadow 0.2s ease;
    will-change: transform;
}
.order-card:active { transform: scale(0.985); }

.order-card .order-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
    gap: 10px;
    min-width: 0;
}
.order-card .order-tag {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1 1 auto;
}
/* Status badges — unified tinted-pill style.
 *
 * Earlier we used "liquid glass" pills (white text on translucent
 * coloured fill with backdrop-blur). On dark backgrounds the in-flight
 * states (wait_payment / paid / sent) read OK, but the lighter alphas
 * made "wait_payment" feel ghost-dim while "completed" / "cancelled"
 * shouted at the eye via their 0.72 alpha + outer glow. The visual
 * weight wasn't consistent across statuses.
 *
 * New approach: every pill shares the SAME alpha values (0.18 tint
 * background, 0.32 inset border) and renders the LABEL itself in the
 * status colour instead of in white. Result: each pill has equal
 * weight, the colour itself carries the semantics, no backdrop-blur
 * is needed (cheaper to paint, no blurry edge artefacts on light
 * themes). Colours pulled from the iOS system palette so they look
 * native inside the Telegram WebApp.
 */
.order-card .order-status {
    --pill-color: 142, 142, 147;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.01em;
    padding: 5px 12px;
    border-radius: 999px;
    color: rgb(var(--pill-color));
    background: rgba(var(--pill-color), 0.18);
    box-shadow: inset 0 0 0 1px rgba(var(--pill-color), 0.32);
    white-space: nowrap;
    text-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    line-height: 1.25;
}
.order-card .order-status.status-wait_payment { --pill-color: 142, 142, 147; }  /* iOS systemGray  */
.order-card .order-status.status-paid         { --pill-color:  56, 162, 255; }  /* bright blue     */
.order-card .order-status.status-sent         { --pill-color: 255, 149,   0; }  /* iOS systemOrange*/
.order-card .order-status.status-completed    { --pill-color:  52, 199,  89; }  /* iOS systemGreen */
.order-card .order-status.status-cancelled    { --pill-color: 255,  75,  75; }  /* warm red        */
/* Cancelled cards stay fully readable — icon, amount and badge are not
   dimmed. Description fades slightly so the eye prioritises status +
   amount. No more 0.55 whole-card opacity (was washing the gift icon out). */
.order-card[data-status="cancelled"] {
    opacity: 1;
}
.order-card[data-status="cancelled"] .order-description,
.order-card[data-status="completed"] .order-description {
    opacity: 0.7;
}
.order-card[data-status="cancelled"] .order-amount {
    text-decoration: line-through;
    text-decoration-color: rgba(200,40,40,0.55);
    text-decoration-thickness: 1.5px;
}
.order-card .order-amount {
    font-size: 17px;
    font-weight: 700;
    letter-spacing: -0.2px;
}
.order-card .order-description {
    color: var(--text-secondary);
    font-size: 13px;
    line-height: 1.4;
    margin-top: 4px;
}
/* Per-card timestamp — wrapped in a small "chip" with a clock icon so
 * it reads as a deliberate UI element instead of stray grey text. The
 * label inside follows _formatOrderDate's adaptive output: "just now",
 * "5 min ago", "Yesterday, 18:36", "12 мая, 18:36" — see the JS for
 * the full ladder. The wrapping div stays in the layout so we can
 * align the chip to the left independently of the card padding.
 */
.order-card .order-date {
    margin-top: 10px;
    display: flex;
    align-items: center;
}
.order-card .order-date-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px 4px 8px;
    border-radius: 999px;
    background: rgba(142, 142, 147, 0.12);
    color: var(--text-secondary);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.01em;
    line-height: 1.2;
    white-space: nowrap;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}
.order-card .order-date-chip svg {
    flex-shrink: 0;
    opacity: 0.85;
}
.order-card .order-date-chip > span {
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Action buttons row at the top of Orders tab — proper gap, no overlap */
.action-buttons {
    display: flex;
    gap: 8px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}
.action-buttons .btn { flex: 1; min-width: 0; }
.action-buttons .btn-secondary.active {
    background: var(--accent-blue);
    color: #fff;
    border-color: var(--accent-blue);
}

/* Share modal */
.share-modal { max-width: 520px; }
.share-preview {
    background: var(--overlay-1);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    padding: 14px;
    margin-bottom: 16px;
    color: var(--text-primary);
    font-size: 14px;
    line-height: 1.5;
    max-height: 280px;
    overflow-y: auto;
}
.share-preview blockquote {
    border-left: 3px solid var(--accent-blue);
    padding: 6px 12px;
    margin: 6px 0;
    background: rgba(10, 132, 255, 0.06);
    border-radius: 4px;
    color: var(--text-primary);
}
/* Link inside the preview should use our brand accent — default browser
   blue read as too dark on the dark surface. */
.share-preview a {
    color: var(--accent-light-blue, #5DC0FF);
    text-decoration: none;
    word-break: break-all;
}
.share-preview code {
    background: var(--overlay-1);
    padding: 1px 5px;
    border-radius: 4px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12.5px;
}
.share-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.order-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 6px 0 4px;
}

/* === Order progress tracker ===
   Adapted from the portals_verifier reference design: thin shell card,
   small (12px) dots with a green palette, animated gradient lines that
   fill via scaleX, and a glowing halo on the current dot. Two sizes:
   `progress-shell` for the order detail screen, `progress--sm` for the
   inline mini-tracker on list cards. */

@keyframes progress-pulse-halo {
    0%, 100% { transform: scale(1);   opacity: 0.6; }
    50%      { transform: scale(1.8); opacity: 0;   }
}
@keyframes progress-shimmer {
    0%   { transform: translate(-130%); }
    100% { transform: translate(130%); }
}
@keyframes progress-reveal {
    0% { transform: scaleX(0); }
    100% { transform: scaleX(var(--line-fill, 0)); }
}

/* Shell — only used by lg-size on the order detail page. */
.progress-shell {
    width: 100%;
    background: linear-gradient(var(--progress-shell-from) 0%, var(--progress-shell-to) 100%);
    border: 1px solid var(--overlay-1);
    border-radius: 24px;
    position: relative;
    overflow: hidden;
    margin-bottom: 16px;
}
.progress-shell::before {
    content: "";
    position: absolute;
    top: -100px; right: -70px;
    width: 220px; height: 220px;
    background: rgba(73,223,100,0.08);
    border-radius: 50%;
    filter: blur(22px);
    pointer-events: none;
}
.progress-inner {
    box-sizing: border-box;
    background: var(--progress-inner-bg);
    border-radius: 24px;
    padding: 14px;
    position: relative;
    z-index: 1;
}
.progress-title-label {
    color: #828387;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin: 0;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.25;
}
.progress-subtitle {
    color: var(--progress-text);
    margin: 10px 0 0;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.3;
}
.progress-subtitle .ratio {
    color: #2db84d;
    text-shadow: 0 0 12px rgba(73,223,100,0.3);
}
:root[data-theme="dark"] .progress-subtitle .ratio { color: #49df64; }
.progress-secured {
    text-align: center;
    color: var(--progress-text-muted);
    margin: 14px 0 0;
    padding: 4px 0;
    font-size: 10px;
    font-weight: 400;
    line-height: 1.25;
}

/* Compact wrapper — used on order list cards.
 * Horizontal padding gives the first & last captions room to be
 * centered ON their dots without overflowing the card edge. Without
 * this padding, the .progress-segment:first-child / .progress-segment-last
 * special-cases below override their captions to left/right anchored,
 * which puts caption #1 ("Создана") tight against the right edge of
 * the next caption ("Принята") while the rest of the row keeps wider
 * symmetric gaps. The user noticed this asymmetry on the deals list.
 * Indenting the track 22px on each side gives every caption — including
 * the edge ones — enough room to center on its dot with uniform spacing.
 */
.progress--sm { padding: 6px 22px 2px; }

/* The track holds segments + connectors. */
.progress-track {
    display: flex;
    align-items: flex-start;
    gap: 1px;
    width: 100%;
    margin-top: 16px;
}
.progress--sm .progress-track { margin-top: 4px; }

.progress-segment,
.progress-segment-last {
    flex: 0 0 12px;
    width: 12px;
    position: relative;
}
/* Single-line caption pill. Padding-bottom is just enough for the
 * pill plus a small visual breather under it — no extra room for
 * wrap is reserved because captions never wrap (see .progress-caption
 * rule below — white-space:nowrap is enforced so Russian / Ukrainian
 * full labels read on a single line on every supported screen width).
 *
 *   - LG (.progress-segment):       dot(12) + 28 = 40px tall
 *     Caption top:20px + ~14px pill = bottom 34 (fits)
 *   - SM (.progress--sm .progress-segment): dot(10) + 22 = 32px tall
 *     Caption top:16px + ~13px pill = bottom 29 (fits)
 */
.progress-segment      { padding-bottom: 28px; }
.progress--sm .progress-segment { padding-bottom: 22px; }
/* All captions — including first and last — center on their dot.
 * Earlier we anchored caption 1 to the left edge of the track and
 * caption 5 to the right edge, but the resulting asymmetry felt
 * uneven (caption 1 hugged the card border while caption 2 sat
 * neatly under its dot). With both SM (.progress--sm wrapper) and
 * LG (.progress-shell .progress-track) given side-padding below,
 * the edge captions have room to overhang their dot without
 * escaping the surrounding panel. The whole row reads as a single
 * tidy rhythm. */
.progress-segment-last .progress-caption,
.progress-segment:first-child .progress-caption {
    left: 6px;
    right: auto;
    transform: translateX(-50%);
    text-align: center;
}
/* LG shell: indent the track so the centered first/last captions
 * fit cleanly inside the shell's rounded border. The inner panel
 * already has 14px padding for the title/subtitle text, but the
 * captions extend ~20px past their dots so we add a bit more for
 * them specifically. */
.progress-shell .progress-track {
    padding-inline: 8px;
    box-sizing: border-box;
}

/* Dot itself is a tiny circle. The pulsing halo lives in ::before so the
   dot's own box-shadow (the green ring on `.done`) stays put. */
.progress-dot {
    position: relative;
    box-sizing: border-box;
    background: #3a3a3a;
    border: 1px solid var(--overlay-1);
    border-radius: 50%;
    width: 12px; height: 12px;
    box-shadow: inset 0 1px var(--overlay-1);
}
.progress--sm .progress-dot { width: 10px; height: 10px; }
.progress-dot.done {
    background: linear-gradient(#62ee7d 0%, #49df64 100%);
    border-color: rgba(73,223,100,0.6);
    box-shadow:
        0 0 0 4px rgba(73,223,100,0.10),
        0 0 14px rgba(73,223,100,0.20);
}
/* Active (current) dot — visibly green even without `done`, so when the
   user is mid-flight (e.g. stage=2 "buyer joined") the dot they're at
   reads as the live one at a glance. The pulsing halo is on top via
   ::before — doesn't override the body fill. */
.progress-dot.active {
    background: linear-gradient(#7eff96 0%, #49df64 100%);
    border-color: rgba(73,223,100,0.8);
    box-shadow:
        0 0 0 4px rgba(73,223,100,0.16),
        0 0 16px rgba(73,223,100,0.36);
}
.progress-dot.active::before {
    content: "";
    position: absolute;
    inset: -4px;
    border-radius: 50%;
    background: rgba(73,223,100,0.55);
    animation: progress-pulse-halo 2.2s ease-in-out infinite;
    pointer-events: none;
}

.progress-connector {
    flex: 1 1 0;
    display: flex;
    align-items: center;
    height: 12px;
    min-width: 0;
}
.progress--sm .progress-connector { height: 10px; }

.progress-line-track {
    box-sizing: border-box;
    background: var(--overlay-1);
    border-radius: 999px;
    width: 100%;
    height: 6px;
    overflow: hidden;
    box-shadow:
        inset 0 1px var(--overlay-1),
        inset 0 -1px rgba(0,0,0,0.2);
}
.progress--sm .progress-line-track { height: 4px; }

.progress-line-fill {
    transform-origin: left center;
    width: 100%;
    height: 100%;
    transform: scaleX(var(--line-fill, 0));
    background: linear-gradient(90deg, #35d357 0%, #49df64 50%, #7bf98f 100%);
    border-radius: 999px;
    position: relative;
    box-shadow:
        0 0 16px rgba(73,223,100,0.34),
        0 0 8px  rgba(73,223,100,0.18);
}
.progress-line-fill.animated {
    animation: progress-reveal 0.9s cubic-bezier(.22,1,.36,1) both;
    animation-delay: var(--line-delay, 0s);
}
.progress-line-fill.active::after {
    content: "";
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.45), transparent);
    position: absolute; inset: 0;
    animation: progress-shimmer 2.4s ease-in-out infinite;
}

/* Caption — glass pill under each dot. Uses backdrop-filter blur to
 * read on both light AND dark themes without per-theme overrides.
 *
 * Always a single line: user explicitly asked that Russian labels
 * never wrap. To make full labels ("У менеджера", "Покупатель")
 * fit single-line on cramped 320px phones, the font is small (8.5px)
 * with subtly tightened tracking and very tight side-padding. Every
 * label in every supported language renders comfortably inside the
 * max-width without truncation. SM and LG share the exact same
 * caption styling so the preview reads as a mini-mirror of the
 * deal-detail track.
 */
.progress-caption {
    z-index: 1;
    box-sizing: border-box;
    text-align: center;
    color: var(--progress-caption-text);
    pointer-events: none;
    width: max-content;
    /* Generous max-width so the natural pill width is rarely capped;
     * narrower-than-pill labels (most of them) center cleanly with
     * comfortable gaps to neighbours. The longest Cyrillic label
     * "У менеджера" renders ≈ 52px wide at the font/padding below;
     * adjacent dots sit ~64–72px apart on every supported width,
     * which leaves a 10+ px gap on every screen. */
    max-width: 64px;
    margin: 0;
    padding: 2px 6px;
    font-size: 8.5px;
    font-weight: 700;
    /* Slight negative tracking buys a couple of pixels on long
     * 11-char Cyrillic labels without making letters touch. */
    letter-spacing: -0.005em;
    line-height: 1.2;
    position: absolute;
    top: 20px; left: 6px;
    transform: translateX(-50%);
    /* Single line — no wrap, no ellipsis. The max-width is set so
     * that every label across all 5 languages fits naturally. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: clip;
    background: var(--progress-caption-bg);
    backdrop-filter: blur(8px) saturate(150%);
    -webkit-backdrop-filter: blur(8px) saturate(150%);
    /* Full stadium pill. */
    border-radius: 999px;
    box-shadow:
        inset 0 0 0 1px rgba(255,255,255,0.10),
        0 1px 3px rgba(0,0,0,0.14);
}
/* Past stages and the active stage tint the pill green — same family
   as the bar fill so the eye links them. Future stages stay grey. */
.progress-segment .progress-dot.done ~ .progress-caption,
.progress-segment-last .progress-dot.done ~ .progress-caption {
    background: rgba(73,223,100,0.70);
}
.progress-segment .progress-dot.active ~ .progress-caption,
.progress-segment-last .progress-dot.active ~ .progress-caption {
    background: rgba(73,223,100,0.70);
    box-shadow:
        inset 0 0 0 1px rgba(255,255,255,0.16),
        0 0 12px rgba(73,223,100,0.35),
        0 1px 2px rgba(0,0,0,0.10);
}
.progress--sm .progress-caption {
    /* SM and LG share identical caption styling (font, padding,
     * max-width, wrapping behaviour). The only thing that changes
     * for SM is the vertical offset, because the SM dot is 10px
     * tall while the LG dot is 12px — keeping the top distance
     * proportionally short. Everything else flows from the base
     * .progress-caption rule, which is exactly what the user
     * asked for ("на превью так же как и внутри сделки"). */
    top: 16px;
}
.progress-segment .progress-dot.active ~ .progress-caption,
.progress-segment .progress-dot.done   ~ .progress-caption,
.progress-segment-last .progress-dot.active ~ .progress-caption,
.progress-segment-last .progress-dot.done   ~ .progress-caption {
    color: rgba(255,255,255,0.92);
}

/* === Compact currency picker ===
   Replaces the native <select> on the wallets page with a horizontal
   chip strip. Each chip = real icon + currency code, snaps to centre,
   one tap to switch. Sized to fit roughly 4-5 chips on screen. */
.currency-strip {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    overflow-y: hidden;
    /* Align with the "My wallets" card edges instead of bleeding
       to the screen edge. Small left/right padding leaves the
       first/last chip slightly inset so the user immediately
       reads it as a scrollable list (the leading whitespace
       hints "there's more — drag me"). Earlier the strip ran
       edge-to-edge with -20px margin which made the chips look
       like they were stuck to the screen border. */
    padding: 6px 8px 12px 16px;
    margin: 4px 0 12px;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    /* Soft right-edge fade so the user sees there's more content
       to scroll into when chips overflow the visible width. */
    mask-image: linear-gradient(to right,
                                rgba(0,0,0,1) 0,
                                rgba(0,0,0,1) calc(100% - 24px),
                                rgba(0,0,0,0.0) 100%);
    -webkit-mask-image: linear-gradient(to right,
                                rgba(0,0,0,1) 0,
                                rgba(0,0,0,1) calc(100% - 24px),
                                rgba(0,0,0,0.0) 100%);
}
.currency-strip::-webkit-scrollbar { display: none; }

.currency-strip .cur-chip {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px 8px 8px;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    color: var(--text-primary);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    scroll-snap-align: start;
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
    user-select: none;
}
.currency-strip .cur-chip .cur-icon {
    width: 24px !important;
    height: 24px !important;
    min-width: 24px;
    min-height: 24px;
}
.currency-strip .cur-chip:active { transform: scale(0.97); }
.currency-strip .cur-chip.active {
    background: var(--accent-blue);
    border-color: var(--accent-blue);
    color: #fff;
}

/* === Pre-create deal safety warning ===
   Shown right after the user submits the create-order form, BEFORE the
   API call. The user has to read it for 10 seconds before the confirm
   button enables. Aesthetically: not a fully-red modal (would look
   alarming/error-state), but with red accents on the header pulse, the
   ❌/⚠️ icons in the rules list, and the confirm button — so the eye
   immediately tracks "this is a serious notice". */
/* Sit BELOW TonConnect (5000 !important) so a TonConnect deeplink
   prompt that opens during the safety warning isn't covered. The
   safety modal lives above all other modals (3000-3500 range) but
   yields to the wallet-connect popup which is itself a hard
   blocker. */
.safety-warning-overlay { z-index: 4900; }

.safety-warning {
    /* Slightly tighter than the default modal so the warning text feels
       focused rather than sprawling. */
    padding: 20px 18px calc(var(--safe-area-bottom) + 18px) !important;
    /* Lock the sheet inside the viewport. We block BOTH horizontal
       scroll (the "можно листать вправо и влево" bug) AND any child
       from exceeding the modal's intrinsic content width. */
    box-sizing: border-box;
    max-width: 100vw;
    width: 100%;
    overflow-x: hidden;
    /* Touch-action prevents iOS pull-to-scroll horizontally even
       when content tries to overflow — belt-and-braces with the
       overflow-x:hidden above. */
    touch-action: pan-y;
}
.safety-warning-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-bottom: 14px;
    margin-bottom: 14px;
    border-bottom: 1px solid var(--overlay-1);
    /* Allow the title block to shrink for long localized titles. */
    min-width: 0;
    max-width: 100%;
    /* IMPORTANT: NO overflow:hidden here. The badge's outer glow
       ring extends ~17px outside the badge perimeter on every side,
       and clipping it at the head's left edge made the icon look
       cut-off / "вылазит за границу". The parent `.safety-warning`
       already has `overflow-x: hidden` so any real overflow is still
       contained at modal level. */
}
.safety-warning-pulse {
    position: relative;
    width: 44px; height: 44px;
    border-radius: 50%;
    flex: 0 0 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    background: linear-gradient(135deg, #ff5252 0%, #d23030 100%);
    /* Soft alpha-pulse on the glow ring — opacity-only so the badge
       doesn't change SIZE (no overflow clipping). The pulse is
       slow + subtle so it conveys urgency without being noisy. */
    box-shadow:
        0 0 0 3px rgba(255, 82, 82, 0.20),
        0 0 14px rgba(255, 82, 82, 0.30);
    animation: safetyPulseGlow 2.2s ease-in-out infinite;
}
@keyframes safetyPulseGlow {
    0%, 100% {
        box-shadow:
            0 0 0 3px rgba(255, 82, 82, 0.18),
            0 0 12px rgba(255, 82, 82, 0.28);
    }
    50% {
        box-shadow:
            0 0 0 4px rgba(255, 82, 82, 0.42),
            0 0 18px rgba(255, 82, 82, 0.55);
    }
}
@media (prefers-reduced-motion: reduce) {
    .safety-warning-pulse { animation: none; }
}
.safety-warning-title {
    margin: 0;
    color: var(--text-primary);
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -0.2px;
    line-height: 1.2;
    /* Long titles wrap at word boundaries when possible. We only
       use `overflow-wrap: break-word`, NOT `anywhere` or
       `word-break: break-all` — those broke words letter-by-letter
       which made Russian/Ukrainian text read like a typewriter
       glitch. break-word only splits a word when there's literally
       no other way to fit it. */
    min-width: 0;
    overflow-wrap: break-word;
    word-wrap: break-word;
    hyphens: auto;
}
.safety-warning-body {
    max-height: 56vh;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    /* No padding-right — used to push the scrollbar slightly off
       the edge, but on iOS it gave the impression the content
       could scroll sideways. */
    padding-right: 0;
    color: var(--text-primary);
    font-size: 14px;
    line-height: 1.55;
    -webkit-overflow-scrolling: touch;
    /* Word-break protection at the BODY level only. Inner elements
       inherit the wrapping behavior naturally. We deliberately do
       NOT cascade `word-break: break-word` to every descendant
       (which made every <p>, <b>, <li> break by letters) — only
       `overflow-wrap: break-word` here is enough for natural,
       readable text in any of the 5 languages. */
    overflow-wrap: break-word;
    word-wrap: break-word;
    /* Hard width cap. The modal sheet has its own padding so this
       value matches the available content width and nothing inside
       can overflow horizontally. */
    max-width: 100%;
    box-sizing: border-box;
    /* Block horizontal touch-pan ourselves too — some browsers
       respect this even when overflow-x:hidden is set. */
    touch-action: pan-y;
}
/* For arabic numerals + URLs that genuinely have no break points
   (e.g. very long contract addresses or t.me links), allow
   breaking mid-word as a last resort. <code> blocks get this so
   our `https://t.me/nft/...` examples don't overflow. */
.safety-warning-body pre,
.safety-warning-body code {
    overflow-wrap: anywhere;
    word-break: break-all;
    white-space: pre-wrap;
    max-width: 100%;
}
.safety-warning-body p { margin: 0 0 10px; }
.safety-warning-body .safety-headline {
    font-weight: 700;
    color: #ff5252;
    font-size: 14px;
    letter-spacing: 0.02em;
}
.safety-warning-body .safety-callout {
    background: rgba(255, 82, 82, 0.10);
    border-left: 3px solid #ff5252;
    padding: 8px 12px;
    border-radius: 8px;
    margin: 8px 0 14px;
    font-weight: 600;
}
[dir="rtl"] .safety-warning-body .safety-callout {
    border-left: none;
    border-right: 3px solid #ff5252;
}
.safety-warning-body .safety-section-title {
    font-weight: 700;
    color: var(--text-primary);
    margin-top: 14px;
}
.safety-warning-body ul.safety-list {
    list-style: none;
    margin: 6px 0 12px;
    padding: 0;
}
.safety-warning-body ul.safety-list li {
    /* IMPORTANT: NOT `display: flex`. Earlier this was flex with
       gap:8px, which turned every text run + every <b> element
       inside the <li> into an *anonymous flex item*. Each one
       then got an 8px gap around it, scattering the sentence
       across the line: "Передавайте  ТОЛЬКО  на  @FunPayEscrow
       подарок  аккаунт" — exactly the screenshot bug.
       The icon now floats absolutely in a left gutter and the
       text flows as normal inline content. No more anonymous
       flex children, words wrap normally. */
    display: block;
    position: relative;
    padding: 8px 10px 8px 36px;
    margin-bottom: 6px;
    background: var(--overlay-1);
    border-radius: 10px;
    font-size: 13.5px;
    line-height: 1.5;
}
[dir="rtl"] .safety-warning-body ul.safety-list li {
    padding: 8px 36px 8px 10px;
    text-align: right;
}
/* Position the icon in the left gutter (or right for RTL) so the
   text inside the li flows as one continuous block — no flex
   children, no weird gaps. */
.safety-warning-body ul.safety-list li > .mat-icon {
    position: absolute;
    left: 10px;
    top: 10px;
}
[dir="rtl"] .safety-warning-body ul.safety-list li > .mat-icon {
    left: auto;
    right: 10px;
}
.safety-warning-body ul.safety-list .ok    { color: #49df64; flex: 0 0 18px; }
.safety-warning-body ul.safety-list .bad   { color: #ff5252; flex: 0 0 18px; }
.safety-warning-body ul.safety-list .warn  { color: #ffcc33; flex: 0 0 18px; }

/* === Material-style inline icons (replace emojis in safety modal) ===
   Each icon scales with the surrounding font-size via 1em sizing and
   gets a per-kind colour + animation so they pull the eye without
   feeling like a static decoration. */
.mat-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.15em;
    height: 1.15em;
    vertical-align: -0.22em;
    flex: 0 0 1.15em;
    line-height: 1;
}
.mat-icon svg {
    width: 100%;
    height: 100%;
    display: block;
}
/* Per-kind colours only — NO animations anywhere. Earlier the
   crisis icon had a heartbeat (`mat-pulse`) but the `scale(1.08)`
   pushed the icon's bounding box outside its inline-flex slot,
   making nearby text appear to twitch and creating the "выходят
   за невидимые грани" effect the user reported. Static icons +
   strong color coding (red = danger, yellow = warn, green = safe,
   blue = trust) carry the message without any motion. */
.mat-icon--crisis { color: #ff5252; }
.mat-icon--warn   { color: #ffcc33; }
.mat-icon--shield { color: #49df64; }
.mat-icon--check  { color: #49df64; }
.mat-icon--cancel { color: #ff5252; }
.mat-icon--money  { color: #ffcc33; }
.mat-icon--lock   { color: var(--accent-blue); }
/* Scale the headline/callout/section icons larger so they read as
   distinct visual landmarks, not just inline punctuation. */
.safety-warning-body .safety-headline .mat-icon { width: 1.3em; height: 1.3em; flex: 0 0 1.3em; }
.safety-warning-body .safety-callout  .mat-icon { width: 1.25em; height: 1.25em; flex: 0 0 1.25em; }
.safety-warning-body .safety-section-title .mat-icon { width: 1.2em; height: 1.2em; flex: 0 0 1.2em; }
.safety-warning-body ul.safety-list li .mat-icon { width: 1.2em; height: 1.2em; flex: 0 0 1.2em; }
.safety-warning-body .safety-footer .mat-icon { width: 1.2em; height: 1.2em; flex: 0 0 1.2em; }
@media (prefers-reduced-motion: reduce) {
    .mat-icon { animation: none !important; }
}
.safety-warning-body ul.safety-list--punish li {
    background: rgba(255, 82, 82, 0.08);
    border: 1px solid rgba(255, 82, 82, 0.18);
}

/* CTA button at the bottom of the safety modal. Starts disabled with
 * a countdown label ("Прочитайте — 10с"); after 10 seconds the
 * --ready class is added and it becomes a tap-to-confirm danger
 * button. Earlier this element had ZERO CSS rules and rendered as a
 * bare native <button> — hard to read on dark theme and indistinguishable
 * from a system control. */
.safety-warning-confirm {
    display: block;
    width: 100%;
    margin-top: 18px;
    padding: 15px 18px;
    border: 1px solid rgba(255, 82, 82, 0.35);
    border-radius: 14px;
    background: rgba(255, 82, 82, 0.08);
    color: rgba(255, 82, 82, 0.78);
    font-family: inherit;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.01em;
    cursor: not-allowed;
    font-variant-numeric: tabular-nums;
    transition:
        background 0.20s ease,
        color      0.20s ease,
        border     0.20s ease,
        transform  0.10s ease;
}
.safety-warning-confirm:disabled {
    cursor: not-allowed;
    opacity: 0.82;
}
/* "Ready" state — full danger-red CTA. Strong shadow + tap feedback
 * so the user clearly sees it's now actionable. */
.safety-warning-confirm--ready {
    cursor: pointer;
    background: linear-gradient(135deg, #ff5252 0%, #d23030 100%);
    color: #ffffff;
    border-color: transparent;
    box-shadow:
        0 8px 22px rgba(255, 82, 82, 0.40),
        inset 0 1px 0 rgba(255, 255, 255, 0.20);
    animation: safetyReadyIn 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}
.safety-warning-confirm--ready:active {
    transform: scale(0.985);
    box-shadow:
        0 4px 12px rgba(255, 82, 82, 0.35),
        inset 0 1px 0 rgba(255, 255, 255, 0.15);
}
/* Subtle reveal animation when the button transitions into the
 * ready state — fade + slight lift so the operator notices it
 * became tappable. Opacity / translateY only — no scale-out so
 * nothing clips against the modal edges. */
@keyframes safetyReadyIn {
    0%   { opacity: 0.7; transform: translateY(4px); }
    100% { opacity: 1;   transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    .safety-warning-confirm--ready { animation: none; }
}
.safety-warning-body .safety-mgr,
.safety-warning-body a.safety-mgr {
    font-weight: 700;
    color: var(--accent-blue);
    background: rgba(10, 132, 255, 0.10);
    padding: 1px 6px;
    border-radius: 6px;
    text-decoration: none;
    /* Keep it inline so it doesn't break the surrounding sentence
       layout; whitespace preserves the natural reading flow. */
    white-space: nowrap;
}
.safety-warning-body a.safety-mgr:active {
    background: rgba(10, 132, 255, 0.20);
}

/* Generic Telegram user link — anywhere we render @username this
   class applies. Same accent-blue colour, subtle hover, opens
   t.me in a new tab. */
.tg-user-link {
    color: var(--accent-blue);
    text-decoration: none;
    font-weight: 600;
    word-break: keep-all;
}
.tg-user-link:hover,
.tg-user-link:focus { text-decoration: underline; }
.tg-user-link:active { opacity: 0.75; }
.safety-warning-body .safety-footer {
    margin-top: 14px;
    padding: 10px 12px;
    background: var(--overlay-1);
    border-radius: 10px;
    font-weight: 600;
    text-align: center;
}

.safety-warning-confirm {
    display: block;
    width: 100%;
    margin-top: 16px;
    padding: 16px;
    border: none;
    border-radius: 14px;
    color: #fff;
    background: linear-gradient(135deg, #b03030 0%, #7a1f1f 100%);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.01em;
    cursor: not-allowed;
    opacity: 0.62;
    transition: opacity 0.25s ease, background 0.25s ease, transform 0.12s ease;
}
.safety-warning-confirm:not([disabled]):hover { opacity: 1; }
.safety-warning-confirm--ready {
    background: linear-gradient(135deg, #ff5252 0%, #d23030 100%);
    box-shadow:
        0 6px 18px rgba(255, 82, 82, 0.32),
        inset 0 1px 0 rgba(255,255,255,0.18);
    cursor: pointer;
    opacity: 1 !important;
}
.safety-warning-confirm--ready:active { transform: scale(0.985); }


/* ╔══════════════════════════════════════════════════════════════════╗
   ║  Accessibility — reduced motion                                  ║
   ║                                                                  ║
   ║  Users who set "Reduce Motion" on their device (iOS Settings,    ║
   ║  Android Accessibility, macOS System Prefs) opt OUT of perpetual ║
   ║  animations. Earlier only `.mat-icon` honoured this; the loading ║
   ║  shimmer, progress halo, and safety pulse kept ticking and       ║
   ║  could trigger vestibular discomfort.                            ║
   ║                                                                  ║
   ║  Below — a single sweeping rule that disables every infinite     ║
   ║  animation we ship. Discrete one-shot transitions (modal slide-  ║
   ║  in, button press) are kept because they convey state change.    ║
   ╚══════════════════════════════════════════════════════════════════╝ */
@media (prefers-reduced-motion: reduce) {
    .skeleton,
    .progress-dot.active::before,
    .progress-line-fill.active::after,
    .safety-warning-pulse,
    .safety-warning-pulse svg,
    .balance-skeleton,
    .tab-indicator {
        animation: none !important;
    }
    /* Slow snappy transitions to be barely perceivable rather than
       jumpy — outright `transition: none` makes the UI feel broken. */
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}


/* ╔══════════════════════════════════════════════════════════════════╗
   ║  RTL (Arabic) global support                                     ║
   ║                                                                  ║
   ║  Earlier RTL was only applied inside the safety-warning modal.   ║
   ║  Now the whole app respects [dir="rtl"] on documentElement: text ║
   ║  flows right-to-left, flex containers get reversed, paddings     ║
   ║  swap sides, and icon-aligned components flip.                   ║
   ╚══════════════════════════════════════════════════════════════════╝ */
[dir="rtl"] body,
[dir="rtl"] .page,
[dir="rtl"] .modal-content {
    text-align: right;
}
[dir="rtl"] .kv {
    flex-direction: row-reverse;
}
[dir="rtl"] .kv-key,
[dir="rtl"] .kv-val {
    text-align: start;
}
[dir="rtl"] .tab-button {
    /* Bottom nav stays LTR — equally spaced items don't need flipping
       and SVG icons don't have laterality. */
}
[dir="rtl"] .back-btn svg,
[dir="rtl"] .btn-back svg {
    transform: scaleX(-1);
}
[dir="rtl"] .modal-actions {
    flex-direction: row-reverse;
}
[dir="rtl"] .cross-pay-row { text-align: right; }
[dir="rtl"] .cross-pay-row-head,
[dir="rtl"] .cross-pay-row-meta {
    flex-direction: row-reverse;
}
[dir="rtl"] .handover-question {
    flex-direction: row-reverse;
}
[dir="rtl"] .handover-mgr {
    flex-direction: row-reverse;
}
/* Progress captions: keep them centred under their dot regardless of
   text direction. translateX(-50%) is symmetric so it works for RTL
   too — but the caption text inside should be `unicode-bidi: plaintext`
   so a Russian/English label inside an RTL document still renders LTR
   internally without the bidi algorithm reordering letters. */
[dir="rtl"] .progress-caption {
    unicode-bidi: plaintext;
}


/* ╔══════════════════════════════════════════════════════════════════╗
   ║  Long-username overflow                                          ║
   ║                                                                  ║
   ║  An escrow handle longer than the modal width used to push the   ║
   ║  layout sideways. Now the code element ellipsis-truncates and    ║
   ║  the row wraps if needed.                                        ║
   ╚══════════════════════════════════════════════════════════════════╝ */
.handover-mgr {
    flex-wrap: wrap;
    min-width: 0;
}
.handover-mgr code {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
    min-width: 0;
    flex: 1 1 auto;
}


/* ╔══════════════════════════════════════════════════════════════════╗
   ║  OWNER PANEL                                                     ║
   ║                                                                  ║
   ║  Visible only to ADMIN_ID. Sits below the admin card on the      ║
   ║  profile page. Uses inline-SVG Material Symbols for icons        ║
   ║  (CSP-self-only — no external font load).                        ║
   ╚══════════════════════════════════════════════════════════════════╝ */

/* Inline Material Symbol — sized via attributes on the SVG, so this
 * rule only handles alignment quirks. `display:inline-block` keeps
 * the glyph baseline-aligned with the text next to it. */
.mi {
    display: inline-block;
    vertical-align: middle;
    flex-shrink: 0;
    line-height: 1;
}

.owner-card .card-title {
    display: flex;
    align-items: center;
    gap: 8px;
}

.owner-card__actions {
    gap: 8px;
}

/* Top-level owner buttons (the 4 entries on the card). Icon-left
 * layout, slightly tighter padding than .btn-block defaults so all
 * four fit on one screen above the fold. */
.owner-action {
    display: flex !important;
    align-items: center;
    justify-content: flex-start !important;
    gap: 12px;
    text-align: left !important;
    padding: 12px 16px !important;
}
.owner-action__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 10px;
    background: rgba(10,132,255,0.12);
    color: var(--accent-blue);
    flex-shrink: 0;
}
.owner-action.btn-primary .owner-action__icon {
    background: rgba(255,255,255,0.20);
    color: #fff;
}

/* Owner-modal scope: anything inside .owner-modal uses its own
 * spacing tweaks so the buttons + form rows look intentional rather
 * than borrowing the generic modal styles. */
.owner-modal .modal-content {
    max-width: 480px;
    width: 100%;
}
.owner-modal .modal-header h2 {
    display: flex;
    align-items: center;
    gap: 8px;
}
.owner-modal .btn-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Section title inside owner modals (e.g. "Whitelist" header above
 * the rows list). */
.owner-section-title {
    margin: 0 0 10px;
    font-size: 13px;
    font-weight: 700;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* Generic loading + empty states for the dynamic modals (escrow,
 * whitelist) — neutral neutral grey text, lots of breathing room. */
.owner-loading,
.owner-empty {
    padding: 24px 12px;
    text-align: center;
    color: var(--text-secondary);
    font-size: 14px;
}

/* Row: a single record (escrow account or whitelist user). Flex with
 * info on the left and an actions cluster on the right. Wraps on
 * narrow screens so the action buttons drop to a new line instead of
 * being cut off. */
.owner-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 12px 14px;
    margin-bottom: 8px;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 14px;
    box-shadow: var(--shadow-small);
    flex-wrap: wrap;
}
.owner-row__info {
    min-width: 0;
    flex: 1 1 60%;
}
.owner-row__head {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.owner-row__title {
    font-size: 14.5px;
    font-weight: 700;
    color: var(--text-primary);
    letter-spacing: -0.01em;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-all;
}
.owner-row__title--num {
    font-variant-numeric: tabular-nums;
}
.owner-row__sub {
    font-size: 12px;
    color: var(--text-secondary);
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
}
.owner-row__actions {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
    flex-wrap: wrap;
}

/* Small action button used inside .owner-row (Set active / Remove). */
.owner-action-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 7px 12px;
    background: var(--btn-secondary-bg, var(--card-bg));
    border: 1px solid var(--btn-secondary-border, var(--border-color));
    border-radius: 10px;
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
}
.owner-action-btn:hover  { background: var(--btn-secondary-bg-hover, var(--overlay-1)); }
.owner-action-btn:active { transform: scale(0.97); }
.owner-action-btn:disabled {
    opacity: 0.55;
    cursor: not-allowed;
    transform: none;
}
.owner-action-btn--danger {
    color: var(--color-danger);
    border-color: rgba(255,59,48,0.30);
}
.owner-action-btn--danger:hover {
    background: rgba(255,59,48,0.08);
    border-color: rgba(255,59,48,0.45);
}

/* Status pill (e.g. "Active") inside the escrow row. */
.owner-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 99px;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    line-height: 1.4;
}
.owner-badge--active {
    background: var(--color-success);
    color: #fff;
}

/* Target selector inside the broadcast modal — two segmented buttons
 * for "All" vs "Admins". Cleaner than the existing recip-toggle since
 * it doesn't compete with the Stars-withdraw component styles. */
.owner-target {
    display: flex;
    gap: 4px;
    padding: 4px;
    background: var(--overlay-1);
    border-radius: 12px;
}
.owner-target__btn {
    flex: 1 1 0;
    padding: 8px 10px;
    background: transparent;
    border: none;
    border-radius: 8px;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.18s ease, color 0.18s ease;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    line-height: 1.25;
}
.owner-target__btn.active {
    background: var(--card-bg);
    color: var(--text-primary);
    box-shadow: var(--shadow-small);
}
/* Top row of the segmented button — the human label */
.owner-target__label {
    font-size: 13px;
    font-weight: 600;
}
/* Bottom row — small tabular-num pill with the recipient count.
 * Reads slightly muted on inactive buttons; gets the brand-blue tint
 * on the active one so the operator knows which target is selected
 * AND how many will get hit. */
.owner-target__count {
    font-size: 11px;
    font-weight: 700;
    padding: 1px 7px;
    border-radius: 99px;
    background: var(--overlay-2);
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
    min-width: 18px;
    text-align: center;
}
.owner-target__btn.active .owner-target__count {
    background: rgba(10,132,255,0.15);
    color: var(--accent-blue);
}

/* Total line below the segmented buttons — restates the recipient
 * count in plain language ("1 234 получателей") so the operator
 * has zero ambiguity about reach before sending. */
.owner-target__total {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 8px;
    padding: 8px 12px;
    background: var(--overlay-1);
    border-radius: 10px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
}
.owner-target__total .mi { color: var(--accent-blue); }
.owner-target__total [data-bc-total] {
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

/* Broadcast textarea — bigger than a plain input, monospace-ish so
 * HTML tags read clearly. */
.owner-textarea {
    resize: vertical;
    min-height: 120px;
    font-family: inherit;
    line-height: 1.45;
}
.owner-hint {
    margin-top: 6px;
    font-size: 11px;
    color: var(--text-secondary);
    line-height: 1.4;
}

/* Result banner shown after a broadcast send. Green on success, red
 * on failure. */
.owner-result {
    padding: 12px 14px;
    border-radius: 12px;
    font-size: 13px;
    line-height: 1.4;
}
.owner-result--ok {
    background: rgba(52,199,89,0.10);
    border: 1px solid rgba(52,199,89,0.30);
}
.owner-result--error {
    background: rgba(255,59,48,0.10);
    border: 1px solid rgba(255,59,48,0.30);
    color: var(--color-danger);
    font-weight: 700;
}
.owner-result__title {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 700;
    color: var(--color-success);
    margin-bottom: 4px;
}
.owner-result__stats {
    color: var(--text-secondary);
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}
.owner-result__stats b {
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    margin-right: 2px;
}
.owner-result__sep { opacity: 0.5; }

/* ──────────────────────────────────────────────────────────────────
 * RTL (Arabic) overrides for the modals/controls that were missed
 * by the earlier 25-rule set. Audit flagged transaction items
 * (border-left wrong side), seg-control / recip-toggle (segmented
 * pills on wrong side), currency-strip chip stack, net-chip strip,
 * tx-icon-wrapper and tx-cancel-btn (margin-left wrong side),
 * tx-reason-block left-border, language-list rows, leaders splash
 * grids, and balance-callout badge alignment.
 *
 * Strategy: flip with logical properties when possible; for legacy
 * physical-property rules in the main stylesheet, mirror them via
 * [dir="rtl"] overrides here. Keeping these in one block makes it
 * easier to audit & extend later.
 * ────────────────────────────────────────────────────────────────── */
[dir="rtl"] .tx-reason-block {
    /* Left-border accent in LTR → right-border in RTL. */
    border-left:  none !important;
    border-right: 3px solid #dc2626 !important;
    /* The asymmetric padding we used to lean the text away from the
     * accent strip — flip it too. */
    padding: 8px 12px 8px 10px !important;
}
[dir="rtl"] .tx-icon-wrapper {
    /* Icon column was on the left in LTR; flip to the right via
     * margin-inline-* so future spacing tweaks stay direction-aware. */
    margin-right: 0;
    margin-left: 12px;
}
[dir="rtl"] .tx-cancel-btn {
    /* Inline `margin-left:8px` in the JS-generated button — overshadow
     * here to ensure visual alignment on Arabic. */
    margin-left: 0 !important;
    margin-right: 8px !important;
}
[dir="rtl"] .tx-status {
    /* Status badge sits next to the type label; flip its inline margin. */
    margin-left: 0 !important;
    margin-right: 6px !important;
}
[dir="rtl"] .seg-control,
[dir="rtl"] .recip-toggle,
[dir="rtl"] .currency-strip,
[dir="rtl"] .net-chip-strip {
    /* Horizontal pill rows. flex-direction:row-reverse so the first
     * chip appears on the right side (natural reading order in RTL)
     * without us having to re-order DOM. */
    flex-direction: row-reverse;
}
[dir="rtl"] .net-chip,
[dir="rtl"] .cur-chip,
[dir="rtl"] .seg-pill,
[dir="rtl"] .recip-btn {
    /* Chip-internal text alignment so labels read RTL even when the
     * flex container is row-reverse'd. */
    text-align: right;
}
[dir="rtl"] .balance-callout {
    /* The "Available" text + amount block sits on one side, the
     * currency badge on the other — flex-reverse them under RTL. */
    flex-direction: row-reverse;
}
[dir="rtl"] .language-item {
    /* Language picker rows: flag → label in LTR, swap under RTL. */
    flex-direction: row-reverse;
    text-align: right;
}
[dir="rtl"] .connected-wallet,
[dir="rtl"] .wallet-info {
    /* TonConnect connected-wallet block. */
    flex-direction: row-reverse;
}
[dir="rtl"] .info-card .copy-btn,
[dir="rtl"] .info-card .btn-icon {
    /* Copy/edit buttons inside info-cards (USDT addresses, deposit
     * card number, TON address etc.). Were flush-right in LTR; flip
     * to flush-left under RTL via margin-inline. */
    margin-inline-start: 0;
    margin-inline-end: 8px;
}
[dir="rtl"] .order-tag,
[dir="rtl"] .order-status,
[dir="rtl"] .order-header {
    /* Order card header chips. */
    text-align: right;
}
[dir="rtl"] .modal-actions {
    /* Confirm/cancel button pair — already had row-reverse rule in
     * upstream CSS for the safety modal, but the generic
     * `.modal-actions` (used by withdraw-cancel, disconnect-wallet)
     * was missed. */
    flex-direction: row-reverse;
}
[dir="rtl"] .stat-card,
[dir="rtl"] .stat-label,
[dir="rtl"] .stat-value {
    text-align: right;
}
[dir="rtl"] .tx-amount {
    /* Sign + amount (e.g. "+5 TON" / "−10 USDT") naturally render
     * LTR-ish even in RTL bodies — keep the number string LTR but
     * align the cell to the start side. */
    direction: ltr;
    text-align: left;
}
[dir="rtl"] .leaders-grid,
[dir="rtl"] .leaders-row {
    /* Top-3 / runner-up rows on the leaderboard splash. */
    text-align: right;
}
