/* =========================================================================
   iOS-style glass design.
   - Animated, blurred color blobs live behind everything (`.bg-anim`).
   - Every surface (.glass) is a translucent, blurred pane that lets the
     blobs show through, mimicking iOS frosted-glass material.
   - Telegram themeParams are still respected (CSS vars set by app.js),
     but we treat them as accent colors over our own glass palette.
   ========================================================================= */

:root {
  /* Brand palette: royal blue + powder pink. */
  --c-royal:        #3447AA;
  --c-royal-deep:   #1F2A6B;
  --c-royal-night:  #0E1442;
  --c-royal-soft:   #5A6CC9;
  --c-pink:         #FBEAEB;
  --c-pink-warm:    #F6D6DA;
  --c-pink-deep:    #E9B9C0;

  /* Energetic accent (ocean / electric blue) used for the wallet pill,
     active tab and cap-info chip. Dark theme keeps the royal look; light
     theme swaps to a punchier electric blue (see [data-bs-theme="light"]). */
  --c-electric:      #0A84FF;
  --c-electric-deep: #0060DF;

  /* Default = dark theme: royal blue canvas, pink accents/text. */
  --tg-bg:           var(--c-royal-night);
  --tg-text:         var(--c-pink);
  --tg-hint:         rgba(251, 234, 235, 0.72);
  --tg-link:         var(--c-pink);
  --tg-button:       var(--c-royal);
  --tg-button-text:  var(--c-pink);
  --tg-secondary-bg: rgba(251, 234, 235, 0.10);

  /* Glass palette (dark base).
     The "fallback" color is the solid tint shown if backdrop-filter hasn't
     painted yet OR isn't supported. It is a deeper royal tint so the card
     never looks grey on first paint. The translucent overlay on top of the
     fallback is what makes the surface feel frosted once blur kicks in. */
  --glass-fallback:  #1a2566;
  --glass-bg:        rgba(251, 234, 235, 0.08);
  --glass-bg-strong: rgba(251, 234, 235, 0.16);
  --glass-border:    rgba(251, 234, 235, 0.24);
  --glass-shadow:    0 10px 30px rgba(15, 21, 60, 0.40),
                     0 1px 0 rgba(251, 234, 235, 0.18) inset;
  --glass-blur:      30px;

  /* Accent-surface tokens used by the active bottom tab + the header wallet
     pill. These MUST track the selected color preset, so avoid hardcoded blue
     shadows/borders on the components themselves. */
  --accent-surface-from: rgba(52, 71, 170, 0.55);
  --accent-surface-to:   rgba(90, 108, 201, 0.55);
  --accent-surface-fg:   var(--c-pink);
  --accent-surface-shadow: rgba(52, 71, 170, 0.35);
  --accent-surface-shadow-strong: rgba(52, 71, 170, 0.40);
  --accent-surface-inset: rgba(251, 234, 235, 0.25);
  --accent-underline: linear-gradient(135deg, var(--c-pink), var(--c-pink-deep));

  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --tabbar-h:    64px;
  --tabbar-collapsed-h: 28px;
  --navbar-h:    40px;

  /* Telegram fullscreen safe-area insets (px). Synced from JS using
     WebApp.safeAreaInset + contentSafeAreaInset. Fall back to the CSS env()
     values when Telegram doesn't report any. */
  --tg-safe-top:        0px;
  --tg-safe-right:      0px;
  --tg-safe-bottom:     0px;
  --tg-safe-left:       0px;
  --tg-content-top:     0px;
  --tg-content-right:   0px;
  --tg-content-bottom:  0px;
  --tg-content-left:    0px;

  /* Custom sponsor banners keep a fixed height while filling phone-width
     layouts. Larger surfaces cap the banner width instead of stretching it
     into an overly flat strip. */
  --custom-banner-h: 120px;
  --custom-banner-max-w: 640px;
}

[data-bs-theme="light"] {
  /* Light theme: powder-pink canvas, royal-blue accents/text.
     `--tg-bg` is intentionally slightly darker than `--c-pink` so the
     phone status bar (clock, battery) stays legible against the
     Telegram-drawn overlay area at the very top. */
  --tg-bg:           #EEF1F4;
  --tg-text:         var(--c-royal-deep);
  --tg-hint:         rgba(31, 42, 107, 0.62);
  --tg-link:         var(--c-royal);
  --tg-button:       var(--c-royal);
  --tg-button-text:  var(--c-pink);
  --tg-secondary-bg: rgba(52, 71, 170, 0.08);

  --glass-fallback:  #FCFCFD;
  /* Lighter, whiter glass in light mode so cards feel cleaner against the
     now-light-gray page background instead of pink-tinted. */
  --glass-bg:        rgba(246, 214, 218, 0.55);
  --glass-bg-strong: rgba(246, 214, 218, 0.72);
  --glass-border:    rgba(52, 71, 170, 0.22);
  --glass-shadow:    0 12px 32px rgba(52, 71, 170, 0.18),
                     0 1px 0 rgba(255, 255, 255, 0.65) inset;

  /* Punchier electric/ocean blue for the wallet pill + active tab in light
     mode — the royal blue read as flat/low-energy on the pale canvas. */
  --c-electric:      #0A84FF;
  --c-electric-deep: #0A5BD6;

  --accent-surface-from: var(--c-electric);
  --accent-surface-to:   var(--c-electric-deep);
  --accent-surface-fg:   #FFFFFF;
  --accent-surface-shadow: rgba(10, 91, 214, 0.45);
  --accent-surface-shadow-strong: rgba(10, 91, 214, 0.45);
  --accent-surface-inset: rgba(255, 255, 255, 0.35);
  --accent-underline: rgba(255, 255, 255, 0.85);
}

/* Alternate palette preset. `classic` is the current royal/pink setup baked
   into :root above; `neo` switches the app to a cleaner gaming palette with
   deep violet surfaces, soft slate text, and a rose action accent. */
[data-color-preset="neo"] {
  --c-royal:         #7C3AED;
  --c-royal-deep:    #4C1D95;
  --c-royal-night:   #0F0F23;
  --c-royal-soft:    #A78BFA;
  --c-pink:          #E2E8F0;
  --c-pink-warm:     #E2E8F0;
  --c-pink-deep:     #94A3B8;
  --c-electric:      #F43F5E;
  --c-electric-deep: #E11D48;

  --tg-bg:           var(--c-royal-night);
  --tg-text:         var(--c-pink);
  --tg-hint:         rgba(148, 163, 184, 0.82);
  --tg-link:         var(--c-electric);
  --tg-button:       var(--c-royal);
  --tg-button-text:  #FFFFFF;
  --tg-secondary-bg: rgba(255,255,255,0.06);

  --glass-fallback:  #1E1C35;
  --glass-bg:        rgba(226, 232, 240, 0.06);
  --glass-bg-strong: rgba(226, 232, 240, 0.12);
  --glass-border:    rgba(167, 139, 250, 0.24);
  --glass-shadow:    0 10px 30px rgba(10, 10, 30, 0.46),
                     0 1px 0 rgba(226, 232, 240, 0.12) inset;

  --accent-surface-from: rgba(124, 58, 237, 0.58);
  --accent-surface-to:   rgba(167, 139, 250, 0.44);
  --accent-surface-fg:   #FFFFFF;
  --accent-surface-shadow: rgba(124, 58, 237, 0.36);
  --accent-surface-shadow-strong: rgba(124, 58, 237, 0.42);
  --accent-surface-inset: rgba(226, 232, 240, 0.18);
  --accent-underline: linear-gradient(135deg, #FBCFE8, #F43F5E);
}

[data-bs-theme="light"][data-color-preset="neo"] {
  --tg-bg:           #EEF1F4;
  --tg-text:         #312E81;
  --tg-hint:         rgba(71, 85, 105, 0.72);
  --tg-link:         var(--c-royal);
  --tg-button:       var(--c-royal);
  --tg-button-text:  #FFFFFF;
  --tg-secondary-bg: rgba(124, 58, 237, 0.08);

  --glass-fallback:  #FCFCFD;
  --glass-bg:        rgba(255,255,255,0.66);
  --glass-bg-strong: rgba(255,255,255,0.80);
  --glass-border:    rgba(124, 58, 237, 0.18);
  --glass-shadow:    0 12px 32px rgba(124, 58, 237, 0.15),
                     0 1px 0 rgba(255, 255, 255, 0.72) inset;

  --accent-surface-from: rgba(124, 58, 237, 0.94);
  --accent-surface-to:   rgba(167, 139, 250, 0.94);
  --accent-surface-fg:   #FFFFFF;
  --accent-surface-shadow: rgba(124, 58, 237, 0.30);
  --accent-surface-shadow-strong: rgba(124, 58, 237, 0.34);
  --accent-surface-inset: rgba(255, 255, 255, 0.35);
  --accent-underline: rgba(255, 255, 255, 0.88);
}

[data-color-preset="aqua-noir"] {
  --c-royal:         #34E0A1;
  --c-royal-deep:    #139767;
  --c-royal-night:   #000000;
  --c-royal-soft:    #7AF0C6;
  --c-pink:          #E8FFF7;
  --c-pink-warm:     #E8FFF7;
  --c-pink-deep:     #A7E9D1;
  --c-electric:      #34E0A1;
  --c-electric-deep: #16C787;

  --tg-bg:           var(--c-royal-night);
  --tg-text:         var(--c-pink);
  --tg-hint:         rgba(168, 214, 196, 0.82);
  --tg-link:         var(--c-royal);
  --tg-button:       var(--c-royal);
  --tg-button-text:  #03120D;
  --tg-secondary-bg: rgba(52, 224, 161, 0.10);

  --glass-fallback:  #081410;
  --glass-bg:        rgba(52, 224, 161, 0.06);
  --glass-bg-strong: rgba(52, 224, 161, 0.12);
  --glass-border:    rgba(52, 224, 161, 0.24);
  --glass-shadow:    0 10px 30px rgba(0, 0, 0, 0.58),
                     0 1px 0 rgba(232, 255, 247, 0.10) inset;

  --accent-surface-from: rgba(52, 224, 161, 0.26);
  --accent-surface-to:   rgba(22, 199, 135, 0.18);
  --accent-surface-fg:   #E8FFF7;
  --accent-surface-shadow: rgba(52, 224, 161, 0.24);
  --accent-surface-shadow-strong: rgba(52, 224, 161, 0.30);
  --accent-surface-inset: rgba(232, 255, 247, 0.16);
  --accent-underline: linear-gradient(135deg, #E8FFF7, #34E0A1);
}

[data-bs-theme="light"][data-color-preset="aqua-noir"] {
  --tg-bg:           #EEF3F1;
  --tg-text:         #06392A;
  --tg-hint:         rgba(6, 57, 42, 0.62);
  --tg-link:         #139767;
  --tg-button:       #34E0A1;
  --tg-button-text:  #03120D;
  --tg-secondary-bg: rgba(52, 224, 161, 0.10);

  --glass-fallback:  #FCFDFC;
  --glass-bg:        rgba(255,255,255,0.70);
  --glass-bg-strong: rgba(255,255,255,0.84);
  --glass-border:    rgba(52, 224, 161, 0.22);
  --glass-shadow:    0 12px 32px rgba(20, 151, 103, 0.14),
                     0 1px 0 rgba(255, 255, 255, 0.78) inset;

  --accent-surface-from: rgba(52, 224, 161, 0.96);
  --accent-surface-to:   rgba(22, 199, 135, 0.96);
  --accent-surface-fg:   #03120D;
  --accent-surface-shadow: rgba(20, 151, 103, 0.22);
  --accent-surface-shadow-strong: rgba(20, 151, 103, 0.26);
  --accent-surface-inset: rgba(255, 255, 255, 0.28);
  --accent-underline: rgba(3, 18, 13, 0.72);
}

[data-color-preset="sunstone"] {
  --c-royal:         #FCDB32;
  --c-royal-deep:    #C79D12;
  --c-royal-night:   #141D38;
  --c-royal-soft:    #FFE87A;
  --c-pink:          #F8F3D8;
  --c-pink-warm:     #F8F3D8;
  --c-pink-deep:     #C9C2A1;
  --c-electric:      #FCDB32;
  --c-electric-deep: #E7C213;

  --tg-bg:           var(--c-royal-night);
  --tg-text:         var(--c-pink);
  --tg-hint:         rgba(201, 194, 161, 0.82);
  --tg-link:         var(--c-royal);
  --tg-button:       var(--c-royal);
  --tg-button-text:  #141D38;
  --tg-secondary-bg: rgba(252, 219, 50, 0.10);

  --glass-fallback:  #1B2647;
  --glass-bg:        rgba(252, 219, 50, 0.06);
  --glass-bg-strong: rgba(252, 219, 50, 0.12);
  --glass-border:    rgba(252, 219, 50, 0.22);
  --glass-shadow:    0 10px 30px rgba(8, 12, 26, 0.48),
                     0 1px 0 rgba(248, 243, 216, 0.12) inset;

  --accent-surface-from: rgba(252, 219, 50, 0.24);
  --accent-surface-to:   rgba(231, 194, 19, 0.18);
  --accent-surface-fg:   #F8F3D8;
  --accent-surface-shadow: rgba(252, 219, 50, 0.24);
  --accent-surface-shadow-strong: rgba(252, 219, 50, 0.30);
  --accent-surface-inset: rgba(248, 243, 216, 0.18);
  --accent-underline: linear-gradient(135deg, #FFF6B0, #FCDB32);
}

[data-bs-theme="light"][data-color-preset="sunstone"] {
  --tg-bg:           #F1F0EA;
  --tg-text:         #141D38;
  --tg-hint:         rgba(20, 29, 56, 0.64);
  --tg-link:         #8A6500;
  --tg-button:       #FCDB32;
  --tg-button-text:  #141D38;
  --tg-secondary-bg: rgba(252, 219, 50, 0.12);

  --glass-fallback:  #FFFDF8;
  --glass-bg:        rgba(255,255,255,0.66);
  --glass-bg-strong: rgba(255,255,255,0.80);
  --glass-border:    rgba(252, 219, 50, 0.24);
  --glass-shadow:    0 12px 32px rgba(20, 29, 56, 0.14),
                     0 1px 0 rgba(255, 255, 255, 0.78) inset;

  --accent-surface-from: rgba(252, 219, 50, 0.96);
  --accent-surface-to:   rgba(231, 194, 19, 0.96);
  --accent-surface-fg:   #141D38;
  --accent-surface-shadow: rgba(20, 29, 56, 0.18);
  --accent-surface-shadow-strong: rgba(20, 29, 56, 0.22);
  --accent-surface-inset: rgba(255, 255, 255, 0.30);
  --accent-underline: rgba(20, 29, 56, 0.72);
}

[data-color-preset="sulu-fir"] {
  --c-royal:         #9FE870;
  --c-royal-deep:    #5D9E33;
  --c-royal-night:   #163300;
  --c-royal-soft:    #BDF18E;
  --c-pink:          #F1F9E7;
  --c-pink-warm:     #F1F9E7;
  --c-pink-deep:     #C3D8B0;
  --c-electric:      #9FE870;
  --c-electric-deep: #7ECC49;

  --tg-bg:           var(--c-royal-night);
  --tg-text:         var(--c-pink);
  --tg-hint:         rgba(195, 216, 176, 0.82);
  --tg-link:         var(--c-royal);
  --tg-button:       var(--c-royal);
  --tg-button-text:  #163300;
  --tg-secondary-bg: rgba(159, 232, 112, 0.10);

  --glass-fallback:  #1E4410;
  --glass-bg:        rgba(159, 232, 112, 0.06);
  --glass-bg-strong: rgba(159, 232, 112, 0.12);
  --glass-border:    rgba(159, 232, 112, 0.24);
  --glass-shadow:    0 10px 30px rgba(7, 20, 0, 0.50),
                     0 1px 0 rgba(241, 249, 231, 0.12) inset;

  --accent-surface-from: rgba(159, 232, 112, 0.24);
  --accent-surface-to:   rgba(126, 204, 73, 0.18);
  --accent-surface-fg:   #F1F9E7;
  --accent-surface-shadow: rgba(159, 232, 112, 0.24);
  --accent-surface-shadow-strong: rgba(159, 232, 112, 0.30);
  --accent-surface-inset: rgba(241, 249, 231, 0.16);
  --accent-underline: linear-gradient(135deg, #F6FFE8, #9FE870);
}

[data-bs-theme="light"][data-color-preset="sulu-fir"] {
  --tg-bg:           #EEF3EC;
  --tg-text:         #163300;
  --tg-hint:         rgba(22, 51, 0, 0.64);
  --tg-link:         #5D9E33;
  --tg-button:       #9FE870;
  --tg-button-text:  #163300;
  --tg-secondary-bg: rgba(159, 232, 112, 0.12);

  --glass-fallback:  #FBFDF9;
  --glass-bg:        rgba(255,255,255,0.68);
  --glass-bg-strong: rgba(255,255,255,0.82);
  --glass-border:    rgba(159, 232, 112, 0.26);
  --glass-shadow:    0 12px 32px rgba(22, 51, 0, 0.14),
                     0 1px 0 rgba(255, 255, 255, 0.80) inset;

  --accent-surface-from: rgba(159, 232, 112, 0.96);
  --accent-surface-to:   rgba(126, 204, 73, 0.96);
  --accent-surface-fg:   #163300;
  --accent-surface-shadow: rgba(22, 51, 0, 0.18);
  --accent-surface-shadow-strong: rgba(22, 51, 0, 0.22);
  --accent-surface-inset: rgba(255, 255, 255, 0.30);
  --accent-underline: rgba(22, 51, 0, 0.72);
}

* { -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--tg-bg);
  color: var(--tg-text);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
               Roboto, "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

body.tg-body {
  /* Solid preset-driven canvas — no animated layer underneath anymore. */
  background: var(--tg-bg);
  min-height: 100vh;
  /* Bottom padding is kept constant across collapse/expand on purpose: shrinking
     it when the tabbar collapses would reduce scrollHeight and make a
     bottom-scrolled page jump. The collapsed pill is smaller than this reserve,
     so a little extra empty space at the very bottom is harmless. */
  padding-bottom: calc(var(--tabbar-h) + max(var(--safe-bottom), var(--tg-safe-bottom)) + 18px);
}

/* No animated background layer anymore. The app now uses a solid preset-driven
   canvas (`body.tg-body { background: var(--tg-bg) }`) so the glass surfaces
   float above a clean, stable color matched to the active preset. */

/* -------------------------------- Glass --------------------------------- */
.glass {
  position: relative;
  /* 95% opaque tinted glass: strong enough to read clearly while still keeping
     the preset color visible. Backdrop blur still does the frosted work. */
  background: color-mix(in srgb, var(--glass-fallback) 95%, transparent);
  border: 1px solid var(--glass-border);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(180%);
  backdrop-filter:        blur(var(--glass-blur)) saturate(180%);
  box-shadow: var(--glass-shadow);
}
/* Same 95% treatment in light mode. */
[data-bs-theme="light"] .glass:not(.app-header):not(.tabbar) {
  background: color-mix(in srgb, var(--glass-fallback) 95%, transparent);
  border-color: var(--glass-border);
  box-shadow: var(--glass-shadow);
}
[data-bs-theme="light"] .glass:not(.app-header):not(.tabbar)::before {
  display: none;
}
/* Browsers without backdrop-filter get a slightly more saturated fallback. */
@supports not ((-webkit-backdrop-filter: blur(2px)) or (backdrop-filter: blur(2px))) {
  .glass { background: var(--glass-fallback); }
}
/* Specular highlight along the top edge — the iOS giveaway. */
.glass::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background: linear-gradient(180deg,
              rgba(255,255,255,0.35) 0%,
              rgba(255,255,255,0.05) 35%,
              rgba(255,255,255,0) 60%);
  mix-blend-mode: overlay;
  opacity: 0.7;
}

.glass-thin {
  --glass-blur: 34px;
  background: color-mix(in srgb, var(--glass-fallback) 95%, transparent);
}

/* ============================================================
   Unified header — single glass strip housing user identity,
   wallet balances, today's progress bar, and the language menu.
   No second wallet-header block on the Wallet page.
   ============================================================ */
.app-header {
  position: sticky;
  top: 0;
  z-index: 30;
  /* In Telegram fullscreen the WebView extends behind:
       1. the device status bar / notch  -> safeAreaInset.top
       2. Telegram's close + 3-dot buttons -> contentSafeAreaInset.top
     We need padding for BOTH, since contentSafeAreaInset is measured
     INSIDE the safeAreaInset (not from the viewport edge). */
  padding-top: calc(
    max(env(safe-area-inset-top, 0px), var(--tg-safe-top))
    + var(--tg-content-top)
    + 8px
  );
  padding-right: 14px;
  padding-bottom: 10px;
  padding-left: 14px;
  border-left: 0;
  border-right: 0;
  border-top: 0;
  border-radius: 0 0 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.hdr-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 28px;
}
/* Give the avatar + name row more breathing room from the very top edge
   of the header so it doesn't feel pinned against Telegram's controls. */
.hdr-row-top {
  padding-top: 12px;
  padding-bottom: 4px;
  min-height: 40px;
}

/* Accordion toggle — collapses/expands the identity (top) row. Now a normal
   flex item at the far-right end of the persistent bottom row. Transparent
   background in both themes; only the icon/border carry the accent color.
   Minus when expanded, plus when collapsed. */
.hdr-collapse-toggle {
  flex: 0 0 auto;
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 1px solid rgba(52, 71, 170, 0.28);
  border-radius: 8px;
  background: transparent;
  color: var(--c-royal);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.hdr-collapse-toggle:active { background-color: rgba(52, 71, 170, 0.10); }
[data-bs-theme="dark"] .hdr-collapse-toggle {
  color: var(--c-pink);
  border-color: rgba(251, 234, 235, 0.34);
}
[data-bs-theme="dark"] .hdr-collapse-toggle:active {
  background-color: rgba(251, 234, 235, 0.10);
}
/* Icon: default expanded state shows a minus (horizontal stroke only).
   Collapsed state reveals the vertical stroke too, turning it into a plus. */
.hdr-collapse-icon-v {
  opacity: 0;
  transition: opacity 0.22s ease;
}

/* Accordion animation: the identity row collapses smoothly via max-height +
   opacity rather than an instant display:none. rt-status stays put.
   NOTE: min-height must be animated/zeroed too — .hdr-row's 28px and this
   row's own 40px min-height would otherwise pin the header height open. */
.hdr-row-top {
  overflow: hidden;
  min-height: 40px;
  max-height: 80px;
  opacity: 1;
  transition: max-height 0.3s ease, min-height 0.3s ease, opacity 0.25s ease,
              padding-top 0.3s ease, padding-bottom 0.3s ease, margin-bottom 0.3s ease;
}
.app-header.collapsed .hdr-row-top {
  min-height: 0;
  max-height: 0;
  opacity: 0;
  padding-top: 0;
  padding-bottom: 0;
  margin-bottom: -8px;   /* cancel the parent .app-header column gap */
}
.app-header.collapsed .hdr-collapse-icon-v { opacity: 1; }

/* Progress bar + daily-cap alert live side-by-side in the bottom row. On
   narrow phones we stack them vertically; on wider screens they split the
   available width 50/50. */
.hdr-progress-cap {
  display: flex;
  align-items: stretch;
  gap: 10px;
  flex: 1 1 auto;
  min-width: 0;
}
.hdr-progress-cap > .hdr-today { flex: 0 1 24%; min-width: 0; }
.hdr-progress-cap > .hdr-cap-alert { flex: 2 1 66.666%; min-width: 0; margin: 0; }

/* Daily-cap alert — compact chip that pairs with the progress bar. Two
   variants: info (while the user can still earn) and warn (cap reached). */
.hdr-cap-alert {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border-radius: 10px;
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.2;
  border: 1px solid transparent;
}
.hdr-cap-alert .hdr-cap-icon { font-size: 13px; line-height: 1; flex: 0 0 auto; }
.hdr-cap-alert .hdr-cap-text {
  /* Wrap to a second line when there isn't enough width instead of being
     clipped/hidden — matches the desktop behaviour on narrow phones. */
  white-space: normal;
  overflow-wrap: anywhere;
  min-width: 0;
}
.hdr-cap-alert-info {
  background: rgba(80, 160, 255, 0.14);
  border-color: rgba(80, 160, 255, 0.28);
  color: #cfe6ff;
}
.hdr-cap-alert-warn {
  background: rgba(255, 170, 40, 0.16);
  border-color: rgba(255, 170, 40, 0.42);
  color: #ffe6b8;
}
[data-bs-theme="light"] .hdr-cap-alert-info {
  background: rgba(10, 132, 255, 0.14);
  border-color: rgba(10, 132, 255, 0.42);
  color: var(--c-electric-deep);
}
[data-bs-theme="light"] .hdr-cap-alert-warn {
  background: rgba(220, 130, 20, 0.14);
  border-color: rgba(220, 130, 20, 0.36);
  color: #5a3600;
}

/* Header background — soft bluish off-white in light theme so it reads
   as chrome against the light body without being pure gray. */
[data-bs-theme="light"] .app-header {
  background:
    linear-gradient(180deg,
      rgba(226, 234, 247, 0.96),
      rgba(213, 224, 244, 0.90)),
    #DDE6F3;
  border-color: rgba(52, 71, 170, 0.24);
}

/* =========================================================================
   Fullscreen-on-mobile header tweaks.

   When Telegram is in fullscreen on a mobile client, the WebView extends
   behind:
     - the system status bar  -> safeAreaInset (status bar)
     - Telegram's close + 3-dot button row -> contentSafeAreaInset
   The horizontal middle of that button row is empty. We KEEP the normal
   two-row glass header (avatar + name on top, today bar on bottom) and
   float ONLY the wallet stats pill into that gap as a separate
   position:fixed element. So the header itself starts BELOW Telegram's
   button row, while the stats sit between the close button and the menu.
   ========================================================================= */
html[data-tg-mobile="true"][data-tg-fullscreen="true"] .app-header {
  /* Push the visible header below the device status bar + Telegram buttons. */
  padding-top: calc(
    max(env(safe-area-inset-top, 0px), var(--tg-safe-top))
    + var(--tg-content-top, 0px)
    + 8px
  );
}
html[data-tg-mobile="true"][data-tg-fullscreen="true"] .hdr-stats {
  /* Detach from the header layout entirely and park inside the Telegram
     button strip (between close button on the left and 3-dot menu on the
     right). The horizontal padding-left/right of the strip is reported
     via contentSafeAreaInset. */
  position: fixed;
  top: max(env(safe-area-inset-top, 0px), var(--tg-safe-top));
  left:  calc(var(--tg-content-left,  0px) + 8px);
  right: calc(var(--tg-content-right, 0px) + 8px);
  margin: 0 auto;
  width: max-content;
  max-width: calc(100vw - var(--tg-content-left, 0px) - var(--tg-content-right, 0px) - 16px);
  height: var(--tg-content-top, 36px);
  padding: 0 12px;
  font-size: 13px;
  border-radius: 999px;
  z-index: 35;
  /* Visually align centered in the strip. */
  display: inline-flex;
  align-items: center;
}
/* The stats pill is no longer in flow, so the hdr-row-bot should re-center
   around the today widget. */
html[data-tg-mobile="true"][data-tg-fullscreen="true"] .hdr-row-bot {
  justify-content: flex-end;
}

/* --- Top row: user + language --- */
.hdr-user {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.hdr-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--c-royal), var(--c-pink-deep));
  color: var(--c-pink);
  font-size: 14px;
  flex-shrink: 0;
  overflow: hidden;          /* clip <img> to circle */
  border: 1px solid rgba(251, 234, 235, 0.4);
}
.hdr-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hdr-user-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  min-width: 0;
  max-width: 60vw;
}
.hdr-user-text strong {
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hdr-user-text small {
  font-size: 10.5px;
  color: var(--tg-hint);
}

/* Premium Gold subscription badge — shown next to the username in the
   header whenever the user has an active premium subscription. Gold
   gradient with a subtle glow so it's clearly the "premium" affordance. */
.hdr-premium-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  background: linear-gradient(135deg, #F9C846 0%, #F0A500 50%, #C47F00 100%);
  color: #2b1a00;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
  border: 1px solid rgba(255, 220, 120, 0.7);
  box-shadow: 0 0 8px rgba(240, 165, 0, 0.55), inset 0 1px 0 rgba(255,255,255,0.35);
  flex-shrink: 0;
  animation: premium-glow 2.4s ease-in-out infinite;
  text-transform: uppercase;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.hdr-premium-badge:active { transform: scale(0.96); }
.hdr-premium-crown { font-size: 12px; line-height: 1; }
.hdr-premium-text  { line-height: 1; }
@keyframes premium-glow {
  0%, 100% { box-shadow: 0 0 6px rgba(240, 165, 0, 0.40), inset 0 1px 0 rgba(255,255,255,0.35); }
  50%      { box-shadow: 0 0 14px rgba(255, 210, 100, 0.85), inset 0 1px 0 rgba(255,255,255,0.35); }
}

/* --- Premium settings card (Settings tab) --- */
.premium-card { display: flex; flex-direction: column; gap: 10px; }
.premium-card-head {
  display: flex; align-items: center; gap: 10px;
}
.premium-card-crown { font-size: 22px; line-height: 1; }
.premium-card-titles { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.premium-card-status {
  color: var(--muted, #9aa3ad);
  font-size: 12px;
}
.premium-card-body { font-size: 14px; }
.premium-card-countdown {
  display: flex; flex-direction: column; gap: 4px;
  padding: 10px 12px;
  border-radius: 12px;
  background: linear-gradient(135deg, rgba(240,165,0,0.14), rgba(240,165,0,0.06));
  border: 1px solid rgba(240, 165, 0, 0.35);
}
.premium-card-countdown-value {
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.01em;
}
.premium-card-actions { display: flex; justify-content: flex-end; }

/* --- Language menu --- */
.hdr-actions {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 10px;
  background: var(--glass-bg-strong);
  border: 1px solid var(--glass-border);
  color: var(--tg-text);
  font-size: 15px;
  cursor: pointer;
  padding: 0;
}
.icon-btn:hover { background: var(--glass-bg); }
.theme-svg {
  display: block;
}
[data-bs-theme="light"] #theme-toggle {
  background: transparent;
  color: var(--tg-hint);
}
[data-bs-theme="light"] #theme-toggle:hover {
  background: transparent;
  color: var(--tg-text);
}
.fullscreen-toggle {
  display: none;
}
html[data-tg-tablet="true"] .fullscreen-toggle:not(.d-none),
html[data-tg-mobile="false"] .fullscreen-toggle:not(.d-none) {
  display: inline-flex;
}
.fullscreen-icon-min { display: none; }
.fullscreen-toggle.is-fullscreen .fullscreen-icon-max { display: none; }
.fullscreen-toggle.is-fullscreen .fullscreen-icon-min { display: block; }
[data-bs-theme="light"] #fullscreen-toggle {
  background: transparent;
  color: var(--tg-hint);
}
[data-bs-theme="light"] #fullscreen-toggle:hover {
  background: transparent;
  color: var(--tg-text);
}

/* --- Segmented language picker (single-tap to switch) --- */
.lang-seg {
  display: inline-flex;
  align-items: stretch;
  padding: 3px;
  gap: 2px;
  border-radius: 999px;
  background: var(--glass-bg-strong);
  border: 1px solid var(--glass-border);
}
.lang-seg-btn {
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  padding: 4px 10px;
  min-width: 32px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.4px;
  color: var(--tg-hint);
  background: transparent;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.lang-seg-btn:hover { color: var(--tg-text); }
.lang-seg-btn.active {
  background: linear-gradient(135deg, var(--c-royal), var(--c-royal-soft));
  color: var(--c-pink);
  box-shadow: 0 2px 8px rgba(52, 71, 170, 0.35);
}
.lang-seg-btn-fa {
  font-family: "Vazirmatn", -apple-system, BlinkMacSystemFont, "SF Pro Text",
               "Segoe UI", Tahoma, Roboto, sans-serif;
  letter-spacing: 0;
}

/* Store region picker — compact pill (mirrors the language selector) that
   sits inline in the store header next to the refresh button. Each button is
   only as wide as its label. */
.section-head-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
.region-seg {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border-radius: 999px;
  background: var(--glass-bg-strong);
  border: 1px solid var(--glass-border);
}
.region-seg-btn {
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 700;
  color: var(--tg-hint);
  background: transparent;
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s ease, color 0.15s ease;
}
.region-seg-btn:hover { color: var(--tg-text); }
.region-seg-btn.active {
  background: linear-gradient(135deg, var(--c-royal), var(--c-royal-soft));
  color: var(--c-pink);
  box-shadow: 0 2px 8px rgba(52, 71, 170, 0.35);
}

/* Store category chips — filter row right under the store intro. Wraps on
   narrow screens and reuses the app's glass/segment language. */
.store-cats {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 14px;
}
.store-cat-chip {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 6px 12px;
  background: var(--glass-bg-strong);
  color: var(--tg-text);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s ease, color 0.15s ease, transform 0.12s ease;
}
.store-cat-chip:hover { background: var(--glass-bg); }
.store-cat-chip:active { transform: scale(0.97); }
.store-cat-chip.is-active {
  background: linear-gradient(135deg, var(--c-royal), var(--c-royal-soft));
  color: var(--c-pink);
  box-shadow: 0 2px 8px rgba(52, 71, 170, 0.35);
  border-color: transparent;
}

/* --- Bottom row: balances + today bar --- */
.hdr-stats {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 5px 12px;
  border-radius: 999px;
  background: linear-gradient(135deg,
              var(--accent-surface-from),
              var(--accent-surface-to));
  border: 1px solid var(--glass-border);
  color: var(--accent-surface-fg);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.2px;
  box-shadow: 0 4px 12px var(--accent-surface-shadow),
              0 1px 0 var(--accent-surface-inset) inset;
  direction: ltr;            /* numbers stay LTR in RTL locales */
}
/* Light mode (and every color preset) now reuses the semantic accent-surface
   variables instead of hardcoded electric-blue styling. */
[data-bs-theme="light"] .hdr-stats {
  background: linear-gradient(135deg,
              var(--accent-surface-from),
              var(--accent-surface-to));
  border-color: var(--glass-border);
  color: var(--accent-surface-fg);
  box-shadow: 0 6px 16px var(--accent-surface-shadow-strong),
              0 1px 0 var(--accent-surface-inset) inset;
}
[data-bs-theme="light"] .hdr-stats .hdr-sep {
  background: color-mix(in srgb, var(--accent-surface-fg) 50%, transparent);
}
.hdr-stat   { display: inline-flex; align-items: center; gap: 4px; position: relative; }
.hdr-glyph  { font-size: 15px; line-height: 1; }
.hdr-amount { min-width: 1ch; transition: color 0.2s ease; }

/* Real-time connection status. Anchored to the HEADER (not the collapsible
   top row) so it stays visible even when the identity row is collapsed. It
   floats in the header's top padding and never changes the header height.
   Label is always English (not translated); the dot + text recolor per
   WebSocket state. */
.rt-status {
  position: absolute;
  top: calc(
    max(env(safe-area-inset-top, 0px), var(--tg-safe-top))
    + var(--tg-content-top)
    + 8px
  );
  left: 14px;
  transform: translateY(-8px);   /* fixed lift so it clears the progress-bar
                                    text when the header is collapsed (% of the
                                    ~8.5px chip was too small to notice) */
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  pointer-events: none;
  z-index: 2;
}
.rt-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 6px currentColor;
}
/* Telegram Desktop only: nudge the connection status ~15% of the header height
   further down (mobile has no OS status bar to clear, so it doesn't need this). */
html[data-tg-mobile="false"] .rt-status {
  top: calc(
    max(env(safe-area-inset-top, 0px), var(--tg-safe-top))
    + var(--tg-content-top)
    + 8px
    + 8%
  );
}
/* Connecting = amber (pulsing), connected = green, disconnected = red. */
.rt-status-connecting  { color: #ffcc55; }
.rt-status-connecting .rt-dot { animation: rt-pulse 1s ease-in-out infinite; }
.rt-status-connected   { color: #5ff0a6; }
.rt-status-disconnected { color: #ff7676; }
[data-bs-theme="light"] .rt-status-connecting  { color: #c47f00; }
[data-bs-theme="light"] .rt-status-connected   { color: #1a7a3e; }
[data-bs-theme="light"] .rt-status-disconnected { color: #c0392b; }
@keyframes rt-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

/* Big countdown number in the live maintenance pre-warning dialog. */
.maintenance-prewarn-count {
  display: inline-block;
  min-width: 1.4em;
  font-variant-numeric: tabular-nums;
  font-size: 22px;
  font-weight: 800;
}
.maintenance-gear-static { animation: none; }
.hdr-sep {
  width: 1px;
  height: 14px;
  background: rgba(251, 234, 235, 0.35);
}
.coin-bump { animation: coin-bump 0.6s ease; }
@keyframes coin-bump {
  0%   { transform: scale(1);    text-shadow: 0 0 0 rgba(251, 234, 235, 0); }
  40%  { transform: scale(1.45); text-shadow: 0 0 14px rgba(251, 234, 235, 0.95); }
  100% { transform: scale(1); }
}

.hdr-today {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  min-width: 120px;
}
.hdr-today-text {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  color: var(--tg-hint);
  font-weight: 500;
  letter-spacing: 0.2px;
}
.hdr-today-text .sep { opacity: 0.55; margin: 0 1px; }
.hdr-today-label { margin-left: 4px; opacity: 0.7; font-size: 10px; }
/* The header container stays LTR overall (balances, numbers, chips), but the
   FA version of the progress text needs its own ordering: «امروز ۲۰ از ۲۰».
   Use an isolated RTL flex row and reverse the child order visually so the
   label comes first, followed by cap, separator, then earned. */
html[dir="rtl"] .hdr-today-text {
  direction: rtl;
  unicode-bidi: isolate;
  flex-direction: row-reverse;
}
html[dir="rtl"] .hdr-today-label {
  margin-left: 0;
  margin-right: 4px;
}
.hdr-today-bar {
  width: 100%;
  height: 6px;
  border-radius: 3px;
  background: rgba(251, 234, 235, 0.15);
  overflow: hidden;
  position: relative;
}
.hdr-today-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0%;
  background: linear-gradient(90deg, var(--c-royal), var(--c-pink));
  transition: width 0.4s cubic-bezier(.4,0,.2,1);
}


/* ----------------------------- Main layout ------------------------------ */
.app-main {
  position: relative;
  z-index: 1;
  padding: 18px 14px;
  max-width: 640px;
  margin: 0 auto;
  /* Hint the compositor: keep scrolling on the GPU. */
  transform: translateZ(0);
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: contain;
  scroll-behavior: auto;
}

/* Tablet / larger screens (iPad, split-view) — let the cards breathe out
   further so we're not showing a phone-narrow column with huge margins.
   Doesn't apply to Telegram Desktop (`data-tg-mobile="false"`), which has
   its own 360px phone-shaped column. */
@media (min-width: 768px) {
  html[data-tg-mobile="true"] .app-main,
  html:not([data-tg-mobile]) .app-main {
    max-width: 860px;
    padding-left: 24px;
    padding-right: 24px;
  }
  html[data-tg-mobile="true"] .app-header,
  html:not([data-tg-mobile]) .app-header {
    padding-left: 24px;
    padding-right: 24px;
  }
}

/* =========================================================================
   Desktop-Telegram polish.

   On non-mobile clients (Telegram Desktop / macOS / Web) we don't request
   fullscreen — the WebApp lives inside Telegram's own window. The WebApp
   API has no method to resize that window from JS, so we shape our own
   layout to fill whatever window Telegram opens: the column width tracks
   the viewport (min 360, max 920), so a user who enlarges the desktop
   window gets wider header/tabbar/cards instead of a phone-narrow strip.
   ========================================================================= */
html[data-tg-mobile="false"] {
  --phone-w: min(920px, max(360px, calc(100vw - 32px)));
  --phone-h: 720px;
}
html[data-tg-mobile="false"] body.tg-body {
  padding-left:  max(0px, calc((100vw - var(--phone-w)) / 2));
  padding-right: max(0px, calc((100vw - var(--phone-w)) / 2));
  /* Pin the header to the top of the window regardless of height (no vertical
     centering — a growing top padding would otherwise open a gap above the
     header once the host window exceeds --phone-h). */
  padding-top: 0;
  padding-bottom: calc(var(--tabbar-h) + max(var(--safe-bottom), var(--tg-safe-bottom)) + 18px);
}
html[data-tg-mobile="false"] .app-header,
html[data-tg-mobile="false"] .app-main {
  max-width: var(--phone-w);
  margin-left: auto;
  margin-right: auto;
}
/* Cap the visible vertical space of the main scroll area too. */
html[data-tg-mobile="false"] .app-main {
  min-height: calc(var(--phone-h) - var(--tabbar-h) - 80px);
}
/* Fixed-position bars need explicit centering since they're taken out of
   the body padding flow. They stay anchored to the window bottom (no
   vertical centering) so the tabbar sits near the bottom edge at any
   window height. */
html[data-tg-mobile="false"] .tabbar-shell,
html[data-tg-mobile="false"] .toast-stack {
  left: 50%;
  right: auto;
  transform: translateX(-50%);
  width: calc(var(--phone-w) - 24px);
  max-width: calc(var(--phone-w) - 24px);
  margin: 0;
}
html[data-tg-mobile="false"] .tabbar {
  bottom: calc(max(var(--safe-bottom), var(--tg-safe-bottom)) + 8px);
}
html[data-tg-mobile="false"] .toast-stack {
  bottom: calc(var(--tabbar-h) + max(var(--safe-bottom), var(--tg-safe-bottom)) + 20px);
}

/* Telegram Desktop tends to render at a larger base font, which pushes the
   header cap-reset text into ellipsis territory. Pin a smaller root font
   size on desktop so the phone-sized column fits its own labels. */
html[data-tg-mobile="false"] {
  font-size: 14px;
}
html[data-tg-mobile="false"] .hdr-cap-alert {
  font-size: 10.5px;
  padding: 3px 6px;
}
html[data-tg-mobile="false"] .hdr-cap-alert .hdr-cap-text {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  line-height: 1.15;
}

.view { animation: fadein 0.28s ease-out; }
@keyframes fadein {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* ----------------------------- Glass card ------------------------------- */
.glass-card {
  border-radius: 22px;
  overflow: hidden;
  margin-bottom: 16px;
}
.card-inner {
  padding: 22px 20px;
  position: relative;
  z-index: 1;
}

.games-promo-banner {
  position: relative;
  min-height: 96px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: 16px;
  overflow: hidden;
  background:
    radial-gradient(circle at 12% 18%, rgba(255, 238, 67, 0.24), transparent 28%),
    linear-gradient(135deg, #102b1d 0%, #14512b 48%, #0a1b13 100%);
  border: 1px solid rgba(255, 238, 67, 0.42);
  box-shadow: 0 14px 32px rgba(3, 24, 13, 0.36), inset 0 1px 0 rgba(255,255,255,0.16);
  color: #fff6b8;
}
.games-promo-banner::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgba(255,238,67,0.18) 0 1px, transparent 1px 12px),
    linear-gradient(0deg, rgba(255,255,255,0.08) 0 1px, transparent 1px 12px);
  opacity: 0.55;
  pointer-events: none;
}
.games-promo-art,
.games-promo-copy {
  position: relative;
  z-index: 1;
}
.games-promo-art {
  flex: 0 0 88px;
  height: 76px;
}
.games-promo-chip,
.games-promo-ticket {
  position: absolute;
  display: block;
  box-shadow: 0 10px 18px rgba(25, 89, 43, 0.22);
}
.games-promo-chip {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: radial-gradient(circle at 33% 28%, #fff8b2 0 20%, #ffd841 21% 58%, #e2a60b 59% 100%);
  border: 2px solid rgba(135, 87, 0, 0.28);
}
.games-promo-chip::after {
  content: "";
  position: absolute;
  inset: 10px;
  border-radius: 50%;
  border: 2px solid rgba(114, 74, 0, 0.28);
}
.games-promo-chip-a { left: 2px; top: 8px; }
.games-promo-chip-b { left: 26px; top: 28px; transform: scale(0.88); }
.games-promo-ticket {
  right: 0;
  top: 12px;
  width: 46px;
  height: 54px;
  border-radius: 8px;
  transform: rotate(9deg);
  background:
    linear-gradient(135deg, #144f29, #159447),
    repeating-linear-gradient(0deg, transparent 0 7px, rgba(255,255,255,0.24) 7px 8px);
  border: 2px solid rgba(255, 238, 67, 0.9);
}
.games-promo-ticket::before,
.games-promo-ticket::after {
  content: "";
  position: absolute;
  left: 9px;
  right: 9px;
  height: 3px;
  border-radius: 999px;
  background: rgba(255, 238, 67, 0.9);
}
.games-promo-ticket::before { top: 16px; }
.games-promo-ticket::after { top: 28px; }
.games-promo-copy {
  min-width: 0;
  display: flex;
  flex-direction: column;
  text-align: start;
}
.games-promo-copy strong {
  font-size: 20px;
  line-height: 1.35;
  letter-spacing: 0;
  color: #fff6b8;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.34);
}
/* Keep the promo banner's dark-mode look in light mode too. The generic
   [data-bs-theme="light"] .glass override (bg/border/shadow swap + ::before
   off) would otherwise lighten it; re-pin the dark styling here. */
[data-bs-theme="light"] .games-promo-banner.glass:not(.app-header):not(.tabbar) {
  background:
    radial-gradient(circle at 12% 18%, rgba(255, 238, 67, 0.24), transparent 28%),
    linear-gradient(135deg, #102b1d 0%, #14512b 48%, #0a1b13 100%);
  border-color: rgba(255, 238, 67, 0.42);
  box-shadow: 0 14px 32px rgba(3, 24, 13, 0.36), inset 0 1px 0 rgba(255,255,255,0.16);
  color: #fff6b8;
}
[data-bs-theme="light"] .games-promo-banner.glass:not(.app-header):not(.tabbar)::before {
  display: block;
}
@media (max-width: 380px) {
  .games-promo-banner { gap: 10px; padding: 12px; }
  .games-promo-art { flex-basis: 70px; transform: scale(0.86); transform-origin: left center; }
  html[dir="rtl"] .games-promo-art { transform-origin: right center; }
  .games-promo-copy strong { font-size: 17px; }
}

/* Game sound mute toggle — icon-only, pinned bottom-right of a minigame card.
   Grayed out by design, flat monochrome speaker (inline SVG, no emoji). The
   "off" (muted) icon is shown only when .is-muted is set. */
.sound-toggle {
  position: absolute;
  right: 12px;
  bottom: 12px;
  z-index: 3;
  width: 40px;
  height: 40px;
  padding: 8px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
  color: inherit;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0.5;                 /* grayed out by design */
  transition: opacity 0.15s ease, background 0.15s ease;
}
.sound-toggle:hover { opacity: 0.8; }
.sound-toggle:active { transform: scale(0.94); }
.sound-toggle .sound-ico {
  width: 100%;
  height: 100%;
  fill: currentColor;
  opacity: 0.85;               /* flat, muted gray look */
}
/* Show on-icon by default, off-icon only when muted. */
.sound-toggle .sound-ico--off { display: none; }
.sound-toggle.is-muted .sound-ico--on  { display: none; }
.sound-toggle.is-muted .sound-ico--off { display: block; }
.sound-toggle.is-muted { opacity: 0.4; }

/* Reserve room at the bottom of the minigame cards so the corner sound toggle
   never overlaps the centered spin CTA. */
#wheel-card .card-inner,
#slots-card .card-inner { padding-bottom: 30px; }

.section-title {
  margin: 0 0 12px;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: 0.2px;
}

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}
.section-head .section-title { margin: 0; }

.btn-refresh {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  padding: 0;
  border: 1px solid rgba(148, 163, 184, 0.28);
  border-radius: 999px;
  background: rgba(148, 163, 184, 0.08);
  color: var(--tg-hint, #94a3b8);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.btn-refresh:hover { color: var(--tg-text, #e5e7eb); }
/* Keep the icon visible on focus (light theme was rendering the SVG in
 * the same color as the browser's default focus background). Remove the
 * outline for pointer-driven focus but preserve it for keyboard nav. */
.btn-refresh:focus { color: var(--tg-text, #e5e7eb); outline: none; }
.btn-refresh:focus:not(:focus-visible) { outline: none; box-shadow: none; }
.btn-refresh:focus-visible {
  outline: 2px solid rgba(99, 102, 241, 0.55);
  outline-offset: 2px;
}
.btn-refresh:disabled { opacity: 0.5; cursor: default; }
.btn-refresh.is-loading svg { animation: btn-refresh-spin 0.8s linear infinite; }
@keyframes btn-refresh-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.display-title {
  margin: 8px 0 10px;
  font-size: 26px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.2px;
}
.badge-count {
  display: inline-block;
  min-width: 34px;
  padding: 2px 10px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--c-royal), var(--c-pink-deep));
  color: var(--c-pink);
  font-weight: 700;
}
.lead-sub {
  color: var(--tg-text);
  font-size: 18px;
  line-height: 1.4;
  font-weight: 500;
  margin: 0 0 14px;
}
.lead-sub strong {
  font-weight: 700;
  color: var(--tg-text);
}
.muted-line { color: var(--tg-hint); font-size: 14.5px; line-height: 1.45; }

/* On the Earn view specifically, give the copy more weight and presence —
   the card has plenty of vertical room. */
#view-home .lead-sub  { font-size: 20px; margin-bottom: 6px; }
#view-home .muted-line { font-size: 15.5px; }
#view-home #earn-card .card-inner > .muted-line { margin-bottom: 8px !important; }

/* User pill. */
.user-pill {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px 6px 6px;
  border-radius: 999px;
  background: var(--glass-bg-strong);
  border: 1px solid var(--glass-border);
  margin-bottom: 14px;
  max-width: 100%;
}
.user-pill-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--c-royal), var(--c-pink-deep));
  color: var(--c-pink);
  font-size: 14px;
}
.user-pill-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  font-size: 13px;
  text-align: left;
}
.user-pill-text small { color: var(--tg-hint); font-size: 11px; }

/* ----------------------------- CTA button ------------------------------- */
.btn-cta {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 200px;
  padding: 14px 28px;
  border: 1px solid rgba(251, 234, 235, 0.42);
  border-radius: 18px;
  background: linear-gradient(135deg,
              rgba(52, 71, 170, 0.95),
              rgba(90, 108, 201, 0.95));
  color: var(--c-pink);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.2px;
  cursor: pointer;
  overflow: hidden;
  box-shadow:
    0 14px 30px rgba(52, 71, 170, 0.42),
    0 1px 0 rgba(251, 234, 235, 0.45) inset;
  transition: transform 0.12s ease, box-shadow 0.2s ease, opacity 0.2s ease;
}
.btn-cta:hover { transform: translateY(-1px); }
.btn-cta:active { transform: translateY(0); }
.btn-cta:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  box-shadow: none;
}
.btn-cta-shine {
  position: absolute;
  inset: 0;
  background: linear-gradient(120deg,
              transparent 30%,
              rgba(251, 234, 235, 0.50) 50%,
              transparent 70%);
  transform: translateX(-100%);
  animation: shine 3.6s ease-in-out infinite;
}
@keyframes shine {
  0%   { transform: translateX(-100%); }
  60%  { transform: translateX(120%); }
  100% { transform: translateX(120%); }
}

.btn-ghost {
  padding: 8px 16px;
  border-radius: 12px;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  color: var(--tg-text);
  font-size: 13.5px;
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  backdrop-filter:        blur(14px) saturate(160%);
  cursor: pointer;
}
.btn-ghost:hover { background: var(--glass-bg-strong); }

/* ----------------------------- Banners ---------------------------------- */
.glass-banner {
  margin-top: 16px;
  padding: 12px 14px;
  border-radius: 14px;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  color: var(--tg-text);
  font-size: 14px;
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  backdrop-filter:        blur(14px) saturate(160%);
}
.glass-banner.cooldown {
  background: rgba(233, 185, 192, 0.22);
  border-color: rgba(233, 185, 192, 0.55);
}
.glass-banner.reward {
  background: rgba(90, 108, 201, 0.28);
  border-color: rgba(90, 108, 201, 0.55);
}
.glass-banner.danger {
  background: rgba(233, 185, 192, 0.30);
  border-color: rgba(233, 185, 192, 0.65);
  color: var(--c-pink);
}
[data-bs-theme="light"] .glass-banner.danger {
  color: var(--c-royal-deep);
  background: rgba(52, 71, 170, 0.10);
  border-color: rgba(52, 71, 170, 0.30);
}

/* ----------------------------- Progress --------------------------------- */
.glass-progress {
  height: 10px;
  border-radius: 999px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  overflow: hidden;
}
.glass-progress-bar {
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, var(--c-royal), var(--c-pink), var(--c-royal));
  background-size: 200% 100%;
  animation: progress-stripes 1.6s linear infinite;
}
@keyframes progress-stripes {
  0%   { background-position: 0% 50%; }
  100% { background-position: 200% 50%; }
}

/* ----------------------------- History list -----------------------------
   Items intentionally NOT glass — the parent .glass-card already provides
   the frosted surface, so each row is just a flat translucent strip with
   a subtle separator. Keeps the rewards page background identical to
   the home card (no double-blurred panels stacked on top). */
.history-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.history-item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 4px;
  border: 0;
  background: transparent;
  border-bottom: 1px solid var(--glass-border);
}
.history-item:last-child { border-bottom: 0; }
.history-item .reward-text { font-weight: 600; font-size: 14.5px; }
.history-item .reward-meta { color: var(--tg-hint); font-size: 11.5px; }
.history-item .reward-id {
  font-size: 11px;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--glass-bg-strong);
  border: 1px solid var(--glass-border);
  white-space: nowrap;
}

/* -------------------------- Bottom tab bar ------------------------------
   Compact, mobile-style. Sized so 5–6 tabs still fit comfortably on a
   small screen — each item is icon + tiny label, square footprint. */
.tabbar-shell {
  position: fixed;
  left: 10px;
  right: 10px;
  bottom: calc(max(var(--safe-bottom), var(--tg-safe-bottom)) + 8px);
  z-index: 40;
  display: flex;
  justify-content: flex-end;
  align-items: stretch;
  max-width: 560px;
  margin: 0 auto;
}
.tabbar {
  position: relative;
  display: flex;
  align-items: stretch;
  justify-content: flex-end;
  gap: 0;
  width: 100%;
  padding: 4px;
  border-radius: 16px;
  height: var(--tabbar-h);
  overflow: hidden;
  transform-origin: right center;
  transition: width 260ms cubic-bezier(.2,.8,.2,1);
  /* Extra pop so the bar visibly floats above the busy content area. Layered
     on top of the .glass background — a royal accent glow + stronger border
     + lifted shadow. */
  border: 1px solid rgba(90, 108, 201, 0.55);
  background:
    linear-gradient(180deg,
      rgba(52, 71, 170, 0.28),
      rgba(52, 71, 170, 0.16)),
    linear-gradient(var(--glass-bg-strong), var(--glass-bg-strong)),
    var(--glass-fallback);
  box-shadow:
    0 -6px 24px rgba(15, 21, 60, 0.35),
    0 12px 28px rgba(15, 21, 60, 0.35),
    0 1px 0 rgba(251, 234, 235, 0.28) inset;
}
.tabbar-items {
  display: flex;
  align-items: stretch;
  justify-content: space-around;
  flex: 1 0 auto;
  min-width: 0;
  transition: opacity 260ms cubic-bezier(.2,.8,.2,1);
}
.tabbar-collapse-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 31px;
  min-width: 31px;
  height: 100%;
  border: 0;
  border-left: 1px solid rgba(251, 234, 235, 0.14);
  border-radius: 12px;
  background: transparent;
  color: rgba(251, 234, 235, 0.94);
  box-shadow: none;
  font: inherit;
  line-height: 1;
  cursor: pointer;
}
.tabbar-collapse-toggle:active { transform: translateY(1px); }
.tabbar-collapse-icon {
  display: block;
  width: 18px;
  height: 18px;
  transition: transform 220ms cubic-bezier(.2,.8,.2,1);
}
html[data-tabbar-collapsed="true"] .tabbar {
  width: 39px;
}
/* When collapsed, the shell still spans nearly the full viewport width (it's a
   fixed, right-justified flex container), so it would keep intercepting taps
   across the empty strip and block buttons underneath. Drop pointer events on
   the shell and re-enable them on the visible pill only. */
html[data-tabbar-collapsed="true"] .tabbar-shell {
  pointer-events: none;
}
html[data-tabbar-collapsed="true"] .tabbar {
  pointer-events: auto;
}
html[data-tabbar-collapsed="true"] .tabbar-items {
  opacity: 0;
  pointer-events: none;
}
html[data-tabbar-collapsed="true"] .tabbar-collapse-toggle {
  border-left-color: transparent;
}
html[data-tabbar-collapsed="true"] .tabbar-collapse-icon {
  transform: rotate(180deg);
}
[data-bs-theme="light"] .tabbar {
  border-color: rgba(52, 71, 170, 0.24);
  background:
    linear-gradient(180deg,
      rgba(226, 234, 247, 0.96),
      rgba(213, 224, 244, 0.90)),
    #DDE6F3;
  box-shadow:
    0 -6px 22px rgba(52, 71, 170, 0.10),
    0 14px 30px rgba(52, 71, 170, 0.14),
    0 1px 0 rgba(255, 255, 255, 0.75) inset;
}
[data-bs-theme="light"] .tabbar-collapse-toggle {
  border-left-color: rgba(31, 42, 107, 0.10);
  color: rgba(31, 42, 107, 0.92);
}
.tabbar-item {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 6px 4px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: rgba(251, 234, 235, 0.88);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
[data-bs-theme="light"] .tabbar-item {
  color: rgba(31, 42, 107, 0.85);
}
.tabbar-icon {
  width: 24px;
  height: 24px;
  stroke-width: 1.8;
}
.tabbar-label {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  font-weight: 600;
}
.tabbar-item.active {
  color: var(--accent-surface-fg);
  background: linear-gradient(135deg,
              var(--accent-surface-from),
              var(--accent-surface-to));
  box-shadow: 0 6px 18px var(--accent-surface-shadow-strong),
              0 1px 0 var(--accent-surface-inset) inset;
}
.tabbar-item.active .tabbar-icon { stroke: var(--accent-surface-fg); }
.tabbar-item.active::after {
  content: "";
  position: absolute;
  bottom: 2px;
  width: 14px;
  height: 2px;
  border-radius: 2px;
  background: var(--accent-underline);
}
[data-bs-theme="light"] .tabbar-item.active {
  color: var(--accent-surface-fg);
  background: linear-gradient(135deg,
              var(--accent-surface-from),
              var(--accent-surface-to));
  box-shadow: 0 6px 18px var(--accent-surface-shadow-strong),
              0 1px 0 var(--accent-surface-inset) inset;
}
[data-bs-theme="light"] .tabbar-item.active .tabbar-icon { stroke: var(--accent-surface-fg); }
[data-bs-theme="light"] .tabbar-item.active::after {
  background: var(--accent-underline);
}

/* ── Shimmer sweep animation (Games tab only) ─────────────────────────────
   Animated gradient colour sweeps across the icon and label text.
   - Icon: inherits `color` via currentColor; we animate `color` through the
     gradient stops so the stroke shifts in hue L→R over time.
   - Label: background-clip:text gradient sweep for the full colour effect.
   - Icon is 20% larger than the standard 24px → 29px.
   - Store tab keeps the ::before overlay shimmer (width-scoped, unchanged).
   - Active state: standard pink active style; gradient animation continues. */

@keyframes tabbar-shimmer-color {
  0%   { color: rgba(251, 234, 235, 0.88); }
  50%  { color: #a78bfa; }
  100% { color: rgba(251, 234, 235, 0.88); }
}

@keyframes tabbar-shimmer-text {
  0%   { background-position: 100% center; }  /* highlight at right edge */
  100% { background-position:   0% center; }  /* highlight at left edge */
}

/* Games tab: synced R→L gradient sweep on icon (via color) + label text.
   animation-direction:alternate makes it bounce: R→L, L→R, R→L, ... */
.tabbar-item--shimmer[data-view="home"] .tabbar-icon {
  width: 24px;
  height: 24px;
  animation: tabbar-shimmer-color 0.9s linear infinite alternate;
}
.tabbar-item--shimmer[data-view="home"] .tabbar-label {
  background: linear-gradient(
    90deg,
    rgba(251, 234, 235, 0.88) 0%,
    var(--c-pink) 30%,
    #a78bfa 50%,
    var(--c-pink) 70%,
    rgba(251, 234, 235, 0.88) 100%
  );
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: tabbar-shimmer-text 0.9s linear infinite alternate;
}

/* Active: same animation, uninterrupted */
.tabbar-item--shimmer[data-view="home"].active .tabbar-icon {
  animation: tabbar-shimmer-color 0.9s linear infinite alternate;
  stroke: currentColor;
}
.tabbar-item--shimmer[data-view="home"].active .tabbar-label {
  -webkit-text-fill-color: transparent;
}

/* Light mode: use dark navy base colour so icon/text is visible on light tabbar */
[data-bs-theme="light"] .tabbar-item--shimmer[data-view="home"]:not(.active) .tabbar-icon {
  animation: tabbar-shimmer-color-light 0.9s linear infinite alternate;
}
[data-bs-theme="light"] .tabbar-item--shimmer[data-view="home"]:not(.active) .tabbar-label {
  background: linear-gradient(
    90deg,
    rgba(31, 42, 107, 0.85) 0%,
    var(--c-pink-deep) 30%,
    #7c3aed 50%,
    var(--c-pink-deep) 70%,
    rgba(31, 42, 107, 0.85) 100%
  );
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: tabbar-shimmer-text 0.9s linear infinite alternate;
}

@keyframes tabbar-shimmer-color-light {
  0%   { color: rgba(31, 42, 107, 0.85); }
  50%  { color: #7c3aed; }
  100% { color: rgba(31, 42, 107, 0.85); }
}

/* ── Store tab shimmer (::before overlay) ────────────────────────────────*/
@keyframes tabbar-shimmer {
  0%        { background-position: -120% center; }
  40%, 100% { background-position:  220% center; }
}

.tabbar-item--shimmer {
  overflow: hidden;
}

.tabbar-item--shimmer::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    105deg,
    transparent 30%,
    rgba(255, 255, 255, 0.28) 50%,
    transparent 70%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  border-radius: inherit;
  pointer-events: none;
  animation: tabbar-shimmer 3s ease-in-out infinite;
}

/* Games tab doesn't use the ::before overlay */
.tabbar-item--shimmer[data-view="home"]::before { display: none; }
/* Games tab: larger icon may extend slightly; allow it */
.tabbar-item--shimmer[data-view="home"] { overflow: visible; }

/* Store tab: offset so it doesn't flash in sync with games */
.tabbar-item--shimmer[data-view="store"]::before {
  animation-delay: 1.5s;
}

/* Active state: standard dot stays on top */
.tabbar-item--shimmer.active::after { z-index: 1; }

/* iOS WebKit freezes background-position / -webkit-background-clip:text sweeps
   after the first frame, so the shimmer looks stuck. Rather than fight it, we
   simply drop the animations on iOS and show the tabs in their plain resting
   state (data-tg-platform="ios" is set on <html> from the Telegram platform). */
[data-tg-platform="ios"] .tabbar-item--shimmer[data-view="home"] .tabbar-icon,
[data-tg-platform="ios"] .tabbar-item--shimmer[data-view="home"] .tabbar-label,
[data-tg-platform="ios"] .tabbar-item--shimmer[data-view="home"].active .tabbar-icon,
[data-tg-platform="ios"] .tabbar-item--shimmer::before,
[data-tg-platform="ios"] .tabbar-item--shimmer[data-view="store"]::before {
  animation: none;
}
[data-tg-platform="ios"] .tabbar-item--shimmer[data-view="home"] .tabbar-label {
  background: none;
  -webkit-background-clip: border-box;
  background-clip: border-box;
  -webkit-text-fill-color: currentColor;
  color: rgba(251, 234, 235, 0.88);
}
[data-bs-theme="light"][data-tg-platform="ios"] .tabbar-item--shimmer[data-view="home"]:not(.active) .tabbar-label {
  color: rgba(31, 42, 107, 0.85);
}
[data-tg-platform="ios"] .tabbar-item--shimmer::before {
  display: none;
}

/* ========================= Compact small-phone tuning ======================
   On genuinely low-resolution phones, the base proportions feel too roomy.
   Keep normal phones untouched and only compress the high-impact UI pieces:
   header, cards, hero text, tap ball, and tabbar. Trigger on narrow OR short
   mobile screens. */
@media (max-width: 380px), (max-height: 740px) {
  :root { --tabbar-h: 58px; }

  .app-header {
    padding-right: 10px;
    padding-bottom: 8px;
    padding-left: 10px;
    gap: 6px;
    border-radius: 0 0 18px 18px;
  }
  .hdr-row-top {
    padding-top: 8px;
    padding-bottom: 2px;
    min-height: 34px;
  }
  .hdr-avatar { width: 24px; height: 24px; font-size: 12px; }
  .hdr-user-text { max-width: 52vw; }
  .hdr-user-text strong { font-size: 12px; }
  .hdr-user-text small  { font-size: 10px; }
  .hdr-premium-badge { font-size: 10px; padding: 2px 7px; }
  .hdr-stats { gap: 10px; padding: 4px 10px; font-size: 13px; }
  .hdr-progress-cap { gap: 8px; }
  .hdr-cap-alert { padding: 3px 7px; font-size: 10.5px; }

  .glass-card { border-radius: 18px; margin-bottom: 12px; }
  .card-inner { padding: 18px 16px; }
  .section-title { margin-bottom: 10px; font-size: 16px; }
  .display-title { margin: 6px 0 8px; font-size: 23px; }
  .lead-sub { font-size: 16px; margin-bottom: 12px; }
  .muted-line { font-size: 13.5px; }
  #view-home .lead-sub  { font-size: 17px; }
  #view-home .muted-line { font-size: 14px; }

  .btn-cta {
    min-width: 176px;
    padding: 12px 22px;
    border-radius: 16px;
    font-size: 15px;
  }
  .btn-ghost { padding: 7px 14px; font-size: 13px; }

  .ball-stage { height: 224px; margin: 0 0 4px; }
  .ball { width: 176px; height: 176px; }

  .tabbar-shell { left: 6px; right: 6px; }
  .tabbar {
    padding: 3px;
    border-radius: 14px;
  }
  .tabbar-collapse-toggle {
    width: 28px;
    min-width: 28px;
    border-radius: 10px;
  }
  html[data-tabbar-collapsed="true"] .tabbar { width: 34px; }
  .tabbar-item { gap: 2px; padding: 5px 3px; }
  .tabbar-icon,
  .tabbar-item--shimmer[data-view="home"] .tabbar-icon { width: 21px; height: 21px; }
  .tabbar-label { font-size: 11px; }

  .user-pill {
    gap: 8px;
    padding: 5px 10px 5px 5px;
    margin-bottom: 10px;
  }
  .user-pill-avatar { width: 24px; height: 24px; font-size: 12px; }
  .user-pill-text { font-size: 12px; }
  .user-pill-text small { font-size: 10px; }
}

/* Bootstrap d-none compatibility (kept from prior version). */
.d-none { display: none !important; }

/* =========================================================================
   Tap ball, store grid, inventory rows, txns list.
   (Header pill styles now live with the unified header block above.)
   ========================================================================= */

/* ----------------------------- Tap ball --------------------------------- */
.ball-stage {
  position: relative;
  height: 260px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 4px 0 6px;
  perspective: 600px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ball {
  position: relative;
  width: 202px;      /* +20% over 168px */
  height: 202px;
  border-radius: 50%;
  cursor: pointer;
  background:
    radial-gradient(circle at 32% 30%, rgba(251, 234, 235, 0.95), rgba(251, 234, 235, 0.0) 38%),
    radial-gradient(circle at 65% 70%, rgba(31, 42, 107, 0.65), rgba(31, 42, 107, 0) 55%),
    linear-gradient(135deg, var(--c-royal), var(--c-royal-soft));
  border: 1px solid rgba(251, 234, 235, 0.40);
  box-shadow:
    0 18px 38px rgba(14, 20, 66, 0.55),
    0 1px 0 rgba(251, 234, 235, 0.55) inset,
    0 -10px 30px rgba(31, 42, 107, 0.55) inset;
  display: flex;
  align-items: center;
  justify-content: center;
  user-select: none;
  -webkit-user-select: none;
  animation: ball-idle 4.5s ease-in-out infinite;
  transition: transform 0.18s cubic-bezier(.2,.9,.3,1.4);
  outline: none;
}
.ball:focus-visible {
  box-shadow:
    0 18px 38px rgba(14, 20, 66, 0.55),
    0 1px 0 rgba(251, 234, 235, 0.55) inset,
    0 -10px 30px rgba(31, 42, 107, 0.55) inset,
    0 0 0 4px rgba(251, 234, 235, 0.35);
}
.ball-face {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 2px;
  color: var(--c-pink);
  text-shadow: 0 2px 6px rgba(14, 20, 66, 0.55);
}
.ball-shine {
  position: absolute;
  inset: 8px;
  border-radius: 50%;
  background: linear-gradient(135deg,
              rgba(251, 234, 235, 0.55) 0%,
              rgba(251, 234, 235, 0)   45%);
  pointer-events: none;
}
.ball-shadow {
  position: absolute;
  bottom: 18px;
  width: 158px;
  height: 20px;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(0,0,0,0.45), transparent 70%);
  filter: blur(4px);
  animation: shadow-idle 4.5s ease-in-out infinite;
}

.ball.is-bouncing { animation: ball-bounce 0.55s cubic-bezier(.2,.9,.3,1.4); }
.ball.is-busy    { opacity: 0.55; cursor: progress; pointer-events: none; }
.ball.is-disabled { opacity: 0.45; cursor: not-allowed; pointer-events: none; }

.kimo-tap-pad {
  position: absolute;
  right: 1.5%;
  top: 50%;
  z-index: 4;
  width: 86px;
  height: 86px;
  transform: translateY(-50%);
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: inherit;
  filter: drop-shadow(0 12px 16px rgba(14, 20, 66, 0.30));
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  user-select: none;
  -webkit-user-select: none;
}
.kimo-tap-pad::before {
  content: "👋";
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 58px;
  line-height: 1;
  transform: rotate(-10deg);
  text-shadow: 0 5px 12px rgba(14, 20, 66, 0.28);
}
.kimo-tap-pad-label {
  position: relative;
  z-index: 5;
  max-width: 50px;
  margin-top: 62px;
  font-size: 9px;
  font-weight: 900;
  line-height: 1.05;
  letter-spacing: 0;
  text-align: center;
  text-transform: uppercase;
  text-shadow: 0 1px 0 rgba(255,255,255,0.45);
}
html[dir="rtl"] .kimo-tap-pad-label { font-family: "Vazirmatn", sans-serif; }
.kimo-tap-pad-ring {
  position: absolute;
  inset: -8px;
  z-index: 2;
  border-radius: 50%;
  border: 0;
  background:
    radial-gradient(circle,
      rgba(255, 247, 112, 0.42) 0%,
      rgba(255, 238, 74, 0.30) 34%,
      rgba(255, 205, 64, 0.16) 58%,
      rgba(255, 205, 64, 0) 78%);
  filter: blur(0.2px);
}
.kimo-tap-pad:focus-visible {
  outline: 3px solid rgba(251, 234, 235, 0.46);
  outline-offset: 3px;
}
.kimo-tap-pad:active,
.ball-stage.is-pad-tapping .kimo-tap-pad {
  transform: translateY(-50%) rotate(-4deg) scale(0.94);
  filter: drop-shadow(0 8px 12px rgba(14, 20, 66, 0.28)) brightness(1.04);
}
.ball-stage.is-pad-tapping .kimo-tap-pad-ring {
  animation: kimo-hand-slap 0.34s ease-out;
}
.kimo-tap-trail {
  position: absolute;
  right: var(--kimo-trail-right, calc(1.5% + 70px));
  top: 50%;
  z-index: 3;
  width: var(--kimo-trail-width, 116px);
  height: 18px;
  transform: translateY(-50%) scaleX(0);
  transform-origin: right center;
  border-radius: 999px;
  background:
    linear-gradient(90deg, transparent, rgba(251, 234, 235, 0.28), rgba(251, 234, 235, 0.92)),
    linear-gradient(90deg, transparent 0 34%, rgba(255,255,255,0.88) 48%, transparent 62%);
  background-size: auto, 72px 100%;
  filter: drop-shadow(0 0 9px rgba(251, 234, 235, 0.62)) blur(0.15px);
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, rgba(0,0,0,0.18) 8%, #000 20%, #000 100%);
  mask-image: linear-gradient(90deg, transparent 0%, rgba(0,0,0,0.18) 8%, #000 20%, #000 100%);
  opacity: 0;
  pointer-events: none;
}
.kimo-tap-trail::before {
  content: "";
  position: absolute;
  inset: 5px 10px;
  border-radius: 999px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.28), rgba(255,255,255,0.82));
}
.ball-stage.is-pad-tapping .kimo-tap-trail,
.ball-stage.is-trail-flowing .kimo-tap-trail {
  transform: translateY(-50%) scaleX(1);
  opacity: 1;
  animation: kimo-trail-flow 0.28s linear infinite;
}
@keyframes kimo-hand-slap {
  0% { transform: scale(1); }
  45% { transform: scale(0.86) translateY(5px); }
  100% { transform: scale(1); }
}
@keyframes kimo-trail-flow {
  from { background-position: 0 0, 72px 0; }
  to   { background-position: 0 0, 0 0; }
}
@media (max-width: 380px) {
  .kimo-tap-pad {
    right: 1%;
    width: 70px;
    height: 70px;
  }
  .kimo-tap-pad::before { font-size: 48px; }
  .kimo-tap-pad-ring { inset: -7px; }
  .kimo-tap-pad-label { font-size: 8px; max-width: 38px; margin-top: 50px; }
  .kimo-tap-trail { right: calc(1% + 58px); width: 92px; height: 24px; }
}

@keyframes ball-idle {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-8px); }
}
@keyframes shadow-idle {
  0%, 100% { transform: scale(1);   opacity: 0.85; }
  50%      { transform: scale(0.75); opacity: 0.55; }
}
@keyframes ball-bounce {
  0%   { transform: translateY(0)   scale(1, 1); }
  20%  { transform: translateY(-26px) scale(1.05, 0.95); }
  45%  { transform: translateY(-44px) scale(0.95, 1.10); }
  70%  { transform: translateY(0)   scale(1.10, 0.90); }
  88%  { transform: translateY(-6px) scale(1, 1); }
  100% { transform: translateY(0)   scale(1, 1); }
}

/* --------------------------- Ball on fire ------------------------------- */
/* Flame overlay sits behind/around the ball; hidden until #ball.is-on-fire.
   Pure CSS — three flame tongues + a warm glow ring on the ball itself. */
.ball-fire {
  position: absolute;
  left: 50%;
  bottom: 62%;                 /* flames lick up from the top of the ball */
  transform: translateX(-50%);
  width: 120px;
  height: 150px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s ease;
  z-index: 2;
}
.ball.is-on-fire .ball-fire { opacity: 1; }
.ball.is-on-fire {
  border-color: rgba(255, 176, 74, 0.9);
  box-shadow:
    0 18px 38px rgba(14, 20, 66, 0.55),
    0 1px 0 rgba(251, 234, 235, 0.55) inset,
    0 -10px 30px rgba(255, 120, 40, 0.6) inset,
    0 0 26px 6px rgba(255, 140, 40, 0.75),
    0 0 60px 18px rgba(255, 90, 20, 0.45);
}
.ball-fire .flame {
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 44px;
  height: 78px;
  border-radius: 50% 50% 50% 50% / 62% 62% 38% 38%;
  background: radial-gradient(ellipse at 50% 80%,
              #fff2b0 0%, #ffcd4a 28%, #ff8a2a 58%, #ff4d1a 82%, rgba(255,77,26,0) 100%);
  transform-origin: 50% 100%;
  filter: blur(0.4px) drop-shadow(0 -2px 6px rgba(255, 120, 30, 0.7));
  mix-blend-mode: screen;
}
.ball-fire .f1 { margin-left: -22px; animation: flame-flicker 0.42s ease-in-out infinite; }
.ball-fire .f2 { margin-left: -34px; width: 34px; height: 62px; animation: flame-flicker 0.36s ease-in-out infinite 0.12s; }
.ball-fire .f3 { margin-left: 2px;  width: 34px; height: 62px; animation: flame-flicker 0.39s ease-in-out infinite 0.06s; }
@keyframes flame-flicker {
  0%, 100% { transform: translateX(-50%) scaleY(1)    scaleX(1)    skewX(0deg); }
  25%      { transform: translateX(-50%) scaleY(1.18) scaleX(0.92) skewX(-4deg); }
  50%      { transform: translateX(-50%) scaleY(0.92) scaleX(1.06) skewX(3deg); }
  75%      { transform: translateX(-50%) scaleY(1.12) scaleX(0.96) skewX(-2deg); }
}

/* Floating "ON FIRE · 1.5×" badge above the ball while it's lit. */
.ball-fire-badge {
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.4px;
  white-space: nowrap;
  color: #fff;
  background: linear-gradient(135deg, #ff8a2a, #ff3d1a);
  box-shadow: 0 6px 18px rgba(255, 77, 26, 0.55);
  animation: fire-badge-pulse 0.9s ease-in-out infinite;
}
@keyframes fire-badge-pulse {
  0%, 100% { transform: translateX(-50%) scale(1);    }
  50%      { transform: translateX(-50%) scale(1.08); }
}

/* ===================== Kimo Avatar (SVG) =============================== */
/* Reimplementation using an inline SVG for crisp scalable artwork.
   NOTE: the internal token stays "flix" (setting value, CSS classes, body
   class) as a stable identifier — only the user-facing NAME is Kimo.
   The SVG groups have class names the CSS animates based on #ball
   state classes (is-bouncing, is-on-fire). The body.avatar-flix class
   toggles visibility; the original #ball logic remains untouched. */

/* Toggle visibility */
.kimo-img {
  display: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
  /* 10% larger Kimo without changing the ball geometry */
  transform: scale(1.1);
  transform-origin: center bottom;
  opacity: 0;
  transition: opacity 0.5s ease-in-out;
  will-change: opacity;
}
/* The layer currently showing the active pose is fully opaque; the other
   layer sits at 0 opacity, ready to receive the next pose and fade in. */
.kimo-img.is-active { opacity: 1; }
.flix { display: none; width: 100%; height: 100%; }
/* Strongly enforce off-by-default: only show the image when the admin toggle
   sets the body.avatar-flix class. Keep the SVG hidden as a dormant fallback so
   the switch logic can move to raster assets without deleting the old hooks. */
#ball .kimo-img,
#ball .flix { display: none !important; }
body.avatar-flix #ball .kimo-img { display: block !important; }
body.avatar-flix #ball .flix { display: none !important; }

/* Eye-fire group (hook class name kept as flix-hat-fire for compatibility)
   hidden by default at the SVG-group level. */
#ball .flix-hat-fire { display: none !important; opacity: 0; }
/* Only show eye-fire when both avatar is active and ball is on-fire */
body.avatar-flix #ball.is-on-fire .flix-hat-fire { display: block !important; opacity:1; transform-origin: 100px 100px; animation: flix-flame-flicker 0.36s ease-in-out infinite; }

/* Ensure the original ball face shows when in "ball" mode */
body.avatar-ball .ball-face { display: block !important; }

body.avatar-flix .ball-shine,
body.avatar-flix .ball-face { display: none; }
body.avatar-flix .ball-fire { display: none; }
body.avatar-flix .flix { display: block; }
body.avatar-flix .ball { background: none !important; border: none !important; box-shadow: none !important; }

/* Make SVG scale & center inside the ball */
.flix { max-width: 100%; max-height: 100%; }
.flix svg { width: 100%; height: 100%; pointer-events: none; }

/* Base transforms for body and appendages */
.flix-body-g { transform-origin: 100px 168px; transition: transform 0.18s cubic-bezier(.2,.9,.3,1.4); }
.flix-arm-l, .flix-arm-r { transform-origin: 100px 150px; }
.flix-legs { transform-origin: 100px 220px; }

/* Idle subtle breathing */
body.avatar-flix #ball .flx-idle { animation: flx-breathe 4.5s ease-in-out infinite; }
@keyframes flx-breathe { 0%,100%{ transform: translateY(0) } 50%{ transform: translateY(-6px)} }

/* Tap -> laugh: trigger on .is-bouncing */
/* Jump behavior: pupils disappear so the eyes go glossy-white; keep the eye
   whites large/open (don't squint them down to slits). */
body.avatar-flix #ball.is-bouncing .flix-mouth { transform-origin: 100px 184px; animation: flix-mouth-laugh 0.45s ease-in-out; transform: scaleY(1.25) translateY(-6px); }
body.avatar-flix #ball.is-bouncing .flix-tongue { opacity: 0 !important; animation: none !important; }
body.avatar-flix #ball.is-bouncing .flix-pupil-l, body.avatar-flix #ball.is-bouncing .flix-pupil-r { opacity: 0; transition: opacity 0.12s linear; }
body.avatar-flix #ball.is-bouncing .flix-eye-l, body.avatar-flix #ball.is-bouncing .flix-eye-r { transform: scaleY(1); transition: transform 0.08s ease-in-out; }
/* During jump show white eyeball and hide dark pupil */
body.avatar-flix #ball.is-bouncing .flix-eye-white-l, body.avatar-flix #ball.is-bouncing .flix-eye-white-r { opacity: 1; transition: opacity 0.08s linear; }
body.avatar-flix #ball.is-bouncing .flix-arm-l { animation: flix-arm-tap-l 0.45s ease-in-out; }
body.avatar-flix #ball.is-bouncing .flix-arm-r { animation: flix-arm-tap-r 0.45s ease-in-out; }

@keyframes flix-mouth-laugh { 0%{ transform: scaleY(1) } 40%{ transform: scaleY(1.35) } 70%{ transform: scaleY(0.9) } 100%{ transform: scaleY(1)} }
@keyframes flix-tongue-pop { 0%{ opacity:0; transform: translateY(-2px) scaleY(0.6)} 40%{ opacity:1; transform: translateY(0) scaleY(1)} 100%{ opacity:1 } }
@keyframes flix-eye-squint { 0%{ transform: scaleY(1)} 45%{ transform: scaleY(0.45)} 100%{ transform: scaleY(1)} }
@keyframes flix-arm-tap-l { 0%{ transform: rotate(0deg)} 50%{ transform: rotate(28deg)} 100%{ transform: rotate(0deg)} }
@keyframes flix-arm-tap-r { 0%{ transform: rotate(0deg)} 50%{ transform: rotate(-28deg)} 100%{ transform: rotate(0deg)} }

/* On-fire state: eye flames + heavier laugh */
body.avatar-flix #ball.is-on-fire .flix-hat-fire { opacity:0; transition: opacity 0.18s ease; }
/* When on fire, reveal eye flames */
body.avatar-flix #ball.is-on-fire .flix-hat-fire { opacity:1; transform-origin: 100px 100px; animation: flix-flame-flicker 0.36s ease-in-out infinite; }
body.avatar-flix #ball.is-on-fire .flix-mouth { animation: flix-mouth-heavy 0.28s ease-in-out infinite; }
body.avatar-flix #ball.is-on-fire .flix-tongue { animation: flix-tongue-pop 0.28s ease-in-out infinite alternate; opacity: 1; }
body.avatar-flix #ball.is-on-fire .flix-body-g { animation: flix-body-shake 0.32s ease-in-out infinite; }
body.avatar-flix #ball.is-on-fire .flix-arm-l { animation: flix-arm-wave-l 0.6s ease-in-out infinite; }
body.avatar-flix #ball.is-on-fire .flix-arm-r { animation: flix-arm-wave-r 0.6s ease-in-out infinite; }

@keyframes flix-flame-flicker { 0%,100%{ transform: translateY(0) scaleY(1)} 50%{ transform: translateY(-3px) scaleY(1.08)} }
@keyframes flix-mouth-heavy { 0%,100%{ transform: scaleY(1)} 50%{ transform: scaleY(1.45) } }
@keyframes flix-body-shake { 0%,100%{ transform: translateX(0) } 25%{ transform: translateX(-4px) } 75%{ transform: translateX(4px) } }
@keyframes flix-arm-wave-l { 0%,100%{ transform: rotate(0)} 50%{ transform: rotate(-18deg)} }
@keyframes flix-arm-wave-r { 0%,100%{ transform: rotate(0)} 50%{ transform: rotate(18deg)} }

/* Accessibility: reduce motion respects prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
  .flx-idle, .flix * { animation: none !important; }
  .kimo-img { transition: none !important; }
}

/* ----------------------------- Wallet ----------------------------------- */

/* ----------------------------- Wallet ----------------------------------- */
/* The wallet page no longer carries a balance header — balances live in
   the unified app header at the top of every page. */

.txn-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.txn-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 4px;
  border-bottom: 1px solid var(--glass-border);
}
.txn-item:last-child { border-bottom: 0; }
.txn-left  { min-width: 0; flex: 1; }
.txn-memo  { font-weight: 600; font-size: 14px; }
.txn-meta  { color: var(--tg-hint); font-size: 11.5px; }
.txn-amount {
  font-weight: 700;
  font-size: 15px;
  white-space: nowrap;
}
.txn-amount.is-credit { color: #b8f1d4; }
.txn-amount.is-debit  { color: var(--c-pink-deep); }
[data-bs-theme="light"] .txn-amount.is-credit { color: #1f7a4a; }
[data-bs-theme="light"] .txn-amount.is-debit  { color: #a8475a; }

/* ------------------------------ Store ----------------------------------- */
.store-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
}

@media (min-width: 486px) {
  .store-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 648px) {
  .store-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
.store-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 16px 12px 14px;
  border-radius: 16px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  backdrop-filter:        blur(14px) saturate(160%);
  transition: transform 0.15s ease, box-shadow 0.2s ease;
  overflow: hidden;
}
.store-card:hover { transform: translateY(-2px); }
/* Sponsored (paid placement) card — visually distinct from the coin-priced
 * cards: a warm gradient wash + green accent border (pharmacy brand cue) so it
 * reads as an ad, not a buyable item. */
.store-card.is-sponsored {
  background:
    linear-gradient(135deg, rgba(30, 168, 60, 0.16), rgba(232, 38, 43, 0.12)),
    var(--glass-bg);
  border-color: rgba(30, 168, 60, 0.55);
}
/* Top-right SPONSORED badge (always visually top-right, both LTR and RTL). */
.store-sponsored-badge {
  position: absolute;
  top: 0;
  right: 0;
  padding: 3px 8px;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: #fff;
  background: rgba(30, 168, 60, 0.92);
  border-top-right-radius: 16px;
  border-bottom-left-radius: 6px;
  pointer-events: none;
  z-index: 3;
}
html[dir="rtl"] .store-sponsored-badge {
  left: auto;
  right: 0;
}
/* Buy button that opens the merchant site (no coin cost). Reuses .store-buy
 * layout but with a green accent and normal link cursor/decoration. */
.store-buy.store-buy-link {
  background: linear-gradient(135deg,
              rgba(30, 168, 60, 0.95),
              rgba(22, 140, 52, 0.95));
  color: #fff;
  text-decoration: none;
}
/* Diagonal discount ribbon on top-right of a card. Sits inside the card
 * (which is `overflow: hidden` above) so the diagonal edges get cropped by
 * the card's rounded corners. LTR by design — the ribbon stays visually
 * anchored to the top-right corner regardless of the page direction. */
.store-ribbon {
  position: absolute;
  top: 0;
  right: 0;
  width: 82px;
  height: 82px;
  pointer-events: none;
  z-index: 3;
  overflow: hidden;
}
.store-ribbon-inner {
  position: absolute;
  display: block;
  top: 12px;
  right: -30px;
  width: 110px;
  padding: 3px 0;
  transform: rotate(45deg);
  background: linear-gradient(135deg, #ff5a8c 0%, #ff2f6a 60%, #d5145a 100%);
  color: #fff;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.4px;
  text-align: center;
  text-transform: uppercase;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.22);
  direction: ltr;
  unicode-bidi: isolate;
}
.store-emoji {
  font-size: 36px;
  line-height: 1;
  margin-bottom: 8px;
  filter: drop-shadow(0 4px 8px rgba(14, 20, 66, 0.45));
}
.store-logo-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 40px;
}
.store-logo {
  height: 40px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  border-radius: 8px;
}
.store-name {
  font-weight: 600;
  font-size: 14px;
  margin-bottom: 4px;
}
.store-desc {
  color: var(--tg-hint);
  font-size: 11.5px;
  line-height: 1.3;
  margin-bottom: 12px;
  min-height: 30px;
}
.store-buy {
  width: 100%;
  margin-top: auto;   /* pin to bottom so buttons line up across cards */
  padding: 8px 10px;
  border: 1px solid rgba(251, 234, 235, 0.42);
  border-radius: 12px;
  background: linear-gradient(135deg,
              rgba(52, 71, 170, 0.95),
              rgba(90, 108, 201, 0.95));
  color: var(--c-pink);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
}
.store-buy:disabled { opacity: 0.5; cursor: not-allowed; }
.store-buy .price { font-weight: 700; }
.store-buy .cost-list {
  font-weight: 500;
  opacity: 0.65;
  text-decoration: line-through;
  margin-right: 4px;
}
[dir="rtl"] .store-buy .cost-list { margin-right: 0; margin-left: 4px; }
.store-payout {
  margin: -4px 0 10px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--c-pink-deep);
}
.store-notice {
  margin: 0 0 10px;
  padding: 8px 10px;
  border-radius: 10px;
  font-size: 11.5px;
  line-height: 1.35;
  background: rgba(255, 200, 60, 0.12);
  border: 1px solid rgba(255, 200, 60, 0.35);
  color: var(--tg-text);
}
.store-info {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0 0 10px;
  padding: 8px 10px;
  border-radius: 10px;
  font-size: 11.5px;
  line-height: 1.35;
  background: rgba(120, 180, 255, 0.12);
  border: 1px solid rgba(120, 180, 255, 0.35);
  color: var(--tg-text);
}
.store-info-icon {
  flex: 0 0 auto;
  font-size: 14px;
  line-height: 1.1;
}
.store-info-text {
  flex: 1 1 auto;
  min-width: 0;
}
.store-warn {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0 0 10px;
  padding: 8px 10px;
  border-radius: 10px;
  font-size: 11.5px;
  line-height: 1.35;
  background: rgba(255, 200, 60, 0.12);
  border: 1px solid rgba(255, 200, 60, 0.42);
  color: var(--tg-text);
}
.store-warn-icon {
  flex: 0 0 auto;
  font-size: 14px;
  line-height: 1.1;
}
.store-warn-text {
  flex: 1 1 auto;
  min-width: 0;
}
.store-sold-today {
  margin: 0 0 10px;
  padding: 8px 10px;
  border-radius: 10px;
  font-size: 11.5px;
  line-height: 1.35;
  background: rgba(120, 180, 255, 0.12);
  border: 1px solid rgba(120, 180, 255, 0.35);
  color: var(--tg-text);
}
.store-card.is-sold-today {
  opacity: 0.82;
}
.store-card.is-sold-today .store-buy {
  cursor: not-allowed;
}
/* Out-of-stock treatment: separate ribbon color (blue-grey) so it doesn't
 * clash with the discount ribbon, and a compact "back in stock soon" notice
 * above the disabled buy button. When both a discount and out-of-stock apply
 * the OOS ribbon takes precedence by being layered on top (later in DOM). */
.store-ribbon-oos .store-ribbon-inner {
  background: linear-gradient(135deg, #6b8db3 0%, #4a6a92 60%, #34547a 100%);
}
.store-oos-notice {
  background: rgba(120, 130, 150, 0.14);
  border-color: rgba(120, 130, 150, 0.38);
}
.store-card.is-out-of-stock {
  opacity: 0.82;
}
.store-card.is-out-of-stock .store-buy {
  cursor: not-allowed;
}
.store-countdown {
  margin: 0 0 8px;
  padding: 6px 10px;
  border-radius: 10px;
  font-size: 11.5px;
  font-weight: 600;
  text-align: center;
  color: var(--c-pink-deep);
  background: rgba(255, 90, 140, 0.10);
  border: 1px solid rgba(255, 90, 140, 0.30);
}
[data-bs-theme="light"] .store-countdown {
  color: #7a1030;
  background: rgba(200, 30, 54, 0.10);
  border-color: rgba(200, 30, 54, 0.35);
}
.store-countdown-v {
  font-variant-numeric: tabular-nums;
  display: inline-block;
}
.store-qty-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 0 0 10px;
}
.store-qty-label {
  font-size: 11.5px;
  color: var(--tg-hint);
  font-weight: 600;
}
.store-qty {
  width: 72px;
  padding: 6px 8px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.06);
  color: var(--tg-text);
  font-size: 13px;
  font-weight: 600;
  text-align: center;
}
.store-qty:focus {
  outline: none;
  border-color: var(--c-pink-deep);
  background: rgba(255, 255, 255, 0.09);
}
html[data-bs-theme="light"] .store-qty {
  background: rgba(0, 0, 0, 0.04);
  border-color: rgba(0, 0, 0, 0.12);
}
.store-qty-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: center;
}
.store-qty-btn {
  min-width: 30px;
  height: 30px;
  padding: 0 8px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.06);
  color: var(--tg-text);
  font-size: 16px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  user-select: none;
}
.store-qty-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.store-qty-max {
  height: 30px;
  padding: 0 10px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.10);
  color: var(--tg-text);
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  user-select: none;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.store-qty-max:disabled { opacity: 0.4; cursor: not-allowed; }
html[data-bs-theme="light"] .store-qty-btn,
html[data-bs-theme="light"] .store-qty-max {
  background: rgba(0, 0, 0, 0.04);
  border-color: rgba(0, 0, 0, 0.12);
}
.confirm-warn {
  margin-top: 12px;
  padding: 8px 10px;
  border-radius: 10px;
  font-size: 12px;
  line-height: 1.4;
  background: rgba(255, 200, 60, 0.12);
  border: 1px solid rgba(255, 200, 60, 0.35);
}
.inv-sent {
  margin-top: 4px;
  font-size: 11.5px;
  color: var(--tg-hint);
}

/* ---------------------------- Inventory --------------------------------- */
.inventory-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.inv-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 4px;
  border-bottom: 1px solid var(--glass-border);
}
.inv-item:last-child { border-bottom: 0; }
.inv-emoji { font-size: 28px; line-height: 1; }
.inv-logo-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
}
.inv-logo {
  width: 40px;
  height: 40px;
  object-fit: contain;
  border-radius: 8px;
}
.inv-text  { flex: 1; min-width: 0; }
.inv-name  { font-weight: 600; font-size: 14px; }
.inv-pending-badge,
.inv-delivered-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 8px;
  border-radius: 9px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2px;
  vertical-align: middle;
}
.inv-pending-badge {
  background: rgba(255, 193, 7, 0.18);
  color: #ffb020;
  border: 1px solid rgba(255, 193, 7, 0.35);
}
.inv-delivered-badge {
  background: rgba(46, 204, 113, 0.18);
  color: #29b371;
  border: 1px solid rgba(46, 204, 113, 0.35);
}
html[data-bs-theme="light"] .inv-pending-badge {
  background: rgba(255, 193, 7, 0.25);
  color: #a06600;
}
html[data-bs-theme="light"] .inv-delivered-badge {
  background: rgba(46, 204, 113, 0.22);
  color: #1e8a52;
}
[dir="rtl"] .inv-pending-badge,
[dir="rtl"] .inv-delivered-badge { margin-left: 0; margin-right: 6px; }
.inv-pending-notice {
  margin-top: 4px;
  font-size: 11.5px;
  color: var(--tg-hint);
}
.inv-meta  { color: var(--tg-hint); font-size: 11.5px; }
.inv-code  {
  margin-top: 4px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  letter-spacing: 1px;
  padding: 3px 8px;
  display: inline-block;
  border-radius: 8px;
  background: var(--glass-bg-strong);
  border: 1px solid var(--glass-border);
}
.inv-action {
  padding: 7px 12px;
  border-radius: 10px;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg-strong);
  color: var(--tg-text);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.inv-action.primary {
  background: linear-gradient(135deg,
              rgba(52, 71, 170, 0.95),
              rgba(90, 108, 201, 0.95));
  color: var(--c-pink);
  border-color: rgba(251, 234, 235, 0.4);
}
.inv-action:disabled { opacity: 0.55; cursor: default; }

.inv-creds {
  margin-top: 6px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 100%;
}
.inv-cred-row {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.inv-cred-label {
  color: var(--tg-hint);
  font-size: 11.5px;
  font-weight: 600;
  min-width: 62px;
}
.inv-cred-value {
  flex: 1;
  min-width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  letter-spacing: 0.5px;
  padding: 3px 8px;
  border-radius: 8px;
  background: var(--glass-bg-strong);
  border: 1px solid var(--glass-border);
  overflow-wrap: anywhere;
  word-break: break-all;
}
.inv-cred-copy {
  padding: 3px 10px;
  border-radius: 8px;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg-strong);
  color: var(--tg-text);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.inv-cred-copy:active { opacity: 0.7; }

/* ============================================================
   Fly-glyph animation — a small emoji travels from the ball
   into the corresponding header pill stat. Used for taps + coins.
   ============================================================ */
#fly-layer {
  position: fixed;
  inset: 0;
  z-index: 80;
  pointer-events: none;
}
.fly-glyph {
  position: absolute;
  top: 0; left: 0;
  transform: translate(-50%, -50%);
  font-size: 30px;
  line-height: 1;
  filter: drop-shadow(0 6px 14px rgba(14, 20, 66, 0.55));
  animation: fly-to-pill 0.8s cubic-bezier(.4,0,.2,1) forwards;
  will-change: transform, opacity;
}
.fly-coin  { color: gold; }
.fly-tap   { color: var(--c-pink); }
@keyframes fly-to-pill {
  0%   { transform: translate(-50%, -50%)                                   scale(1.1) rotate(0deg);    opacity: 1; }
  35%  { transform: translate(calc(-50% + var(--dx) * 0.35), calc(-50% + var(--dy) * 0.35 - 30px)) scale(1.35) rotate(-25deg); opacity: 1; }
  80%  { transform: translate(calc(-50% + var(--dx) * 0.95), calc(-50% + var(--dy) * 0.95))     scale(0.75) rotate(15deg);  opacity: 1; }
  100% { transform: translate(calc(-50% + var(--dx)),        calc(-50% + var(--dy)))            scale(0.4)  rotate(0deg);   opacity: 0; }
}

/* ============================================================
   Toast stack — stacked, auto-hiding, dismissable notifications
   ============================================================ */
.toast-stack {
  position: fixed;
  left: 12px;
  right: 12px;
  /* Sit just above the tab bar. */
  bottom: calc(var(--tabbar-h) + max(var(--safe-bottom), var(--tg-safe-bottom)) + 20px);
  z-index: 7000;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
  max-width: 520px;
  margin: 0 auto;
}
.toast-item {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 14px;
  background:
    linear-gradient(var(--glass-bg-strong), var(--glass-bg-strong)),
    var(--glass-fallback);
  border: 1px solid var(--glass-border);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  backdrop-filter:        blur(18px) saturate(160%);
  box-shadow: 0 10px 24px rgba(15, 21, 60, 0.4);
  color: var(--tg-text);
  font-size: 13px;
  line-height: 1.35;
  animation: toast-in 0.28s cubic-bezier(.2,.9,.3,1.2);
  position: relative;
  overflow: hidden;
  /* Drag-to-dismiss support — JS sets --tx + --opacity inline while dragging. */
  transform: translateX(var(--tx, 0));
  opacity: var(--opacity, 1);
  touch-action: pan-y;
}
.toast-item.toast-dragging { transition: none; cursor: grabbing; }
.toast-item.toast-snapback { transition: transform 0.22s ease, opacity 0.22s ease; }
.toast-item.toast-out      { animation: toast-out 0.25s ease forwards; }
.toast-item.toast-fly-out  {
  transition: transform 0.25s ease, opacity 0.25s ease;
  pointer-events: none;
}
.toast-item .toast-icon {
  flex-shrink: 0;
  font-size: 16px;
  line-height: 1.2;
  margin-top: 1px;
}
.toast-item .toast-msg {
  flex: 1;
  min-width: 0;
  word-wrap: break-word;
}
.toast-item .toast-close {
  flex-shrink: 0;
  background: transparent;
  border: 0;
  color: inherit;
  opacity: 0.7;
  font-size: 18px;
  line-height: 1;
  padding: 0 4px;
  cursor: pointer;
  margin: -2px -4px 0 0;
}
.toast-item .toast-close:hover { opacity: 1; }
.toast-item.toast-no-close .toast-close { display: none; }
.toast-item .toast-bar {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  background: linear-gradient(90deg, rgba(255,255,255,0.85), rgba(255,255,255,0.4));
  animation: toast-bar linear forwards;
  opacity: 0.85;
}

/* --- Colored variants ---
   Each kind gets its own translucent colored layer over the glass fallback
   plus a matching tinted border + icon. The base colors are tuned for both
   dark and light themes. */
.toast-item.toast-success {
  background:
    linear-gradient(rgba(34, 158, 96, 0.62), rgba(34, 158, 96, 0.62)),
    #0f3a26;
  border-color: rgba(120, 235, 175, 0.55);
  color: #f0fff7;
}
.toast-item.toast-success .toast-icon { color: #c6ffd9; }

.toast-item.toast-error {
  background:
    linear-gradient(rgba(200, 50, 70, 0.65), rgba(200, 50, 70, 0.65)),
    #4a0d1a;
  border-color: rgba(255, 150, 165, 0.6);
  color: #fff0f3;
}
.toast-item.toast-error .toast-icon { color: #ffd8df; }

.toast-item.toast-warn {
  background:
    linear-gradient(rgba(214, 145, 35, 0.62), rgba(214, 145, 35, 0.62)),
    #4a2f08;
  border-color: rgba(255, 210, 130, 0.55);
  color: #fff7e6;
}
.toast-item.toast-warn .toast-icon { color: #ffe9b8; }

.toast-item.toast-info {
  background:
    linear-gradient(rgba(52, 71, 170, 0.65), rgba(52, 71, 170, 0.65)),
    #1F2A6B;
  border-color: rgba(251, 234, 235, 0.45);
  color: var(--c-pink);
}
.toast-item.toast-info .toast-icon { color: var(--c-pink); }

/* Light theme — soften the colors so they don't read as neon on pink. */
[data-bs-theme="light"] .toast-item.toast-success {
  background:
    linear-gradient(rgba(190, 240, 210, 0.85), rgba(190, 240, 210, 0.85)),
    #d6f3e1;
  border-color: rgba(46, 138, 92, 0.45);
  color: #134029;
}
[data-bs-theme="light"] .toast-item.toast-success .toast-icon { color: #1d6c43; }
[data-bs-theme="light"] .toast-item.toast-error {
  background:
    linear-gradient(rgba(252, 210, 215, 0.85), rgba(252, 210, 215, 0.85)),
    #fbe2e6;
  border-color: rgba(180, 50, 70, 0.45);
  color: #5e1320;
}
[data-bs-theme="light"] .toast-item.toast-error .toast-icon { color: #8a1a2d; }
[data-bs-theme="light"] .toast-item.toast-warn {
  background:
    linear-gradient(rgba(254, 230, 180, 0.9), rgba(254, 230, 180, 0.9)),
    #fef0d8;
  border-color: rgba(170, 110, 30, 0.45);
  color: #4a2a08;
}
[data-bs-theme="light"] .toast-item.toast-warn .toast-icon { color: #7a4d14; }
[data-bs-theme="light"] .toast-item.toast-info {
  background:
    linear-gradient(rgba(218, 224, 250, 0.9), rgba(218, 224, 250, 0.9)),
    #e7eaf9;
  border-color: rgba(52, 71, 170, 0.35);
  color: var(--c-royal-deep);
}
[data-bs-theme="light"] .toast-item.toast-info .toast-icon { color: var(--c-royal); }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(20px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0)    scale(1);    }
}
@keyframes toast-out {
  to { opacity: 0; transform: translateY(8px) scale(0.96); }
}
@keyframes toast-bar { from { width: 100%; } to { width: 0%; } }

[dir="rtl"] .toast-item .toast-bar { left: auto; right: 0; }
[dir="rtl"] .toast-item .toast-close { margin: -2px 0 0 -4px; }

/* ============================================================
   Multi-language polish — Persian font + RTL tweaks
   ============================================================ */
html[lang="fa"], html[lang="fa"] body {
  font-family: "Vazirmatn", -apple-system, BlinkMacSystemFont, "SF Pro Text",
               "Segoe UI", Tahoma, Roboto, sans-serif;
}
/* RTL polish */
[dir="rtl"] .txn-item       { text-align: right; }
[dir="rtl"] .inv-item       { text-align: right; }
[dir="rtl"] .display-title  { text-align: center; }


/* ============================================================
   Confirm dialog (reusable) + consent gate + consent status row
   ============================================================ */

/* Confirm modal — small centered glass card, dimmed backdrop. */
.confirm-root {
  position: fixed;
  inset: 0;
  z-index: 9010;
  background: rgba(4, 8, 30, 0.72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  animation: fade-in 0.18s ease;
}
.confirm-root.d-none { display: none !important; }
.confirm-card {
  width: 100%;
  max-width: 360px;
  padding: 18px 18px 14px;
  border-radius: 18px;
  text-align: center;
  animation: confirm-pop 0.22s cubic-bezier(.2,.9,.3,1.2);
}
@keyframes confirm-pop {
  from { opacity: 0; transform: translateY(8px) scale(0.96); }
  to   { opacity: 1; transform: none; }
}
.confirm-title {
  margin: 0 0 8px;
  font-size: 17px;
  font-weight: 700;
}
.confirm-body {
  font-size: 14px;
  color: var(--tg-text);
  margin: 0 0 16px;
  line-height: 1.4;
}
.confirm-body strong { font-weight: 700; }
.confirm-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
}
.confirm-actions .btn-ghost,
.confirm-actions .btn-cta-sm {
  flex: 1;
}
.btn-cta-sm {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 9px 14px;
  border-radius: 12px;
  border: 1px solid rgba(251, 234, 235, 0.42);
  background: linear-gradient(135deg, var(--c-royal), var(--c-royal-soft));
  color: var(--c-pink);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.2px;
  cursor: pointer;
}
.btn-cta-sm.danger {
  background: linear-gradient(135deg, #c83246, #a8243a);
  border-color: rgba(255, 200, 210, 0.55);
}
/* Loading state: hide the label with visibility (keeps its box, so the button
   width is preserved) and overlay a centered spinner. Used while a rewarded ad
   is being requested so we don't need a "loading ad" toast. */
.btn-cta-sm.is-loading { position: relative; pointer-events: none; }
.btn-cta-sm.is-loading > * { visibility: hidden; }
.btn-cta-sm.is-loading::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: btn-cta-spin 0.7s linear infinite;
}
@keyframes btn-cta-spin { to { transform: rotate(360deg); } }

/* Small ghost/outline button — same footprint as .btn-cta-sm but a subtle
   translucent fill. Used for secondary actions (word hint, "Play with a
   friend", "Cancel invite") so they visually match the primary CTA sizing. */
.btn-ghost-sm {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 9px 14px;
  border-radius: 12px;
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.16));
  background: var(--glass-bg, rgba(255, 255, 255, 0.06));
  color: inherit;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.2px;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.btn-ghost-sm:hover { background: var(--glass-bg-strong, rgba(255, 255, 255, 0.12)); }
.btn-ghost-sm:disabled { opacity: 0.55; cursor: not-allowed; }
[data-bs-theme="light"] .btn-ghost-sm {
  border-color: rgba(0, 0, 0, 0.14);
  background: rgba(0, 0, 0, 0.05);
}
[data-bs-theme="light"] .btn-ghost-sm:hover { background: rgba(0, 0, 0, 0.09); }

/* ============================================================
   Ad hint overlay — pre-ad warning (Adsgram full-screen ads).
   80%-opacity dark scrim, big readable text, curved arrow(s)
   pointing at the native close button / ad skip button.
   ============================================================ */
.ad-hint-root {
  position: fixed;
  inset: 0;
  z-index: 7030;              /* above focused minigames and app modal overlays */
  background: rgba(3, 6, 24, 0.95);   /* 95% opacity as requested */
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 22px;
  animation: fade-in 0.18s ease;
}
.ad-hint-root.d-none { display: none !important; }

/* Arrows sit level with the BOTTOM of the orange maintenance header strip
   (≈ safe-area-inset-top + 17px: 2px top pad + ~13px text + 2px bottom pad).
   Yellow (app-close ✕ warning) points LEFT, pinned 20px from the left edge.
   Green (ad skip button) points RIGHT, pinned 10px from the right edge and
   nudged a further 10px down. */
.ad-hint-arrow {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 47px);
  width: 120px;
  height: 120px;
  pointer-events: none;
  animation: ad-hint-arrow-bob 1.1s ease-in-out infinite;
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.5));
}
.ad-hint-arrow-close {
  left: 90px;
  top: calc(env(safe-area-inset-top, 0px) + 77px);
}
.ad-hint-arrow-skip  {
  right: 35px;
  top: calc(env(safe-area-inset-top, 0px) + 117px);
}
.ad-hint-arrow.d-none { display: none !important; }
@keyframes ad-hint-arrow-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-8px); }
}

.ad-hint-card {
  width: 100%;
  max-width: 400px;
  padding: 26px 22px 22px;
  border-radius: 20px;
  text-align: center;
  background: linear-gradient(160deg, #16205a, #0d1440);
  border: 1px solid rgba(255, 214, 10, 0.45);
  box-shadow: 0 18px 46px rgba(0, 0, 0, 0.55);
  animation: confirm-pop 0.24s cubic-bezier(.2,.9,.3,1.2);
}
.ad-hint-emoji {
  font-size: 52px;
  line-height: 1;
  margin-bottom: 10px;
}
.ad-hint-title {
  margin: 0 0 14px;
  font-size: 24px;
  font-weight: 800;
  color: #fff;
  line-height: 1.25;
}
.ad-hint-body {
  font-size: 19px;
  line-height: 1.5;
  color: #eef1ff;
  margin: 0 0 14px;
}
.ad-hint-body strong { color: #ffd60a; font-weight: 800; }
.ad-hint-skip-body strong { color: #4ade80; }
.ad-hint-dontshow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  font-size: 17px;
  color: #cfd6ff;
  margin: 6px 0 18px;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
.ad-hint-dontshow input {
  width: 22px;
  height: 22px;
  accent-color: #ffd60a;
  cursor: pointer;
}
.ad-hint-ok {
  width: 100%;
  font-size: 20px;
  font-weight: 800;
  padding: 14px 18px;
}

/* Consent gate icon. */
.consent-icon {
  font-size: 44px;
  line-height: 1;
  margin: 4px 0 8px;
  filter: drop-shadow(0 6px 14px rgba(14, 20, 66, 0.5));
}

/* Consent status row in Wallet view. */
.consent-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 12px;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  margin-bottom: 14px;
}
.consent-status-text {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  min-width: 0;
}
.consent-status-text strong { font-size: 13.5px; }
.consent-status-text small  { color: var(--tg-hint); font-size: 11.5px; }

/* ============================================================
   Fuel pipe — vertical "water" gauge next to the tap ball.

   The pipe drains 1 unit per tap. When it empties the ball goes
   into a 2-minute cool-down and the pipe refills slowly. A small
   "2m" / "1m" label below the pipe shows the remaining time.
   The actual fill % is controlled by --fuel (0..1) set from JS.
   ============================================================ */
/* ============================================================
   Fuel pipe — vertical water gauge next to the tap ball.

   Layout:
     .fuel-pipe        : positioning wrapper next to the ball
     .fuel-pipe-bg     : the empty casing (translucent navy)
     .fuel-water       : the colored fluid column. Its HEIGHT tracks
                         --fuel (0..1). Width is constant. Colors come
                         from a 3-band linear-gradient anchored to the
                         pipe height (red bottom 30% / amber 30% / green 40%)
                         so the visible color of a given physical point in
                         the pipe stays the same regardless of fill.
     .fuel-pipe-shadow : casing border + inset highlights painted on TOP
                         of the water so the rim always reads cleanly
   Wave:
     The top edge of .fuel-water is carved by an SVG `mask-image` that
     contains a sine-wave path. The mask is anchored to the top of the
     water column (mask-position: 0 0), and its horizontal position
     is animated to make the wave scroll.
   --pipe-h: inner height of the casing (used by --fuel math)
   --fuel-band-red / --fuel-band-amber / --fuel-band-green: band stops
   ============================================================ */
.fuel-pipe {
  --fuel: 1;
  --pipe-h: 84%;                                 /* 100% - 6% top - 10% bottom */
  /* Refined band palette — picked to read as a smooth slate-to-living-green
     ramp rather than a crayon traffic-light. */
  --fuel-band-red-1:   #6f1521;   /* deep oxblood, very bottom */
  --fuel-band-red-2:   #b13245;   /* warmer wine, top of red band */
  --fuel-band-amber-1: #b67226;   /* burnt sienna */
  --fuel-band-amber-2: #d9a23b;   /* honeyed amber */
  --fuel-band-green-1: #3e8c5e;   /* sage-green */
  --fuel-band-green-2: #6dcf8a;   /* fresh leaf */

  position: absolute;
  right: 8%;
  top: 0; bottom: 0;
  width: 32px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
[dir="rtl"] .fuel-pipe { right: auto; left: 8%; }

.fuel-pipe-bg {
  position: absolute;
  top: 6%;
  bottom: 10%;
  left: 50%;
  transform: translateX(-50%);
  width: 22px;
  border-radius: 12px;
  background:
    linear-gradient(180deg,
      rgba(251, 234, 235, 0.06) 0%,
      rgba(14, 20, 66, 0.55)    100%);
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.45),
    inset 0 -2px 6px rgba(251, 234, 235, 0.08);
  overflow: hidden;
}

.fuel-water {
  position: absolute;
  bottom: 10%;
  left: 50%;
  transform: translateX(-50%);
  width: 22px;
  height: calc(var(--pipe-h) * var(--fuel));
  border-bottom-left-radius: 12px;
  border-bottom-right-radius: 12px;
  pointer-events: none;
  /* Solid fresh-leaf green — matches the top of the previous gradient. */
  background: var(--fuel-band-green-2);
  /* Mask the top edge with a wavy line that scrolls horizontally. The
     mask SVG is a 60×16 viewbox with a sine wave at the top — anything
     above the wave is transparent, below is opaque. */
  -webkit-mask-image:
    linear-gradient(black, black),                  /* the body of the column */
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 16' preserveAspectRatio='none'><path d='M0,10 C10,3 20,17 30,10 S50,3 60,10 L60,16 L0,16 Z' fill='black'/></svg>");
          mask-image:
    linear-gradient(black, black),
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 16' preserveAspectRatio='none'><path d='M0,10 C10,3 20,17 30,10 S50,3 60,10 L60,16 L0,16 Z' fill='black'/></svg>");
  -webkit-mask-repeat: no-repeat, repeat-x;
          mask-repeat: no-repeat, repeat-x;
  /* Body covers everything below 10px so the wave reads as the surface. */
  -webkit-mask-size: 100% calc(100% - 10px), 60px 16px;
          mask-size: 100% calc(100% - 10px), 60px 16px;
  -webkit-mask-position: 0 10px, 0 0;
          mask-position: 0 10px, 0 0;
  -webkit-mask-composite: source-over;
          mask-composite: add;
  animation: fuel-wave-scroll 3s linear infinite;
  transition: height 0.4s cubic-bezier(.4,0,.2,1);
}
/* Subtle inner highlight + bottom shadow ON the water for depth. */
.fuel-water::after {
  content: "";
  position: absolute;
  inset: 0;
  border-bottom-left-radius: 12px;
  border-bottom-right-radius: 12px;
  box-shadow:
    inset 0 -3px 8px rgba(0, 0, 0, 0.35),
    inset 0  2px 2px rgba(255, 255, 255, 0.18);
  pointer-events: none;
}

/* Casing rim + outer shadow painted on top so the wave can't poke past
   the pipe's rounded border. */
.fuel-pipe-shadow {
  position: absolute;
  top: 6%;
  bottom: 10%;
  left: 50%;
  transform: translateX(-50%);
  width: 22px;
  border-radius: 12px;
  border: 1px solid rgba(251, 234, 235, 0.30);
  box-shadow: 0 6px 18px rgba(14, 20, 66, 0.35);
  pointer-events: none;
}

/* The wave scrolls horizontally one tile per cycle. */
@keyframes fuel-wave-scroll {
  from { -webkit-mask-position: 0 10px,  0px  0; mask-position: 0 10px,  0px  0; }
  to   { -webkit-mask-position: 0 10px, -60px 0; mask-position: 0 10px, -60px 0; }
}

/* Countdown label below the pipe. */
.fuel-countdown {
  position: absolute;
  bottom: -22px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: var(--tg-text);
  text-shadow: 0 1px 2px rgba(14, 20, 66, 0.55);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  min-width: 4ch;
  text-align: center;
}

/* While cool-down is active dim the ball without removing the layout. */
/* Cool-down: make Kimo look exhausted — droopy half-open eyes, a tired open/
   close frown, and slumped posture. Keep the face anchored in place; don't
   translate it upward. */
.ball.is-cooling { opacity: 0.65; cursor: not-allowed; pointer-events: none; }
/* Catching-breath: same ambient float as normal, just ~20% faster
   (4.5s -> 3.6s) while cooling down so Kimo visibly pants a little faster.
   Re-declare the full shorthand so only the speed differs from the base. */
.ball.is-cooling { animation: ball-idle 3.6s ease-in-out infinite; }
body.avatar-flix #ball.is-cooling .flix-body-g { transform: translateY(6px) scaleY(0.98); filter: brightness(0.85) saturate(0.8); }
body.avatar-flix #ball.is-cooling .flix-eye-l, body.avatar-flix #ball.is-cooling .flix-eye-r { transform: scaleY(0.55) translateY(6px); }
body.avatar-flix #ball.is-cooling .flix-eye-white-l, body.avatar-flix #ball.is-cooling .flix-eye-white-r { opacity: 0; }
body.avatar-flix #ball.is-cooling .flix-pupil-l, body.avatar-flix #ball.is-cooling .flix-pupil-r { opacity: 1; }
body.avatar-flix #ball.is-cooling .flix-mouth { opacity: 0; animation: none !important; }
body.avatar-flix #ball.is-cooling .flix-lip { opacity: 0; }
body.avatar-flix #ball.is-cooling .flix-mouth-frown { opacity: 1; animation: flix-mouth-tired 0.95s ease-in-out infinite; }
body.avatar-flix #ball.is-cooling .flix-lip-frown { opacity: 1; }
body.avatar-flix #ball.is-cooling .flix-tongue { opacity: 0 !important; animation: none !important; }
body.avatar-flix #ball.is-cooling .flix-arm-l, body.avatar-flix #ball.is-cooling .flix-arm-r { transform: rotate(8deg); opacity: 0.7; }

@keyframes flix-mouth-tired {
  0%,100% { transform: scaleY(0.82); }
  50%     { transform: scaleY(1.12); }
}
/* During cool-down the JS only nudges --fuel every 10% so the column
   "steps up" rather than creeping. Use a fast snap transition so each
   step pops in instead of crawling for 12s. */
.fuel-pipe.is-cooling .fuel-water { transition: height 0.45s cubic-bezier(.4,0,.2,1); }

/* Bypass-cooldown button — shown below the ball during the 2-minute break. */
.bypass-row {
  margin: 14px auto 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.bypass-row.d-none { display: none !important; }
#btn-bypass-cooldown {
  padding: 10px 18px;
  font-size: 13.5px;
  font-weight: 700;
  border-radius: 14px;
  border: 1px solid rgba(251, 234, 235, 0.42);
  background: linear-gradient(135deg, var(--c-royal), var(--c-royal-soft));
  color: var(--c-pink);
  letter-spacing: 0.2px;
  cursor: pointer;
  box-shadow: 0 6px 16px rgba(52, 71, 170, 0.35);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
#btn-bypass-cooldown:hover { filter: brightness(1.05); }
#btn-bypass-cooldown:disabled { opacity: 0.55; cursor: progress; }
/* Note: the 🎬 glyph now lives in the i18n label text (cooldown.bypass,
 * wheel.watchAd, slots.watchAd) — the earlier ::before rules doubled it up. */
#btn-wheel-ad:disabled,
#btn-slots-ad:disabled,
#btn-word-ad:disabled { opacity: 0.55; cursor: progress; }

/* ============================================================
   Task ad card (Adsgram <adsgram-task>)
   ============================================================ */

/* Minigame task card — flat bordered box, no glass/backdrop-filter.
   Looks like an info panel / notice board rather than a game card.
   Dark: dark-tinted border, near-opaque dark bg.
   Light: clean white card with a light border. */
#adsgram-minigame-card {
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 14px;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}
#adsgram-minigame-card::before { background: none; }

[data-bs-theme="light"] #adsgram-minigame-card {
  background: rgba(255,255,255,0.72);
  border-color: rgba(0,0,0,0.09);
}

/* Description text: slightly brighter than default muted so it's readable
   on the low-contrast background. */
#adsgram-minigame-card .muted-line {
  color: var(--tg-text, #e2e8f0);
  opacity: 0.75;
  font-size: 13.5px;
  margin-bottom: 22px;
}
[data-bs-theme="light"] #adsgram-minigame-card .muted-line {
  color: var(--tg-hint);
  opacity: 1;
}

/* Follow the app language direction; JS also writes dir on the Adsgram web
   component and its slotted buttons when rendering/localizing. */
#adsgram-minigame-slot,
#task-ad-slot {
  direction: inherit;
}

.task-ad-slot {
  /* Style hooks recognised by Adsgram's web component. */
  --adsgram-task-font-size: 14px;
  --adsgram-task-icon-size: 36px;
  --adsgram-task-button-width: 56px;
  min-height: 56px;
  display: block;
}
.task-ad-slot adsgram-task {
  width: 100%;
  display: block;
}
.task-ad-slot .task__reward { font-weight: 700; }
/* Slight breathing room between the task icon/image and the title+reward text
   column. The icon uses logical margin-inline-end so it works in RTL (fa) too. */
.task-ad-slot .task__icon,
.task-ad-slot .task__img,
.task-ad-slot .task__logo {
  margin-inline-end: 10px;
}
.task-ad-slot .task__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 6px 14px;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--c-royal), var(--c-royal-soft));
  color: var(--c-pink);
  font-weight: 700;
  border: 1px solid rgba(251, 234, 235, 0.42);
  cursor: pointer;
}
.task-ad-slot .task__button_claim { background: linear-gradient(135deg, #2a9268, #1d6c43); }
.task-ad-slot .task__button_done  { background: rgba(120, 130, 150, 0.45); cursor: default; }

.missions-slot {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.missions-heading {
  font-size: 13px;
  font-weight: 800;
  color: var(--tg-text);
}
.mission-task {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 12px;
  align-items: center;
  min-height: 68px;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg-strong);
  color: var(--tg-text);
}
.mission-task.is-disabled {
  opacity: 0.56;
  filter: grayscale(0.2);
}
.mission-task-title {
  font-size: 14px;
  font-weight: 800;
  line-height: 1.25;
  color: var(--tg-text);
}
.mission-task-desc,
.mission-task-status,
.mission-task-reset {
  margin-top: 3px;
  font-size: 12px;
  color: var(--tg-hint);
  line-height: 1.35;
}
.mission-task-reset {
  font-weight: 650;
  color: var(--tg-text);
}
.mission-task-window {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  max-width: 100%;
  margin-top: 7px;
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px solid var(--glass-border);
  background: var(--tg-secondary-bg);
  color: var(--tg-text);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.25;
}
.mission-task-window.is-warning {
  border-color: rgba(245, 158, 11, 0.58);
  background: rgba(245, 158, 11, 0.18);
  color: #f59e0b;
}
.mission-task-window.is-ended {
  border-color: rgba(239, 68, 68, 0.62);
  background: rgba(239, 68, 68, 0.17);
  color: #ef4444;
}
.mission-task-window.is-future {
  border-color: rgba(59, 130, 246, 0.48);
  background: rgba(59, 130, 246, 0.14);
  color: var(--tg-text);
}
.mission-task-progress {
  height: 5px;
  margin-top: 7px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--tg-secondary-bg);
}
.mission-task-progress span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, #31c48d, #f6c453);
}
.mission-task-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 7px;
  min-width: 74px;
}
.mission-task .task__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  padding: 4px 10px;
  border-radius: 8px;
  font-size: 12px;
  background: linear-gradient(135deg, var(--c-royal), var(--c-royal-soft));
  color: var(--c-pink);
  font-weight: 800;
  border: 1px solid rgba(251, 234, 235, 0.42);
  box-shadow: 0 8px 18px rgba(0,0,0,0.18);
  cursor: pointer;
}
.mission-task .mission-claim:not(:disabled) {
  background: linear-gradient(135deg, #2fb879, #16864c);
  color: #fff;
  border-color: rgba(218, 255, 235, 0.58);
}
.mission-task-side .task__button[disabled] {
  background: rgba(120, 130, 150, 0.45);
  color: rgba(255,255,255,0.7);
  box-shadow: none;
  opacity: 0.72;
  cursor: default;
}
.missions-ad-divider {
  height: 1px;
  margin: 12px 0;
  background: var(--glass-border);
}

@media (max-width: 420px) {
  .mission-task {
    grid-template-columns: 1fr;
  }
  .mission-task-side {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    width: 100%;
  }
}


/* ------------------------- About tab ---------------------------------- */
.about-title {
  position: relative;
  display: inline-block;
  padding-bottom: 14px;
  margin: 6px 0 8px;
  font-size: 22px;
  letter-spacing: 0.02em;
  font-weight: 700;
}
.about-title::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 9px;
  border-radius: 2px;
  background: linear-gradient(
    to bottom,
    #000000 0, #000000 3px,
    #DD0000 3px, #DD0000 6px,
    #FFCE00 6px, #FFCE00 9px
  );
}

/* =========================================================================
   Mini-games (Earn tab): Prize Wheel + Slot Machine
   ========================================================================= */

.minigame-title {
  margin: 4px 0 4px;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.2px;
}
#wheel-card .minigame-title { margin-bottom: 18px; }
.minigame-hint { margin: 0 0 10px; }
.minigame-spin-btn { margin-top: 10px; }

/* -------------------------------------------------------------------------
   Attention-grabbing "activate the game" buttons.

   The four game-arm buttons (.minigame-spin-btn: wheel / slots / word /
   backgammon) and the cooldown-bypass button switch from the royal-blue CTA
   to a red gradient — electric pink in dark mode, warm red in light mode —
   and gently zoom in/out so the user notices the call to action.
   ------------------------------------------------------------------------- */
.minigame-spin-btn,
#btn-bypass-cooldown {
  background: linear-gradient(135deg, #FF2D78, #D6006A);   /* electric pink (dark) */
  border-color: rgba(255, 200, 220, 0.55);
  box-shadow: 0 6px 18px rgba(214, 0, 106, 0.45);
  animation: game-cta-pulse 1.8s ease-in-out infinite;
  transform-origin: center;
  will-change: transform;
}
[data-bs-theme="light"] .minigame-spin-btn,
[data-bs-theme="light"] #btn-bypass-cooldown {
  background: linear-gradient(135deg, #F4442E, #C42618);   /* warm red (light) */
  border-color: rgba(255, 210, 200, 0.65);
  box-shadow: 0 6px 18px rgba(196, 38, 24, 0.40);
}
/* Pause the zoom while the ad is loading (disabled) so it reads as "busy". */
.minigame-spin-btn:disabled,
#btn-bypass-cooldown:disabled {
  animation: none;
  transform: none;
}
@keyframes game-cta-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.045); }
}
@media (prefers-reduced-motion: reduce) {
  .minigame-spin-btn,
  #btn-bypass-cooldown { animation: none; }
}

/* Title row: h3 + "powered by AI" badge sit side-by-side, centred. */
.word-title-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 4px 0 4px;
}
.word-title-row .minigame-title { margin: 0; }

/* "powered by AI" badge next to the word-game title. Small gradient pill,
 * caseless & compact so it doesn't compete with the h3. */
.word-ai-badge {
  display: inline-block;
  margin: 0;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: #fff;
  background: linear-gradient(90deg, #7c5cff 0%, #5aa8ff 55%, #34d1a0 100%);
  box-shadow: 0 1px 4px rgba(90, 108, 255, 0.35);
  user-select: none;
}

/* ---- Prize Wheel ---- */
.wheel-stage {
  position: relative;
  width: 220px;
  height: 220px;
  margin: 6px auto 4px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.wheel-pointer {
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 12px solid transparent;
  border-right: 12px solid transparent;
  border-top: 18px solid #FFB300;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,0.4));
  z-index: 3;
}
.prize-wheel {
  position: relative;
  width: 220px;
  height: 220px;
  border-radius: 50%;
  cursor: pointer;
  outline: none;
  user-select: none;
  -webkit-user-select: none;
  box-shadow:
    0 10px 24px rgba(0, 0, 0, 0.45),
    0 0 0 4px #4A3208 inset,
    0 0 0 8px #E8B846 inset;
}
.prize-wheel:focus-visible {
  box-shadow:
    0 10px 24px rgba(0, 0, 0, 0.45),
    0 0 0 4px #4A3208 inset,
    0 0 0 8px #E8B846 inset,
    0 0 0 4px rgba(255, 210, 90, 0.45);
}
.wheel-disc {
  position: absolute;
  inset: 8px;
  border-radius: 50%;
  /* 12 alternating wedges (30° each): deep bronze/brown for prize wedges (so
     the gold coin/tap emoji pop) and pale cream-gold for empty wedges. Prize
     wedges sit at even indices (0,2,4,6,8,10); the empty wedges at odd indices
     are visually quieter. */
  background: conic-gradient(
    #6B4A11 0deg 30deg,
    #F7E39B 30deg 60deg,
    #6B4A11 60deg 90deg,
    #F7E39B 90deg 120deg,
    #6B4A11 120deg 150deg,
    #F7E39B 150deg 180deg,
    #6B4A11 180deg 210deg,
    #F7E39B 210deg 240deg,
    #6B4A11 240deg 270deg,
    #F7E39B 270deg 300deg,
    #6B4A11 300deg 330deg,
    #F7E39B 330deg 360deg
  );
  transition: transform 5.4s cubic-bezier(0.17, 0.67, 0.24, 1);
  will-change: transform;
}
.wheel-label {
  position: absolute;
  top: 50%;
  left: 50%;
  transform-origin: 0 0;
  font-size: 11px;
  font-weight: 800;
  pointer-events: none;
  white-space: nowrap;
}
/* Prize wedges (dark bronze background) — bright warm text so the gold
   coin/tap emoji don't disappear against the gold background. */
.wheel-label-coin,
.wheel-label-tap {
  color: #FFF3C4;
  text-shadow:
    0 1px 0 rgba(0,0,0,0.55),
    0 0 6px rgba(0,0,0,0.35);
}
/* Empty wedges (pale cream background) — a small, muted glyph that reads
   as "no prize" without competing with the wins. */
.wheel-label-none {
  color: #7A5A00;
  opacity: 0.5;
  font-size: 20px;
  text-shadow: none;
}
.wheel-hub {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 68px;
  height: 68px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 30%, #FFF3C4, #E0A800 70%);
  color: #3A2A00;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 900;
  font-size: 14px;
  letter-spacing: 1.5px;
  box-shadow:
    0 4px 10px rgba(0, 0, 0, 0.45),
    0 0 0 3px #8A6100 inset;
  pointer-events: none;
  z-index: 2;
}
.prize-wheel.is-spinning { cursor: wait; }
.prize-wheel.is-spinning .wheel-hub { animation: hub-pulse 0.8s ease-in-out infinite; }
@keyframes hub-pulse {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50%      { transform: translate(-50%, -50%) scale(1.05); }
}

/* ---- Slots ----
   Each reel is a fixed-height viewport with a vertical strip of symbols
   inside. Rolling animates the strip's translateY so it slides upward and
   comes to rest exactly on the target cell — no post-animation snap. A
   subtle perspective + top/bottom gradient masks give it a 3D depth feel. */
.slots-stage {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin: 6px auto 4px;
  padding: 10px;
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(0,0,0,0.35), rgba(0,0,0,0.15));
  border: 1px solid rgba(255,255,255,0.08);
  max-width: 260px;
  perspective: 400px;
}
.slot-reel {
  position: relative;
  width: 68px;
  height: 84px;
  overflow: hidden;
  border-radius: 10px;
  background: linear-gradient(180deg, #fff, #e6e6e6);
  color: #202020;
  box-shadow:
    inset 0 2px 4px rgba(0,0,0,0.25),
    inset 0 -2px 4px rgba(0,0,0,0.15);
  transform-style: preserve-3d;
}
/* Fade the top+bottom of each reel so the moving strip looks like it
   curves away — the 3D illusion is mostly this mask. */
.slot-reel::before,
.slot-reel::after {
  content: "";
  position: absolute; left: 0; right: 0; height: 22px;
  pointer-events: none; z-index: 2;
}
.slot-reel::before {
  top: 0;
  background: linear-gradient(180deg, rgba(255,255,255,0.85), rgba(255,255,255,0));
}
.slot-reel::after {
  bottom: 0;
  background: linear-gradient(0deg, rgba(0,0,0,0.28), rgba(0,0,0,0));
}
.slot-strip {
  --cell-h: 84px;
  --dur: 2.6s;
  display: block;
  will-change: transform;
  transform: translateY(0);
}
.slot-strip.is-rolling {
  /* 2.5-3.4s of slow-out roll, ending exactly on the target cell. */
  transition: transform var(--dur, 2.6s) cubic-bezier(0.15, 0.65, 0.15, 1);
}
.slot-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  height: var(--cell-h, 84px);
  font-size: 40px;
  line-height: 1;
  /* Tilt cells slightly so as they scroll past the center they look
     rounded. Neutralized for the center-most cell via the strip transform. */
}
.slot-reel.is-win {
  box-shadow:
    inset 0 2px 4px rgba(0,0,0,0.25),
    inset 0 -2px 4px rgba(0,0,0,0.15),
    0 0 0 2px #FFD54A,
    0 0 14px rgba(255, 213, 74, 0.7);
  animation: win-flash 0.6s ease-in-out 3;
}
@keyframes win-flash {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.25); }
}

/* Slot machine = reels + a draggable side-rail lever on the right.
   The lever is the ONLY play control: the user drags the grip from the top
   of the rail to the bottom and releases to spin the reels.
   direction:ltr is forced so the lever always sits on the physical right,
   in both LTR and RTL (Persian) layouts. */
.slots-machine {
  display: flex;
  direction: ltr;
  align-items: center;
  justify-content: center;
  gap: 30px;
  margin: 6px auto 4px;
}
.slots-machine .slots-stage { margin: 0; }
@media (max-width: 520px) {
  .slots-machine:has(.slots-lever.is-push) {
    display: grid;
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 12px;
  }
  .slots-machine:has(.slots-lever.is-push) .slots-stage,
  .slots-machine:has(.slots-lever.is-push) .slots-lever.is-push {
    margin-left: auto;
    margin-right: auto;
  }
}
/* Side rail: a vertical track the grip slides down. --grip is 0 (top) .. 1
   (bottom); JS updates it live while dragging, and CSS eases it back on
   release. */
.slots-lever {
  --grip: 0;
  --grip-travel: 94px;
  position: relative;
  width: 43px;
  height: 142px;
  flex: 0 0 auto;
  cursor: grab;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
}
.slots-lever.is-dragging { cursor: grabbing; }
/* The rail groove the grip rides in — a metallic chrome track with an inner
   shadow so the grip reads as recessed. */
.slots-lever-rail {
  position: absolute;
  left: 50%;
  top: 4px;
  bottom: 4px;
  width: 16px;
  margin-left: -8px;
  border-radius: 0;
  background:
    linear-gradient(90deg,
      rgba(255,255,255,0.18) 0%,
      rgba(0,0,0,0.55) 42%,
      rgba(0,0,0,0.62) 58%,
      rgba(255,255,255,0.12) 100%);
  box-shadow:
    inset 0 2px 5px rgba(0,0,0,0.7),
    inset 0 -2px 4px rgba(255,255,255,0.1),
    0 1px 2px rgba(255,255,255,0.12);
}
/* The grip the user drags — a single landscape (wider-than-tall) metal slider
   block. Sits at the top by default; translateY tracks --grip. */
.slots-lever-grip {
  position: absolute;
  left: 50%;
  top: 6px;
  width: 40px;
  height: 26px;
  margin-left: -20px;
  border-radius: 8px;
  background:
    linear-gradient(180deg,
      #f2f5f9 0%,
      #cfd6e0 30%,
      #9099a8 62%,
      #6b7484 84%,
      #4d5563 100%);
  box-shadow:
    0 5px 9px rgba(0,0,0,0.5),
    0 1px 0 rgba(255,255,255,0.55),
    inset 0 2px 3px rgba(255,255,255,0.7),
    inset 0 -4px 6px rgba(0,0,0,0.32),
    inset 2px 0 3px rgba(255,255,255,0.35),
    inset -3px 0 4px rgba(0,0,0,0.3);
  transform: translateY(calc(var(--grip) * var(--grip-travel)));
  transition: transform 0.3s cubic-bezier(0.34, 1.35, 0.64, 1);
}
/* While actively dragging, follow the finger instantly (no easing). */
.slots-lever.is-dragging .slots-lever-grip { transition: none; }
/* Locked mirrors the reel stage's disabled look. */
.slots-lever.is-locked {
  cursor: not-allowed;
  filter: grayscale(0.55) brightness(0.75);
  opacity: 0.7;
  pointer-events: none;
}
/* Armed = gentle amber glow on the grip to draw the eye. */
.slots-lever.is-armed .slots-lever-grip {
  animation: slots-lever-pulse 1.4s ease-in-out infinite;
}
@keyframes slots-lever-pulse {
  0%, 100% { box-shadow: 0 5px 9px rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.55), inset 0 2px 3px rgba(255,255,255,0.7), inset 0 -4px 6px rgba(0,0,0,0.32), inset 2px 0 3px rgba(255,255,255,0.35), inset -3px 0 4px rgba(0,0,0,0.3), 0 0 0 0 rgba(255,213,74,0.0); }
  50%      { box-shadow: 0 5px 9px rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.55), inset 0 2px 3px rgba(255,255,255,0.7), inset 0 -4px 6px rgba(0,0,0,0.32), inset 2px 0 3px rgba(255,255,255,0.35), inset -3px 0 4px rgba(0,0,0,0.3), 0 0 18px 6px rgba(255,213,74,0.65); }
}

/* Optional slot control: green elevator-style push button. Same DOM as the
   lever, switched by the admin-configured .is-push class. The base is a round
   brown "socket" sitting a bit lower than the green button so the button reads
   as resting on top of it. */
.slots-lever.is-push {
  width: 76px;
  height: 76px;
  border-radius: 50%;
  cursor: pointer;
  align-self: center;
  background:
    radial-gradient(circle at 38% 28%, rgba(255,255,255,0.24), transparent 44%),
    linear-gradient(145deg, #9a5a28 0%, #6b3818 50%, #3b1d0d 100%);
  box-shadow:
    0 8px 0 #2a1308,
    0 15px 22px rgba(0,0,0,0.38),
    inset 0 3px 0 rgba(255,222,166,0.32),
    inset 0 -9px 16px rgba(34,13,4,0.56),
    inset 7px 0 12px rgba(255,181,88,0.10),
    inset -7px 0 12px rgba(0,0,0,0.26);
}
.slots-lever.is-push .slots-lever-rail { display: none; }
.slots-lever.is-push .slots-lever-grip {
  left: 50%;
  top: 44%;
  width: 60px;
  height: 60px;
  margin: -30px 0 0 -30px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 36% 26%, rgba(255,255,255,0.95) 0 8%, rgba(255,255,255,0.22) 9% 24%, rgba(255,255,255,0) 25%),
    linear-gradient(145deg, #5EFF8E 0%, #16C65B 45%, #078C39 100%);
  box-shadow:
    0 8px 0 #035825,
    0 13px 20px rgba(0,0,0,0.44),
    inset 0 5px 8px rgba(255,255,255,0.42),
    inset 0 -10px 14px rgba(0,70,28,0.48);
  transform: translateY(0);
  transition: transform 0.22s cubic-bezier(0.34, 1.4, 0.5, 1),
              box-shadow 0.22s cubic-bezier(0.34, 1.4, 0.5, 1);
}
.slots-lever.is-push.is-pressing .slots-lever-grip,
.slots-lever.is-push:active .slots-lever-grip {
  transform: translateY(7px) scale(0.98);
  box-shadow:
    0 2px 0 #03491f,
    0 6px 12px rgba(0,0,0,0.4),
    inset 0 7px 14px rgba(0,70,28,0.5),
    inset 0 -3px 5px rgba(255,255,255,0.22);
}
.slots-lever.is-push.is-armed .slots-lever-grip {
  animation: slots-push-pulse 1.25s ease-in-out infinite;
}
.slots-lever.is-push.is-pressing .slots-lever-grip,
.slots-lever.is-push:active .slots-lever-grip {
  animation: none;
}
/* Push variant stays clickable while locked so the press animation can play
   (it just won't spin) — the grayed-out look still signals "not ready". */
.slots-lever.is-push.is-locked {
  pointer-events: auto;
  cursor: pointer;
}
@keyframes slots-push-pulse {
  0%, 100% { box-shadow: 0 8px 0 #035825, 0 14px 22px rgba(0,0,0,0.46), inset 0 5px 8px rgba(255,255,255,0.42), inset 0 -10px 14px rgba(0,70,28,0.48), 0 0 0 0 rgba(35, 220, 94, 0); }
  50%      { box-shadow: 0 8px 0 #035825, 0 14px 22px rgba(0,0,0,0.46), inset 0 5px 8px rgba(255,255,255,0.42), inset 0 -10px 14px rgba(0,70,28,0.48), 0 0 22px 7px rgba(35, 220, 94, 0.62); }
}
[data-bs-theme="light"] .slots-lever.is-push {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.26), transparent 26%),
    linear-gradient(145deg, #a86531 0%, #743f1c 50%, #44210e 100%);
  box-shadow:
    0 9px 0 #2f1609,
    0 16px 22px rgba(80,44,20,0.30),
    inset 0 3px 0 rgba(255,226,180,0.46),
    inset 0 -10px 18px rgba(45,18,6,0.48),
    inset 8px 0 14px rgba(255,190,100,0.16),
    inset -8px 0 14px rgba(0,0,0,0.20);
}

/* Duration selector shown right under the slots stage. Small pill buttons;
   the active one has the accent colour. Persisted per-user in localStorage
   so re-opening the mini app keeps the last-picked duration. */
.slots-duration {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  margin: 4px auto 6px;
}
.slots-duration-label {
  font-size: 11.5px;
  color: var(--muted, #9aa4b2);
  letter-spacing: 0.02em;
}
.slots-duration-btns {
  display: inline-flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: center;
}
.slots-dur-btn {
  min-width: 52px;
  padding: 9px 14px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.15);
  background: rgba(255,255,255,0.06);
  color: inherit;
  font-size: 14.5px;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
}
.slots-dur-btn:hover { background: rgba(255,255,255,0.12); }
.slots-dur-btn.is-active {
  background: rgba(255, 213, 74, 0.22);
  border-color: rgba(255, 213, 74, 0.55);
  color: #FFE38A;
  font-weight: 600;
}
body[data-theme="light"] .slots-dur-btn,
[data-bs-theme="light"] .slots-dur-btn {
  border-color: rgba(60, 110, 190, 0.35);
  background: rgba(90, 140, 220, 0.10);
  color: #1a3a63;
}
body[data-theme="light"] .slots-dur-btn:hover,
[data-bs-theme="light"] .slots-dur-btn:hover { background: rgba(90, 140, 220, 0.18); }
body[data-theme="light"] .slots-dur-btn.is-active,
[data-bs-theme="light"] .slots-dur-btn.is-active {
  background: rgba(52, 71, 170, 0.18);
  border-color: rgba(52, 71, 170, 0.65);
  color: #1F2A6B;
  font-weight: 700;
}


/* Locked = user hasn't watched an ad yet; the game is not interactive. */
.slots-stage.is-locked {
  cursor: not-allowed;
  filter: grayscale(0.55) brightness(0.75);
  opacity: 0.7;
}
/* The wheel dims via an overlay pseudo-element (z-index:1) instead of container
   opacity/filter, so the center hub (z-index:2) stays fully solid and colorful
   while only the wheel face behind it is greyed/darkened. Putting opacity on
   .prize-wheel itself would flatten the hub into the same faded group — a child
   opacity:1 can't escape a parent opacity group — hence the overlay approach. */
.prize-wheel.is-locked { cursor: not-allowed; }
.prize-wheel.is-locked::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: rgba(20, 16, 4, 0.42);
  backdrop-filter: grayscale(0.55) brightness(0.75);
  -webkit-backdrop-filter: grayscale(0.55) brightness(0.75);
  z-index: 1;
  pointer-events: none;
}
.slots-stage.is-locked { pointer-events: none; }
.prize-wheel.is-locked { pointer-events: none; }
/* Fade the hub to read as disabled — matching the greyed board — but via
   `filter` (not opacity) so the background stays solid, not see-through. */
.prize-wheel.is-locked .wheel-hub {
  filter: grayscale(0.8) brightness(0.6);
}

/* Armed = ad watched, next tap will spin. Subtle glow to draw the eye. */
.prize-wheel.is-armed {
  animation: minigame-armed-pulse 1.4s ease-in-out infinite;
}
.prize-wheel.is-armed { cursor: pointer; }
/* Slots reels are no longer tappable — the lever is the only control, and it
   carries the "ready" glow now, so the reels stay quiet. */
.slots-stage.is-armed { cursor: default; }
@keyframes minigame-armed-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 213, 74, 0.0); }
  50%      { box-shadow: 0 0 22px 4px rgba(255, 213, 74, 0.35); }
}
/* Richer amber glow in light theme so it stays visible on the pink body
   instead of blending into a pale wash. */
[data-bs-theme="light"] .prize-wheel.is-armed {
  animation: minigame-armed-pulse-light 1.4s ease-in-out infinite;
}
@keyframes minigame-armed-pulse-light {
  0%, 100% { box-shadow: 0 0 0 0 rgba(212, 130, 20, 0.0); }
  50%      { box-shadow: 0 0 22px 4px rgba(212, 130, 20, 0.55); }
}
/* When the slots container is armed, wrap the shadow around the whole
   stage rather than each reel individually. */
.slots-stage.is-armed { transition: box-shadow 0.2s ease; }

/* ================== Focused minigame cards ================== */
#word-card,
#slots-card,
#cmem-card {
  position: relative;
  transition: transform 0.26s ease, opacity 0.2s ease, border-radius 0.26s ease, box-shadow 0.26s ease;
}
.cmem-focus-toggle,
.game-focus-toggle {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 4;
  width: 40px;
  height: 40px;
  padding: 8px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
  color: inherit;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 0.15s ease, background 0.15s ease;
}
.cmem-focus-toggle:hover,
.game-focus-toggle:hover {
  background: rgba(255, 255, 255, 0.06);
  opacity: 0.8;
}
.cmem-focus-toggle:active,
.game-focus-toggle:active { transform: scale(0.94); }
[dir="rtl"] .cmem-focus-toggle,
[dir="rtl"] .game-focus-toggle {
  right: 10px;
  left: auto;
}
.cmem-focus-icon {
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0.85;
}
.cmem-focus-icon-min { display: none; }
.glass-card.is-focused .cmem-focus-icon-max { display: none; }
.glass-card.is-focused .cmem-focus-icon-min { display: block; }
body.cmem-focus-open {
  overflow: hidden !important;
}
body.cmem-focus-open::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 6900;
  background: rgba(3, 6, 24, 0.78);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  pointer-events: auto;
  animation: cmem-focus-backdrop-in 0.24s ease both;
}
:is(#word-card, #cmem-card).is-focused {
  position: fixed;
  z-index: 6910;
  top: calc(max(10px, env(safe-area-inset-top), var(--tg-safe-top, 0px)) + var(--tg-content-top, 0px));
  right: max(10px, env(safe-area-inset-right), var(--tg-safe-right, 0px), var(--tg-content-right, 0px));
  bottom: max(10px, env(safe-area-inset-bottom), var(--tg-safe-bottom, 0px), var(--tg-content-bottom, 0px));
  left: max(10px, env(safe-area-inset-left), var(--tg-safe-left, 0px), var(--tg-content-left, 0px));
  margin: 0;
  border-radius: 18px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: stretch;
  transform-origin: center;
  animation: cmem-focus-in 0.28s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
:is(#word-card, #cmem-card).is-focused.is-closing {
  animation: cmem-focus-out 0.22s ease both;
}
:is(#word-card, #cmem-card).is-focused .card-inner {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 18px 16px 16px;
}
:is(#word-card, #cmem-card).is-focused .minigame-title { margin-top: 4px; }
:is(#word-card, #cmem-card).is-focused .minigame-hint {
  max-width: 720px;
  margin-inline: auto;
}
#word-card.is-focused .card-inner {
  justify-content: center;
}
#word-card.is-focused .word-stage {
  width: min(100%, 640px);
  margin-inline: auto;
}

/* ================== Card Memory minigame ================== */
#cmem-card.is-focused .cmem-stage {
  width: min(100%, 860px);
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin-top: 8px;
}
#cmem-card.is-focused .cmem-grid {
  width: 100%;
  max-width: min(100%, 760px);
  gap: clamp(6px, 1.1vmin, 10px);
}
#cmem-card.is-focused .cmem-grid[data-cols="4"] { max-width: min(100%, 520px); }
#cmem-card.is-focused .cmem-grid[data-cols="6"] { max-width: min(100%, 680px); }
#cmem-card.is-focused .cmem-card {
  height: var(--cmem-focus-card-h, 64px);
}
@keyframes cmem-focus-in {
  from { opacity: 0.72; transform: scale(0.94); }
  to { opacity: 1; transform: scale(1); }
}
@keyframes cmem-focus-out {
  from { opacity: 1; transform: scale(1); }
  to { opacity: 0.72; transform: scale(0.94); }
}
@keyframes cmem-focus-backdrop-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
.cmem-stage {
  margin: 10px auto 6px;
  padding: 10px;
  border-radius: 16px;
  background: rgba(0, 0, 0, 0.18);
}
.cmem-stage.is-locked {
  filter: grayscale(0.16) brightness(0.94);
  opacity: 0.88;
  pointer-events: none;
}
.cmem-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
  min-height: 22px;
  flex-wrap: wrap;
}
.cmem-turn {
  font-size: 12px;
  font-weight: 700;
  color: #ffd54a;
}
.cmem-turn.is-mine { color: #4ade80; }
.cmem-scores {
  display: flex;
  gap: 10px;
  font-size: 12px;
}
.cmem-score b { font-weight: 800; }
.cmem-score-me b { color: #4ade80; }
.cmem-score-opp b { color: #ff8a8a; }
.cmem-timer { font-size: 12px; margin-left: auto; opacity: 0.9; }
/* Timer value pill — mirrors the word game's amber/red threshold styling. */
.cmem-timer-v {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  margin-inline-start: 6px;
  font-weight: 800;
  padding: 2px 8px;
  border-radius: 8px;
  transition: background 0.2s ease, color 0.2s ease;
}
.cmem-timer-num {
  display: inline-block;
  min-width: 1.6em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.cmem-timer-unit { opacity: 0.85; font-weight: 600; }
.cmem-timer-v.is-warn {
  color: #ffb020;
  background: rgba(255, 176, 32, 0.14);
}
.cmem-timer-v.is-danger {
  color: #ff5347;
  background: rgba(255, 83, 71, 0.16);
  animation: word-timer-pulse 0.9s ease-in-out infinite;
}
body[data-theme="light"] .cmem-timer-v.is-warn,
[data-bs-theme="light"] .cmem-timer-v.is-warn {
  color: #b57200;
  background: rgba(255, 176, 32, 0.18);
}
body[data-theme="light"] .cmem-timer-v.is-danger,
[data-bs-theme="light"] .cmem-timer-v.is-danger {
  color: #b32a1e;
  background: rgba(255, 83, 71, 0.14);
}

.cmem-grid {
  display: grid;
  grid-template-columns: repeat(var(--cols, 4), 1fr);
  gap: 6px;
  perspective: 700px;
  /* Cap the board width so cards read a bit smaller & the grid stays centred. */
  max-width: 320px;
  margin: 0 auto;
}
/* Wider column counts (6 / 8) get more of the container so the cards don't
   shrink to slivers — height is fixed in CSS, this only relaxes the width cap. */
.cmem-grid[data-cols="6"] { max-width: 460px; }
.cmem-grid[data-cols="8"] { max-width: 100%; }
.cmem-card {
  position: relative;
  /* Fixed row height so the board's total height is identical across every
     difficulty (and the idle placeholder) — only the column count / card
     width changes. Width still flexes via the grid's 1fr columns. */
  height: 62px;
  border: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
  transform-style: preserve-3d;
  transition: transform 0.35s cubic-bezier(0.3, 0.8, 0.4, 1.2);
  -webkit-tap-highlight-color: transparent;
}
.cmem-card.is-flipped,
.cmem-card.is-matched { transform: rotateY(180deg); }
.cmem-card:disabled { cursor: default; }
/* Idle placeholder cards (rendered before the game is armed): static, no
   pointer, slightly dimmed so they read as a preview rather than a live board. */
.cmem-card.is-placeholder {
  cursor: default;
  pointer-events: none;
  opacity: 0.9;
}
.cmem-card-face {
  position: absolute;
  inset: 0;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  overflow: hidden;
}
.cmem-card-back {
  background:
    radial-gradient(circle at 18% 22%, rgba(255,255,255,0.32) 0 4%, transparent 5% 100%),
    radial-gradient(circle at 78% 72%, rgba(57,255,20,0.86) 0 8%, transparent 9% 100%),
    repeating-conic-gradient(from 18deg, rgba(57,255,20,0.96) 0 8deg, transparent 8deg 19deg),
    repeating-linear-gradient(35deg, rgba(255, 235, 74, 0.32) 0 3px, transparent 3px 9px),
    linear-gradient(135deg, #ff3131 0%, #d30e18 40%, #7d0711 100%);
  border: 2px solid #39FF14;
  box-shadow:
    inset 0 0 0 3px rgba(121, 0, 12, 0.58),
    inset 0 0 0 7px rgba(57, 255, 20, 0.58),
    inset 0 0 20px rgba(0, 0, 0, 0.38),
    0 0 10px rgba(57, 255, 20, 0.28),
    0 2px 6px rgba(0, 0, 0, 0.45);
}
/* Busy red / fluorescent-green card-back motif. */
.cmem-card-back::before {
  content: "";
  position: absolute;
  inset: 8px;
  border-radius: 7px;
  background:
    repeating-linear-gradient(90deg, rgba(57,255,20,0.92) 0 2px, transparent 2px 8px),
    repeating-linear-gradient(0deg, rgba(255,255,255,0.18) 0 1px, transparent 1px 7px),
    radial-gradient(ellipse at center, rgba(255, 49, 49, 0.92) 0 28%, transparent 29%);
  box-shadow:
    inset 0 0 0 2px rgba(57, 255, 20, 0.95),
    inset 0 0 0 5px rgba(126, 0, 14, 0.64),
    0 0 12px rgba(57, 255, 20, 0.48);
}
.cmem-card-back::after {
  content: "";
  position: absolute;
  inset: 16px 12px;
  border-radius: 12px;
  border: 2px solid rgba(255, 238, 74, 0.82);
  background:
    repeating-conic-gradient(from 45deg, rgba(57,255,20,0.88) 0 10deg, rgba(255,49,49,0.82) 10deg 20deg),
    radial-gradient(circle at center, rgba(255,238,74,0.96) 0 16%, transparent 17%);
  transform: rotate(12deg);
  box-shadow: inset 0 0 0 2px rgba(117, 0, 13, 0.72), 0 0 10px rgba(255, 49, 49, 0.36);
}
.cmem-card-front {
  transform: rotateY(180deg);
  background: #fff;
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.06),
              0 2px 4px rgba(0, 0, 0, 0.4);
}
.cmem-card-front svg { width: 62%; height: 62%; display: block; }
.cmem-card.is-matched .cmem-card-front {
  box-shadow: inset 0 0 0 2px rgba(74, 222, 128, 0.9),
              0 0 12px 2px rgba(74, 222, 128, 0.5);
  animation: cmem-match-pop 0.4s ease;
}
@keyframes cmem-match-pop {
  0% { transform: rotateY(180deg) scale(1); }
  50% { transform: rotateY(180deg) scale(1.08); }
  100% { transform: rotateY(180deg) scale(1); }
}

/* Mode chooser + friend picker + waiting states */
.cmem-mode,
.cmem-friends,
.cmem-waiting {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 8px 0 4px;
}
.cmem-mode .btn-cta-sm.is-active,
.cmem-mode .btn-ghost-sm.is-active {
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.32), 0 10px 24px rgba(0, 0, 0, 0.18);
  transform: translateY(-1px);
}
.cmem-mode .btn-cta-sm:disabled,
.cmem-mode .btn-ghost-sm:disabled {
  opacity: 0.34;
  filter: grayscale(0.85) saturate(0.35);
  box-shadow: none;
  cursor: not-allowed;
}
[data-bs-theme="light"] .cmem-mode .btn-cta-sm:disabled,
[data-bs-theme="light"] .cmem-mode .btn-ghost-sm:disabled {
  opacity: 0.42;
}
.cmem-friend-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
}
.cmem-friend-chip {
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.08);
  color: inherit;
  border-radius: 999px;
  padding: 5px 12px;
  font-size: 12px;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.cmem-friend-chip.is-selected {
  background: rgba(255, 213, 74, 0.22);
  border-color: rgba(255, 213, 74, 0.7);
}
.cmem-friend-input {
  width: 100%;
  padding: 9px 12px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(0, 0, 0, 0.25);
  color: inherit;
  font-size: 14px;
  text-align: center;
}
.cmem-friend-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
}

/* Non-dismissible invite dialog extras (reuses .confirm-root/.confirm-card). */
.cmem-invite-root { z-index: 9010; }
.cmem-invite-emoji { font-size: 34px; margin-bottom: 4px; }
body.cmem-noscroll { overflow: hidden !important; }

/* Light theme */
[data-bs-theme="light"] .cmem-stage { background: rgba(0, 0, 0, 0.05); }
[data-bs-theme="light"] .cmem-friend-input {
  background: rgba(0, 0, 0, 0.05);
  border-color: rgba(0, 0, 0, 0.15);
}
[data-bs-theme="light"] .cmem-friend-chip {
  border-color: rgba(0, 0, 0, 0.15);
  background: rgba(0, 0, 0, 0.05);
}


/* ================== Reload overlay ==================
   Brief full-viewport takeover shown while the app reloads after a
   language / region switch, so the transition doesn't look frozen.
   Sits above every other overlay. */
.reload-root {
  position: fixed;
  inset: 0;
  z-index: 7040;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
  background: rgba(4, 8, 30, 0.78);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.reload-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
.reload-spinner {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.18);
  border-top-color: var(--c-pink, #ff7eb6);
  animation: reload-spin 0.8s linear infinite;
}
.reload-text {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  opacity: 0.9;
}
@keyframes reload-spin {
  to { transform: rotate(360deg); }
}

/* Body scroll-lock while any consent-style dialog is open (toggled from JS via
   the modal scroll-lock observer). Freezes the underlying page so it can't be
   scrolled behind the fixed overlay. The overlay's own scrollable regions
   (e.g. the consent policy box) keep working via their `overflow: auto`. */
html.dialog-open,
body.dialog-open {
  overflow: hidden;
}

/* ================== Maintenance overlay ==================
   Centered card/dialog on a blurred backdrop — same visual language as the
   consent gate. Shown when the admin has flipped maintenance_mode on. Only
   blocks non-super-admin users. */
.maintenance-root {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(4, 8, 30, 0.72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: var(--tg-text, #fff);
}

/* STAGING marker: a thick red frame around the whole viewport so the staging
   clone is unmistakable. Only drawn when app.js sets data-staging="1" (i.e.
   config.staging is true). pointer-events:none so it never eats taps. */
html[data-staging="1"] body::after {
  content: "";
  position: fixed;
  inset: 0;
  border: 6px solid #ff2d2d;
  pointer-events: none;
  z-index: 99999;
}
.maintenance-inner {
  max-width: 400px;
  width: 100%;
  padding: 26px 22px 22px;
  border-radius: 18px;
  text-align: center;
}
.maintenance-gear {
  font-size: 60px;
  line-height: 1;
  display: inline-block;
  animation: maintenance-spin 3.4s linear infinite;
  filter: drop-shadow(0 4px 18px rgba(0, 0, 0, 0.35));
}
.maintenance-title {
  margin: 16px 0 8px;
  font-size: 20px;
  font-weight: 700;
}
.maintenance-body {
  margin: 0;
  opacity: 0.85;
  font-size: 15px;
  line-height: 1.45;
}
@keyframes maintenance-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* ================== Consent gate overlay ==================
   Full-viewport takeover shown until the user explicitly accepts the
   privacy policy. Persists across sessions server-side, so this only
   renders on the first launch (or after the user revokes). */
.consent-root {
  position: fixed;
  inset: 0;
  z-index: 7020;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(4, 8, 30, 0.72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.consent-inner {
  max-width: 460px;
  width: 100%;
  max-height: 88vh;
  padding: 22px 20px 18px;
  border-radius: 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.consent-title {
  margin: 0;
  font-size: 20px;
  font-weight: 700;
}
.consent-policy-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 13.5px;
  line-height: 1.55;
}
[data-bs-theme="light"] .consent-policy-scroll {
  background: rgba(15, 25, 60, 0.04);
  border-color: rgba(15, 25, 60, 0.10);
}
.consent-policy-heading {
  display: block;
  margin-bottom: 8px;
  font-weight: 700;
  font-size: 14.5px;
}
.consent-policy-body {
  margin: 0;
}
.consent-hint {
  margin: 0;
  font-size: 12.5px;
}
.consent-actions {
  display: flex;
  justify-content: flex-end;
}

/* Referral section inside consent overlay */
.consent-divider {
  border: none;
  border-top: 1px solid var(--glass-border);
  margin: 14px 0 12px;
}
.consent-referral-title {
  font-size: 14px;
  font-weight: 600;
  margin: 0 0 8px;
}
.consent-referral-hint {
  font-size: 13px;
  margin: 0 0 8px;
}
.consent-referral-code-display {
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--glass-border);
  border-radius: 8px;
  padding: 8px 12px;
  text-align: center;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 2px;
  margin-bottom: 4px;
}

/* Friends card & rows */
.referral-friends-card { margin-top: 12px; }
.friend-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 0;
  border-bottom: 1px solid var(--glass-border);
}
.friend-row:last-child { border-bottom: none; }
.friend-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.friend-name {
  font-size: 14px;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.friend-dir {
  font-size: 11px;
  opacity: 0.6;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.friend-balances {
  display: flex;
  gap: 8px;
  font-size: 12.5px;
  opacity: 0.75;
  white-space: nowrap;
}
.friend-send-btn {
  flex-shrink: 0;
  padding: 5px;
  opacity: 0.7;
  border-radius: 6px;
}
.friend-send-btn:hover, .friend-send-btn:active { opacity: 1; }

.friend-row--self {
  background: rgba(255,255,255,0.04);
  border-radius: 8px;
  padding-left: 8px;
  padding-right: 8px;
  margin: 0 -8px;
}
[data-bs-theme="light"] .friend-row--self {
  background: rgba(0,0,0,0.05);
}
.friend-dir.self {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  opacity: 1;
  color: var(--tg-button-color, #5288c1);
}
[data-bs-theme="light"] .friend-dir.self {
  color: #1a73e8;
}
.friend-username {
  display: inline;
  opacity: 0.7;
  font-size: 12.5px;
  unicode-bidi: isolate;
}

/* Share row: copy + native share side by side */
.referral-share-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.btn-referral-share-native {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 13.5px;
}

/* Reload-required gate: consent-style card, but centered with a celebratory
   emoji and the action button pushed further down for breathing room. */
.reloadgate-inner {
  text-align: center;
  align-items: center;
}
.reloadgate-emoji {
  font-size: 54px;
  line-height: 1;
  margin-bottom: 4px;
}
.reloadgate-title {
  align-self: stretch;
}
.reloadgate-body {
  margin: 0;
  font-size: 15px;
  line-height: 1.45;
  opacity: 0.9;
}
.reloadgate-actions {
  justify-content: center;
  margin-top: 22px;
}

/* Settings > Privacy card: consent-status row (small label + revoke btn). */
.consent-status-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 6px;
  margin-bottom: 4px;
}
.consent-status-row .btn-sm {
  padding: 4px 10px;
  font-size: 12.5px;
  border-radius: 8px;
}

/* Slim banner shown to the super admin only when maintenance_mode is on.
   Pinned at the top of the viewport so it's obvious the app is otherwise
   locked to everyone else. */
.maintenance-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 4900;
  /* Sized to roughly cover only the phone status bar area — a thin strip
     over the safe-area inset plus a couple of pixels for the label. */
  padding: 2px 10px;
  padding-top: calc(2px + var(--tg-safe-top, 0px));
  background: linear-gradient(90deg, #b45309, #d97706);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.30);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

/* Status-bar backdrop.

   In light theme the app body is pink/white — the phone's OS status bar
   text (clock, battery, signal) is usually white, so it disappears
   against our light body. This element covers ONLY the status-bar-height
   area at the top of the viewport with a dark strip so the system text
   stays legible. Hidden in dark theme (body is already dark) and on
   non-fullscreen mobile / desktop clients where Telegram itself renders
   above the status bar. */
.statusbar-backdrop {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  /* Cover only 80% of the status-bar height so a thin sliver of the
     header shows through at the bottom for a softer visual transition. */
  height: calc(max(env(safe-area-inset-top, 0px), var(--tg-safe-top, 0px)) * 0.8);
  background: #000;
  z-index: 4950;
  pointer-events: none;
}
[data-bs-theme="light"] html[data-tg-mobile="true"][data-tg-fullscreen="true"] .statusbar-backdrop,
html[data-bs-theme="light"][data-tg-mobile="true"][data-tg-fullscreen="true"] .statusbar-backdrop {
  display: block;
}
.maintenance-banner-gear {
  display: inline-block;
  font-size: 12px;
  animation: maintenance-spin 3.4s linear infinite;
}
/* When the banner is visible, push the rest of the UI down so the header
   isn't hidden underneath it. Kept small — matches the thinner banner. */
body:has(#maintenance-banner:not(.d-none)) .app-header {
  margin-top: 18px;
}

/* ================== Referrals view ================== */
.referral-code-block {
  margin: 12px 0 18px;
  padding: 14px 16px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
  text-align: center;
}
.referral-code-label {
  font-size: 13px;
  opacity: 0.8;
  margin-bottom: 6px;
}
.referral-code-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.referral-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 0.15em;
  padding: 6px 12px;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.25);
  color: var(--tg-text, #fff);
  user-select: all;
}
.btn-referral-copy {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 12px;
  font-size: 13px;
}
.referral-stats {
  text-align: center;
  margin-bottom: 18px;
  font-size: 14px;
  opacity: 0.9;
}
.referral-redeem-label {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
  opacity: 0.9;
}
.referral-redeem-row {
  display: flex;
  gap: 8px;
}
.referral-input {
  flex: 1 1 auto;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(0, 0, 0, 0.25);
  color: var(--tg-text, #fff);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 16px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
[data-bs-theme="light"] .referral-input {
  background: rgba(246, 214, 218, 0.55);
  color: #1a1a1a;
  border-color: rgba(0, 0, 0, 0.1);
}
[data-bs-theme="light"] .referral-code {
  background: rgba(0, 0, 0, 0.06);
  color: #1a1a1a;
}
[data-bs-theme="light"] .referral-code-block {
  background: rgba(0, 0, 0, 0.04);
  border-color: rgba(0, 0, 0, 0.08);
}
.referral-notice {
  margin-top: 12px;
  padding: 10px 12px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 13px;
  text-align: center;
  opacity: 0.9;
}

.referral-share-block {
  margin: 4px 0 18px;
  padding: 12px 14px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.referral-share-text {
  width: 100%;
  resize: none;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(0, 0, 0, 0.25);
  color: var(--tg-text, #fff);
  font-size: 14px;
  line-height: 1.4;
}
.referral-share-row {
  display: flex;
  justify-content: flex-end;
  margin-top: 8px;
}
[data-bs-theme="light"] .referral-share-block {
  background: rgba(0, 0, 0, 0.03);
  border-color: rgba(0, 0, 0, 0.08);
}
[data-bs-theme="light"] .referral-share-text {
  background: rgba(255, 255, 255, 0.75);
  color: #1a1a1a;
  border-color: rgba(0, 0, 0, 0.1);
}

.send-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 4px;
}
.send-preset {
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.06);
  color: var(--tg-text, #fff);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.send-preset:hover { background: rgba(255, 255, 255, 0.12); }
.send-preset.active {
  background: rgba(120, 190, 255, 0.28);
  border-color: rgba(120, 190, 255, 0.55);
}
[data-bs-theme="light"] .send-preset {
  background: rgba(0, 0, 0, 0.04);
  color: #1a1a1a;
  border-color: rgba(0, 0, 0, 0.1);
}
[data-bs-theme="light"] .send-preset.active {
  background: rgba(50, 130, 220, 0.18);
  border-color: rgba(50, 130, 220, 0.5);
}
/* Amount input: numeric, so relax the referral-code look */
#send-amount, #send-username {
  text-transform: none;
  letter-spacing: normal;
}
/* Inputs that always render left-to-right regardless of the app language.
   Usernames are English-only, so RTL flipping the caret + placeholder is
   a UX bug — pin it. Placeholder alignment follows the input direction. */
.ltr-input {
  direction: ltr !important;
  text-align: left !important;
}
[dir="rtl"] .ltr-input::placeholder { text-align: left; }

/* ---------- Direction locks ----------
   Tabbar always LTR, ball+fuel area always RTL, regardless of the selected
   app language. The header is mostly LTR (balances/progress/bar) but the
   daily-cap alert TEXT flips with the language for legibility. Persian flips
   <html dir="rtl">; these overrides keep the fixed zones oriented as designed. */
/* Ad LTR hard-lock: while a full-screen ad (rewarded/interstitial) is playing,
   app.js adds .ad-force-ltr to <html> and keeps dir="ltr". This class is a
   belt-and-suspenders guarantee — if any ad SDK re-flips direction mid-play,
   the document (and its content) stays LTR until the ad closes. */
html.ad-force-ltr,
html.ad-force-ltr body,
html.ad-force-ltr body * {
  direction: ltr !important;
}

html[dir="rtl"] .app-header,
html[dir="rtl"] .app-header * {
  direction: ltr !important;
}
/* Cap-alert text follows the app language even when the surrounding header
   is force-LTR. The fraction ("10/10 today") and the progress bar stay LTR
   because they live outside .hdr-cap-text. */
html[dir="rtl"] .hdr-cap-alert {
  direction: rtl !important;
}
html[dir="rtl"] .hdr-cap-alert .hdr-cap-text {
  direction: rtl !important;
  text-align: right;
  unicode-bidi: plaintext;
}
/* The numeric fraction + progress bar are always LTR — they read left-to-right
   even in RTL languages. */
html[dir="rtl"] .hdr-today,
html[dir="rtl"] .hdr-today-text,
html[dir="rtl"] .hdr-today-bar {
  direction: ltr !important;
  text-align: left;
}
html[dir="rtl"] .tabbar,
html[dir="rtl"] .tabbar * {
  direction: ltr !important;
}
html[dir="rtl"] .tabbar-collapse-toggle,
html[dir="rtl"] .tabbar-collapse-toggle * {
  direction: ltr !important;
}
html[dir="ltr"] .ball-stage,
html[dir="rtl"] .ball-stage {
  direction: rtl !important;
}

/* ---------- Coin icon (replaces 🪙 emoji, which renders as a dark moon on
   iOS). Pure-CSS gold coin — inherits font-size, so it lines up with text
   like an emoji would. Use <span class="coin-icon" aria-hidden="true"></span>. */
.coin-icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  border-radius: 50%;
  background:
    radial-gradient(circle at 35% 30%, #fff6bd 0%, #ffd76b 32%, #d68a1a 72%, #7a4a0d 100%);
  box-shadow:
    inset 0 0 0 0.06em rgba(255, 236, 160, 0.9),
    inset 0 -0.08em 0.12em rgba(80, 50, 0, 0.55),
    0 0.02em 0.08em rgba(0, 0, 0, 0.35);
  position: relative;
}
.coin-icon::after {
  /* subtle inner "$"-less bevel ring */
  content: "";
  position: absolute;
  inset: 15%;
  border-radius: 50%;
  border: 0.05em solid rgba(120, 70, 0, 0.35);
  background: radial-gradient(circle at 40% 35%, rgba(255,255,255,0.35) 0%, rgba(255,255,255,0) 55%);
}
/* Header pill glyph is bigger — bump to a fixed size so it dominates the pill. */
.hdr-glyph.coin-icon {
  width: 18px;
  height: 18px;
  vertical-align: -3px;
}
.settings-card-title {
  display: block;
  font-size: 15px;
  font-weight: 700;
  margin-bottom: 6px;
}
.settings-card-title.danger-title {
  color: #ffb4bd;
}
[data-bs-theme="light"] .settings-card-title.danger-title {
  color: #b31229;
}
.settings-card-body {
  margin: 0 0 10px;
  line-height: 1.55;
}

/* Danger-styled button (delete account etc.). */
.btn-danger {
  display: inline-block;
  padding: 9px 16px;
  border: 1px solid rgba(240, 80, 100, 0.55);
  background: rgba(200, 50, 70, 0.22);
  color: #ffd6dc;
  border-radius: 10px;
  font-weight: 600;
  cursor: pointer;
  font: inherit;
}
.btn-danger:hover  { background: rgba(220, 60, 80, 0.32); }
.btn-danger:active { transform: translateY(1px); }
[data-bs-theme="light"] .btn-danger {
  background: transparent;
  border-color: #C81E36;
  border-width: 1.5px;
  color: #C81E36;
}
[data-bs-theme="light"] .btn-danger:hover {
  background: rgba(200, 30, 54, 0.08);
}

/* ---------- Made-in-Germany footer note (no card background) ---------- */
.made-in-germany-block {
  padding: 14px 8px 4px;
  opacity: 0.85;
}
.made-in-germany-title {
  font-size: 15px;
  padding-bottom: 10px;
  margin: 0 0 4px;
}
.made-in-germany-title::after {
  height: 6px;
  background: linear-gradient(
    to bottom,
    #000000 0, #000000 2px,
    #DD0000 2px, #DD0000 4px,
    #FFCE00 4px, #FFCE00 6px
  );
}
.made-in-germany-block .muted-line { font-size: 12.5px; }

/* =========================
   Backgammon mini-game
   ========================= */

#backgammon-card { margin-top: 14px; }
.bg-stage {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  margin: 10px 0 6px;
}
.bg-status-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 6px;
}
.bg-turn-pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.14);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: var(--tg-text);
}
.bg-turn-pill.is-ai {
  background: rgba(255,255,255,0.03);
  color: var(--tg-hint);
}
.bg-timer {
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  font-weight: 700;
  color: var(--tg-text);
  min-width: 32px;
  text-align: center;
}
.bg-timer.is-low { color: #f0605a; }
.bg-dice {
  display: inline-flex;
  gap: 6px;
  min-width: 60px;
  justify-content: flex-end;
}
.bg-die {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px; height: 26px;
  background: #fefefe;
  color: #1a1a1a;
  font-size: 18px;
  line-height: 1;
  font-weight: 700;
  border-radius: 6px;
  border: 1px solid rgba(0,0,0,0.15);
  box-shadow: 0 1px 2px rgba(0,0,0,0.35);
}
.bg-die.is-spent { opacity: 0.35; text-decoration: line-through; }
.bg-board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(6, 1fr) 12px repeat(6, 1fr);
  grid-template-rows: 92px 92px;
  gap: 0;
  width: 100%;
  max-width: 360px;
  margin: 0 auto;
  background: linear-gradient(180deg, #3b2418, #241612);
  border: 1px solid rgba(0,0,0,0.5);
  border-radius: 10px;
  padding: 6px;
  box-shadow: inset 0 0 12px rgba(0,0,0,0.5);
}
.bg-bar-col {
  grid-column: 7 / 8;
  grid-row: 1 / 3;
  align-self: stretch;
  justify-self: stretch;
  background: rgba(0,0,0,0.45);
  border-left: 1px solid rgba(255,255,255,0.05);
  border-right: 1px solid rgba(255,255,255,0.05);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 4px 0;
}
.bg-bar-col .bg-bar-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font-size: 10px;
  color: rgba(255,255,255,0.6);
}
.bg-point {
  position: relative;
  min-height: 0;
  padding: 3px 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  cursor: default;
  user-select: none;
}
.bg-point[data-clickable="1"] { cursor: pointer; }
.bg-point--top { justify-content: flex-start; }
.bg-point--bot { justify-content: flex-end; flex-direction: column-reverse; }
.bg-point::before {
  content: "";
  position: absolute;
  left: 0; right: 0;
  width: 0; height: 0;
  border-left: calc(50% - 1px) solid transparent;
  border-right: calc(50% - 1px) solid transparent;
  z-index: 0;
}
.bg-point--top::before {
  top: 0;
  border-top: 80px solid var(--bg-point-color, #a06844);
}
.bg-point--bot::before {
  bottom: 0;
  border-bottom: 80px solid var(--bg-point-color, #a06844);
}
.bg-point--alt { --bg-point-color: #6d4028; }
.bg-point--src::before,
.bg-point--dst::before {
  filter: brightness(1.35);
}
.bg-point--src { box-shadow: inset 0 0 0 2px #ffcf5a; border-radius: 4px; }
.bg-point--dst { box-shadow: inset 0 0 0 2px #6dd07a; border-radius: 4px; }
.bg-checker {
  position: relative;
  z-index: 1;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  margin: 1px 0;
  border: 1.5px solid rgba(0,0,0,0.4);
  box-shadow: 0 1px 2px rgba(0,0,0,0.4);
}
.bg-checker--you {
  background: radial-gradient(circle at 35% 30%, #ff9ab8, #ec3170);
}
.bg-checker--ai {
  background: radial-gradient(circle at 35% 30%, #eeeeee, #9a9a9a);
  border-color: rgba(0,0,0,0.55);
}
.bg-checker-plus {
  position: relative;
  z-index: 2;
  font-size: 10px;
  font-weight: 800;
  color: #fff;
  background: rgba(0,0,0,0.55);
  border-radius: 999px;
  padding: 1px 5px;
  margin-top: 2px;
}
.bg-bar-off-strip {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin-top: 2px;
  font-size: 11.5px;
  color: var(--tg-hint);
}
.bg-bar-off-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 4px 6px;
  border-radius: 8px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
}
.bg-bar-off-cell.is-you { color: var(--tg-text); }
.bg-bar-off-cell .bg-count {
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--tg-text);
}
.bg-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 4px;
}
.bg-actions .btn-cta-sm { min-width: 96px; }
.btn-cta-sm.bg-danger {
  background: rgba(240, 96, 90, 0.12);
  border-color: rgba(240, 96, 90, 0.5);
  color: #f0605a;
}
.btn-cta-sm.bg-danger:hover { background: rgba(240, 96, 90, 0.20); }

/* Light-theme overrides — softer wood + higher-contrast checkers/text. */
html[data-bs-theme="light"] .bg-board {
  background: linear-gradient(180deg, #d8b995, #b98960);
  border-color: rgba(0,0,0,0.15);
  box-shadow: inset 0 0 12px rgba(0,0,0,0.15);
}
html[data-bs-theme="light"] .bg-point--top::before,
html[data-bs-theme="light"] .bg-point--bot::before {
  border-top-color: #b06b3c;
  border-bottom-color: #b06b3c;
}
html[data-bs-theme="light"] .bg-point--alt { --bg-point-color: #7f4826; }
html[data-bs-theme="light"] .bg-bar-col {
  background: rgba(0,0,0,0.15);
}
html[data-bs-theme="light"] .bg-turn-pill {
  background: rgba(0,0,0,0.05);
  border-color: rgba(0,0,0,0.12);
}
html[data-bs-theme="light"] .bg-bar-off-cell {
  background: rgba(0,0,0,0.03);
  border-color: rgba(0,0,0,0.10);
}

/* ==========================================================================
   Simple mode (accessibility)

   Toggled from the Settings tab. The pre-boot script in index.html sets
   `<html data-simple="true">` before first paint; the switch UI is at
   `.simple-mode-row`.
   ========================================================================== */

/* --- Toggle switch in the Settings card ------------------------------- */
.simple-mode-row {
  display: flex;
  align-items: center;
  gap: 14px;
}
.simple-mode-copy { flex: 1; min-width: 0; }
.simple-mode-copy .settings-card-body { margin-bottom: 0; }
/* Ad-hint rows reuse the simple-mode switch layout; the label is a plain row
   title (no body paragraph), and rows after the first get a subtle divider. */
.settings-hint-label { font-size: 14px; font-weight: 600; }
.simple-mode-row + .simple-mode-row { margin-top: 10px; }
.simple-mode-switch {
  position: relative;
  flex-shrink: 0;
  display: inline-block;
  width: 54px;
  height: 30px;
  cursor: pointer;
}
.simple-mode-switch input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}
.simple-mode-track {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.22);
  transition: background 0.18s ease, border-color 0.18s ease;
}
.simple-mode-track::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
  transition: transform 0.18s ease, left 0.18s ease, right 0.18s ease;
}
/* RTL: anchor the thumb to the right edge instead of the left. Using
   `left: auto` + `right: 3px` keeps the animation logic mirrored and
   avoids the translate flipping the thumb off-screen. */
html[dir="rtl"] .simple-mode-track::after {
  left: auto;
  right: 3px;
}
.simple-mode-switch input:checked + .simple-mode-track {
  background: #22c55e;
  border-color: #16a34a;
}
.simple-mode-switch input:checked + .simple-mode-track::after {
  transform: translateX(24px);
}
html[dir="rtl"] .simple-mode-switch input:checked + .simple-mode-track::after {
  transform: translateX(-24px);
}
html[data-bs-theme="light"] .simple-mode-track {
  background: rgba(0, 0, 0, 0.15);
  border-color: rgba(0, 0, 0, 0.20);
}
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

/* --- Global bumps applied when simple mode is on ---------------------- */
html[data-simple="true"] {
  font-size: 20px;
  /* Grow the tabbar reservation so content isn't hidden behind the taller bar. */
  --tabbar-h: 84px;
  --tabbar-collapsed-h: 32px;
}
html[data-simple="true"] body {
  font-size: 1rem;
}
html[data-simple="true"] .btn-cta,
html[data-simple="true"] .btn-primary,
html[data-simple="true"] .btn-danger {
  min-height: 58px;
  padding: 16px 32px;
  font-size: 19px;
  font-weight: 800;
  letter-spacing: 0.3px;
}
html[data-simple="true"] .btn-cta-sm {
  min-height: 50px;
  padding: 12px 22px;
  font-size: 17px;
  font-weight: 700;
}
html[data-simple="true"] #btn-bypass-cooldown {
  min-height: 50px;
  padding: 12px 22px;
  font-size: 17px;
  font-weight: 700;
}
html[data-simple="true"] .btn-ghost {
  min-height: 50px;
  padding: 12px 22px;
  font-size: 17px;
  font-weight: 700;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.06);
}
html[data-simple="true"][data-bs-theme="light"] .btn-ghost {
  border-color: rgba(0, 0, 0, 0.20);
  background: rgba(0, 0, 0, 0.04);
}
html[data-simple="true"] input,
html[data-simple="true"] textarea,
html[data-simple="true"] select {
  font-size: 18px;
  min-height: 50px;
}

/* --- Header (top bar) ------------------------------------------------- */
html[data-simple="true"] .icon-btn {
  width: 42px;
  height: 42px;
  border-radius: 12px;
  font-size: 20px;
}
html[data-simple="true"] .lang-seg-btn {
  padding: 8px 14px;
  min-width: 44px;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.5px;
}
/* Keep avatar + name/username the same size as normal mode (per user request). */
html[data-simple="true"] .hdr-actions { gap: 10px; }

/* Daily-cap / today bar: just a touch bigger, not full-size. */
html[data-simple="true"] .hdr-today-text { font-size: 12.5px; }
html[data-simple="true"] .hdr-today-label { font-size: 11.5px; }
html[data-simple="true"] .hdr-cap-alert { padding: 6px 10px; }
html[data-simple="true"] .hdr-cap-alert .hdr-cap-icon { font-size: 15px; }
html[data-simple="true"] .hdr-cap-alert .hdr-cap-text { font-size: 12.5px; }

/* --- Bottom tab bar --------------------------------------------------- */
html[data-simple="true"] .tabbar-item {
  gap: 5px;
  padding: 8px 4px;
  font-size: 14px;
  font-weight: 700;
}
html[data-simple="true"] .tabbar-icon {
  width: 30px;
  height: 30px;
  stroke-width: 2;
}
html[data-simple="true"] .tabbar-label { font-size: 13px; }

/* --- Store tab -------------------------------------------------------- */
html[data-simple="true"] .store-desc,
html[data-simple="true"] .store-payout,
html[data-simple="true"] .store-notice {
  display: none !important;
}
/* Warning alerts stay visible — critical info shouldn't hide in Simple
 * Mode. Bump the font a touch so it matches the rest of the mode. */
html[data-simple="true"] .store-warn {
  display: flex !important;
  font-size: 13px;
  line-height: 1.4;
  padding: 10px 12px;
}
html[data-simple="true"] .store-warn-icon { font-size: 16px; }
html[data-simple="true"] .store-name {
  font-size: 19px;
  margin-bottom: 6px;
}
html[data-simple="true"] .store-card .btn-cta,
html[data-simple="true"] .store-card .btn-primary,
html[data-simple="true"] .store-buy {
  width: 100%;
  min-height: 58px;
  padding: 14px 24px;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.3px;
}
html[data-simple="true"] .store-emoji { font-size: 50px; }
html[data-simple="true"] .store-logo,
html[data-simple="true"] .store-logo-wrap {
  height: 56px;
}
html[data-simple="true"] .store-logo { width: auto; }

/* Quantity +/- and Max buttons on bulk-buy items — sized to fit the counter on one row. */
html[data-simple="true"] .store-qty-btn {
  min-width: 40px;
  width: 40px;
  height: 44px;
  padding: 0 8px;
  font-size: 20px;
  border-radius: 12px;
}
html[data-simple="true"] .store-qty-max {
  height: 44px;
  padding: 0 14px;
  font-size: 15px;
  border-radius: 12px;
}
html[data-simple="true"] .store-qty {
  width: 72px;
  height: 44px;
  padding: 6px 8px;
  font-size: 17px;
  border-radius: 12px;
}

/* --- My Items tab ----------------------------------------------------- */
html[data-simple="true"] .inv-meta,
html[data-simple="true"] .inv-sent {
  display: none !important;
}
html[data-simple="true"] .inv-name {
  font-size: 18px;
}
html[data-simple="true"] .inv-action {
  min-height: 40px;
  padding: 8px 14px;
  font-size: 14px;
  font-weight: 700;
}
html[data-simple="true"] .inv-emoji,
html[data-simple="true"] .inv-logo-wrap {
  width: 56px;
  height: 56px;
  font-size: 40px;
}
html[data-simple="true"] .inv-logo { width: 56px; height: 56px; }

/* --- Referrals tab ---------------------------------------------------- */
html[data-simple="true"] #send-presets,
html[data-simple="true"] .send-presets {
  display: none !important;
}
/* Keep the share message textarea at its normal size in simple mode
   (per user request); only the copy button grows via .btn-ghost. */
html[data-simple="true"] .referral-share-text {
  font-size: 14px;
  min-height: 0;
  line-height: 1.4;
}
html[data-simple="true"] .referral-share-block .referral-code-label {
  font-size: 13px;
}
html[data-simple="true"] .referral-code-label,
html[data-simple="true"] .referral-redeem-label {
  font-size: 17px;
}
html[data-simple="true"] .referral-input {
  font-size: 18px;
  min-height: 52px;
}

/* --- Missions --------------------------------------------------------- */
html[data-simple="true"] .mission-task-title {
  font-size: 18px;
  line-height: 1.28;
}
html[data-simple="true"] .mission-task-desc {
  display: none !important;
}
html[data-simple="true"] .mission-task .task__button {
  min-height: 42px;
  padding: 10px 18px;
  font-size: 16px;
  border-radius: 12px;
}

/* --- Settings tab spacing --------------------------------------------- */
html[data-simple="true"] .settings-card-title { font-size: 19px; }
html[data-simple="true"] .settings-card-body  { font-size: 17px; }

/* --- Toasts, slot-duration buttons, wallet ledger --- */
html[data-simple="true"] .toast-item .toast-msg { font-size: 16px; line-height: 1.35; }
html[data-simple="true"] .toast-item .toast-icon { font-size: 20px; }

html[data-simple="true"] .slots-dur-btn {
  min-width: 62px;
  padding: 12px 18px;
  font-size: 16.5px;
}

html[data-simple="true"] .txn-memo   { font-size: 15.5px; }
html[data-simple="true"] .txn-meta   { font-size: 13px; }
html[data-simple="true"] .txn-amount { font-size: 15.5px; }

/* --- Discounted store items: diagonal strikethrough on the old price
 *     (applies in both normal and simple mode).
 *     `text-decoration: line-through` renders horizontally; a rotated
 *     ::after gives us the diagonal look without hiding the number. */
.store-buy .cost-list {
  text-decoration: none;
  position: relative;
  display: inline-block;
}
.store-buy .cost-list::after {
  content: "";
  position: absolute;
  left: -2px;
  right: -2px;
  top: 50%;
  height: 1.5px;
  background: currentColor;
  transform: translateY(-50%) rotate(-14deg);
  transform-origin: center;
  pointer-events: none;
}

/* ---------------------------------------------------------------------
 * Scroll perf.
 *
 * Long lists (store cards, inventory rows, wallet ledger, txns) use
 * `content-visibility: auto` so cards that scroll off-screen skip
 * layout + paint. `contain-intrinsic-size` reserves height so the
 * scrollbar doesn't jump as cards enter/leave the render tree.
 *
 * NOTE: we intentionally do NOT toggle backdrop-filter on scroll —
 * that caused visible flicker (blur snapping in/out).
 * ------------------------------------------------------------------- */
.store-card,
.inv-item,
.wallet-item,
.txn-item {
  content-visibility: auto;
  contain-intrinsic-size: 1px 140px;
}

/* Tab-switch is instant — no fade/animate on view show. */
.view { animation: none !important; }

/* ---------------------------------------------------------------------
 * AdSense banner slots.
 *
 * These are NOT cards: no background, border, blur, or shadow. Just a
 * transparent container with a bit of vertical breathing room so the
 * banner sits cleanly between cards. Hidden entirely when the admin
 * has banner ads disabled (`html:not([data-banners]) .ad-banner`).
 * ------------------------------------------------------------------- */
.ad-banner {
  margin: 12px 0;
  min-height: 0;
  overflow: hidden;
}
.ad-banner:empty { display: none; }
html:not([data-banners="on"]) .ad-banner { display: none !important; }
/* Store/Games tab spacing: each banner carries a 12px top margin that stacked on top
 * of the app-main padding, pushing the banners down further than the card on
 * other tabs. Zero the first banner's top margin inside Store and Games so it
 * starts flush at the top, then keep a 12px bottom gap to the next element. */
#view-store > .ad-banner,
#view-store > .custom-banner,
#view-home > .home-sticky-banner { margin-top: 0; margin-bottom: 12px; }
.ad-banner .adsbygoogle {
  display: block;
  width: 100%;
  min-height: 60px;
}

/* Custom promo banner (mobile gif). Rendered only when the admin has
 * enabled the `custom_banner_enabled` setting AND JS has flipped
 * <html data-cb-on="1">. */
.custom-banner {
  position: relative;
  width: 100%;
  max-width: var(--custom-banner-max-w, 640px);
  margin: 12px auto;
  overflow: hidden;
  border-radius: 12px;
  height: var(--custom-banner-h, 120px);
}
.custom-banner:empty { display: none; }
html:not([data-cb-on="1"]) .custom-banner { display: none !important; }

/* Rotating banner: when BOTH custom banners are enabled they share one
 * container. Each banner is an absolutely-stacked layer; JS slides the
 * outgoing layer to translateX(-100%) (out left) while the incoming one goes
 * translateX(100%) -> 0 (in from the right), so motion is ALWAYS leftward with
 * no blank frame. The container uses the fixed custom-banner height so window
 * width changes do not resize the banner vertically. */
.banner-rotator {
  position: relative;
  overflow: hidden;
  height: var(--custom-banner-h, 120px);
}

.banner-rotator .banner-slide {
  position: absolute;
  inset: 0;
  transition: transform 0.5s ease;
  will-change: transform;
}
.banner-slide .custom-banner-link { height: 100%; }
.banner-slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Store tab: the banner sticks below the header so it stays in view while the
 * user scrolls the item list. The header is `position: sticky; top: 0`; we pin
 * the banner just under it using the measured header height (set by JS as
 * `--app-header-h`; falls back to 0 before it's measured). */
#view-store > .store-sticky-banner,
#view-home > .store-sticky-banner,
html[data-ui-version="v1"] #view-home > .home-sticky-banner {
  position: sticky;
  top: var(--app-header-h, 0px);
  z-index: 20;
}
.custom-banner-link {
  display: block;
  position: relative;
  width: 100%;
  height: 100%;
  line-height: 0;
  border-radius: 12px;
  overflow: hidden;
}
.custom-banner img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: fill;
  border-radius: 12px;
}
.custom-banner-badge {
  position: absolute;
  top: 0;
  right: 0;
  padding: 3px 8px;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: #fff;
  background: rgba(0, 0, 0, 0.62);
  border-top-right-radius: 12px;
  border-bottom-left-radius: 6px;
  pointer-events: none;
  z-index: 2;
}
/* Force top-right regardless of document direction. In RTL, `right:0` on
 * an absolutely positioned element still resolves to the visual right,
 * but we set both to be explicit and reset any inherited alignment. */
html[dir="rtl"] .custom-banner-badge {
  left: auto;
  right: 0;
}

/* -------------------------------------------------------------------
 * Yektanet (Adivery) native-ad banner — pinned at the top of the
 * Wallet tab. Assembled from the SDK's native fields. Hidden until the
 * ad loads (JS removes `.d-none`); `:empty` also collapses it.
 * ------------------------------------------------------------------- */
.yektanet-banner {
  margin: 12px 0;
}
.yektanet-banner:empty { display: none; }
#view-wallet > .yektanet-banner { margin-top: 0; }
.yektanet-native {
  position: relative;
  display: block;
  text-decoration: none;
  color: var(--tg-text);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 14px;
  overflow: hidden;
}
.yektanet-native__image {
  display: block;
  width: 100%;
  height: auto;
  object-fit: cover;
}
.yektanet-native__body {
  padding: 10px 12px 12px;
}
.yektanet-native__head {
  display: flex;
  align-items: center;
  gap: 10px;
}
.yektanet-native__icon {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  object-fit: cover;
  flex: 0 0 auto;
}
.yektanet-native__titles { min-width: 0; }
.yektanet-native__headline {
  font-weight: 700;
  font-size: 14px;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.yektanet-native__advertiser {
  font-size: 11px;
  opacity: 0.7;
}
.yektanet-native__desc {
  margin-top: 6px;
  font-size: 12px;
  line-height: 1.4;
  opacity: 0.85;
}
.yektanet-native__cta {
  margin-top: 10px;
  display: inline-block;
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 600;
  border-radius: 10px;
  color: #fff;
  background: var(--tg-button, #2ea6ff);
}
.yektanet-native__badge {
  position: absolute;
  top: 0;
  right: 0;
  padding: 3px 8px;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: #fff;
  background: rgba(0, 0, 0, 0.62);
  border-top-right-radius: 14px;
  border-bottom-left-radius: 6px;
  pointer-events: none;
  z-index: 2;
}
html[dir="rtl"] .yektanet-native__badge {
  left: auto;
  right: 0;
}


/* Word Scramble minigame */
.word-diff {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
  margin: 8px 0 12px;
}
.word-diff-btn {
  appearance: none;
  border: 1px solid rgba(255,255,255,0.16);
  background: rgba(255,255,255,0.06);
  color: var(--tg-text);
  border-radius: 10px;
  padding: 8px 14px;
  font-size: 14px;
  line-height: 1.2;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
}
.word-diff-btn em {
  font-style: normal;
  opacity: 0.75;
  margin-inline-start: 4px;
  font-size: 12px;
}
.word-diff-btn:hover { background: rgba(255,255,255,0.12); }
.word-diff-btn.is-active {
  background: rgba(90, 140, 220, 0.28);
  border-color: rgba(90, 140, 220, 0.55);
}
.word-diff-btn:disabled { opacity: 0.5; cursor: not-allowed; }
#cmem-difficulty .word-diff-btn > span {
  direction: ltr;
  unicode-bidi: isolate;
}
body[data-theme="light"] .word-diff-btn,
[data-bs-theme="light"] .word-diff-btn {
  border-color: rgba(0,0,0,0.14);
  background: rgba(0,0,0,0.04);
}
body[data-theme="light"] .word-diff-btn:hover,
[data-bs-theme="light"] .word-diff-btn:hover { background: rgba(90, 140, 220, 0.18); }
body[data-theme="light"] .word-diff-btn.is-active,
[data-bs-theme="light"] .word-diff-btn.is-active {
  background: rgba(90, 140, 220, 0.22);
  border-color: rgba(90, 140, 220, 0.55);
}

.word-stage {
  margin-top: 6px;
  padding: 10px 6px 4px;
  border-radius: 12px;
  transition: box-shadow 0.2s ease, opacity 0.2s ease;
}
.word-stage.is-locked { opacity: 0.55; pointer-events: none; }
.word-stage.is-armed {
  animation: minigame-armed-pulse 1.4s ease-in-out infinite;
  transition: box-shadow 0.2s ease;
}
[data-bs-theme="light"] .word-stage.is-armed {
  animation: minigame-armed-pulse-light 1.4s ease-in-out infinite;
}

.word-cells {
  display: flex;
  gap: 6px;
  justify-content: center;
  flex-wrap: wrap;
  margin: 6px 0 10px;
}
.word-cell {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  height: 42px;
  padding: 0 8px;
  border-radius: 8px;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.14);
  font-weight: 700;
  font-size: 20px;
  text-transform: uppercase;
  color: var(--tg-text);
}
body[data-theme="light"] .word-cell,
[data-bs-theme="light"] .word-cell {
  background: rgba(0,0,0,0.04);
  border-color: rgba(0,0,0,0.12);
}

.word-cell.is-placeholder {
  opacity: 0.5;
  font-weight: 400;
  font-size: 22px;
  color: var(--tg-hint);
}

/* Tappable letter tiles: pointer affordance + a clear selected state so the
   user can see which letters they've committed to the guess. */
.word-cell[role="button"] { cursor: pointer; user-select: none; transition: background 0.12s ease, border-color 0.12s ease, transform 0.08s ease; }
.word-cell[role="button"]:active { transform: scale(0.94); }
.word-cell.is-selected {
  background: linear-gradient(135deg, #3B82F6, #2563EB);
  border-color: #2563EB;
  color: #fff;
}
body[data-theme="light"] .word-cell.is-selected,
[data-bs-theme="light"] .word-cell.is-selected {
  background: linear-gradient(135deg, #2563EB, #1D4ED8);
  border-color: #1D4ED8;
  color: #fff;
}

.word-timer {
  font-size: 13px;
  color: var(--tg-hint);
  margin: 4px 0 8px;
}
.word-timer-v {
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
  margin-inline-start: 6px;
  font-weight: 700;
  color: var(--tg-text);
  padding: 2px 8px;
  border-radius: 8px;
  transition: background 0.2s ease, color 0.2s ease;
}
.word-timer-num {
  display: inline-block;
  min-width: 1.6em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.word-timer-unit { opacity: 0.85; font-weight: 600; }
.word-timer-v.is-warn {
  color: #ffb020;
  background: rgba(255, 176, 32, 0.14);
}
.word-timer-v.is-danger {
  color: #ff5347;
  background: rgba(255, 83, 71, 0.16);
  animation: word-timer-pulse 0.9s ease-in-out infinite;
}
@keyframes word-timer-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,83,71,0.32); }
  50%      { box-shadow: 0 0 0 6px rgba(255,83,71,0);  }
}
body[data-theme="light"] .word-timer-v.is-warn,
[data-bs-theme="light"] .word-timer-v.is-warn {
  color: #b57200;
  background: rgba(255, 176, 32, 0.18);
}
body[data-theme="light"] .word-timer-v.is-danger,
[data-bs-theme="light"] .word-timer-v.is-danger {
  color: #b32a1e;
  background: rgba(255, 83, 71, 0.14);
}

.word-answer {
  display: block;
  width: 100%;
  max-width: 320px;
  margin: 0 auto;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(255,255,255,0.06);
  color: var(--tg-text);
  font-size: 16px;
  text-align: center;
  letter-spacing: 0.06em;
}
/* Latin languages: visually uppercase the input value so it mirrors the
 * tiles above it. Persian (RTL) is caseless — no override needed. */
html[lang="en"] .word-answer,
html[lang="de"] .word-answer {
  text-transform: uppercase;
}
body[data-theme="light"] .word-answer,
[data-bs-theme="light"] .word-answer {
  background: rgba(0,0,0,0.03);
  border-color: rgba(0,0,0,0.14);
}
.word-answer:disabled { opacity: 0.6; }

.word-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 10px;
}
/* Hint sits on its OWN row below submit — putting it inline caused submit
 * to shift horizontally when the hint label text changed ("Show hint" →
 * "Hint used — reward reduced"). Tighter top-margin than the submit row. */
.word-actions-hint {
  margin-top: 6px;
  min-height: 0;
}

.word-reveal {
  margin-top: 10px;
  padding: 8px 12px;
  border-radius: 10px;
  font-size: 14px;
  line-height: 1.35;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
  min-height: 40px;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.word-reveal-lbl { font-weight: 700; }
.word-reveal-word {
  position: relative;
  display: inline-block;
  font-weight: 800;
  font-size: 16px;
  letter-spacing: 0.03em;
  direction: ltr;
  unicode-bidi: isolate;
  padding: 4px 10px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.10);
  border: 1px solid rgba(255, 255, 255, 0.14);
  transition: background 0.25s ease-out, border-color 0.25s ease-out;
}
:root[dir="rtl"] .word-reveal-word,
html[dir="rtl"] .word-reveal-word {
  direction: rtl;
}
/* Concealment mask while the round is live ("barfak" / TV static): an opaque
 * layer of random black & white grain sits over the letters. Real noise comes
 * from an inline SVG feTurbulence; the animation jumps background-position to
 * scattered, non-sequential offsets each step so the grain reshuffles
 * chaotically rather than drifting one way. Reads on any background, light or
 * dark. Removed by wordFinish (class swap) to reveal the sharp word. */
.word-reveal-word.is-blurred {
  color: transparent;
  user-select: none;
  pointer-events: none;
  /* Opaque base so the word is never exposed while the static grain covers it.
     Drop the pill border/background so no white outline rings the grain. */
  background-color: #f4f4f5;
  border-color: transparent;
  overflow: hidden;
}
/* "Barfak" TV static: a single STATIC layer of random black & white grain.
   It's always present on the reveal word but transparent; while .is-blurred is
   set it's fully opaque and covers the word INSTANTLY (no fade-in at round
   start). When wordFinish removes .is-blurred, opacity transitions 1 -> 0, so
   the static FADES OUT to reveal the sharp word underneath. No motion. */
.word-reveal-word::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  /* Fractal-noise tile rendered as high-contrast black/white grain. */
  background-color: #f4f4f5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 -18 9'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 80px 80px;
  /* Default (revealed) state: transparent, and reaching it animates the
     fade-OUT. */
  opacity: 0;
  transition: opacity 0.6s ease-out;
  pointer-events: none;
}
/* Blurred: fully opaque and applied with NO transition so the grain is there
   from frame zero when the round starts. */
.word-reveal-word.is-blurred::after { opacity: 1; transition: none; }
@media (prefers-reduced-motion: reduce) {
  .word-reveal-word::after { transition: none; }
}
.word-reveal.is-info {
  background: rgba(52, 71, 170, 0.14);
  border: 1px solid rgba(90, 120, 210, 0.35);
  color: var(--tg-text);
}
.word-reveal.is-correct {
  background: rgba(46, 204, 113, 0.14);
  border: 1px solid rgba(46, 204, 113, 0.45);
  color: var(--tg-text);
}
.word-reveal.is-wrong {
  background: rgba(231, 76, 60, 0.14);
  border: 1px solid rgba(231, 76, 60, 0.45);
  color: var(--tg-text);
}

/* HOT ribbon on top-LEFT of the word card. Always LTR-anchored so it stays
 * on the visual top-left regardless of html[dir]. */
#word-card { position: relative; }
.word-hot-ribbon {
  position: absolute;
  top: 0;
  left: 0;
  width: 82px;
  height: 82px;
  pointer-events: none;
  z-index: 3;
  overflow: hidden;
  direction: ltr;
  unicode-bidi: isolate;
}
html[dir="rtl"] .word-hot-ribbon { left: 0; right: auto; }
.word-hot-ribbon-inner {
  position: absolute;
  display: block;
  top: 12px;
  left: -30px;
  width: 110px;
  padding: 3px 0;
  transform: rotate(-45deg);
  background: linear-gradient(135deg, #ff6a2c 0%, #ff2f2f 60%, #d51414 100%);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.4px;
  text-align: center;
  text-transform: uppercase;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.22);
}
/* Card Memory uses the same corner ribbon but labelled "Multiplayer" with a
   distinct blue/purple gradient (vs the red HOT ribbon on Word Scramble). The
   longer word needs a smaller font + tighter tracking to stay on one line. */
.word-hot-ribbon.is-multiplayer .word-hot-ribbon-inner {
  background: linear-gradient(135deg, #5b8def 0%, #7a5cf0 55%, #9b4dff 100%);
  font-size: 8px;
  letter-spacing: 0.2px;
}

/* Hint button — smaller ghost variant beside Submit. */
.word-hint-btn {
  padding: 6px 10px;
  border-radius: 10px;
  font-size: 12px;
  background: transparent;
  border: 1px solid var(--card-border, rgba(255,255,255,0.16));
  color: var(--tg-text);
  cursor: pointer;
}
.word-hint-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Simple-mode bumps for Word Scramble */
html[data-simple="true"] .word-diff-btn {
  font-size: 16px;
  padding: 10px 16px;
}
html[data-simple="true"] .word-cell {
  min-width: 42px;
  height: 52px;
  font-size: 24px;
}
html[data-simple="true"] .word-answer {
  font-size: 18px;
  padding: 12px 14px;
  min-height: 48px;
}
html[data-simple="true"] .word-timer { font-size: 15px; }
html[data-simple="true"] .word-reveal { font-size: 16px; }

/* =========================================================================
   V2 theme — Home/Earn carousel.

   Admin-toggled via the `ui_version` app setting. When active, JS
   (GameCarousel) lifts every Home card into a horizontal, swipe-only
   carousel: full remaining viewport height, neighbours peeking at the
   edges, content centered. All geometry below is driven by inline styles
   set from JS (wrap height, track side-padding); these rules only handle
   look, overflow, and the edge-to-edge bleed past the .app-main padding.
   ========================================================================= */

/* Kill the Home view's normal vertical rhythm while the carousel owns it,
   and bleed edge-to-edge past the .app-main 14px side padding so slides can
   reach the screen edges. Negative margins cancel the padding exactly. The
   home view itself never scrolls vertically in V2 — the carousel fills the
   viewport and each card scrolls internally if it's too tall. */
html[data-ui-version="v2"] #view-home {
  margin-left: -14px;
  margin-right: -14px;
  overflow: hidden;
  /* Flex column + `order` guarantees the custom banner sits ABOVE the
     carousel regardless of DOM insertion order. */
  display: flex;
  flex-direction: column;
}
/* Stacking order (flex column): custom banner sticks to the header (order 0),
   then the carousel fills the remaining space (order 1). */
html[data-ui-version="v2"] #view-home > .custom-banner {
  order: 0;
}
html[data-ui-version="v2"] #view-home > .v2-carousel {
  order: 1;
}
/* No page-level vertical scroll while the V2 carousel Home tab is the active
   view. Scoped with :has() so OTHER tabs (wallet/store/…) keep scrolling —
   `.app-main` is the shared scroller for every view. */
html[data-ui-version="v2"] .app-main:has(> #view-home:not(.d-none)) {
  overflow-y: hidden;
}
@media (min-width: 768px) {
  html[data-ui-version="v2"][data-tg-mobile="true"] #view-home,
  html[data-ui-version="v2"]:not([data-tg-mobile]) #view-home {
    margin-left: -24px;
    margin-right: -24px;
  }
}
@media (max-width: 1399.98px) {
  html[data-ui-version="v2"] #view-home {
    width: 100vw;
    width: 100dvw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    margin-left: calc(50% - 50dvw);
    margin-right: calc(50% - 50dvw);
  }
}

/* Clipping viewport for the carousel. Height is set inline from JS to the
   remaining space below the header (and custom banner, if any) and above the
   tabbar. `touch-action: pan-y` lets vertical page gestures through while the
   JS axis-lock claims horizontal ones. */
html[data-ui-version="v2"] .v2-carousel {
  position: relative;
  width: 100%;
  overflow: hidden;
  touch-action: pan-y;
}

/* Above-carousel elements (custom banner) sit inside an edge-to-edge Home
   view in V2, so restore the same side gutters as .app-main and cap the
   sponsor container width. */
html[data-ui-version="v2"] #view-home .custom-banner {
  width: calc(100% - 28px);
  max-width: var(--custom-banner-max-w, 640px);
  margin-left: auto !important;
  margin-right: auto !important;
}
@media (min-width: 768px) {
  html[data-ui-version="v2"][data-tg-mobile="true"] #view-home .custom-banner,
  html[data-ui-version="v2"]:not([data-tg-mobile]) #view-home .custom-banner {
    width: calc(100% - 48px);
  }
}

/* Stick the top of the Home content (custom banner / carousel) right up under
   the header in V2 by removing .app-main's top padding while the carousel Home
   tab is active. Scoped with :has() so other tabs keep it. */
html[data-ui-version="v2"] .app-main:has(> #view-home:not(.d-none)) {
  padding-top: 0 !important;
}

/* The moving strip. FORCED LTR so the translate math is identical in FA/RTL
   — a leftward drag always advances, regardless of page `dir`. Centering /
   peek is done purely via the JS transform (peekOffset() folded into
   positionFor), so this track carries NO inline padding — that avoids the
   stale-padding shrink bug when Telegram's minimize gesture distorts layout. */
html[data-ui-version="v2"] .v2-carousel-track {
  display: flex;
  align-items: stretch;
  height: 100%;
  gap: 12px;
  direction: ltr;
  will-change: transform;
  backface-visibility: hidden;
  transform: translate3d(0,0,0);
}

/* Each slide: fixed proportion of the viewport so the next/prev peek in.
   Equal height enforced via `height:100%` + the flex row's `stretch`.
   Card content inside respects the page direction (LTR/RTL). */
html[data-ui-version="v2"] .v2-slide {
  flex: 0 0 89.87%;
  max-width: 89.87%;
  height: 100%;
  display: flex;
  align-items: center;      /* vertical centering of the card */
  justify-content: center;  /* horizontal centering of the card */
  box-sizing: border-box;
  /* Any horizontal drag that starts on a card should swipe, not select/scroll
     the card horizontally. Vertical still passes to the page. */
  touch-action: pan-y;
}

/* Card content respects PAGE direction. The track is force-LTR for swipe
   math, so `inherit` would wrongly resolve to LTR (inheriting through the
   track). Instead pin the slide content to the actual html[dir] value. */
html[dir="ltr"][data-ui-version="v2"] .v2-slide,
html[dir="ltr"][data-ui-version="v2"] .v2-slide * {
  direction: ltr;
}
html[dir="rtl"][data-ui-version="v2"] .v2-slide,
html[dir="rtl"][data-ui-version="v2"] .v2-slide * {
  direction: rtl;
}
/* Ball stage keeps its designed RTL layout (fuel pipe beside ball) in both
   locales — it's a fixed visual arrangement, not text flow. */
html[data-ui-version="v2"] .v2-slide .ball-stage {
  direction: rtl;
}
/* Word cells and backgammon board are always LTR (letter/point ordering). */
html[data-ui-version="v2"] .v2-slide .word-cells,
html[data-ui-version="v2"] .v2-slide .bg-board {
  direction: ltr;
}
/* Force pan-y on EVERY descendant of a slide so the browser never claims a
   horizontal gesture for itself (text selection / native scroll) — it hands
   horizontal to our JS swipe while keeping vertical scrolling. Without this
   a drag that starts on inner content (buttons, canvas, text) wouldn't
   initiate the swipe. */
html[data-ui-version="v2"] .v2-slide * {
  touch-action: pan-y;
}

/* The card inside fills its slide (equal height) and centers its own inner
   content. Cards keep their .glass-card look; a too-tall card scrolls
   internally so the page itself never grows a vertical scrollbar. */
html[data-ui-version="v2"] .v2-slide > .glass-card,
html[data-ui-version="v2"] .v2-slide > .ad-banner {
  width: 100%;
  height: 100%;
  margin: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
html[data-ui-version="v2"] .v2-slide > .glass-card > .card-inner {
  width: 100%;
}
html[data-ui-version="v2"] .v2-slide > .games-promo-banner {
  height: auto;
  min-height: 112px;
  max-height: 152px;
  overflow: hidden;
}
